From 5065f46aa7953b1bb45cac7ce0704e2cce2609c1 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 29 Apr 2019 17:22:02 +0200 Subject: [PATCH 01/35] add newhope1024ccakem --- crypto_kem/newhope1024ccakem/META.yml | 21 + crypto_kem/newhope1024ccakem/clean/LICENSE | 1 + crypto_kem/newhope1024ccakem/clean/Makefile | 19 + .../clean/Makefile.Microsoft_nmake | 19 + crypto_kem/newhope1024ccakem/clean/api.h | 15 + crypto_kem/newhope1024ccakem/clean/cpapke.c | 192 +++++++++ crypto_kem/newhope1024ccakem/clean/cpapke.h | 16 + crypto_kem/newhope1024ccakem/clean/kem.c | 116 ++++++ crypto_kem/newhope1024ccakem/clean/ntt.c | 127 ++++++ crypto_kem/newhope1024ccakem/clean/ntt.h | 14 + crypto_kem/newhope1024ccakem/clean/params.h | 25 ++ crypto_kem/newhope1024ccakem/clean/poly.c | 370 ++++++++++++++++++ crypto_kem/newhope1024ccakem/clean/poly.h | 32 ++ crypto_kem/newhope1024ccakem/clean/precomp.c | 261 ++++++++++++ crypto_kem/newhope1024ccakem/clean/reduce.c | 26 ++ crypto_kem/newhope1024ccakem/clean/reduce.h | 8 + crypto_kem/newhope1024ccakem/clean/verify.c | 49 +++ crypto_kem/newhope1024ccakem/clean/verify.h | 12 + 18 files changed, 1323 insertions(+) create mode 100644 crypto_kem/newhope1024ccakem/META.yml create mode 100644 crypto_kem/newhope1024ccakem/clean/LICENSE create mode 100644 crypto_kem/newhope1024ccakem/clean/Makefile create mode 100644 crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake create mode 100644 crypto_kem/newhope1024ccakem/clean/api.h create mode 100644 crypto_kem/newhope1024ccakem/clean/cpapke.c create mode 100644 crypto_kem/newhope1024ccakem/clean/cpapke.h create mode 100644 crypto_kem/newhope1024ccakem/clean/kem.c create mode 100644 crypto_kem/newhope1024ccakem/clean/ntt.c create mode 100644 crypto_kem/newhope1024ccakem/clean/ntt.h create mode 100644 crypto_kem/newhope1024ccakem/clean/params.h create mode 100644 crypto_kem/newhope1024ccakem/clean/poly.c create mode 100644 crypto_kem/newhope1024ccakem/clean/poly.h create mode 100644 crypto_kem/newhope1024ccakem/clean/precomp.c create mode 100644 crypto_kem/newhope1024ccakem/clean/reduce.c create mode 100644 crypto_kem/newhope1024ccakem/clean/reduce.h create mode 100644 crypto_kem/newhope1024ccakem/clean/verify.c create mode 100644 crypto_kem/newhope1024ccakem/clean/verify.h diff --git a/crypto_kem/newhope1024ccakem/META.yml b/crypto_kem/newhope1024ccakem/META.yml new file mode 100644 index 00000000..467ed950 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/META.yml @@ -0,0 +1,21 @@ +name: NewHope1024CCAKEM +type: kem +claimed-nist-level: 5 +length-public-key: 1824 +length-secret-key: 3680 +length-ciphertext: 2208 +length-shared-secret: 32 +testvectors-sha256: 233bab7b5e2971b7e271f046e39ba443ffcceada84d3fdb5017d6d3a2e48b0d0 +nistkat-sha256: 8500b88222b3a62e57a6ecaac57f79258f08af49211e0c3f2ca7eab8089c0ce0 +principal-submitter: Thomas Pöppelmann +auxiliary-submitters: +- Erdem Alkim +- Roberto Avanzi +- Joppe Bos +- Léo Ducas +- Antonio de la Piedra +- Peter Schwabe +- Douglas Stebila +implementations: +- name: clean + version: https://github.com/newhopecrypto/newhope/commit/3fc68c6090b23c56cc190a78af2f43ee8900e9d0 diff --git a/crypto_kem/newhope1024ccakem/clean/LICENSE b/crypto_kem/newhope1024ccakem/clean/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/newhope1024ccakem/clean/Makefile b/crypto_kem/newhope1024ccakem/clean/Makefile new file mode 100644 index 00000000..e63127fb --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libnewhope1024ccakem_clean.a +HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h +OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake b/crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake new file mode 100644 index 00000000..7c0fc463 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libnewhope1024ccakem_clean.lib +OBJECTS=cpapke.obj kem.obj ntt.obj poly.obj precomp.obj reduce.obj verify.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/newhope1024ccakem/clean/api.h b/crypto_kem/newhope1024ccakem/clean/api.h new file mode 100644 index 00000000..a4d84e69 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/api.h @@ -0,0 +1,15 @@ +#ifndef PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_API_H +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_API_H + + +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_SECRETKEYBYTES 3680 +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_PUBLICKEYBYTES 1824 +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_CIPHERTEXTBYTES 2208 +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_BYTES 32 +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_ALGNAME "NewHope1024-CCAKEM" + +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/cpapke.c b/crypto_kem/newhope1024ccakem/clean/cpapke.c new file mode 100644 index 00000000..4bbd0b3a --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/cpapke.c @@ -0,0 +1,192 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "poly.h" +#include "randombytes.h" +#include + +/************************************************* +* Name: encode_pk +* +* Description: Serialize the public key as concatenation of the +* serialization of the polynomial pk and the public seed +* used to generete the polynomial a. +* +* Arguments: unsigned char *r: pointer to the output serialized public key +* const poly *pk: pointer to the input public-key polynomial +* const unsigned char *seed: pointer to the input public seed +**************************************************/ +static void encode_pk(unsigned char *r, const poly *pk, const unsigned char *seed) { + int i; + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(r, pk); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + r[NEWHOPE_POLYBYTES + i] = seed[i]; + } +} + +/************************************************* +* Name: decode_pk +* +* Description: De-serialize the public key; inverse of encode_pk +* +* Arguments: poly *pk: pointer to output public-key polynomial +* unsigned char *seed: pointer to output public seed +* const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_pk(poly *pk, unsigned char *seed, const unsigned char *r) { + int i; + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(pk, r); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + seed[i] = r[NEWHOPE_POLYBYTES + i]; + } +} + +/************************************************* +* Name: encode_c +* +* Description: Serialize the ciphertext as concatenation of the +* serialization of the polynomial b and serialization +* of the compressed polynomial v +* +* Arguments: - unsigned char *r: pointer to the output serialized ciphertext +* - const poly *b: pointer to the input polynomial b +* - const poly *v: pointer to the input polynomial v +**************************************************/ +static void encode_c(unsigned char *r, const poly *b, const poly *v) { + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(r, b); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(r + NEWHOPE_POLYBYTES, v); +} + +/************************************************* +* Name: decode_c +* +* Description: de-serialize the ciphertext; inverse of encode_c +* +* Arguments: - poly *b: pointer to output polynomial b +* - poly *v: pointer to output polynomial v +* - const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_c(poly *b, poly *v, const unsigned char *r) { + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(b, r); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(v, r + NEWHOPE_POLYBYTES); +} + +/************************************************* +* Name: gen_a +* +* Description: Deterministically generate public polynomial a from seed +* +* Arguments: - poly *a: pointer to output polynomial a +* - const unsigned char *seed: pointer to input seed +**************************************************/ +static void gen_a(poly *a, const unsigned char *seed) { + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(a, seed); +} + + +/************************************************* +* Name: cpapke_keypair +* +* Description: Generates public and private key +* for the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *pk: pointer to output public key +* - unsigned char *sk: pointer to output private key +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk) { + poly ahat, ehat, ahat_shat, bhat, shat; + unsigned char z[2 * NEWHOPE_SYMBYTES]; + unsigned char *publicseed = z; + unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; + + randombytes(z, NEWHOPE_SYMBYTES); + shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); + + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&shat, noiseseed, 0); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&shat); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&ehat, noiseseed, 1); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&ehat); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&ahat_shat, &shat, &ahat); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&bhat, &ehat, &ahat_shat); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(sk, &shat); + encode_pk(pk, &bhat, publicseed); +} + +/************************************************* +* Name: cpapke_enc +* +* Description: Encryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *c: pointer to output ciphertext +* - const unsigned char *m: pointer to input message (of length NEWHOPE_SYMBYTES bytes) +* - const unsigned char *pk: pointer to input public key +* - const unsigned char *coin: pointer to input random coins used as seed +* to deterministically generate all randomness +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coin) { + poly sprime, eprime, vprime, ahat, bhat, eprimeprime, uhat, v; + unsigned char publicseed[NEWHOPE_SYMBYTES]; + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(&v, m); + + decode_pk(&bhat, publicseed, pk); + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&sprime, coin, 0); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&eprime, coin, 1); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&eprimeprime, coin, 2); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&sprime); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&eprime); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&uhat, &ahat, &sprime); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&uhat, &uhat, &eprime); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&vprime, &bhat, &sprime); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(&vprime); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&vprime, &vprime, &eprimeprime); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&vprime, &vprime, &v); // add message + + encode_c(c, &uhat, &vprime); +} + + +/************************************************* +* Name: cpapke_dec +* +* Description: Decryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *m: pointer to output decrypted message +* - const unsigned char *c: pointer to input ciphertext +* - const unsigned char *sk: pointer to input secret key +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk) { + poly vprime, uhat, tmp, shat; + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(&shat, sk); + + decode_c(&uhat, &vprime, c); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&tmp, &shat, &uhat); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(&tmp); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(&tmp, &tmp, &vprime); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(m, &tmp); +} diff --git a/crypto_kem/newhope1024ccakem/clean/cpapke.h b/crypto_kem/newhope1024ccakem/clean/cpapke.h new file mode 100644 index 00000000..dad194f6 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/cpapke.h @@ -0,0 +1,16 @@ +#ifndef INDCPA_H +#define INDCPA_H + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk); + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coins); + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/kem.c b/crypto_kem/newhope1024ccakem/clean/kem.c new file mode 100644 index 00000000..fc33da81 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/kem.c @@ -0,0 +1,116 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "params.h" +#include "randombytes.h" +#include "verify.h" + +#include + +/************************************************* +* Name: crypto_kem_keypair +* +* Description: Generates public and private key +* for CCA secure NewHope key encapsulation +* mechanism +* +* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + size_t i; + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(pk, sk); /* First put the actual secret key into sk */ + sk += NEWHOPE_CPAPKE_SECRETKEYBYTES; + + for (i = 0; i < NEWHOPE_CPAPKE_PUBLICKEYBYTES; i++) { /* Append the public key for re-encryption */ + sk[i] = pk[i]; + } + sk += NEWHOPE_CPAPKE_PUBLICKEYBYTES; + + shake256(sk, NEWHOPE_SYMBYTES, pk, NEWHOPE_CPAPKE_PUBLICKEYBYTES); /* Append the hash of the public key */ + sk += NEWHOPE_SYMBYTES; + + randombytes(sk, NEWHOPE_SYMBYTES); /* Append the value s for pseudo-random output on reject */ + + return 0; +} + +/************************************************* +* Name: crypto_kem_enc +* +* Description: Generates cipher text and shared +* secret for given public key +* +* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { + unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ + unsigned char buf[2 * NEWHOPE_SYMBYTES]; + int i; + + randombytes(buf, NEWHOPE_SYMBYTES); + + shake256(buf, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ + shake256(buf + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */ + shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(ct, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */ + } + + shake256(k_coins_d + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, ct, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); /* overwrite coins in k_coins_d with h(c) */ + shake256(ss, NEWHOPE_SYMBYTES, k_coins_d, 2 * NEWHOPE_SYMBYTES); /* hash concatenation of pre-k and h(c) to ss */ + return 0; +} + +/************************************************* +* Name: crypto_kem_dec +* +* Description: Generates shared secret for given +* cipher text and private key +* +* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 for sucess or -1 for failure +* +* On failure, ss will contain a randomized value. +**************************************************/ +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { + int i, fail; + unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES]; + unsigned char buf[2 * NEWHOPE_SYMBYTES]; + unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ + const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES; + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_dec(buf, ct, sk); + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */ + buf[NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i]; + } + shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); + + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(ct_cmp, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; + } + + fail = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(ct, ct_cmp, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); + + shake256(k_coins_d + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, ct, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); /* overwrite coins in k_coins_d with h(c) */ + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(k_coins_d, sk + NEWHOPE_CCAKEM_SECRETKEYBYTES - NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */ + shake256(ss, NEWHOPE_SYMBYTES, k_coins_d, 2 * NEWHOPE_SYMBYTES); /* hash concatenation of pre-k and h(c) to k */ + + return 0; +} diff --git a/crypto_kem/newhope1024ccakem/clean/ntt.c b/crypto_kem/newhope1024ccakem/clean/ntt.c new file mode 100644 index 00000000..afed4ee1 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/ntt.c @@ -0,0 +1,127 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" + +/************************************************************ +* Name: bitrev_table +* +* Description: Contains bit-reversed 10-bit indices to be used to re-order +* polynomials before number theoratic transform +************************************************************/ +static uint16_t bitrev_table[NEWHOPE_N] = { + 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704, 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864, 224, 736, 480, 992, + 16, 528, 272, 784, 144, 656, 400, 912, 80, 592, 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944, 112, 624, 368, 880, 240, 752, 496, 1008, + 8, 520, 264, 776, 136, 648, 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808, 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, + 24, 536, 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984, 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760, 504, 1016, + 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836, 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612, 356, 868, 228, 740, 484, 996, + 20, 532, 276, 788, 148, 660, 404, 916, 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692, 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, + 12, 524, 268, 780, 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556, 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004, + 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732, 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892, 252, 764, 508, 1020, + 2, 514, 258, 770, 130, 642, 386, 898, 66, 578, 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930, 98, 610, 354, 866, 226, 738, 482, 994, + 18, 530, 274, 786, 146, 658, 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818, 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, + 10, 522, 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970, 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746, 490, 1002, + 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858, 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634, 378, 890, 250, 762, 506, 1018, + 6, 518, 262, 774, 134, 646, 390, 902, 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678, 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, + 22, 534, 278, 790, 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566, 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014, + 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718, 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878, 238, 750, 494, 1006, + 30, 542, 286, 798, 158, 670, 414, 926, 94, 606, 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958, 126, 638, 382, 894, 254, 766, 510, 1022, + 1, 513, 257, 769, 129, 641, 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801, 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, + 17, 529, 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977, 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, 497, 1009, + 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617, 361, 873, 233, 745, 489, 1001, + 25, 537, 281, 793, 153, 665, 409, 921, 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697, 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, + 5, 517, 261, 773, 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997, + 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725, 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885, 245, 757, 501, 1013, + 13, 525, 269, 781, 141, 653, 397, 909, 77, 589, 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941, 109, 621, 365, 877, 237, 749, 493, 1005, + 29, 541, 285, 797, 157, 669, 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829, 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, + 3, 515, 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963, 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739, 483, 995, + 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851, 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627, 371, 883, 243, 755, 499, 1011, + 11, 523, 267, 779, 139, 651, 395, 907, 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683, 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, + 27, 539, 283, 795, 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571, 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019, + 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711, 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871, 231, 743, 487, 999, + 23, 535, 279, 791, 151, 663, 407, 919, 87, 599, 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951, 119, 631, 375, 887, 247, 759, 503, 1015, + 15, 527, 271, 783, 143, 655, 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815, 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, + 31, 543, 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991, 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767, 511, 1023 +}; + +/************************************************* +* Name: bitrev_vector +* +* Description: Permutes coefficients of a polynomial into bitreversed order +* +* Arguments: - uint16_t* poly: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(uint16_t *poly) { + unsigned int i, r; + uint16_t tmp; + + for (i = 0; i < NEWHOPE_N; i++) { + r = bitrev_table[i]; + if (i < r) { + tmp = poly[i]; + poly[i] = poly[r]; + poly[r] = tmp; + } + } +} + +/************************************************* +* Name: mul_coefficients +* +* Description: Performs pointwise (coefficient-wise) multiplication +* of two polynomials +* Arguments: - uint16_t* poly: pointer to in/output polynomial +* - const uint16_t* factors: pointer to input polynomial, coefficients +* are assumed to be in Montgomery representation +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors) { + unsigned int i; + + for (i = 0; i < NEWHOPE_N; i++) { + poly[i] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce((poly[i] * factors[i])); + } +} + + +void /************************************************* +* Name: ntt +* +* Description: Computes number-theoretic transform (NTT) of +* a polynomial in place; inputs assumed to be in +* bitreversed order, output in normal order +* +* Arguments: - uint16_t * a: pointer to in/output polynomial +* - const uint16_t* omega: pointer to input powers of root of unity omega; +* assumed to be in Montgomery domain +**************************************************/ +PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { + int i, start, j, jTwiddle, distance; + uint16_t temp, W; + + + for (i = 0; i < 10; i += 2) { + // Even level + distance = (1 << i); + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]); // Omit reduction (be lazy) + a[j + distance] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + + // Odd level + distance <<= 1; + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]) % NEWHOPE_Q; + a[j + distance] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + } +} diff --git a/crypto_kem/newhope1024ccakem/clean/ntt.h b/crypto_kem/newhope1024ccakem/clean/ntt.h new file mode 100644 index 00000000..e9fd5e1d --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/ntt.h @@ -0,0 +1,14 @@ +#ifndef NTT_H +#define NTT_H + +#include "inttypes.h" + +extern const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_inv_montgomery[]; + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(uint16_t *poly); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt(uint16_t *a, const uint16_t *omegas); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/params.h b/crypto_kem/newhope1024ccakem/clean/params.h new file mode 100644 index 00000000..ab049d68 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/params.h @@ -0,0 +1,25 @@ +#ifndef PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_PARAMS_H +#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_PARAMS_H + +#define NEWHOPE_N 1024 +#define NEWHOPE_Q 12289 +#define NEWHOPE_K 8 /* used in noise sampling */ + +#define NEWHOPE_SYMBYTES 32 /* size of shared key, seeds/coins, and hashes */ + +#define NEWHOPE_POLYBYTES ((14*NEWHOPE_N)/8) +#define NEWHOPE_POLYCOMPRESSEDBYTES (( 3*NEWHOPE_N)/8) + +#define NEWHOPE_CPAPKE_PUBLICKEYBYTES (NEWHOPE_POLYBYTES + NEWHOPE_SYMBYTES) +#define NEWHOPE_CPAPKE_SECRETKEYBYTES (NEWHOPE_POLYBYTES) +#define NEWHOPE_CPAPKE_CIPHERTEXTBYTES (NEWHOPE_POLYBYTES + NEWHOPE_POLYCOMPRESSEDBYTES) + +#define NEWHOPE_CPAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CPAKEM_SECRETKEYBYTES NEWHOPE_CPAPKE_SECRETKEYBYTES +#define NEWHOPE_CPAKEM_CIPHERTEXTBYTES NEWHOPE_CPAPKE_CIPHERTEXTBYTES + +#define NEWHOPE_CCAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CCAKEM_SECRETKEYBYTES (NEWHOPE_CPAPKE_SECRETKEYBYTES + NEWHOPE_CPAPKE_PUBLICKEYBYTES + 2*NEWHOPE_SYMBYTES) +#define NEWHOPE_CCAKEM_CIPHERTEXTBYTES (NEWHOPE_CPAPKE_CIPHERTEXTBYTES + NEWHOPE_SYMBYTES) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/poly.c b/crypto_kem/newhope1024ccakem/clean/poly.c new file mode 100644 index 00000000..1c6c4768 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/poly.c @@ -0,0 +1,370 @@ +#include "fips202.h" +#include "ntt.h" +#include "poly.h" +#include "reduce.h" + +/************************************************* +* Name: coeff_freeze +* +* Description: Fully reduces an integer modulo q in constant time +* +* Arguments: uint16_t x: input integer to be reduced +* +* Returns integer in {0,...,q-1} congruent to x modulo q +**************************************************/ +static uint16_t coeff_freeze(uint16_t x) { + uint16_t m, r; + int16_t c; + r = x % NEWHOPE_Q; + + m = r - NEWHOPE_Q; + c = m; + c >>= 15; + r = m ^ ((r ^ m)&c); + + return r; +} + +/************************************************* +* Name: flipabs +* +* Description: Computes |(x mod q) - Q/2| +* +* Arguments: uint16_t x: input coefficient +* +* Returns |(x mod q) - Q/2| +**************************************************/ +static uint16_t flipabs(uint16_t x) { + int16_t r, m; + r = coeff_freeze(x); + + r = r - NEWHOPE_Q / 2; + m = r >> 15; + return (r + m) ^ m; +} + +/************************************************* +* Name: poly_frombytes +* +* Description: De-serialization of a polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(poly *r, const unsigned char *a) { + int i; + for (i = 0; i < NEWHOPE_N / 4; i++) { + r->coeffs[4 * i + 0] = a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); + r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) | (((uint16_t)a[7 * i + 2]) << 2) | (((uint16_t)a[7 * i + 3] & 0x0f) << 10); + r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) | (((uint16_t)a[7 * i + 4]) << 4) | (((uint16_t)a[7 * i + 5] & 0x03) << 12); + r->coeffs[4 * i + 3] = (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6); + } +} + +/************************************************* +* Name: poly_tobytes +* +* Description: Serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(unsigned char *r, const poly *p) { + int i; + uint16_t t0, t1, t2, t3; + for (i = 0; i < NEWHOPE_N / 4; i++) { + t0 = coeff_freeze(p->coeffs[4 * i + 0]); + t1 = coeff_freeze(p->coeffs[4 * i + 1]); + t2 = coeff_freeze(p->coeffs[4 * i + 2]); + t3 = coeff_freeze(p->coeffs[4 * i + 3]); + + r[7 * i + 0] = t0 & 0xff; + r[7 * i + 1] = (t0 >> 8) | (t1 << 6); + r[7 * i + 2] = (t1 >> 2); + r[7 * i + 3] = (t1 >> 10) | (t2 << 4); + r[7 * i + 4] = (t2 >> 4); + r[7 * i + 5] = (t2 >> 12) | (t3 << 2); + r[7 * i + 6] = (t3 >> 6); + } +} + +/************************************************* +* Name: poly_compress +* +* Description: Compression and subsequent serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(unsigned char *r, const poly *p) { + unsigned int i, j, k = 0; + + uint32_t t[8]; + + for (i = 0; i < NEWHOPE_N; i += 8) { + for (j = 0; j < 8; j++) { + t[j] = coeff_freeze(p->coeffs[i + j]); + t[j] = (((t[j] << 3) + NEWHOPE_Q / 2) / NEWHOPE_Q) & 0x7; + } + + r[k] = t[0] | (t[1] << 3) | (t[2] << 6); + r[k + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); + r[k + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + k += 3; + } +} + +/************************************************* +* Name: poly_decompress +* +* Description: De-serialization and subsequent decompression of a polynomial; +* approximate inverse of poly_compress +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(poly *r, const unsigned char *a) { + unsigned int i, j; + for (i = 0; i < NEWHOPE_N; i += 8) { + r->coeffs[i + 0] = a[0] & 7; + r->coeffs[i + 1] = (a[0] >> 3) & 7; + r->coeffs[i + 2] = (a[0] >> 6) | ((a[1] << 2) & 4); + r->coeffs[i + 3] = (a[1] >> 1) & 7; + r->coeffs[i + 4] = (a[1] >> 4) & 7; + r->coeffs[i + 5] = (a[1] >> 7) | ((a[2] << 1) & 6); + r->coeffs[i + 6] = (a[2] >> 2) & 7; + r->coeffs[i + 7] = (a[2] >> 5); + a += 3; + for (j = 0; j < 8; j++) { + r->coeffs[i + j] = ((uint32_t)r->coeffs[i + j] * NEWHOPE_Q + 4) >> 3; + } + } +} + +/************************************************* +* Name: poly_frommsg +* +* Description: Convert 32-byte message to polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *msg: pointer to input message +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { + unsigned int i, j, mask; + for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (j = 0; j < 8; j++) { + mask = -((msg[i] >> j) & 1); + r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 256] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 512] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 768] = mask & (NEWHOPE_Q / 2); + } + } +} + +/************************************************* +* Name: poly_tomsg +* +* Description: Convert polynomial to 32-byte message +* +* Arguments: - unsigned char *msg: pointer to output message +* - const poly *x: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { + unsigned int i; + uint16_t t; + + for (i = 0; i < 32; i++) { + msg[i] = 0; + } + + for (i = 0; i < 256; i++) { + t = flipabs(x->coeffs[i + 0]); + t += flipabs(x->coeffs[i + 256]); + t += flipabs(x->coeffs[i + 512]); + t += flipabs(x->coeffs[i + 768]); + t = ((t - NEWHOPE_Q)); + + t >>= 15; + msg[i >> 3] |= t << (i & 7); + } +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample a polynomial deterministically from a seed, +* with output polynomial looking uniformly random +* +* Arguments: - poly *a: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { + unsigned int ctr = 0; + uint16_t val; + uint64_t state[25]; + uint8_t buf[SHAKE128_RATE]; + uint8_t extseed[NEWHOPE_SYMBYTES + 1]; + int i, j; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ + ctr = 0; + extseed[NEWHOPE_SYMBYTES] = i; /* domain-separate the 16 independent calls */ + shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + while (ctr < 64) { /* Very unlikely to run more than once */ + shake128_squeezeblocks(buf, 1, state); + for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { + val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); + if (val < 5 * NEWHOPE_Q) { + a->coeffs[i * 64 + ctr] = val; + ctr++; + } + } + } + } +} + +/************************************************* +* Name: hw +* +* Description: Compute the Hamming weight of a byte +* +* Arguments: - unsigned char a: input byte +**************************************************/ +static unsigned char hw(unsigned char a) { + unsigned char i, r = 0; + for (i = 0; i < 8; i++) { + r += (a >> i) & 1; + } + return r; +} + +/************************************************* +* Name: poly_sample +* +* Description: Sample a polynomial deterministically from a seed and a nonce, +* with output polynomial close to centered binomial distribution +* with parameter k=8 +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +* - unsigned char nonce: one-byte input nonce +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { + unsigned char buf[128], a, b; +// uint32_t t, d, a, b, c; + int i, j; + + unsigned char extseed[NEWHOPE_SYMBYTES + 2]; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + extseed[NEWHOPE_SYMBYTES] = nonce; + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* Generate noise in blocks of 64 coefficients */ + extseed[NEWHOPE_SYMBYTES + 1] = i; + shake256(buf, 128, extseed, NEWHOPE_SYMBYTES + 2); + for (j = 0; j < 64; j++) { + a = buf[2 * j]; + b = buf[2 * j + 1]; + r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); + /* + t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); + d = 0; + for(k=0;k<8;k++) + d += (t >> k) & 0x01010101; + a = d & 0xff; + b = ((d >> 8) & 0xff); + c = ((d >> 16) & 0xff); + d >>= 24; + r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; + r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; + */ + } + } +} + +/************************************************* +* Name: poly_pointwise +* +* Description: Multiply two polynomials pointwise (i.e., coefficient-wise). +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b) { + int i; + uint16_t t; + for (i = 0; i < NEWHOPE_N; i++) { + t = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(3186 * b->coeffs[i]); /* t is now in Montgomery domain */ + r->coeffs[i] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ + } +} + +/************************************************* +* Name: poly_add +* +* Description: Add two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + 3 * NEWHOPE_Q - b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_ntt +* +* Description: Forward NTT transform of a polynomial in place +* Input is assumed to have coefficients in bitreversed order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(poly *r) { + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery); +} + +/************************************************* +* Name: poly_invntt +* +* Description: Inverse NTT transform of a polynomial in place +* Input is assumed to have coefficients in normal order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(poly *r) { + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(r->coeffs); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery); + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_inv_montgomery); +} + diff --git a/crypto_kem/newhope1024ccakem/clean/poly.h b/crypto_kem/newhope1024ccakem/clean/poly.h new file mode 100644 index 00000000..2ffed246 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/poly.h @@ -0,0 +1,32 @@ +#ifndef POLY_H +#define POLY_H + +#include "params.h" +#include + +/* + * Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial + * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] + */ +typedef struct { + uint16_t coeffs[NEWHOPE_N]; +} poly; + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(poly *a, const unsigned char *seed); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(poly *r); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(poly *r); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(poly *r, const unsigned char *a); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(poly *r, const unsigned char *a); + +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(poly *r, const unsigned char *msg); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(unsigned char *msg, const poly *x); +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(poly *r, const poly *a, const poly *b); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/precomp.c b/crypto_kem/newhope1024ccakem/clean/precomp.c new file mode 100644 index 00000000..b61ee8fb --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/precomp.c @@ -0,0 +1,261 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" + +/* Precomputed NTT contants generated by Pari/GP script as follows: + * + * For n = 512: + * + * brv = [0,256,128,384,64,320,192,448,32,288,160,416,96,352,224,480,16,272,144,400,80,336,208,464,48,304,176,432,112,368,240,496,8, + * 264,136,392,72,328,200,456,40,296,168,424,104,360,232,488,24,280,152,408,88,344,216,472,56,312,184,440,120,376,248,504,4, + * 260,132,388,68,324,196,452,36,292,164,420,100,356,228,484,20,276,148,404,84,340,212,468,52,308,180,436,116,372,244,500,12, + * 268,140,396,76,332,204,460,44,300,172,428,108,364,236,492,28,284,156,412,92,348,220,476,60,316,188,444,124,380,252,508,2, + * 258,130,386,66,322,194,450,34,290,162,418,98,354,226,482,18,274,146,402,82,338,210,466,50,306,178,434,114,370,242,498,10, + * 266,138,394,74,330,202,458,42,298,170,426,106,362,234,490,26,282,154,410,90,346,218,474,58,314,186,442,122,378,250,506,6, + * 262,134,390,70,326,198,454,38,294,166,422,102,358,230,486,22,278,150,406,86,342,214,470,54,310,182,438,118,374,246,502,14, + * 270,142,398,78,334,206,462,46,302,174,430,110,366,238,494,30,286,158,414,94,350,222,478,62,318,190,446,126,382,254,510,1, + * 257,129,385,65,321,193,449,33,289,161,417,97,353,225,481,17,273,145,401,81,337,209,465,49,305,177,433,113,369,241,497,9, + * 265,137,393,73,329,201,457,41,297,169,425,105,361,233,489,25,281,153,409,89,345,217,473,57,313,185,441,121,377,249,505,5, + * 261,133,389,69,325,197,453,37,293,165,421,101,357,229,485,21,277,149,405,85,341,213,469,53,309,181,437,117,373,245,501,13, + * 269,141,397,77,333,205,461,45,301,173,429,109,365,237,493,29,285,157,413,93,349,221,477,61,317,189,445,125,381,253,509,3, + * 259,131,387,67,323,195,451,35,291,163,419,99,355,227,483,19,275,147,403,83,339,211,467,51,307,179,435,115,371,243,499,11, + * 267,139,395,75,331,203,459,43,299,171,427,107,363,235,491,27,283,155,411,91,347,219,475,59,315,187,443,123,379,251,507,7, + * 263,135,391,71,327,199,455,39,295,167,423,103,359,231,487,23,279,151,407,87,343,215,471,55,311,183,439,119,375,247,503,15, + * 271,143,399,79,335,207,463,47,303,175,431,111,367,239,495,31,287,159,415,95,351,223,479,63,319,191,447,127,383,255,511] + * n = 512; q = 12289; mont=2^18 + * g = Mod(10968, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) + * + * + * For n = 1024: + * + * brv = [0,512,256,768,128,640,384,896,64,576,320,832,192,704,448,960,32,544,288,800,160,672,416,928,96,608,352,864,224,736,480,992, \ + * 16,528,272,784,144,656,400,912,80,592,336,848,208,720,464,976,48,560,304,816,176,688,432,944,112,624,368,880,240,752,496,1008, \ + * 8,520,264,776,136,648,392,904,72,584,328,840,200,712,456,968,40,552,296,808,168,680,424,936,104,616,360,872,232,744,488,1000, \ + * 24,536,280,792,152,664,408,920,88,600,344,856,216,728,472,984,56,568,312,824,184,696,440,952,120,632,376,888,248,760,504,1016, \ + * 4,516,260,772,132,644,388,900,68,580,324,836,196,708,452,964,36,548,292,804,164,676,420,932,100,612,356,868,228,740,484,996, \ + * 20,532,276,788,148,660,404,916,84,596,340,852,212,724,468,980,52,564,308,820,180,692,436,948,116,628,372,884,244,756,500,1012, \ + * 12,524,268,780,140,652,396,908,76,588,332,844,204,716,460,972,44,556,300,812,172,684,428,940,108,620,364,876,236,748,492,1004, \ + * 28,540,284,796,156,668,412,924,92,604,348,860,220,732,476,988,60,572,316,828,188,700,444,956,124,636,380,892,252,764,508,1020, \ + * 2,514,258,770,130,642,386,898,66,578,322,834,194,706,450,962,34,546,290,802,162,674,418,930,98,610,354,866,226,738,482,994, \ + * 18,530,274,786,146,658,402,914,82,594,338,850,210,722,466,978,50,562,306,818,178,690,434,946,114,626,370,882,242,754,498,1010, \ + * 10,522,266,778,138,650,394,906,74,586,330,842,202,714,458,970,42,554,298,810,170,682,426,938,106,618,362,874,234,746,490,1002, \ + * 26,538,282,794,154,666,410,922,90,602,346,858,218,730,474,986,58,570,314,826,186,698,442,954,122,634,378,890,250,762,506,1018, \ + * 6,518,262,774,134,646,390,902,70,582,326,838,198,710,454,966,38,550,294,806,166,678,422,934,102,614,358,870,230,742,486,998, \ + * 22,534,278,790,150,662,406,918,86,598,342,854,214,726,470,982,54,566,310,822,182,694,438,950,118,630,374,886,246,758,502,1014, \ + * 14,526,270,782,142,654,398,910,78,590,334,846,206,718,462,974,46,558,302,814,174,686,430,942,110,622,366,878,238,750,494,1006, \ + * 30,542,286,798,158,670,414,926,94,606,350,862,222,734,478,990,62,574,318,830,190,702,446,958,126,638,382,894,254,766,510,1022, \ + * 1,513,257,769,129,641,385,897,65,577,321,833,193,705,449,961,33,545,289,801,161,673,417,929,97,609,353,865,225,737,481,993, \ + * 17,529,273,785,145,657,401,913,81,593,337,849,209,721,465,977,49,561,305,817,177,689,433,945,113,625,369,881,241,753,497,1009, \ + * 9,521,265,777,137,649,393,905,73,585,329,841,201,713,457,969,41,553,297,809,169,681,425,937,105,617,361,873,233,745,489,1001, \ + * 25,537,281,793,153,665,409,921,89,601,345,857,217,729,473,985,57,569,313,825,185,697,441,953,121,633,377,889,249,761,505,1017, \ + * 5,517,261,773,133,645,389,901,69,581,325,837,197,709,453,965,37,549,293,805,165,677,421,933,101,613,357,869,229,741,485,997, \ + * 21,533,277,789,149,661,405,917,85,597,341,853,213,725,469,981,53,565,309,821,181,693,437,949,117,629,373,885,245,757,501,1013, \ + * 13,525,269,781,141,653,397,909,77,589,333,845,205,717,461,973,45,557,301,813,173,685,429,941,109,621,365,877,237,749,493,1005, \ + * 29,541,285,797,157,669,413,925,93,605,349,861,221,733,477,989,61,573,317,829,189,701,445,957,125,637,381,893,253,765,509,1021, \ + * 3,515,259,771,131,643,387,899,67,579,323,835,195,707,451,963,35,547,291,803,163,675,419,931,99,611,355,867,227,739,483,995, \ + * 19,531,275,787,147,659,403,915,83,595,339,851,211,723,467,979,51,563,307,819,179,691,435,947,115,627,371,883,243,755,499,1011, \ + * 11,523,267,779,139,651,395,907,75,587,331,843,203,715,459,971,43,555,299,811,171,683,427,939,107,619,363,875,235,747,491,1003, \ + * 27,539,283,795,155,667,411,923,91,603,347,859,219,731,475,987,59,571,315,827,187,699,443,955,123,635,379,891,251,763,507,1019, \ + * 7,519,263,775,135,647,391,903,71,583,327,839,199,711,455,967,39,551,295,807,167,679,423,935,103,615,359,871,231,743,487,999, \ + * 23,535,279,791,151,663,407,919,87,599,343,855,215,727,471,983,55,567,311,823,183,695,439,951,119,631,375,887,247,759,503,1015, \ + * 15,527,271,783,143,655,399,911,79,591,335,847,207,719,463,975,47,559,303,815,175,687,431,943,111,623,367,879,239,751,495,1007, \ + * 31,543,287,799,159,671,415,927,95,607,351,863,223,735,479,991,63,575,319,831,191,703,447,959,127,639,383,895,255,767,511,1023] + * + * n = 1024; q = 12289; mont=2^18 + * g = Mod(7, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) +*/ + + +/************************************************************ +* Name: omegas_inv_bitrev_montgomery +* +* Description: Contains inverses of powers of nth root of unity +* in Montgomery domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery[NEWHOPE_N / 2] = { + 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278, 9945, 3514, 11248, 11271, 5925, + 147, 8500, 7840, 6833, 5537, 4749, 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, + 9090, 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427, 7341, 6152, 10561, 400, + 8410, 1922, 2033, 8291, 1359, 6854, 11035, 973, 8579, 6093, 6950, 5446, 11821, 8301, 11907, 316, + 52, 3174, 10966, 9523, 6055, 8953, 11612, 6415, 2505, 5906, 10710, 11858, 8332, 9450, 10162, 151, + 3482, 787, 5468, 1010, 4169, 9162, 5241, 9369, 7509, 8844, 7232, 4698, 192, 1321, 10240, 4912, + 885, 6281, 10333, 7280, 8757, 11286, 58, 12048, 12147, 11184, 8812, 6608, 2844, 3438, 4212, 11314, + 8687, 6068, 421, 8209, 3600, 3263, 7665, 6077, 7507, 5886, 3029, 6695, 4213, 504, 11684, 2302, + 1962, 1594, 6328, 7183, 168, 2692, 8960, 4298, 5184, 11089, 6122, 9734, 10929, 3956, 5297, 6170, + 3762, 9370, 4016, 4077, 6523, 652, 11994, 6099, 1146, 11341, 11964, 10885, 6299, 1159, 8240, 8561, + 11177, 2078, 10331, 4322, 11367, 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719, 11454, 6224, + 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633, 12225, 9830, 683, 1566, 5782, 9786, 9341, + 12115, 723, 3009, 1693, 5735, 2655, 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858, + 1583, 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777, 350, 6920, 10232, 4493, 9087, + 8855, 8760, 9381, 218, 9928, 10446, 9259, 4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, + 6381, 11836, 8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008, 5876, 5333, 10258, + 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689, 8236, 2645, 5042, 9984, 7094, 9509, 1484, 7394, + 3, 4437, 160, 3149, 113, 7370, 10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635, 10512, 1663, + 6957, 3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882, 3186, 10659, 10163, 1153, 9405, 8241, 10040, + 2178, 1544, 5559, 420, 8304, 4905, 476, 3531, 5191, 9153, 2399, 8889, 3000, 671, 243, 3016, + 3763, 10849, 12262, 9223, 10657, 7205, 11272, 7404, 7575, 8146, 10752, 242, 2678, 3704, 11744, 5019, + 3833, 3778, 11899, 773, 5101, 11222, 9888, 442, 2912, 5698, 11935, 4861, 7277, 9808, 11244, 2859, + 3780, 11414, 4976, 10682, 7201, 8005, 11287, 5011, 6267, 2987, 2437, 3646, 2566, 10102, 9867, 6250, + 5444, 2381, 11796, 8193, 4337, 11854, 1912, 1378, 404, 7644, 1065, 2143, 11121, 5277, 3248, 11082, + 2548, 8058, 8907, 11934, 1759, 8582, 3694, 7110, 12144, 6747, 8652, 3459, 2731, 8357, 6378, 7399, + 10861, 1696, 9863, 334, 7657, 6534, 11029, 4388, 11560, 3241, 10276, 9000, 9408, 3284, 10200, 7197, + 6498, 544, 2468, 339, 11267, 9, 2842, 480, 5331, 7300, 1673, 4278, 4177, 8705, 9764, 1381, + 7837, 2396, 8340, 8993, 4354, 130, 6915, 2837, 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, + 3006, 9545, 563, 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328, 6512, 1351, 7311, + 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545, 3621, 8747, 8785, 1646, 1212, 5860, 3195, + 7203, 10963, 3201, 3014, 955, 11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995, 11227, + 1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289, 9198, 12208, 2963, 7393, 2366, 9238 +}; + +/************************************************************ +* Name: gammas_bitrev_montgomery +* +* Description: Contains powers of nth root of -1 in Montgomery +* domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery[NEWHOPE_N] = { + 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, 8775, 2344, 11011, 5574, 1973, + 4536, 1050, 6844, 3860, 3818, 6118, 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, + 11973, 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, 3998, 10256, 10367, 3879, + 11889, 1728, 6137, 4948, 5862, 6136, 3643, 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, + 9987, 605, 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080, 11868, 6221, 3602, + 975, 8077, 8851, 9445, 5681, 3477, 1105, 142, 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, + 7377, 2049, 10968, 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821, 11502, 8807, + 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874, 677, 3336, 6234, 2766, 1323, 9115, 12237, + 2031, 6956, 6413, 2281, 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453, 5908, + 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030, 1843, 2361, 12071, 2908, 3529, 3434, + 3202, 7796, 2057, 5369, 11939, 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706, + 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634, 6554, 10596, 9280, 11566, 174, + 2948, 2503, 6507, 10723, 11606, 2459, 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, + 6065, 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, 7967, 1958, 10211, 1112, + 3728, 4049, 11130, 5990, 1404, 325, 948, 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, + 6119, 6992, 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106, 5961, 10695, 10327, + 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969, 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, + 1062, 2294, 3553, 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088, 1326, 5086, + 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479, 1, 8246, 7143, 11567, 10984, 4134, 5736, + 4978, 10938, 5777, 8961, 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744, 9283, + 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374, 12159, 7935, 3296, 3949, 9893, 4452, + 10908, 2525, 3584, 8112, 8011, 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791, + 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755, 4632, 11955, 2426, 10593, 1428, + 4890, 5911, 3932, 9558, 8830, 3637, 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, + 1207, 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952, 4096, 493, 9908, 6845, + 6039, 2422, 2187, 9723, 8643, 9852, 9302, 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, + 9430, 1045, 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, 390, 8511, 8456, + 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, + 9273, 12046, 11618, 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730, 10745, 10111, + 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686, 9042, 2969, 8311, 9424, 9919, 8779, 5332, + 10626, 1777, 4654, 10863, 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852, 12286, + 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364, 3271, 4057, 4414, 9442, 7917, 2174, + 3947, 11951, 2455, 6599, 10545, 10975, 3654, 2894, 7681, 7126, 7287, 12269, 4119, 3343, 2151, 1522, + 7174, 7350, 11041, 2442, 2148, 5959, 6492, 8330, 8945, 5598, 3624, 10397, 1325, 6565, 1945, 11260, + 10077, 2674, 3338, 3276, 11034, 506, 6505, 1392, 5478, 8778, 1178, 2776, 3408, 10347, 11124, 2575, + 9489, 12096, 6092, 10058, 4167, 6085, 923, 11251, 11912, 4578, 10669, 11914, 425, 10453, 392, 10104, + 8464, 4235, 8761, 7376, 2291, 3375, 7954, 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680, 636, + 6825, 7383, 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021, 146, 10485, 1403, 5189, 6094, + 2483, 2054, 3042, 10945, 3981, 10821, 11826, 8882, 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, + 11232, 2600, 7584, 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073, 9261, 2360, 11925, + 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209, 8581, 3238, 8840, 1136, 9363, 1826, 3171, 4489, + 7885, 346, 2068, 1389, 8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125, 11749, + 10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343, 1908, 4538, 10423, 7078, 4727, 1208, + 11572, 3589, 2982, 1373, 1721, 10753, 4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218, + 8347, 5232, 8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566, 5836, 12229, 2717, 1535, 3200, + 5588, 5845, 412, 5102, 7326, 3744, 3056, 2528, 7406, 8314, 9202, 6454, 6613, 1417, 10032, 7784, + 1518, 3765, 4176, 5063, 9828, 2275, 6636, 4267, 6463, 2065, 7725, 3495, 8328, 8755, 8144, 10533, + 5966, 12077, 9175, 9520, 5596, 6302, 8400, 579, 6781, 11014, 5734, 11113, 11164, 4860, 1131, 10844, + 9068, 8016, 9694, 3837, 567, 9348, 7000, 6627, 7699, 5082, 682, 11309, 5207, 4050, 7087, 844, + 7434, 3769, 293, 9057, 6940, 9344, 10883, 2633, 8190, 3944, 5530, 5604, 3480, 2171, 9282, 11024, + 2213, 8136, 3805, 767, 12239, 216, 11520, 6763, 10353, 7, 8566, 845, 7235, 3154, 4360, 3285, + 10268, 2832, 3572, 1282, 7559, 3229, 8360, 10583, 6105, 3120, 6643, 6203, 8536, 8348, 6919, 3536, + 9199, 10891, 11463, 5043, 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783, 3065, 7806, 6586, + 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929, 4684, 12226, 7154, 9916, 7302, 8481, 3670, + 11066, 2334, 1590, 7878, 10734, 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996, + 9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371, 12265, 2485, 11385, 5039, 6742, + 8449, 1842, 12217, 8176, 9577, 4834, 7937, 9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, + 5406, 4665, 3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038, 11249, 2035, 6125, 10407, + 4565, 7315, 5078, 10506, 2840, 2478, 9270, 4194, 9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, + 1734, 3815, 10939, 5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173, 189, 10080, 10526, + 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530, 12150, 8957, 2532, 3317, 9349, 10243, 1481, 9332, + 3454, 3758, 7899, 4218, 2593, 11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988, 8, 457, + 648, 150, 8000, 2307, 2301, 874, 5650, 170, 9462, 2873, 9855, 11498, 2535, 11169, 5808, 12268, + 9687, 1901, 7171, 11787, 3846, 1573, 6063, 3793, 466, 11259, 10608, 3821, 6320, 4649, 6263, 2929 +}; + +/************************************************************ +* Name: gammas_inv_montgomery +* +* Description: Contains inverses of powers of nth root of -1 +* divided by n in Montgomery domain with R=2^18 +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_inv_montgomery[NEWHOPE_N] = { + 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000, 2327, 2088, 5565, 795, 10647, + 1521, 5484, 2539, 7385, 1055, 7173, 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, + 10525, 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207, 5582, 2553, 7387, 6322, + 9681, 1383, 10731, 1533, 219, 5298, 4268, 7632, 6357, 9686, 8406, 4712, 9451, 10128, 4958, 5975, + 11387, 8649, 11769, 6948, 11526, 12180, 1740, 10782, 6807, 2728, 7412, 4570, 4164, 4106, 11120, 12122, + 8754, 11784, 3439, 5758, 11356, 6889, 9762, 11928, 1704, 1999, 10819, 12079, 12259, 7018, 11536, 1648, + 1991, 2040, 2047, 2048, 10826, 12080, 8748, 8272, 8204, 1172, 1923, 7297, 2798, 7422, 6327, 4415, + 7653, 6360, 11442, 12168, 7005, 8023, 9924, 8440, 8228, 2931, 7441, 1063, 3663, 5790, 9605, 10150, + 1450, 8985, 11817, 10466, 10273, 12001, 3470, 7518, 1074, 1909, 7295, 9820, 4914, 702, 5367, 7789, + 8135, 9940, 1420, 3714, 11064, 12114, 12264, 1752, 5517, 9566, 11900, 1700, 3754, 5803, 829, 1874, + 7290, 2797, 10933, 5073, 7747, 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535, 10140, 11982, 8734, + 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825, 5956, 4362, 9401, 1343, 3703, 529, 10609, 12049, + 6988, 6265, 895, 3639, 4031, 4087, 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095, + 10220, 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075, 4379, 11159, 10372, 8504, 4726, + 9453, 3106, 7466, 11600, 10435, 8513, 9994, 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, + 5616, 6069, 867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794, 9177, 1311, 5454, + 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531, 3587, 2268, 324, 5313, 759, 1864, 5533, 2546, + 7386, 9833, 8427, 4715, 11207, 1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474, 10744, 5046, + 4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118, 8182, 4680, 11202, 6867, 981, 8918, 1274, + 182, 26, 7026, 8026, 11680, 12202, 10521, 1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454, 3249, + 9242, 6587, 941, 1890, 270, 10572, 6777, 9746, 6659, 6218, 6155, 6146, 878, 1881, 7291, 11575, + 12187, 1741, 7271, 8061, 11685, 6936, 4502, 9421, 4857, 4205, 7623, 1089, 10689, 1527, 8996, 10063, + 11971, 10488, 6765, 2722, 3900, 9335, 11867, 6962, 11528, 5158, 4248, 4118, 5855, 2592, 5637, 6072, + 2623, 7397, 8079, 9932, 4930, 5971, 853, 3633, 519, 8852, 11798, 3441, 11025, 1575, 225, 8810, + 11792, 12218, 3501, 9278, 3081, 9218, 4828, 7712, 8124, 11694, 12204, 3499, 4011, 573, 3593, 5780, + 7848, 9899, 10192, 1456, 208, 7052, 2763, 7417, 11593, 10434, 12024, 8740, 11782, 10461, 3250, 5731, + 7841, 9898, 1414, 202, 3540, 7528, 2831, 2160, 10842, 5060, 4234, 4116, 588, 84, 12, 7024, + 2759, 9172, 6577, 11473, 1639, 9012, 3043, 7457, 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778, + 12216, 10523, 6770, 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540, 6201, 4397, 9406, 8366, 9973, + 8447, 8229, 11709, 8695, 10020, 3187, 5722, 2573, 10901, 6824, 4486, 4152, 9371, 8361, 2950, 2177, + 311, 1800, 9035, 8313, 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609, 3414, 7510, + 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815, 10180, 6721, 9738, 10169, 8475, 8233, + 9954, 1422, 8981, 1283, 5450, 11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704, + 672, 96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500, 1500, 5481, 783, 3623, 11051, + 8601, 8251, 8201, 11705, 10450, 5004, 4226, 7626, 2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, + 1514, 5483, 6050, 6131, 4387, 7649, 8115, 6426, 918, 8909, 8295, 1185, 5436, 11310, 8638, 1234, + 5443, 11311, 5127, 2488, 2111, 10835, 5059, 7745, 2862, 3920, 560, 80, 1767, 2008, 3798, 11076, + 6849, 2734, 10924, 12094, 8750, 1250, 10712, 6797, 971, 7161, 1023, 8924, 4786, 7706, 4612, 4170, + 7618, 6355, 4419, 5898, 11376, 10403, 10264, 6733, 4473, 639, 5358, 2521, 9138, 3061, 5704, 4326, + 618, 5355, 765, 5376, 768, 7132, 4530, 9425, 3102, 9221, 6584, 11474, 10417, 10266, 12000, 6981, + 6264, 4406, 2385, 7363, 4563, 4163, 7617, 9866, 3165, 9230, 11852, 10471, 5007, 5982, 11388, 5138, + 734, 3616, 11050, 12112, 6997, 11533, 12181, 10518, 12036, 3475, 2252, 7344, 9827, 4915, 9480, 6621, + 4457, 7659, 9872, 6677, 4465, 4149, 7615, 4599, 657, 3605, 515, 10607, 6782, 4480, 640, 1847, + 3775, 5806, 2585, 5636, 9583, 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184, 9947, 1421, + 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378, 4708, 11206, 5112, 5997, 7879, 11659, + 12199, 8765, 10030, 4944, 5973, 6120, 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, + 8394, 9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742, 106, 8793, 10034, 3189, + 10989, 5081, 4237, 5872, 4350, 2377, 10873, 6820, 6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, + 2453, 2106, 3812, 11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262, 4120, 11122, 5100, + 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930, 10952, 12098, 6995, 6266, 9673, 4893, 699, 3611, + 4027, 5842, 11368, 1624, 232, 8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797, 3625, 4029, + 11109, 1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093, 12261, 12285, 1755, 7273, 1039, 1904, 272, + 3550, 9285, 3082, 5707, 6082, 4380, 7648, 11626, 5172, 4250, 9385, 8363, 8217, 4685, 5936, 848, + 8899, 6538, 934, 1889, 3781, 9318, 10109, 10222, 6727, 961, 5404, 772, 5377, 9546, 8386, 1198, + 8949, 3034, 2189, 7335, 4559, 5918, 2601, 10905, 5069, 9502, 3113, 7467, 8089, 11689, 5181, 9518, + 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914, 5683, 4323, 11151, 1593, 10761, 6804, 972, 3650, + 2277, 5592, 4310, 7638, 9869, 4921, 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765, + 6376, 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721, 12065, 12257, 1751, 9028, + 8312, 2943, 2176, 3822, 546, 78, 8789, 11789, 10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, + 613, 10621, 6784, 9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688, 6365, 6176, 6149, + 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894, 10477, 8519, 1217, 3685, 2282, 326, 10580, 3267, + 7489, 4581, 2410, 5611, 11335, 6886, 8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185, 455, 65, + 5276, 7776, 4622, 5927, 7869, 9902, 11948, 5218, 2501, 5624, 2559, 10899, 1557, 1978, 10816, 10323, + 8497, 4725, 675, 1852, 10798, 12076, 10503, 3256, 9243, 3076, 2195, 10847, 12083, 10504, 12034, 10497 +}; + diff --git a/crypto_kem/newhope1024ccakem/clean/reduce.c b/crypto_kem/newhope1024ccakem/clean/reduce.c new file mode 100644 index 00000000..d14c6748 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/reduce.c @@ -0,0 +1,26 @@ +#include "reduce.h" +#include "params.h" + +static const uint32_t qinv = 12287; // -inverse_mod(p,2^18) +static const uint32_t rlog = 18; + +/************************************************* +* Name: verify +* +* Description: Montgomery reduction; given a 32-bit integer a, computes +* 16-bit integer congruent to a * R^-1 mod q, +* where R=2^18 (see value of rlog) +* +* Arguments: - uint32_t a: input unsigned integer to be reduced; has to be in {0,...,1073491968} +* +* Returns: unsigned integer in {0,...,2^14-1} congruent to a * R^-1 modulo q. +**************************************************/ +uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(uint32_t a) { + uint32_t u; + + u = (a * qinv); + u &= ((1 << rlog) - 1); + u *= NEWHOPE_Q; + a = a + u; + return a >> 18; +} diff --git a/crypto_kem/newhope1024ccakem/clean/reduce.h b/crypto_kem/newhope1024ccakem/clean/reduce.h new file mode 100644 index 00000000..1598d193 --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/reduce.h @@ -0,0 +1,8 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include + +uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(uint32_t a); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/verify.c b/crypto_kem/newhope1024ccakem/clean/verify.c new file mode 100644 index 00000000..c277b8be --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/verify.c @@ -0,0 +1,49 @@ +#include "verify.h" +#include +#include + +/************************************************* +* Name: verify +* +* Description: Compare two arrays for equality in constant time. +* +* Arguments: const unsigned char *a: pointer to first byte array +* const unsigned char *b: pointer to second byte array +* size_t len: length of the byte arrays +* +* Returns 0 if the byte arrays are equal, 1 otherwise +**************************************************/ +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { + uint64_t r; + size_t i; + r = 0; + + for (i = 0; i < len; i++) { + r |= a[i] ^ b[i]; + } + + r = (-r) >> 63; + return r; +} + +/************************************************* +* Name: cmov +* +* Description: Copy len bytes from x to r if b is 1; +* don't modify x if b is 0. Requires b to be in {0,1}; +* assumes two's complement representation of negative integers. +* Runs in constant time. +* +* Arguments: unsigned char *r: pointer to output byte array +* const unsigned char *x: pointer to input byte array +* size_t len: Amount of bytes to be copied +* unsigned char b: Condition bit; has to be in {0,1} +**************************************************/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/newhope1024ccakem/clean/verify.h b/crypto_kem/newhope1024ccakem/clean/verify.h new file mode 100644 index 00000000..12e73d9d --- /dev/null +++ b/crypto_kem/newhope1024ccakem/clean/verify.h @@ -0,0 +1,12 @@ +#ifndef VERIFY_H +#define VERIFY_H + +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); + +#endif From 82e53bfdd1f69d1b8f47dcab5df8d1404f5f2775 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 7 May 2019 19:20:06 +0200 Subject: [PATCH 02/35] fix MS compiler warnings --- crypto_kem/newhope1024ccakem/clean/kem.c | 2 +- crypto_kem/newhope1024ccakem/clean/poly.c | 22 ++++++++++----------- crypto_kem/newhope1024ccakem/clean/verify.c | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crypto_kem/newhope1024ccakem/clean/kem.c b/crypto_kem/newhope1024ccakem/clean/kem.c index fc33da81..67585c23 100644 --- a/crypto_kem/newhope1024ccakem/clean/kem.c +++ b/crypto_kem/newhope1024ccakem/clean/kem.c @@ -109,7 +109,7 @@ int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_dec(unsigned char *ss, const unsi fail = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(ct, ct_cmp, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); shake256(k_coins_d + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, ct, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); /* overwrite coins in k_coins_d with h(c) */ - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(k_coins_d, sk + NEWHOPE_CCAKEM_SECRETKEYBYTES - NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */ + PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(k_coins_d, sk + NEWHOPE_CCAKEM_SECRETKEYBYTES - NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, (unsigned char) fail); /* Overwrite pre-k with z on re-encryption failure */ shake256(ss, NEWHOPE_SYMBYTES, k_coins_d, 2 * NEWHOPE_SYMBYTES); /* hash concatenation of pre-k and h(c) to k */ return 0; diff --git a/crypto_kem/newhope1024ccakem/clean/poly.c b/crypto_kem/newhope1024ccakem/clean/poly.c index 1c6c4768..4d11314d 100644 --- a/crypto_kem/newhope1024ccakem/clean/poly.c +++ b/crypto_kem/newhope1024ccakem/clean/poly.c @@ -79,12 +79,12 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(unsigned char *r, const poly * t3 = coeff_freeze(p->coeffs[4 * i + 3]); r[7 * i + 0] = t0 & 0xff; - r[7 * i + 1] = (t0 >> 8) | (t1 << 6); - r[7 * i + 2] = (t1 >> 2); - r[7 * i + 3] = (t1 >> 10) | (t2 << 4); - r[7 * i + 4] = (t2 >> 4); - r[7 * i + 5] = (t2 >> 12) | (t3 << 2); - r[7 * i + 6] = (t3 >> 6); + r[7 * i + 1] = (unsigned char) ((t0 >> 8) | (t1 << 6)); + r[7 * i + 2] = (unsigned char) ((t1 >> 2)); + r[7 * i + 3] = (unsigned char) ((t1 >> 10) | (t2 << 4)); + r[7 * i + 4] = (unsigned char) ((t2 >> 4)); + r[7 * i + 5] = (unsigned char) ((t2 >> 12) | (t3 << 2)); + r[7 * i + 6] = (unsigned char) ((t3 >> 6)); } } @@ -107,9 +107,9 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(unsigned char *r, const poly t[j] = (((t[j] << 3) + NEWHOPE_Q / 2) / NEWHOPE_Q) & 0x7; } - r[k] = t[0] | (t[1] << 3) | (t[2] << 6); - r[k + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7); - r[k + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5); + r[k] = (unsigned char) (t[0] | (t[1] << 3) | (t[2] << 6)); + r[k + 1] = (unsigned char) ((t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7)); + r[k + 2] = (unsigned char) ((t[5] >> 1) | (t[6] << 2) | (t[7] << 5)); k += 3; } } @@ -213,7 +213,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(poly *a, const unsigned char * for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ ctr = 0; - extseed[NEWHOPE_SYMBYTES] = i; /* domain-separate the 16 independent calls */ + extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); while (ctr < 64) { /* Very unlikely to run more than once */ shake128_squeezeblocks(buf, 1, state); @@ -267,7 +267,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(poly *r, const unsigned char *s extseed[NEWHOPE_SYMBYTES] = nonce; for (i = 0; i < NEWHOPE_N / 64; i++) { /* Generate noise in blocks of 64 coefficients */ - extseed[NEWHOPE_SYMBYTES + 1] = i; + extseed[NEWHOPE_SYMBYTES + 1] = (unsigned char) i; shake256(buf, 128, extseed, NEWHOPE_SYMBYTES + 2); for (j = 0; j < 64; j++) { a = buf[2 * j]; diff --git a/crypto_kem/newhope1024ccakem/clean/verify.c b/crypto_kem/newhope1024ccakem/clean/verify.c index c277b8be..8e5126c2 100644 --- a/crypto_kem/newhope1024ccakem/clean/verify.c +++ b/crypto_kem/newhope1024ccakem/clean/verify.c @@ -22,8 +22,8 @@ int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(const unsigned char *a, const unsigne r |= a[i] ^ b[i]; } - r = (-r) >> 63; - return r; + r = (-(int64_t)r) >> 63; + return (int)r; } /************************************************* From 01b3bde4bd974e9fba142e8d72c458eec858382a Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 7 May 2019 19:33:23 +0200 Subject: [PATCH 03/35] remove testvector hash --- crypto_kem/newhope1024ccakem/META.yml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crypto_kem/newhope1024ccakem/META.yml b/crypto_kem/newhope1024ccakem/META.yml index 467ed950..d8c4662c 100644 --- a/crypto_kem/newhope1024ccakem/META.yml +++ b/crypto_kem/newhope1024ccakem/META.yml @@ -2,12 +2,11 @@ name: NewHope1024CCAKEM type: kem claimed-nist-level: 5 length-public-key: 1824 -length-secret-key: 3680 -length-ciphertext: 2208 -length-shared-secret: 32 -testvectors-sha256: 233bab7b5e2971b7e271f046e39ba443ffcceada84d3fdb5017d6d3a2e48b0d0 -nistkat-sha256: 8500b88222b3a62e57a6ecaac57f79258f08af49211e0c3f2ca7eab8089c0ce0 -principal-submitter: Thomas Pöppelmann +length-secret-key: 3680 +length-ciphertext: 2208 +length-shared-secret: 32 +nistkat-sha256: 8500b88222b3a62e57a6ecaac57f79258f08af49211e0c3f2ca7eab8089c0ce0 +principal-submitter: Thomas Pöppelmann auxiliary-submitters: - Erdem Alkim - Roberto Avanzi From d879595da33a155bad9a0397a206580f7570f3a2 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 8 May 2019 17:06:55 +0200 Subject: [PATCH 04/35] add newhope512cca --- crypto_kem/newhope512cca/META.yml | 20 + crypto_kem/newhope512cca/clean/LICENSE | 1 + crypto_kem/newhope512cca/clean/Makefile | 19 + .../clean/Makefile.Microsoft_nmake | 19 + crypto_kem/newhope512cca/clean/api.h | 15 + crypto_kem/newhope512cca/clean/cpapke.c | 192 +++++++++ crypto_kem/newhope512cca/clean/cpapke.h | 16 + crypto_kem/newhope512cca/clean/kem.c | 116 ++++++ crypto_kem/newhope512cca/clean/ntt.c | 112 ++++++ crypto_kem/newhope512cca/clean/ntt.h | 14 + crypto_kem/newhope512cca/clean/params.h | 25 ++ crypto_kem/newhope512cca/clean/poly.c | 366 ++++++++++++++++++ crypto_kem/newhope512cca/clean/poly.h | 32 ++ crypto_kem/newhope512cca/clean/precomp.c | 179 +++++++++ crypto_kem/newhope512cca/clean/reduce.c | 26 ++ crypto_kem/newhope512cca/clean/reduce.h | 8 + crypto_kem/newhope512cca/clean/verify.c | 49 +++ crypto_kem/newhope512cca/clean/verify.h | 12 + 18 files changed, 1221 insertions(+) create mode 100644 crypto_kem/newhope512cca/META.yml create mode 100644 crypto_kem/newhope512cca/clean/LICENSE create mode 100644 crypto_kem/newhope512cca/clean/Makefile create mode 100644 crypto_kem/newhope512cca/clean/Makefile.Microsoft_nmake create mode 100644 crypto_kem/newhope512cca/clean/api.h create mode 100644 crypto_kem/newhope512cca/clean/cpapke.c create mode 100644 crypto_kem/newhope512cca/clean/cpapke.h create mode 100644 crypto_kem/newhope512cca/clean/kem.c create mode 100644 crypto_kem/newhope512cca/clean/ntt.c create mode 100644 crypto_kem/newhope512cca/clean/ntt.h create mode 100644 crypto_kem/newhope512cca/clean/params.h create mode 100644 crypto_kem/newhope512cca/clean/poly.c create mode 100644 crypto_kem/newhope512cca/clean/poly.h create mode 100644 crypto_kem/newhope512cca/clean/precomp.c create mode 100644 crypto_kem/newhope512cca/clean/reduce.c create mode 100644 crypto_kem/newhope512cca/clean/reduce.h create mode 100644 crypto_kem/newhope512cca/clean/verify.c create mode 100644 crypto_kem/newhope512cca/clean/verify.h diff --git a/crypto_kem/newhope512cca/META.yml b/crypto_kem/newhope512cca/META.yml new file mode 100644 index 00000000..d35d9630 --- /dev/null +++ b/crypto_kem/newhope512cca/META.yml @@ -0,0 +1,20 @@ +name: NewHope512CCA +type: kem +claimed-nist-level: 1 +length-public-key: 928 +length-secret-key: 1888 +length-ciphertext: 1120 +length-shared-secret: 32 +nistkat-sha256: 5b0389f8d9c30055ad0fb83da540ca36969dde041bebe6f1018c37768c5e1479 +principal-submitter: Thomas Pöppelmann +auxiliary-submitters: +- Erdem Alkim +- Roberto Avanzi +- Joppe Bos +- Léo Ducas +- Antonio de la Piedra +- Peter Schwabe +- Douglas Stebila +implementations: +- name: clean + version: https://github.com/newhopecrypto/newhope/commit/3fc68c6090b23c56cc190a78af2f43ee8900e9d0 diff --git a/crypto_kem/newhope512cca/clean/LICENSE b/crypto_kem/newhope512cca/clean/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/newhope512cca/clean/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/newhope512cca/clean/Makefile b/crypto_kem/newhope512cca/clean/Makefile new file mode 100644 index 00000000..34b0c30f --- /dev/null +++ b/crypto_kem/newhope512cca/clean/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libnewhope512cca_clean.a +HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h +OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/newhope512cca/clean/Makefile.Microsoft_nmake b/crypto_kem/newhope512cca/clean/Makefile.Microsoft_nmake new file mode 100644 index 00000000..321e4e6a --- /dev/null +++ b/crypto_kem/newhope512cca/clean/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libnewhope512cca_clean.lib +OBJECTS=cpapke.obj kem.obj ntt.obj poly.obj precomp.obj reduce.obj verify.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/newhope512cca/clean/api.h b/crypto_kem/newhope512cca/clean/api.h new file mode 100644 index 00000000..6526df97 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/api.h @@ -0,0 +1,15 @@ +#ifndef PQCLEAN_NEWHOPE512CCA_CLEAN_API_H +#define PQCLEAN_NEWHOPE512CCA_CLEAN_API_H + + +#define PQCLEAN_NEWHOPE512CCA_CLEAN_CRYPTO_SECRETKEYBYTES 1888 +#define PQCLEAN_NEWHOPE512CCA_CLEAN_CRYPTO_PUBLICKEYBYTES 928 +#define PQCLEAN_NEWHOPE512CCA_CLEAN_CRYPTO_CIPHERTEXTBYTES 1120 +#define PQCLEAN_NEWHOPE512CCA_CLEAN_CRYPTO_BYTES 32 +#define PQCLEAN_NEWHOPE512CCA_CLEAN_CRYPTO_ALGNAME "NewHope512-CCAKEM" + +int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); +int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); +int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope512cca/clean/cpapke.c b/crypto_kem/newhope512cca/clean/cpapke.c new file mode 100644 index 00000000..f965a213 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/cpapke.c @@ -0,0 +1,192 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "poly.h" +#include "randombytes.h" +#include + +/************************************************* +* Name: encode_pk +* +* Description: Serialize the public key as concatenation of the +* serialization of the polynomial pk and the public seed +* used to generete the polynomial a. +* +* Arguments: unsigned char *r: pointer to the output serialized public key +* const poly *pk: pointer to the input public-key polynomial +* const unsigned char *seed: pointer to the input public seed +**************************************************/ +static void encode_pk(unsigned char *r, const poly *pk, const unsigned char *seed) { + int i; + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tobytes(r, pk); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + r[NEWHOPE_POLYBYTES + i] = seed[i]; + } +} + +/************************************************* +* Name: decode_pk +* +* Description: De-serialize the public key; inverse of encode_pk +* +* Arguments: poly *pk: pointer to output public-key polynomial +* unsigned char *seed: pointer to output public seed +* const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_pk(poly *pk, unsigned char *seed, const unsigned char *r) { + int i; + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frombytes(pk, r); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + seed[i] = r[NEWHOPE_POLYBYTES + i]; + } +} + +/************************************************* +* Name: encode_c +* +* Description: Serialize the ciphertext as concatenation of the +* serialization of the polynomial b and serialization +* of the compressed polynomial v +* +* Arguments: - unsigned char *r: pointer to the output serialized ciphertext +* - const poly *b: pointer to the input polynomial b +* - const poly *v: pointer to the input polynomial v +**************************************************/ +static void encode_c(unsigned char *r, const poly *b, const poly *v) { + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tobytes(r, b); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_compress(r + NEWHOPE_POLYBYTES, v); +} + +/************************************************* +* Name: decode_c +* +* Description: de-serialize the ciphertext; inverse of encode_c +* +* Arguments: - poly *b: pointer to output polynomial b +* - poly *v: pointer to output polynomial v +* - const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_c(poly *b, poly *v, const unsigned char *r) { + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frombytes(b, r); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_decompress(v, r + NEWHOPE_POLYBYTES); +} + +/************************************************* +* Name: gen_a +* +* Description: Deterministically generate public polynomial a from seed +* +* Arguments: - poly *a: pointer to output polynomial a +* - const unsigned char *seed: pointer to input seed +**************************************************/ +static void gen_a(poly *a, const unsigned char *seed) { + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_uniform(a, seed); +} + + +/************************************************* +* Name: cpapke_keypair +* +* Description: Generates public and private key +* for the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *pk: pointer to output public key +* - unsigned char *sk: pointer to output private key +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk) { + poly ahat, ehat, ahat_shat, bhat, shat; + unsigned char z[2 * NEWHOPE_SYMBYTES]; + unsigned char *publicseed = z; + unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; + + randombytes(z, NEWHOPE_SYMBYTES); + shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); + + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(&shat, noiseseed, 0); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_ntt(&shat); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(&ehat, noiseseed, 1); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_ntt(&ehat); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_mul_pointwise(&ahat_shat, &shat, &ahat); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_add(&bhat, &ehat, &ahat_shat); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tobytes(sk, &shat); + encode_pk(pk, &bhat, publicseed); +} + +/************************************************* +* Name: cpapke_enc +* +* Description: Encryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *c: pointer to output ciphertext +* - const unsigned char *m: pointer to input message (of length NEWHOPE_SYMBYTES bytes) +* - const unsigned char *pk: pointer to input public key +* - const unsigned char *coin: pointer to input random coins used as seed +* to deterministically generate all randomness +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coin) { + poly sprime, eprime, vprime, ahat, bhat, eprimeprime, uhat, v; + unsigned char publicseed[NEWHOPE_SYMBYTES]; + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frommsg(&v, m); + + decode_pk(&bhat, publicseed, pk); + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(&sprime, coin, 0); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(&eprime, coin, 1); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(&eprimeprime, coin, 2); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_ntt(&sprime); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_ntt(&eprime); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_mul_pointwise(&uhat, &ahat, &sprime); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_add(&uhat, &uhat, &eprime); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_mul_pointwise(&vprime, &bhat, &sprime); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_invntt(&vprime); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_add(&vprime, &vprime, &eprimeprime); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_add(&vprime, &vprime, &v); // add message + + encode_c(c, &uhat, &vprime); +} + + +/************************************************* +* Name: cpapke_dec +* +* Description: Decryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *m: pointer to output decrypted message +* - const unsigned char *c: pointer to input ciphertext +* - const unsigned char *sk: pointer to input secret key +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk) { + poly vprime, uhat, tmp, shat; + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frombytes(&shat, sk); + + decode_c(&uhat, &vprime, c); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_mul_pointwise(&tmp, &shat, &uhat); + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_invntt(&tmp); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sub(&tmp, &tmp, &vprime); + + PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tomsg(m, &tmp); +} diff --git a/crypto_kem/newhope512cca/clean/cpapke.h b/crypto_kem/newhope512cca/clean/cpapke.h new file mode 100644 index 00000000..4b99524b --- /dev/null +++ b/crypto_kem/newhope512cca/clean/cpapke.h @@ -0,0 +1,16 @@ +#ifndef INDCPA_H +#define INDCPA_H + +void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk); + +void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coins); + +void PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope512cca/clean/kem.c b/crypto_kem/newhope512cca/clean/kem.c new file mode 100644 index 00000000..a9d5da8c --- /dev/null +++ b/crypto_kem/newhope512cca/clean/kem.c @@ -0,0 +1,116 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "params.h" +#include "randombytes.h" +#include "verify.h" + +#include + +/************************************************* +* Name: crypto_kem_keypair +* +* Description: Generates public and private key +* for CCA secure NewHope key encapsulation +* mechanism +* +* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + size_t i; + + PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_keypair(pk, sk); /* First put the actual secret key into sk */ + sk += NEWHOPE_CPAPKE_SECRETKEYBYTES; + + for (i = 0; i < NEWHOPE_CPAPKE_PUBLICKEYBYTES; i++) { /* Append the public key for re-encryption */ + sk[i] = pk[i]; + } + sk += NEWHOPE_CPAPKE_PUBLICKEYBYTES; + + shake256(sk, NEWHOPE_SYMBYTES, pk, NEWHOPE_CPAPKE_PUBLICKEYBYTES); /* Append the hash of the public key */ + sk += NEWHOPE_SYMBYTES; + + randombytes(sk, NEWHOPE_SYMBYTES); /* Append the value s for pseudo-random output on reject */ + + return 0; +} + +/************************************************* +* Name: crypto_kem_enc +* +* Description: Generates cipher text and shared +* secret for given public key +* +* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { + unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ + unsigned char buf[2 * NEWHOPE_SYMBYTES]; + int i; + + randombytes(buf, NEWHOPE_SYMBYTES); + + shake256(buf, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ + shake256(buf + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */ + shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); + + PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(ct, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */ + } + + shake256(k_coins_d + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, ct, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); /* overwrite coins in k_coins_d with h(c) */ + shake256(ss, NEWHOPE_SYMBYTES, k_coins_d, 2 * NEWHOPE_SYMBYTES); /* hash concatenation of pre-k and h(c) to ss */ + return 0; +} + +/************************************************* +* Name: crypto_kem_dec +* +* Description: Generates shared secret for given +* cipher text and private key +* +* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 for sucess or -1 for failure +* +* On failure, ss will contain a randomized value. +**************************************************/ +int PQCLEAN_NEWHOPE512CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { + int i, fail; + unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES]; + unsigned char buf[2 * NEWHOPE_SYMBYTES]; + unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ + const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES; + + PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_dec(buf, ct, sk); + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */ + buf[NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i]; + } + shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); + + PQCLEAN_NEWHOPE512CCA_CLEAN_cpapke_enc(ct_cmp, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; + } + + fail = PQCLEAN_NEWHOPE512CCA_CLEAN_verify(ct, ct_cmp, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); + + shake256(k_coins_d + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, ct, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); /* overwrite coins in k_coins_d with h(c) */ + PQCLEAN_NEWHOPE512CCA_CLEAN_cmov(k_coins_d, sk + NEWHOPE_CCAKEM_SECRETKEYBYTES - NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, (unsigned char) fail); /* Overwrite pre-k with z on re-encryption failure */ + shake256(ss, NEWHOPE_SYMBYTES, k_coins_d, 2 * NEWHOPE_SYMBYTES); /* hash concatenation of pre-k and h(c) to k */ + + return 0; +} diff --git a/crypto_kem/newhope512cca/clean/ntt.c b/crypto_kem/newhope512cca/clean/ntt.c new file mode 100644 index 00000000..17cad0a0 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/ntt.c @@ -0,0 +1,112 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" + +/************************************************************ +* Name: bitrev_table +* +* Description: Contains bit-reversed 9-bit indices to be used to re-order +* polynomials before number theoratic transform +************************************************************/ +static uint16_t bitrev_table [512] = { + 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, 240, 496, 8, + 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, 120, 376, 248, 504, 4, + 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, 180, 436, 116, 372, 244, 500, 12, + 268, 140, 396, 76, 332, 204, 460, 44, 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, 60, 316, 188, 444, 124, 380, 252, 508, 2, + 258, 130, 386, 66, 322, 194, 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, + 266, 138, 394, 74, 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, + 262, 134, 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, + 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, 510, 1, + 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, 369, 241, 497, 9, + 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, 441, 121, 377, 249, 505, 5, + 261, 133, 389, 69, 325, 197, 453, 37, 293, 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, 309, 181, 437, 117, 373, 245, 501, 13, + 269, 141, 397, 77, 333, 205, 461, 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, + 259, 131, 387, 67, 323, 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, + 267, 139, 395, 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, + 263, 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, 15, + 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, 255, 511 +}; + +/************************************************* +* Name: bitrev_vector +* +* Description: Permutes coefficients of a polynomial into bitreversed order +* +* Arguments: - uint16_t* poly: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_bitrev_vector(uint16_t *poly) { + unsigned int i, r; + uint16_t tmp; + + for (i = 0; i < NEWHOPE_N; i++) { + r = bitrev_table[i]; + if (i < r) { + tmp = poly[i]; + poly[i] = poly[r]; + poly[r] = tmp; + } + } +} + +/************************************************* +* Name: mul_coefficients +* +* Description: Performs pointwise (coefficient-wise) multiplication +* of two polynomials +* Arguments: - uint16_t* poly: pointer to in/output polynomial +* - const uint16_t* factors: pointer to input polynomial, coefficients +* are assumed to be in Montgomery representation +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors) { + unsigned int i; + + for (i = 0; i < NEWHOPE_N; i++) { + poly[i] = PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce((poly[i] * factors[i])); + } +} + + +/************************************************* +* Name: ntt +* +* Description: Computes number-theoretic transform (NTT) of +* a polynomial in place; inputs assumed to be in +* bitreversed order, output in normal order +* +* Arguments: - uint16_t * a: pointer to in/output polynomial +* - const uint16_t* omega: pointer to input powers of root of unity omega; +* assumed to be in Montgomery domain +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { + int i, start, j, jTwiddle, distance; + uint16_t temp, W; + + + for (i = 0; i < 9; i += 2) { + // Even level + distance = (1 << i); + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]); // Omit reduction (be lazy) + a[j + distance] = PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + if (i + 1 < 9) { + // Odd level + distance <<= 1; + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]) % NEWHOPE_Q; + a[j + distance] = PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + } + } +} diff --git a/crypto_kem/newhope512cca/clean/ntt.h b/crypto_kem/newhope512cca/clean/ntt.h new file mode 100644 index 00000000..ecc7b993 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/ntt.h @@ -0,0 +1,14 @@ +#ifndef NTT_H +#define NTT_H + +#include "inttypes.h" + +extern const uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_omegas_inv_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_inv_montgomery[]; + +void PQCLEAN_NEWHOPE512CCA_CLEAN_bitrev_vector(uint16_t *poly); +void PQCLEAN_NEWHOPE512CCA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors); +void PQCLEAN_NEWHOPE512CCA_CLEAN_ntt(uint16_t *a, const uint16_t *omegas); + +#endif diff --git a/crypto_kem/newhope512cca/clean/params.h b/crypto_kem/newhope512cca/clean/params.h new file mode 100644 index 00000000..6526ba90 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/params.h @@ -0,0 +1,25 @@ +#ifndef PQCLEAN_NEWHOPE512CCA_CLEAN_PARAMS_H +#define PQCLEAN_NEWHOPE512CCA_CLEAN_PARAMS_H + +#define NEWHOPE_N 512 +#define NEWHOPE_Q 12289 +#define NEWHOPE_K 8 /* used in noise sampling */ + +#define NEWHOPE_SYMBYTES 32 /* size of shared key, seeds/coins, and hashes */ + +#define NEWHOPE_POLYBYTES ((14*NEWHOPE_N)/8) +#define NEWHOPE_POLYCOMPRESSEDBYTES (( 3*NEWHOPE_N)/8) + +#define NEWHOPE_CPAPKE_PUBLICKEYBYTES (NEWHOPE_POLYBYTES + NEWHOPE_SYMBYTES) +#define NEWHOPE_CPAPKE_SECRETKEYBYTES (NEWHOPE_POLYBYTES) +#define NEWHOPE_CPAPKE_CIPHERTEXTBYTES (NEWHOPE_POLYBYTES + NEWHOPE_POLYCOMPRESSEDBYTES) + +#define NEWHOPE_CPAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CPAKEM_SECRETKEYBYTES NEWHOPE_CPAPKE_SECRETKEYBYTES +#define NEWHOPE_CPAKEM_CIPHERTEXTBYTES NEWHOPE_CPAPKE_CIPHERTEXTBYTES + +#define NEWHOPE_CCAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CCAKEM_SECRETKEYBYTES (NEWHOPE_CPAPKE_SECRETKEYBYTES + NEWHOPE_CPAPKE_PUBLICKEYBYTES + 2*NEWHOPE_SYMBYTES) +#define NEWHOPE_CCAKEM_CIPHERTEXTBYTES (NEWHOPE_CPAPKE_CIPHERTEXTBYTES + NEWHOPE_SYMBYTES) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/newhope512cca/clean/poly.c b/crypto_kem/newhope512cca/clean/poly.c new file mode 100644 index 00000000..53c54083 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/poly.c @@ -0,0 +1,366 @@ +#include "fips202.h" +#include "ntt.h" +#include "poly.h" +#include "reduce.h" + +/************************************************* +* Name: coeff_freeze +* +* Description: Fully reduces an integer modulo q in constant time +* +* Arguments: uint16_t x: input integer to be reduced +* +* Returns integer in {0,...,q-1} congruent to x modulo q +**************************************************/ +static uint16_t coeff_freeze(uint16_t x) { + uint16_t m, r; + int16_t c; + r = x % NEWHOPE_Q; + + m = r - NEWHOPE_Q; + c = m; + c >>= 15; + r = m ^ ((r ^ m)&c); + + return r; +} + +/************************************************* +* Name: flipabs +* +* Description: Computes |(x mod q) - Q/2| +* +* Arguments: uint16_t x: input coefficient +* +* Returns |(x mod q) - Q/2| +**************************************************/ +static uint16_t flipabs(uint16_t x) { + int16_t r, m; + r = coeff_freeze(x); + + r = r - NEWHOPE_Q / 2; + m = r >> 15; + return (r + m) ^ m; +} + +/************************************************* +* Name: poly_frombytes +* +* Description: De-serialization of a polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frombytes(poly *r, const unsigned char *a) { + int i; + for (i = 0; i < NEWHOPE_N / 4; i++) { + r->coeffs[4 * i + 0] = a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); + r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) | (((uint16_t)a[7 * i + 2]) << 2) | (((uint16_t)a[7 * i + 3] & 0x0f) << 10); + r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) | (((uint16_t)a[7 * i + 4]) << 4) | (((uint16_t)a[7 * i + 5] & 0x03) << 12); + r->coeffs[4 * i + 3] = (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6); + } +} + +/************************************************* +* Name: poly_tobytes +* +* Description: Serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tobytes(unsigned char *r, const poly *p) { + int i; + uint16_t t0, t1, t2, t3; + for (i = 0; i < NEWHOPE_N / 4; i++) { + t0 = coeff_freeze(p->coeffs[4 * i + 0]); + t1 = coeff_freeze(p->coeffs[4 * i + 1]); + t2 = coeff_freeze(p->coeffs[4 * i + 2]); + t3 = coeff_freeze(p->coeffs[4 * i + 3]); + + r[7 * i + 0] = t0 & 0xff; + r[7 * i + 1] = (unsigned char) ((t0 >> 8) | (t1 << 6)); + r[7 * i + 2] = (unsigned char) ((t1 >> 2)); + r[7 * i + 3] = (unsigned char) ((t1 >> 10) | (t2 << 4)); + r[7 * i + 4] = (unsigned char) ((t2 >> 4)); + r[7 * i + 5] = (unsigned char) ((t2 >> 12) | (t3 << 2)); + r[7 * i + 6] = (unsigned char) ((t3 >> 6)); + } +} + +/************************************************* +* Name: poly_compress +* +* Description: Compression and subsequent serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_compress(unsigned char *r, const poly *p) { + unsigned int i, j, k = 0; + + uint32_t t[8]; + + for (i = 0; i < NEWHOPE_N; i += 8) { + for (j = 0; j < 8; j++) { + t[j] = coeff_freeze(p->coeffs[i + j]); + t[j] = (((t[j] << 3) + NEWHOPE_Q / 2) / NEWHOPE_Q) & 0x7; + } + + r[k] = (unsigned char) (t[0] | (t[1] << 3) | (t[2] << 6)); + r[k + 1] = (unsigned char) ((t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7)); + r[k + 2] = (unsigned char) ((t[5] >> 1) | (t[6] << 2) | (t[7] << 5)); + k += 3; + } +} + +/************************************************* +* Name: poly_decompress +* +* Description: De-serialization and subsequent decompression of a polynomial; +* approximate inverse of poly_compress +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_decompress(poly *r, const unsigned char *a) { + unsigned int i, j; + for (i = 0; i < NEWHOPE_N; i += 8) { + r->coeffs[i + 0] = a[0] & 7; + r->coeffs[i + 1] = (a[0] >> 3) & 7; + r->coeffs[i + 2] = (a[0] >> 6) | ((a[1] << 2) & 4); + r->coeffs[i + 3] = (a[1] >> 1) & 7; + r->coeffs[i + 4] = (a[1] >> 4) & 7; + r->coeffs[i + 5] = (a[1] >> 7) | ((a[2] << 1) & 6); + r->coeffs[i + 6] = (a[2] >> 2) & 7; + r->coeffs[i + 7] = (a[2] >> 5); + a += 3; + for (j = 0; j < 8; j++) { + r->coeffs[i + j] = ((uint32_t)r->coeffs[i + j] * NEWHOPE_Q + 4) >> 3; + } + } +} + +/************************************************* +* Name: poly_frommsg +* +* Description: Convert 32-byte message to polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *msg: pointer to input message +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { + unsigned int i, j, mask; + for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (j = 0; j < 8; j++) { + mask = -((msg[i] >> j) & 1); + r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 256] = mask & (NEWHOPE_Q / 2); + } + } +} + +/************************************************* +* Name: poly_tomsg +* +* Description: Convert polynomial to 32-byte message +* +* Arguments: - unsigned char *msg: pointer to output message +* - const poly *x: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { + unsigned int i; + uint16_t t; + + for (i = 0; i < 32; i++) { + msg[i] = 0; + } + + for (i = 0; i < 256; i++) { + t = flipabs(x->coeffs[i + 0]); + t += flipabs(x->coeffs[i + 256]); + t = ((t - NEWHOPE_Q / 2)); + + t >>= 15; + msg[i >> 3] |= t << (i & 7); + } +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample a polynomial deterministically from a seed, +* with output polynomial looking uniformly random +* +* Arguments: - poly *a: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { + unsigned int ctr = 0; + uint16_t val; + uint64_t state[25]; + uint8_t buf[SHAKE128_RATE]; + uint8_t extseed[NEWHOPE_SYMBYTES + 1]; + int i, j; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ + ctr = 0; + extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ + shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + while (ctr < 64) { /* Very unlikely to run more than once */ + shake128_squeezeblocks(buf, 1, state); + for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { + val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); + if (val < 5 * NEWHOPE_Q) { + a->coeffs[i * 64 + ctr] = val; + ctr++; + } + } + } + } +} + +/************************************************* +* Name: hw +* +* Description: Compute the Hamming weight of a byte +* +* Arguments: - unsigned char a: input byte +**************************************************/ +static unsigned char hw(unsigned char a) { + unsigned char i, r = 0; + for (i = 0; i < 8; i++) { + r += (a >> i) & 1; + } + return r; +} + +/************************************************* +* Name: poly_sample +* +* Description: Sample a polynomial deterministically from a seed and a nonce, +* with output polynomial close to centered binomial distribution +* with parameter k=8 +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +* - unsigned char nonce: one-byte input nonce +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { + unsigned char buf[128], a, b; +// uint32_t t, d, a, b, c; + int i, j; + + unsigned char extseed[NEWHOPE_SYMBYTES + 2]; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + extseed[NEWHOPE_SYMBYTES] = nonce; + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* Generate noise in blocks of 64 coefficients */ + extseed[NEWHOPE_SYMBYTES + 1] = (unsigned char) i; + shake256(buf, 128, extseed, NEWHOPE_SYMBYTES + 2); + for (j = 0; j < 64; j++) { + a = buf[2 * j]; + b = buf[2 * j + 1]; + r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); + /* + t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); + d = 0; + for(k=0;k<8;k++) + d += (t >> k) & 0x01010101; + a = d & 0xff; + b = ((d >> 8) & 0xff); + c = ((d >> 16) & 0xff); + d >>= 24; + r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; + r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; + */ + } + } +} + +/************************************************* +* Name: poly_pointwise +* +* Description: Multiply two polynomials pointwise (i.e., coefficient-wise). +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b) { + int i; + uint16_t t; + for (i = 0; i < NEWHOPE_N; i++) { + t = PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce(3186 * b->coeffs[i]); /* t is now in Montgomery domain */ + r->coeffs[i] = PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ + } +} + +/************************************************* +* Name: poly_add +* +* Description: Add two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_add(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + 3 * NEWHOPE_Q - b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_ntt +* +* Description: Forward NTT transform of a polynomial in place +* Input is assumed to have coefficients in bitreversed order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_ntt(poly *r) { + PQCLEAN_NEWHOPE512CCA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_bitrev_montgomery); + PQCLEAN_NEWHOPE512CCA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_bitrev_montgomery); +} + +/************************************************* +* Name: poly_invntt +* +* Description: Inverse NTT transform of a polynomial in place +* Input is assumed to have coefficients in normal order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_invntt(poly *r) { + PQCLEAN_NEWHOPE512CCA_CLEAN_bitrev_vector(r->coeffs); + PQCLEAN_NEWHOPE512CCA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE512CCA_CLEAN_omegas_inv_bitrev_montgomery); + PQCLEAN_NEWHOPE512CCA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_inv_montgomery); +} + diff --git a/crypto_kem/newhope512cca/clean/poly.h b/crypto_kem/newhope512cca/clean/poly.h new file mode 100644 index 00000000..cdf9e98f --- /dev/null +++ b/crypto_kem/newhope512cca/clean/poly.h @@ -0,0 +1,32 @@ +#ifndef POLY_H +#define POLY_H + +#include "params.h" +#include + +/* + * Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial + * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] + */ +typedef struct { + uint16_t coeffs[NEWHOPE_N]; +} poly; + +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_add(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_ntt(poly *r); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_invntt(poly *r); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frombytes(poly *r, const unsigned char *a); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tobytes(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_compress(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_decompress(poly *r, const unsigned char *a); + +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x); +void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b); + +#endif diff --git a/crypto_kem/newhope512cca/clean/precomp.c b/crypto_kem/newhope512cca/clean/precomp.c new file mode 100644 index 00000000..20d5a9e1 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/precomp.c @@ -0,0 +1,179 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" + +/* Precomputed NTT contants generated by Pari/GP script as follows: + * + * For n = 512: + * + * brv = [0,256,128,384,64,320,192,448,32,288,160,416,96,352,224,480,16,272,144,400,80,336,208,464,48,304,176,432,112,368,240,496,8, + * 264,136,392,72,328,200,456,40,296,168,424,104,360,232,488,24,280,152,408,88,344,216,472,56,312,184,440,120,376,248,504,4, + * 260,132,388,68,324,196,452,36,292,164,420,100,356,228,484,20,276,148,404,84,340,212,468,52,308,180,436,116,372,244,500,12, + * 268,140,396,76,332,204,460,44,300,172,428,108,364,236,492,28,284,156,412,92,348,220,476,60,316,188,444,124,380,252,508,2, + * 258,130,386,66,322,194,450,34,290,162,418,98,354,226,482,18,274,146,402,82,338,210,466,50,306,178,434,114,370,242,498,10, + * 266,138,394,74,330,202,458,42,298,170,426,106,362,234,490,26,282,154,410,90,346,218,474,58,314,186,442,122,378,250,506,6, + * 262,134,390,70,326,198,454,38,294,166,422,102,358,230,486,22,278,150,406,86,342,214,470,54,310,182,438,118,374,246,502,14, + * 270,142,398,78,334,206,462,46,302,174,430,110,366,238,494,30,286,158,414,94,350,222,478,62,318,190,446,126,382,254,510,1, + * 257,129,385,65,321,193,449,33,289,161,417,97,353,225,481,17,273,145,401,81,337,209,465,49,305,177,433,113,369,241,497,9, + * 265,137,393,73,329,201,457,41,297,169,425,105,361,233,489,25,281,153,409,89,345,217,473,57,313,185,441,121,377,249,505,5, + * 261,133,389,69,325,197,453,37,293,165,421,101,357,229,485,21,277,149,405,85,341,213,469,53,309,181,437,117,373,245,501,13, + * 269,141,397,77,333,205,461,45,301,173,429,109,365,237,493,29,285,157,413,93,349,221,477,61,317,189,445,125,381,253,509,3, + * 259,131,387,67,323,195,451,35,291,163,419,99,355,227,483,19,275,147,403,83,339,211,467,51,307,179,435,115,371,243,499,11, + * 267,139,395,75,331,203,459,43,299,171,427,107,363,235,491,27,283,155,411,91,347,219,475,59,315,187,443,123,379,251,507,7, + * 263,135,391,71,327,199,455,39,295,167,423,103,359,231,487,23,279,151,407,87,343,215,471,55,311,183,439,119,375,247,503,15, + * 271,143,399,79,335,207,463,47,303,175,431,111,367,239,495,31,287,159,415,95,351,223,479,63,319,191,447,127,383,255,511] + * n = 512; q = 12289; mont=2^18 + * g = Mod(10968, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) + * + * + * For n = 1024: + * + * brv = [0,512,256,768,128,640,384,896,64,576,320,832,192,704,448,960,32,544,288,800,160,672,416,928,96,608,352,864,224,736,480,992, \ + * 16,528,272,784,144,656,400,912,80,592,336,848,208,720,464,976,48,560,304,816,176,688,432,944,112,624,368,880,240,752,496,1008, \ + * 8,520,264,776,136,648,392,904,72,584,328,840,200,712,456,968,40,552,296,808,168,680,424,936,104,616,360,872,232,744,488,1000, \ + * 24,536,280,792,152,664,408,920,88,600,344,856,216,728,472,984,56,568,312,824,184,696,440,952,120,632,376,888,248,760,504,1016, \ + * 4,516,260,772,132,644,388,900,68,580,324,836,196,708,452,964,36,548,292,804,164,676,420,932,100,612,356,868,228,740,484,996, \ + * 20,532,276,788,148,660,404,916,84,596,340,852,212,724,468,980,52,564,308,820,180,692,436,948,116,628,372,884,244,756,500,1012, \ + * 12,524,268,780,140,652,396,908,76,588,332,844,204,716,460,972,44,556,300,812,172,684,428,940,108,620,364,876,236,748,492,1004, \ + * 28,540,284,796,156,668,412,924,92,604,348,860,220,732,476,988,60,572,316,828,188,700,444,956,124,636,380,892,252,764,508,1020, \ + * 2,514,258,770,130,642,386,898,66,578,322,834,194,706,450,962,34,546,290,802,162,674,418,930,98,610,354,866,226,738,482,994, \ + * 18,530,274,786,146,658,402,914,82,594,338,850,210,722,466,978,50,562,306,818,178,690,434,946,114,626,370,882,242,754,498,1010, \ + * 10,522,266,778,138,650,394,906,74,586,330,842,202,714,458,970,42,554,298,810,170,682,426,938,106,618,362,874,234,746,490,1002, \ + * 26,538,282,794,154,666,410,922,90,602,346,858,218,730,474,986,58,570,314,826,186,698,442,954,122,634,378,890,250,762,506,1018, \ + * 6,518,262,774,134,646,390,902,70,582,326,838,198,710,454,966,38,550,294,806,166,678,422,934,102,614,358,870,230,742,486,998, \ + * 22,534,278,790,150,662,406,918,86,598,342,854,214,726,470,982,54,566,310,822,182,694,438,950,118,630,374,886,246,758,502,1014, \ + * 14,526,270,782,142,654,398,910,78,590,334,846,206,718,462,974,46,558,302,814,174,686,430,942,110,622,366,878,238,750,494,1006, \ + * 30,542,286,798,158,670,414,926,94,606,350,862,222,734,478,990,62,574,318,830,190,702,446,958,126,638,382,894,254,766,510,1022, \ + * 1,513,257,769,129,641,385,897,65,577,321,833,193,705,449,961,33,545,289,801,161,673,417,929,97,609,353,865,225,737,481,993, \ + * 17,529,273,785,145,657,401,913,81,593,337,849,209,721,465,977,49,561,305,817,177,689,433,945,113,625,369,881,241,753,497,1009, \ + * 9,521,265,777,137,649,393,905,73,585,329,841,201,713,457,969,41,553,297,809,169,681,425,937,105,617,361,873,233,745,489,1001, \ + * 25,537,281,793,153,665,409,921,89,601,345,857,217,729,473,985,57,569,313,825,185,697,441,953,121,633,377,889,249,761,505,1017, \ + * 5,517,261,773,133,645,389,901,69,581,325,837,197,709,453,965,37,549,293,805,165,677,421,933,101,613,357,869,229,741,485,997, \ + * 21,533,277,789,149,661,405,917,85,597,341,853,213,725,469,981,53,565,309,821,181,693,437,949,117,629,373,885,245,757,501,1013, \ + * 13,525,269,781,141,653,397,909,77,589,333,845,205,717,461,973,45,557,301,813,173,685,429,941,109,621,365,877,237,749,493,1005, \ + * 29,541,285,797,157,669,413,925,93,605,349,861,221,733,477,989,61,573,317,829,189,701,445,957,125,637,381,893,253,765,509,1021, \ + * 3,515,259,771,131,643,387,899,67,579,323,835,195,707,451,963,35,547,291,803,163,675,419,931,99,611,355,867,227,739,483,995, \ + * 19,531,275,787,147,659,403,915,83,595,339,851,211,723,467,979,51,563,307,819,179,691,435,947,115,627,371,883,243,755,499,1011, \ + * 11,523,267,779,139,651,395,907,75,587,331,843,203,715,459,971,43,555,299,811,171,683,427,939,107,619,363,875,235,747,491,1003, \ + * 27,539,283,795,155,667,411,923,91,603,347,859,219,731,475,987,59,571,315,827,187,699,443,955,123,635,379,891,251,763,507,1019, \ + * 7,519,263,775,135,647,391,903,71,583,327,839,199,711,455,967,39,551,295,807,167,679,423,935,103,615,359,871,231,743,487,999, \ + * 23,535,279,791,151,663,407,919,87,599,343,855,215,727,471,983,55,567,311,823,183,695,439,951,119,631,375,887,247,759,503,1015, \ + * 15,527,271,783,143,655,399,911,79,591,335,847,207,719,463,975,47,559,303,815,175,687,431,943,111,623,367,879,239,751,495,1007, \ + * 31,543,287,799,159,671,415,927,95,607,351,863,223,735,479,991,63,575,319,831,191,703,447,959,127,639,383,895,255,767,511,1023] + * + * n = 1024; q = 12289; mont=2^18 + * g = Mod(7, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) +*/ + +/************************************************************ +* Name: omegas_inv_bitrev_montgomery +* +* Description: Contains inverses of powers of nth root of unity +* in Montgomery domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_omegas_inv_bitrev_montgomery[NEWHOPE_N / 2] = { + 4075, 6974, 4916, 4324, 7210, 3262, 2169, 11767, 3514, 1041, 5925, 11271, 6715, 10316, 11011, 9945, + 1190, 9606, 3818, 6118, 1050, 7753, 8429, 6844, 4449, 6833, 147, 3789, 7540, 6752, 4467, 4789, + 10367, 3879, 2033, 3998, 11316, 1254, 6854, 1359, 3988, 468, 11907, 11973, 8579, 6196, 5446, 6950, + 1987, 10587, 654, 3565, 3199, 12233, 7083, 6760, 6427, 6153, 3643, 6874, 4948, 6152, 11889, 1728, + 7280, 10333, 6008, 11404, 3532, 11286, 241, 12231, 11314, 4212, 8851, 9445, 3477, 6608, 12147, 1105, + 5594, 9260, 5886, 7507, 4213, 11785, 2302, 11684, 8687, 6221, 8209, 421, 7665, 6212, 8689, 3263, + 10710, 431, 9784, 5906, 9450, 8332, 2127, 151, 3174, 52, 1323, 9523, 6415, 11612, 3336, 6234, + 7048, 9369, 4169, 3127, 11279, 6821, 787, 3482, 3445, 4780, 7232, 7591, 7377, 2049, 1321, 192, + 9551, 6421, 5735, 9634, 10596, 9280, 723, 12115, 9364, 347, 1975, 3757, 10431, 7535, 11863, 3315, + 4493, 3202, 5369, 10232, 350, 10777, 6906, 10474, 1483, 6374, 49, 1263, 10706, 6347, 1489, 9789, + 7552, 1293, 4774, 5429, 3772, 418, 6381, 453, 9522, 156, 3969, 3991, 6956, 10258, 10008, 6413, + 8855, 3529, 218, 9381, 9259, 8174, 2361, 10446, 10335, 2051, 9407, 10484, 9842, 6147, 3963, 576, + 6523, 11637, 6099, 11994, 9370, 3762, 8273, 4077, 11964, 1404, 11143, 11341, 1159, 6299, 4049, 8561, + 5961, 7183, 1962, 10695, 9597, 12121, 8960, 7991, 6992, 6170, 10929, 8333, 2555, 6167, 11089, 5184, + 3570, 4240, 11454, 6065, 3150, 10970, 709, 8243, 1058, 8210, 441, 11367, 10331, 7967, 1112, 2078, + 10542, 3123, 5486, 9235, 7856, 6370, 8455, 5257, 9341, 9786, 6507, 10723, 2459, 683, 8633, 64, +}; + +/************************************************************ +* Name: gammas_bitrev_montgomery +* +* Description: Contains powers of nth root of -1 in Montgomery +* domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_bitrev_montgomery[NEWHOPE_N] = { + 4075, 5315, 7965, 7373, 522, 10120, 9027, 5079, 2344, 1278, 1973, 5574, 1018, 6364, 11248, 8775, + 7500, 7822, 5537, 4749, 8500, 12142, 5456, 7840, 5445, 3860, 4536, 11239, 6171, 8471, 2683, 11099, + 10561, 400, 6137, 7341, 5415, 8646, 6136, 5862, 5529, 5206, 56, 9090, 8724, 11635, 1702, 10302, + 5339, 6843, 6093, 3710, 316, 382, 11821, 8301, 10930, 5435, 11035, 973, 8291, 10256, 8410, 1922, + 12097, 10968, 10240, 4912, 4698, 5057, 7509, 8844, 8807, 11502, 5468, 1010, 9162, 8120, 2920, 5241, + 6055, 8953, 677, 5874, 2766, 10966, 12237, 9115, 12138, 10162, 3957, 2839, 6383, 2505, 11858, 1579, + 9026, 3600, 6077, 4624, 11868, 4080, 6068, 3602, 605, 9987, 504, 8076, 4782, 6403, 3029, 6695, + 11184, 142, 5681, 8812, 2844, 3438, 8077, 975, 58, 12048, 1003, 8757, 885, 6281, 1956, 5009, + 12225, 3656, 11606, 9830, 1566, 5782, 2503, 2948, 7032, 3834, 5919, 4433, 3054, 6803, 9166, 1747, + 10211, 11177, 4322, 1958, 922, 11848, 4079, 11231, 4046, 11580, 1319, 9139, 6224, 835, 8049, 8719, + 7105, 1200, 6122, 9734, 3956, 1360, 6119, 5297, 4298, 3329, 168, 2692, 1594, 10327, 5106, 6328, + 3728, 8240, 5990, 11130, 948, 1146, 10885, 325, 8212, 4016, 8527, 2919, 295, 6190, 652, 5766, + 11713, 8326, 6142, 2447, 1805, 2882, 10238, 1954, 1843, 9928, 4115, 3030, 2908, 12071, 8760, 3434, + 5876, 2281, 2031, 5333, 8298, 8320, 12133, 2767, 11836, 5908, 11871, 8517, 6860, 7515, 10996, 4737, + 2500, 10800, 5942, 1583, 11026, 12240, 5915, 10806, 1815, 5383, 1512, 11939, 2057, 6920, 9087, 7796, + 8974, 426, 4754, 1858, 8532, 10314, 11942, 2925, 174, 11566, 3009, 1693, 2655, 6554, 5868, 2738, + 11796, 8193, 9908, 5444, 10911, 1912, 7952, 435, 404, 7644, 11224, 10146, 7012, 11121, 11082, 9041, + 9723, 2187, 9867, 6250, 3646, 9852, 6267, 2987, 8509, 875, 4976, 10682, 8005, 5088, 7278, 11287, + 9223, 27, 3763, 10849, 11272, 7404, 5084, 10657, 8146, 4714, 12047, 10752, 2678, 3704, 545, 7270, + 1067, 5101, 442, 2401, 390, 11516, 3778, 8456, 1045, 9430, 9808, 5012, 9377, 6591, 11935, 4861, + 7852, 3, 3149, 12129, 12176, 4919, 10123, 3915, 3636, 7351, 2704, 5291, 1663, 1777, 1426, 7635, + 1484, 7394, 2780, 7094, 8236, 2645, 7247, 2305, 2847, 7875, 7917, 10115, 10600, 8925, 4057, 3271, + 9273, 243, 9289, 11618, 3136, 5191, 8889, 9890, 11869, 5559, 10111, 10745, 11813, 8758, 4905, 3985, + 9603, 9042, 3978, 9320, 3510, 5332, 9424, 2370, 9405, 11136, 2249, 8241, 10659, 10163, 9103, 6882, + 10810, 1, 5146, 4043, 8155, 5736, 11567, 1305, 1212, 10643, 9094, 5860, 8747, 8785, 8668, 2545, + 4591, 6561, 5023, 6461, 10938, 4978, 6512, 8961, 949, 2625, 2639, 7468, 11726, 2975, 9545, 9283, + 3091, 81, 11289, 7969, 9238, 9923, 2963, 7393, 12149, 1853, 11563, 7678, 8034, 11112, 1635, 9521, + 3201, 3014, 1326, 7203, 1170, 9970, 11334, 790, 3135, 3712, 4846, 2747, 3553, 7484, 11227, 2294, + 11267, 9, 9447, 11809, 11950, 2468, 5791, 11745, 10908, 9764, 8112, 3584, 4989, 5331, 4278, 10616, + 4452, 9893, 8340, 8993, 130, 7935, 9452, 6915, 8541, 11336, 11462, 5767, 7222, 2197, 12171, 9813, + 3241, 729, 3289, 10276, 9408, 3284, 2089, 5092, 11029, 4388, 5755, 7657, 10861, 1696, 2426, 11955, + 4231, 2548, 11934, 3382, 10530, 3707, 3694, 7110, 3637, 8830, 6747, 145, 7399, 5911, 2731, 8357, +}; + +/************************************************************ +* Name: gammas_inv_montgomery +* +* Description: Contains inverses of powers of nth root of -1 +* divided by n in Montgomery domain with R=2^18 +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_gammas_inv_montgomery[NEWHOPE_N] = { + 512, 3944, 4267, 5411, 9615, 5900, 3205, 6063, 9261, 2021, 3087, 4770, 1029, 1590, 343, 530, + 8307, 4273, 2769, 9617, 923, 7302, 4404, 2434, 1468, 9004, 8682, 11194, 2894, 11924, 5061, 8071, + 1687, 10883, 8755, 7724, 11111, 6671, 7800, 6320, 2600, 6203, 4963, 6164, 9847, 6151, 11475, 10243, + 3825, 11607, 1275, 3869, 425, 5386, 4238, 9988, 5509, 11522, 10029, 7937, 3343, 6742, 9307, 10440, + 11295, 3480, 3765, 1160, 1255, 4483, 8611, 9687, 11063, 3229, 7784, 9269, 6691, 7186, 10423, 10588, + 11667, 11722, 3889, 12100, 9489, 12226, 3163, 12268, 9247, 12282, 11275, 4094, 11951, 5461, 8080, 10013, + 10886, 7434, 7725, 2478, 2575, 826, 9051, 8468, 3017, 6919, 5102, 10499, 5797, 7596, 10125, 2532, + 3375, 844, 1125, 8474, 375, 6921, 125, 2307, 4138, 769, 9572, 8449, 7287, 11009, 2429, 7766, + 4906, 6685, 9828, 10421, 3276, 7570, 1092, 10716, 364, 3572, 8314, 5287, 10964, 9955, 7751, 11511, + 6680, 3837, 6323, 1279, 6204, 8619, 2068, 2873, 8882, 5054, 7057, 5781, 10545, 1927, 3515, 8835, + 5268, 2945, 1756, 5078, 8778, 5789, 2926, 6026, 9168, 6105, 3056, 2035, 5115, 8871, 1705, 2957, + 8761, 5082, 11113, 1694, 11897, 4661, 8062, 5650, 10880, 10076, 7723, 7455, 10767, 2485, 3589, 9021, + 9389, 3007, 7226, 9195, 6505, 3065, 10361, 5118, 7550, 1706, 6613, 4665, 10397, 1555, 7562, 8711, + 6617, 7000, 6302, 10526, 6197, 7605, 6162, 2535, 2054, 845, 4781, 4378, 5690, 9652, 5993, 11410, + 6094, 11996, 10224, 8095, 3408, 10891, 1136, 11823, 4475, 3941, 5588, 5410, 5959, 9996, 10179, 3332, + 3393, 5207, 1131, 5832, 377, 1944, 4222, 648, 9600, 216, 3200, 72, 5163, 24, 1721, 8, + 4670, 4099, 5653, 9559, 10077, 11379, 3359, 3793, 5216, 9457, 5835, 11345, 1945, 7878, 8841, 2626, + 2947, 9068, 9175, 7119, 11251, 2373, 11943, 791, 3981, 4360, 1327, 9646, 8635, 11408, 11071, 7899, + 11883, 2633, 3961, 4974, 9513, 1658, 3171, 4649, 1057, 5646, 8545, 1882, 11041, 8820, 11873, 2940, + 8054, 980, 6781, 4423, 10453, 9667, 11677, 11415, 12085, 3805, 12221, 9461, 8170, 7250, 10916, 6513, + 7735, 2171, 10771, 4820, 11783, 5703, 8024, 1901, 6771, 4730, 2257, 5673, 8945, 1891, 7078, 8823, + 10552, 2941, 11710, 9173, 12096, 7154, 4032, 6481, 1344, 10353, 448, 3451, 8342, 9343, 6877, 11307, + 10485, 3769, 3495, 9449, 1165, 7246, 8581, 10608, 11053, 3536, 11877, 5275, 3959, 9951, 5416, 3317, + 9998, 5202, 7429, 1734, 10669, 578, 11749, 4289, 12109, 5526, 12229, 1842, 12269, 614, 8186, 4301, + 6825, 5530, 2275, 10036, 8951, 11538, 7080, 3846, 2360, 1282, 4883, 8620, 5724, 11066, 1908, 7785, + 636, 2595, 212, 865, 4167, 8481, 1389, 2827, 463, 9135, 8347, 3045, 10975, 1015, 11851, 8531, + 12143, 6940, 8144, 10506, 6811, 3502, 10463, 9360, 7584, 3120, 2528, 1040, 4939, 4443, 9839, 1481, + 7376, 4590, 6555, 1530, 2185, 510, 8921, 170, 7070, 4153, 6453, 9577, 2151, 11385, 717, 3795, + 239, 1265, 4176, 4518, 1392, 1506, 464, 502, 4251, 8360, 1417, 6883, 8665, 10487, 11081, 7592, + 7790, 6627, 6693, 2209, 2231, 8929, 4840, 11169, 9806, 3723, 7365, 1241, 2455, 4510, 9011, 9696, + 7100, 3232, 6463, 9270, 10347, 3090, 3449, 1030, 5246, 8536, 5845, 11038, 10141, 11872, 11573, 12150, + 7954, 4050, 10844, 1350, 7711, 450, 10763, 150, 7684, 50, 10754, 4113, 7681, 1371, 10753, 457, +}; diff --git a/crypto_kem/newhope512cca/clean/reduce.c b/crypto_kem/newhope512cca/clean/reduce.c new file mode 100644 index 00000000..cdaffba7 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/reduce.c @@ -0,0 +1,26 @@ +#include "reduce.h" +#include "params.h" + +static const uint32_t qinv = 12287; // -inverse_mod(p,2^18) +static const uint32_t rlog = 18; + +/************************************************* +* Name: verify +* +* Description: Montgomery reduction; given a 32-bit integer a, computes +* 16-bit integer congruent to a * R^-1 mod q, +* where R=2^18 (see value of rlog) +* +* Arguments: - uint32_t a: input unsigned integer to be reduced; has to be in {0,...,1073491968} +* +* Returns: unsigned integer in {0,...,2^14-1} congruent to a * R^-1 modulo q. +**************************************************/ +uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce(uint32_t a) { + uint32_t u; + + u = (a * qinv); + u &= ((1 << rlog) - 1); + u *= NEWHOPE_Q; + a = a + u; + return a >> 18; +} diff --git a/crypto_kem/newhope512cca/clean/reduce.h b/crypto_kem/newhope512cca/clean/reduce.h new file mode 100644 index 00000000..7e98ce2e --- /dev/null +++ b/crypto_kem/newhope512cca/clean/reduce.h @@ -0,0 +1,8 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include + +uint16_t PQCLEAN_NEWHOPE512CCA_CLEAN_montgomery_reduce(uint32_t a); + +#endif diff --git a/crypto_kem/newhope512cca/clean/verify.c b/crypto_kem/newhope512cca/clean/verify.c new file mode 100644 index 00000000..553c0e50 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/verify.c @@ -0,0 +1,49 @@ +#include "verify.h" +#include +#include + +/************************************************* +* Name: verify +* +* Description: Compare two arrays for equality in constant time. +* +* Arguments: const unsigned char *a: pointer to first byte array +* const unsigned char *b: pointer to second byte array +* size_t len: length of the byte arrays +* +* Returns 0 if the byte arrays are equal, 1 otherwise +**************************************************/ +int PQCLEAN_NEWHOPE512CCA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { + uint64_t r; + size_t i; + r = 0; + + for (i = 0; i < len; i++) { + r |= a[i] ^ b[i]; + } + + r = (-(int64_t)r) >> 63; + return (int)r; +} + +/************************************************* +* Name: cmov +* +* Description: Copy len bytes from x to r if b is 1; +* don't modify x if b is 0. Requires b to be in {0,1}; +* assumes two's complement representation of negative integers. +* Runs in constant time. +* +* Arguments: unsigned char *r: pointer to output byte array +* const unsigned char *x: pointer to input byte array +* size_t len: Amount of bytes to be copied +* unsigned char b: Condition bit; has to be in {0,1} +**************************************************/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/newhope512cca/clean/verify.h b/crypto_kem/newhope512cca/clean/verify.h new file mode 100644 index 00000000..5db88072 --- /dev/null +++ b/crypto_kem/newhope512cca/clean/verify.h @@ -0,0 +1,12 @@ +#ifndef VERIFY_H +#define VERIFY_H + +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +int PQCLEAN_NEWHOPE512CCA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_NEWHOPE512CCA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); + +#endif From 12fafb1bf044e98b07c1d8179691213b7401ca6d Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 8 May 2019 17:07:57 +0200 Subject: [PATCH 05/35] rename newhope1024ccakem -> newhope1024cca --- .../META.yml | 2 +- .../clean/LICENSE | 0 .../clean/Makefile | 2 +- .../clean/Makefile.Microsoft_nmake | 2 +- crypto_kem/newhope1024cca/clean/api.h | 15 ++++ .../clean/cpapke.c | 68 +++++++++---------- .../clean/cpapke.h | 6 +- .../clean/kem.c | 18 ++--- .../clean/ntt.c | 12 ++-- crypto_kem/newhope1024cca/clean/ntt.h | 14 ++++ .../clean/params.h | 4 +- .../clean/poly.c | 40 +++++------ crypto_kem/newhope1024cca/clean/poly.h | 32 +++++++++ .../clean/precomp.c | 6 +- .../clean/reduce.c | 2 +- crypto_kem/newhope1024cca/clean/reduce.h | 8 +++ .../clean/verify.c | 4 +- crypto_kem/newhope1024cca/clean/verify.h | 12 ++++ crypto_kem/newhope1024ccakem/clean/api.h | 15 ---- crypto_kem/newhope1024ccakem/clean/ntt.h | 14 ---- crypto_kem/newhope1024ccakem/clean/poly.h | 32 --------- crypto_kem/newhope1024ccakem/clean/reduce.h | 8 --- crypto_kem/newhope1024ccakem/clean/verify.h | 12 ---- 23 files changed, 164 insertions(+), 164 deletions(-) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/META.yml (95%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/LICENSE (100%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/Makefile (93%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/Makefile.Microsoft_nmake (91%) create mode 100644 crypto_kem/newhope1024cca/clean/api.h rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/cpapke.c (70%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/cpapke.h (54%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/kem.c (79%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/ntt.c (92%) create mode 100644 crypto_kem/newhope1024cca/clean/ntt.h rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/params.h (91%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/poly.c (85%) create mode 100644 crypto_kem/newhope1024cca/clean/poly.h rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/precomp.c (99%) rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/reduce.c (91%) create mode 100644 crypto_kem/newhope1024cca/clean/reduce.h rename crypto_kem/{newhope1024ccakem => newhope1024cca}/clean/verify.c (86%) create mode 100644 crypto_kem/newhope1024cca/clean/verify.h delete mode 100644 crypto_kem/newhope1024ccakem/clean/api.h delete mode 100644 crypto_kem/newhope1024ccakem/clean/ntt.h delete mode 100644 crypto_kem/newhope1024ccakem/clean/poly.h delete mode 100644 crypto_kem/newhope1024ccakem/clean/reduce.h delete mode 100644 crypto_kem/newhope1024ccakem/clean/verify.h diff --git a/crypto_kem/newhope1024ccakem/META.yml b/crypto_kem/newhope1024cca/META.yml similarity index 95% rename from crypto_kem/newhope1024ccakem/META.yml rename to crypto_kem/newhope1024cca/META.yml index d8c4662c..39a20392 100644 --- a/crypto_kem/newhope1024ccakem/META.yml +++ b/crypto_kem/newhope1024cca/META.yml @@ -1,4 +1,4 @@ -name: NewHope1024CCAKEM +name: NewHope1024CCA type: kem claimed-nist-level: 5 length-public-key: 1824 diff --git a/crypto_kem/newhope1024ccakem/clean/LICENSE b/crypto_kem/newhope1024cca/clean/LICENSE similarity index 100% rename from crypto_kem/newhope1024ccakem/clean/LICENSE rename to crypto_kem/newhope1024cca/clean/LICENSE diff --git a/crypto_kem/newhope1024ccakem/clean/Makefile b/crypto_kem/newhope1024cca/clean/Makefile similarity index 93% rename from crypto_kem/newhope1024ccakem/clean/Makefile rename to crypto_kem/newhope1024cca/clean/Makefile index e63127fb..933c6e2d 100644 --- a/crypto_kem/newhope1024ccakem/clean/Makefile +++ b/crypto_kem/newhope1024cca/clean/Makefile @@ -1,6 +1,6 @@ # This Makefile can be used with GNU Make or BSD Make -LIB=libnewhope1024ccakem_clean.a +LIB=libnewhope1024cca_clean.a HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o diff --git a/crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake b/crypto_kem/newhope1024cca/clean/Makefile.Microsoft_nmake similarity index 91% rename from crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake rename to crypto_kem/newhope1024cca/clean/Makefile.Microsoft_nmake index 7c0fc463..f6dca8d7 100644 --- a/crypto_kem/newhope1024ccakem/clean/Makefile.Microsoft_nmake +++ b/crypto_kem/newhope1024cca/clean/Makefile.Microsoft_nmake @@ -1,7 +1,7 @@ # This Makefile can be used with Microsoft Visual Studio's nmake using the command: # nmake /f Makefile.Microsoft_nmake -LIBRARY=libnewhope1024ccakem_clean.lib +LIBRARY=libnewhope1024cca_clean.lib OBJECTS=cpapke.obj kem.obj ntt.obj poly.obj precomp.obj reduce.obj verify.obj CFLAGS=/nologo /I ..\..\..\common /W4 /WX diff --git a/crypto_kem/newhope1024cca/clean/api.h b/crypto_kem/newhope1024cca/clean/api.h new file mode 100644 index 00000000..62139de0 --- /dev/null +++ b/crypto_kem/newhope1024cca/clean/api.h @@ -0,0 +1,15 @@ +#ifndef PQCLEAN_NEWHOPE1024CCA_CLEAN_API_H +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_API_H + + +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_CRYPTO_SECRETKEYBYTES 3680 +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_CRYPTO_PUBLICKEYBYTES 1824 +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_CRYPTO_CIPHERTEXTBYTES 2208 +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_CRYPTO_BYTES 32 +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_CRYPTO_ALGNAME "NewHope1024-CCAKEM" + +int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); +int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); +int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/cpapke.c b/crypto_kem/newhope1024cca/clean/cpapke.c similarity index 70% rename from crypto_kem/newhope1024ccakem/clean/cpapke.c rename to crypto_kem/newhope1024cca/clean/cpapke.c index 4bbd0b3a..09986223 100644 --- a/crypto_kem/newhope1024ccakem/clean/cpapke.c +++ b/crypto_kem/newhope1024cca/clean/cpapke.c @@ -18,7 +18,7 @@ **************************************************/ static void encode_pk(unsigned char *r, const poly *pk, const unsigned char *seed) { int i; - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(r, pk); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tobytes(r, pk); for (i = 0; i < NEWHOPE_SYMBYTES; i++) { r[NEWHOPE_POLYBYTES + i] = seed[i]; } @@ -35,7 +35,7 @@ static void encode_pk(unsigned char *r, const poly *pk, const unsigned char *see **************************************************/ static void decode_pk(poly *pk, unsigned char *seed, const unsigned char *r) { int i; - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(pk, r); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frombytes(pk, r); for (i = 0; i < NEWHOPE_SYMBYTES; i++) { seed[i] = r[NEWHOPE_POLYBYTES + i]; } @@ -53,8 +53,8 @@ static void decode_pk(poly *pk, unsigned char *seed, const unsigned char *r) { * - const poly *v: pointer to the input polynomial v **************************************************/ static void encode_c(unsigned char *r, const poly *b, const poly *v) { - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(r, b); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(r + NEWHOPE_POLYBYTES, v); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tobytes(r, b); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_compress(r + NEWHOPE_POLYBYTES, v); } /************************************************* @@ -67,8 +67,8 @@ static void encode_c(unsigned char *r, const poly *b, const poly *v) { * - const unsigned char *r: pointer to input byte array **************************************************/ static void decode_c(poly *b, poly *v, const unsigned char *r) { - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(b, r); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(v, r + NEWHOPE_POLYBYTES); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frombytes(b, r); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_decompress(v, r + NEWHOPE_POLYBYTES); } /************************************************* @@ -80,7 +80,7 @@ static void decode_c(poly *b, poly *v, const unsigned char *r) { * - const unsigned char *seed: pointer to input seed **************************************************/ static void gen_a(poly *a, const unsigned char *seed) { - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(a, seed); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_uniform(a, seed); } @@ -94,7 +94,7 @@ static void gen_a(poly *a, const unsigned char *seed) { * Arguments: - unsigned char *pk: pointer to output public key * - unsigned char *sk: pointer to output private key **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(unsigned char *pk, +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_keypair(unsigned char *pk, unsigned char *sk) { poly ahat, ehat, ahat_shat, bhat, shat; unsigned char z[2 * NEWHOPE_SYMBYTES]; @@ -106,16 +106,16 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(unsigned char *pk, gen_a(&ahat, publicseed); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&shat, noiseseed, 0); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&shat); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(&shat, noiseseed, 0); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_ntt(&shat); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&ehat, noiseseed, 1); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&ehat); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(&ehat, noiseseed, 1); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_ntt(&ehat); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&ahat_shat, &shat, &ahat); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&bhat, &ehat, &ahat_shat); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_mul_pointwise(&ahat_shat, &shat, &ahat); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_add(&bhat, &ehat, &ahat_shat); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(sk, &shat); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tobytes(sk, &shat); encode_pk(pk, &bhat, publicseed); } @@ -132,33 +132,33 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(unsigned char *pk, * - const unsigned char *coin: pointer to input random coins used as seed * to deterministically generate all randomness **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(unsigned char *c, +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(unsigned char *c, const unsigned char *m, const unsigned char *pk, const unsigned char *coin) { poly sprime, eprime, vprime, ahat, bhat, eprimeprime, uhat, v; unsigned char publicseed[NEWHOPE_SYMBYTES]; - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(&v, m); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frommsg(&v, m); decode_pk(&bhat, publicseed, pk); gen_a(&ahat, publicseed); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&sprime, coin, 0); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&eprime, coin, 1); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(&eprimeprime, coin, 2); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(&sprime, coin, 0); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(&eprime, coin, 1); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(&eprimeprime, coin, 2); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&sprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(&eprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_ntt(&sprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_ntt(&eprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&uhat, &ahat, &sprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&uhat, &uhat, &eprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_mul_pointwise(&uhat, &ahat, &sprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_add(&uhat, &uhat, &eprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&vprime, &bhat, &sprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(&vprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_mul_pointwise(&vprime, &bhat, &sprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_invntt(&vprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&vprime, &vprime, &eprimeprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(&vprime, &vprime, &v); // add message + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_add(&vprime, &vprime, &eprimeprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_add(&vprime, &vprime, &v); // add message encode_c(c, &uhat, &vprime); } @@ -175,18 +175,18 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(unsigned char *c, * - const unsigned char *c: pointer to input ciphertext * - const unsigned char *sk: pointer to input secret key **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_dec(unsigned char *m, +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_dec(unsigned char *m, const unsigned char *c, const unsigned char *sk) { poly vprime, uhat, tmp, shat; - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(&shat, sk); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frombytes(&shat, sk); decode_c(&uhat, &vprime, c); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(&tmp, &shat, &uhat); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(&tmp); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_mul_pointwise(&tmp, &shat, &uhat); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_invntt(&tmp); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(&tmp, &tmp, &vprime); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sub(&tmp, &tmp, &vprime); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(m, &tmp); + PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tomsg(m, &tmp); } diff --git a/crypto_kem/newhope1024ccakem/clean/cpapke.h b/crypto_kem/newhope1024cca/clean/cpapke.h similarity index 54% rename from crypto_kem/newhope1024ccakem/clean/cpapke.h rename to crypto_kem/newhope1024cca/clean/cpapke.h index dad194f6..34be8055 100644 --- a/crypto_kem/newhope1024ccakem/clean/cpapke.h +++ b/crypto_kem/newhope1024cca/clean/cpapke.h @@ -1,15 +1,15 @@ #ifndef INDCPA_H #define INDCPA_H -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(unsigned char *pk, +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_keypair(unsigned char *pk, unsigned char *sk); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(unsigned char *c, +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(unsigned char *c, const unsigned char *m, const unsigned char *pk, const unsigned char *coins); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_dec(unsigned char *m, +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_dec(unsigned char *m, const unsigned char *c, const unsigned char *sk); diff --git a/crypto_kem/newhope1024ccakem/clean/kem.c b/crypto_kem/newhope1024cca/clean/kem.c similarity index 79% rename from crypto_kem/newhope1024ccakem/clean/kem.c rename to crypto_kem/newhope1024cca/clean/kem.c index 67585c23..2ac276c6 100644 --- a/crypto_kem/newhope1024ccakem/clean/kem.c +++ b/crypto_kem/newhope1024cca/clean/kem.c @@ -19,10 +19,10 @@ * * Returns 0 (success) **************************************************/ -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { +int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { size_t i; - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_keypair(pk, sk); /* First put the actual secret key into sk */ + PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_keypair(pk, sk); /* First put the actual secret key into sk */ sk += NEWHOPE_CPAPKE_SECRETKEYBYTES; for (i = 0; i < NEWHOPE_CPAPKE_PUBLICKEYBYTES; i++) { /* Append the public key for re-encryption */ @@ -50,7 +50,7 @@ int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_keypair(unsigned char *pk, unsign * * Returns 0 (success) **************************************************/ -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { +int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ unsigned char buf[2 * NEWHOPE_SYMBYTES]; int i; @@ -61,7 +61,7 @@ int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned c shake256(buf + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, pk, NEWHOPE_CCAKEM_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */ shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(ct, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ + PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(ct, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ for (i = 0; i < NEWHOPE_SYMBYTES; i++) { ct[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; /* copy Targhi-Unruh hash into ct */ @@ -86,30 +86,30 @@ int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned c * * On failure, ss will contain a randomized value. **************************************************/ -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { +int PQCLEAN_NEWHOPE1024CCA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { int i, fail; unsigned char ct_cmp[NEWHOPE_CCAKEM_CIPHERTEXTBYTES]; unsigned char buf[2 * NEWHOPE_SYMBYTES]; unsigned char k_coins_d[3 * NEWHOPE_SYMBYTES]; /* Will contain key, coins, qrom-hash */ const unsigned char *pk = sk + NEWHOPE_CPAPKE_SECRETKEYBYTES; - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_dec(buf, ct, sk); + PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_dec(buf, ct, sk); for (i = 0; i < NEWHOPE_SYMBYTES; i++) { /* Use hash of pk stored in sk */ buf[NEWHOPE_SYMBYTES + i] = sk[NEWHOPE_CCAKEM_SECRETKEYBYTES - 2 * NEWHOPE_SYMBYTES + i]; } shake256(k_coins_d, 3 * NEWHOPE_SYMBYTES, buf, 2 * NEWHOPE_SYMBYTES); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cpapke_enc(ct_cmp, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ + PQCLEAN_NEWHOPE1024CCA_CLEAN_cpapke_enc(ct_cmp, buf, pk, k_coins_d + NEWHOPE_SYMBYTES); /* coins are in k_coins_d+NEWHOPE_SYMBYTES */ for (i = 0; i < NEWHOPE_SYMBYTES; i++) { ct_cmp[i + NEWHOPE_CPAPKE_CIPHERTEXTBYTES] = k_coins_d[i + 2 * NEWHOPE_SYMBYTES]; } - fail = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(ct, ct_cmp, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); + fail = PQCLEAN_NEWHOPE1024CCA_CLEAN_verify(ct, ct_cmp, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); shake256(k_coins_d + NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, ct, NEWHOPE_CCAKEM_CIPHERTEXTBYTES); /* overwrite coins in k_coins_d with h(c) */ - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(k_coins_d, sk + NEWHOPE_CCAKEM_SECRETKEYBYTES - NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, (unsigned char) fail); /* Overwrite pre-k with z on re-encryption failure */ + PQCLEAN_NEWHOPE1024CCA_CLEAN_cmov(k_coins_d, sk + NEWHOPE_CCAKEM_SECRETKEYBYTES - NEWHOPE_SYMBYTES, NEWHOPE_SYMBYTES, (unsigned char) fail); /* Overwrite pre-k with z on re-encryption failure */ shake256(ss, NEWHOPE_SYMBYTES, k_coins_d, 2 * NEWHOPE_SYMBYTES); /* hash concatenation of pre-k and h(c) to k */ return 0; diff --git a/crypto_kem/newhope1024ccakem/clean/ntt.c b/crypto_kem/newhope1024cca/clean/ntt.c similarity index 92% rename from crypto_kem/newhope1024ccakem/clean/ntt.c rename to crypto_kem/newhope1024cca/clean/ntt.c index afed4ee1..ffefa465 100644 --- a/crypto_kem/newhope1024ccakem/clean/ntt.c +++ b/crypto_kem/newhope1024cca/clean/ntt.c @@ -51,7 +51,7 @@ static uint16_t bitrev_table[NEWHOPE_N] = { * * Arguments: - uint16_t* poly: pointer to in/output polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(uint16_t *poly) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_bitrev_vector(uint16_t *poly) { unsigned int i, r; uint16_t tmp; @@ -74,11 +74,11 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(uint16_t *poly) { * - const uint16_t* factors: pointer to input polynomial, coefficients * are assumed to be in Montgomery representation **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors) { unsigned int i; for (i = 0; i < NEWHOPE_N; i++) { - poly[i] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce((poly[i] * factors[i])); + poly[i] = PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce((poly[i] * factors[i])); } } @@ -94,7 +94,7 @@ void /************************************************* * - const uint16_t* omega: pointer to input powers of root of unity omega; * assumed to be in Montgomery domain **************************************************/ -PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { +PQCLEAN_NEWHOPE1024CCA_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { int i, start, j, jTwiddle, distance; uint16_t temp, W; @@ -108,7 +108,7 @@ PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { W = omega[jTwiddle++]; temp = a[j]; a[j] = (temp + a[j + distance]); // Omit reduction (be lazy) - a[j + distance] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + a[j + distance] = PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); } } @@ -120,7 +120,7 @@ PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { W = omega[jTwiddle++]; temp = a[j]; a[j] = (temp + a[j + distance]) % NEWHOPE_Q; - a[j + distance] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + a[j + distance] = PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); } } } diff --git a/crypto_kem/newhope1024cca/clean/ntt.h b/crypto_kem/newhope1024cca/clean/ntt.h new file mode 100644 index 00000000..c43ba5f1 --- /dev/null +++ b/crypto_kem/newhope1024cca/clean/ntt.h @@ -0,0 +1,14 @@ +#ifndef NTT_H +#define NTT_H + +#include "inttypes.h" + +extern const uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_omegas_inv_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_inv_montgomery[]; + +void PQCLEAN_NEWHOPE1024CCA_CLEAN_bitrev_vector(uint16_t *poly); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_ntt(uint16_t *a, const uint16_t *omegas); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/params.h b/crypto_kem/newhope1024cca/clean/params.h similarity index 91% rename from crypto_kem/newhope1024ccakem/clean/params.h rename to crypto_kem/newhope1024cca/clean/params.h index ab049d68..4e5e6442 100644 --- a/crypto_kem/newhope1024ccakem/clean/params.h +++ b/crypto_kem/newhope1024cca/clean/params.h @@ -1,5 +1,5 @@ -#ifndef PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_PARAMS_H -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_PARAMS_H +#ifndef PQCLEAN_NEWHOPE1024CCA_CLEAN_PARAMS_H +#define PQCLEAN_NEWHOPE1024CCA_CLEAN_PARAMS_H #define NEWHOPE_N 1024 #define NEWHOPE_Q 12289 diff --git a/crypto_kem/newhope1024ccakem/clean/poly.c b/crypto_kem/newhope1024cca/clean/poly.c similarity index 85% rename from crypto_kem/newhope1024ccakem/clean/poly.c rename to crypto_kem/newhope1024cca/clean/poly.c index 4d11314d..e368a6b3 100644 --- a/crypto_kem/newhope1024ccakem/clean/poly.c +++ b/crypto_kem/newhope1024cca/clean/poly.c @@ -51,7 +51,7 @@ static uint16_t flipabs(uint16_t x) { * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *a: pointer to input byte array **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(poly *r, const unsigned char *a) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frombytes(poly *r, const unsigned char *a) { int i; for (i = 0; i < NEWHOPE_N / 4; i++) { r->coeffs[4 * i + 0] = a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); @@ -69,7 +69,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(poly *r, const unsigned char * Arguments: - unsigned char *r: pointer to output byte array * - const poly *p: pointer to input polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(unsigned char *r, const poly *p) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tobytes(unsigned char *r, const poly *p) { int i; uint16_t t0, t1, t2, t3; for (i = 0; i < NEWHOPE_N / 4; i++) { @@ -96,7 +96,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(unsigned char *r, const poly * * Arguments: - unsigned char *r: pointer to output byte array * - const poly *p: pointer to input polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(unsigned char *r, const poly *p) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_compress(unsigned char *r, const poly *p) { unsigned int i, j, k = 0; uint32_t t[8]; @@ -123,7 +123,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(unsigned char *r, const poly * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *a: pointer to input byte array **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(poly *r, const unsigned char *a) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_decompress(poly *r, const unsigned char *a) { unsigned int i, j; for (i = 0; i < NEWHOPE_N; i += 8) { r->coeffs[i + 0] = a[0] & 7; @@ -149,7 +149,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(poly *r, const unsigned cha * Arguments: - poly *r: pointer to output polynomial * - const unsigned char *msg: pointer to input message **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { unsigned int i, j, mask; for (i = 0; i < 32; i++) { // XXX: MACRO for 32 for (j = 0; j < 8; j++) { @@ -170,7 +170,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(poly *r, const unsigned char * * Arguments: - unsigned char *msg: pointer to output message * - const poly *x: pointer to input polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { unsigned int i; uint16_t t; @@ -199,7 +199,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(unsigned char *msg, const poly * * Arguments: - poly *a: pointer to output polynomial * - const unsigned char *seed: pointer to input seed **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { unsigned int ctr = 0; uint16_t val; uint64_t state[25]; @@ -254,7 +254,7 @@ static unsigned char hw(unsigned char a) { * - const unsigned char *seed: pointer to input seed * - unsigned char nonce: one-byte input nonce **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { unsigned char buf[128], a, b; // uint32_t t, d, a, b, c; int i, j; @@ -298,12 +298,12 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(poly *r, const unsigned char *s * - const poly *a: pointer to first input polynomial * - const poly *b: pointer to second input polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b) { int i; uint16_t t; for (i = 0; i < NEWHOPE_N; i++) { - t = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(3186 * b->coeffs[i]); /* t is now in Montgomery domain */ - r->coeffs[i] = PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ + t = PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce(3186 * b->coeffs[i]); /* t is now in Montgomery domain */ + r->coeffs[i] = PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ } } @@ -316,7 +316,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(poly *r, const poly *a, * - const poly *a: pointer to first input polynomial * - const poly *b: pointer to second input polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(poly *r, const poly *a, const poly *b) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_add(poly *r, const poly *a, const poly *b) { int i; for (i = 0; i < NEWHOPE_N; i++) { r->coeffs[i] = (a->coeffs[i] + b->coeffs[i]) % NEWHOPE_Q; @@ -332,7 +332,7 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(poly *r, const poly *a, const poly * - const poly *a: pointer to first input polynomial * - const poly *b: pointer to second input polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) { int i; for (i = 0; i < NEWHOPE_N; i++) { r->coeffs[i] = (a->coeffs[i] + 3 * NEWHOPE_Q - b->coeffs[i]) % NEWHOPE_Q; @@ -348,9 +348,9 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(poly *r, const poly *a, const poly * * Arguments: - poly *r: pointer to in/output polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(poly *r) { - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_ntt(poly *r) { + PQCLEAN_NEWHOPE1024CCA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_bitrev_montgomery); + PQCLEAN_NEWHOPE1024CCA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_bitrev_montgomery); } /************************************************* @@ -362,9 +362,9 @@ void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(poly *r) { * * Arguments: - poly *r: pointer to in/output polynomial **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(poly *r) { - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(r->coeffs); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery); - PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_inv_montgomery); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_invntt(poly *r) { + PQCLEAN_NEWHOPE1024CCA_CLEAN_bitrev_vector(r->coeffs); + PQCLEAN_NEWHOPE1024CCA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CCA_CLEAN_omegas_inv_bitrev_montgomery); + PQCLEAN_NEWHOPE1024CCA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_inv_montgomery); } diff --git a/crypto_kem/newhope1024cca/clean/poly.h b/crypto_kem/newhope1024cca/clean/poly.h new file mode 100644 index 00000000..7da7ee58 --- /dev/null +++ b/crypto_kem/newhope1024cca/clean/poly.h @@ -0,0 +1,32 @@ +#ifndef POLY_H +#define POLY_H + +#include "params.h" +#include + +/* + * Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial + * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] + */ +typedef struct { + uint16_t coeffs[NEWHOPE_N]; +} poly; + +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_add(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_ntt(poly *r); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_invntt(poly *r); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frombytes(poly *r, const unsigned char *a); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tobytes(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_compress(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_decompress(poly *r, const unsigned char *a); + +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x); +void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/precomp.c b/crypto_kem/newhope1024cca/clean/precomp.c similarity index 99% rename from crypto_kem/newhope1024ccakem/clean/precomp.c rename to crypto_kem/newhope1024cca/clean/precomp.c index b61ee8fb..1540c6bb 100644 --- a/crypto_kem/newhope1024ccakem/clean/precomp.c +++ b/crypto_kem/newhope1024cca/clean/precomp.c @@ -78,7 +78,7 @@ * Description: Contains inverses of powers of nth root of unity * in Montgomery domain with R=2^18 in bit-reversed order ************************************************************/ -const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery[NEWHOPE_N / 2] = { +const uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_omegas_inv_bitrev_montgomery[NEWHOPE_N / 2] = { 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278, 9945, 3514, 11248, 11271, 5925, 147, 8500, 7840, 6833, 5537, 4749, 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, 9090, 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427, 7341, 6152, 10561, 400, @@ -119,7 +119,7 @@ const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery[NEWH * Description: Contains powers of nth root of -1 in Montgomery * domain with R=2^18 in bit-reversed order ************************************************************/ -const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery[NEWHOPE_N] = { +const uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_bitrev_montgomery[NEWHOPE_N] = { 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, 8775, 2344, 11011, 5574, 1973, 4536, 1050, 6844, 3860, 3818, 6118, 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, 11973, 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, 3998, 10256, 10367, 3879, @@ -192,7 +192,7 @@ const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery[NEWHOPE_ * Description: Contains inverses of powers of nth root of -1 * divided by n in Montgomery domain with R=2^18 ************************************************************/ -const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_inv_montgomery[NEWHOPE_N] = { +const uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_gammas_inv_montgomery[NEWHOPE_N] = { 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000, 2327, 2088, 5565, 795, 10647, 1521, 5484, 2539, 7385, 1055, 7173, 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, 10525, 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207, 5582, 2553, 7387, 6322, diff --git a/crypto_kem/newhope1024ccakem/clean/reduce.c b/crypto_kem/newhope1024cca/clean/reduce.c similarity index 91% rename from crypto_kem/newhope1024ccakem/clean/reduce.c rename to crypto_kem/newhope1024cca/clean/reduce.c index d14c6748..a024f7ea 100644 --- a/crypto_kem/newhope1024ccakem/clean/reduce.c +++ b/crypto_kem/newhope1024cca/clean/reduce.c @@ -15,7 +15,7 @@ static const uint32_t rlog = 18; * * Returns: unsigned integer in {0,...,2^14-1} congruent to a * R^-1 modulo q. **************************************************/ -uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(uint32_t a) { +uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce(uint32_t a) { uint32_t u; u = (a * qinv); diff --git a/crypto_kem/newhope1024cca/clean/reduce.h b/crypto_kem/newhope1024cca/clean/reduce.h new file mode 100644 index 00000000..268b049b --- /dev/null +++ b/crypto_kem/newhope1024cca/clean/reduce.h @@ -0,0 +1,8 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include + +uint16_t PQCLEAN_NEWHOPE1024CCA_CLEAN_montgomery_reduce(uint32_t a); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/verify.c b/crypto_kem/newhope1024cca/clean/verify.c similarity index 86% rename from crypto_kem/newhope1024ccakem/clean/verify.c rename to crypto_kem/newhope1024cca/clean/verify.c index 8e5126c2..0cb31049 100644 --- a/crypto_kem/newhope1024ccakem/clean/verify.c +++ b/crypto_kem/newhope1024cca/clean/verify.c @@ -13,7 +13,7 @@ * * Returns 0 if the byte arrays are equal, 1 otherwise **************************************************/ -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { +int PQCLEAN_NEWHOPE1024CCA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { uint64_t r; size_t i; r = 0; @@ -39,7 +39,7 @@ int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(const unsigned char *a, const unsigne * size_t len: Amount of bytes to be copied * unsigned char b: Condition bit; has to be in {0,1} **************************************************/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { size_t i; b = -b; diff --git a/crypto_kem/newhope1024cca/clean/verify.h b/crypto_kem/newhope1024cca/clean/verify.h new file mode 100644 index 00000000..e5819338 --- /dev/null +++ b/crypto_kem/newhope1024cca/clean/verify.h @@ -0,0 +1,12 @@ +#ifndef VERIFY_H +#define VERIFY_H + +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +int PQCLEAN_NEWHOPE1024CCA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_NEWHOPE1024CCA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); + +#endif diff --git a/crypto_kem/newhope1024ccakem/clean/api.h b/crypto_kem/newhope1024ccakem/clean/api.h deleted file mode 100644 index a4d84e69..00000000 --- a/crypto_kem/newhope1024ccakem/clean/api.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_API_H -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_API_H - - -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_SECRETKEYBYTES 3680 -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_PUBLICKEYBYTES 1824 -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_CIPHERTEXTBYTES 2208 -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_BYTES 32 -#define PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_CRYPTO_ALGNAME "NewHope1024-CCAKEM" - -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); - -#endif diff --git a/crypto_kem/newhope1024ccakem/clean/ntt.h b/crypto_kem/newhope1024ccakem/clean/ntt.h deleted file mode 100644 index e9fd5e1d..00000000 --- a/crypto_kem/newhope1024ccakem/clean/ntt.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef NTT_H -#define NTT_H - -#include "inttypes.h" - -extern const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_omegas_inv_bitrev_montgomery[]; -extern const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_bitrev_montgomery[]; -extern const uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_gammas_inv_montgomery[]; - -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_bitrev_vector(uint16_t *poly); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_ntt(uint16_t *a, const uint16_t *omegas); - -#endif diff --git a/crypto_kem/newhope1024ccakem/clean/poly.h b/crypto_kem/newhope1024ccakem/clean/poly.h deleted file mode 100644 index 2ffed246..00000000 --- a/crypto_kem/newhope1024ccakem/clean/poly.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef POLY_H -#define POLY_H - -#include "params.h" -#include - -/* - * Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial - * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] - */ -typedef struct { - uint16_t coeffs[NEWHOPE_N]; -} poly; - -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_uniform(poly *a, const unsigned char *seed); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_add(poly *r, const poly *a, const poly *b); - -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_ntt(poly *r); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_invntt(poly *r); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b); - -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frombytes(poly *r, const unsigned char *a); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tobytes(unsigned char *r, const poly *p); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_compress(unsigned char *r, const poly *p); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_decompress(poly *r, const unsigned char *a); - -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_frommsg(poly *r, const unsigned char *msg); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_tomsg(unsigned char *msg, const poly *x); -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_poly_sub(poly *r, const poly *a, const poly *b); - -#endif diff --git a/crypto_kem/newhope1024ccakem/clean/reduce.h b/crypto_kem/newhope1024ccakem/clean/reduce.h deleted file mode 100644 index 1598d193..00000000 --- a/crypto_kem/newhope1024ccakem/clean/reduce.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef REDUCE_H -#define REDUCE_H - -#include - -uint16_t PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_montgomery_reduce(uint32_t a); - -#endif diff --git a/crypto_kem/newhope1024ccakem/clean/verify.h b/crypto_kem/newhope1024ccakem/clean/verify.h deleted file mode 100644 index 12e73d9d..00000000 --- a/crypto_kem/newhope1024ccakem/clean/verify.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef VERIFY_H -#define VERIFY_H - -#include - -/* returns 0 for equal strings, 1 for non-equal strings */ -int PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); - -/* b = 1 means mov, b = 0 means don't mov*/ -void PQCLEAN_NEWHOPE1024CCAKEM_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); - -#endif From 4f4ed3cc8b000b12924d8e0bf822b4ceca69044d Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 8 May 2019 17:33:08 +0200 Subject: [PATCH 06/35] add newhope512cpa --- crypto_kem/newhope512cpa/META.yml | 20 + crypto_kem/newhope512cpa/clean/LICENSE | 1 + crypto_kem/newhope512cpa/clean/Makefile | 19 + .../clean/Makefile.Microsoft_nmake | 19 + crypto_kem/newhope512cpa/clean/api.h | 15 + crypto_kem/newhope512cpa/clean/cpapke.c | 192 +++++++++ crypto_kem/newhope512cpa/clean/cpapke.h | 16 + crypto_kem/newhope512cpa/clean/kem.c | 71 ++++ crypto_kem/newhope512cpa/clean/ntt.c | 112 ++++++ crypto_kem/newhope512cpa/clean/ntt.h | 14 + crypto_kem/newhope512cpa/clean/params.h | 25 ++ crypto_kem/newhope512cpa/clean/poly.c | 366 ++++++++++++++++++ crypto_kem/newhope512cpa/clean/poly.h | 32 ++ crypto_kem/newhope512cpa/clean/precomp.c | 179 +++++++++ crypto_kem/newhope512cpa/clean/reduce.c | 26 ++ crypto_kem/newhope512cpa/clean/reduce.h | 8 + crypto_kem/newhope512cpa/clean/verify.c | 49 +++ crypto_kem/newhope512cpa/clean/verify.h | 12 + 18 files changed, 1176 insertions(+) create mode 100644 crypto_kem/newhope512cpa/META.yml create mode 100644 crypto_kem/newhope512cpa/clean/LICENSE create mode 100644 crypto_kem/newhope512cpa/clean/Makefile create mode 100644 crypto_kem/newhope512cpa/clean/Makefile.Microsoft_nmake create mode 100644 crypto_kem/newhope512cpa/clean/api.h create mode 100644 crypto_kem/newhope512cpa/clean/cpapke.c create mode 100644 crypto_kem/newhope512cpa/clean/cpapke.h create mode 100644 crypto_kem/newhope512cpa/clean/kem.c create mode 100644 crypto_kem/newhope512cpa/clean/ntt.c create mode 100644 crypto_kem/newhope512cpa/clean/ntt.h create mode 100644 crypto_kem/newhope512cpa/clean/params.h create mode 100644 crypto_kem/newhope512cpa/clean/poly.c create mode 100644 crypto_kem/newhope512cpa/clean/poly.h create mode 100644 crypto_kem/newhope512cpa/clean/precomp.c create mode 100644 crypto_kem/newhope512cpa/clean/reduce.c create mode 100644 crypto_kem/newhope512cpa/clean/reduce.h create mode 100644 crypto_kem/newhope512cpa/clean/verify.c create mode 100644 crypto_kem/newhope512cpa/clean/verify.h diff --git a/crypto_kem/newhope512cpa/META.yml b/crypto_kem/newhope512cpa/META.yml new file mode 100644 index 00000000..8db17433 --- /dev/null +++ b/crypto_kem/newhope512cpa/META.yml @@ -0,0 +1,20 @@ +name: NewHope512CPA +type: kem +claimed-nist-level: 1 +length-public-key: 928 +length-secret-key: 896 +length-ciphertext: 1088 +length-shared-secret: 32 +nistkat-sha256: 42444446b96f45c9b7221c4fde8afd5dfc0b3c2ff05b9a88ff12ea3949fbb76c +principal-submitter: Thomas Pöppelmann +auxiliary-submitters: +- Erdem Alkim +- Roberto Avanzi +- Joppe Bos +- Léo Ducas +- Antonio de la Piedra +- Peter Schwabe +- Douglas Stebila +implementations: +- name: clean + version: https://github.com/newhopecrypto/newhope/commit/3fc68c6090b23c56cc190a78af2f43ee8900e9d0 diff --git a/crypto_kem/newhope512cpa/clean/LICENSE b/crypto_kem/newhope512cpa/clean/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/newhope512cpa/clean/Makefile b/crypto_kem/newhope512cpa/clean/Makefile new file mode 100644 index 00000000..8f5967d5 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libnewhope512cpa_clean.a +HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h +OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/newhope512cpa/clean/Makefile.Microsoft_nmake b/crypto_kem/newhope512cpa/clean/Makefile.Microsoft_nmake new file mode 100644 index 00000000..249a7d1f --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libnewhope512cpa_clean.lib +OBJECTS=cpapke.obj kem.obj ntt.obj poly.obj precomp.obj reduce.obj verify.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/newhope512cpa/clean/api.h b/crypto_kem/newhope512cpa/clean/api.h new file mode 100644 index 00000000..791d72af --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/api.h @@ -0,0 +1,15 @@ +#ifndef PQCLEAN_NEWHOPE512CPA_CLEAN_API_H +#define PQCLEAN_NEWHOPE512CPA_CLEAN_API_H + + +#define PQCLEAN_NEWHOPE512CPA_CLEAN_CRYPTO_SECRETKEYBYTES 896 +#define PQCLEAN_NEWHOPE512CPA_CLEAN_CRYPTO_PUBLICKEYBYTES 928 +#define PQCLEAN_NEWHOPE512CPA_CLEAN_CRYPTO_CIPHERTEXTBYTES 1088 +#define PQCLEAN_NEWHOPE512CPA_CLEAN_CRYPTO_BYTES 32 +#define PQCLEAN_NEWHOPE512CPA_CLEAN_CRYPTO_ALGNAME "NewHope512-CPAKEM" + +int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); +int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); +int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope512cpa/clean/cpapke.c b/crypto_kem/newhope512cpa/clean/cpapke.c new file mode 100644 index 00000000..dbcc3434 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/cpapke.c @@ -0,0 +1,192 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "poly.h" +#include "randombytes.h" +#include + +/************************************************* +* Name: encode_pk +* +* Description: Serialize the public key as concatenation of the +* serialization of the polynomial pk and the public seed +* used to generete the polynomial a. +* +* Arguments: unsigned char *r: pointer to the output serialized public key +* const poly *pk: pointer to the input public-key polynomial +* const unsigned char *seed: pointer to the input public seed +**************************************************/ +static void encode_pk(unsigned char *r, const poly *pk, const unsigned char *seed) { + int i; + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tobytes(r, pk); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + r[NEWHOPE_POLYBYTES + i] = seed[i]; + } +} + +/************************************************* +* Name: decode_pk +* +* Description: De-serialize the public key; inverse of encode_pk +* +* Arguments: poly *pk: pointer to output public-key polynomial +* unsigned char *seed: pointer to output public seed +* const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_pk(poly *pk, unsigned char *seed, const unsigned char *r) { + int i; + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frombytes(pk, r); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + seed[i] = r[NEWHOPE_POLYBYTES + i]; + } +} + +/************************************************* +* Name: encode_c +* +* Description: Serialize the ciphertext as concatenation of the +* serialization of the polynomial b and serialization +* of the compressed polynomial v +* +* Arguments: - unsigned char *r: pointer to the output serialized ciphertext +* - const poly *b: pointer to the input polynomial b +* - const poly *v: pointer to the input polynomial v +**************************************************/ +static void encode_c(unsigned char *r, const poly *b, const poly *v) { + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tobytes(r, b); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_compress(r + NEWHOPE_POLYBYTES, v); +} + +/************************************************* +* Name: decode_c +* +* Description: de-serialize the ciphertext; inverse of encode_c +* +* Arguments: - poly *b: pointer to output polynomial b +* - poly *v: pointer to output polynomial v +* - const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_c(poly *b, poly *v, const unsigned char *r) { + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frombytes(b, r); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_decompress(v, r + NEWHOPE_POLYBYTES); +} + +/************************************************* +* Name: gen_a +* +* Description: Deterministically generate public polynomial a from seed +* +* Arguments: - poly *a: pointer to output polynomial a +* - const unsigned char *seed: pointer to input seed +**************************************************/ +static void gen_a(poly *a, const unsigned char *seed) { + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_uniform(a, seed); +} + + +/************************************************* +* Name: cpapke_keypair +* +* Description: Generates public and private key +* for the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *pk: pointer to output public key +* - unsigned char *sk: pointer to output private key +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk) { + poly ahat, ehat, ahat_shat, bhat, shat; + unsigned char z[2 * NEWHOPE_SYMBYTES]; + unsigned char *publicseed = z; + unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; + + randombytes(z, NEWHOPE_SYMBYTES); + shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); + + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(&shat, noiseseed, 0); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_ntt(&shat); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(&ehat, noiseseed, 1); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_ntt(&ehat); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_mul_pointwise(&ahat_shat, &shat, &ahat); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_add(&bhat, &ehat, &ahat_shat); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tobytes(sk, &shat); + encode_pk(pk, &bhat, publicseed); +} + +/************************************************* +* Name: cpapke_enc +* +* Description: Encryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *c: pointer to output ciphertext +* - const unsigned char *m: pointer to input message (of length NEWHOPE_SYMBYTES bytes) +* - const unsigned char *pk: pointer to input public key +* - const unsigned char *coin: pointer to input random coins used as seed +* to deterministically generate all randomness +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coin) { + poly sprime, eprime, vprime, ahat, bhat, eprimeprime, uhat, v; + unsigned char publicseed[NEWHOPE_SYMBYTES]; + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frommsg(&v, m); + + decode_pk(&bhat, publicseed, pk); + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(&sprime, coin, 0); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(&eprime, coin, 1); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(&eprimeprime, coin, 2); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_ntt(&sprime); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_ntt(&eprime); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_mul_pointwise(&uhat, &ahat, &sprime); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_add(&uhat, &uhat, &eprime); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_mul_pointwise(&vprime, &bhat, &sprime); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_invntt(&vprime); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_add(&vprime, &vprime, &eprimeprime); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_add(&vprime, &vprime, &v); // add message + + encode_c(c, &uhat, &vprime); +} + + +/************************************************* +* Name: cpapke_dec +* +* Description: Decryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *m: pointer to output decrypted message +* - const unsigned char *c: pointer to input ciphertext +* - const unsigned char *sk: pointer to input secret key +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk) { + poly vprime, uhat, tmp, shat; + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frombytes(&shat, sk); + + decode_c(&uhat, &vprime, c); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_mul_pointwise(&tmp, &shat, &uhat); + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_invntt(&tmp); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sub(&tmp, &tmp, &vprime); + + PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tomsg(m, &tmp); +} diff --git a/crypto_kem/newhope512cpa/clean/cpapke.h b/crypto_kem/newhope512cpa/clean/cpapke.h new file mode 100644 index 00000000..43539e07 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/cpapke.h @@ -0,0 +1,16 @@ +#ifndef INDCPA_H +#define INDCPA_H + +void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk); + +void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coins); + +void PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope512cpa/clean/kem.c b/crypto_kem/newhope512cpa/clean/kem.c new file mode 100644 index 00000000..95fbd4ff --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/kem.c @@ -0,0 +1,71 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "params.h" +#include "randombytes.h" +#include "verify.h" +#include + +/************************************************* +* Name: crypto_kem_keypair +* +* Description: Generates public and private key +* for CCA secure NewHope key encapsulation +* mechanism +* +* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_keypair(pk, sk); /* First put the actual secret key into sk */ + + return 0; +} + +/************************************************* +* Name: crypto_kem_enc +* +* Description: Generates cipher text and shared +* secret for given public key +* +* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { + unsigned char buf[2 * NEWHOPE_SYMBYTES]; + + randombytes(buf, NEWHOPE_SYMBYTES); + + shake256(buf, 2 * NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ + + PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_enc(ct, buf, pk, buf + NEWHOPE_SYMBYTES); /* coins are in buf+NEWHOPE_SYMBYTES */ + + shake256(ss, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* hash pre-k to ss */ + return 0; +} + + +/************************************************* +* Name: crypto_kem_dec +* +* Description: Generates shared secret for given +* cipher text and private key +* +* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE512CPA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { + PQCLEAN_NEWHOPE512CPA_CLEAN_cpapke_dec(ss, ct, sk); + + shake256(ss, NEWHOPE_SYMBYTES, ss, NEWHOPE_SYMBYTES); /* hash pre-k to ss */ + + return 0; +} diff --git a/crypto_kem/newhope512cpa/clean/ntt.c b/crypto_kem/newhope512cpa/clean/ntt.c new file mode 100644 index 00000000..7a449088 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/ntt.c @@ -0,0 +1,112 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" + +/************************************************************ +* Name: bitrev_table +* +* Description: Contains bit-reversed 9-bit indices to be used to re-order +* polynomials before number theoratic transform +************************************************************/ +static uint16_t bitrev_table [512] = { + 0, 256, 128, 384, 64, 320, 192, 448, 32, 288, 160, 416, 96, 352, 224, 480, 16, 272, 144, 400, 80, 336, 208, 464, 48, 304, 176, 432, 112, 368, 240, 496, 8, + 264, 136, 392, 72, 328, 200, 456, 40, 296, 168, 424, 104, 360, 232, 488, 24, 280, 152, 408, 88, 344, 216, 472, 56, 312, 184, 440, 120, 376, 248, 504, 4, + 260, 132, 388, 68, 324, 196, 452, 36, 292, 164, 420, 100, 356, 228, 484, 20, 276, 148, 404, 84, 340, 212, 468, 52, 308, 180, 436, 116, 372, 244, 500, 12, + 268, 140, 396, 76, 332, 204, 460, 44, 300, 172, 428, 108, 364, 236, 492, 28, 284, 156, 412, 92, 348, 220, 476, 60, 316, 188, 444, 124, 380, 252, 508, 2, + 258, 130, 386, 66, 322, 194, 450, 34, 290, 162, 418, 98, 354, 226, 482, 18, 274, 146, 402, 82, 338, 210, 466, 50, 306, 178, 434, 114, 370, 242, 498, 10, + 266, 138, 394, 74, 330, 202, 458, 42, 298, 170, 426, 106, 362, 234, 490, 26, 282, 154, 410, 90, 346, 218, 474, 58, 314, 186, 442, 122, 378, 250, 506, 6, + 262, 134, 390, 70, 326, 198, 454, 38, 294, 166, 422, 102, 358, 230, 486, 22, 278, 150, 406, 86, 342, 214, 470, 54, 310, 182, 438, 118, 374, 246, 502, 14, + 270, 142, 398, 78, 334, 206, 462, 46, 302, 174, 430, 110, 366, 238, 494, 30, 286, 158, 414, 94, 350, 222, 478, 62, 318, 190, 446, 126, 382, 254, 510, 1, + 257, 129, 385, 65, 321, 193, 449, 33, 289, 161, 417, 97, 353, 225, 481, 17, 273, 145, 401, 81, 337, 209, 465, 49, 305, 177, 433, 113, 369, 241, 497, 9, + 265, 137, 393, 73, 329, 201, 457, 41, 297, 169, 425, 105, 361, 233, 489, 25, 281, 153, 409, 89, 345, 217, 473, 57, 313, 185, 441, 121, 377, 249, 505, 5, + 261, 133, 389, 69, 325, 197, 453, 37, 293, 165, 421, 101, 357, 229, 485, 21, 277, 149, 405, 85, 341, 213, 469, 53, 309, 181, 437, 117, 373, 245, 501, 13, + 269, 141, 397, 77, 333, 205, 461, 45, 301, 173, 429, 109, 365, 237, 493, 29, 285, 157, 413, 93, 349, 221, 477, 61, 317, 189, 445, 125, 381, 253, 509, 3, + 259, 131, 387, 67, 323, 195, 451, 35, 291, 163, 419, 99, 355, 227, 483, 19, 275, 147, 403, 83, 339, 211, 467, 51, 307, 179, 435, 115, 371, 243, 499, 11, + 267, 139, 395, 75, 331, 203, 459, 43, 299, 171, 427, 107, 363, 235, 491, 27, 283, 155, 411, 91, 347, 219, 475, 59, 315, 187, 443, 123, 379, 251, 507, 7, + 263, 135, 391, 71, 327, 199, 455, 39, 295, 167, 423, 103, 359, 231, 487, 23, 279, 151, 407, 87, 343, 215, 471, 55, 311, 183, 439, 119, 375, 247, 503, 15, + 271, 143, 399, 79, 335, 207, 463, 47, 303, 175, 431, 111, 367, 239, 495, 31, 287, 159, 415, 95, 351, 223, 479, 63, 319, 191, 447, 127, 383, 255, 511 +}; + +/************************************************* +* Name: bitrev_vector +* +* Description: Permutes coefficients of a polynomial into bitreversed order +* +* Arguments: - uint16_t* poly: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_bitrev_vector(uint16_t *poly) { + unsigned int i, r; + uint16_t tmp; + + for (i = 0; i < NEWHOPE_N; i++) { + r = bitrev_table[i]; + if (i < r) { + tmp = poly[i]; + poly[i] = poly[r]; + poly[r] = tmp; + } + } +} + +/************************************************* +* Name: mul_coefficients +* +* Description: Performs pointwise (coefficient-wise) multiplication +* of two polynomials +* Arguments: - uint16_t* poly: pointer to in/output polynomial +* - const uint16_t* factors: pointer to input polynomial, coefficients +* are assumed to be in Montgomery representation +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors) { + unsigned int i; + + for (i = 0; i < NEWHOPE_N; i++) { + poly[i] = PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce((poly[i] * factors[i])); + } +} + + +/************************************************* +* Name: ntt +* +* Description: Computes number-theoretic transform (NTT) of +* a polynomial in place; inputs assumed to be in +* bitreversed order, output in normal order +* +* Arguments: - uint16_t * a: pointer to in/output polynomial +* - const uint16_t* omega: pointer to input powers of root of unity omega; +* assumed to be in Montgomery domain +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { + int i, start, j, jTwiddle, distance; + uint16_t temp, W; + + + for (i = 0; i < 9; i += 2) { + // Even level + distance = (1 << i); + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]); // Omit reduction (be lazy) + a[j + distance] = PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + if (i + 1 < 9) { + // Odd level + distance <<= 1; + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]) % NEWHOPE_Q; + a[j + distance] = PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + } + } +} diff --git a/crypto_kem/newhope512cpa/clean/ntt.h b/crypto_kem/newhope512cpa/clean/ntt.h new file mode 100644 index 00000000..6d17c247 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/ntt.h @@ -0,0 +1,14 @@ +#ifndef NTT_H +#define NTT_H + +#include "inttypes.h" + +extern const uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_omegas_inv_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_inv_montgomery[]; + +void PQCLEAN_NEWHOPE512CPA_CLEAN_bitrev_vector(uint16_t *poly); +void PQCLEAN_NEWHOPE512CPA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors); +void PQCLEAN_NEWHOPE512CPA_CLEAN_ntt(uint16_t *a, const uint16_t *omegas); + +#endif diff --git a/crypto_kem/newhope512cpa/clean/params.h b/crypto_kem/newhope512cpa/clean/params.h new file mode 100644 index 00000000..f9de0856 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/params.h @@ -0,0 +1,25 @@ +#ifndef PQCLEAN_NEWHOPE512CPA_CLEAN_PARAMS_H +#define PQCLEAN_NEWHOPE512CPA_CLEAN_PARAMS_H + +#define NEWHOPE_N 512 +#define NEWHOPE_Q 12289 +#define NEWHOPE_K 8 /* used in noise sampling */ + +#define NEWHOPE_SYMBYTES 32 /* size of shared key, seeds/coins, and hashes */ + +#define NEWHOPE_POLYBYTES ((14*NEWHOPE_N)/8) +#define NEWHOPE_POLYCOMPRESSEDBYTES (( 3*NEWHOPE_N)/8) + +#define NEWHOPE_CPAPKE_PUBLICKEYBYTES (NEWHOPE_POLYBYTES + NEWHOPE_SYMBYTES) +#define NEWHOPE_CPAPKE_SECRETKEYBYTES (NEWHOPE_POLYBYTES) +#define NEWHOPE_CPAPKE_CIPHERTEXTBYTES (NEWHOPE_POLYBYTES + NEWHOPE_POLYCOMPRESSEDBYTES) + +#define NEWHOPE_CPAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CPAKEM_SECRETKEYBYTES NEWHOPE_CPAPKE_SECRETKEYBYTES +#define NEWHOPE_CPAKEM_CIPHERTEXTBYTES NEWHOPE_CPAPKE_CIPHERTEXTBYTES + +#define NEWHOPE_CCAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CCAKEM_SECRETKEYBYTES (NEWHOPE_CPAPKE_SECRETKEYBYTES + NEWHOPE_CPAPKE_PUBLICKEYBYTES + 2*NEWHOPE_SYMBYTES) +#define NEWHOPE_CCAKEM_CIPHERTEXTBYTES (NEWHOPE_CPAPKE_CIPHERTEXTBYTES + NEWHOPE_SYMBYTES) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/newhope512cpa/clean/poly.c b/crypto_kem/newhope512cpa/clean/poly.c new file mode 100644 index 00000000..cd6cac24 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/poly.c @@ -0,0 +1,366 @@ +#include "fips202.h" +#include "ntt.h" +#include "poly.h" +#include "reduce.h" + +/************************************************* +* Name: coeff_freeze +* +* Description: Fully reduces an integer modulo q in constant time +* +* Arguments: uint16_t x: input integer to be reduced +* +* Returns integer in {0,...,q-1} congruent to x modulo q +**************************************************/ +static uint16_t coeff_freeze(uint16_t x) { + uint16_t m, r; + int16_t c; + r = x % NEWHOPE_Q; + + m = r - NEWHOPE_Q; + c = m; + c >>= 15; + r = m ^ ((r ^ m)&c); + + return r; +} + +/************************************************* +* Name: flipabs +* +* Description: Computes |(x mod q) - Q/2| +* +* Arguments: uint16_t x: input coefficient +* +* Returns |(x mod q) - Q/2| +**************************************************/ +static uint16_t flipabs(uint16_t x) { + int16_t r, m; + r = coeff_freeze(x); + + r = r - NEWHOPE_Q / 2; + m = r >> 15; + return (r + m) ^ m; +} + +/************************************************* +* Name: poly_frombytes +* +* Description: De-serialization of a polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frombytes(poly *r, const unsigned char *a) { + int i; + for (i = 0; i < NEWHOPE_N / 4; i++) { + r->coeffs[4 * i + 0] = a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); + r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) | (((uint16_t)a[7 * i + 2]) << 2) | (((uint16_t)a[7 * i + 3] & 0x0f) << 10); + r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) | (((uint16_t)a[7 * i + 4]) << 4) | (((uint16_t)a[7 * i + 5] & 0x03) << 12); + r->coeffs[4 * i + 3] = (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6); + } +} + +/************************************************* +* Name: poly_tobytes +* +* Description: Serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tobytes(unsigned char *r, const poly *p) { + int i; + uint16_t t0, t1, t2, t3; + for (i = 0; i < NEWHOPE_N / 4; i++) { + t0 = coeff_freeze(p->coeffs[4 * i + 0]); + t1 = coeff_freeze(p->coeffs[4 * i + 1]); + t2 = coeff_freeze(p->coeffs[4 * i + 2]); + t3 = coeff_freeze(p->coeffs[4 * i + 3]); + + r[7 * i + 0] = t0 & 0xff; + r[7 * i + 1] = (unsigned char) ((t0 >> 8) | (t1 << 6)); + r[7 * i + 2] = (unsigned char) ((t1 >> 2)); + r[7 * i + 3] = (unsigned char) ((t1 >> 10) | (t2 << 4)); + r[7 * i + 4] = (unsigned char) ((t2 >> 4)); + r[7 * i + 5] = (unsigned char) ((t2 >> 12) | (t3 << 2)); + r[7 * i + 6] = (unsigned char) ((t3 >> 6)); + } +} + +/************************************************* +* Name: poly_compress +* +* Description: Compression and subsequent serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_compress(unsigned char *r, const poly *p) { + unsigned int i, j, k = 0; + + uint32_t t[8]; + + for (i = 0; i < NEWHOPE_N; i += 8) { + for (j = 0; j < 8; j++) { + t[j] = coeff_freeze(p->coeffs[i + j]); + t[j] = (((t[j] << 3) + NEWHOPE_Q / 2) / NEWHOPE_Q) & 0x7; + } + + r[k] = (unsigned char) (t[0] | (t[1] << 3) | (t[2] << 6)); + r[k + 1] = (unsigned char) ((t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7)); + r[k + 2] = (unsigned char) ((t[5] >> 1) | (t[6] << 2) | (t[7] << 5)); + k += 3; + } +} + +/************************************************* +* Name: poly_decompress +* +* Description: De-serialization and subsequent decompression of a polynomial; +* approximate inverse of poly_compress +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_decompress(poly *r, const unsigned char *a) { + unsigned int i, j; + for (i = 0; i < NEWHOPE_N; i += 8) { + r->coeffs[i + 0] = a[0] & 7; + r->coeffs[i + 1] = (a[0] >> 3) & 7; + r->coeffs[i + 2] = (a[0] >> 6) | ((a[1] << 2) & 4); + r->coeffs[i + 3] = (a[1] >> 1) & 7; + r->coeffs[i + 4] = (a[1] >> 4) & 7; + r->coeffs[i + 5] = (a[1] >> 7) | ((a[2] << 1) & 6); + r->coeffs[i + 6] = (a[2] >> 2) & 7; + r->coeffs[i + 7] = (a[2] >> 5); + a += 3; + for (j = 0; j < 8; j++) { + r->coeffs[i + j] = ((uint32_t)r->coeffs[i + j] * NEWHOPE_Q + 4) >> 3; + } + } +} + +/************************************************* +* Name: poly_frommsg +* +* Description: Convert 32-byte message to polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *msg: pointer to input message +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { + unsigned int i, j, mask; + for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (j = 0; j < 8; j++) { + mask = -((msg[i] >> j) & 1); + r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 256] = mask & (NEWHOPE_Q / 2); + } + } +} + +/************************************************* +* Name: poly_tomsg +* +* Description: Convert polynomial to 32-byte message +* +* Arguments: - unsigned char *msg: pointer to output message +* - const poly *x: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { + unsigned int i; + uint16_t t; + + for (i = 0; i < 32; i++) { + msg[i] = 0; + } + + for (i = 0; i < 256; i++) { + t = flipabs(x->coeffs[i + 0]); + t += flipabs(x->coeffs[i + 256]); + t = ((t - NEWHOPE_Q / 2)); + + t >>= 15; + msg[i >> 3] |= t << (i & 7); + } +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample a polynomial deterministically from a seed, +* with output polynomial looking uniformly random +* +* Arguments: - poly *a: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { + unsigned int ctr = 0; + uint16_t val; + uint64_t state[25]; + uint8_t buf[SHAKE128_RATE]; + uint8_t extseed[NEWHOPE_SYMBYTES + 1]; + int i, j; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ + ctr = 0; + extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ + shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + while (ctr < 64) { /* Very unlikely to run more than once */ + shake128_squeezeblocks(buf, 1, state); + for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { + val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); + if (val < 5 * NEWHOPE_Q) { + a->coeffs[i * 64 + ctr] = val; + ctr++; + } + } + } + } +} + +/************************************************* +* Name: hw +* +* Description: Compute the Hamming weight of a byte +* +* Arguments: - unsigned char a: input byte +**************************************************/ +static unsigned char hw(unsigned char a) { + unsigned char i, r = 0; + for (i = 0; i < 8; i++) { + r += (a >> i) & 1; + } + return r; +} + +/************************************************* +* Name: poly_sample +* +* Description: Sample a polynomial deterministically from a seed and a nonce, +* with output polynomial close to centered binomial distribution +* with parameter k=8 +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +* - unsigned char nonce: one-byte input nonce +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { + unsigned char buf[128], a, b; +// uint32_t t, d, a, b, c; + int i, j; + + unsigned char extseed[NEWHOPE_SYMBYTES + 2]; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + extseed[NEWHOPE_SYMBYTES] = nonce; + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* Generate noise in blocks of 64 coefficients */ + extseed[NEWHOPE_SYMBYTES + 1] = (unsigned char) i; + shake256(buf, 128, extseed, NEWHOPE_SYMBYTES + 2); + for (j = 0; j < 64; j++) { + a = buf[2 * j]; + b = buf[2 * j + 1]; + r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); + /* + t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); + d = 0; + for(k=0;k<8;k++) + d += (t >> k) & 0x01010101; + a = d & 0xff; + b = ((d >> 8) & 0xff); + c = ((d >> 16) & 0xff); + d >>= 24; + r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; + r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; + */ + } + } +} + +/************************************************* +* Name: poly_pointwise +* +* Description: Multiply two polynomials pointwise (i.e., coefficient-wise). +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b) { + int i; + uint16_t t; + for (i = 0; i < NEWHOPE_N; i++) { + t = PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce(3186 * b->coeffs[i]); /* t is now in Montgomery domain */ + r->coeffs[i] = PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ + } +} + +/************************************************* +* Name: poly_add +* +* Description: Add two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_add(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + 3 * NEWHOPE_Q - b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_ntt +* +* Description: Forward NTT transform of a polynomial in place +* Input is assumed to have coefficients in bitreversed order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_ntt(poly *r) { + PQCLEAN_NEWHOPE512CPA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_bitrev_montgomery); + PQCLEAN_NEWHOPE512CPA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_bitrev_montgomery); +} + +/************************************************* +* Name: poly_invntt +* +* Description: Inverse NTT transform of a polynomial in place +* Input is assumed to have coefficients in normal order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_invntt(poly *r) { + PQCLEAN_NEWHOPE512CPA_CLEAN_bitrev_vector(r->coeffs); + PQCLEAN_NEWHOPE512CPA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE512CPA_CLEAN_omegas_inv_bitrev_montgomery); + PQCLEAN_NEWHOPE512CPA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_inv_montgomery); +} + diff --git a/crypto_kem/newhope512cpa/clean/poly.h b/crypto_kem/newhope512cpa/clean/poly.h new file mode 100644 index 00000000..18b5e9a9 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/poly.h @@ -0,0 +1,32 @@ +#ifndef POLY_H +#define POLY_H + +#include "params.h" +#include + +/* + * Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial + * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] + */ +typedef struct { + uint16_t coeffs[NEWHOPE_N]; +} poly; + +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_add(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_ntt(poly *r); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_invntt(poly *r); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frombytes(poly *r, const unsigned char *a); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tobytes(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_compress(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_decompress(poly *r, const unsigned char *a); + +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x); +void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b); + +#endif diff --git a/crypto_kem/newhope512cpa/clean/precomp.c b/crypto_kem/newhope512cpa/clean/precomp.c new file mode 100644 index 00000000..039d671b --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/precomp.c @@ -0,0 +1,179 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" + +/* Precomputed NTT contants generated by Pari/GP script as follows: + * + * For n = 512: + * + * brv = [0,256,128,384,64,320,192,448,32,288,160,416,96,352,224,480,16,272,144,400,80,336,208,464,48,304,176,432,112,368,240,496,8, + * 264,136,392,72,328,200,456,40,296,168,424,104,360,232,488,24,280,152,408,88,344,216,472,56,312,184,440,120,376,248,504,4, + * 260,132,388,68,324,196,452,36,292,164,420,100,356,228,484,20,276,148,404,84,340,212,468,52,308,180,436,116,372,244,500,12, + * 268,140,396,76,332,204,460,44,300,172,428,108,364,236,492,28,284,156,412,92,348,220,476,60,316,188,444,124,380,252,508,2, + * 258,130,386,66,322,194,450,34,290,162,418,98,354,226,482,18,274,146,402,82,338,210,466,50,306,178,434,114,370,242,498,10, + * 266,138,394,74,330,202,458,42,298,170,426,106,362,234,490,26,282,154,410,90,346,218,474,58,314,186,442,122,378,250,506,6, + * 262,134,390,70,326,198,454,38,294,166,422,102,358,230,486,22,278,150,406,86,342,214,470,54,310,182,438,118,374,246,502,14, + * 270,142,398,78,334,206,462,46,302,174,430,110,366,238,494,30,286,158,414,94,350,222,478,62,318,190,446,126,382,254,510,1, + * 257,129,385,65,321,193,449,33,289,161,417,97,353,225,481,17,273,145,401,81,337,209,465,49,305,177,433,113,369,241,497,9, + * 265,137,393,73,329,201,457,41,297,169,425,105,361,233,489,25,281,153,409,89,345,217,473,57,313,185,441,121,377,249,505,5, + * 261,133,389,69,325,197,453,37,293,165,421,101,357,229,485,21,277,149,405,85,341,213,469,53,309,181,437,117,373,245,501,13, + * 269,141,397,77,333,205,461,45,301,173,429,109,365,237,493,29,285,157,413,93,349,221,477,61,317,189,445,125,381,253,509,3, + * 259,131,387,67,323,195,451,35,291,163,419,99,355,227,483,19,275,147,403,83,339,211,467,51,307,179,435,115,371,243,499,11, + * 267,139,395,75,331,203,459,43,299,171,427,107,363,235,491,27,283,155,411,91,347,219,475,59,315,187,443,123,379,251,507,7, + * 263,135,391,71,327,199,455,39,295,167,423,103,359,231,487,23,279,151,407,87,343,215,471,55,311,183,439,119,375,247,503,15, + * 271,143,399,79,335,207,463,47,303,175,431,111,367,239,495,31,287,159,415,95,351,223,479,63,319,191,447,127,383,255,511] + * n = 512; q = 12289; mont=2^18 + * g = Mod(10968, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) + * + * + * For n = 1024: + * + * brv = [0,512,256,768,128,640,384,896,64,576,320,832,192,704,448,960,32,544,288,800,160,672,416,928,96,608,352,864,224,736,480,992, \ + * 16,528,272,784,144,656,400,912,80,592,336,848,208,720,464,976,48,560,304,816,176,688,432,944,112,624,368,880,240,752,496,1008, \ + * 8,520,264,776,136,648,392,904,72,584,328,840,200,712,456,968,40,552,296,808,168,680,424,936,104,616,360,872,232,744,488,1000, \ + * 24,536,280,792,152,664,408,920,88,600,344,856,216,728,472,984,56,568,312,824,184,696,440,952,120,632,376,888,248,760,504,1016, \ + * 4,516,260,772,132,644,388,900,68,580,324,836,196,708,452,964,36,548,292,804,164,676,420,932,100,612,356,868,228,740,484,996, \ + * 20,532,276,788,148,660,404,916,84,596,340,852,212,724,468,980,52,564,308,820,180,692,436,948,116,628,372,884,244,756,500,1012, \ + * 12,524,268,780,140,652,396,908,76,588,332,844,204,716,460,972,44,556,300,812,172,684,428,940,108,620,364,876,236,748,492,1004, \ + * 28,540,284,796,156,668,412,924,92,604,348,860,220,732,476,988,60,572,316,828,188,700,444,956,124,636,380,892,252,764,508,1020, \ + * 2,514,258,770,130,642,386,898,66,578,322,834,194,706,450,962,34,546,290,802,162,674,418,930,98,610,354,866,226,738,482,994, \ + * 18,530,274,786,146,658,402,914,82,594,338,850,210,722,466,978,50,562,306,818,178,690,434,946,114,626,370,882,242,754,498,1010, \ + * 10,522,266,778,138,650,394,906,74,586,330,842,202,714,458,970,42,554,298,810,170,682,426,938,106,618,362,874,234,746,490,1002, \ + * 26,538,282,794,154,666,410,922,90,602,346,858,218,730,474,986,58,570,314,826,186,698,442,954,122,634,378,890,250,762,506,1018, \ + * 6,518,262,774,134,646,390,902,70,582,326,838,198,710,454,966,38,550,294,806,166,678,422,934,102,614,358,870,230,742,486,998, \ + * 22,534,278,790,150,662,406,918,86,598,342,854,214,726,470,982,54,566,310,822,182,694,438,950,118,630,374,886,246,758,502,1014, \ + * 14,526,270,782,142,654,398,910,78,590,334,846,206,718,462,974,46,558,302,814,174,686,430,942,110,622,366,878,238,750,494,1006, \ + * 30,542,286,798,158,670,414,926,94,606,350,862,222,734,478,990,62,574,318,830,190,702,446,958,126,638,382,894,254,766,510,1022, \ + * 1,513,257,769,129,641,385,897,65,577,321,833,193,705,449,961,33,545,289,801,161,673,417,929,97,609,353,865,225,737,481,993, \ + * 17,529,273,785,145,657,401,913,81,593,337,849,209,721,465,977,49,561,305,817,177,689,433,945,113,625,369,881,241,753,497,1009, \ + * 9,521,265,777,137,649,393,905,73,585,329,841,201,713,457,969,41,553,297,809,169,681,425,937,105,617,361,873,233,745,489,1001, \ + * 25,537,281,793,153,665,409,921,89,601,345,857,217,729,473,985,57,569,313,825,185,697,441,953,121,633,377,889,249,761,505,1017, \ + * 5,517,261,773,133,645,389,901,69,581,325,837,197,709,453,965,37,549,293,805,165,677,421,933,101,613,357,869,229,741,485,997, \ + * 21,533,277,789,149,661,405,917,85,597,341,853,213,725,469,981,53,565,309,821,181,693,437,949,117,629,373,885,245,757,501,1013, \ + * 13,525,269,781,141,653,397,909,77,589,333,845,205,717,461,973,45,557,301,813,173,685,429,941,109,621,365,877,237,749,493,1005, \ + * 29,541,285,797,157,669,413,925,93,605,349,861,221,733,477,989,61,573,317,829,189,701,445,957,125,637,381,893,253,765,509,1021, \ + * 3,515,259,771,131,643,387,899,67,579,323,835,195,707,451,963,35,547,291,803,163,675,419,931,99,611,355,867,227,739,483,995, \ + * 19,531,275,787,147,659,403,915,83,595,339,851,211,723,467,979,51,563,307,819,179,691,435,947,115,627,371,883,243,755,499,1011, \ + * 11,523,267,779,139,651,395,907,75,587,331,843,203,715,459,971,43,555,299,811,171,683,427,939,107,619,363,875,235,747,491,1003, \ + * 27,539,283,795,155,667,411,923,91,603,347,859,219,731,475,987,59,571,315,827,187,699,443,955,123,635,379,891,251,763,507,1019, \ + * 7,519,263,775,135,647,391,903,71,583,327,839,199,711,455,967,39,551,295,807,167,679,423,935,103,615,359,871,231,743,487,999, \ + * 23,535,279,791,151,663,407,919,87,599,343,855,215,727,471,983,55,567,311,823,183,695,439,951,119,631,375,887,247,759,503,1015, \ + * 15,527,271,783,143,655,399,911,79,591,335,847,207,719,463,975,47,559,303,815,175,687,431,943,111,623,367,879,239,751,495,1007, \ + * 31,543,287,799,159,671,415,927,95,607,351,863,223,735,479,991,63,575,319,831,191,703,447,959,127,639,383,895,255,767,511,1023] + * + * n = 1024; q = 12289; mont=2^18 + * g = Mod(7, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) +*/ + +/************************************************************ +* Name: omegas_inv_bitrev_montgomery +* +* Description: Contains inverses of powers of nth root of unity +* in Montgomery domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_omegas_inv_bitrev_montgomery[NEWHOPE_N / 2] = { + 4075, 6974, 4916, 4324, 7210, 3262, 2169, 11767, 3514, 1041, 5925, 11271, 6715, 10316, 11011, 9945, + 1190, 9606, 3818, 6118, 1050, 7753, 8429, 6844, 4449, 6833, 147, 3789, 7540, 6752, 4467, 4789, + 10367, 3879, 2033, 3998, 11316, 1254, 6854, 1359, 3988, 468, 11907, 11973, 8579, 6196, 5446, 6950, + 1987, 10587, 654, 3565, 3199, 12233, 7083, 6760, 6427, 6153, 3643, 6874, 4948, 6152, 11889, 1728, + 7280, 10333, 6008, 11404, 3532, 11286, 241, 12231, 11314, 4212, 8851, 9445, 3477, 6608, 12147, 1105, + 5594, 9260, 5886, 7507, 4213, 11785, 2302, 11684, 8687, 6221, 8209, 421, 7665, 6212, 8689, 3263, + 10710, 431, 9784, 5906, 9450, 8332, 2127, 151, 3174, 52, 1323, 9523, 6415, 11612, 3336, 6234, + 7048, 9369, 4169, 3127, 11279, 6821, 787, 3482, 3445, 4780, 7232, 7591, 7377, 2049, 1321, 192, + 9551, 6421, 5735, 9634, 10596, 9280, 723, 12115, 9364, 347, 1975, 3757, 10431, 7535, 11863, 3315, + 4493, 3202, 5369, 10232, 350, 10777, 6906, 10474, 1483, 6374, 49, 1263, 10706, 6347, 1489, 9789, + 7552, 1293, 4774, 5429, 3772, 418, 6381, 453, 9522, 156, 3969, 3991, 6956, 10258, 10008, 6413, + 8855, 3529, 218, 9381, 9259, 8174, 2361, 10446, 10335, 2051, 9407, 10484, 9842, 6147, 3963, 576, + 6523, 11637, 6099, 11994, 9370, 3762, 8273, 4077, 11964, 1404, 11143, 11341, 1159, 6299, 4049, 8561, + 5961, 7183, 1962, 10695, 9597, 12121, 8960, 7991, 6992, 6170, 10929, 8333, 2555, 6167, 11089, 5184, + 3570, 4240, 11454, 6065, 3150, 10970, 709, 8243, 1058, 8210, 441, 11367, 10331, 7967, 1112, 2078, + 10542, 3123, 5486, 9235, 7856, 6370, 8455, 5257, 9341, 9786, 6507, 10723, 2459, 683, 8633, 64, +}; + +/************************************************************ +* Name: gammas_bitrev_montgomery +* +* Description: Contains powers of nth root of -1 in Montgomery +* domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_bitrev_montgomery[NEWHOPE_N] = { + 4075, 5315, 7965, 7373, 522, 10120, 9027, 5079, 2344, 1278, 1973, 5574, 1018, 6364, 11248, 8775, + 7500, 7822, 5537, 4749, 8500, 12142, 5456, 7840, 5445, 3860, 4536, 11239, 6171, 8471, 2683, 11099, + 10561, 400, 6137, 7341, 5415, 8646, 6136, 5862, 5529, 5206, 56, 9090, 8724, 11635, 1702, 10302, + 5339, 6843, 6093, 3710, 316, 382, 11821, 8301, 10930, 5435, 11035, 973, 8291, 10256, 8410, 1922, + 12097, 10968, 10240, 4912, 4698, 5057, 7509, 8844, 8807, 11502, 5468, 1010, 9162, 8120, 2920, 5241, + 6055, 8953, 677, 5874, 2766, 10966, 12237, 9115, 12138, 10162, 3957, 2839, 6383, 2505, 11858, 1579, + 9026, 3600, 6077, 4624, 11868, 4080, 6068, 3602, 605, 9987, 504, 8076, 4782, 6403, 3029, 6695, + 11184, 142, 5681, 8812, 2844, 3438, 8077, 975, 58, 12048, 1003, 8757, 885, 6281, 1956, 5009, + 12225, 3656, 11606, 9830, 1566, 5782, 2503, 2948, 7032, 3834, 5919, 4433, 3054, 6803, 9166, 1747, + 10211, 11177, 4322, 1958, 922, 11848, 4079, 11231, 4046, 11580, 1319, 9139, 6224, 835, 8049, 8719, + 7105, 1200, 6122, 9734, 3956, 1360, 6119, 5297, 4298, 3329, 168, 2692, 1594, 10327, 5106, 6328, + 3728, 8240, 5990, 11130, 948, 1146, 10885, 325, 8212, 4016, 8527, 2919, 295, 6190, 652, 5766, + 11713, 8326, 6142, 2447, 1805, 2882, 10238, 1954, 1843, 9928, 4115, 3030, 2908, 12071, 8760, 3434, + 5876, 2281, 2031, 5333, 8298, 8320, 12133, 2767, 11836, 5908, 11871, 8517, 6860, 7515, 10996, 4737, + 2500, 10800, 5942, 1583, 11026, 12240, 5915, 10806, 1815, 5383, 1512, 11939, 2057, 6920, 9087, 7796, + 8974, 426, 4754, 1858, 8532, 10314, 11942, 2925, 174, 11566, 3009, 1693, 2655, 6554, 5868, 2738, + 11796, 8193, 9908, 5444, 10911, 1912, 7952, 435, 404, 7644, 11224, 10146, 7012, 11121, 11082, 9041, + 9723, 2187, 9867, 6250, 3646, 9852, 6267, 2987, 8509, 875, 4976, 10682, 8005, 5088, 7278, 11287, + 9223, 27, 3763, 10849, 11272, 7404, 5084, 10657, 8146, 4714, 12047, 10752, 2678, 3704, 545, 7270, + 1067, 5101, 442, 2401, 390, 11516, 3778, 8456, 1045, 9430, 9808, 5012, 9377, 6591, 11935, 4861, + 7852, 3, 3149, 12129, 12176, 4919, 10123, 3915, 3636, 7351, 2704, 5291, 1663, 1777, 1426, 7635, + 1484, 7394, 2780, 7094, 8236, 2645, 7247, 2305, 2847, 7875, 7917, 10115, 10600, 8925, 4057, 3271, + 9273, 243, 9289, 11618, 3136, 5191, 8889, 9890, 11869, 5559, 10111, 10745, 11813, 8758, 4905, 3985, + 9603, 9042, 3978, 9320, 3510, 5332, 9424, 2370, 9405, 11136, 2249, 8241, 10659, 10163, 9103, 6882, + 10810, 1, 5146, 4043, 8155, 5736, 11567, 1305, 1212, 10643, 9094, 5860, 8747, 8785, 8668, 2545, + 4591, 6561, 5023, 6461, 10938, 4978, 6512, 8961, 949, 2625, 2639, 7468, 11726, 2975, 9545, 9283, + 3091, 81, 11289, 7969, 9238, 9923, 2963, 7393, 12149, 1853, 11563, 7678, 8034, 11112, 1635, 9521, + 3201, 3014, 1326, 7203, 1170, 9970, 11334, 790, 3135, 3712, 4846, 2747, 3553, 7484, 11227, 2294, + 11267, 9, 9447, 11809, 11950, 2468, 5791, 11745, 10908, 9764, 8112, 3584, 4989, 5331, 4278, 10616, + 4452, 9893, 8340, 8993, 130, 7935, 9452, 6915, 8541, 11336, 11462, 5767, 7222, 2197, 12171, 9813, + 3241, 729, 3289, 10276, 9408, 3284, 2089, 5092, 11029, 4388, 5755, 7657, 10861, 1696, 2426, 11955, + 4231, 2548, 11934, 3382, 10530, 3707, 3694, 7110, 3637, 8830, 6747, 145, 7399, 5911, 2731, 8357, +}; + +/************************************************************ +* Name: gammas_inv_montgomery +* +* Description: Contains inverses of powers of nth root of -1 +* divided by n in Montgomery domain with R=2^18 +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_gammas_inv_montgomery[NEWHOPE_N] = { + 512, 3944, 4267, 5411, 9615, 5900, 3205, 6063, 9261, 2021, 3087, 4770, 1029, 1590, 343, 530, + 8307, 4273, 2769, 9617, 923, 7302, 4404, 2434, 1468, 9004, 8682, 11194, 2894, 11924, 5061, 8071, + 1687, 10883, 8755, 7724, 11111, 6671, 7800, 6320, 2600, 6203, 4963, 6164, 9847, 6151, 11475, 10243, + 3825, 11607, 1275, 3869, 425, 5386, 4238, 9988, 5509, 11522, 10029, 7937, 3343, 6742, 9307, 10440, + 11295, 3480, 3765, 1160, 1255, 4483, 8611, 9687, 11063, 3229, 7784, 9269, 6691, 7186, 10423, 10588, + 11667, 11722, 3889, 12100, 9489, 12226, 3163, 12268, 9247, 12282, 11275, 4094, 11951, 5461, 8080, 10013, + 10886, 7434, 7725, 2478, 2575, 826, 9051, 8468, 3017, 6919, 5102, 10499, 5797, 7596, 10125, 2532, + 3375, 844, 1125, 8474, 375, 6921, 125, 2307, 4138, 769, 9572, 8449, 7287, 11009, 2429, 7766, + 4906, 6685, 9828, 10421, 3276, 7570, 1092, 10716, 364, 3572, 8314, 5287, 10964, 9955, 7751, 11511, + 6680, 3837, 6323, 1279, 6204, 8619, 2068, 2873, 8882, 5054, 7057, 5781, 10545, 1927, 3515, 8835, + 5268, 2945, 1756, 5078, 8778, 5789, 2926, 6026, 9168, 6105, 3056, 2035, 5115, 8871, 1705, 2957, + 8761, 5082, 11113, 1694, 11897, 4661, 8062, 5650, 10880, 10076, 7723, 7455, 10767, 2485, 3589, 9021, + 9389, 3007, 7226, 9195, 6505, 3065, 10361, 5118, 7550, 1706, 6613, 4665, 10397, 1555, 7562, 8711, + 6617, 7000, 6302, 10526, 6197, 7605, 6162, 2535, 2054, 845, 4781, 4378, 5690, 9652, 5993, 11410, + 6094, 11996, 10224, 8095, 3408, 10891, 1136, 11823, 4475, 3941, 5588, 5410, 5959, 9996, 10179, 3332, + 3393, 5207, 1131, 5832, 377, 1944, 4222, 648, 9600, 216, 3200, 72, 5163, 24, 1721, 8, + 4670, 4099, 5653, 9559, 10077, 11379, 3359, 3793, 5216, 9457, 5835, 11345, 1945, 7878, 8841, 2626, + 2947, 9068, 9175, 7119, 11251, 2373, 11943, 791, 3981, 4360, 1327, 9646, 8635, 11408, 11071, 7899, + 11883, 2633, 3961, 4974, 9513, 1658, 3171, 4649, 1057, 5646, 8545, 1882, 11041, 8820, 11873, 2940, + 8054, 980, 6781, 4423, 10453, 9667, 11677, 11415, 12085, 3805, 12221, 9461, 8170, 7250, 10916, 6513, + 7735, 2171, 10771, 4820, 11783, 5703, 8024, 1901, 6771, 4730, 2257, 5673, 8945, 1891, 7078, 8823, + 10552, 2941, 11710, 9173, 12096, 7154, 4032, 6481, 1344, 10353, 448, 3451, 8342, 9343, 6877, 11307, + 10485, 3769, 3495, 9449, 1165, 7246, 8581, 10608, 11053, 3536, 11877, 5275, 3959, 9951, 5416, 3317, + 9998, 5202, 7429, 1734, 10669, 578, 11749, 4289, 12109, 5526, 12229, 1842, 12269, 614, 8186, 4301, + 6825, 5530, 2275, 10036, 8951, 11538, 7080, 3846, 2360, 1282, 4883, 8620, 5724, 11066, 1908, 7785, + 636, 2595, 212, 865, 4167, 8481, 1389, 2827, 463, 9135, 8347, 3045, 10975, 1015, 11851, 8531, + 12143, 6940, 8144, 10506, 6811, 3502, 10463, 9360, 7584, 3120, 2528, 1040, 4939, 4443, 9839, 1481, + 7376, 4590, 6555, 1530, 2185, 510, 8921, 170, 7070, 4153, 6453, 9577, 2151, 11385, 717, 3795, + 239, 1265, 4176, 4518, 1392, 1506, 464, 502, 4251, 8360, 1417, 6883, 8665, 10487, 11081, 7592, + 7790, 6627, 6693, 2209, 2231, 8929, 4840, 11169, 9806, 3723, 7365, 1241, 2455, 4510, 9011, 9696, + 7100, 3232, 6463, 9270, 10347, 3090, 3449, 1030, 5246, 8536, 5845, 11038, 10141, 11872, 11573, 12150, + 7954, 4050, 10844, 1350, 7711, 450, 10763, 150, 7684, 50, 10754, 4113, 7681, 1371, 10753, 457, +}; diff --git a/crypto_kem/newhope512cpa/clean/reduce.c b/crypto_kem/newhope512cpa/clean/reduce.c new file mode 100644 index 00000000..75d23570 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/reduce.c @@ -0,0 +1,26 @@ +#include "reduce.h" +#include "params.h" + +static const uint32_t qinv = 12287; // -inverse_mod(p,2^18) +static const uint32_t rlog = 18; + +/************************************************* +* Name: verify +* +* Description: Montgomery reduction; given a 32-bit integer a, computes +* 16-bit integer congruent to a * R^-1 mod q, +* where R=2^18 (see value of rlog) +* +* Arguments: - uint32_t a: input unsigned integer to be reduced; has to be in {0,...,1073491968} +* +* Returns: unsigned integer in {0,...,2^14-1} congruent to a * R^-1 modulo q. +**************************************************/ +uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce(uint32_t a) { + uint32_t u; + + u = (a * qinv); + u &= ((1 << rlog) - 1); + u *= NEWHOPE_Q; + a = a + u; + return a >> 18; +} diff --git a/crypto_kem/newhope512cpa/clean/reduce.h b/crypto_kem/newhope512cpa/clean/reduce.h new file mode 100644 index 00000000..d7424375 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/reduce.h @@ -0,0 +1,8 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include + +uint16_t PQCLEAN_NEWHOPE512CPA_CLEAN_montgomery_reduce(uint32_t a); + +#endif diff --git a/crypto_kem/newhope512cpa/clean/verify.c b/crypto_kem/newhope512cpa/clean/verify.c new file mode 100644 index 00000000..449bc219 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/verify.c @@ -0,0 +1,49 @@ +#include "verify.h" +#include +#include + +/************************************************* +* Name: verify +* +* Description: Compare two arrays for equality in constant time. +* +* Arguments: const unsigned char *a: pointer to first byte array +* const unsigned char *b: pointer to second byte array +* size_t len: length of the byte arrays +* +* Returns 0 if the byte arrays are equal, 1 otherwise +**************************************************/ +int PQCLEAN_NEWHOPE512CPA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { + uint64_t r; + size_t i; + r = 0; + + for (i = 0; i < len; i++) { + r |= a[i] ^ b[i]; + } + + r = (-(int64_t)r) >> 63; + return (int)r; +} + +/************************************************* +* Name: cmov +* +* Description: Copy len bytes from x to r if b is 1; +* don't modify x if b is 0. Requires b to be in {0,1}; +* assumes two's complement representation of negative integers. +* Runs in constant time. +* +* Arguments: unsigned char *r: pointer to output byte array +* const unsigned char *x: pointer to input byte array +* size_t len: Amount of bytes to be copied +* unsigned char b: Condition bit; has to be in {0,1} +**************************************************/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/newhope512cpa/clean/verify.h b/crypto_kem/newhope512cpa/clean/verify.h new file mode 100644 index 00000000..64385a42 --- /dev/null +++ b/crypto_kem/newhope512cpa/clean/verify.h @@ -0,0 +1,12 @@ +#ifndef VERIFY_H +#define VERIFY_H + +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +int PQCLEAN_NEWHOPE512CPA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_NEWHOPE512CPA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); + +#endif From 75015226a2aaf0724fb3732c21d7129893cc6cf2 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 8 May 2019 17:38:41 +0200 Subject: [PATCH 07/35] add newhope1024cpa --- crypto_kem/newhope1024cpa/META.yml | 20 + crypto_kem/newhope1024cpa/clean/LICENSE | 1 + crypto_kem/newhope1024cpa/clean/Makefile | 19 + .../clean/Makefile.Microsoft_nmake | 19 + crypto_kem/newhope1024cpa/clean/api.h | 15 + crypto_kem/newhope1024cpa/clean/cpapke.c | 192 +++++++++ crypto_kem/newhope1024cpa/clean/cpapke.h | 16 + crypto_kem/newhope1024cpa/clean/kem.c | 71 ++++ crypto_kem/newhope1024cpa/clean/ntt.c | 127 ++++++ crypto_kem/newhope1024cpa/clean/ntt.h | 14 + crypto_kem/newhope1024cpa/clean/params.h | 25 ++ crypto_kem/newhope1024cpa/clean/poly.c | 370 ++++++++++++++++++ crypto_kem/newhope1024cpa/clean/poly.h | 32 ++ crypto_kem/newhope1024cpa/clean/precomp.c | 261 ++++++++++++ crypto_kem/newhope1024cpa/clean/reduce.c | 26 ++ crypto_kem/newhope1024cpa/clean/reduce.h | 8 + crypto_kem/newhope1024cpa/clean/verify.c | 49 +++ crypto_kem/newhope1024cpa/clean/verify.h | 12 + 18 files changed, 1277 insertions(+) create mode 100644 crypto_kem/newhope1024cpa/META.yml create mode 100644 crypto_kem/newhope1024cpa/clean/LICENSE create mode 100644 crypto_kem/newhope1024cpa/clean/Makefile create mode 100644 crypto_kem/newhope1024cpa/clean/Makefile.Microsoft_nmake create mode 100644 crypto_kem/newhope1024cpa/clean/api.h create mode 100644 crypto_kem/newhope1024cpa/clean/cpapke.c create mode 100644 crypto_kem/newhope1024cpa/clean/cpapke.h create mode 100644 crypto_kem/newhope1024cpa/clean/kem.c create mode 100644 crypto_kem/newhope1024cpa/clean/ntt.c create mode 100644 crypto_kem/newhope1024cpa/clean/ntt.h create mode 100644 crypto_kem/newhope1024cpa/clean/params.h create mode 100644 crypto_kem/newhope1024cpa/clean/poly.c create mode 100644 crypto_kem/newhope1024cpa/clean/poly.h create mode 100644 crypto_kem/newhope1024cpa/clean/precomp.c create mode 100644 crypto_kem/newhope1024cpa/clean/reduce.c create mode 100644 crypto_kem/newhope1024cpa/clean/reduce.h create mode 100644 crypto_kem/newhope1024cpa/clean/verify.c create mode 100644 crypto_kem/newhope1024cpa/clean/verify.h diff --git a/crypto_kem/newhope1024cpa/META.yml b/crypto_kem/newhope1024cpa/META.yml new file mode 100644 index 00000000..5802eecb --- /dev/null +++ b/crypto_kem/newhope1024cpa/META.yml @@ -0,0 +1,20 @@ +name: NewHope1024CPA +type: kem +claimed-nist-level: 5 +length-public-key: 1824 +length-secret-key: 1792 +length-ciphertext: 2176 +length-shared-secret: 32 +nistkat-sha256: f48b42b21a51d7f9325abc5fbda74872d62feaa8cbf818bee87f29bf96630a2f +principal-submitter: Thomas Pöppelmann +auxiliary-submitters: +- Erdem Alkim +- Roberto Avanzi +- Joppe Bos +- Léo Ducas +- Antonio de la Piedra +- Peter Schwabe +- Douglas Stebila +implementations: +- name: clean + version: https://github.com/newhopecrypto/newhope/commit/3fc68c6090b23c56cc190a78af2f43ee8900e9d0 diff --git a/crypto_kem/newhope1024cpa/clean/LICENSE b/crypto_kem/newhope1024cpa/clean/LICENSE new file mode 100644 index 00000000..d5d21fff --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/LICENSE @@ -0,0 +1 @@ +Public Domain diff --git a/crypto_kem/newhope1024cpa/clean/Makefile b/crypto_kem/newhope1024cpa/clean/Makefile new file mode 100644 index 00000000..b4c76fd3 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libnewhope1024cpa_clean.a +HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h +OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/newhope1024cpa/clean/Makefile.Microsoft_nmake b/crypto_kem/newhope1024cpa/clean/Makefile.Microsoft_nmake new file mode 100644 index 00000000..1aa986f0 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libnewhope1024cpa_clean.lib +OBJECTS=cpapke.obj kem.obj ntt.obj poly.obj precomp.obj reduce.obj verify.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/newhope1024cpa/clean/api.h b/crypto_kem/newhope1024cpa/clean/api.h new file mode 100644 index 00000000..683aa8a7 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/api.h @@ -0,0 +1,15 @@ +#ifndef PQCLEAN_NEWHOPE1024CPA_CLEAN_API_H +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_API_H + + +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_CRYPTO_SECRETKEYBYTES 1792 +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_CRYPTO_PUBLICKEYBYTES 1824 +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_CRYPTO_CIPHERTEXTBYTES 2176 +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_CRYPTO_BYTES 32 +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_CRYPTO_ALGNAME "NewHope1024-CPAKEM" + +int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk); +int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk); +int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope1024cpa/clean/cpapke.c b/crypto_kem/newhope1024cpa/clean/cpapke.c new file mode 100644 index 00000000..ec5a5b07 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/cpapke.c @@ -0,0 +1,192 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "poly.h" +#include "randombytes.h" +#include + +/************************************************* +* Name: encode_pk +* +* Description: Serialize the public key as concatenation of the +* serialization of the polynomial pk and the public seed +* used to generete the polynomial a. +* +* Arguments: unsigned char *r: pointer to the output serialized public key +* const poly *pk: pointer to the input public-key polynomial +* const unsigned char *seed: pointer to the input public seed +**************************************************/ +static void encode_pk(unsigned char *r, const poly *pk, const unsigned char *seed) { + int i; + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tobytes(r, pk); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + r[NEWHOPE_POLYBYTES + i] = seed[i]; + } +} + +/************************************************* +* Name: decode_pk +* +* Description: De-serialize the public key; inverse of encode_pk +* +* Arguments: poly *pk: pointer to output public-key polynomial +* unsigned char *seed: pointer to output public seed +* const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_pk(poly *pk, unsigned char *seed, const unsigned char *r) { + int i; + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frombytes(pk, r); + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + seed[i] = r[NEWHOPE_POLYBYTES + i]; + } +} + +/************************************************* +* Name: encode_c +* +* Description: Serialize the ciphertext as concatenation of the +* serialization of the polynomial b and serialization +* of the compressed polynomial v +* +* Arguments: - unsigned char *r: pointer to the output serialized ciphertext +* - const poly *b: pointer to the input polynomial b +* - const poly *v: pointer to the input polynomial v +**************************************************/ +static void encode_c(unsigned char *r, const poly *b, const poly *v) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tobytes(r, b); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_compress(r + NEWHOPE_POLYBYTES, v); +} + +/************************************************* +* Name: decode_c +* +* Description: de-serialize the ciphertext; inverse of encode_c +* +* Arguments: - poly *b: pointer to output polynomial b +* - poly *v: pointer to output polynomial v +* - const unsigned char *r: pointer to input byte array +**************************************************/ +static void decode_c(poly *b, poly *v, const unsigned char *r) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frombytes(b, r); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_decompress(v, r + NEWHOPE_POLYBYTES); +} + +/************************************************* +* Name: gen_a +* +* Description: Deterministically generate public polynomial a from seed +* +* Arguments: - poly *a: pointer to output polynomial a +* - const unsigned char *seed: pointer to input seed +**************************************************/ +static void gen_a(poly *a, const unsigned char *seed) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_uniform(a, seed); +} + + +/************************************************* +* Name: cpapke_keypair +* +* Description: Generates public and private key +* for the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *pk: pointer to output public key +* - unsigned char *sk: pointer to output private key +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk) { + poly ahat, ehat, ahat_shat, bhat, shat; + unsigned char z[2 * NEWHOPE_SYMBYTES]; + unsigned char *publicseed = z; + unsigned char *noiseseed = z + NEWHOPE_SYMBYTES; + + randombytes(z, NEWHOPE_SYMBYTES); + shake256(z, 2 * NEWHOPE_SYMBYTES, z, NEWHOPE_SYMBYTES); + + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(&shat, noiseseed, 0); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_ntt(&shat); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(&ehat, noiseseed, 1); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_ntt(&ehat); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_mul_pointwise(&ahat_shat, &shat, &ahat); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_add(&bhat, &ehat, &ahat_shat); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tobytes(sk, &shat); + encode_pk(pk, &bhat, publicseed); +} + +/************************************************* +* Name: cpapke_enc +* +* Description: Encryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *c: pointer to output ciphertext +* - const unsigned char *m: pointer to input message (of length NEWHOPE_SYMBYTES bytes) +* - const unsigned char *pk: pointer to input public key +* - const unsigned char *coin: pointer to input random coins used as seed +* to deterministically generate all randomness +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coin) { + poly sprime, eprime, vprime, ahat, bhat, eprimeprime, uhat, v; + unsigned char publicseed[NEWHOPE_SYMBYTES]; + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frommsg(&v, m); + + decode_pk(&bhat, publicseed, pk); + gen_a(&ahat, publicseed); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(&sprime, coin, 0); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(&eprime, coin, 1); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(&eprimeprime, coin, 2); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_ntt(&sprime); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_ntt(&eprime); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_mul_pointwise(&uhat, &ahat, &sprime); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_add(&uhat, &uhat, &eprime); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_mul_pointwise(&vprime, &bhat, &sprime); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_invntt(&vprime); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_add(&vprime, &vprime, &eprimeprime); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_add(&vprime, &vprime, &v); // add message + + encode_c(c, &uhat, &vprime); +} + + +/************************************************* +* Name: cpapke_dec +* +* Description: Decryption function of +* the CPA public-key encryption scheme underlying +* the NewHope KEMs +* +* Arguments: - unsigned char *m: pointer to output decrypted message +* - const unsigned char *c: pointer to input ciphertext +* - const unsigned char *sk: pointer to input secret key +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk) { + poly vprime, uhat, tmp, shat; + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frombytes(&shat, sk); + + decode_c(&uhat, &vprime, c); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_mul_pointwise(&tmp, &shat, &uhat); + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_invntt(&tmp); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sub(&tmp, &tmp, &vprime); + + PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tomsg(m, &tmp); +} diff --git a/crypto_kem/newhope1024cpa/clean/cpapke.h b/crypto_kem/newhope1024cpa/clean/cpapke.h new file mode 100644 index 00000000..ea284e10 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/cpapke.h @@ -0,0 +1,16 @@ +#ifndef INDCPA_H +#define INDCPA_H + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_keypair(unsigned char *pk, + unsigned char *sk); + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_enc(unsigned char *c, + const unsigned char *m, + const unsigned char *pk, + const unsigned char *coins); + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_dec(unsigned char *m, + const unsigned char *c, + const unsigned char *sk); + +#endif diff --git a/crypto_kem/newhope1024cpa/clean/kem.c b/crypto_kem/newhope1024cpa/clean/kem.c new file mode 100644 index 00000000..54f5a2f3 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/kem.c @@ -0,0 +1,71 @@ +#include "api.h" +#include "cpapke.h" +#include "fips202.h" +#include "params.h" +#include "randombytes.h" +#include "verify.h" +#include + +/************************************************* +* Name: crypto_kem_keypair +* +* Description: Generates public and private key +* for CCA secure NewHope key encapsulation +* mechanism +* +* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_keypair(pk, sk); /* First put the actual secret key into sk */ + + return 0; +} + +/************************************************* +* Name: crypto_kem_enc +* +* Description: Generates cipher text and shared +* secret for given public key +* +* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { + unsigned char buf[2 * NEWHOPE_SYMBYTES]; + + randombytes(buf, NEWHOPE_SYMBYTES); + + shake256(buf, 2 * NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* Don't release system RNG output */ + + PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_enc(ct, buf, pk, buf + NEWHOPE_SYMBYTES); /* coins are in buf+NEWHOPE_SYMBYTES */ + + shake256(ss, NEWHOPE_SYMBYTES, buf, NEWHOPE_SYMBYTES); /* hash pre-k to ss */ + return 0; +} + + +/************************************************* +* Name: crypto_kem_dec +* +* Description: Generates shared secret for given +* cipher text and private key +* +* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes) +* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes) +* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes) +* +* Returns 0 (success) +**************************************************/ +int PQCLEAN_NEWHOPE1024CPA_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_cpapke_dec(ss, ct, sk); + + shake256(ss, NEWHOPE_SYMBYTES, ss, NEWHOPE_SYMBYTES); /* hash pre-k to ss */ + + return 0; +} diff --git a/crypto_kem/newhope1024cpa/clean/ntt.c b/crypto_kem/newhope1024cpa/clean/ntt.c new file mode 100644 index 00000000..4680c81c --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/ntt.c @@ -0,0 +1,127 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" +#include "reduce.h" + +/************************************************************ +* Name: bitrev_table +* +* Description: Contains bit-reversed 10-bit indices to be used to re-order +* polynomials before number theoratic transform +************************************************************/ +static uint16_t bitrev_table[NEWHOPE_N] = { + 0, 512, 256, 768, 128, 640, 384, 896, 64, 576, 320, 832, 192, 704, 448, 960, 32, 544, 288, 800, 160, 672, 416, 928, 96, 608, 352, 864, 224, 736, 480, 992, + 16, 528, 272, 784, 144, 656, 400, 912, 80, 592, 336, 848, 208, 720, 464, 976, 48, 560, 304, 816, 176, 688, 432, 944, 112, 624, 368, 880, 240, 752, 496, 1008, + 8, 520, 264, 776, 136, 648, 392, 904, 72, 584, 328, 840, 200, 712, 456, 968, 40, 552, 296, 808, 168, 680, 424, 936, 104, 616, 360, 872, 232, 744, 488, 1000, + 24, 536, 280, 792, 152, 664, 408, 920, 88, 600, 344, 856, 216, 728, 472, 984, 56, 568, 312, 824, 184, 696, 440, 952, 120, 632, 376, 888, 248, 760, 504, 1016, + 4, 516, 260, 772, 132, 644, 388, 900, 68, 580, 324, 836, 196, 708, 452, 964, 36, 548, 292, 804, 164, 676, 420, 932, 100, 612, 356, 868, 228, 740, 484, 996, + 20, 532, 276, 788, 148, 660, 404, 916, 84, 596, 340, 852, 212, 724, 468, 980, 52, 564, 308, 820, 180, 692, 436, 948, 116, 628, 372, 884, 244, 756, 500, 1012, + 12, 524, 268, 780, 140, 652, 396, 908, 76, 588, 332, 844, 204, 716, 460, 972, 44, 556, 300, 812, 172, 684, 428, 940, 108, 620, 364, 876, 236, 748, 492, 1004, + 28, 540, 284, 796, 156, 668, 412, 924, 92, 604, 348, 860, 220, 732, 476, 988, 60, 572, 316, 828, 188, 700, 444, 956, 124, 636, 380, 892, 252, 764, 508, 1020, + 2, 514, 258, 770, 130, 642, 386, 898, 66, 578, 322, 834, 194, 706, 450, 962, 34, 546, 290, 802, 162, 674, 418, 930, 98, 610, 354, 866, 226, 738, 482, 994, + 18, 530, 274, 786, 146, 658, 402, 914, 82, 594, 338, 850, 210, 722, 466, 978, 50, 562, 306, 818, 178, 690, 434, 946, 114, 626, 370, 882, 242, 754, 498, 1010, + 10, 522, 266, 778, 138, 650, 394, 906, 74, 586, 330, 842, 202, 714, 458, 970, 42, 554, 298, 810, 170, 682, 426, 938, 106, 618, 362, 874, 234, 746, 490, 1002, + 26, 538, 282, 794, 154, 666, 410, 922, 90, 602, 346, 858, 218, 730, 474, 986, 58, 570, 314, 826, 186, 698, 442, 954, 122, 634, 378, 890, 250, 762, 506, 1018, + 6, 518, 262, 774, 134, 646, 390, 902, 70, 582, 326, 838, 198, 710, 454, 966, 38, 550, 294, 806, 166, 678, 422, 934, 102, 614, 358, 870, 230, 742, 486, 998, + 22, 534, 278, 790, 150, 662, 406, 918, 86, 598, 342, 854, 214, 726, 470, 982, 54, 566, 310, 822, 182, 694, 438, 950, 118, 630, 374, 886, 246, 758, 502, 1014, + 14, 526, 270, 782, 142, 654, 398, 910, 78, 590, 334, 846, 206, 718, 462, 974, 46, 558, 302, 814, 174, 686, 430, 942, 110, 622, 366, 878, 238, 750, 494, 1006, + 30, 542, 286, 798, 158, 670, 414, 926, 94, 606, 350, 862, 222, 734, 478, 990, 62, 574, 318, 830, 190, 702, 446, 958, 126, 638, 382, 894, 254, 766, 510, 1022, + 1, 513, 257, 769, 129, 641, 385, 897, 65, 577, 321, 833, 193, 705, 449, 961, 33, 545, 289, 801, 161, 673, 417, 929, 97, 609, 353, 865, 225, 737, 481, 993, + 17, 529, 273, 785, 145, 657, 401, 913, 81, 593, 337, 849, 209, 721, 465, 977, 49, 561, 305, 817, 177, 689, 433, 945, 113, 625, 369, 881, 241, 753, 497, 1009, + 9, 521, 265, 777, 137, 649, 393, 905, 73, 585, 329, 841, 201, 713, 457, 969, 41, 553, 297, 809, 169, 681, 425, 937, 105, 617, 361, 873, 233, 745, 489, 1001, + 25, 537, 281, 793, 153, 665, 409, 921, 89, 601, 345, 857, 217, 729, 473, 985, 57, 569, 313, 825, 185, 697, 441, 953, 121, 633, 377, 889, 249, 761, 505, 1017, + 5, 517, 261, 773, 133, 645, 389, 901, 69, 581, 325, 837, 197, 709, 453, 965, 37, 549, 293, 805, 165, 677, 421, 933, 101, 613, 357, 869, 229, 741, 485, 997, + 21, 533, 277, 789, 149, 661, 405, 917, 85, 597, 341, 853, 213, 725, 469, 981, 53, 565, 309, 821, 181, 693, 437, 949, 117, 629, 373, 885, 245, 757, 501, 1013, + 13, 525, 269, 781, 141, 653, 397, 909, 77, 589, 333, 845, 205, 717, 461, 973, 45, 557, 301, 813, 173, 685, 429, 941, 109, 621, 365, 877, 237, 749, 493, 1005, + 29, 541, 285, 797, 157, 669, 413, 925, 93, 605, 349, 861, 221, 733, 477, 989, 61, 573, 317, 829, 189, 701, 445, 957, 125, 637, 381, 893, 253, 765, 509, 1021, + 3, 515, 259, 771, 131, 643, 387, 899, 67, 579, 323, 835, 195, 707, 451, 963, 35, 547, 291, 803, 163, 675, 419, 931, 99, 611, 355, 867, 227, 739, 483, 995, + 19, 531, 275, 787, 147, 659, 403, 915, 83, 595, 339, 851, 211, 723, 467, 979, 51, 563, 307, 819, 179, 691, 435, 947, 115, 627, 371, 883, 243, 755, 499, 1011, + 11, 523, 267, 779, 139, 651, 395, 907, 75, 587, 331, 843, 203, 715, 459, 971, 43, 555, 299, 811, 171, 683, 427, 939, 107, 619, 363, 875, 235, 747, 491, 1003, + 27, 539, 283, 795, 155, 667, 411, 923, 91, 603, 347, 859, 219, 731, 475, 987, 59, 571, 315, 827, 187, 699, 443, 955, 123, 635, 379, 891, 251, 763, 507, 1019, + 7, 519, 263, 775, 135, 647, 391, 903, 71, 583, 327, 839, 199, 711, 455, 967, 39, 551, 295, 807, 167, 679, 423, 935, 103, 615, 359, 871, 231, 743, 487, 999, + 23, 535, 279, 791, 151, 663, 407, 919, 87, 599, 343, 855, 215, 727, 471, 983, 55, 567, 311, 823, 183, 695, 439, 951, 119, 631, 375, 887, 247, 759, 503, 1015, + 15, 527, 271, 783, 143, 655, 399, 911, 79, 591, 335, 847, 207, 719, 463, 975, 47, 559, 303, 815, 175, 687, 431, 943, 111, 623, 367, 879, 239, 751, 495, 1007, + 31, 543, 287, 799, 159, 671, 415, 927, 95, 607, 351, 863, 223, 735, 479, 991, 63, 575, 319, 831, 191, 703, 447, 959, 127, 639, 383, 895, 255, 767, 511, 1023 +}; + +/************************************************* +* Name: bitrev_vector +* +* Description: Permutes coefficients of a polynomial into bitreversed order +* +* Arguments: - uint16_t* poly: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_bitrev_vector(uint16_t *poly) { + unsigned int i, r; + uint16_t tmp; + + for (i = 0; i < NEWHOPE_N; i++) { + r = bitrev_table[i]; + if (i < r) { + tmp = poly[i]; + poly[i] = poly[r]; + poly[r] = tmp; + } + } +} + +/************************************************* +* Name: mul_coefficients +* +* Description: Performs pointwise (coefficient-wise) multiplication +* of two polynomials +* Arguments: - uint16_t* poly: pointer to in/output polynomial +* - const uint16_t* factors: pointer to input polynomial, coefficients +* are assumed to be in Montgomery representation +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors) { + unsigned int i; + + for (i = 0; i < NEWHOPE_N; i++) { + poly[i] = PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce((poly[i] * factors[i])); + } +} + + +void /************************************************* +* Name: ntt +* +* Description: Computes number-theoretic transform (NTT) of +* a polynomial in place; inputs assumed to be in +* bitreversed order, output in normal order +* +* Arguments: - uint16_t * a: pointer to in/output polynomial +* - const uint16_t* omega: pointer to input powers of root of unity omega; +* assumed to be in Montgomery domain +**************************************************/ +PQCLEAN_NEWHOPE1024CPA_CLEAN_ntt(uint16_t *a, const uint16_t *omega) { + int i, start, j, jTwiddle, distance; + uint16_t temp, W; + + + for (i = 0; i < 10; i += 2) { + // Even level + distance = (1 << i); + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]); // Omit reduction (be lazy) + a[j + distance] = PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + + // Odd level + distance <<= 1; + for (start = 0; start < distance; start++) { + jTwiddle = 0; + for (j = start; j < NEWHOPE_N - 1; j += 2 * distance) { + W = omega[jTwiddle++]; + temp = a[j]; + a[j] = (temp + a[j + distance]) % NEWHOPE_Q; + a[j + distance] = PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce((W * ((uint32_t)temp + 3 * NEWHOPE_Q - a[j + distance]))); + } + } + } +} diff --git a/crypto_kem/newhope1024cpa/clean/ntt.h b/crypto_kem/newhope1024cpa/clean/ntt.h new file mode 100644 index 00000000..42e41df0 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/ntt.h @@ -0,0 +1,14 @@ +#ifndef NTT_H +#define NTT_H + +#include "inttypes.h" + +extern const uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_omegas_inv_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_bitrev_montgomery[]; +extern const uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_inv_montgomery[]; + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_bitrev_vector(uint16_t *poly); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_mul_coefficients(uint16_t *poly, const uint16_t *factors); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_ntt(uint16_t *a, const uint16_t *omegas); + +#endif diff --git a/crypto_kem/newhope1024cpa/clean/params.h b/crypto_kem/newhope1024cpa/clean/params.h new file mode 100644 index 00000000..64d582b7 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/params.h @@ -0,0 +1,25 @@ +#ifndef PQCLEAN_NEWHOPE1024CPA_CLEAN_PARAMS_H +#define PQCLEAN_NEWHOPE1024CPA_CLEAN_PARAMS_H + +#define NEWHOPE_N 1024 +#define NEWHOPE_Q 12289 +#define NEWHOPE_K 8 /* used in noise sampling */ + +#define NEWHOPE_SYMBYTES 32 /* size of shared key, seeds/coins, and hashes */ + +#define NEWHOPE_POLYBYTES ((14*NEWHOPE_N)/8) +#define NEWHOPE_POLYCOMPRESSEDBYTES (( 3*NEWHOPE_N)/8) + +#define NEWHOPE_CPAPKE_PUBLICKEYBYTES (NEWHOPE_POLYBYTES + NEWHOPE_SYMBYTES) +#define NEWHOPE_CPAPKE_SECRETKEYBYTES (NEWHOPE_POLYBYTES) +#define NEWHOPE_CPAPKE_CIPHERTEXTBYTES (NEWHOPE_POLYBYTES + NEWHOPE_POLYCOMPRESSEDBYTES) + +#define NEWHOPE_CPAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CPAKEM_SECRETKEYBYTES NEWHOPE_CPAPKE_SECRETKEYBYTES +#define NEWHOPE_CPAKEM_CIPHERTEXTBYTES NEWHOPE_CPAPKE_CIPHERTEXTBYTES + +#define NEWHOPE_CCAKEM_PUBLICKEYBYTES NEWHOPE_CPAPKE_PUBLICKEYBYTES +#define NEWHOPE_CCAKEM_SECRETKEYBYTES (NEWHOPE_CPAPKE_SECRETKEYBYTES + NEWHOPE_CPAPKE_PUBLICKEYBYTES + 2*NEWHOPE_SYMBYTES) +#define NEWHOPE_CCAKEM_CIPHERTEXTBYTES (NEWHOPE_CPAPKE_CIPHERTEXTBYTES + NEWHOPE_SYMBYTES) /* Second part is for Targhi-Unruh */ + +#endif diff --git a/crypto_kem/newhope1024cpa/clean/poly.c b/crypto_kem/newhope1024cpa/clean/poly.c new file mode 100644 index 00000000..360e07d7 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/poly.c @@ -0,0 +1,370 @@ +#include "fips202.h" +#include "ntt.h" +#include "poly.h" +#include "reduce.h" + +/************************************************* +* Name: coeff_freeze +* +* Description: Fully reduces an integer modulo q in constant time +* +* Arguments: uint16_t x: input integer to be reduced +* +* Returns integer in {0,...,q-1} congruent to x modulo q +**************************************************/ +static uint16_t coeff_freeze(uint16_t x) { + uint16_t m, r; + int16_t c; + r = x % NEWHOPE_Q; + + m = r - NEWHOPE_Q; + c = m; + c >>= 15; + r = m ^ ((r ^ m)&c); + + return r; +} + +/************************************************* +* Name: flipabs +* +* Description: Computes |(x mod q) - Q/2| +* +* Arguments: uint16_t x: input coefficient +* +* Returns |(x mod q) - Q/2| +**************************************************/ +static uint16_t flipabs(uint16_t x) { + int16_t r, m; + r = coeff_freeze(x); + + r = r - NEWHOPE_Q / 2; + m = r >> 15; + return (r + m) ^ m; +} + +/************************************************* +* Name: poly_frombytes +* +* Description: De-serialization of a polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frombytes(poly *r, const unsigned char *a) { + int i; + for (i = 0; i < NEWHOPE_N / 4; i++) { + r->coeffs[4 * i + 0] = a[7 * i + 0] | (((uint16_t)a[7 * i + 1] & 0x3f) << 8); + r->coeffs[4 * i + 1] = (a[7 * i + 1] >> 6) | (((uint16_t)a[7 * i + 2]) << 2) | (((uint16_t)a[7 * i + 3] & 0x0f) << 10); + r->coeffs[4 * i + 2] = (a[7 * i + 3] >> 4) | (((uint16_t)a[7 * i + 4]) << 4) | (((uint16_t)a[7 * i + 5] & 0x03) << 12); + r->coeffs[4 * i + 3] = (a[7 * i + 5] >> 2) | (((uint16_t)a[7 * i + 6]) << 6); + } +} + +/************************************************* +* Name: poly_tobytes +* +* Description: Serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tobytes(unsigned char *r, const poly *p) { + int i; + uint16_t t0, t1, t2, t3; + for (i = 0; i < NEWHOPE_N / 4; i++) { + t0 = coeff_freeze(p->coeffs[4 * i + 0]); + t1 = coeff_freeze(p->coeffs[4 * i + 1]); + t2 = coeff_freeze(p->coeffs[4 * i + 2]); + t3 = coeff_freeze(p->coeffs[4 * i + 3]); + + r[7 * i + 0] = t0 & 0xff; + r[7 * i + 1] = (unsigned char) ((t0 >> 8) | (t1 << 6)); + r[7 * i + 2] = (unsigned char) ((t1 >> 2)); + r[7 * i + 3] = (unsigned char) ((t1 >> 10) | (t2 << 4)); + r[7 * i + 4] = (unsigned char) ((t2 >> 4)); + r[7 * i + 5] = (unsigned char) ((t2 >> 12) | (t3 << 2)); + r[7 * i + 6] = (unsigned char) ((t3 >> 6)); + } +} + +/************************************************* +* Name: poly_compress +* +* Description: Compression and subsequent serialization of a polynomial +* +* Arguments: - unsigned char *r: pointer to output byte array +* - const poly *p: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_compress(unsigned char *r, const poly *p) { + unsigned int i, j, k = 0; + + uint32_t t[8]; + + for (i = 0; i < NEWHOPE_N; i += 8) { + for (j = 0; j < 8; j++) { + t[j] = coeff_freeze(p->coeffs[i + j]); + t[j] = (((t[j] << 3) + NEWHOPE_Q / 2) / NEWHOPE_Q) & 0x7; + } + + r[k] = (unsigned char) (t[0] | (t[1] << 3) | (t[2] << 6)); + r[k + 1] = (unsigned char) ((t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7)); + r[k + 2] = (unsigned char) ((t[5] >> 1) | (t[6] << 2) | (t[7] << 5)); + k += 3; + } +} + +/************************************************* +* Name: poly_decompress +* +* Description: De-serialization and subsequent decompression of a polynomial; +* approximate inverse of poly_compress +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *a: pointer to input byte array +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_decompress(poly *r, const unsigned char *a) { + unsigned int i, j; + for (i = 0; i < NEWHOPE_N; i += 8) { + r->coeffs[i + 0] = a[0] & 7; + r->coeffs[i + 1] = (a[0] >> 3) & 7; + r->coeffs[i + 2] = (a[0] >> 6) | ((a[1] << 2) & 4); + r->coeffs[i + 3] = (a[1] >> 1) & 7; + r->coeffs[i + 4] = (a[1] >> 4) & 7; + r->coeffs[i + 5] = (a[1] >> 7) | ((a[2] << 1) & 6); + r->coeffs[i + 6] = (a[2] >> 2) & 7; + r->coeffs[i + 7] = (a[2] >> 5); + a += 3; + for (j = 0; j < 8; j++) { + r->coeffs[i + j] = ((uint32_t)r->coeffs[i + j] * NEWHOPE_Q + 4) >> 3; + } + } +} + +/************************************************* +* Name: poly_frommsg +* +* Description: Convert 32-byte message to polynomial +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *msg: pointer to input message +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { + unsigned int i, j, mask; + for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (j = 0; j < 8; j++) { + mask = -((msg[i] >> j) & 1); + r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 256] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 512] = mask & (NEWHOPE_Q / 2); + r->coeffs[8 * i + j + 768] = mask & (NEWHOPE_Q / 2); + } + } +} + +/************************************************* +* Name: poly_tomsg +* +* Description: Convert polynomial to 32-byte message +* +* Arguments: - unsigned char *msg: pointer to output message +* - const poly *x: pointer to input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { + unsigned int i; + uint16_t t; + + for (i = 0; i < 32; i++) { + msg[i] = 0; + } + + for (i = 0; i < 256; i++) { + t = flipabs(x->coeffs[i + 0]); + t += flipabs(x->coeffs[i + 256]); + t += flipabs(x->coeffs[i + 512]); + t += flipabs(x->coeffs[i + 768]); + t = ((t - NEWHOPE_Q)); + + t >>= 15; + msg[i >> 3] |= t << (i & 7); + } +} + +/************************************************* +* Name: poly_uniform +* +* Description: Sample a polynomial deterministically from a seed, +* with output polynomial looking uniformly random +* +* Arguments: - poly *a: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { + unsigned int ctr = 0; + uint16_t val; + uint64_t state[25]; + uint8_t buf[SHAKE128_RATE]; + uint8_t extseed[NEWHOPE_SYMBYTES + 1]; + int i, j; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ + ctr = 0; + extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ + shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + while (ctr < 64) { /* Very unlikely to run more than once */ + shake128_squeezeblocks(buf, 1, state); + for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { + val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); + if (val < 5 * NEWHOPE_Q) { + a->coeffs[i * 64 + ctr] = val; + ctr++; + } + } + } + } +} + +/************************************************* +* Name: hw +* +* Description: Compute the Hamming weight of a byte +* +* Arguments: - unsigned char a: input byte +**************************************************/ +static unsigned char hw(unsigned char a) { + unsigned char i, r = 0; + for (i = 0; i < 8; i++) { + r += (a >> i) & 1; + } + return r; +} + +/************************************************* +* Name: poly_sample +* +* Description: Sample a polynomial deterministically from a seed and a nonce, +* with output polynomial close to centered binomial distribution +* with parameter k=8 +* +* Arguments: - poly *r: pointer to output polynomial +* - const unsigned char *seed: pointer to input seed +* - unsigned char nonce: one-byte input nonce +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { + unsigned char buf[128], a, b; +// uint32_t t, d, a, b, c; + int i, j; + + unsigned char extseed[NEWHOPE_SYMBYTES + 2]; + + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { + extseed[i] = seed[i]; + } + extseed[NEWHOPE_SYMBYTES] = nonce; + + for (i = 0; i < NEWHOPE_N / 64; i++) { /* Generate noise in blocks of 64 coefficients */ + extseed[NEWHOPE_SYMBYTES + 1] = (unsigned char) i; + shake256(buf, 128, extseed, NEWHOPE_SYMBYTES + 2); + for (j = 0; j < 64; j++) { + a = buf[2 * j]; + b = buf[2 * j + 1]; + r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); + /* + t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); + d = 0; + for(k=0;k<8;k++) + d += (t >> k) & 0x01010101; + a = d & 0xff; + b = ((d >> 8) & 0xff); + c = ((d >> 16) & 0xff); + d >>= 24; + r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; + r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; + */ + } + } +} + +/************************************************* +* Name: poly_pointwise +* +* Description: Multiply two polynomials pointwise (i.e., coefficient-wise). +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b) { + int i; + uint16_t t; + for (i = 0; i < NEWHOPE_N; i++) { + t = PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce(3186 * b->coeffs[i]); /* t is now in Montgomery domain */ + r->coeffs[i] = PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce(a->coeffs[i] * t); /* r->coeffs[i] is back in normal domain */ + } +} + +/************************************************* +* Name: poly_add +* +* Description: Add two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_add(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_sub +* +* Description: Subtract two polynomials +* +* Arguments: - poly *r: pointer to output polynomial +* - const poly *a: pointer to first input polynomial +* - const poly *b: pointer to second input polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) { + int i; + for (i = 0; i < NEWHOPE_N; i++) { + r->coeffs[i] = (a->coeffs[i] + 3 * NEWHOPE_Q - b->coeffs[i]) % NEWHOPE_Q; + } +} + +/************************************************* +* Name: poly_ntt +* +* Description: Forward NTT transform of a polynomial in place +* Input is assumed to have coefficients in bitreversed order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_ntt(poly *r) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_bitrev_montgomery); + PQCLEAN_NEWHOPE1024CPA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_bitrev_montgomery); +} + +/************************************************* +* Name: poly_invntt +* +* Description: Inverse NTT transform of a polynomial in place +* Input is assumed to have coefficients in normal order +* Output has coefficients in normal order +* +* Arguments: - poly *r: pointer to in/output polynomial +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_invntt(poly *r) { + PQCLEAN_NEWHOPE1024CPA_CLEAN_bitrev_vector(r->coeffs); + PQCLEAN_NEWHOPE1024CPA_CLEAN_ntt((uint16_t *)r->coeffs, PQCLEAN_NEWHOPE1024CPA_CLEAN_omegas_inv_bitrev_montgomery); + PQCLEAN_NEWHOPE1024CPA_CLEAN_mul_coefficients(r->coeffs, PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_inv_montgomery); +} + diff --git a/crypto_kem/newhope1024cpa/clean/poly.h b/crypto_kem/newhope1024cpa/clean/poly.h new file mode 100644 index 00000000..349d1ed9 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/poly.h @@ -0,0 +1,32 @@ +#ifndef POLY_H +#define POLY_H + +#include "params.h" +#include + +/* + * Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial + * coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1] + */ +typedef struct { + uint16_t coeffs[NEWHOPE_N]; +} poly; + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_add(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_ntt(poly *r); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_invntt(poly *r); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_mul_pointwise(poly *r, const poly *a, const poly *b); + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frombytes(poly *r, const unsigned char *a); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tobytes(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_compress(unsigned char *r, const poly *p); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_decompress(poly *r, const unsigned char *a); + +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x); +void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sub(poly *r, const poly *a, const poly *b); + +#endif diff --git a/crypto_kem/newhope1024cpa/clean/precomp.c b/crypto_kem/newhope1024cpa/clean/precomp.c new file mode 100644 index 00000000..19eda045 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/precomp.c @@ -0,0 +1,261 @@ +#include "inttypes.h" +#include "ntt.h" +#include "params.h" + +/* Precomputed NTT contants generated by Pari/GP script as follows: + * + * For n = 512: + * + * brv = [0,256,128,384,64,320,192,448,32,288,160,416,96,352,224,480,16,272,144,400,80,336,208,464,48,304,176,432,112,368,240,496,8, + * 264,136,392,72,328,200,456,40,296,168,424,104,360,232,488,24,280,152,408,88,344,216,472,56,312,184,440,120,376,248,504,4, + * 260,132,388,68,324,196,452,36,292,164,420,100,356,228,484,20,276,148,404,84,340,212,468,52,308,180,436,116,372,244,500,12, + * 268,140,396,76,332,204,460,44,300,172,428,108,364,236,492,28,284,156,412,92,348,220,476,60,316,188,444,124,380,252,508,2, + * 258,130,386,66,322,194,450,34,290,162,418,98,354,226,482,18,274,146,402,82,338,210,466,50,306,178,434,114,370,242,498,10, + * 266,138,394,74,330,202,458,42,298,170,426,106,362,234,490,26,282,154,410,90,346,218,474,58,314,186,442,122,378,250,506,6, + * 262,134,390,70,326,198,454,38,294,166,422,102,358,230,486,22,278,150,406,86,342,214,470,54,310,182,438,118,374,246,502,14, + * 270,142,398,78,334,206,462,46,302,174,430,110,366,238,494,30,286,158,414,94,350,222,478,62,318,190,446,126,382,254,510,1, + * 257,129,385,65,321,193,449,33,289,161,417,97,353,225,481,17,273,145,401,81,337,209,465,49,305,177,433,113,369,241,497,9, + * 265,137,393,73,329,201,457,41,297,169,425,105,361,233,489,25,281,153,409,89,345,217,473,57,313,185,441,121,377,249,505,5, + * 261,133,389,69,325,197,453,37,293,165,421,101,357,229,485,21,277,149,405,85,341,213,469,53,309,181,437,117,373,245,501,13, + * 269,141,397,77,333,205,461,45,301,173,429,109,365,237,493,29,285,157,413,93,349,221,477,61,317,189,445,125,381,253,509,3, + * 259,131,387,67,323,195,451,35,291,163,419,99,355,227,483,19,275,147,403,83,339,211,467,51,307,179,435,115,371,243,499,11, + * 267,139,395,75,331,203,459,43,299,171,427,107,363,235,491,27,283,155,411,91,347,219,475,59,315,187,443,123,379,251,507,7, + * 263,135,391,71,327,199,455,39,295,167,423,103,359,231,487,23,279,151,407,87,343,215,471,55,311,183,439,119,375,247,503,15, + * 271,143,399,79,335,207,463,47,303,175,431,111,367,239,495,31,287,159,415,95,351,223,479,63,319,191,447,127,383,255,511] + * n = 512; q = 12289; mont=2^18 + * g = Mod(10968, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) + * + * + * For n = 1024: + * + * brv = [0,512,256,768,128,640,384,896,64,576,320,832,192,704,448,960,32,544,288,800,160,672,416,928,96,608,352,864,224,736,480,992, \ + * 16,528,272,784,144,656,400,912,80,592,336,848,208,720,464,976,48,560,304,816,176,688,432,944,112,624,368,880,240,752,496,1008, \ + * 8,520,264,776,136,648,392,904,72,584,328,840,200,712,456,968,40,552,296,808,168,680,424,936,104,616,360,872,232,744,488,1000, \ + * 24,536,280,792,152,664,408,920,88,600,344,856,216,728,472,984,56,568,312,824,184,696,440,952,120,632,376,888,248,760,504,1016, \ + * 4,516,260,772,132,644,388,900,68,580,324,836,196,708,452,964,36,548,292,804,164,676,420,932,100,612,356,868,228,740,484,996, \ + * 20,532,276,788,148,660,404,916,84,596,340,852,212,724,468,980,52,564,308,820,180,692,436,948,116,628,372,884,244,756,500,1012, \ + * 12,524,268,780,140,652,396,908,76,588,332,844,204,716,460,972,44,556,300,812,172,684,428,940,108,620,364,876,236,748,492,1004, \ + * 28,540,284,796,156,668,412,924,92,604,348,860,220,732,476,988,60,572,316,828,188,700,444,956,124,636,380,892,252,764,508,1020, \ + * 2,514,258,770,130,642,386,898,66,578,322,834,194,706,450,962,34,546,290,802,162,674,418,930,98,610,354,866,226,738,482,994, \ + * 18,530,274,786,146,658,402,914,82,594,338,850,210,722,466,978,50,562,306,818,178,690,434,946,114,626,370,882,242,754,498,1010, \ + * 10,522,266,778,138,650,394,906,74,586,330,842,202,714,458,970,42,554,298,810,170,682,426,938,106,618,362,874,234,746,490,1002, \ + * 26,538,282,794,154,666,410,922,90,602,346,858,218,730,474,986,58,570,314,826,186,698,442,954,122,634,378,890,250,762,506,1018, \ + * 6,518,262,774,134,646,390,902,70,582,326,838,198,710,454,966,38,550,294,806,166,678,422,934,102,614,358,870,230,742,486,998, \ + * 22,534,278,790,150,662,406,918,86,598,342,854,214,726,470,982,54,566,310,822,182,694,438,950,118,630,374,886,246,758,502,1014, \ + * 14,526,270,782,142,654,398,910,78,590,334,846,206,718,462,974,46,558,302,814,174,686,430,942,110,622,366,878,238,750,494,1006, \ + * 30,542,286,798,158,670,414,926,94,606,350,862,222,734,478,990,62,574,318,830,190,702,446,958,126,638,382,894,254,766,510,1022, \ + * 1,513,257,769,129,641,385,897,65,577,321,833,193,705,449,961,33,545,289,801,161,673,417,929,97,609,353,865,225,737,481,993, \ + * 17,529,273,785,145,657,401,913,81,593,337,849,209,721,465,977,49,561,305,817,177,689,433,945,113,625,369,881,241,753,497,1009, \ + * 9,521,265,777,137,649,393,905,73,585,329,841,201,713,457,969,41,553,297,809,169,681,425,937,105,617,361,873,233,745,489,1001, \ + * 25,537,281,793,153,665,409,921,89,601,345,857,217,729,473,985,57,569,313,825,185,697,441,953,121,633,377,889,249,761,505,1017, \ + * 5,517,261,773,133,645,389,901,69,581,325,837,197,709,453,965,37,549,293,805,165,677,421,933,101,613,357,869,229,741,485,997, \ + * 21,533,277,789,149,661,405,917,85,597,341,853,213,725,469,981,53,565,309,821,181,693,437,949,117,629,373,885,245,757,501,1013, \ + * 13,525,269,781,141,653,397,909,77,589,333,845,205,717,461,973,45,557,301,813,173,685,429,941,109,621,365,877,237,749,493,1005, \ + * 29,541,285,797,157,669,413,925,93,605,349,861,221,733,477,989,61,573,317,829,189,701,445,957,125,637,381,893,253,765,509,1021, \ + * 3,515,259,771,131,643,387,899,67,579,323,835,195,707,451,963,35,547,291,803,163,675,419,931,99,611,355,867,227,739,483,995, \ + * 19,531,275,787,147,659,403,915,83,595,339,851,211,723,467,979,51,563,307,819,179,691,435,947,115,627,371,883,243,755,499,1011, \ + * 11,523,267,779,139,651,395,907,75,587,331,843,203,715,459,971,43,555,299,811,171,683,427,939,107,619,363,875,235,747,491,1003, \ + * 27,539,283,795,155,667,411,923,91,603,347,859,219,731,475,987,59,571,315,827,187,699,443,955,123,635,379,891,251,763,507,1019, \ + * 7,519,263,775,135,647,391,903,71,583,327,839,199,711,455,967,39,551,295,807,167,679,423,935,103,615,359,871,231,743,487,999, \ + * 23,535,279,791,151,663,407,919,87,599,343,855,215,727,471,983,55,567,311,823,183,695,439,951,119,631,375,887,247,759,503,1015, \ + * 15,527,271,783,143,655,399,911,79,591,335,847,207,719,463,975,47,559,303,815,175,687,431,943,111,623,367,879,239,751,495,1007, \ + * 31,543,287,799,159,671,415,927,95,607,351,863,223,735,479,991,63,575,319,831,191,703,447,959,127,639,383,895,255,767,511,1023] + * + * n = 1024; q = 12289; mont=2^18 + * g = Mod(7, q); + * omegas_inv_bitrev_montgomery = lift(vector(n/2, i, (g^2)^(-brv[2*(i-1)+1])*mont)) + * gammas_bitrev_montgomery = lift(vector(n, i, g^(brv[i])*mont)) + * gammas_inv_montgomery = lift(vector(n, i, g^(-(i-1))/n*mont)) +*/ + + +/************************************************************ +* Name: omegas_inv_bitrev_montgomery +* +* Description: Contains inverses of powers of nth root of unity +* in Montgomery domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_omegas_inv_bitrev_montgomery[NEWHOPE_N / 2] = { + 4075, 5315, 4324, 4916, 10120, 11767, 7210, 9027, 10316, 6715, 1278, 9945, 3514, 11248, 11271, 5925, + 147, 8500, 7840, 6833, 5537, 4749, 4467, 7500, 11099, 9606, 6171, 8471, 8429, 5445, 11239, 7753, + 9090, 12233, 5529, 5206, 10587, 1987, 11635, 3565, 5415, 8646, 6153, 6427, 7341, 6152, 10561, 400, + 8410, 1922, 2033, 8291, 1359, 6854, 11035, 973, 8579, 6093, 6950, 5446, 11821, 8301, 11907, 316, + 52, 3174, 10966, 9523, 6055, 8953, 11612, 6415, 2505, 5906, 10710, 11858, 8332, 9450, 10162, 151, + 3482, 787, 5468, 1010, 4169, 9162, 5241, 9369, 7509, 8844, 7232, 4698, 192, 1321, 10240, 4912, + 885, 6281, 10333, 7280, 8757, 11286, 58, 12048, 12147, 11184, 8812, 6608, 2844, 3438, 4212, 11314, + 8687, 6068, 421, 8209, 3600, 3263, 7665, 6077, 7507, 5886, 3029, 6695, 4213, 504, 11684, 2302, + 1962, 1594, 6328, 7183, 168, 2692, 8960, 4298, 5184, 11089, 6122, 9734, 10929, 3956, 5297, 6170, + 3762, 9370, 4016, 4077, 6523, 652, 11994, 6099, 1146, 11341, 11964, 10885, 6299, 1159, 8240, 8561, + 11177, 2078, 10331, 4322, 11367, 441, 4079, 11231, 3150, 1319, 8243, 709, 8049, 8719, 11454, 6224, + 3054, 6803, 3123, 10542, 4433, 6370, 7032, 3834, 8633, 12225, 9830, 683, 1566, 5782, 9786, 9341, + 12115, 723, 3009, 1693, 5735, 2655, 2738, 6421, 11942, 2925, 1975, 8532, 3315, 11863, 4754, 1858, + 1583, 6347, 2500, 10800, 6374, 1483, 12240, 1263, 1815, 5383, 10777, 350, 6920, 10232, 4493, 9087, + 8855, 8760, 9381, 218, 9928, 10446, 9259, 4115, 6147, 9842, 8326, 576, 10335, 10238, 10484, 9407, + 6381, 11836, 8517, 418, 6860, 7515, 1293, 7552, 2767, 156, 8298, 8320, 10008, 5876, 5333, 10258, + 10115, 4372, 2847, 7875, 8232, 9018, 8925, 1689, 8236, 2645, 5042, 9984, 7094, 9509, 1484, 7394, + 3, 4437, 160, 3149, 113, 7370, 10123, 3915, 6998, 2704, 8653, 4938, 1426, 7635, 10512, 1663, + 6957, 3510, 2370, 2865, 3978, 9320, 3247, 9603, 6882, 3186, 10659, 10163, 1153, 9405, 8241, 10040, + 2178, 1544, 5559, 420, 8304, 4905, 476, 3531, 5191, 9153, 2399, 8889, 3000, 671, 243, 3016, + 3763, 10849, 12262, 9223, 10657, 7205, 11272, 7404, 7575, 8146, 10752, 242, 2678, 3704, 11744, 5019, + 3833, 3778, 11899, 773, 5101, 11222, 9888, 442, 2912, 5698, 11935, 4861, 7277, 9808, 11244, 2859, + 3780, 11414, 4976, 10682, 7201, 8005, 11287, 5011, 6267, 2987, 2437, 3646, 2566, 10102, 9867, 6250, + 5444, 2381, 11796, 8193, 4337, 11854, 1912, 1378, 404, 7644, 1065, 2143, 11121, 5277, 3248, 11082, + 2548, 8058, 8907, 11934, 1759, 8582, 3694, 7110, 12144, 6747, 8652, 3459, 2731, 8357, 6378, 7399, + 10861, 1696, 9863, 334, 7657, 6534, 11029, 4388, 11560, 3241, 10276, 9000, 9408, 3284, 10200, 7197, + 6498, 544, 2468, 339, 11267, 9, 2842, 480, 5331, 7300, 1673, 4278, 4177, 8705, 9764, 1381, + 7837, 2396, 8340, 8993, 4354, 130, 6915, 2837, 11462, 5767, 953, 8541, 9813, 118, 7222, 2197, + 3006, 9545, 563, 9314, 2625, 11340, 4821, 2639, 7266, 5828, 6561, 7698, 3328, 6512, 1351, 7311, + 6553, 8155, 1305, 722, 5146, 4043, 12288, 10810, 2545, 3621, 8747, 8785, 1646, 1212, 5860, 3195, + 7203, 10963, 3201, 3014, 955, 11499, 9970, 11119, 3135, 3712, 7443, 9542, 7484, 8736, 9995, 11227, + 1635, 9521, 1177, 8034, 140, 10436, 11563, 7678, 4320, 11289, 9198, 12208, 2963, 7393, 2366, 9238 +}; + +/************************************************************ +* Name: gammas_bitrev_montgomery +* +* Description: Contains powers of nth root of -1 in Montgomery +* domain with R=2^18 in bit-reversed order +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_bitrev_montgomery[NEWHOPE_N] = { + 4075, 6974, 7373, 7965, 3262, 5079, 522, 2169, 6364, 1018, 1041, 8775, 2344, 11011, 5574, 1973, + 4536, 1050, 6844, 3860, 3818, 6118, 2683, 1190, 4789, 7822, 7540, 6752, 5456, 4449, 3789, 12142, + 11973, 382, 3988, 468, 6843, 5339, 6196, 3710, 11316, 1254, 5435, 10930, 3998, 10256, 10367, 3879, + 11889, 1728, 6137, 4948, 5862, 6136, 3643, 6874, 8724, 654, 10302, 1702, 7083, 6760, 56, 3199, + 9987, 605, 11785, 8076, 5594, 9260, 6403, 4782, 6212, 4624, 9026, 8689, 4080, 11868, 6221, 3602, + 975, 8077, 8851, 9445, 5681, 3477, 1105, 142, 241, 12231, 1003, 3532, 5009, 1956, 6008, 11404, + 7377, 2049, 10968, 12097, 7591, 5057, 3445, 4780, 2920, 7048, 3127, 8120, 11279, 6821, 11502, 8807, + 12138, 2127, 2839, 3957, 431, 1579, 6383, 9784, 5874, 677, 3336, 6234, 2766, 1323, 9115, 12237, + 2031, 6956, 6413, 2281, 3969, 3991, 12133, 9522, 4737, 10996, 4774, 5429, 11871, 3772, 453, 5908, + 2882, 1805, 2051, 1954, 11713, 3963, 2447, 6142, 8174, 3030, 1843, 2361, 12071, 2908, 3529, 3434, + 3202, 7796, 2057, 5369, 11939, 1512, 6906, 10474, 11026, 49, 10806, 5915, 1489, 9789, 5942, 10706, + 10431, 7535, 426, 8974, 3757, 10314, 9364, 347, 5868, 9551, 9634, 6554, 10596, 9280, 11566, 174, + 2948, 2503, 6507, 10723, 11606, 2459, 64, 3656, 8455, 5257, 5919, 7856, 1747, 9166, 5486, 9235, + 6065, 835, 3570, 4240, 11580, 4046, 10970, 9139, 1058, 8210, 11848, 922, 7967, 1958, 10211, 1112, + 3728, 4049, 11130, 5990, 1404, 325, 948, 11143, 6190, 295, 11637, 5766, 8212, 8273, 2919, 8527, + 6119, 6992, 8333, 1360, 2555, 6167, 1200, 7105, 7991, 3329, 9597, 12121, 5106, 5961, 10695, 10327, + 3051, 9923, 4896, 9326, 81, 3091, 1000, 7969, 4611, 726, 1853, 12149, 4255, 11112, 2768, 10654, + 1062, 2294, 3553, 4805, 2747, 4846, 8577, 9154, 1170, 2319, 790, 11334, 9275, 9088, 1326, 5086, + 9094, 6429, 11077, 10643, 3504, 3542, 8668, 9744, 1479, 1, 8246, 7143, 11567, 10984, 4134, 5736, + 4978, 10938, 5777, 8961, 4591, 5728, 6461, 5023, 9650, 7468, 949, 9664, 2975, 11726, 2744, 9283, + 10092, 5067, 12171, 2476, 3748, 11336, 6522, 827, 9452, 5374, 12159, 7935, 3296, 3949, 9893, 4452, + 10908, 2525, 3584, 8112, 8011, 10616, 4989, 6958, 11809, 9447, 12280, 1022, 11950, 9821, 11745, 5791, + 5092, 2089, 9005, 2881, 3289, 2013, 9048, 729, 7901, 1260, 5755, 4632, 11955, 2426, 10593, 1428, + 4890, 5911, 3932, 9558, 8830, 3637, 5542, 145, 5179, 8595, 3707, 10530, 355, 3382, 4231, 9741, + 1207, 9041, 7012, 1168, 10146, 11224, 4645, 11885, 10911, 10377, 435, 7952, 4096, 493, 9908, 6845, + 6039, 2422, 2187, 9723, 8643, 9852, 9302, 6022, 7278, 1002, 4284, 5088, 1607, 7313, 875, 8509, + 9430, 1045, 2481, 5012, 7428, 354, 6591, 9377, 11847, 2401, 1067, 7188, 11516, 390, 8511, 8456, + 7270, 545, 8585, 9611, 12047, 1537, 4143, 4714, 4885, 1017, 5084, 1632, 3066, 27, 1440, 8526, + 9273, 12046, 11618, 9289, 3400, 9890, 3136, 7098, 8758, 11813, 7384, 3985, 11869, 6730, 10745, 10111, + 2249, 4048, 2884, 11136, 2126, 1630, 9103, 5407, 2686, 9042, 2969, 8311, 9424, 9919, 8779, 5332, + 10626, 1777, 4654, 10863, 7351, 3636, 9585, 5291, 8374, 2166, 4919, 12176, 9140, 12129, 7852, 12286, + 4895, 10805, 2780, 5195, 2305, 7247, 9644, 4053, 10600, 3364, 3271, 4057, 4414, 9442, 7917, 2174, + 3947, 11951, 2455, 6599, 10545, 10975, 3654, 2894, 7681, 7126, 7287, 12269, 4119, 3343, 2151, 1522, + 7174, 7350, 11041, 2442, 2148, 5959, 6492, 8330, 8945, 5598, 3624, 10397, 1325, 6565, 1945, 11260, + 10077, 2674, 3338, 3276, 11034, 506, 6505, 1392, 5478, 8778, 1178, 2776, 3408, 10347, 11124, 2575, + 9489, 12096, 6092, 10058, 4167, 6085, 923, 11251, 11912, 4578, 10669, 11914, 425, 10453, 392, 10104, + 8464, 4235, 8761, 7376, 2291, 3375, 7954, 8896, 6617, 7790, 1737, 11667, 3982, 9342, 6680, 636, + 6825, 7383, 512, 4670, 2900, 12050, 7735, 994, 1687, 11883, 7021, 146, 10485, 1403, 5189, 6094, + 2483, 2054, 3042, 10945, 3981, 10821, 11826, 8882, 8151, 180, 9600, 7684, 5219, 10880, 6780, 204, + 11232, 2600, 7584, 3121, 3017, 11053, 7814, 7043, 4251, 4739, 11063, 6771, 7073, 9261, 2360, 11925, + 1928, 11825, 8024, 3678, 3205, 3359, 11197, 5209, 8581, 3238, 8840, 1136, 9363, 1826, 3171, 4489, + 7885, 346, 2068, 1389, 8257, 3163, 4840, 6127, 8062, 8921, 612, 4238, 10763, 8067, 125, 11749, + 10125, 5416, 2110, 716, 9839, 10584, 11475, 11873, 3448, 343, 1908, 4538, 10423, 7078, 4727, 1208, + 11572, 3589, 2982, 1373, 1721, 10753, 4103, 2429, 4209, 5412, 5993, 9011, 438, 3515, 7228, 1218, + 8347, 5232, 8682, 1327, 7508, 4924, 448, 1014, 10029, 12221, 4566, 5836, 12229, 2717, 1535, 3200, + 5588, 5845, 412, 5102, 7326, 3744, 3056, 2528, 7406, 8314, 9202, 6454, 6613, 1417, 10032, 7784, + 1518, 3765, 4176, 5063, 9828, 2275, 6636, 4267, 6463, 2065, 7725, 3495, 8328, 8755, 8144, 10533, + 5966, 12077, 9175, 9520, 5596, 6302, 8400, 579, 6781, 11014, 5734, 11113, 11164, 4860, 1131, 10844, + 9068, 8016, 9694, 3837, 567, 9348, 7000, 6627, 7699, 5082, 682, 11309, 5207, 4050, 7087, 844, + 7434, 3769, 293, 9057, 6940, 9344, 10883, 2633, 8190, 3944, 5530, 5604, 3480, 2171, 9282, 11024, + 2213, 8136, 3805, 767, 12239, 216, 11520, 6763, 10353, 7, 8566, 845, 7235, 3154, 4360, 3285, + 10268, 2832, 3572, 1282, 7559, 3229, 8360, 10583, 6105, 3120, 6643, 6203, 8536, 8348, 6919, 3536, + 9199, 10891, 11463, 5043, 1658, 5618, 8787, 5789, 4719, 751, 11379, 6389, 10783, 3065, 7806, 6586, + 2622, 5386, 510, 7628, 6921, 578, 10345, 11839, 8929, 4684, 12226, 7154, 9916, 7302, 8481, 3670, + 11066, 2334, 1590, 7878, 10734, 1802, 1891, 5103, 6151, 8820, 3418, 7846, 9951, 4693, 417, 9996, + 9652, 4510, 2946, 5461, 365, 881, 1927, 1015, 11675, 11009, 1371, 12265, 2485, 11385, 5039, 6742, + 8449, 1842, 12217, 8176, 9577, 4834, 7937, 9461, 2643, 11194, 3045, 6508, 4094, 3451, 7911, 11048, + 5406, 4665, 3020, 6616, 11345, 7519, 3669, 5287, 1790, 7014, 5410, 11038, 11249, 2035, 6125, 10407, + 4565, 7315, 5078, 10506, 2840, 2478, 9270, 4194, 9195, 4518, 7469, 1160, 6878, 2730, 10421, 10036, + 1734, 3815, 10939, 5832, 10595, 10759, 4423, 8420, 9617, 7119, 11010, 11424, 9173, 189, 10080, 10526, + 3466, 10588, 7592, 3578, 11511, 7785, 9663, 530, 12150, 8957, 2532, 3317, 9349, 10243, 1481, 9332, + 3454, 3758, 7899, 4218, 2593, 11410, 2276, 982, 6513, 1849, 8494, 9021, 4523, 7988, 8, 457, + 648, 150, 8000, 2307, 2301, 874, 5650, 170, 9462, 2873, 9855, 11498, 2535, 11169, 5808, 12268, + 9687, 1901, 7171, 11787, 3846, 1573, 6063, 3793, 466, 11259, 10608, 3821, 6320, 4649, 6263, 2929 +}; + +/************************************************************ +* Name: gammas_inv_montgomery +* +* Description: Contains inverses of powers of nth root of -1 +* divided by n in Montgomery domain with R=2^18 +************************************************************/ +const uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_gammas_inv_montgomery[NEWHOPE_N] = { + 256, 10570, 1510, 7238, 1034, 7170, 6291, 7921, 11665, 3422, 4000, 2327, 2088, 5565, 795, 10647, + 1521, 5484, 2539, 7385, 1055, 7173, 8047, 11683, 1669, 1994, 3796, 5809, 4341, 9398, 11876, 12230, + 10525, 12037, 12253, 3506, 4012, 9351, 4847, 2448, 7372, 9831, 3160, 2207, 5582, 2553, 7387, 6322, + 9681, 1383, 10731, 1533, 219, 5298, 4268, 7632, 6357, 9686, 8406, 4712, 9451, 10128, 4958, 5975, + 11387, 8649, 11769, 6948, 11526, 12180, 1740, 10782, 6807, 2728, 7412, 4570, 4164, 4106, 11120, 12122, + 8754, 11784, 3439, 5758, 11356, 6889, 9762, 11928, 1704, 1999, 10819, 12079, 12259, 7018, 11536, 1648, + 1991, 2040, 2047, 2048, 10826, 12080, 8748, 8272, 8204, 1172, 1923, 7297, 2798, 7422, 6327, 4415, + 7653, 6360, 11442, 12168, 7005, 8023, 9924, 8440, 8228, 2931, 7441, 1063, 3663, 5790, 9605, 10150, + 1450, 8985, 11817, 10466, 10273, 12001, 3470, 7518, 1074, 1909, 7295, 9820, 4914, 702, 5367, 7789, + 8135, 9940, 1420, 3714, 11064, 12114, 12264, 1752, 5517, 9566, 11900, 1700, 3754, 5803, 829, 1874, + 7290, 2797, 10933, 5073, 7747, 8129, 6428, 6185, 11417, 1631, 233, 5300, 9535, 10140, 11982, 8734, + 8270, 2937, 10953, 8587, 8249, 2934, 9197, 4825, 5956, 4362, 9401, 1343, 3703, 529, 10609, 12049, + 6988, 6265, 895, 3639, 4031, 4087, 4095, 585, 10617, 8539, 4731, 4187, 9376, 3095, 9220, 10095, + 10220, 1460, 10742, 12068, 1724, 5513, 11321, 6884, 2739, 5658, 6075, 4379, 11159, 10372, 8504, 4726, + 9453, 3106, 7466, 11600, 10435, 8513, 9994, 8450, 9985, 3182, 10988, 8592, 2983, 9204, 4826, 2445, + 5616, 6069, 867, 3635, 5786, 11360, 5134, 2489, 10889, 12089, 1727, 7269, 2794, 9177, 1311, 5454, + 9557, 6632, 2703, 9164, 10087, 1441, 3717, 531, 3587, 2268, 324, 5313, 759, 1864, 5533, 2546, + 7386, 9833, 8427, 4715, 11207, 1601, 7251, 4547, 11183, 12131, 1733, 10781, 10318, 1474, 10744, 5046, + 4232, 11138, 10369, 6748, 964, 7160, 4534, 7670, 8118, 8182, 4680, 11202, 6867, 981, 8918, 1274, + 182, 26, 7026, 8026, 11680, 12202, 10521, 1503, 7237, 4545, 5916, 9623, 8397, 11733, 10454, 3249, + 9242, 6587, 941, 1890, 270, 10572, 6777, 9746, 6659, 6218, 6155, 6146, 878, 1881, 7291, 11575, + 12187, 1741, 7271, 8061, 11685, 6936, 4502, 9421, 4857, 4205, 7623, 1089, 10689, 1527, 8996, 10063, + 11971, 10488, 6765, 2722, 3900, 9335, 11867, 6962, 11528, 5158, 4248, 4118, 5855, 2592, 5637, 6072, + 2623, 7397, 8079, 9932, 4930, 5971, 853, 3633, 519, 8852, 11798, 3441, 11025, 1575, 225, 8810, + 11792, 12218, 3501, 9278, 3081, 9218, 4828, 7712, 8124, 11694, 12204, 3499, 4011, 573, 3593, 5780, + 7848, 9899, 10192, 1456, 208, 7052, 2763, 7417, 11593, 10434, 12024, 8740, 11782, 10461, 3250, 5731, + 7841, 9898, 1414, 202, 3540, 7528, 2831, 2160, 10842, 5060, 4234, 4116, 588, 84, 12, 7024, + 2759, 9172, 6577, 11473, 1639, 9012, 3043, 7457, 6332, 11438, 1634, 1989, 9062, 11828, 8712, 11778, + 12216, 10523, 6770, 9745, 10170, 4964, 9487, 6622, 946, 8913, 6540, 6201, 4397, 9406, 8366, 9973, + 8447, 8229, 11709, 8695, 10020, 3187, 5722, 2573, 10901, 6824, 4486, 4152, 9371, 8361, 2950, 2177, + 311, 1800, 9035, 8313, 11721, 3430, 490, 70, 10, 1757, 251, 3547, 7529, 11609, 3414, 7510, + 4584, 4166, 9373, 1339, 5458, 7802, 11648, 1664, 7260, 9815, 10180, 6721, 9738, 10169, 8475, 8233, + 9954, 1422, 8981, 1283, 5450, 11312, 1616, 3742, 11068, 10359, 4991, 713, 3613, 9294, 8350, 4704, + 672, 96, 7036, 9783, 11931, 3460, 5761, 823, 10651, 12055, 10500, 1500, 5481, 783, 3623, 11051, + 8601, 8251, 8201, 11705, 10450, 5004, 4226, 7626, 2845, 2162, 3820, 7568, 9859, 3164, 452, 10598, + 1514, 5483, 6050, 6131, 4387, 7649, 8115, 6426, 918, 8909, 8295, 1185, 5436, 11310, 8638, 1234, + 5443, 11311, 5127, 2488, 2111, 10835, 5059, 7745, 2862, 3920, 560, 80, 1767, 2008, 3798, 11076, + 6849, 2734, 10924, 12094, 8750, 1250, 10712, 6797, 971, 7161, 1023, 8924, 4786, 7706, 4612, 4170, + 7618, 6355, 4419, 5898, 11376, 10403, 10264, 6733, 4473, 639, 5358, 2521, 9138, 3061, 5704, 4326, + 618, 5355, 765, 5376, 768, 7132, 4530, 9425, 3102, 9221, 6584, 11474, 10417, 10266, 12000, 6981, + 6264, 4406, 2385, 7363, 4563, 4163, 7617, 9866, 3165, 9230, 11852, 10471, 5007, 5982, 11388, 5138, + 734, 3616, 11050, 12112, 6997, 11533, 12181, 10518, 12036, 3475, 2252, 7344, 9827, 4915, 9480, 6621, + 4457, 7659, 9872, 6677, 4465, 4149, 7615, 4599, 657, 3605, 515, 10607, 6782, 4480, 640, 1847, + 3775, 5806, 2585, 5636, 9583, 1369, 10729, 8555, 10000, 11962, 5220, 7768, 8132, 8184, 9947, 1421, + 203, 29, 8782, 11788, 1684, 10774, 10317, 4985, 9490, 8378, 4708, 11206, 5112, 5997, 7879, 11659, + 12199, 8765, 10030, 4944, 5973, 6120, 6141, 6144, 7900, 11662, 1666, 238, 34, 3516, 5769, 9602, + 8394, 9977, 6692, 956, 10670, 6791, 9748, 11926, 8726, 11780, 5194, 742, 106, 8793, 10034, 3189, + 10989, 5081, 4237, 5872, 4350, 2377, 10873, 6820, 6241, 11425, 10410, 10265, 3222, 5727, 9596, 4882, + 2453, 2106, 3812, 11078, 12116, 5242, 4260, 11142, 8614, 11764, 12214, 5256, 4262, 4120, 11122, 5100, + 11262, 5120, 2487, 5622, 9581, 8391, 8221, 2930, 10952, 12098, 6995, 6266, 9673, 4893, 699, 3611, + 4027, 5842, 11368, 1624, 232, 8811, 8281, 1183, 169, 8802, 3013, 2186, 5579, 797, 3625, 4029, + 11109, 1587, 7249, 11569, 8675, 6506, 2685, 10917, 12093, 12261, 12285, 1755, 7273, 1039, 1904, 272, + 3550, 9285, 3082, 5707, 6082, 4380, 7648, 11626, 5172, 4250, 9385, 8363, 8217, 4685, 5936, 848, + 8899, 6538, 934, 1889, 3781, 9318, 10109, 10222, 6727, 961, 5404, 772, 5377, 9546, 8386, 1198, + 8949, 3034, 2189, 7335, 4559, 5918, 2601, 10905, 5069, 9502, 3113, 7467, 8089, 11689, 5181, 9518, + 8382, 2953, 3933, 4073, 4093, 7607, 8109, 2914, 5683, 4323, 11151, 1593, 10761, 6804, 972, 3650, + 2277, 5592, 4310, 7638, 9869, 4921, 703, 1856, 9043, 4803, 9464, 1352, 8971, 11815, 5199, 7765, + 6376, 4422, 7654, 2849, 407, 8836, 6529, 7955, 2892, 9191, 1313, 10721, 12065, 12257, 1751, 9028, + 8312, 2943, 2176, 3822, 546, 78, 8789, 11789, 10462, 12028, 6985, 4509, 9422, 1346, 5459, 4291, + 613, 10621, 6784, 9747, 3148, 7472, 2823, 5670, 810, 7138, 8042, 4660, 7688, 6365, 6176, 6149, + 2634, 5643, 9584, 10147, 11983, 5223, 9524, 11894, 10477, 8519, 1217, 3685, 2282, 326, 10580, 3267, + 7489, 4581, 2410, 5611, 11335, 6886, 8006, 8166, 11700, 3427, 11023, 8597, 10006, 3185, 455, 65, + 5276, 7776, 4622, 5927, 7869, 9902, 11948, 5218, 2501, 5624, 2559, 10899, 1557, 1978, 10816, 10323, + 8497, 4725, 675, 1852, 10798, 12076, 10503, 3256, 9243, 3076, 2195, 10847, 12083, 10504, 12034, 10497 +}; + diff --git a/crypto_kem/newhope1024cpa/clean/reduce.c b/crypto_kem/newhope1024cpa/clean/reduce.c new file mode 100644 index 00000000..f975bf92 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/reduce.c @@ -0,0 +1,26 @@ +#include "reduce.h" +#include "params.h" + +static const uint32_t qinv = 12287; // -inverse_mod(p,2^18) +static const uint32_t rlog = 18; + +/************************************************* +* Name: verify +* +* Description: Montgomery reduction; given a 32-bit integer a, computes +* 16-bit integer congruent to a * R^-1 mod q, +* where R=2^18 (see value of rlog) +* +* Arguments: - uint32_t a: input unsigned integer to be reduced; has to be in {0,...,1073491968} +* +* Returns: unsigned integer in {0,...,2^14-1} congruent to a * R^-1 modulo q. +**************************************************/ +uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce(uint32_t a) { + uint32_t u; + + u = (a * qinv); + u &= ((1 << rlog) - 1); + u *= NEWHOPE_Q; + a = a + u; + return a >> 18; +} diff --git a/crypto_kem/newhope1024cpa/clean/reduce.h b/crypto_kem/newhope1024cpa/clean/reduce.h new file mode 100644 index 00000000..724e20fe --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/reduce.h @@ -0,0 +1,8 @@ +#ifndef REDUCE_H +#define REDUCE_H + +#include + +uint16_t PQCLEAN_NEWHOPE1024CPA_CLEAN_montgomery_reduce(uint32_t a); + +#endif diff --git a/crypto_kem/newhope1024cpa/clean/verify.c b/crypto_kem/newhope1024cpa/clean/verify.c new file mode 100644 index 00000000..53276b93 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/verify.c @@ -0,0 +1,49 @@ +#include "verify.h" +#include +#include + +/************************************************* +* Name: verify +* +* Description: Compare two arrays for equality in constant time. +* +* Arguments: const unsigned char *a: pointer to first byte array +* const unsigned char *b: pointer to second byte array +* size_t len: length of the byte arrays +* +* Returns 0 if the byte arrays are equal, 1 otherwise +**************************************************/ +int PQCLEAN_NEWHOPE1024CPA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) { + uint64_t r; + size_t i; + r = 0; + + for (i = 0; i < len; i++) { + r |= a[i] ^ b[i]; + } + + r = (-(int64_t)r) >> 63; + return (int)r; +} + +/************************************************* +* Name: cmov +* +* Description: Copy len bytes from x to r if b is 1; +* don't modify x if b is 0. Requires b to be in {0,1}; +* assumes two's complement representation of negative integers. +* Runs in constant time. +* +* Arguments: unsigned char *r: pointer to output byte array +* const unsigned char *x: pointer to input byte array +* size_t len: Amount of bytes to be copied +* unsigned char b: Condition bit; has to be in {0,1} +**************************************************/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) { + size_t i; + + b = -b; + for (i = 0; i < len; i++) { + r[i] ^= b & (x[i] ^ r[i]); + } +} diff --git a/crypto_kem/newhope1024cpa/clean/verify.h b/crypto_kem/newhope1024cpa/clean/verify.h new file mode 100644 index 00000000..9cdd0e95 --- /dev/null +++ b/crypto_kem/newhope1024cpa/clean/verify.h @@ -0,0 +1,12 @@ +#ifndef VERIFY_H +#define VERIFY_H + +#include + +/* returns 0 for equal strings, 1 for non-equal strings */ +int PQCLEAN_NEWHOPE1024CPA_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len); + +/* b = 1 means mov, b = 0 means don't mov*/ +void PQCLEAN_NEWHOPE1024CPA_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b); + +#endif From 1597e625146b66cf07bb0ecf3980101b2754bdfb Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 13 May 2019 13:17:41 +0200 Subject: [PATCH 08/35] add IND-CPA/IND-CCA2 security field to METADATA. add test for it as well --- CONTRIBUTING.md | 1 + crypto_kem/frodokem1344aes/META.yml | 1 + crypto_kem/frodokem1344shake/META.yml | 1 + crypto_kem/frodokem640aes/META.yml | 1 + crypto_kem/frodokem640shake/META.yml | 1 + crypto_kem/frodokem976aes/META.yml | 1 + crypto_kem/frodokem976shake/META.yml | 1 + crypto_kem/kyber1024/META.yml | 1 + crypto_kem/kyber512/META.yml | 1 + crypto_kem/kyber768/META.yml | 1 + crypto_kem/ntruhps2048509/META.yml | 1 + crypto_kem/ntruhps2048677/META.yml | 1 + crypto_kem/ntruhps4096821/META.yml | 1 + crypto_kem/ntruhrss701/META.yml | 1 + test/test_metadata.py | 5 +++++ 15 files changed, 19 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64f29fe7..f7ab30e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,6 +25,7 @@ See the section [API](#API) below. name: Name type: claimed-nist-level: + claimed-security: IND-CPA/IND-CCA2 # KEM only length-public-key: # KEM and signature length-secret-key: # KEM and signature length-ciphertext: # KEM only diff --git a/crypto_kem/frodokem1344aes/META.yml b/crypto_kem/frodokem1344aes/META.yml index cd6b1991..98528881 100644 --- a/crypto_kem/frodokem1344aes/META.yml +++ b/crypto_kem/frodokem1344aes/META.yml @@ -1,6 +1,7 @@ name: FrodoKEM-1344-AES type: kem claimed-nist-level: 5 +claimed-security: IND-CCA2 length-public-key: 21520 length-secret-key: 43088 length-ciphertext: 21632 diff --git a/crypto_kem/frodokem1344shake/META.yml b/crypto_kem/frodokem1344shake/META.yml index 5048603b..534d3f43 100644 --- a/crypto_kem/frodokem1344shake/META.yml +++ b/crypto_kem/frodokem1344shake/META.yml @@ -1,6 +1,7 @@ name: FrodoKEM-1344-SHAKE type: kem claimed-nist-level: 5 +claimed-security: IND-CCA2 length-public-key: 21520 length-secret-key: 43088 length-ciphertext: 21632 diff --git a/crypto_kem/frodokem640aes/META.yml b/crypto_kem/frodokem640aes/META.yml index 44861a47..a4932688 100644 --- a/crypto_kem/frodokem640aes/META.yml +++ b/crypto_kem/frodokem640aes/META.yml @@ -1,6 +1,7 @@ name: FrodoKEM-640-AES type: kem claimed-nist-level: 1 +claimed-security: IND-CCA2 length-public-key: 9616 length-secret-key: 19888 length-ciphertext: 9720 diff --git a/crypto_kem/frodokem640shake/META.yml b/crypto_kem/frodokem640shake/META.yml index db07a8c7..99e685c5 100644 --- a/crypto_kem/frodokem640shake/META.yml +++ b/crypto_kem/frodokem640shake/META.yml @@ -1,6 +1,7 @@ name: FrodoKEM-640-SHAKE type: kem claimed-nist-level: 1 +claimed-security: IND-CCA2 length-public-key: 9616 length-secret-key: 19888 length-ciphertext: 9720 diff --git a/crypto_kem/frodokem976aes/META.yml b/crypto_kem/frodokem976aes/META.yml index 526cc315..78f277b1 100644 --- a/crypto_kem/frodokem976aes/META.yml +++ b/crypto_kem/frodokem976aes/META.yml @@ -1,6 +1,7 @@ name: FrodoKEM-976-AES type: kem claimed-nist-level: 3 +claimed-security: IND-CCA2 length-public-key: 15632 length-secret-key: 31296 length-ciphertext: 15744 diff --git a/crypto_kem/frodokem976shake/META.yml b/crypto_kem/frodokem976shake/META.yml index 181043a8..35c9c8a8 100644 --- a/crypto_kem/frodokem976shake/META.yml +++ b/crypto_kem/frodokem976shake/META.yml @@ -1,6 +1,7 @@ name: FrodoKEM-976-SHAKE type: kem claimed-nist-level: 3 +claimed-security: IND-CCA2 length-public-key: 15632 length-secret-key: 31296 length-ciphertext: 15744 diff --git a/crypto_kem/kyber1024/META.yml b/crypto_kem/kyber1024/META.yml index 5055cd57..e2ab2a5a 100644 --- a/crypto_kem/kyber1024/META.yml +++ b/crypto_kem/kyber1024/META.yml @@ -1,6 +1,7 @@ name: Kyber1024 type: kem claimed-nist-level: 5 +claimed-security: IND-CCA2 length-public-key: 1568 length-ciphertext: 1568 length-secret-key: 3168 diff --git a/crypto_kem/kyber512/META.yml b/crypto_kem/kyber512/META.yml index 47148557..b5e7455a 100644 --- a/crypto_kem/kyber512/META.yml +++ b/crypto_kem/kyber512/META.yml @@ -1,6 +1,7 @@ name: Kyber512 type: kem claimed-nist-level: 1 +claimed-security: IND-CCA2 length-public-key: 800 length-ciphertext: 736 length-secret-key: 1632 diff --git a/crypto_kem/kyber768/META.yml b/crypto_kem/kyber768/META.yml index 2d8a309e..2efae031 100644 --- a/crypto_kem/kyber768/META.yml +++ b/crypto_kem/kyber768/META.yml @@ -1,6 +1,7 @@ name: Kyber768 type: kem claimed-nist-level: 3 +claimed-security: IND-CCA2 length-public-key: 1184 length-ciphertext: 1088 length-secret-key: 2400 diff --git a/crypto_kem/ntruhps2048509/META.yml b/crypto_kem/ntruhps2048509/META.yml index a3a4c1ba..f05a94ac 100644 --- a/crypto_kem/ntruhps2048509/META.yml +++ b/crypto_kem/ntruhps2048509/META.yml @@ -1,6 +1,7 @@ name: ntru-hps2048509 type: kem claimed-nist-level: 1 +claimed-security: IND-CCA2 length-public-key: 699 length-secret-key: 935 length-ciphertext: 699 diff --git a/crypto_kem/ntruhps2048677/META.yml b/crypto_kem/ntruhps2048677/META.yml index d80ff7b8..be3a3d67 100644 --- a/crypto_kem/ntruhps2048677/META.yml +++ b/crypto_kem/ntruhps2048677/META.yml @@ -1,6 +1,7 @@ name: ntru-hps2048677 type: kem claimed-nist-level: 3 +claimed-security: IND-CCA2 length-public-key: 930 length-secret-key: 1234 length-ciphertext: 930 diff --git a/crypto_kem/ntruhps4096821/META.yml b/crypto_kem/ntruhps4096821/META.yml index 308b7cd0..15f072c9 100644 --- a/crypto_kem/ntruhps4096821/META.yml +++ b/crypto_kem/ntruhps4096821/META.yml @@ -1,6 +1,7 @@ name: ntru-hps4096821 type: kem claimed-nist-level: 5 +claimed-security: IND-CCA2 length-public-key: 1230 length-secret-key: 1590 length-ciphertext: 1230 diff --git a/crypto_kem/ntruhrss701/META.yml b/crypto_kem/ntruhrss701/META.yml index e5b53e09..aa389d75 100644 --- a/crypto_kem/ntruhrss701/META.yml +++ b/crypto_kem/ntruhrss701/META.yml @@ -1,6 +1,7 @@ name: ntru-hrss701 type: kem claimed-nist-level: 3 +claimed-security: IND-CCA2 length-public-key: 1138 length-secret-key: 1450 length-ciphertext: 1138 diff --git a/test/test_metadata.py b/test/test_metadata.py index a19a6148..472b92b8 100644 --- a/test/test_metadata.py +++ b/test/test_metadata.py @@ -62,6 +62,7 @@ EXPECTED_FIELDS = { } KEM_FIELDS = { + 'claimed-security' : {'type' : str, 'values' : ['IND-CPA', 'IND-CCA2'] }, 'length-ciphertext': {'type': int, 'min': 1}, 'length-shared-secret': {'type': int, 'min': 1}, 'nistkat-sha256': {'type': str, 'length': 64}, @@ -123,6 +124,10 @@ def check_element(field, element, props): raise ValueError("Value of field '{}' should be length {}" " but was length {}" .format(field, props['length'], actual_len)) + if 'values' in props and element not in props['values']: + raise ValueError("'{}' should be in {}" + .format(element, props['values'])) + if type_ == list: # recursively check the elements for el in element: From 6659ba1d9cb0b4d594349f97dbc88c3000677507 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 13 May 2019 13:30:01 +0200 Subject: [PATCH 09/35] add IND-CPA/IND-CCA2 flag to newhope --- crypto_kem/newhope1024cca/META.yml | 1 + crypto_kem/newhope1024cpa/META.yml | 5 +++-- crypto_kem/newhope512cca/META.yml | 1 + crypto_kem/newhope512cpa/META.yml | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/crypto_kem/newhope1024cca/META.yml b/crypto_kem/newhope1024cca/META.yml index 39a20392..2912288a 100644 --- a/crypto_kem/newhope1024cca/META.yml +++ b/crypto_kem/newhope1024cca/META.yml @@ -1,6 +1,7 @@ name: NewHope1024CCA type: kem claimed-nist-level: 5 +claimed-security: IND-CCA2 length-public-key: 1824 length-secret-key: 3680 length-ciphertext: 2208 diff --git a/crypto_kem/newhope1024cpa/META.yml b/crypto_kem/newhope1024cpa/META.yml index 5802eecb..43dfa5f9 100644 --- a/crypto_kem/newhope1024cpa/META.yml +++ b/crypto_kem/newhope1024cpa/META.yml @@ -1,11 +1,12 @@ name: NewHope1024CPA type: kem claimed-nist-level: 5 -length-public-key: 1824 +claimed-security: IND-CPA +length-public-key: 1824 length-secret-key: 1792 length-ciphertext: 2176 length-shared-secret: 32 -nistkat-sha256: f48b42b21a51d7f9325abc5fbda74872d62feaa8cbf818bee87f29bf96630a2f +nistkat-sha256: f48b42b21a51d7f9325abc5fbda74872d62feaa8cbf818bee87f29bf96630a2f principal-submitter: Thomas Pöppelmann auxiliary-submitters: - Erdem Alkim diff --git a/crypto_kem/newhope512cca/META.yml b/crypto_kem/newhope512cca/META.yml index d35d9630..721dfa78 100644 --- a/crypto_kem/newhope512cca/META.yml +++ b/crypto_kem/newhope512cca/META.yml @@ -1,6 +1,7 @@ name: NewHope512CCA type: kem claimed-nist-level: 1 +claimed-security: IND-CCA2 length-public-key: 928 length-secret-key: 1888 length-ciphertext: 1120 diff --git a/crypto_kem/newhope512cpa/META.yml b/crypto_kem/newhope512cpa/META.yml index 8db17433..695f4be9 100644 --- a/crypto_kem/newhope512cpa/META.yml +++ b/crypto_kem/newhope512cpa/META.yml @@ -1,11 +1,12 @@ name: NewHope512CPA type: kem claimed-nist-level: 1 +claimed-security: IND-CPA length-public-key: 928 length-secret-key: 896 length-ciphertext: 1088 length-shared-secret: 32 -nistkat-sha256: 42444446b96f45c9b7221c4fde8afd5dfc0b3c2ff05b9a88ff12ea3949fbb76c +nistkat-sha256: 42444446b96f45c9b7221c4fde8afd5dfc0b3c2ff05b9a88ff12ea3949fbb76c principal-submitter: Thomas Pöppelmann auxiliary-submitters: - Erdem Alkim From 951f7a082430b64dff84df4c1846efc3e574148a Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 16 May 2019 11:20:18 +0200 Subject: [PATCH 10/35] check nist kats for signatures. resolves #169 --- CONTRIBUTING.md | 2 +- crypto_sign/mqdss-48/META.yml | 1 + crypto_sign/mqdss-64/META.yml | 1 + .../sphincs-haraka-128f-robust/META.yml | 1 + .../sphincs-haraka-128f-simple/META.yml | 1 + .../sphincs-haraka-128s-robust/META.yml | 1 + .../sphincs-haraka-128s-simple/META.yml | 1 + .../sphincs-haraka-192f-robust/META.yml | 1 + .../sphincs-haraka-192f-simple/META.yml | 1 + .../sphincs-haraka-192s-robust/META.yml | 1 + .../sphincs-haraka-192s-simple/META.yml | 1 + .../sphincs-haraka-256f-robust/META.yml | 1 + .../sphincs-haraka-256f-simple/META.yml | 1 + .../sphincs-haraka-256s-robust/META.yml | 1 + .../sphincs-haraka-256s-simple/META.yml | 1 + .../sphincs-sha256-128f-robust/META.yml | 1 + .../sphincs-sha256-128f-simple/META.yml | 1 + .../sphincs-sha256-128s-robust/META.yml | 1 + .../sphincs-sha256-128s-simple/META.yml | 1 + .../sphincs-sha256-192f-robust/META.yml | 1 + .../sphincs-sha256-192f-simple/META.yml | 1 + .../sphincs-sha256-192s-robust/META.yml | 1 + .../sphincs-sha256-192s-simple/META.yml | 1 + .../sphincs-sha256-256f-robust/META.yml | 1 + .../sphincs-sha256-256f-simple/META.yml | 1 + .../sphincs-sha256-256s-robust/META.yml | 1 + .../sphincs-sha256-256s-simple/META.yml | 1 + .../sphincs-shake256-128f-robust/META.yml | 1 + .../sphincs-shake256-128f-simple/META.yml | 1 + .../sphincs-shake256-128s-robust/META.yml | 1 + .../sphincs-shake256-128s-simple/META.yml | 1 + .../sphincs-shake256-192f-robust/META.yml | 1 + .../sphincs-shake256-192f-simple/META.yml | 1 + .../sphincs-shake256-192s-robust/META.yml | 1 + .../sphincs-shake256-192s-simple/META.yml | 1 + .../sphincs-shake256-256f-robust/META.yml | 1 + .../sphincs-shake256-256f-simple/META.yml | 1 + .../sphincs-shake256-256s-robust/META.yml | 1 + .../sphincs-shake256-256s-simple/META.yml | 1 + test/crypto_sign/nistkat.c | 102 ++++++++++++++++++ test/test_metadata.py | 2 +- test/test_nistkat.py | 2 - 42 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 test/crypto_sign/nistkat.c diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f7ab30e0..eaa4b9e5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -31,7 +31,7 @@ See the section [API](#API) below. length-ciphertext: # KEM only length-shared-secret: # KEM only length-signature: # Signature only - nistkat-sha256: sha256sum of 1st NIST KAT test case # KEM only + nistkat-sha256: sha256sum of 1st NIST KAT test case # KEM and signature testvectors-sha256: sha256sum of output of testvectors # Signature only principal-submitter: Eve auxiliary-submitters: diff --git a/crypto_sign/mqdss-48/META.yml b/crypto_sign/mqdss-48/META.yml index 4c34eaa7..ab9154f5 100644 --- a/crypto_sign/mqdss-48/META.yml +++ b/crypto_sign/mqdss-48/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 46 length-secret-key: 16 length-signature: 20854 +nistkat-sha256: 0a3754ebeb4bc41118b488c2b46499f6652398e83cb0d6eaf2929dbfd33fc8d7 testvectors-sha256: 3350a80ccf4316b32ef13060fca8880d6802b7e61150fd36f021d1c52d8edb98 principal-submitter: Simona Samardjiska auxiliary-submitters: diff --git a/crypto_sign/mqdss-64/META.yml b/crypto_sign/mqdss-64/META.yml index 6d6ba9a8..88df82fc 100644 --- a/crypto_sign/mqdss-64/META.yml +++ b/crypto_sign/mqdss-64/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 64 length-secret-key: 24 length-signature: 43728 +nistkat-sha256: 2a50f067babbf4a3eed5197e87820472944d1d79fc03b1d9322a8ad8c245501e testvectors-sha256: 1edd33ca64b14f60f153b84dd25c7064cfa9b7dbf1bb5c4296f343377cb0c864 principal-submitter: Simona Samardjiska auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-128f-robust/META.yml b/crypto_sign/sphincs-haraka-128f-robust/META.yml index d79ca253..b40b21a4 100644 --- a/crypto_sign/sphincs-haraka-128f-robust/META.yml +++ b/crypto_sign/sphincs-haraka-128f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 16976 +nistkat-sha256: 4d04dcfa1ed0dcbe0af382fe1925b5031a279811f9fea298d64a9fe8eaaf2165 testvectors-sha256: f0f84722cf529a108006d84b52966cbebd92146ee33cacdd7d1bba2cdc1944fd principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-128f-simple/META.yml b/crypto_sign/sphincs-haraka-128f-simple/META.yml index f7783474..76e4075c 100644 --- a/crypto_sign/sphincs-haraka-128f-simple/META.yml +++ b/crypto_sign/sphincs-haraka-128f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 16976 +nistkat-sha256: 82967bdf0188ff7c6c6f5723798d3e3ec17679123f2df9c6b572ec3c0b3ffd65 testvectors-sha256: b9ea5703411a79c215a2643862bf4924ff62eeec08a0d1e328e39f47417fec8f principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-128s-robust/META.yml b/crypto_sign/sphincs-haraka-128s-robust/META.yml index 4d28ab3b..a35dd309 100644 --- a/crypto_sign/sphincs-haraka-128s-robust/META.yml +++ b/crypto_sign/sphincs-haraka-128s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 8080 +nistkat-sha256: 78c68bae7ab635195b41807bd8a6e89f740d762d5b2a7022550cb34cc79cf3b3 testvectors-sha256: a7057ca5ce0d7f01d1c1aabe474f8449796b051becbc8b148a78c84893193fcf principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-128s-simple/META.yml b/crypto_sign/sphincs-haraka-128s-simple/META.yml index d9907683..e15be027 100644 --- a/crypto_sign/sphincs-haraka-128s-simple/META.yml +++ b/crypto_sign/sphincs-haraka-128s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 8080 +nistkat-sha256: dbded19fb5983657e93d047c61ebb0069ea7f5afb928463a308fa44f792429d4 testvectors-sha256: fcc816e14d200e212b4b955d3011f5a6b61240c7c0003e17acb1bf396ca5d4ad principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-192f-robust/META.yml b/crypto_sign/sphincs-haraka-192f-robust/META.yml index a893346f..04c60bb6 100644 --- a/crypto_sign/sphincs-haraka-192f-robust/META.yml +++ b/crypto_sign/sphincs-haraka-192f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 35664 +nistkat-sha256: 195f00a8c88110b333c30de6d672265d89a19d1991c107aeebe06759dfde33fc testvectors-sha256: a88d3adbeb5c1805a90e506c93f5000b266d1227f1621c0f77adf75bdbe4ba02 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-192f-simple/META.yml b/crypto_sign/sphincs-haraka-192f-simple/META.yml index c0473ea7..3d24628c 100644 --- a/crypto_sign/sphincs-haraka-192f-simple/META.yml +++ b/crypto_sign/sphincs-haraka-192f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 35664 +nistkat-sha256: b6050873b334c67aeb7e3e3148f39479ffeab4e8c3b3481983abc44278904984 testvectors-sha256: d054d5394d578057e8264c5ef8a33627fcf194a25270a1dc6c2d7de86408876d principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-192s-robust/META.yml b/crypto_sign/sphincs-haraka-192s-robust/META.yml index 81e2ed43..3f895cba 100644 --- a/crypto_sign/sphincs-haraka-192s-robust/META.yml +++ b/crypto_sign/sphincs-haraka-192s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 17064 +nistkat-sha256: c59a79130d012b6c25546e57d6d9bb080e2721a40c71e27077bd5b793d96cbe5 testvectors-sha256: 5dd40c8ea9a81ad93e0685843ec1cabdcb6eec9f6e64fc01d928ebaf7cf377c6 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-192s-simple/META.yml b/crypto_sign/sphincs-haraka-192s-simple/META.yml index d13213bd..c81fdbac 100644 --- a/crypto_sign/sphincs-haraka-192s-simple/META.yml +++ b/crypto_sign/sphincs-haraka-192s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 17064 +nistkat-sha256: 1e0b5aefda28f48fb8c4e81a0294e689211616f0748a9d9daf37be9e76b5141a testvectors-sha256: 7e50b92ec85e31260326092a62e84d2f12df84213a494d0f0527125a5e6b7ed7 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-256f-robust/META.yml b/crypto_sign/sphincs-haraka-256f-robust/META.yml index 69b7ba18..900d7e2f 100644 --- a/crypto_sign/sphincs-haraka-256f-robust/META.yml +++ b/crypto_sign/sphincs-haraka-256f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 49216 +nistkat-sha256: c2d6cebdf902e168ad27d8a942b36bc6909ea643e0f2b9ab78fd474dbdc0d373 testvectors-sha256: b5e3a1c1dbb45751f2a4c9323a5d900b30f38e4c7e2943e234a5b9526de1146c principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-256f-simple/META.yml b/crypto_sign/sphincs-haraka-256f-simple/META.yml index a8decdf1..8831e1c1 100644 --- a/crypto_sign/sphincs-haraka-256f-simple/META.yml +++ b/crypto_sign/sphincs-haraka-256f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 49216 +nistkat-sha256: a848b318c46f1c0a6932fd5102ca4bab43bb3c4692f97b2ee97c9e9bdbd5de36 testvectors-sha256: 3cddd379bf490efac9a8aefaa9b59e7f70fe96bb177a8bfc404f99bfc2172aee principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-256s-robust/META.yml b/crypto_sign/sphincs-haraka-256s-robust/META.yml index 5bb978d9..8b155a56 100644 --- a/crypto_sign/sphincs-haraka-256s-robust/META.yml +++ b/crypto_sign/sphincs-haraka-256s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 29792 +nistkat-sha256: 0a57c7fba38bcf56fde765a89da296ae99fda745f96845adda54b4f8fe76b6c6 testvectors-sha256: feb4f482dd5ab66dd09f2e5e02175e7109de4385da5704f78cc1dac074368c56 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-haraka-256s-simple/META.yml b/crypto_sign/sphincs-haraka-256s-simple/META.yml index fee133e2..7c6987fd 100644 --- a/crypto_sign/sphincs-haraka-256s-simple/META.yml +++ b/crypto_sign/sphincs-haraka-256s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 29792 +nistkat-sha256: a65476425ff1a68c5d6f941fecaec6e6c00be10695f6cfff15047875bcd5f490 testvectors-sha256: 25fcc82aa371d06c8b494c2d0a3ac4920cfb8134bef9962491669ef2c6a0b820 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-128f-robust/META.yml b/crypto_sign/sphincs-sha256-128f-robust/META.yml index a352f117..44b52785 100644 --- a/crypto_sign/sphincs-sha256-128f-robust/META.yml +++ b/crypto_sign/sphincs-sha256-128f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 16976 +nistkat-sha256: cf7935fc0277099a7453f6c5dc54e40d5cf34fbe989909940a77a3fbbab6c42e testvectors-sha256: 3e7c782b25e405940160468c2d777a5ab6eb9b6cfe318efed257f3270cca8c72 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-128f-simple/META.yml b/crypto_sign/sphincs-sha256-128f-simple/META.yml index b0520b3c..ab82adba 100644 --- a/crypto_sign/sphincs-sha256-128f-simple/META.yml +++ b/crypto_sign/sphincs-sha256-128f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 16976 +nistkat-sha256: 4375bc4276fa44654979db0da886ba5cf754011db268fc63fa7584d50f5dfb63 testvectors-sha256: 5ce16422e028eb7a6198d0a276a1760a6bbcd4ba9457ddbbfd5e08f34985c0ce principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-128s-robust/META.yml b/crypto_sign/sphincs-sha256-128s-robust/META.yml index 7f85adfd..afe78608 100644 --- a/crypto_sign/sphincs-sha256-128s-robust/META.yml +++ b/crypto_sign/sphincs-sha256-128s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 8080 +nistkat-sha256: 4ddcad5141217340f9f28afdcf25cc236d7975bcfb41b39660e84568a9a461fe testvectors-sha256: 29d6d0dd732078d177779a61b7654bbe59fcf2ecb9bcd2ade8391791a6570a63 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-128s-simple/META.yml b/crypto_sign/sphincs-sha256-128s-simple/META.yml index 2f2e6b53..fd7f29ed 100644 --- a/crypto_sign/sphincs-sha256-128s-simple/META.yml +++ b/crypto_sign/sphincs-sha256-128s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 8080 +nistkat-sha256: 8ae7a91b321cd18bd855710eea9d13deea1a53bb7858baee5f77d0237d1897eb testvectors-sha256: edf1b76246ac560558d7938f8ac7bbf820f1e697ef4f5b5e1962f04fadb84a76 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-192f-robust/META.yml b/crypto_sign/sphincs-sha256-192f-robust/META.yml index 8ede894f..dacf29d1 100644 --- a/crypto_sign/sphincs-sha256-192f-robust/META.yml +++ b/crypto_sign/sphincs-sha256-192f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 35664 +nistkat-sha256: 9d0898cb264172c31d0fb4901dd56d46728e83e0bf008abccb8b0912c2ebbc52 testvectors-sha256: ca61e66c0377fd367ab0c920d2190855a64348668a336d300ec7f2c72e721be4 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-192f-simple/META.yml b/crypto_sign/sphincs-sha256-192f-simple/META.yml index 22134e40..bd15076f 100644 --- a/crypto_sign/sphincs-sha256-192f-simple/META.yml +++ b/crypto_sign/sphincs-sha256-192f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 35664 +nistkat-sha256: 306fef951d07b17b27c67ffe9e63185ae5d5fde87619b76872a3ca969299d47c testvectors-sha256: b25e0f2560f500d8988809522c72ea3ab0f81be52476a6cdf9d05a890a2d2ce0 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-192s-robust/META.yml b/crypto_sign/sphincs-sha256-192s-robust/META.yml index 72efa7d9..8c25156d 100644 --- a/crypto_sign/sphincs-sha256-192s-robust/META.yml +++ b/crypto_sign/sphincs-sha256-192s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 17064 +nistkat-sha256: 23374b2ece45c8ec7272473d70eb424894324702616b8456343dbd79f109b675 testvectors-sha256: 1be5c30de6d0b856b1b51f0ff50a2acf9c3a359ee2178004e153bdfc50a68832 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-192s-simple/META.yml b/crypto_sign/sphincs-sha256-192s-simple/META.yml index 53a29b4f..ebd07554 100644 --- a/crypto_sign/sphincs-sha256-192s-simple/META.yml +++ b/crypto_sign/sphincs-sha256-192s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 17064 +nistkat-sha256: 02b192ff93bc8977a80e9efc8fa6814ae85c2ad939f7185a959b428c1eb77150 testvectors-sha256: ee413e410a29274a9647b9440d6a554670e0f9587efaaddedf82e4923f68f80e principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-256f-robust/META.yml b/crypto_sign/sphincs-sha256-256f-robust/META.yml index 996632a5..ca697970 100644 --- a/crypto_sign/sphincs-sha256-256f-robust/META.yml +++ b/crypto_sign/sphincs-sha256-256f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 49216 +nistkat-sha256: e6fafb97dc3575d5dcd79183a4d7faad4f2c986745c63e61ddae3648559664f7 testvectors-sha256: 14dd19ba3ff75bad890949050289ab0f178d7baa6dcb8ff6bcd6a873692a5686 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-256f-simple/META.yml b/crypto_sign/sphincs-sha256-256f-simple/META.yml index 0a52e059..af6c695f 100644 --- a/crypto_sign/sphincs-sha256-256f-simple/META.yml +++ b/crypto_sign/sphincs-sha256-256f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 49216 +nistkat-sha256: 88fa150041ce9c305a971cef8ec444881afc14c4590637fa4b91c1deb15bb215 testvectors-sha256: b4755edf8351c51225921af38a724d2bd9ff9f3afe4ae2abbc3a59763ecc897d principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-256s-robust/META.yml b/crypto_sign/sphincs-sha256-256s-robust/META.yml index f4ab2c23..68d01b3a 100644 --- a/crypto_sign/sphincs-sha256-256s-robust/META.yml +++ b/crypto_sign/sphincs-sha256-256s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 29792 +nistkat-sha256: da28ff350ac552f100b35b01ecb494dc02f9dcf542fa2d88439cd427985e9581 testvectors-sha256: 6a85ec1f64d017fc2ffd88aa7d679de7e0554e00bdea62c7fea5c4c403e3eafa principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-sha256-256s-simple/META.yml b/crypto_sign/sphincs-sha256-256s-simple/META.yml index 231b96dc..8d3bd747 100644 --- a/crypto_sign/sphincs-sha256-256s-simple/META.yml +++ b/crypto_sign/sphincs-sha256-256s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 29792 +nistkat-sha256: 768d61c537b3abacca3ab468623edafb33d28a33dc5a9859f803679a3020b639 testvectors-sha256: 796b5101fa5170c92f0186b347716dc0662eac35002a8c4d80ac9283cbef5a02 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-128f-robust/META.yml b/crypto_sign/sphincs-shake256-128f-robust/META.yml index 9b2474f3..6c85ad7b 100644 --- a/crypto_sign/sphincs-shake256-128f-robust/META.yml +++ b/crypto_sign/sphincs-shake256-128f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 16976 +nistkat-sha256: e7789df37278d1e147996bd9bf4cda55d5ec5cbe921e64b0766927af4b02decd testvectors-sha256: eea7f59958e732c15110d0d06e3c23005d73df2b15a1e7b4ebc0ca2dcf162bb5 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-128f-simple/META.yml b/crypto_sign/sphincs-shake256-128f-simple/META.yml index 5814eaa1..e53da837 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/META.yml +++ b/crypto_sign/sphincs-shake256-128f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 16976 +nistkat-sha256: c99700873ca6914944fcef3b649270c86c056dcd11ce6e8f22580b193a136e6f testvectors-sha256: a14cb8e4f149493fc5979e465e09ce943e8d669186ff5c7c3d11239fa869def6 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-128s-robust/META.yml b/crypto_sign/sphincs-shake256-128s-robust/META.yml index 6302c5c7..824c4d4e 100644 --- a/crypto_sign/sphincs-shake256-128s-robust/META.yml +++ b/crypto_sign/sphincs-shake256-128s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 8080 +nistkat-sha256: e9c31937277677d1cb387ce76408c76b0128938f3af047f60fb5d073a3c788b3 testvectors-sha256: f3f56ddff38a75ee07b44c023b9c9133ffe9538bb4b64f8ec8742b21fcaa6a50 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-128s-simple/META.yml b/crypto_sign/sphincs-shake256-128s-simple/META.yml index 41237bc4..24cf2b38 100644 --- a/crypto_sign/sphincs-shake256-128s-simple/META.yml +++ b/crypto_sign/sphincs-shake256-128s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 1 length-public-key: 32 length-secret-key: 64 length-signature: 8080 +nistkat-sha256: 5d23c9f334e9bd99d5294cf40c6b2c096ee668076e809b44b928ca146d2c5e3a testvectors-sha256: ee2af38333f6ba705102ab66689c262b07c1fd9ce1d46180796bcb263bf1a654 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-192f-robust/META.yml b/crypto_sign/sphincs-shake256-192f-robust/META.yml index 95be6a3a..0fba24a0 100644 --- a/crypto_sign/sphincs-shake256-192f-robust/META.yml +++ b/crypto_sign/sphincs-shake256-192f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 35664 +nistkat-sha256: 5cfcf998ad0bedf8e6b961c8891048f456d6422d3b4a26fcb095a913c9efd03e testvectors-sha256: de65b2a7b6d5e819f58b6e1a08ec4ef3308a9c36b7c962450105f82263e35e98 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-192f-simple/META.yml b/crypto_sign/sphincs-shake256-192f-simple/META.yml index 4e9fe612..5759e456 100644 --- a/crypto_sign/sphincs-shake256-192f-simple/META.yml +++ b/crypto_sign/sphincs-shake256-192f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 35664 +nistkat-sha256: 28528adef75a728d013bb493d85e358a75344c72000792419f1f539c16f24f10 testvectors-sha256: 14f60a3099cfddf30c46491a98a5f3508739df108425b2eaa5c19383f0ca4b22 principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-192s-robust/META.yml b/crypto_sign/sphincs-shake256-192s-robust/META.yml index ccc5bc5c..860fc704 100644 --- a/crypto_sign/sphincs-shake256-192s-robust/META.yml +++ b/crypto_sign/sphincs-shake256-192s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 17064 +nistkat-sha256: 619ce596575f52ed8fd3e5b0501db21985e505c95f0f595faa4d6a6f0a2fd81c testvectors-sha256: 4f80c9cf98c017293c7543f96170f18655e6ef65675300aa302de42562b21f5a principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-192s-simple/META.yml b/crypto_sign/sphincs-shake256-192s-simple/META.yml index 3bf7fa16..695619d5 100644 --- a/crypto_sign/sphincs-shake256-192s-simple/META.yml +++ b/crypto_sign/sphincs-shake256-192s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 3 length-public-key: 48 length-secret-key: 96 length-signature: 17064 +nistkat-sha256: 31b341c25230f8524e123db8a5dc29e8dd952cd11a63a821ac488b97d5106597 testvectors-sha256: ea1c38dafdeec8bd6b5a844955b1edffbb1d16f392a647fdae8e6dd148c6396c principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-256f-robust/META.yml b/crypto_sign/sphincs-shake256-256f-robust/META.yml index 67eb8355..b949d913 100644 --- a/crypto_sign/sphincs-shake256-256f-robust/META.yml +++ b/crypto_sign/sphincs-shake256-256f-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 49216 +nistkat-sha256: d5410edbaa120cf24f0bcf8cb834fdb08b4b5652809ee17c026d37212f4a4934 testvectors-sha256: 4757a2ce7aec6daac4ab894336586949f7919c63d55200ec6325eb395efcf1ef principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-256f-simple/META.yml b/crypto_sign/sphincs-shake256-256f-simple/META.yml index 37d2134b..7978a30b 100644 --- a/crypto_sign/sphincs-shake256-256f-simple/META.yml +++ b/crypto_sign/sphincs-shake256-256f-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 49216 +nistkat-sha256: 5a8959fc0436a66d6d69cc8adb2f24936b763ae324bc97ed139ae92f9f7e03c3 testvectors-sha256: 1b261fc7394dc847349c07bde922ac028aad94c534f51341f8202670558ed27a principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-256s-robust/META.yml b/crypto_sign/sphincs-shake256-256s-robust/META.yml index a04440fd..bf7b1bf1 100644 --- a/crypto_sign/sphincs-shake256-256s-robust/META.yml +++ b/crypto_sign/sphincs-shake256-256s-robust/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 29792 +nistkat-sha256: 09004dba03b2a190a327b5404a4d75c663f025703253b78946d0a99ca1492d6f testvectors-sha256: eea62308d71394a888e05128f078c4663dc83e128c34e0300bb16cb839d8698b principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/crypto_sign/sphincs-shake256-256s-simple/META.yml b/crypto_sign/sphincs-shake256-256s-simple/META.yml index 33732662..482dc1e4 100644 --- a/crypto_sign/sphincs-shake256-256s-simple/META.yml +++ b/crypto_sign/sphincs-shake256-256s-simple/META.yml @@ -4,6 +4,7 @@ claimed-nist-level: 5 length-public-key: 64 length-secret-key: 128 length-signature: 29792 +nistkat-sha256: f704deaf990987c306082bb28258cfb8c6f03b49940c06df582ef3fb86958e8a testvectors-sha256: fc518be7778d0363f17a30c50efbe28841f5a795e7375e94d206f115967f30df principal-submitter: Andreas Hülsing auxiliary-submitters: diff --git a/test/crypto_sign/nistkat.c b/test/crypto_sign/nistkat.c new file mode 100644 index 00000000..adef86cc --- /dev/null +++ b/test/crypto_sign/nistkat.c @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "api.h" +#include "randombytes.h" + +// https://stackoverflow.com/a/1489985/1711232 +#define PASTER(x, y) x##_##y +#define EVALUATOR(x, y) PASTER(x, y) +#define NAMESPACE(fun) EVALUATOR(PQCLEAN_NAMESPACE, fun) + +#define CRYPTO_PUBLICKEYBYTES NAMESPACE(CRYPTO_PUBLICKEYBYTES) +#define CRYPTO_SECRETKEYBYTES NAMESPACE(CRYPTO_SECRETKEYBYTES) +#define CRYPTO_BYTES NAMESPACE(CRYPTO_BYTES) +#define CRYPTO_ALGNAME NAMESPACE(CRYPTO_ALGNAME) + +#define crypto_sign_keypair NAMESPACE(crypto_sign_keypair) +#define crypto_sign NAMESPACE(crypto_sign) +#define crypto_sign_open NAMESPACE(crypto_sign_open) + +void nist_kat_init(unsigned char *entropy_input, unsigned char *personalization_string, int security_strength); + +static void fprintBstr(FILE *fp, const char *S, const uint8_t *A, size_t L) { + size_t i; + fprintf(fp, "%s", S); + for (i = 0; i < L; i++) { + fprintf(fp, "%02X", A[i]); + } + if (L == 0) { + fprintf(fp, "00"); + } + fprintf(fp, "\n"); +} + +int main() { + + uint8_t entropy_input[48]; + uint8_t seed[48]; + FILE *fh = stdout; + uint8_t public_key[CRYPTO_PUBLICKEYBYTES]; + uint8_t secret_key[CRYPTO_SECRETKEYBYTES]; + size_t mlen = 33; + size_t smlen, mlen1; + uint8_t m[33]; + uint8_t sm[33 + CRYPTO_BYTES]; + int rc; + + for (uint8_t i = 0; i < 48; i++) { + entropy_input[i] = i; + } + + nist_kat_init(entropy_input, NULL, 256); + + fprintf(fh, "count = 0\n"); + randombytes(seed, 48); + fprintBstr(fh, "seed = ", seed, 48); + + fprintf(fh, "mlen = 33\n"); + + randombytes(m, mlen); + fprintBstr(fh, "msg = ", m, mlen); + + nist_kat_init(seed, NULL, 256); + + rc = crypto_sign_keypair(public_key, secret_key); + if (rc != 0) { + fprintf(stderr, "[kat_kem] %s ERROR: crypto_kem_keypair failed!\n", CRYPTO_ALGNAME); + return -1; + } + fprintBstr(fh, "pk = ", public_key, CRYPTO_PUBLICKEYBYTES); + fprintBstr(fh, "sk = ", secret_key, CRYPTO_SECRETKEYBYTES); + + rc = crypto_sign(sm, &smlen, m, mlen, secret_key); + if (rc != 0) { + fprintf(stderr, "[kat_kem] %s ERROR: crypto_sign failed!\n", CRYPTO_ALGNAME); + return -2; + } + fprintf(fh, "smlen = %lu\n", smlen); + fprintBstr(fh, "sm = ", sm, smlen); + + rc = crypto_sign_open(sm, &mlen1, sm, smlen, public_key); + if (rc != 0) { + fprintf(stderr, "[kat_kem] %s ERROR: crypto_sign_open failed!\n", CRYPTO_ALGNAME); + return -3; + } + + if ( mlen != mlen1 ) { + printf("crypto_sign_open returned bad 'mlen': got <%lu>, expected <%lu>\n", mlen1, mlen); + return -4; + } + if (memcmp(m, sm, mlen)) { + printf("crypto_sign_open returned bad 'm' value\n"); + return -5; + } + return 0; + +} diff --git a/test/test_metadata.py b/test/test_metadata.py index 472b92b8..284c2678 100644 --- a/test/test_metadata.py +++ b/test/test_metadata.py @@ -47,6 +47,7 @@ EXPECTED_FIELDS = { 'claimed-nist-level': {'type': int, 'min': 1, 'max': 5}, 'length-public-key': {'type': int, 'min': 1}, 'length-secret-key': {'type': int, 'min': 1}, + 'nistkat-sha256': {'type': str, 'length': 64}, 'principal-submitter': {'type': str}, 'auxiliary-submitters': {'type': list, 'elements': {'type': str}}, 'implementations': { @@ -65,7 +66,6 @@ KEM_FIELDS = { 'claimed-security' : {'type' : str, 'values' : ['IND-CPA', 'IND-CCA2'] }, 'length-ciphertext': {'type': int, 'min': 1}, 'length-shared-secret': {'type': int, 'min': 1}, - 'nistkat-sha256': {'type': str, 'length': 64}, } SIGNATURE_FIELDS = { diff --git a/test/test_nistkat.py b/test/test_nistkat.py index daebca49..6aac1318 100644 --- a/test/test_nistkat.py +++ b/test/test_nistkat.py @@ -17,8 +17,6 @@ import unittest def test_nistkat(): for scheme in pqclean.Scheme.all_schemes(): - if scheme.type != 'kem': - continue for implementation in scheme.implementations: yield check_nistkat, implementation From 0dd0a4a528e72e869b829a04e32cf7b905d43a68 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Thu, 16 May 2019 11:30:24 +0200 Subject: [PATCH 11/35] fix format strings for Windows --- test/crypto_sign/nistkat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/crypto_sign/nistkat.c b/test/crypto_sign/nistkat.c index adef86cc..267b072f 100644 --- a/test/crypto_sign/nistkat.c +++ b/test/crypto_sign/nistkat.c @@ -80,7 +80,7 @@ int main() { fprintf(stderr, "[kat_kem] %s ERROR: crypto_sign failed!\n", CRYPTO_ALGNAME); return -2; } - fprintf(fh, "smlen = %lu\n", smlen); + fprintf(fh, "smlen = %zu\n", smlen); fprintBstr(fh, "sm = ", sm, smlen); rc = crypto_sign_open(sm, &mlen1, sm, smlen, public_key); @@ -90,7 +90,7 @@ int main() { } if ( mlen != mlen1 ) { - printf("crypto_sign_open returned bad 'mlen': got <%lu>, expected <%lu>\n", mlen1, mlen); + printf("crypto_sign_open returned bad 'mlen': got <%zu>, expected <%zu>\n", mlen1, mlen); return -4; } if (memcmp(m, sm, mlen)) { From 3d67b4c1c2631e07775c7eb95346d0dc1c0ba73c Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Fri, 17 May 2019 16:10:07 +0200 Subject: [PATCH 12/35] add duplicate consistency checks and remove some comments --- crypto_kem/newhope1024cca/clean/poly.c | 13 ------ crypto_kem/newhope1024cpa/clean/poly.c | 13 ------ crypto_kem/newhope512cca/clean/poly.c | 13 ------ crypto_kem/newhope512cpa/clean/poly.c | 13 ------ .../newhope1024cca_clean.yml | 43 ++++++++++++++++++ .../newhope1024cpa_clean.yml | 42 ++++++++++++++++++ .../newhope512cca_clean.yml | 44 +++++++++++++++++++ .../newhope512cpa_clean.yml | 42 ++++++++++++++++++ 8 files changed, 171 insertions(+), 52 deletions(-) create mode 100644 test/duplicate_consistency/newhope1024cca_clean.yml create mode 100644 test/duplicate_consistency/newhope1024cpa_clean.yml create mode 100644 test/duplicate_consistency/newhope512cca_clean.yml create mode 100644 test/duplicate_consistency/newhope512cpa_clean.yml diff --git a/crypto_kem/newhope1024cca/clean/poly.c b/crypto_kem/newhope1024cca/clean/poly.c index e368a6b3..94422dcf 100644 --- a/crypto_kem/newhope1024cca/clean/poly.c +++ b/crypto_kem/newhope1024cca/clean/poly.c @@ -256,7 +256,6 @@ static unsigned char hw(unsigned char a) { **************************************************/ void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { unsigned char buf[128], a, b; -// uint32_t t, d, a, b, c; int i, j; unsigned char extseed[NEWHOPE_SYMBYTES + 2]; @@ -273,18 +272,6 @@ void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed a = buf[2 * j]; b = buf[2 * j + 1]; r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); - /* - t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); - d = 0; - for(k=0;k<8;k++) - d += (t >> k) & 0x01010101; - a = d & 0xff; - b = ((d >> 8) & 0xff); - c = ((d >> 16) & 0xff); - d >>= 24; - r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; - r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; - */ } } } diff --git a/crypto_kem/newhope1024cpa/clean/poly.c b/crypto_kem/newhope1024cpa/clean/poly.c index 360e07d7..772fa5a7 100644 --- a/crypto_kem/newhope1024cpa/clean/poly.c +++ b/crypto_kem/newhope1024cpa/clean/poly.c @@ -256,7 +256,6 @@ static unsigned char hw(unsigned char a) { **************************************************/ void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { unsigned char buf[128], a, b; -// uint32_t t, d, a, b, c; int i, j; unsigned char extseed[NEWHOPE_SYMBYTES + 2]; @@ -273,18 +272,6 @@ void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed a = buf[2 * j]; b = buf[2 * j + 1]; r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); - /* - t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); - d = 0; - for(k=0;k<8;k++) - d += (t >> k) & 0x01010101; - a = d & 0xff; - b = ((d >> 8) & 0xff); - c = ((d >> 16) & 0xff); - d >>= 24; - r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; - r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; - */ } } } diff --git a/crypto_kem/newhope512cca/clean/poly.c b/crypto_kem/newhope512cca/clean/poly.c index 53c54083..7998c417 100644 --- a/crypto_kem/newhope512cca/clean/poly.c +++ b/crypto_kem/newhope512cca/clean/poly.c @@ -252,7 +252,6 @@ static unsigned char hw(unsigned char a) { **************************************************/ void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { unsigned char buf[128], a, b; -// uint32_t t, d, a, b, c; int i, j; unsigned char extseed[NEWHOPE_SYMBYTES + 2]; @@ -269,18 +268,6 @@ void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_sample(poly *r, const unsigned char *seed, a = buf[2 * j]; b = buf[2 * j + 1]; r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); - /* - t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); - d = 0; - for(k=0;k<8;k++) - d += (t >> k) & 0x01010101; - a = d & 0xff; - b = ((d >> 8) & 0xff); - c = ((d >> 16) & 0xff); - d >>= 24; - r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; - r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; - */ } } } diff --git a/crypto_kem/newhope512cpa/clean/poly.c b/crypto_kem/newhope512cpa/clean/poly.c index cd6cac24..720d8e4f 100644 --- a/crypto_kem/newhope512cpa/clean/poly.c +++ b/crypto_kem/newhope512cpa/clean/poly.c @@ -252,7 +252,6 @@ static unsigned char hw(unsigned char a) { **************************************************/ void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, unsigned char nonce) { unsigned char buf[128], a, b; -// uint32_t t, d, a, b, c; int i, j; unsigned char extseed[NEWHOPE_SYMBYTES + 2]; @@ -269,18 +268,6 @@ void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_sample(poly *r, const unsigned char *seed, a = buf[2 * j]; b = buf[2 * j + 1]; r->coeffs[64 * i + j] = hw(a) + NEWHOPE_Q - hw(b); - /* - t = buf[j] | ((uint32_t)buf[j+1] << 8) | ((uint32_t)buf[j+2] << 16) | ((uint32_t)buf[j+3] << 24); - d = 0; - for(k=0;k<8;k++) - d += (t >> k) & 0x01010101; - a = d & 0xff; - b = ((d >> 8) & 0xff); - c = ((d >> 16) & 0xff); - d >>= 24; - r->coeffs[64*i+j/2] = a + NEWHOPE_Q - b; - r->coeffs[64*i+j/2+1] = c + NEWHOPE_Q - d; - */ } } } diff --git a/test/duplicate_consistency/newhope1024cca_clean.yml b/test/duplicate_consistency/newhope1024cca_clean.yml new file mode 100644 index 00000000..21764ea3 --- /dev/null +++ b/test/duplicate_consistency/newhope1024cca_clean.yml @@ -0,0 +1,43 @@ +consistency_checks: +- source: + scheme: newhope1024cpa + implementation: clean + files: + - ntt.c + - poly.c + - precomp.c + - cpapke.c + - reduce.c + - verify.c + - params.h + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope512cca + implementation: clean + files: + - kem.c + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope512cpa + implementation: clean + files: + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h + diff --git a/test/duplicate_consistency/newhope1024cpa_clean.yml b/test/duplicate_consistency/newhope1024cpa_clean.yml new file mode 100644 index 00000000..ecf8b874 --- /dev/null +++ b/test/duplicate_consistency/newhope1024cpa_clean.yml @@ -0,0 +1,42 @@ +consistency_checks: +- source: + scheme: newhope1024cca + implementation: clean + files: + - ntt.c + - poly.c + - precomp.c + - cpapke.c + - reduce.c + - verify.c + - params.h + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope512cca + implementation: clean + files: + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope512cpa + implementation: clean + files: + - kem.c + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h diff --git a/test/duplicate_consistency/newhope512cca_clean.yml b/test/duplicate_consistency/newhope512cca_clean.yml new file mode 100644 index 00000000..ff0c6036 --- /dev/null +++ b/test/duplicate_consistency/newhope512cca_clean.yml @@ -0,0 +1,44 @@ +consistency_checks: +- source: + scheme: newhope1024cpa + implementation: clean + files: + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope1024cca + implementation: clean + files: + - kem.c + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope512cpa + implementation: clean + files: + - ntt.c + - poly.c + - precomp.c + - cpapke.c + - reduce.c + - verify.c + - params.h + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h + + diff --git a/test/duplicate_consistency/newhope512cpa_clean.yml b/test/duplicate_consistency/newhope512cpa_clean.yml new file mode 100644 index 00000000..e18fab3b --- /dev/null +++ b/test/duplicate_consistency/newhope512cpa_clean.yml @@ -0,0 +1,42 @@ +consistency_checks: +- source: + scheme: newhope1024cpa + implementation: clean + files: + - kem.c + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope1024cca + implementation: clean + files: + - cpapke.c + - reduce.c + - verify.c + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h +- source: + scheme: newhope512cca + implementation: clean + files: + - ntt.c + - poly.c + - precomp.c + - cpapke.c + - reduce.c + - verify.c + - params.h + - cpapke.h + - ntt.h + - poly.h + - reduce.h + - verify.h From 82fdce64a2e8c9b6688d4b5f0f0f1ec235c3ad82 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sat, 18 May 2019 11:27:45 +0200 Subject: [PATCH 13/35] Macro for loop length --- crypto_kem/newhope1024cca/clean/poly.c | 2 +- crypto_kem/newhope1024cpa/clean/poly.c | 2 +- crypto_kem/newhope512cca/clean/poly.c | 2 +- crypto_kem/newhope512cpa/clean/poly.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto_kem/newhope1024cca/clean/poly.c b/crypto_kem/newhope1024cca/clean/poly.c index 94422dcf..2ede9dea 100644 --- a/crypto_kem/newhope1024cca/clean/poly.c +++ b/crypto_kem/newhope1024cca/clean/poly.c @@ -151,7 +151,7 @@ void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_decompress(poly *r, const unsigned char * **************************************************/ void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { unsigned int i, j, mask; - for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (j = 0; j < 8; j++) { mask = -((msg[i] >> j) & 1); r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); diff --git a/crypto_kem/newhope1024cpa/clean/poly.c b/crypto_kem/newhope1024cpa/clean/poly.c index 772fa5a7..5ab00927 100644 --- a/crypto_kem/newhope1024cpa/clean/poly.c +++ b/crypto_kem/newhope1024cpa/clean/poly.c @@ -151,7 +151,7 @@ void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_decompress(poly *r, const unsigned char * **************************************************/ void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { unsigned int i, j, mask; - for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (j = 0; j < 8; j++) { mask = -((msg[i] >> j) & 1); r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); diff --git a/crypto_kem/newhope512cca/clean/poly.c b/crypto_kem/newhope512cca/clean/poly.c index 7998c417..b8075df5 100644 --- a/crypto_kem/newhope512cca/clean/poly.c +++ b/crypto_kem/newhope512cca/clean/poly.c @@ -151,7 +151,7 @@ void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_decompress(poly *r, const unsigned char *a **************************************************/ void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { unsigned int i, j, mask; - for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (j = 0; j < 8; j++) { mask = -((msg[i] >> j) & 1); r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); diff --git a/crypto_kem/newhope512cpa/clean/poly.c b/crypto_kem/newhope512cpa/clean/poly.c index 720d8e4f..364c7af6 100644 --- a/crypto_kem/newhope512cpa/clean/poly.c +++ b/crypto_kem/newhope512cpa/clean/poly.c @@ -151,7 +151,7 @@ void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_decompress(poly *r, const unsigned char *a **************************************************/ void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_frommsg(poly *r, const unsigned char *msg) { unsigned int i, j, mask; - for (i = 0; i < 32; i++) { // XXX: MACRO for 32 + for (i = 0; i < NEWHOPE_SYMBYTES; i++) { for (j = 0; j < 8; j++) { mask = -((msg[i] >> j) & 1); r->coeffs[8 * i + j + 0] = mask & (NEWHOPE_Q / 2); From 7c30aa73c90ed569b9a64ba5cf178239a7e304ea Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 09:20:12 +0200 Subject: [PATCH 14/35] SHA2 state constants in common --- common/sha2.c | 108 ++++++++++++++++++++++----------------------- common/sha2.h | 40 ++++++++++++----- test/common/sha2.c | 18 ++++---- 3 files changed, 91 insertions(+), 75 deletions(-) diff --git a/common/sha2.c b/common/sha2.c index 12ba35be..cc42f760 100644 --- a/common/sha2.c +++ b/common/sha2.c @@ -492,73 +492,73 @@ static const uint8_t iv_512[64] = { 0x6b, 0x5b, 0xe0, 0xcd, 0x19, 0x13, 0x7e, 0x21, 0x79 }; -void sha224_inc_init(uint8_t *state) { +void sha224_inc_init(sha224ctx *state) { for (size_t i = 0; i < 32; ++i) { - state[i] = iv_224[i]; + state->ctx[i] = iv_224[i]; } for (size_t i = 32; i < 40; ++i) { - state[i] = 0; + state->ctx[i] = 0; } } -void sha256_inc_init(uint8_t *state) { +void sha256_inc_init(sha256ctx *state) { for (size_t i = 0; i < 32; ++i) { - state[i] = iv_256[i]; + state->ctx[i] = iv_256[i]; } for (size_t i = 32; i < 40; ++i) { - state[i] = 0; + state->ctx[i] = 0; } } -void sha384_inc_init(uint8_t *state) { +void sha384_inc_init(sha384ctx *state) { for (size_t i = 0; i < 64; ++i) { - state[i] = iv_384[i]; + state->ctx[i] = iv_384[i]; } for (size_t i = 64; i < 72; ++i) { - state[i] = 0; + state->ctx[i] = 0; } } -void sha512_inc_init(uint8_t *state) { +void sha512_inc_init(sha512ctx *state) { for (size_t i = 0; i < 64; ++i) { - state[i] = iv_512[i]; + state->ctx[i] = iv_512[i]; } for (size_t i = 64; i < 72; ++i) { - state[i] = 0; + state->ctx[i] = 0; } } -void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { - uint64_t bytes = load_bigendian_64(state + 32); +void sha256_inc_blocks(sha256ctx *state, const uint8_t *in, size_t inblocks) { + uint64_t bytes = load_bigendian_64(state->ctx + 32); - crypto_hashblocks_sha256(state, in, 64 * inblocks); + crypto_hashblocks_sha256(state->ctx, in, 64 * inblocks); bytes += 64 * inblocks; - store_bigendian_64(state + 32, bytes); + store_bigendian_64(state->ctx + 32, bytes); } -void sha224_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { - sha256_inc_blocks(state, in, inblocks); +void sha224_inc_blocks(sha224ctx *state, const uint8_t *in, size_t inblocks) { + sha256_inc_blocks((sha256ctx*) state, in, inblocks); } -void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { - uint64_t bytes = load_bigendian_64(state + 64); +void sha512_inc_blocks(sha512ctx *state, const uint8_t *in, size_t inblocks) { + uint64_t bytes = load_bigendian_64(state->ctx + 64); - crypto_hashblocks_sha256(state, in, 128 * inblocks); + crypto_hashblocks_sha256(state->ctx, in, 128 * inblocks); bytes += 128 * inblocks; - store_bigendian_64(state + 64, bytes); + store_bigendian_64(state->ctx + 64, bytes); } -void sha384_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks) { - sha512_inc_blocks(state, in, inblocks); +void sha384_inc_blocks(sha384ctx *state, const uint8_t *in, size_t inblocks) { + sha512_inc_blocks((sha512ctx*) state, in, inblocks); } -void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { +void sha256_inc_finalize(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen) { uint8_t padded[128]; - uint64_t bytes = load_bigendian_64(state + 32) + inlen; + uint64_t bytes = load_bigendian_64(state->ctx + 32) + inlen; - crypto_hashblocks_sha256(state, in, inlen); + crypto_hashblocks_sha256(state->ctx, in, inlen); in += inlen; inlen &= 63; in -= inlen; @@ -580,7 +580,7 @@ void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t padded[61] = (uint8_t) (bytes >> 13); padded[62] = (uint8_t) (bytes >> 5); padded[63] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha256(state, padded, 64); + crypto_hashblocks_sha256(state->ctx, padded, 64); } else { for (size_t i = inlen + 1; i < 120; ++i) { padded[i] = 0; @@ -593,27 +593,27 @@ void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t padded[125] = (uint8_t) (bytes >> 13); padded[126] = (uint8_t) (bytes >> 5); padded[127] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha256(state, padded, 128); + crypto_hashblocks_sha256(state->ctx, padded, 128); } for (size_t i = 0; i < 32; ++i) { - out[i] = state[i]; + out[i] = state->ctx[i]; } } -void sha224_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { - sha256_inc_finalize(state, state, in, inlen); +void sha224_inc_finalize(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen) { + sha256_inc_finalize(state->ctx, (sha256ctx*)state, in, inlen); for (size_t i = 0; i < 28; ++i) { - out[i] = state[i]; + out[i] = state->ctx[i]; } } -void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { +void sha512_inc_finalize(uint8_t *out, sha512ctx *state, const uint8_t *in, size_t inlen) { uint8_t padded[256]; - uint64_t bytes = load_bigendian_64(state + 64) + inlen; + uint64_t bytes = load_bigendian_64(state->ctx + 64) + inlen; - crypto_hashblocks_sha512(state, in, inlen); + crypto_hashblocks_sha512(state->ctx, in, inlen); in += inlen; inlen &= 127; in -= inlen; @@ -636,7 +636,7 @@ void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t padded[125] = (uint8_t) (bytes >> 13); padded[126] = (uint8_t) (bytes >> 5); padded[127] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha512(state, padded, 128); + crypto_hashblocks_sha512(state->ctx, padded, 128); } else { for (size_t i = inlen + 1; i < 247; ++i) { padded[i] = 0; @@ -650,46 +650,46 @@ void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t padded[253] = (uint8_t) (bytes >> 13); padded[254] = (uint8_t) (bytes >> 5); padded[255] = (uint8_t) (bytes << 3); - crypto_hashblocks_sha512(state, padded, 256); + crypto_hashblocks_sha512(state->ctx, padded, 256); } for (size_t i = 0; i < 64; ++i) { - out[i] = state[i]; + out[i] = state->ctx[i]; } } -void sha384_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen) { - sha512_inc_finalize(state, state, in, inlen); +void sha384_inc_finalize(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen) { + sha512_inc_finalize(state->ctx, (sha512ctx*)state, in, inlen); for (size_t i = 0; i < 48; ++i) { - out[i] = state[i]; + out[i] = state->ctx[i]; } } void sha224(uint8_t *out, const uint8_t *in, size_t inlen) { - uint8_t state[40]; + sha224ctx state; - sha224_inc_init(state); - sha224_inc_finalize(out, state, in, inlen); + sha224_inc_init(&state); + sha224_inc_finalize(out, &state, in, inlen); } void sha256(uint8_t *out, const uint8_t *in, size_t inlen) { - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); - sha256_inc_finalize(out, state, in, inlen); + sha256_inc_init(&state); + sha256_inc_finalize(out, &state, in, inlen); } void sha384(uint8_t *out, const uint8_t *in, size_t inlen) { - uint8_t state[72]; + sha384ctx state; - sha384_inc_init(state); - sha384_inc_finalize(out, state, in, inlen); + sha384_inc_init(&state); + sha384_inc_finalize(out, &state, in, inlen); } void sha512(uint8_t *out, const uint8_t *in, size_t inlen) { - uint8_t state[72]; + sha512ctx state; - sha512_inc_init(state); - sha512_inc_finalize(out, state, in, inlen); + sha512_inc_init(&state); + sha512_inc_finalize(out, &state, in, inlen); } diff --git a/common/sha2.h b/common/sha2.h index ce6a8aff..618683ef 100644 --- a/common/sha2.h +++ b/common/sha2.h @@ -8,24 +8,40 @@ must be exactly 64 bytes each. Use the 'finalize' functions for any remaining bytes (possibly over 64). */ -void sha224_inc_init(uint8_t *state); -void sha224_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); -void sha224_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); +typedef struct { + uint8_t ctx[40]; +} sha224ctx; + +typedef struct { + uint8_t ctx[40]; +} sha256ctx; + +typedef struct { + uint8_t ctx[72]; +} sha384ctx; + +typedef struct { + uint8_t ctx[72]; +} sha512ctx; + +void sha224_inc_init(sha224ctx *state); +void sha224_inc_blocks(sha224ctx *state, const uint8_t *in, size_t inblocks); +void sha224_inc_finalize(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen); void sha224(uint8_t *out, const uint8_t *in, size_t inlen); -void sha256_inc_init(uint8_t *state); -void sha256_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); -void sha256_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); +void sha256_inc_init(sha256ctx *state); +void sha256_inc_blocks(sha256ctx *state, const uint8_t *in, size_t inblocks); +void sha256_inc_finalize(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen); void sha256(uint8_t *out, const uint8_t *in, size_t inlen); -void sha384_inc_init(uint8_t *state); -void sha384_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); -void sha384_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); +void sha384_inc_init(sha384ctx *state); +void sha384_inc_blocks(sha384ctx *state, const uint8_t *in, size_t inblocks); +void sha384_inc_finalize(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen); void sha384(uint8_t *out, const uint8_t *in, size_t inlen); -void sha512_inc_init(uint8_t *state); -void sha512_inc_blocks(uint8_t *state, const uint8_t *in, size_t inblocks); -void sha512_inc_finalize(uint8_t *out, uint8_t *state, const uint8_t *in, size_t inlen); +void sha512_inc_init(sha512ctx *state); +void sha512_inc_blocks(sha512ctx *state, const uint8_t *in, size_t inblocks); +void sha512_inc_finalize(uint8_t *out, sha512ctx *state, const uint8_t *in, size_t inlen); void sha512(uint8_t *out, const uint8_t *in, size_t inlen); #endif diff --git a/test/common/sha2.c b/test/common/sha2.c index f08eb06b..b04f59a2 100644 --- a/test/common/sha2.c +++ b/test/common/sha2.c @@ -37,14 +37,14 @@ const unsigned char expected_512[64] = { static int test_sha256_incremental(void) { unsigned char output[32]; - uint8_t state[40]; + sha256ctx state; int i = 0; - sha256_inc_init(state); - sha256_inc_blocks(state, plaintext, 1); - sha256_inc_finalize(output, state, plaintext + 64, 112 - 64); + sha256_inc_init(&state); + sha256_inc_blocks(&state, plaintext, 1); + sha256_inc_finalize(output, &state, plaintext + 64, 112 - 64); - if (memcmp(expected_256, output, 32)) { + if (memcmp(expected_256, output, 32) != 0) { printf("ERROR sha256 incremental did not match sha256.\n"); printf(" Expected: "); for (i = 0; i < 32; i++) { @@ -68,7 +68,7 @@ static int test_sha224(void) { sha224(output, plaintext, 112); - if (memcmp(expected_224, output, 28)) { + if (memcmp(expected_224, output, 28) != 0) { printf("ERROR sha224 output did not match test vector.\n"); printf("Expected: "); for (i = 0; i < 28; i++) { @@ -92,7 +92,7 @@ static int test_sha256(void) { sha256(output, plaintext, 112); - if (memcmp(expected_256, output, 32)) { + if (memcmp(expected_256, output, 32) != 0) { printf("ERROR sha256 output did not match test vector.\n"); printf("Expected: "); for (i = 0; i < 32; i++) { @@ -116,7 +116,7 @@ static int test_sha384(void) { sha384(output, plaintext, 112); - if (memcmp(expected_384, output, 48)) { + if (memcmp(expected_384, output, 48) != 0) { printf("ERROR sha384 output did not match test vector.\n"); printf("Expected: "); for (i = 0; i < 48; i++) { @@ -140,7 +140,7 @@ static int test_sha512(void) { sha512(output, plaintext, 112); - if (memcmp(expected_512, output, 64)) { + if (memcmp(expected_512, output, 64) != 0) { printf("ERROR sha512 output did not match test vector.\n"); printf("Expected: "); for (i = 0; i < 64; i++) { From 6953a0b32e7be7cd610e91f0694ef069dac9c916 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 09:39:06 +0200 Subject: [PATCH 15/35] Port SPHINCS+-SHA256 to sha256ctx struct --- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-128f-robust/clean/sha256.c | 6 ++--- .../sphincs-sha256-128f-robust/clean/sha256.h | 4 +++- .../clean/thash_sha256_robust.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-128f-simple/clean/sha256.c | 6 ++--- .../sphincs-sha256-128f-simple/clean/sha256.h | 4 +++- .../clean/thash_sha256_simple.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-128s-robust/clean/sha256.c | 6 ++--- .../sphincs-sha256-128s-robust/clean/sha256.h | 4 +++- .../clean/thash_sha256_robust.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-128s-simple/clean/sha256.c | 6 ++--- .../sphincs-sha256-128s-simple/clean/sha256.h | 4 +++- .../clean/thash_sha256_simple.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-192f-robust/clean/sha256.c | 6 ++--- .../sphincs-sha256-192f-robust/clean/sha256.h | 4 +++- .../clean/thash_sha256_robust.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-192f-simple/clean/sha256.c | 6 ++--- .../sphincs-sha256-192f-simple/clean/sha256.h | 4 +++- .../clean/thash_sha256_simple.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-192s-robust/clean/sha256.c | 6 ++--- .../sphincs-sha256-192s-robust/clean/sha256.h | 4 +++- .../clean/thash_sha256_robust.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-192s-simple/clean/sha256.c | 6 ++--- .../sphincs-sha256-192s-simple/clean/sha256.h | 4 +++- .../clean/thash_sha256_simple.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-256f-robust/clean/sha256.c | 6 ++--- .../sphincs-sha256-256f-robust/clean/sha256.h | 4 +++- .../clean/thash_sha256_robust.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-256f-simple/clean/sha256.c | 6 ++--- .../sphincs-sha256-256f-simple/clean/sha256.h | 4 +++- .../clean/thash_sha256_simple.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-256s-robust/clean/sha256.c | 6 ++--- .../sphincs-sha256-256s-robust/clean/sha256.h | 4 +++- .../clean/thash_sha256_robust.c | 6 ++--- .../clean/hash_sha256.c | 22 +++++++++---------- .../sphincs-sha256-256s-simple/clean/sha256.c | 6 ++--- .../sphincs-sha256-256s-simple/clean/sha256.h | 4 +++- .../clean/thash_sha256_simple.c | 6 ++--- 48 files changed, 240 insertions(+), 216 deletions(-) diff --git a/crypto_sign/sphincs-sha256-128f-robust/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-128f-robust/clean/hash_sha256.c index 7af46b0b..da1fe0dd 100644 --- a/crypto_sign/sphincs-sha256-128f-robust/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-128f-robust/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.c b/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.c index abecf7d7..e822cb07 100644 --- a/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.h b/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.h index 225cd12a..86ee829d 100644 --- a/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-128f-robust/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-128f-robust/clean/thash_sha256_robust.c b/crypto_sign/sphincs-sha256-128f-robust/clean/thash_sha256_robust.c index c2f6688c..8c610c93 100644 --- a/crypto_sign/sphincs-sha256-128f-robust/clean/thash_sha256_robust.c +++ b/crypto_sign/sphincs-sha256-128f-robust/clean/thash_sha256_robust.c @@ -18,7 +18,7 @@ static void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4; - uint8_t sha2_state[40]; + sha256ctx sha2_state; unsigned int i; memcpy(buf, pub_seed, SPX_N); @@ -27,13 +27,13 @@ static void PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_thash( PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256128FROBUST_CLEAN_state_seeded, sizeof(sha256ctx)); 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, + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } diff --git a/crypto_sign/sphincs-sha256-128f-simple/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-128f-simple/clean/hash_sha256.c index 96d67fe7..b1579dbc 100644 --- a/crypto_sign/sphincs-sha256-128f-simple/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-128f-simple/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.c b/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.c index f37d567b..c96445a7 100644 --- a/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.h b/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.h index a9895c49..cd2c1cb7 100644 --- a/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-128f-simple/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-128f-simple/clean/thash_sha256_simple.c b/crypto_sign/sphincs-sha256-128f-simple/clean/thash_sha256_simple.c index 4c14be56..ffd2e9ed 100644 --- a/crypto_sign/sphincs-sha256-128f-simple/clean/thash_sha256_simple.c +++ b/crypto_sign/sphincs-sha256-128f-simple/clean/thash_sha256_simple.c @@ -17,17 +17,17 @@ static void PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_thash( const unsigned char *pub_seed, uint32_t addr[8]) { unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; + sha256ctx sha2_state; (void)pub_seed; /* Suppress an 'unused parameter' warning. */ /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_state_seeded, sizeof(sha256ctx)); PQCLEAN_SPHINCSSHA256128FSIMPLE_CLEAN_compress_address(buf, addr); memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + 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/crypto_sign/sphincs-sha256-128s-robust/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-128s-robust/clean/hash_sha256.c index c15b44b1..8b342c5d 100644 --- a/crypto_sign/sphincs-sha256-128s-robust/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-128s-robust/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.c b/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.c index 27d2fbad..071bc2fb 100644 --- a/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.h b/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.h index 22e85bd0..421d6fde 100644 --- a/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-128s-robust/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-128s-robust/clean/thash_sha256_robust.c b/crypto_sign/sphincs-sha256-128s-robust/clean/thash_sha256_robust.c index 5c468dae..d9474ab4 100644 --- a/crypto_sign/sphincs-sha256-128s-robust/clean/thash_sha256_robust.c +++ b/crypto_sign/sphincs-sha256-128s-robust/clean/thash_sha256_robust.c @@ -18,7 +18,7 @@ static void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4; - uint8_t sha2_state[40]; + sha256ctx sha2_state; unsigned int i; memcpy(buf, pub_seed, SPX_N); @@ -27,13 +27,13 @@ static void PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_thash( PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256128SROBUST_CLEAN_state_seeded, sizeof(sha256ctx)); 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, + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } diff --git a/crypto_sign/sphincs-sha256-128s-simple/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-128s-simple/clean/hash_sha256.c index 154c489e..35237406 100644 --- a/crypto_sign/sphincs-sha256-128s-simple/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-128s-simple/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.c b/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.c index b52f6c49..9d241b6a 100644 --- a/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.h b/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.h index f3f2c3dc..245c60b6 100644 --- a/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-128s-simple/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-128s-simple/clean/thash_sha256_simple.c b/crypto_sign/sphincs-sha256-128s-simple/clean/thash_sha256_simple.c index b6303756..34f7d485 100644 --- a/crypto_sign/sphincs-sha256-128s-simple/clean/thash_sha256_simple.c +++ b/crypto_sign/sphincs-sha256-128s-simple/clean/thash_sha256_simple.c @@ -17,17 +17,17 @@ static void PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_thash( const unsigned char *pub_seed, uint32_t addr[8]) { unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; + sha256ctx sha2_state; (void)pub_seed; /* Suppress an 'unused parameter' warning. */ /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_state_seeded, sizeof(sha256ctx)); PQCLEAN_SPHINCSSHA256128SSIMPLE_CLEAN_compress_address(buf, addr); memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + 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/crypto_sign/sphincs-sha256-192f-robust/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-192f-robust/clean/hash_sha256.c index 73d3bbd1..dbe22075 100644 --- a/crypto_sign/sphincs-sha256-192f-robust/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-192f-robust/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.c b/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.c index 4f112ae9..22ce5960 100644 --- a/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.h b/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.h index 1ee273f2..2ddfb42c 100644 --- a/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-192f-robust/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-192f-robust/clean/thash_sha256_robust.c b/crypto_sign/sphincs-sha256-192f-robust/clean/thash_sha256_robust.c index 32924361..69ba05ed 100644 --- a/crypto_sign/sphincs-sha256-192f-robust/clean/thash_sha256_robust.c +++ b/crypto_sign/sphincs-sha256-192f-robust/clean/thash_sha256_robust.c @@ -18,7 +18,7 @@ static void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4; - uint8_t sha2_state[40]; + sha256ctx sha2_state; unsigned int i; memcpy(buf, pub_seed, SPX_N); @@ -27,13 +27,13 @@ static void PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_thash( PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256192FROBUST_CLEAN_state_seeded, sizeof(sha256ctx)); 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, + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } diff --git a/crypto_sign/sphincs-sha256-192f-simple/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-192f-simple/clean/hash_sha256.c index 6944d0ff..2bc9f610 100644 --- a/crypto_sign/sphincs-sha256-192f-simple/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-192f-simple/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.c b/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.c index 425fd631..4de4b235 100644 --- a/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.h b/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.h index 02e0536f..c4f74403 100644 --- a/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-192f-simple/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-192f-simple/clean/thash_sha256_simple.c b/crypto_sign/sphincs-sha256-192f-simple/clean/thash_sha256_simple.c index 0f843507..966d33db 100644 --- a/crypto_sign/sphincs-sha256-192f-simple/clean/thash_sha256_simple.c +++ b/crypto_sign/sphincs-sha256-192f-simple/clean/thash_sha256_simple.c @@ -17,17 +17,17 @@ static void PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_thash( const unsigned char *pub_seed, uint32_t addr[8]) { unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; + sha256ctx sha2_state; (void)pub_seed; /* Suppress an 'unused parameter' warning. */ /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_state_seeded, sizeof(sha256ctx)); PQCLEAN_SPHINCSSHA256192FSIMPLE_CLEAN_compress_address(buf, addr); memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + 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/crypto_sign/sphincs-sha256-192s-robust/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-192s-robust/clean/hash_sha256.c index 99850139..59659720 100644 --- a/crypto_sign/sphincs-sha256-192s-robust/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-192s-robust/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.c b/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.c index 2d94d069..2666f1d3 100644 --- a/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.h b/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.h index 63f173d0..a391bc85 100644 --- a/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-192s-robust/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-192s-robust/clean/thash_sha256_robust.c b/crypto_sign/sphincs-sha256-192s-robust/clean/thash_sha256_robust.c index c2c09379..ee3ce784 100644 --- a/crypto_sign/sphincs-sha256-192s-robust/clean/thash_sha256_robust.c +++ b/crypto_sign/sphincs-sha256-192s-robust/clean/thash_sha256_robust.c @@ -18,7 +18,7 @@ static void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4; - uint8_t sha2_state[40]; + sha256ctx sha2_state; unsigned int i; memcpy(buf, pub_seed, SPX_N); @@ -27,13 +27,13 @@ static void PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_thash( PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256192SROBUST_CLEAN_state_seeded, sizeof(sha256ctx)); 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, + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } diff --git a/crypto_sign/sphincs-sha256-192s-simple/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-192s-simple/clean/hash_sha256.c index 230ad7de..027a2825 100644 --- a/crypto_sign/sphincs-sha256-192s-simple/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-192s-simple/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.c b/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.c index d6fe5626..7db3b07f 100644 --- a/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.h b/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.h index c5c68a72..e9208f3a 100644 --- a/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-192s-simple/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-192s-simple/clean/thash_sha256_simple.c b/crypto_sign/sphincs-sha256-192s-simple/clean/thash_sha256_simple.c index 64745d6d..f03f06b0 100644 --- a/crypto_sign/sphincs-sha256-192s-simple/clean/thash_sha256_simple.c +++ b/crypto_sign/sphincs-sha256-192s-simple/clean/thash_sha256_simple.c @@ -17,17 +17,17 @@ static void PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_thash( const unsigned char *pub_seed, uint32_t addr[8]) { unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; + sha256ctx sha2_state; (void)pub_seed; /* Suppress an 'unused parameter' warning. */ /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_state_seeded, sizeof(sha256ctx)); PQCLEAN_SPHINCSSHA256192SSIMPLE_CLEAN_compress_address(buf, addr); memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + 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/crypto_sign/sphincs-sha256-256f-robust/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-256f-robust/clean/hash_sha256.c index 699f52e1..02d07d37 100644 --- a/crypto_sign/sphincs-sha256-256f-robust/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-256f-robust/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.c b/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.c index 294b0de6..85500774 100644 --- a/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.h b/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.h index c16a7819..3e605ea5 100644 --- a/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-256f-robust/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-256f-robust/clean/thash_sha256_robust.c b/crypto_sign/sphincs-sha256-256f-robust/clean/thash_sha256_robust.c index 37f81ded..db986771 100644 --- a/crypto_sign/sphincs-sha256-256f-robust/clean/thash_sha256_robust.c +++ b/crypto_sign/sphincs-sha256-256f-robust/clean/thash_sha256_robust.c @@ -18,7 +18,7 @@ static void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4; - uint8_t sha2_state[40]; + sha256ctx sha2_state; unsigned int i; memcpy(buf, pub_seed, SPX_N); @@ -27,13 +27,13 @@ static void PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_thash( PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256256FROBUST_CLEAN_state_seeded, sizeof(sha256ctx)); 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, + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } diff --git a/crypto_sign/sphincs-sha256-256f-simple/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-256f-simple/clean/hash_sha256.c index f8c840fb..be9cae55 100644 --- a/crypto_sign/sphincs-sha256-256f-simple/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-256f-simple/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.c b/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.c index 13d1aece..02ab0dc3 100644 --- a/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.h b/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.h index 7dad0c93..e77db8ec 100644 --- a/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-256f-simple/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-256f-simple/clean/thash_sha256_simple.c b/crypto_sign/sphincs-sha256-256f-simple/clean/thash_sha256_simple.c index ab8c6af8..466ca969 100644 --- a/crypto_sign/sphincs-sha256-256f-simple/clean/thash_sha256_simple.c +++ b/crypto_sign/sphincs-sha256-256f-simple/clean/thash_sha256_simple.c @@ -17,17 +17,17 @@ static void PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_thash( const unsigned char *pub_seed, uint32_t addr[8]) { unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; + sha256ctx sha2_state; (void)pub_seed; /* Suppress an 'unused parameter' warning. */ /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_state_seeded, sizeof(sha256ctx)); PQCLEAN_SPHINCSSHA256256FSIMPLE_CLEAN_compress_address(buf, addr); memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + 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/crypto_sign/sphincs-sha256-256s-robust/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-256s-robust/clean/hash_sha256.c index da4e2519..6e7d10cf 100644 --- a/crypto_sign/sphincs-sha256-256s-robust/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-256s-robust/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.c b/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.c index 181009b8..fa002464 100644 --- a/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.h b/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.h index 80106cc7..fe94f592 100644 --- a/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-256s-robust/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-256s-robust/clean/thash_sha256_robust.c b/crypto_sign/sphincs-sha256-256s-robust/clean/thash_sha256_robust.c index d7498c60..37e4b2b2 100644 --- a/crypto_sign/sphincs-sha256-256s-robust/clean/thash_sha256_robust.c +++ b/crypto_sign/sphincs-sha256-256s-robust/clean/thash_sha256_robust.c @@ -18,7 +18,7 @@ static void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; unsigned char *bitmask = buf + SPX_N + SPX_SHA256_ADDR_BYTES + 4; - uint8_t sha2_state[40]; + sha256ctx sha2_state; unsigned int i; memcpy(buf, pub_seed, SPX_N); @@ -27,13 +27,13 @@ static void PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_thash( PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_mgf1(bitmask, inblocks * SPX_N, buf, SPX_N + SPX_SHA256_ADDR_BYTES); /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256256SROBUST_CLEAN_state_seeded, sizeof(sha256ctx)); 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, + sha256_inc_finalize(outbuf, &sha2_state, buf + SPX_N, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } diff --git a/crypto_sign/sphincs-sha256-256s-simple/clean/hash_sha256.c b/crypto_sign/sphincs-sha256-256s-simple/clean/hash_sha256.c index 73cb17d0..0fa93668 100644 --- a/crypto_sign/sphincs-sha256-256s-simple/clean/hash_sha256.c +++ b/crypto_sign/sphincs-sha256-256s-simple/clean/hash_sha256.c @@ -45,7 +45,7 @@ void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_gen_message_random( const unsigned char *sk_prf, const unsigned char *optrand, const unsigned char *m, size_t mlen) { unsigned char buf[SPX_SHA256_BLOCK_BYTES + SPX_SHA256_OUTPUT_BYTES]; - uint8_t state[40]; + sha256ctx state; int i; /* This implements HMAC-SHA256 */ @@ -54,25 +54,25 @@ void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_gen_message_random( } memset(buf + SPX_N, 0x36, SPX_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_init(state); - sha256_inc_blocks(state, buf, 1); + sha256_inc_init(&state); + sha256_inc_blocks(&state, buf, 1); memcpy(buf, optrand, SPX_N); /* If optrand + message cannot fill up an entire block */ if (SPX_N + mlen < SPX_SHA256_BLOCK_BYTES) { memcpy(buf + SPX_N, m, mlen); - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, + sha256_inc_finalize(buf + SPX_SHA256_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_SHA256_BLOCK_BYTES - SPX_N); - sha256_inc_blocks(state, buf, 1); + sha256_inc_blocks(&state, buf, 1); m += SPX_SHA256_BLOCK_BYTES - SPX_N; mlen -= SPX_SHA256_BLOCK_BYTES - SPX_N; - sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, state, m, mlen); + sha256_inc_finalize(buf + SPX_SHA256_BLOCK_BYTES, &state, m, mlen); } for (i = 0; i < SPX_N; i++) { @@ -108,9 +108,9 @@ void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint8_t state[40]; + sha256ctx state; - sha256_inc_init(state); + sha256_inc_init(&state); memcpy(inbuf, R, SPX_N); memcpy(inbuf + SPX_N, pk, SPX_PK_BYTES); @@ -118,17 +118,17 @@ void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_hash_message( /* If R + pk + message cannot fill up an entire block */ if (SPX_N + SPX_PK_BYTES + mlen < SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES) { memcpy(inbuf + SPX_N + SPX_PK_BYTES, m, mlen); - sha256_inc_finalize(seed, state, inbuf, SPX_N + SPX_PK_BYTES + mlen); + sha256_inc_finalize(seed, &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_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES); - sha256_inc_blocks(state, inbuf, SPX_INBLOCKS); + sha256_inc_blocks(&state, inbuf, SPX_INBLOCKS); m += SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; mlen -= SPX_INBLOCKS * SPX_SHA256_BLOCK_BYTES - SPX_N - SPX_PK_BYTES; - sha256_inc_finalize(seed, state, m, mlen); + sha256_inc_finalize(seed, &state, m, mlen); } /* By doing this in two steps, we prevent hashing the message twice; diff --git a/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.c b/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.c index acaa08e0..4c46b19d 100644 --- a/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.c +++ b/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.c @@ -50,7 +50,7 @@ void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_mgf1( } } -uint8_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded[40]; +sha256ctx PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded; /** * Absorb the constant pub_seed using one round of the compression function @@ -67,6 +67,6 @@ void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_seed_state(const unsigned char *pub_s block[i] = 0; } - sha256_inc_init(PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded); - sha256_inc_blocks(PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded, block, 1); + sha256_inc_init(&PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded); + sha256_inc_blocks(&PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded, block, 1); } diff --git a/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.h b/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.h index a7a557a0..c6dda301 100644 --- a/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.h +++ b/crypto_sign/sphincs-sha256-256s-simple/clean/sha256.h @@ -8,13 +8,15 @@ #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); -extern uint8_t PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded[40]; +extern sha256ctx PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded; void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_seed_state(const unsigned char *pub_seed); diff --git a/crypto_sign/sphincs-sha256-256s-simple/clean/thash_sha256_simple.c b/crypto_sign/sphincs-sha256-256s-simple/clean/thash_sha256_simple.c index 67d008c6..d3a31872 100644 --- a/crypto_sign/sphincs-sha256-256s-simple/clean/thash_sha256_simple.c +++ b/crypto_sign/sphincs-sha256-256s-simple/clean/thash_sha256_simple.c @@ -17,17 +17,17 @@ static void PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_thash( const unsigned char *pub_seed, uint32_t addr[8]) { unsigned char outbuf[SPX_SHA256_OUTPUT_BYTES]; - uint8_t sha2_state[40]; + sha256ctx sha2_state; (void)pub_seed; /* Suppress an 'unused parameter' warning. */ /* Retrieve precomputed state containing pub_seed */ - memcpy(sha2_state, PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded, 40 * sizeof(uint8_t)); + memcpy(&sha2_state, &PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_state_seeded, sizeof(sha256ctx)); PQCLEAN_SPHINCSSHA256256SSIMPLE_CLEAN_compress_address(buf, addr); memcpy(buf + SPX_SHA256_ADDR_BYTES, in, inblocks * SPX_N); - sha256_inc_finalize(outbuf, sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); + sha256_inc_finalize(outbuf, &sha2_state, buf, SPX_SHA256_ADDR_BYTES + inblocks * SPX_N); memcpy(out, outbuf, SPX_N); } From b153768783a9facb2b58890aae8d3b1803f258da Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 10:22:51 +0200 Subject: [PATCH 16/35] Implement ctx struct for fips202 --- common/fips202.c | 98 +++++++++++++++++++++---------------------- common/fips202.h | 67 +++++++++++++++++++++-------- test/common/fips202.c | 82 ++++++++++++++---------------------- 3 files changed, 129 insertions(+), 118 deletions(-) diff --git a/common/fips202.c b/common/fips202.c index ceeb6a5c..0fb29fab 100644 --- a/common/fips202.c +++ b/common/fips202.c @@ -520,36 +520,36 @@ static void keccak_inc_squeeze(uint8_t *h, size_t outlen, } } -void shake128_inc_init(uint64_t *s_inc) { - keccak_inc_init(s_inc); +void shake128_inc_init(shake128incctx *state) { + keccak_inc_init(state->ctx); } -void shake128_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) { - keccak_inc_absorb(s_inc, SHAKE128_RATE, input, inlen); +void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHAKE128_RATE, input, inlen); } -void shake128_inc_finalize(uint64_t *s_inc) { - keccak_inc_finalize(s_inc, SHAKE128_RATE, 0x1F); +void shake128_inc_finalize(shake128incctx *state) { + keccak_inc_finalize(state->ctx, SHAKE128_RATE, 0x1F); } -void shake128_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc) { - keccak_inc_squeeze(output, outlen, s_inc, SHAKE128_RATE); +void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state) { + keccak_inc_squeeze(output, outlen, state->ctx, SHAKE128_RATE); } -void shake256_inc_init(uint64_t *s_inc) { - keccak_inc_init(s_inc); +void shake256_inc_init(shake256incctx *state) { + keccak_inc_init(state->ctx); } -void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) { - keccak_inc_absorb(s_inc, SHAKE256_RATE, input, inlen); +void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHAKE256_RATE, input, inlen); } -void shake256_inc_finalize(uint64_t *s_inc) { - keccak_inc_finalize(s_inc, SHAKE256_RATE, 0x1F); +void shake256_inc_finalize(shake256incctx *state) { + keccak_inc_finalize(state->ctx, SHAKE256_RATE, 0x1F); } -void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc) { - keccak_inc_squeeze(output, outlen, s_inc, SHAKE256_RATE); +void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state) { + keccak_inc_squeeze(output, outlen, state->ctx, SHAKE256_RATE); } @@ -564,8 +564,8 @@ void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc) { * into s * - size_t inlen: length of input in bytes **************************************************/ -void shake128_absorb(uint64_t *s, const uint8_t *input, size_t inlen) { - keccak_absorb(s, SHAKE128_RATE, input, inlen, 0x1F); +void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen) { + keccak_absorb(state->ctx, SHAKE128_RATE, input, inlen, 0x1F); } /************************************************* @@ -578,10 +578,10 @@ void shake128_absorb(uint64_t *s, const uint8_t *input, size_t inlen) { * Arguments: - uint8_t *output: pointer to output blocks * - size_t nblocks: number of blocks to be squeezed * (written to output) - * - uint64_t *s: pointer to input/output Keccak state + * - shake128ctx *state: pointer to input/output Keccak state **************************************************/ -void shake128_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) { - keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE); +void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state) { + keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE128_RATE); } /************************************************* @@ -590,13 +590,13 @@ void shake128_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) { * Description: Absorb step of the SHAKE256 XOF. * non-incremental, starts by zeroeing the state. * - * Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state + * Arguments: - shake256ctx *state: pointer to (uninitialized) output Keccak state * - const uint8_t *input: pointer to input to be absorbed * into s * - size_t inlen: length of input in bytes **************************************************/ -void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen) { - keccak_absorb(s, SHAKE256_RATE, input, inlen, 0x1F); +void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen) { + keccak_absorb(state->ctx, SHAKE256_RATE, input, inlen, 0x1F); } /************************************************* @@ -609,10 +609,10 @@ void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen) { * Arguments: - uint8_t *output: pointer to output blocks * - size_t nblocks: number of blocks to be squeezed * (written to output) - * - uint64_t *s: pointer to input/output Keccak state + * - shake256ctx *state: pointer to input/output Keccak state **************************************************/ -void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s) { - keccak_squeezeblocks(output, nblocks, s, SHAKE256_RATE); +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state) { + keccak_squeezeblocks(output, nblocks, state->ctx, SHAKE256_RATE); } /************************************************* @@ -629,16 +629,16 @@ void shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) { size_t nblocks = outlen / SHAKE128_RATE; uint8_t t[SHAKE128_RATE]; - uint64_t s[25]; + shake128ctx s; - shake128_absorb(s, input, inlen); - shake128_squeezeblocks(output, nblocks, s); + shake128_absorb(&s, input, inlen); + shake128_squeezeblocks(output, nblocks, &s); output += nblocks * SHAKE128_RATE; outlen -= nblocks * SHAKE128_RATE; if (outlen) { - shake128_squeezeblocks(t, 1, s); + shake128_squeezeblocks(t, 1, &s); for (size_t i = 0; i < outlen; ++i) { output[i] = t[i]; } @@ -659,35 +659,35 @@ void shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) { size_t nblocks = outlen / SHAKE256_RATE; uint8_t t[SHAKE256_RATE]; - uint64_t s[25]; + shake256ctx s; - shake256_absorb(s, input, inlen); - shake256_squeezeblocks(output, nblocks, s); + shake256_absorb(&s, input, inlen); + shake256_squeezeblocks(output, nblocks, &s); output += nblocks * SHAKE256_RATE; outlen -= nblocks * SHAKE256_RATE; if (outlen) { - shake256_squeezeblocks(t, 1, s); + shake256_squeezeblocks(t, 1, &s); for (size_t i = 0; i < outlen; ++i) { output[i] = t[i]; } } } -void sha3_256_inc_init(uint64_t *s_inc) { - keccak_inc_init(s_inc); +void sha3_256_inc_init(sha3_256incctx *state) { + keccak_inc_init(state->ctx); } -void sha3_256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) { - keccak_inc_absorb(s_inc, SHA3_256_RATE, input, inlen); +void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHA3_256_RATE, input, inlen); } -void sha3_256_inc_finalize(uint8_t *output, uint64_t *s_inc) { +void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state) { uint8_t t[SHA3_256_RATE]; - keccak_inc_finalize(s_inc, SHA3_256_RATE, 0x06); + keccak_inc_finalize(state->ctx, SHA3_256_RATE, 0x06); - keccak_squeezeblocks(t, 1, s_inc, SHA3_256_RATE); + keccak_squeezeblocks(t, 1, state->ctx, SHA3_256_RATE); for (size_t i = 0; i < 32; i++) { output[i] = t[i]; @@ -718,19 +718,19 @@ void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) { } } -void sha3_512_inc_init(uint64_t *s_inc) { - keccak_inc_init(s_inc); +void sha3_512_inc_init(sha3_512incctx *state) { + keccak_inc_init(state->ctx); } -void sha3_512_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen) { - keccak_inc_absorb(s_inc, SHA3_512_RATE, input, inlen); +void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen) { + keccak_inc_absorb(state->ctx, SHA3_512_RATE, input, inlen); } -void sha3_512_inc_finalize(uint8_t *output, uint64_t *s_inc) { +void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state) { uint8_t t[SHA3_512_RATE]; - keccak_inc_finalize(s_inc, SHA3_512_RATE, 0x06); + keccak_inc_finalize(state->ctx, SHA3_512_RATE, 0x06); - keccak_squeezeblocks(t, 1, s_inc, SHA3_512_RATE); + keccak_squeezeblocks(t, 1, state->ctx, SHA3_512_RATE); for (size_t i = 0; i < 32; i++) { output[i] = t[i]; diff --git a/common/fips202.h b/common/fips202.h index 8971cf5c..622d736a 100644 --- a/common/fips202.h +++ b/common/fips202.h @@ -9,22 +9,53 @@ #define SHA3_256_RATE 136 #define SHA3_512_RATE 72 -void shake128_absorb(uint64_t *s, const uint8_t *input, size_t inlen); -void shake128_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s); +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} shake128incctx; -void shake128_inc_init(uint64_t *s_inc); -void shake128_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void shake128_inc_finalize(uint64_t *s_inc); -void shake128_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc); +// Context for non-incremental API +typedef struct { + uint64_t ctx[25]; +} shake128ctx; -void shake256_absorb(uint64_t *s, const uint8_t *input, size_t inlen); -void shake256_squeezeblocks(uint8_t *output, size_t nblocks, uint64_t *s); +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} shake256incctx; -void shake256_inc_init(uint64_t *s_inc); -void shake256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void shake256_inc_finalize(uint64_t *s_inc); -void shake256_inc_squeeze(uint8_t *output, size_t outlen, uint64_t *s_inc); +// Context for non-incremental API +typedef struct { + uint64_t ctx[25]; +} shake256ctx; + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} sha3_256incctx; + +// Context for incremental API +typedef struct { + uint64_t ctx[26]; +} sha3_512incctx; + +void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen); + +void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state); + +void shake128_inc_init(shake128incctx *state); +void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); +void shake128_inc_finalize(shake128incctx *state); +void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); + +void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen); +void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state); + +void shake256_inc_init(shake256incctx *state); +void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); +void shake256_inc_finalize(shake256incctx *state); +void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); void shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen); @@ -32,15 +63,15 @@ void shake128(uint8_t *output, size_t outlen, void shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen); -void sha3_256_inc_init(uint64_t *s_inc); -void sha3_256_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void sha3_256_inc_finalize(uint8_t *output, uint64_t *s_inc); +void sha3_256_inc_init(sha3_256incctx *state); +void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen); +void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state); void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); -void sha3_512_inc_init(uint64_t *s_inc); -void sha3_512_inc_absorb(uint64_t *s_inc, const uint8_t *input, size_t inlen); -void sha3_512_inc_finalize(uint8_t *output, uint64_t *s_inc); +void sha3_512_inc_init(sha3_512incctx *state); +void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen); +void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state); void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); diff --git a/test/common/fips202.c b/test/common/fips202.c index e7d017d8..9cd09f85 100644 --- a/test/common/fips202.c +++ b/test/common/fips202.c @@ -56,7 +56,7 @@ static int test_sha3_256_incremental(void) { unsigned char input[512]; unsigned char check[32]; unsigned char output[32]; - uint64_t s_inc[26]; + sha3_256incctx state; int i; int absorbed; int returncode = 0; @@ -67,18 +67,18 @@ static int test_sha3_256_incremental(void) { sha3_256(check, input, 512); - sha3_256_inc_init(s_inc); + sha3_256_inc_init(&state); absorbed = 0; for (i = 0; i < 512 && absorbed + i <= 512; i++) { - sha3_256_inc_absorb(s_inc, input + absorbed, i); + sha3_256_inc_absorb(&state, input + absorbed, i); absorbed += i; } - sha3_256_inc_absorb(s_inc, input + absorbed, 512 - absorbed); + sha3_256_inc_absorb(&state, input + absorbed, 512 - absorbed); - sha3_256_inc_finalize(output, s_inc); + sha3_256_inc_finalize(output, &state); - if (memcmp(check, output, 32)) { + if (memcmp(check, output, 32) != 0) { printf("ERROR sha3_256 incremental did not match sha3_256.\n"); printf(" Expected: "); for (i = 0; i < 32; i++) { @@ -100,11 +100,11 @@ static int test_shake128_incremental(void) { unsigned char input[512]; unsigned char check[512]; unsigned char output[512]; - uint64_t s_inc_absorb[26]; - uint64_t s_inc_squeeze[26]; - uint64_t s_inc_squeeze_all[26]; - uint64_t s_inc_both[26]; - uint64_t s_combined[25]; + shake128incctx state_absorb; + shake128incctx state_squeeze; + shake128incctx state_squeeze_all; + shake128incctx state_both; + shake128ctx state_combined; int i; int absorbed; int squeezed; @@ -116,47 +116,27 @@ static int test_shake128_incremental(void) { shake128(check, 512, input, 512); - shake128_inc_init(s_inc_absorb); + shake128_inc_init(&state_absorb); absorbed = 0; for (i = 0; i < 512 && absorbed + i <= 512; i++) { - shake128_inc_absorb(s_inc_absorb, input + absorbed, i); + shake128_inc_absorb(&state_absorb, input + absorbed, i); absorbed += i; } - shake128_inc_absorb(s_inc_absorb, input + absorbed, 512 - absorbed); + shake128_inc_absorb(&state_absorb, input + absorbed, 512 - absorbed); - shake128_inc_finalize(s_inc_absorb); + shake128_inc_finalize(&state_absorb); - shake128_absorb(s_combined, input, 512); + shake128_absorb(&state_combined, input, 512); - if (memcmp(s_inc_absorb, s_combined, 25 * sizeof(uint64_t))) { + if (memcmp(&state_absorb, &state_combined, sizeof(shake128ctx)) != 0) { printf("ERROR shake128 state after incremental absorb did not match all-at-once absorb.\n"); - printf(" Expected: "); - for (i = 0; i < 25; i++) { - printf("%016" PRIx64, s_combined[i]); - } - printf("\n"); - printf(" State: "); - for (i = 0; i < 25; i++) { - printf("%016" PRIx64, s_inc_absorb[i]); - } - printf("\n"); - for (i = 0; i < 8 * 25; i++) { - if (((s_combined[i >> 3] >> (8*(i & 0x7))) & 0xFF) != - ((s_inc_absorb[i >> 3] >> (8*(i & 0x7))) & 0xFF)) { - printf(" First occurred in int %d, byte %d (%02X should be %02X)\n", - i >> 3, i & 0x7, - (uint8_t)((s_inc_absorb[i >> 3] >> (8*(i & 0x7))) & 0xFF), - (uint8_t)((s_combined[i >> 3] >> (8*(i & 0x7))) & 0xFF)); - break; - } - } returncode = 1; } - memcpy(s_inc_both, s_inc_absorb, 26 * sizeof(uint64_t)); + memcpy(&state_both, &state_absorb, sizeof(shake128incctx)); - shake128_squeezeblocks(output, 3, s_inc_absorb); + shake128_squeezeblocks(output, 3, (shake128ctx*)&state_absorb); if (memcmp(check, output, 3*SHAKE128_RATE)) { printf("ERROR shake128 incremental absorb did not match shake128.\n"); @@ -173,14 +153,14 @@ static int test_shake128_incremental(void) { returncode = 1; } - shake128_absorb(s_inc_squeeze, input, 512); - s_inc_squeeze[25] = 0; + shake128_absorb((shake128ctx*)&state_squeeze, input, 512); + state_squeeze.ctx[25] = 0; - memcpy(s_inc_squeeze_all, s_inc_squeeze, 26 * sizeof(uint64_t)); + memcpy(&state_squeeze_all, &state_squeeze, sizeof(shake128incctx)); - shake128_inc_squeeze(output, 512, s_inc_squeeze_all); + shake128_inc_squeeze(output, 512, &state_squeeze_all); - if (memcmp(check, output, 512)) { + if (memcmp(check, output, 512) != 0) { printf("ERROR shake128 incremental squeeze-all did not match shake128.\n"); printf(" Expected: "); for (i = 0; i < 512; i++) { @@ -198,12 +178,12 @@ static int test_shake128_incremental(void) { squeezed = 0; memset(output, 0, 512); for (i = 0; i < 512 && squeezed + i <= 512; i++) { - shake128_inc_squeeze(output + squeezed, i, s_inc_squeeze); + shake128_inc_squeeze(output + squeezed, i, &state_squeeze); squeezed += i; } - shake128_inc_squeeze(output + squeezed, 512 - squeezed, s_inc_squeeze); + shake128_inc_squeeze(output + squeezed, 512 - squeezed, &state_squeeze); - if (memcmp(check, output, 512)) { + if (memcmp(check, output, 512) != 0) { printf("ERROR shake128 incremental squeeze did not match shake128.\n"); printf(" Expected: "); for (i = 0; i < 512; i++) { @@ -221,12 +201,12 @@ static int test_shake128_incremental(void) { squeezed = 0; memset(output, 0, 512); for (i = 0; i < 512 && squeezed + i <= 512; i++) { - shake128_inc_squeeze(output + squeezed, i, s_inc_both); + shake128_inc_squeeze(output + squeezed, i, &state_both); squeezed += i; } - shake128_inc_squeeze(output + squeezed, 512 - squeezed, s_inc_both); + shake128_inc_squeeze(output + squeezed, 512 - squeezed, &state_both); - if (memcmp(check, output, 512)) { + if (memcmp(check, output, 512) != 0) { printf("ERROR shake128 incremental absorb + squeeze did not match shake128.\n"); printf(" Expected: "); for (i = 0; i < 512; i++) { @@ -250,7 +230,7 @@ static int test_shake128(void) { shake128(output, 32, plaintext, 43); - if (memcmp(expected, output, 32)) { + if (memcmp(expected, output, 32) != 0) { printf("ERROR shake128 output did not match test vector.\n"); printf("Expected: "); for (i = 0; i < 32; i++) { From 23e118207dfacf1a30482423f2b1684a89fcffa9 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 10:23:22 +0200 Subject: [PATCH 17/35] Port Kyber{512,768,1024} to fips202 ctx struct --- crypto_kem/kyber1024/clean/symmetric-fips202.c | 10 +++++----- crypto_kem/kyber1024/clean/symmetric.h | 10 +++------- crypto_kem/kyber512/clean/symmetric-fips202.c | 12 ++++++------ crypto_kem/kyber512/clean/symmetric.h | 10 +++------- crypto_kem/kyber768/clean/symmetric-fips202.c | 12 ++++++------ crypto_kem/kyber768/clean/symmetric.h | 10 +++------- 6 files changed, 26 insertions(+), 38 deletions(-) diff --git a/crypto_kem/kyber1024/clean/symmetric-fips202.c b/crypto_kem/kyber1024/clean/symmetric-fips202.c index b1dbf478..8b5c7d8d 100644 --- a/crypto_kem/kyber1024/clean/symmetric-fips202.c +++ b/crypto_kem/kyber1024/clean/symmetric-fips202.c @@ -13,7 +13,7 @@ * - unsigned char i additional byte of input * - unsigned char j additional byte of input **************************************************/ -void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y) { +void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y) { unsigned char extseed[KYBER_SYMBYTES + 2]; int i; @@ -22,7 +22,7 @@ void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsign } extseed[i++] = x; extseed[i] = y; - shake128_absorb(s->s, extseed, KYBER_SYMBYTES + 2); + shake128_absorb(s, extseed, KYBER_SYMBYTES + 2); } /************************************************* @@ -34,10 +34,10 @@ void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsign * * Arguments: - unsigned char *output: pointer to output blocks * - size_t nblocks: number of blocks to be squeezed (written to output) -* - keccak_state *s: pointer to in/output Keccak state +* - shake128ctx *s: pointer to in/output Keccak state **************************************************/ -void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s) { - shake128_squeezeblocks(output, nblocks, s->s); +void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s) { + shake128_squeezeblocks(output, nblocks, s); } /************************************************* diff --git a/crypto_kem/kyber1024/clean/symmetric.h b/crypto_kem/kyber1024/clean/symmetric.h index c67fbd6a..e79560e3 100644 --- a/crypto_kem/kyber1024/clean/symmetric.h +++ b/crypto_kem/kyber1024/clean/symmetric.h @@ -6,12 +6,8 @@ #include -typedef struct { - uint64_t s[25]; -} keccak_state; - -void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y); -void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s); +void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y); +void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s); void PQCLEAN_KYBER1024_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce); #define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES) @@ -23,6 +19,6 @@ void PQCLEAN_KYBER1024_CLEAN_shake256_prf(unsigned char *output, size_t outlen, #define XOF_BLOCKBYTES 168 -typedef keccak_state xof_state; +typedef shake128ctx xof_state; #endif /* SYMMETRIC_H */ diff --git a/crypto_kem/kyber512/clean/symmetric-fips202.c b/crypto_kem/kyber512/clean/symmetric-fips202.c index 345cebb4..cb17e0c2 100644 --- a/crypto_kem/kyber512/clean/symmetric-fips202.c +++ b/crypto_kem/kyber512/clean/symmetric-fips202.c @@ -8,12 +8,12 @@ * * Description: Absorb step of the SHAKE128 specialized for the Kyber context. * -* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state +* Arguments: - shake128ctx *s: pointer to (uninitialized) output Keccak state * - const unsigned char *input: pointer to KYBER_SYMBYTES input to be absorbed into s * - unsigned char i additional byte of input * - unsigned char j additional byte of input **************************************************/ -void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y) { +void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y) { unsigned char extseed[KYBER_SYMBYTES + 2]; int i; @@ -22,7 +22,7 @@ void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigne } extseed[i++] = x; extseed[i] = y; - shake128_absorb(s->s, extseed, KYBER_SYMBYTES + 2); + shake128_absorb(s, extseed, KYBER_SYMBYTES + 2); } /************************************************* @@ -34,10 +34,10 @@ void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigne * * Arguments: - unsigned char *output: pointer to output blocks * - size_t nblocks: number of blocks to be squeezed (written to output) -* - keccak_state *s: pointer to in/output Keccak state +* - shake128ctx *s: pointer to in/output Keccak state **************************************************/ -void PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s) { - shake128_squeezeblocks(output, nblocks, s->s); +void PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s) { + shake128_squeezeblocks(output, nblocks, s); } /************************************************* diff --git a/crypto_kem/kyber512/clean/symmetric.h b/crypto_kem/kyber512/clean/symmetric.h index b0f61aeb..7ad121e1 100644 --- a/crypto_kem/kyber512/clean/symmetric.h +++ b/crypto_kem/kyber512/clean/symmetric.h @@ -4,12 +4,8 @@ #include "fips202.h" #include "params.h" -typedef struct { - uint64_t s[25]; -} keccak_state; - -void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y); -void PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s); +void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y); +void PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s); void PQCLEAN_KYBER512_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce); #define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES) @@ -21,6 +17,6 @@ void PQCLEAN_KYBER512_CLEAN_shake256_prf(unsigned char *output, size_t outlen, c #define XOF_BLOCKBYTES 168 -typedef keccak_state xof_state; +typedef shake128ctx xof_state; #endif /* SYMMETRIC_H */ diff --git a/crypto_kem/kyber768/clean/symmetric-fips202.c b/crypto_kem/kyber768/clean/symmetric-fips202.c index 3d4e858c..c9e16068 100644 --- a/crypto_kem/kyber768/clean/symmetric-fips202.c +++ b/crypto_kem/kyber768/clean/symmetric-fips202.c @@ -8,12 +8,12 @@ * * Description: Absorb step of the SHAKE128 specialized for the Kyber context. * -* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state +* Arguments: - shake128ctx *s: pointer to (uninitialized) output Keccak state * - const unsigned char *input: pointer to KYBER_SYMBYTES input to be absorbed into s * - unsigned char i additional byte of input * - unsigned char j additional byte of input **************************************************/ -void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y) { +void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y) { unsigned char extseed[KYBER_SYMBYTES + 2]; int i; @@ -22,7 +22,7 @@ void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigne } extseed[i++] = x; extseed[i] = y; - shake128_absorb(s->s, extseed, KYBER_SYMBYTES + 2); + shake128_absorb(s, extseed, KYBER_SYMBYTES + 2); } /************************************************* @@ -34,10 +34,10 @@ void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigne * * Arguments: - unsigned char *output: pointer to output blocks * - size_t nblocks: number of blocks to be squeezed (written to output) -* - keccak_state *s: pointer to in/output Keccak state +* - shake128ctx *s: pointer to in/output Keccak state **************************************************/ -void PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s) { - shake128_squeezeblocks(output, nblocks, s->s); +void PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s) { + shake128_squeezeblocks(output, nblocks, s); } /************************************************* diff --git a/crypto_kem/kyber768/clean/symmetric.h b/crypto_kem/kyber768/clean/symmetric.h index 7cdff295..b2c5126a 100644 --- a/crypto_kem/kyber768/clean/symmetric.h +++ b/crypto_kem/kyber768/clean/symmetric.h @@ -4,12 +4,8 @@ #include "fips202.h" #include "params.h" -typedef struct { - uint64_t s[25]; -} keccak_state; - -void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y); -void PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s); +void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(shake128ctx *s, const unsigned char *input, unsigned char x, unsigned char y); +void PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, shake128ctx *s); void PQCLEAN_KYBER768_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce); #define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES) @@ -21,6 +17,6 @@ void PQCLEAN_KYBER768_CLEAN_shake256_prf(unsigned char *output, size_t outlen, c #define XOF_BLOCKBYTES 168 -typedef keccak_state xof_state; +typedef shake128ctx xof_state; #endif /* SYMMETRIC_H */ From 98002329ad0b765c0d947e6613516d5f2dab45ea Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 10:30:35 +0200 Subject: [PATCH 18/35] Port NewHope to fips202 structs --- crypto_kem/newhope1024cca/clean/poly.c | 6 +++--- crypto_kem/newhope1024cpa/clean/poly.c | 6 +++--- crypto_kem/newhope512cca/clean/poly.c | 6 +++--- crypto_kem/newhope512cpa/clean/poly.c | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/crypto_kem/newhope1024cca/clean/poly.c b/crypto_kem/newhope1024cca/clean/poly.c index 2ede9dea..10ec5535 100644 --- a/crypto_kem/newhope1024cca/clean/poly.c +++ b/crypto_kem/newhope1024cca/clean/poly.c @@ -202,7 +202,7 @@ void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { unsigned int ctr = 0; uint16_t val; - uint64_t state[25]; + shake128ctx state; uint8_t buf[SHAKE128_RATE]; uint8_t extseed[NEWHOPE_SYMBYTES + 1]; int i, j; @@ -214,9 +214,9 @@ void PQCLEAN_NEWHOPE1024CCA_CLEAN_poly_uniform(poly *a, const unsigned char *see for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ ctr = 0; extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ - shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + shake128_absorb(&state, extseed, NEWHOPE_SYMBYTES + 1); while (ctr < 64) { /* Very unlikely to run more than once */ - shake128_squeezeblocks(buf, 1, state); + shake128_squeezeblocks(buf, 1, &state); for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); if (val < 5 * NEWHOPE_Q) { diff --git a/crypto_kem/newhope1024cpa/clean/poly.c b/crypto_kem/newhope1024cpa/clean/poly.c index 5ab00927..f9b4cce8 100644 --- a/crypto_kem/newhope1024cpa/clean/poly.c +++ b/crypto_kem/newhope1024cpa/clean/poly.c @@ -202,7 +202,7 @@ void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { unsigned int ctr = 0; uint16_t val; - uint64_t state[25]; + shake128ctx state; uint8_t buf[SHAKE128_RATE]; uint8_t extseed[NEWHOPE_SYMBYTES + 1]; int i, j; @@ -214,9 +214,9 @@ void PQCLEAN_NEWHOPE1024CPA_CLEAN_poly_uniform(poly *a, const unsigned char *see for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ ctr = 0; extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ - shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + shake128_absorb(&state, extseed, NEWHOPE_SYMBYTES + 1); while (ctr < 64) { /* Very unlikely to run more than once */ - shake128_squeezeblocks(buf, 1, state); + shake128_squeezeblocks(buf, 1, &state); for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); if (val < 5 * NEWHOPE_Q) { diff --git a/crypto_kem/newhope512cca/clean/poly.c b/crypto_kem/newhope512cca/clean/poly.c index b8075df5..aa3175f0 100644 --- a/crypto_kem/newhope512cca/clean/poly.c +++ b/crypto_kem/newhope512cca/clean/poly.c @@ -198,7 +198,7 @@ void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { unsigned int ctr = 0; uint16_t val; - uint64_t state[25]; + shake128ctx state; uint8_t buf[SHAKE128_RATE]; uint8_t extseed[NEWHOPE_SYMBYTES + 1]; int i, j; @@ -210,9 +210,9 @@ void PQCLEAN_NEWHOPE512CCA_CLEAN_poly_uniform(poly *a, const unsigned char *seed for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ ctr = 0; extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ - shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + shake128_absorb(&state, extseed, NEWHOPE_SYMBYTES + 1); while (ctr < 64) { /* Very unlikely to run more than once */ - shake128_squeezeblocks(buf, 1, state); + shake128_squeezeblocks(buf, 1, &state); for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); if (val < 5 * NEWHOPE_Q) { diff --git a/crypto_kem/newhope512cpa/clean/poly.c b/crypto_kem/newhope512cpa/clean/poly.c index 364c7af6..6bd47ae6 100644 --- a/crypto_kem/newhope512cpa/clean/poly.c +++ b/crypto_kem/newhope512cpa/clean/poly.c @@ -198,7 +198,7 @@ void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_tomsg(unsigned char *msg, const poly *x) { void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed) { unsigned int ctr = 0; uint16_t val; - uint64_t state[25]; + shake128ctx state; uint8_t buf[SHAKE128_RATE]; uint8_t extseed[NEWHOPE_SYMBYTES + 1]; int i, j; @@ -210,9 +210,9 @@ void PQCLEAN_NEWHOPE512CPA_CLEAN_poly_uniform(poly *a, const unsigned char *seed for (i = 0; i < NEWHOPE_N / 64; i++) { /* generate a in blocks of 64 coefficients */ ctr = 0; extseed[NEWHOPE_SYMBYTES] = (unsigned char) i; /* domain-separate the 16 independent calls */ - shake128_absorb(state, extseed, NEWHOPE_SYMBYTES + 1); + shake128_absorb(&state, extseed, NEWHOPE_SYMBYTES + 1); while (ctr < 64) { /* Very unlikely to run more than once */ - shake128_squeezeblocks(buf, 1, state); + shake128_squeezeblocks(buf, 1, &state); for (j = 0; j < SHAKE128_RATE && ctr < 64; j += 2) { val = (buf[j] | ((uint16_t) buf[j + 1] << 8)); if (val < 5 * NEWHOPE_Q) { From 692fba119c424503cb4c5975b74ad47b31f39033 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 10:38:31 +0200 Subject: [PATCH 19/35] Port SPHINCS+-SHAKE256 to fips202 ctx structs --- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- .../clean/hash_shake256.c | 28 +++++++++---------- 12 files changed, 168 insertions(+), 168 deletions(-) diff --git a/crypto_sign/sphincs-shake256-128f-robust/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-128f-robust/clean/hash_shake256.c index 9603b8c8..d3b7ac7d 100644 --- a/crypto_sign/sphincs-shake256-128f-robust/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-128f-robust/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256128FROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-128f-simple/clean/hash_shake256.c index 68103a41..bd6894ca 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256128FSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-128s-robust/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-128s-robust/clean/hash_shake256.c index f636a41f..a897adf6 100644 --- a/crypto_sign/sphincs-shake256-128s-robust/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-128s-robust/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256128SROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-128s-simple/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-128s-simple/clean/hash_shake256.c index 2408a3e0..74d4ffeb 100644 --- a/crypto_sign/sphincs-shake256-128s-simple/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-128s-simple/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256128SSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-192f-robust/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-192f-robust/clean/hash_shake256.c index 6e5b7b07..49c8ae7b 100644 --- a/crypto_sign/sphincs-shake256-192f-robust/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-192f-robust/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256192FROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-192f-simple/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-192f-simple/clean/hash_shake256.c index d970155e..82e4430e 100644 --- a/crypto_sign/sphincs-shake256-192f-simple/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-192f-simple/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256192FSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-192s-robust/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-192s-robust/clean/hash_shake256.c index 6b4e0656..0181d11e 100644 --- a/crypto_sign/sphincs-shake256-192s-robust/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-192s-robust/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256192SROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-192s-simple/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-192s-simple/clean/hash_shake256.c index 5c79d478..7129db40 100644 --- a/crypto_sign/sphincs-shake256-192s-simple/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-192s-simple/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256192SSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-256f-robust/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-256f-robust/clean/hash_shake256.c index 308338b4..8fbf5cbf 100644 --- a/crypto_sign/sphincs-shake256-256f-robust/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-256f-robust/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256256FROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-256f-simple/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-256f-simple/clean/hash_shake256.c index db8875d7..9a1306e9 100644 --- a/crypto_sign/sphincs-shake256-256f-simple/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-256f-simple/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256256FSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-256s-robust/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-256s-robust/clean/hash_shake256.c index 41146c98..5aeb3db4 100644 --- a/crypto_sign/sphincs-shake256-256s-robust/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-256s-robust/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256256SROBUST_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; diff --git a/crypto_sign/sphincs-shake256-256s-simple/clean/hash_shake256.c b/crypto_sign/sphincs-shake256-256s-simple/clean/hash_shake256.c index a0982585..acc211fb 100644 --- a/crypto_sign/sphincs-shake256-256s-simple/clean/hash_shake256.c +++ b/crypto_sign/sphincs-shake256-256s-simple/clean/hash_shake256.c @@ -37,14 +37,14 @@ 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) { - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, sk_prf, SPX_N); + shake256_inc_absorb(&state, optrand, SPX_N); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(R, SPX_N, &state); } /** @@ -64,14 +64,14 @@ void PQCLEAN_SPHINCSSHAKE256256SSIMPLE_CLEAN_hash_message( unsigned char buf[SPX_DGST_BYTES]; unsigned char *bufp = buf; - uint64_t s_inc[26]; + shake256incctx state; - 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_init(&state); + shake256_inc_absorb(&state, R, SPX_N); + shake256_inc_absorb(&state, pk, SPX_PK_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(buf, SPX_DGST_BYTES, &state); memcpy(digest, bufp, SPX_FORS_MSG_BYTES); bufp += SPX_FORS_MSG_BYTES; From 0e73f2dda2ca8811b53e2026a14d2fe5f3830526 Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 10:52:28 +0200 Subject: [PATCH 20/35] Use opaque fips202 structs in MQDSS --- crypto_sign/mqdss-48/clean/gf31.c | 12 +++---- crypto_sign/mqdss-48/clean/sign.c | 54 +++++++++++++++---------------- crypto_sign/mqdss-64/clean/gf31.c | 12 +++---- crypto_sign/mqdss-64/clean/sign.c | 54 +++++++++++++++---------------- 4 files changed, 66 insertions(+), 66 deletions(-) diff --git a/crypto_sign/mqdss-48/clean/gf31.c b/crypto_sign/mqdss-48/clean/gf31.c index e6c7fc4f..9a5f2df0 100644 --- a/crypto_sign/mqdss-48/clean/gf31.c +++ b/crypto_sign/mqdss-48/clean/gf31.c @@ -49,13 +49,13 @@ void PQCLEAN_MQDSS48_CLEAN_vgf31_shorten_unique(gf31 *out, const gf31 *in) { them in a vector of 16-bit elements */ void PQCLEAN_MQDSS48_CLEAN_gf31_nrand(gf31 *out, int len, const unsigned char *seed, size_t seedlen) { int i = 0, j; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; - shake256_absorb(shakestate, seed, seedlen); + shake256_absorb(&shakestate, seed, seedlen); while (i < len) { - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); for (j = 0; j < SHAKE256_RATE && i < len; j++) { if ((shakeblock[j] & 31) != 31) { out[i] = (shakeblock[j] & 31); @@ -70,13 +70,13 @@ void PQCLEAN_MQDSS48_CLEAN_gf31_nrand(gf31 *out, int len, const unsigned char *s This is used for the expansion of F, which wants packed elements. */ void PQCLEAN_MQDSS48_CLEAN_gf31_nrand_schar(signed char *out, int len, const unsigned char *seed, size_t seedlen) { int i = 0, j; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; - shake256_absorb(shakestate, seed, seedlen); + shake256_absorb(&shakestate, seed, seedlen); while (i < len) { - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); for (j = 0; j < SHAKE256_RATE && i < len; j++) { if ((shakeblock[j] & 31) != 31) { out[i] = (signed char)(((signed char)shakeblock[j] & 31) - 15); diff --git a/crypto_sign/mqdss-48/clean/sign.c b/crypto_sign/mqdss-48/clean/sign.c index 38de45dc..01d67ef9 100644 --- a/crypto_sign/mqdss-48/clean/sign.c +++ b/crypto_sign/mqdss-48/clean/sign.c @@ -85,7 +85,7 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_signature( unsigned char *h0 = D_sigma0_h0_sigma1 + 2 * HASH_BYTES; unsigned char *t1packed = D_sigma0_h0_sigma1 + 3 * HASH_BYTES; unsigned char *e1packed = D_sigma0_h0_sigma1 + 3 * HASH_BYTES + ROUNDS * NPACKED_BYTES; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; unsigned char h1[((ROUNDS + 7) & ~7) >> 3]; unsigned char rnd_seed[HASH_BYTES + SEED_BYTES]; @@ -109,17 +109,17 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_signature( int alpha_count = 0; int b; int i, j; - uint64_t s_inc[26]; + shake256incctx state; shake256(skbuf, SEED_BYTES * 4, sk, SEED_BYTES); PQCLEAN_MQDSS48_CLEAN_gf31_nrand_schar(F, F_LEN, skbuf, SEED_BYTES); - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, sk, SEED_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(sig, HASH_BYTES, s_inc); // Compute R. + shake256_inc_init(&state); + shake256_inc_absorb(&state, sk, SEED_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(sig, HASH_BYTES, &state); // Compute R. memcpy(pk, skbuf, SEED_BYTES); PQCLEAN_MQDSS48_CLEAN_gf31_nrand(sk_gf31, N, skbuf + SEED_BYTES, SEED_BYTES); @@ -127,12 +127,12 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_signature( PQCLEAN_MQDSS48_CLEAN_vgf31_unique(pk_gf31, pk_gf31); PQCLEAN_MQDSS48_CLEAN_gf31_npack(pk + SEED_BYTES, pk_gf31, M); - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, pk, PK_BYTES); - shake256_inc_absorb(s_inc, sig, HASH_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(D, HASH_BYTES, s_inc); + shake256_inc_init(&state); + shake256_inc_absorb(&state, pk, PK_BYTES); + shake256_inc_absorb(&state, sig, HASH_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(D, HASH_BYTES, &state); sig += HASH_BYTES; // Compensate for prefixed R. @@ -166,8 +166,8 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_signature( } H(sigma0, c, HASH_BYTES * ROUNDS * 2); // Compute sigma_0. - shake256_absorb(shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_absorb(&shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); + shake256_squeezeblocks(shakeblock, 1, &shakestate); memcpy(h0, shakeblock, HASH_BYTES); @@ -180,7 +180,7 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_signature( alpha_count++; if (alpha_count == SHAKE256_RATE) { alpha_count = 0; - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); } } while (alpha == 31); for (j = 0; j < N; j++) { @@ -246,24 +246,24 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_verify( gf31 z[M]; unsigned char packbuf0[NPACKED_BYTES]; unsigned char packbuf1[MPACKED_BYTES]; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; int i, j; gf31 alpha; int alpha_count = 0; int b; - uint64_t s_inc[26]; + shake256incctx state; if (siglen != SIG_LEN) { return -1; } - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, pk, PK_BYTES); - shake256_inc_absorb(s_inc, sig, HASH_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(D, HASH_BYTES, s_inc); + shake256_inc_init(&state); + shake256_inc_absorb(&state, pk, PK_BYTES); + shake256_inc_absorb(&state, sig, HASH_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(D, HASH_BYTES, &state); sig += HASH_BYTES; @@ -273,8 +273,8 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_verify( memcpy(sigma0, sig, HASH_BYTES); - shake256_absorb(shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_absorb(&shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); + shake256_squeezeblocks(shakeblock, 1, &shakestate); memcpy(h0, shakeblock, HASH_BYTES); @@ -293,7 +293,7 @@ int PQCLEAN_MQDSS48_CLEAN_crypto_sign_verify( alpha_count++; if (alpha_count == SHAKE256_RATE) { alpha_count = 0; - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); } } while (alpha == 31); b = (h1[(i >> 3)] >> (i & 7)) & 1; diff --git a/crypto_sign/mqdss-64/clean/gf31.c b/crypto_sign/mqdss-64/clean/gf31.c index 2b564739..54bb7da5 100644 --- a/crypto_sign/mqdss-64/clean/gf31.c +++ b/crypto_sign/mqdss-64/clean/gf31.c @@ -49,13 +49,13 @@ void PQCLEAN_MQDSS64_CLEAN_vgf31_shorten_unique(gf31 *out, const gf31 *in) { them in a vector of 16-bit elements */ void PQCLEAN_MQDSS64_CLEAN_gf31_nrand(gf31 *out, int len, const unsigned char *seed, size_t seedlen) { int i = 0, j; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; - shake256_absorb(shakestate, seed, seedlen); + shake256_absorb(&shakestate, seed, seedlen); while (i < len) { - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); for (j = 0; j < SHAKE256_RATE && i < len; j++) { if ((shakeblock[j] & 31) != 31) { out[i] = (shakeblock[j] & 31); @@ -70,13 +70,13 @@ void PQCLEAN_MQDSS64_CLEAN_gf31_nrand(gf31 *out, int len, const unsigned char *s This is used for the expansion of F, which wants packed elements. */ void PQCLEAN_MQDSS64_CLEAN_gf31_nrand_schar(signed char *out, int len, const unsigned char *seed, size_t seedlen) { int i = 0, j; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; - shake256_absorb(shakestate, seed, seedlen); + shake256_absorb(&shakestate, seed, seedlen); while (i < len) { - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); for (j = 0; j < SHAKE256_RATE && i < len; j++) { if ((shakeblock[j] & 31) != 31) { out[i] = (signed char)(((signed char)shakeblock[j] & 31) - 15); diff --git a/crypto_sign/mqdss-64/clean/sign.c b/crypto_sign/mqdss-64/clean/sign.c index 681799c9..189b70f8 100644 --- a/crypto_sign/mqdss-64/clean/sign.c +++ b/crypto_sign/mqdss-64/clean/sign.c @@ -85,7 +85,7 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_signature( unsigned char *h0 = D_sigma0_h0_sigma1 + 2 * HASH_BYTES; unsigned char *t1packed = D_sigma0_h0_sigma1 + 3 * HASH_BYTES; unsigned char *e1packed = D_sigma0_h0_sigma1 + 3 * HASH_BYTES + ROUNDS * NPACKED_BYTES; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; unsigned char h1[((ROUNDS + 7) & ~7) >> 3]; unsigned char rnd_seed[HASH_BYTES + SEED_BYTES]; @@ -109,17 +109,17 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_signature( int alpha_count = 0; int b; int i, j; - uint64_t s_inc[26]; + shake256incctx state; shake256(skbuf, SEED_BYTES * 4, sk, SEED_BYTES); PQCLEAN_MQDSS64_CLEAN_gf31_nrand_schar(F, F_LEN, skbuf, SEED_BYTES); - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, sk, SEED_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(sig, HASH_BYTES, s_inc); // Compute R. + shake256_inc_init(&state); + shake256_inc_absorb(&state, sk, SEED_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(sig, HASH_BYTES, &state); // Compute R. memcpy(pk, skbuf, SEED_BYTES); PQCLEAN_MQDSS64_CLEAN_gf31_nrand(sk_gf31, N, skbuf + SEED_BYTES, SEED_BYTES); @@ -127,12 +127,12 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_signature( PQCLEAN_MQDSS64_CLEAN_vgf31_unique(pk_gf31, pk_gf31); PQCLEAN_MQDSS64_CLEAN_gf31_npack(pk + SEED_BYTES, pk_gf31, M); - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, pk, PK_BYTES); - shake256_inc_absorb(s_inc, sig, HASH_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(D, HASH_BYTES, s_inc); + shake256_inc_init(&state); + shake256_inc_absorb(&state, pk, PK_BYTES); + shake256_inc_absorb(&state, sig, HASH_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(D, HASH_BYTES, &state); sig += HASH_BYTES; // Compensate for prefixed R. @@ -166,8 +166,8 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_signature( } H(sigma0, c, HASH_BYTES * ROUNDS * 2); // Compute sigma_0. - shake256_absorb(shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_absorb(&shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); + shake256_squeezeblocks(shakeblock, 1, &shakestate); memcpy(h0, shakeblock, HASH_BYTES); @@ -180,7 +180,7 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_signature( alpha_count++; if (alpha_count == SHAKE256_RATE) { alpha_count = 0; - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); } } while (alpha == 31); for (j = 0; j < N; j++) { @@ -246,24 +246,24 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_verify( gf31 z[M]; unsigned char packbuf0[NPACKED_BYTES]; unsigned char packbuf1[MPACKED_BYTES]; - uint64_t shakestate[25] = {0}; + shake256ctx shakestate; unsigned char shakeblock[SHAKE256_RATE]; int i, j; gf31 alpha; int alpha_count = 0; int b; - uint64_t s_inc[26]; + shake256incctx state; if (siglen != SIG_LEN) { return -1; } - shake256_inc_init(s_inc); - shake256_inc_absorb(s_inc, pk, PK_BYTES); - shake256_inc_absorb(s_inc, sig, HASH_BYTES); - shake256_inc_absorb(s_inc, m, mlen); - shake256_inc_finalize(s_inc); - shake256_inc_squeeze(D, HASH_BYTES, s_inc); + shake256_inc_init(&state); + shake256_inc_absorb(&state, pk, PK_BYTES); + shake256_inc_absorb(&state, sig, HASH_BYTES); + shake256_inc_absorb(&state, m, mlen); + shake256_inc_finalize(&state); + shake256_inc_squeeze(D, HASH_BYTES, &state); sig += HASH_BYTES; @@ -273,8 +273,8 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_verify( memcpy(sigma0, sig, HASH_BYTES); - shake256_absorb(shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_absorb(&shakestate, D_sigma0_h0_sigma1, 2 * HASH_BYTES); + shake256_squeezeblocks(shakeblock, 1, &shakestate); memcpy(h0, shakeblock, HASH_BYTES); @@ -293,7 +293,7 @@ int PQCLEAN_MQDSS64_CLEAN_crypto_sign_verify( alpha_count++; if (alpha_count == SHAKE256_RATE) { alpha_count = 0; - shake256_squeezeblocks(shakeblock, 1, shakestate); + shake256_squeezeblocks(shakeblock, 1, &shakestate); } } while (alpha == 31); b = (h1[(i >> 3)] >> (i & 7)) & 1; From a4906713be256046bd1454df4a7bf0da673222b3 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Mon, 20 May 2019 15:12:51 +0200 Subject: [PATCH 21/35] use optimized matrix_shake.c for frodokem640shake --- crypto_kem/frodokem640shake/META.yml | 2 + crypto_kem/frodokem640shake/opt/LICENSE | 21 ++ crypto_kem/frodokem640shake/opt/Makefile | 19 ++ .../opt/Makefile.Microsoft_nmake | 19 ++ crypto_kem/frodokem640shake/opt/api.h | 20 ++ crypto_kem/frodokem640shake/opt/common.h | 19 ++ crypto_kem/frodokem640shake/opt/kem.c | 238 ++++++++++++++++++ .../frodokem640shake/opt/matrix_shake.c | 206 +++++++++++++++ crypto_kem/frodokem640shake/opt/noise.c | 35 +++ crypto_kem/frodokem640shake/opt/params.h | 27 ++ crypto_kem/frodokem640shake/opt/util.c | 235 +++++++++++++++++ 11 files changed, 841 insertions(+) create mode 100644 crypto_kem/frodokem640shake/opt/LICENSE create mode 100644 crypto_kem/frodokem640shake/opt/Makefile create mode 100644 crypto_kem/frodokem640shake/opt/Makefile.Microsoft_nmake create mode 100644 crypto_kem/frodokem640shake/opt/api.h create mode 100644 crypto_kem/frodokem640shake/opt/common.h create mode 100644 crypto_kem/frodokem640shake/opt/kem.c create mode 100644 crypto_kem/frodokem640shake/opt/matrix_shake.c create mode 100644 crypto_kem/frodokem640shake/opt/noise.c create mode 100644 crypto_kem/frodokem640shake/opt/params.h create mode 100644 crypto_kem/frodokem640shake/opt/util.c diff --git a/crypto_kem/frodokem640shake/META.yml b/crypto_kem/frodokem640shake/META.yml index 99e685c5..2a37b7f9 100644 --- a/crypto_kem/frodokem640shake/META.yml +++ b/crypto_kem/frodokem640shake/META.yml @@ -23,3 +23,5 @@ auxiliary-submitters: implementations: - name: clean version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 +- name: opt + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 diff --git a/crypto_kem/frodokem640shake/opt/LICENSE b/crypto_kem/frodokem640shake/opt/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/crypto_kem/frodokem640shake/opt/Makefile b/crypto_kem/frodokem640shake/opt/Makefile new file mode 100644 index 00000000..6059e5df --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem640shake_opt.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_shake.o noise.o util.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/frodokem640shake/opt/Makefile.Microsoft_nmake b/crypto_kem/frodokem640shake/opt/Makefile.Microsoft_nmake new file mode 100644 index 00000000..3a590958 --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libfrodokem640shake_opt.lib +OBJECTS=kem.obj matrix_shake.obj noise.obj util.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/frodokem640shake/opt/api.h b/crypto_kem/frodokem640shake/opt/api.h new file mode 100644 index 00000000..c63d9f9d --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM640SHAKE_OPT_API_H +#define PQCLEAN_FRODOKEM640SHAKE_OPT_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_SECRETKEYBYTES 19888 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_PUBLICKEYBYTES 9616 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_BYTES 16 +#define PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_CIPHERTEXTBYTES 9720 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_ALGNAME "FrodoKEM-640-SHAKE" + +int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem640shake/opt/common.h b/crypto_kem/frodokem640shake/opt/common.h new file mode 100644 index 00000000..2910c84f --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/common.h @@ -0,0 +1,19 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(uint16_t *s, size_t n); +void PQCLEAN_FRODOKEM640SHAKE_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM640SHAKE_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM640SHAKE_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM640SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM640SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM640SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(uint16_t n); + +#endif diff --git a/crypto_kem/frodokem640shake/opt/kem.c b/crypto_kem/frodokem640shake/opt/kem.c new file mode 100644 index 00000000..50bb88c8 --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/kem.c @@ -0,0 +1,238 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" +#include "randombytes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + // FrodoKEM's key generation + // Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes) + // secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH bytes) + uint8_t *pk_seedA = &pk[0]; + uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *sk_s = &sk[0]; + uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + uint8_t *sk_S = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t S[2 * PARAMS_N * PARAMS_NBAR] = {0}; // contains secret data + uint16_t *E = &S[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t randomness[2 * CRYPTO_BYTES + BYTES_SEED_A]; // contains secret data via randomness_s and randomness_seedSE + uint8_t *randomness_s = &randomness[0]; // contains secret data + uint8_t *randomness_seedSE = &randomness[CRYPTO_BYTES]; // contains secret data + uint8_t *randomness_z = &randomness[2 * CRYPTO_BYTES]; + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // Generate the secret value s, the seed for S and E, and the seed for the seed for A. Add seed_A to the public key + randombytes(randomness, CRYPTO_BYTES + CRYPTO_BYTES + BYTES_SEED_A); + shake(pk_seedA, BYTES_SEED_A, randomness_z, BYTES_SEED_A); + + // Generate S and E, and compute B = A*S + E. Generate A on-the-fly + shake_input_seedSE[0] = 0x5F; + memcpy(&shake_input_seedSE[1], randomness_seedSE, CRYPTO_BYTES); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < 2 * PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(S[i]); + } + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(E, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM640SHAKE_OPT_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Add s, pk and S to the secret key + memcpy(sk_s, randomness_s, CRYPTO_BYTES); + memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(S[i]); + } + memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); + + // Add H(pk) to the secret key + shake(sk_pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + + // Cleanup: + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(randomness, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + // FrodoKEM's key encapsulation + const uint8_t *pk_seedA = &pk[0]; + const uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *ct_c1 = &ct[0]; + uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t V[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via mu + uint8_t *pkh = &G2in[0]; + uint8_t *mu = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSE = &G2out[0]; // contains secret data + uint8_t *k = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // pkh <- G_1(pk), generate random mu, compute (seedSE || k) = G_2(pkh || mu) + shake(pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + randombytes(mu, BYTES_MU); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSE[0] = 0x96; + memcpy(&shake_input_seedSE[1], seedSE, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM640SHAKE_OPT_pack(ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Generate Epp, and compute V = Sp*B + Epp + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM640SHAKE_OPT_key_encode(C, (uint16_t *)mu); + PQCLEAN_FRODOKEM640SHAKE_OPT_add(C, V, C); + PQCLEAN_FRODOKEM640SHAKE_OPT_pack(ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ); + + // Compute ss = F(ct||KK) + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + memcpy(Fin_k, k, CRYPTO_BYTES); + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM640SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + // FrodoKEM's key decapsulation + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t W[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t CC[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t BBp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *ct_c1 = &ct[0]; + const uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + const uint8_t *sk_s = &sk[0]; + const uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + const uint16_t *sk_S = (uint16_t *) &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint16_t S[PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + const uint8_t *pk_seedA = &sk_pk[0]; + const uint8_t *pk_b = &sk_pk[BYTES_SEED_A]; + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via muprime + uint8_t *pkh = &G2in[0]; + uint8_t *muprime = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSEprime = &G2out[0]; // contains secret data + uint8_t *kprime = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data + + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(sk_S[i]); + } + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_OPT_mul_bs(W, Bp, S); + PQCLEAN_FRODOKEM640SHAKE_OPT_sub(W, C, W); + PQCLEAN_FRODOKEM640SHAKE_OPT_key_decode((uint16_t *)muprime, W); + + // Generate (seedSE' || k') = G_2(pkh || mu') + memcpy(pkh, sk_pkh, BYTES_PKHASH); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSEprime[0] = 0x96; + memcpy(&shake_input_seedSEprime[1], seedSEprime, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM640SHAKE_OPT_key_encode(CC, (uint16_t *)muprime); + PQCLEAN_FRODOKEM640SHAKE_OPT_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); + } + + // Is (Bp == BBp & C == CC) = true + if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { + // Load k' to do ss = F(ct || k') + memcpy(Fin_k, kprime, CRYPTO_BYTES); + } else { + // Load s to do ss = F(ct || s) + memcpy(Fin_k, sk_s, CRYPTO_BYTES); + } + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem640shake/opt/matrix_shake.c b/crypto_kem/frodokem640shake/opt/matrix_shake.c new file mode 100644 index 00000000..0eb59f6b --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/matrix_shake.c @@ -0,0 +1,206 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" + +#include "api.h" +#include "common.h" +#include "params.h" +#define USE_SHAKE128_FOR_A + +int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. + // Inputs: s, e (N x N_BAR) + // Output: out = A*s + e (N x N_BAR) + int i, j, k; + int16_t a_row[4 * PARAMS_N] = {0}; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + #if defined(USE_AES128_FOR_A) + int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once + #if !defined(USE_OPENSSL) + uint8_t aes_key_schedule[16 * 11]; + AES128_load_schedule(seed_A, aes_key_schedule); + #else + EVP_CIPHER_CTX *aes_key_schedule; + int len; + if (!(aes_key_schedule = EVP_CIPHER_CTX_new())) { + handleErrors(); + } + if (1 != EVP_EncryptInit_ex(aes_key_schedule, EVP_aes_128_ecb(), NULL, seed_A, NULL)) { + handleErrors(); + } + #endif + + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { + a_row_temp[j + 1 + 0 * PARAMS_N] = j; // Loading values in the little-endian order + a_row_temp[j + 1 + 1 * PARAMS_N] = j; + a_row_temp[j + 1 + 2 * PARAMS_N] = j; + a_row_temp[j + 1 + 3 * PARAMS_N] = j; + } + + for (i = 0; i < PARAMS_N; i += 4) { + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time + a_row_temp[j + 0 * PARAMS_N] = i + 0; // Loading values in the little-endian order + a_row_temp[j + 1 * PARAMS_N] = i + 1; + a_row_temp[j + 2 * PARAMS_N] = i + 2; + a_row_temp[j + 3 * PARAMS_N] = i + 3; + } + + #if !defined(USE_OPENSSL) + AES128_ECB_enc_sch((uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t), aes_key_schedule, (uint8_t *)a_row); + #else + if (1 != EVP_EncryptUpdate(aes_key_schedule, (uint8_t *)a_row, &len, (uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t))) { + handleErrors(); + } + #endif + #elif defined (USE_SHAKE128_FOR_A) + uint8_t seed_A_separated[2 + BYTES_SEED_A]; + uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; + memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); + for (i = 0; i < PARAMS_N; i += 4) { + seed_A_origin[0] = (uint16_t) (i + 0); + shake128((unsigned char *)(a_row + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = (uint16_t) (i + 1); + shake128((unsigned char *)(a_row + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = (uint16_t) (i + 2); + shake128((unsigned char *)(a_row + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = (uint16_t) (i + 3); + shake128((unsigned char *)(a_row + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + #endif + + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum[4] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[k * PARAMS_N + j]; + sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s + sum[1] += a_row[1 * PARAMS_N + j] * sp; + sum[2] += a_row[2 * PARAMS_N + j] * sp; + sum[3] += a_row[3 * PARAMS_N + j] * sp; + } + out[(i + 0)*PARAMS_NBAR + k] += sum[0]; + out[(i + 2)*PARAMS_NBAR + k] += sum[2]; + out[(i + 1)*PARAMS_NBAR + k] += sum[1]; + out[(i + 3)*PARAMS_NBAR + k] += sum[3]; + } + } + + #if defined(USE_AES128_FOR_A) + AES128_free_schedule(aes_key_schedule); + #endif + return 1; +} + + +int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. + // Inputs: s', e' (N_BAR x N) + // Output: out = s'*A + e' (N_BAR x N) + int i, j, k, kk; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + #if defined(USE_AES128_FOR_A) + uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + #if !defined(USE_OPENSSL) + uint8_t aes_key_schedule[16 * 11]; + AES128_load_schedule(seed_A, aes_key_schedule); + #else + EVP_CIPHER_CTX *aes_key_schedule; + int len; + if (!(aes_key_schedule = EVP_CIPHER_CTX_new())) { + handleErrors(); + } + if (1 != EVP_EncryptInit_ex(aes_key_schedule, EVP_aes_128_ecb(), NULL, seed_A, NULL)) { + handleErrors(); + } + #endif + + for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { + a_cols_temp[j] = i; // Loading values in the little-endian order + } + + for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. + for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) { + a_cols_temp[i + 1] = kk; // Loading values in the little-endian order + } + + #if !defined(USE_OPENSSL) + AES128_ECB_enc_sch((uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t), aes_key_schedule, (uint8_t *)a_cols); + #else + if (1 != EVP_EncryptUpdate(aes_key_schedule, (uint8_t *)a_cols, &len, (uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t))) { + handleErrors(); + } + #endif + + for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. + for (k = 0; k < PARAMS_STRIPE_STEP; k++) { + a_cols_t[k * PARAMS_N + i] = a_cols[i * PARAMS_STRIPE_STEP + k]; + } + } + + for (i = 0; i < PARAMS_NBAR; i++) { + for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) { + uint16_t sum[PARAMS_PARALLEL] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[i * PARAMS_N + j]; + sum[0] += sp * a_cols_t[(k + 0) * PARAMS_N + j]; + sum[1] += sp * a_cols_t[(k + 1) * PARAMS_N + j]; + sum[2] += sp * a_cols_t[(k + 2) * PARAMS_N + j]; + sum[3] += sp * a_cols_t[(k + 3) * PARAMS_N + j]; + } + out[i * PARAMS_N + kk + k + 0] += sum[0]; + out[i * PARAMS_N + kk + k + 2] += sum[2]; + out[i * PARAMS_N + kk + k + 1] += sum[1]; + out[i * PARAMS_N + kk + k + 3] += sum[3]; + } + } + } + AES128_free_schedule(aes_key_schedule); + + #elif defined (USE_SHAKE128_FOR_A) // SHAKE128 + int t = 0; + uint16_t a_cols[4 * PARAMS_N] = {0}; + uint8_t seed_A_separated[2 + BYTES_SEED_A]; + uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; + memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); + for (kk = 0; kk < PARAMS_N; kk += 4) { + seed_A_origin[0] = (uint16_t) (kk + 0); + shake128((unsigned char *)(a_cols + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = (uint16_t) (kk + 1); + shake128((unsigned char *)(a_cols + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = (uint16_t) (kk + 2); + shake128((unsigned char *)(a_cols + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = (uint16_t) (kk + 3); + shake128((unsigned char *)(a_cols + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + + for (i = 0; i < PARAMS_NBAR; i++) { + uint16_t sum[PARAMS_N] = {0}; + for (j = 0; j < 4; j++) { + uint16_t sp = s[i * PARAMS_N + kk + j]; + for (k = 0; k < PARAMS_N; k++) { // Matrix-vector multiplication + sum[k] += sp * a_cols[(t + j) * PARAMS_N + k]; + } + } + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_N + k] += sum[k]; + } + } + } + #endif + + return 1; +} diff --git a/crypto_kem/frodokem640shake/opt/noise.c b/crypto_kem/frodokem640shake/opt/noise.c new file mode 100644 index 00000000..170a944b --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/noise.c @@ -0,0 +1,35 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM640SHAKE_OPT_sample_n(uint16_t *s, size_t n) { + // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. + // The distribution is specified by its CDF. + // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output. + size_t i; + unsigned int j; + + for (i = 0; i < n; ++i) { + uint16_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint16_t sign = s[i] & 0x1; // Pick the least significant bit + + // No need to compare with the last value. + for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) { + // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits. + sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15; + } + // Assuming that sign is either 0 or 1, flips sample iff sign = 1 + s[i] = ((-sign) ^ sample) + sign; + } +} diff --git a/crypto_kem/frodokem640shake/opt/params.h b/crypto_kem/frodokem640shake/opt/params.h new file mode 100644 index 00000000..dcdad3d3 --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM640SHAKE_OPT_CRYPTO_CIPHERTEXTBYTES + +#define PARAMS_N 640 +#define PARAMS_NBAR 8 +#define PARAMS_LOGQ 15 +#define PARAMS_Q (1 << PARAMS_LOGQ) +#define PARAMS_EXTRACTED_BITS 2 +#define PARAMS_STRIPE_STEP 8 +#define PARAMS_PARALLEL 4 +#define BYTES_SEED_A 16 +#define BYTES_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) +#define BYTES_PKHASH CRYPTO_BYTES + +// Selecting SHAKE XOF function for the KEM and noise sampling +#define shake shake128 + +// CDF table +#define CDF_TABLE_DATA {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767} +#define CDF_TABLE_LEN 13 + +#endif diff --git a/crypto_kem/frodokem640shake/opt/util.c b/crypto_kem/frodokem640shake/opt/util.c new file mode 100644 index 00000000..ab2f74c9 --- /dev/null +++ b/crypto_kem/frodokem640shake/opt/util.c @@ -0,0 +1,235 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(uint16_t n) { + return (((uint8_t *) &n)[0] | (((uint8_t *) &n)[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(uint16_t n) { + uint16_t y; + uint8_t *z = (uint8_t *) &y; + z[0] = n & 0xFF; + z[1] = (n & 0xFF00) >> 8; + return y; +} + +void PQCLEAN_FRODOKEM640SHAKE_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { + // Multiply by s on the right + // Inputs: b (N_BAR x N), s (N x N_BAR) + // Output: out = b*s (N_BAR x N_BAR) + int i, j, k; + + for (i = 0; i < PARAMS_NBAR; i++) { + for (j = 0; j < PARAMS_NBAR; j++) { + out[i * PARAMS_NBAR + j] = 0; + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; + } + out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { + // Multiply by s on the left + // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR) + // Output: out = s*b + e (N_BAR x N_BAR) + int i, j, k; + + for (k = 0; k < PARAMS_NBAR; k++) { + for (i = 0; i < PARAMS_NBAR; i++) { + out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; + for (j = 0; j < PARAMS_N; j++) { + out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + } + out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Add a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a + b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Subtract a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a - b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in) { + // Encoding + unsigned int i, j, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint64_t temp, mask = ((uint64_t)1 << PARAMS_EXTRACTED_BITS) - 1; + uint16_t *pos = out; + + for (i = 0; i < nwords; i++) { + temp = 0; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + temp |= ((uint64_t)((uint8_t *)in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j); + } + for (j = 0; j < npieces_word; j++) { + *pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS)); + temp >>= PARAMS_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in) { + // Decoding + unsigned int i, j, index = 0, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint16_t temp, maskex = ((uint16_t)1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t)1 << PARAMS_LOGQ) - 1; + uint8_t *pos = (uint8_t *)out; + uint64_t templong; + + for (i = 0; i < nwords; i++) { + templong = 0; + for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5) + temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS); + templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j); + index++; + } + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb) { + // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element. + // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied. + memset(out, 0, outlen); + + size_t i = 0; // whole bytes already filled in + size_t j = 0; // whole uint16_t already copied + uint16_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (uint8_t) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = lsb; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == 8) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb) { + // Unpack the input char vector into a uint16_t output vector, copying lsb bits + // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb). + memset(out, 0, outlen * sizeof(uint16_t)); + + size_t i = 0; // whole uint16_t already filled in + size_t j = 0; // whole bytes already copied + uint8_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb bits of w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | | | | | |**|**|... + ^ + j + w : | *| + ^ + bits + out:| *****| *****| *** | |... + ^ ^ + i b + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = 8; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == lsb) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) { + // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. + // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. + volatile uint8_t *v = mem; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} From 199adb80726febd6143c63f4c07a0b10aabe85cd Mon Sep 17 00:00:00 2001 From: Thom Wiggers Date: Mon, 20 May 2019 16:12:01 +0200 Subject: [PATCH 22/35] Add -Wredundant-decls --- crypto_kem/frodokem1344aes/clean/Makefile | 2 +- crypto_kem/frodokem1344shake/clean/Makefile | 2 +- crypto_kem/frodokem640aes/clean/Makefile | 2 +- crypto_kem/frodokem640shake/clean/Makefile | 2 +- crypto_kem/frodokem976aes/clean/Makefile | 2 +- crypto_kem/frodokem976shake/clean/Makefile | 2 +- crypto_kem/kyber1024/clean/Makefile | 2 +- crypto_kem/kyber512/clean/Makefile | 2 +- crypto_kem/kyber768/clean/Makefile | 2 +- crypto_kem/newhope1024cca/clean/Makefile | 2 +- crypto_kem/newhope1024cpa/clean/Makefile | 2 +- crypto_kem/newhope512cca/clean/Makefile | 2 +- crypto_kem/newhope512cpa/clean/Makefile | 2 +- crypto_kem/ntruhps2048509/clean/Makefile | 2 +- crypto_kem/ntruhps2048677/clean/Makefile | 2 +- crypto_kem/ntruhps4096821/clean/Makefile | 2 +- crypto_kem/ntruhrss701/clean/Makefile | 2 +- crypto_sign/mqdss-48/clean/Makefile | 2 +- crypto_sign/mqdss-64/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-128f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-128f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-128s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-128s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-192f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-192f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-192s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-192s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-256f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-256f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-256s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-haraka-256s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-128f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-128f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-128s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-128s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-192f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-192f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-192s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-192s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-256f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-256f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-256s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-sha256-256s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-128f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-128f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-128s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-128s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-192f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-192f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-192s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-192s-simple/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-256f-robust/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-256f-simple/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-256s-robust/clean/Makefile | 2 +- crypto_sign/sphincs-shake256-256s-simple/clean/Makefile | 2 +- 55 files changed, 55 insertions(+), 55 deletions(-) diff --git a/crypto_kem/frodokem1344aes/clean/Makefile b/crypto_kem/frodokem1344aes/clean/Makefile index ba564d21..546e887d 100644 --- a/crypto_kem/frodokem1344aes/clean/Makefile +++ b/crypto_kem/frodokem1344aes/clean/Makefile @@ -4,7 +4,7 @@ LIB=libfrodokem1344aes_clean.a HEADERS=api.h params.h common.h OBJECTS=kem.o matrix_aes.o noise.o util.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/frodokem1344shake/clean/Makefile b/crypto_kem/frodokem1344shake/clean/Makefile index 39df6863..0f21a201 100644 --- a/crypto_kem/frodokem1344shake/clean/Makefile +++ b/crypto_kem/frodokem1344shake/clean/Makefile @@ -4,7 +4,7 @@ LIB=libfrodokem1344shake_clean.a HEADERS=api.h params.h common.h OBJECTS=kem.o matrix_shake.o noise.o util.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/frodokem640aes/clean/Makefile b/crypto_kem/frodokem640aes/clean/Makefile index 81e5d62d..efddb726 100644 --- a/crypto_kem/frodokem640aes/clean/Makefile +++ b/crypto_kem/frodokem640aes/clean/Makefile @@ -4,7 +4,7 @@ LIB=libfrodokem640aes_clean.a HEADERS=api.h params.h common.h OBJECTS=kem.o matrix_aes.o noise.o util.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/frodokem640shake/clean/Makefile b/crypto_kem/frodokem640shake/clean/Makefile index a7949f55..af1010fb 100644 --- a/crypto_kem/frodokem640shake/clean/Makefile +++ b/crypto_kem/frodokem640shake/clean/Makefile @@ -4,7 +4,7 @@ LIB=libfrodokem640shake_clean.a HEADERS=api.h params.h common.h OBJECTS=kem.o matrix_shake.o noise.o util.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/frodokem976aes/clean/Makefile b/crypto_kem/frodokem976aes/clean/Makefile index 376d9655..02d18827 100644 --- a/crypto_kem/frodokem976aes/clean/Makefile +++ b/crypto_kem/frodokem976aes/clean/Makefile @@ -4,7 +4,7 @@ LIB=libfrodokem976aes_clean.a HEADERS=api.h params.h common.h OBJECTS=kem.o matrix_aes.o noise.o util.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/frodokem976shake/clean/Makefile b/crypto_kem/frodokem976shake/clean/Makefile index 2d0a4652..ac582018 100644 --- a/crypto_kem/frodokem976shake/clean/Makefile +++ b/crypto_kem/frodokem976shake/clean/Makefile @@ -4,7 +4,7 @@ LIB=libfrodokem976shake_clean.a HEADERS=api.h params.h common.h OBJECTS=kem.o matrix_shake.o noise.o util.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/kyber1024/clean/Makefile b/crypto_kem/kyber1024/clean/Makefile index e00741f7..d6ae930c 100644 --- a/crypto_kem/kyber1024/clean/Makefile +++ b/crypto_kem/kyber1024/clean/Makefile @@ -4,7 +4,7 @@ LIB=libkyber1024_clean.a HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h symmetric.h OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o verify.o symmetric-fips202.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/kyber512/clean/Makefile b/crypto_kem/kyber512/clean/Makefile index 84dc881b..0b0678ee 100644 --- a/crypto_kem/kyber512/clean/Makefile +++ b/crypto_kem/kyber512/clean/Makefile @@ -4,7 +4,7 @@ LIB=libkyber512_clean.a HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h symmetric.h OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o verify.o symmetric-fips202.o -CFLAGS=-Wall -O3 -Wmissing-prototypes -Wextra -Wpedantic -Werror -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/kyber768/clean/Makefile b/crypto_kem/kyber768/clean/Makefile index c98f6e49..33864abd 100644 --- a/crypto_kem/kyber768/clean/Makefile +++ b/crypto_kem/kyber768/clean/Makefile @@ -4,7 +4,7 @@ LIB=libkyber768_clean.a HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h symmetric.h OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o verify.o symmetric-fips202.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/newhope1024cca/clean/Makefile b/crypto_kem/newhope1024cca/clean/Makefile index 933c6e2d..0d011039 100644 --- a/crypto_kem/newhope1024cca/clean/Makefile +++ b/crypto_kem/newhope1024cca/clean/Makefile @@ -4,7 +4,7 @@ LIB=libnewhope1024cca_clean.a HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/newhope1024cpa/clean/Makefile b/crypto_kem/newhope1024cpa/clean/Makefile index b4c76fd3..46b0b736 100644 --- a/crypto_kem/newhope1024cpa/clean/Makefile +++ b/crypto_kem/newhope1024cpa/clean/Makefile @@ -4,7 +4,7 @@ LIB=libnewhope1024cpa_clean.a HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/newhope512cca/clean/Makefile b/crypto_kem/newhope512cca/clean/Makefile index 34b0c30f..73a193d0 100644 --- a/crypto_kem/newhope512cca/clean/Makefile +++ b/crypto_kem/newhope512cca/clean/Makefile @@ -4,7 +4,7 @@ LIB=libnewhope512cca_clean.a HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/newhope512cpa/clean/Makefile b/crypto_kem/newhope512cpa/clean/Makefile index 8f5967d5..8659694c 100644 --- a/crypto_kem/newhope512cpa/clean/Makefile +++ b/crypto_kem/newhope512cpa/clean/Makefile @@ -4,7 +4,7 @@ LIB=libnewhope512cpa_clean.a HEADERS=api.h cpapke.h ntt.h params.h poly.h reduce.h verify.h OBJECTS=cpapke.o kem.o ntt.o poly.o precomp.o reduce.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/ntruhps2048509/clean/Makefile b/crypto_kem/ntruhps2048509/clean/Makefile index f4d4d328..e8b20e47 100644 --- a/crypto_kem/ntruhps2048509/clean/Makefile +++ b/crypto_kem/ntruhps2048509/clean/Makefile @@ -4,7 +4,7 @@ LIB=libntruhps2048509_clean.a HEADERS=api.h crypto_sort.h owcpa.h params.h poly.h sample.h verify.h OBJECTS=crypto_sort.o kem.o owcpa.o pack3.o packq.o poly.o sample.o verify.o -CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wredundant-decls -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/ntruhps2048677/clean/Makefile b/crypto_kem/ntruhps2048677/clean/Makefile index 22ecc1f7..7e892038 100644 --- a/crypto_kem/ntruhps2048677/clean/Makefile +++ b/crypto_kem/ntruhps2048677/clean/Makefile @@ -4,7 +4,7 @@ LIB=libntruhps2048677_clean.a HEADERS=api.h crypto_sort.h owcpa.h params.h poly.h sample.h verify.h OBJECTS=crypto_sort.o kem.o owcpa.o pack3.o packq.o poly.o sample.o verify.o -CFLAGS=-Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/ntruhps4096821/clean/Makefile b/crypto_kem/ntruhps4096821/clean/Makefile index c04c7f38..281e99dd 100644 --- a/crypto_kem/ntruhps4096821/clean/Makefile +++ b/crypto_kem/ntruhps4096821/clean/Makefile @@ -4,7 +4,7 @@ LIB=libntruhps4096821_clean.a HEADERS=api.h crypto_sort.h owcpa.h params.h poly.h sample.h verify.h OBJECTS=crypto_sort.o kem.o owcpa.o pack3.o packq.o poly.o sample.o verify.o -CFLAGS=-Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_kem/ntruhrss701/clean/Makefile b/crypto_kem/ntruhrss701/clean/Makefile index 88cc97b8..62328bc3 100644 --- a/crypto_kem/ntruhrss701/clean/Makefile +++ b/crypto_kem/ntruhrss701/clean/Makefile @@ -4,7 +4,7 @@ LIB=libntruhrss701_clean.a HEADERS=api.h owcpa.h params.h poly.h sample.h verify.h OBJECTS=kem.o owcpa.o pack3.o packq.o poly.o sample.o verify.o -CFLAGS=-Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/mqdss-48/clean/Makefile b/crypto_sign/mqdss-48/clean/Makefile index 0264ec92..258fe79e 100644 --- a/crypto_sign/mqdss-48/clean/Makefile +++ b/crypto_sign/mqdss-48/clean/Makefile @@ -5,7 +5,7 @@ LIB=libmqdss-48_clean.a HEADERS = params.h gf31.h mq.h api.h OBJECTS = gf31.o mq.o sign.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/mqdss-64/clean/Makefile b/crypto_sign/mqdss-64/clean/Makefile index 04c693a5..1582ef72 100644 --- a/crypto_sign/mqdss-64/clean/Makefile +++ b/crypto_sign/mqdss-64/clean/Makefile @@ -5,7 +5,7 @@ LIB=libmqdss-64_clean.a HEADERS = params.h gf31.h mq.h api.h OBJECTS = gf31.o mq.o sign.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-128f-robust/clean/Makefile b/crypto_sign/sphincs-haraka-128f-robust/clean/Makefile index 8bf94024..31635e61 100644 --- a/crypto_sign/sphincs-haraka-128f-robust/clean/Makefile +++ b/crypto_sign/sphincs-haraka-128f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-128f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_robust.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-128f-simple/clean/Makefile b/crypto_sign/sphincs-haraka-128f-simple/clean/Makefile index b99f46b6..ed71d91e 100644 --- a/crypto_sign/sphincs-haraka-128f-simple/clean/Makefile +++ b/crypto_sign/sphincs-haraka-128f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-128f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_simple.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-128s-robust/clean/Makefile b/crypto_sign/sphincs-haraka-128s-robust/clean/Makefile index 630bbb51..76834753 100644 --- a/crypto_sign/sphincs-haraka-128s-robust/clean/Makefile +++ b/crypto_sign/sphincs-haraka-128s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-128s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_robust.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-128s-simple/clean/Makefile b/crypto_sign/sphincs-haraka-128s-simple/clean/Makefile index 7f5c5278..ad33bc8e 100644 --- a/crypto_sign/sphincs-haraka-128s-simple/clean/Makefile +++ b/crypto_sign/sphincs-haraka-128s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-128s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_simple.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-192f-robust/clean/Makefile b/crypto_sign/sphincs-haraka-192f-robust/clean/Makefile index aa67c3fa..7c857afb 100644 --- a/crypto_sign/sphincs-haraka-192f-robust/clean/Makefile +++ b/crypto_sign/sphincs-haraka-192f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-192f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_robust.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-192f-simple/clean/Makefile b/crypto_sign/sphincs-haraka-192f-simple/clean/Makefile index b6c0e316..e3dc2789 100644 --- a/crypto_sign/sphincs-haraka-192f-simple/clean/Makefile +++ b/crypto_sign/sphincs-haraka-192f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-192f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_simple.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-192s-robust/clean/Makefile b/crypto_sign/sphincs-haraka-192s-robust/clean/Makefile index 6e7a2986..20621594 100644 --- a/crypto_sign/sphincs-haraka-192s-robust/clean/Makefile +++ b/crypto_sign/sphincs-haraka-192s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-192s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_robust.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-192s-simple/clean/Makefile b/crypto_sign/sphincs-haraka-192s-simple/clean/Makefile index 13423bf4..67a12498 100644 --- a/crypto_sign/sphincs-haraka-192s-simple/clean/Makefile +++ b/crypto_sign/sphincs-haraka-192s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-192s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_simple.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-256f-robust/clean/Makefile b/crypto_sign/sphincs-haraka-256f-robust/clean/Makefile index f714b735..6b0f52c1 100644 --- a/crypto_sign/sphincs-haraka-256f-robust/clean/Makefile +++ b/crypto_sign/sphincs-haraka-256f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-256f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_robust.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-256f-simple/clean/Makefile b/crypto_sign/sphincs-haraka-256f-simple/clean/Makefile index 2db645ad..bd87aae1 100644 --- a/crypto_sign/sphincs-haraka-256f-simple/clean/Makefile +++ b/crypto_sign/sphincs-haraka-256f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-256f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_simple.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-256s-robust/clean/Makefile b/crypto_sign/sphincs-haraka-256s-robust/clean/Makefile index c97db733..b822f639 100644 --- a/crypto_sign/sphincs-haraka-256s-robust/clean/Makefile +++ b/crypto_sign/sphincs-haraka-256s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-256s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_robust.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-haraka-256s-simple/clean/Makefile b/crypto_sign/sphincs-haraka-256s-simple/clean/Makefile index be89decc..39506a3f 100644 --- a/crypto_sign/sphincs-haraka-256s-simple/clean/Makefile +++ b/crypto_sign/sphincs-haraka-256s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-haraka-256s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h haraka.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_haraka.o thash_haraka_simple.o haraka.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-128f-robust/clean/Makefile b/crypto_sign/sphincs-sha256-128f-robust/clean/Makefile index a882a93d..f316f443 100644 --- a/crypto_sign/sphincs-sha256-128f-robust/clean/Makefile +++ b/crypto_sign/sphincs-sha256-128f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-128f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_robust.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-128f-simple/clean/Makefile b/crypto_sign/sphincs-sha256-128f-simple/clean/Makefile index 00341164..9b73ece1 100644 --- a/crypto_sign/sphincs-sha256-128f-simple/clean/Makefile +++ b/crypto_sign/sphincs-sha256-128f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-128f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_simple.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-128s-robust/clean/Makefile b/crypto_sign/sphincs-sha256-128s-robust/clean/Makefile index 54dc7ba3..7008633e 100644 --- a/crypto_sign/sphincs-sha256-128s-robust/clean/Makefile +++ b/crypto_sign/sphincs-sha256-128s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-128s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_robust.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-128s-simple/clean/Makefile b/crypto_sign/sphincs-sha256-128s-simple/clean/Makefile index 4264ce00..c4d4ee71 100644 --- a/crypto_sign/sphincs-sha256-128s-simple/clean/Makefile +++ b/crypto_sign/sphincs-sha256-128s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-128s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_simple.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-192f-robust/clean/Makefile b/crypto_sign/sphincs-sha256-192f-robust/clean/Makefile index a06d5196..fe77f6ae 100644 --- a/crypto_sign/sphincs-sha256-192f-robust/clean/Makefile +++ b/crypto_sign/sphincs-sha256-192f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-192f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_robust.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-192f-simple/clean/Makefile b/crypto_sign/sphincs-sha256-192f-simple/clean/Makefile index f847f77a..95d9a155 100644 --- a/crypto_sign/sphincs-sha256-192f-simple/clean/Makefile +++ b/crypto_sign/sphincs-sha256-192f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-192f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_simple.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-192s-robust/clean/Makefile b/crypto_sign/sphincs-sha256-192s-robust/clean/Makefile index 2f134259..bc213ecc 100644 --- a/crypto_sign/sphincs-sha256-192s-robust/clean/Makefile +++ b/crypto_sign/sphincs-sha256-192s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-192s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_robust.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-192s-simple/clean/Makefile b/crypto_sign/sphincs-sha256-192s-simple/clean/Makefile index 087324db..329667ce 100644 --- a/crypto_sign/sphincs-sha256-192s-simple/clean/Makefile +++ b/crypto_sign/sphincs-sha256-192s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-192s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_simple.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-256f-robust/clean/Makefile b/crypto_sign/sphincs-sha256-256f-robust/clean/Makefile index cae42e69..c312b90e 100644 --- a/crypto_sign/sphincs-sha256-256f-robust/clean/Makefile +++ b/crypto_sign/sphincs-sha256-256f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-256f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_robust.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-256f-simple/clean/Makefile b/crypto_sign/sphincs-sha256-256f-simple/clean/Makefile index df2ed05c..852496ea 100644 --- a/crypto_sign/sphincs-sha256-256f-simple/clean/Makefile +++ b/crypto_sign/sphincs-sha256-256f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-256f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_simple.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-256s-robust/clean/Makefile b/crypto_sign/sphincs-sha256-256s-robust/clean/Makefile index e06192c4..efa210e8 100644 --- a/crypto_sign/sphincs-sha256-256s-robust/clean/Makefile +++ b/crypto_sign/sphincs-sha256-256s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-256s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_robust.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-sha256-256s-simple/clean/Makefile b/crypto_sign/sphincs-sha256-256s-simple/clean/Makefile index ce925c1b..cc527069 100644 --- a/crypto_sign/sphincs-sha256-256s-simple/clean/Makefile +++ b/crypto_sign/sphincs-sha256-256s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-sha256-256s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h sha256.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_sha256.o thash_sha256_simple.o sha256.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-128f-robust/clean/Makefile b/crypto_sign/sphincs-shake256-128f-robust/clean/Makefile index 86825431..df59f00d 100644 --- a/crypto_sign/sphincs-shake256-128f-robust/clean/Makefile +++ b/crypto_sign/sphincs-shake256-128f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-128f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_robust.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-128f-simple/clean/Makefile b/crypto_sign/sphincs-shake256-128f-simple/clean/Makefile index 1e5260b5..0d64090f 100644 --- a/crypto_sign/sphincs-shake256-128f-simple/clean/Makefile +++ b/crypto_sign/sphincs-shake256-128f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-128f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_simple.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-128s-robust/clean/Makefile b/crypto_sign/sphincs-shake256-128s-robust/clean/Makefile index dcb37067..5a9b6997 100644 --- a/crypto_sign/sphincs-shake256-128s-robust/clean/Makefile +++ b/crypto_sign/sphincs-shake256-128s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-128s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_robust.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-128s-simple/clean/Makefile b/crypto_sign/sphincs-shake256-128s-simple/clean/Makefile index c3c9de0b..9c01dfa1 100644 --- a/crypto_sign/sphincs-shake256-128s-simple/clean/Makefile +++ b/crypto_sign/sphincs-shake256-128s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-128s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_simple.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-192f-robust/clean/Makefile b/crypto_sign/sphincs-shake256-192f-robust/clean/Makefile index 1173c5ef..812a7645 100644 --- a/crypto_sign/sphincs-shake256-192f-robust/clean/Makefile +++ b/crypto_sign/sphincs-shake256-192f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-192f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_robust.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-192f-simple/clean/Makefile b/crypto_sign/sphincs-shake256-192f-simple/clean/Makefile index 895dd95b..917bc6c6 100644 --- a/crypto_sign/sphincs-shake256-192f-simple/clean/Makefile +++ b/crypto_sign/sphincs-shake256-192f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-192f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_simple.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-192s-robust/clean/Makefile b/crypto_sign/sphincs-shake256-192s-robust/clean/Makefile index 3a777491..506d6ae4 100644 --- a/crypto_sign/sphincs-shake256-192s-robust/clean/Makefile +++ b/crypto_sign/sphincs-shake256-192s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-192s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_robust.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-192s-simple/clean/Makefile b/crypto_sign/sphincs-shake256-192s-simple/clean/Makefile index 49763008..4758a68f 100644 --- a/crypto_sign/sphincs-shake256-192s-simple/clean/Makefile +++ b/crypto_sign/sphincs-shake256-192s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-192s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_simple.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-256f-robust/clean/Makefile b/crypto_sign/sphincs-shake256-256f-robust/clean/Makefile index 7a30f008..4944a906 100644 --- a/crypto_sign/sphincs-shake256-256f-robust/clean/Makefile +++ b/crypto_sign/sphincs-shake256-256f-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-256f-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_robust.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-256f-simple/clean/Makefile b/crypto_sign/sphincs-shake256-256f-simple/clean/Makefile index 2d90b6a9..2e09eaae 100644 --- a/crypto_sign/sphincs-shake256-256f-simple/clean/Makefile +++ b/crypto_sign/sphincs-shake256-256f-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-256f-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_simple.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-256s-robust/clean/Makefile b/crypto_sign/sphincs-shake256-256s-robust/clean/Makefile index 66d22b40..c767c4ac 100644 --- a/crypto_sign/sphincs-shake256-256s-robust/clean/Makefile +++ b/crypto_sign/sphincs-shake256-256s-robust/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-256s-robust_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_robust.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) diff --git a/crypto_sign/sphincs-shake256-256s-simple/clean/Makefile b/crypto_sign/sphincs-shake256-256s-simple/clean/Makefile index f764bc17..e871e956 100644 --- a/crypto_sign/sphincs-shake256-256s-simple/clean/Makefile +++ b/crypto_sign/sphincs-shake256-256s-simple/clean/Makefile @@ -5,7 +5,7 @@ LIB=libsphincs-shake256-256s-simple_clean.a HEADERS = params.h address.h wots.h utils.h fors.h api.h hash.h thash.h OBJECTS = address.o wots.o utils.o fors.o sign.o hash_shake256.o thash_shake256_simple.o -CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) +CFLAGS=-O3 -Wall -Wconversion -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -Wredundant-decls -std=c99 -I../../../common $(EXTRAFLAGS) all: $(LIB) From 081442bb8d7b97c1d3d5e3499fbb2ca67c960b77 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 21 May 2019 15:15:52 +0200 Subject: [PATCH 23/35] use more recent version of the code --- .../frodokem640shake/opt/matrix_shake.c | 61 +++++++++++-------- 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/crypto_kem/frodokem640shake/opt/matrix_shake.c b/crypto_kem/frodokem640shake/opt/matrix_shake.c index 0eb59f6b..ed0aa32a 100644 --- a/crypto_kem/frodokem640shake/opt/matrix_shake.c +++ b/crypto_kem/frodokem640shake/opt/matrix_shake.c @@ -12,14 +12,15 @@ #include "api.h" #include "common.h" #include "params.h" -#define USE_SHAKE128_FOR_A + +#define USE_SHAKE128_FOR_A 1 int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. // Inputs: s, e (N x N_BAR) // Output: out = A*s + e (N x N_BAR) int i, j, k; - int16_t a_row[4 * PARAMS_N] = {0}; + int16_t a_row[4 * PARAMS_N]; for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); @@ -42,18 +43,18 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t #endif for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { - a_row_temp[j + 1 + 0 * PARAMS_N] = j; // Loading values in the little-endian order - a_row_temp[j + 1 + 1 * PARAMS_N] = j; - a_row_temp[j + 1 + 2 * PARAMS_N] = j; - a_row_temp[j + 1 + 3 * PARAMS_N] = j; + a_row_temp[j + 1 + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); // Loading values in the little-endian order + a_row_temp[j + 1 + 1 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 2 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); } for (i = 0; i < PARAMS_N; i += 4) { for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time - a_row_temp[j + 0 * PARAMS_N] = i + 0; // Loading values in the little-endian order - a_row_temp[j + 1 * PARAMS_N] = i + 1; - a_row_temp[j + 2 * PARAMS_N] = i + 2; - a_row_temp[j + 3 * PARAMS_N] = i + 3; + a_row_temp[j + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 0); // Loading values in the little-endian order + a_row_temp[j + 1 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 1); + a_row_temp[j + 2 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 2); + a_row_temp[j + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 3); } #if !defined(USE_OPENSSL) @@ -68,16 +69,18 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); for (i = 0; i < PARAMS_N; i += 4) { - seed_A_origin[0] = (uint16_t) (i + 0); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 0); shake128((unsigned char *)(a_row + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - seed_A_origin[0] = (uint16_t) (i + 1); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 1); shake128((unsigned char *)(a_row + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - seed_A_origin[0] = (uint16_t) (i + 2); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 2); shake128((unsigned char *)(a_row + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - seed_A_origin[0] = (uint16_t) (i + 3); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 3); shake128((unsigned char *)(a_row + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); #endif - + for (k = 0; k < 4 * PARAMS_N; k++) { + a_row[k] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(a_row[k]); + } for (k = 0; k < PARAMS_NBAR; k++) { uint16_t sum[4] = {0}; for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication @@ -101,19 +104,22 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t } + + int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. // Inputs: s', e' (N_BAR x N) // Output: out = s'*A + e' (N_BAR x N) - int i, j, k, kk; + int i, j, kk; for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); } #if defined(USE_AES128_FOR_A) + int k; uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; - uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; #if !defined(USE_OPENSSL) uint8_t aes_key_schedule[16 * 11]; @@ -130,12 +136,12 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t #endif for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { - a_cols_temp[j] = i; // Loading values in the little-endian order + a_cols_temp[j] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i); // Loading values in the little-endian order } for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) { - a_cols_temp[i + 1] = kk; // Loading values in the little-endian order + a_cols_temp[i + 1] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk); // Loading values in the little-endian order } #if !defined(USE_OPENSSL) @@ -148,7 +154,7 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. for (k = 0; k < PARAMS_STRIPE_STEP; k++) { - a_cols_t[k * PARAMS_N + i] = a_cols[i * PARAMS_STRIPE_STEP + k]; + a_cols_t[k * PARAMS_N + i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(a_cols[i * PARAMS_STRIPE_STEP + k]); } } @@ -173,19 +179,24 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t #elif defined (USE_SHAKE128_FOR_A) // SHAKE128 int t = 0; - uint16_t a_cols[4 * PARAMS_N] = {0}; + uint16_t a_cols[4 * PARAMS_N]; + + int k; uint8_t seed_A_separated[2 + BYTES_SEED_A]; uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); for (kk = 0; kk < PARAMS_N; kk += 4) { - seed_A_origin[0] = (uint16_t) (kk + 0); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk + 0); shake128((unsigned char *)(a_cols + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - seed_A_origin[0] = (uint16_t) (kk + 1); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk + 1); shake128((unsigned char *)(a_cols + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - seed_A_origin[0] = (uint16_t) (kk + 2); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk + 2); shake128((unsigned char *)(a_cols + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - seed_A_origin[0] = (uint16_t) (kk + 3); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk + 3); shake128((unsigned char *)(a_cols + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + for (i = 0; i < 4 * PARAMS_N; i++) { + a_cols[i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(a_cols[i]); + } for (i = 0; i < PARAMS_NBAR; i++) { uint16_t sum[PARAMS_N] = {0}; From 7701666093fe7266b12b8c2c5492f6c795ff67ba Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 21 May 2019 15:17:57 +0200 Subject: [PATCH 24/35] remove OPENSSL preprocessor conditionals --- .../frodokem640shake/opt/matrix_shake.c | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/crypto_kem/frodokem640shake/opt/matrix_shake.c b/crypto_kem/frodokem640shake/opt/matrix_shake.c index ed0aa32a..cf7f15b4 100644 --- a/crypto_kem/frodokem640shake/opt/matrix_shake.c +++ b/crypto_kem/frodokem640shake/opt/matrix_shake.c @@ -28,19 +28,8 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t #if defined(USE_AES128_FOR_A) int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once - #if !defined(USE_OPENSSL) uint8_t aes_key_schedule[16 * 11]; AES128_load_schedule(seed_A, aes_key_schedule); - #else - EVP_CIPHER_CTX *aes_key_schedule; - int len; - if (!(aes_key_schedule = EVP_CIPHER_CTX_new())) { - handleErrors(); - } - if (1 != EVP_EncryptInit_ex(aes_key_schedule, EVP_aes_128_ecb(), NULL, seed_A, NULL)) { - handleErrors(); - } - #endif for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { a_row_temp[j + 1 + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); // Loading values in the little-endian order @@ -57,13 +46,7 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t a_row_temp[j + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 3); } - #if !defined(USE_OPENSSL) AES128_ECB_enc_sch((uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t), aes_key_schedule, (uint8_t *)a_row); - #else - if (1 != EVP_EncryptUpdate(aes_key_schedule, (uint8_t *)a_row, &len, (uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t))) { - handleErrors(); - } - #endif #elif defined (USE_SHAKE128_FOR_A) uint8_t seed_A_separated[2 + BYTES_SEED_A]; uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; @@ -121,19 +104,8 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; - #if !defined(USE_OPENSSL) uint8_t aes_key_schedule[16 * 11]; AES128_load_schedule(seed_A, aes_key_schedule); - #else - EVP_CIPHER_CTX *aes_key_schedule; - int len; - if (!(aes_key_schedule = EVP_CIPHER_CTX_new())) { - handleErrors(); - } - if (1 != EVP_EncryptInit_ex(aes_key_schedule, EVP_aes_128_ecb(), NULL, seed_A, NULL)) { - handleErrors(); - } - #endif for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { a_cols_temp[j] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i); // Loading values in the little-endian order @@ -144,13 +116,7 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t a_cols_temp[i + 1] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk); // Loading values in the little-endian order } - #if !defined(USE_OPENSSL) AES128_ECB_enc_sch((uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t), aes_key_schedule, (uint8_t *)a_cols); - #else - if (1 != EVP_EncryptUpdate(aes_key_schedule, (uint8_t *)a_cols, &len, (uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t))) { - handleErrors(); - } - #endif for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. for (k = 0; k < PARAMS_STRIPE_STEP; k++) { From cf8e4e5179f293b2fb12dea85bfcce95a5178c02 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 21 May 2019 15:46:59 +0200 Subject: [PATCH 25/35] add optimized frodokem640aes --- crypto_kem/frodokem640aes/META.yml | 2 + crypto_kem/frodokem640aes/opt/LICENSE | 21 ++ crypto_kem/frodokem640aes/opt/Makefile | 19 ++ .../opt/Makefile.Microsoft_nmake | 19 ++ crypto_kem/frodokem640aes/opt/api.h | 20 ++ crypto_kem/frodokem640aes/opt/common.h | 19 ++ crypto_kem/frodokem640aes/opt/kem.c | 238 ++++++++++++++++++ crypto_kem/frodokem640aes/opt/matrix_aes.c | 124 +++++++++ crypto_kem/frodokem640aes/opt/noise.c | 35 +++ crypto_kem/frodokem640aes/opt/params.h | 27 ++ crypto_kem/frodokem640aes/opt/util.c | 235 +++++++++++++++++ 11 files changed, 759 insertions(+) create mode 100644 crypto_kem/frodokem640aes/opt/LICENSE create mode 100644 crypto_kem/frodokem640aes/opt/Makefile create mode 100644 crypto_kem/frodokem640aes/opt/Makefile.Microsoft_nmake create mode 100644 crypto_kem/frodokem640aes/opt/api.h create mode 100644 crypto_kem/frodokem640aes/opt/common.h create mode 100644 crypto_kem/frodokem640aes/opt/kem.c create mode 100644 crypto_kem/frodokem640aes/opt/matrix_aes.c create mode 100644 crypto_kem/frodokem640aes/opt/noise.c create mode 100644 crypto_kem/frodokem640aes/opt/params.h create mode 100644 crypto_kem/frodokem640aes/opt/util.c diff --git a/crypto_kem/frodokem640aes/META.yml b/crypto_kem/frodokem640aes/META.yml index a4932688..1e462e5d 100644 --- a/crypto_kem/frodokem640aes/META.yml +++ b/crypto_kem/frodokem640aes/META.yml @@ -23,3 +23,5 @@ auxiliary-submitters: implementations: - name: clean version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 +- name: opt + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 diff --git a/crypto_kem/frodokem640aes/opt/LICENSE b/crypto_kem/frodokem640aes/opt/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/crypto_kem/frodokem640aes/opt/Makefile b/crypto_kem/frodokem640aes/opt/Makefile new file mode 100644 index 00000000..1dfc87fc --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem640aes_opt.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_aes.o noise.o util.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/frodokem640aes/opt/Makefile.Microsoft_nmake b/crypto_kem/frodokem640aes/opt/Makefile.Microsoft_nmake new file mode 100644 index 00000000..ce195a97 --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libfrodokem640aes_opt.lib +OBJECTS=kem.obj matrix_aes.obj noise.obj util.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/frodokem640aes/opt/api.h b/crypto_kem/frodokem640aes/opt/api.h new file mode 100644 index 00000000..896e73c2 --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM640AES_OPT_API_H +#define PQCLEAN_FRODOKEM640AES_OPT_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_SECRETKEYBYTES 19888 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_PUBLICKEYBYTES 9616 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_BYTES 16 +#define PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_CIPHERTEXTBYTES 9720 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_ALGNAME "FrodoKEM-640-AES" + +int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem640aes/opt/common.h b/crypto_kem/frodokem640aes/opt/common.h new file mode 100644 index 00000000..ea2f4d6d --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/common.h @@ -0,0 +1,19 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM640AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM640AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM640AES_OPT_sample_n(uint16_t *s, size_t n); +void PQCLEAN_FRODOKEM640AES_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM640AES_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM640AES_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM640AES_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM640AES_OPT_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM640AES_OPT_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM640AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM640AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(uint16_t n); + +#endif diff --git a/crypto_kem/frodokem640aes/opt/kem.c b/crypto_kem/frodokem640aes/opt/kem.c new file mode 100644 index 00000000..386553a1 --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/kem.c @@ -0,0 +1,238 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" +#include "randombytes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + // FrodoKEM's key generation + // Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes) + // secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH bytes) + uint8_t *pk_seedA = &pk[0]; + uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *sk_s = &sk[0]; + uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + uint8_t *sk_S = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t S[2 * PARAMS_N * PARAMS_NBAR] = {0}; // contains secret data + uint16_t *E = &S[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t randomness[2 * CRYPTO_BYTES + BYTES_SEED_A]; // contains secret data via randomness_s and randomness_seedSE + uint8_t *randomness_s = &randomness[0]; // contains secret data + uint8_t *randomness_seedSE = &randomness[CRYPTO_BYTES]; // contains secret data + uint8_t *randomness_z = &randomness[2 * CRYPTO_BYTES]; + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // Generate the secret value s, the seed for S and E, and the seed for the seed for A. Add seed_A to the public key + randombytes(randomness, CRYPTO_BYTES + CRYPTO_BYTES + BYTES_SEED_A); + shake(pk_seedA, BYTES_SEED_A, randomness_z, BYTES_SEED_A); + + // Generate S and E, and compute B = A*S + E. Generate A on-the-fly + shake_input_seedSE[0] = 0x5F; + memcpy(&shake_input_seedSE[1], randomness_seedSE, CRYPTO_BYTES); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < 2 * PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(S[i]); + } + PQCLEAN_FRODOKEM640AES_OPT_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_sample_n(E, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM640AES_OPT_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Add s, pk and S to the secret key + memcpy(sk_s, randomness_s, CRYPTO_BYTES); + memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(S[i]); + } + memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); + + // Add H(pk) to the secret key + shake(sk_pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + + // Cleanup: + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(randomness, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + // FrodoKEM's key encapsulation + const uint8_t *pk_seedA = &pk[0]; + const uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *ct_c1 = &ct[0]; + uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t V[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via mu + uint8_t *pkh = &G2in[0]; + uint8_t *mu = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSE = &G2out[0]; // contains secret data + uint8_t *k = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // pkh <- G_1(pk), generate random mu, compute (seedSE || k) = G_2(pkh || mu) + shake(pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + randombytes(mu, BYTES_MU); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSE[0] = 0x96; + memcpy(&shake_input_seedSE[1], seedSE, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM640AES_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM640AES_OPT_pack(ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Generate Epp, and compute V = Sp*B + Epp + PQCLEAN_FRODOKEM640AES_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640AES_OPT_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM640AES_OPT_key_encode(C, (uint16_t *)mu); + PQCLEAN_FRODOKEM640AES_OPT_add(C, V, C); + PQCLEAN_FRODOKEM640AES_OPT_pack(ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ); + + // Compute ss = F(ct||KK) + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + memcpy(Fin_k, k, CRYPTO_BYTES); + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM640AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + // FrodoKEM's key decapsulation + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t W[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t CC[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t BBp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *ct_c1 = &ct[0]; + const uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + const uint8_t *sk_s = &sk[0]; + const uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + const uint16_t *sk_S = (uint16_t *) &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint16_t S[PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + const uint8_t *pk_seedA = &sk_pk[0]; + const uint8_t *pk_b = &sk_pk[BYTES_SEED_A]; + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via muprime + uint8_t *pkh = &G2in[0]; + uint8_t *muprime = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSEprime = &G2out[0]; // contains secret data + uint8_t *kprime = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data + + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(sk_S[i]); + } + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM640AES_OPT_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640AES_OPT_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640AES_OPT_mul_bs(W, Bp, S); + PQCLEAN_FRODOKEM640AES_OPT_sub(W, C, W); + PQCLEAN_FRODOKEM640AES_OPT_key_decode((uint16_t *)muprime, W); + + // Generate (seedSE' || k') = G_2(pkh || mu') + memcpy(pkh, sk_pkh, BYTES_PKHASH); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSEprime[0] = 0x96; + memcpy(&shake_input_seedSEprime[1], seedSEprime, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM640AES_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM640AES_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM640AES_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640AES_OPT_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM640AES_OPT_key_encode(CC, (uint16_t *)muprime); + PQCLEAN_FRODOKEM640AES_OPT_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); + } + + // Is (Bp == BBp & C == CC) = true + if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { + // Load k' to do ss = F(ct || k') + memcpy(Fin_k, kprime, CRYPTO_BYTES); + } else { + // Load s to do ss = F(ct || s) + memcpy(Fin_k, sk_s, CRYPTO_BYTES); + } + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem640aes/opt/matrix_aes.c b/crypto_kem/frodokem640aes/opt/matrix_aes.c new file mode 100644 index 00000000..d7993e5c --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/matrix_aes.c @@ -0,0 +1,124 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "aes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM640AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. + // Inputs: s, e (N x N_BAR) + // Output: out = A*s + e (N x N_BAR) + int i, j, k; + int16_t a_row[4 * PARAMS_N]; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once + aes128ctx ctx128; + + aes128_keyexp(&ctx128, seed_A); + + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { + a_row_temp[j + 1 + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(j); // Loading values in the little-endian order + a_row_temp[j + 1 + 1 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 2 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(j); + } + + for (i = 0; i < PARAMS_N; i += 4) { + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time + a_row_temp[j + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(i + 0); // Loading values in the little-endian order + a_row_temp[j + 1 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(i + 1); + a_row_temp[j + 2 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(i + 2); + a_row_temp[j + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(i + 3); + } + aes128_ecb((uint8_t *)a_row, (uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t) / AES_BLOCKBYTES, &ctx128); + for (k = 0; k < 4 * PARAMS_N; k++) { + a_row[k] = PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(a_row[k]); + } + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum[4] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[k * PARAMS_N + j]; + sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s + sum[1] += a_row[1 * PARAMS_N + j] * sp; + sum[2] += a_row[2 * PARAMS_N + j] * sp; + sum[3] += a_row[3 * PARAMS_N + j] * sp; + } + out[(i + 0)*PARAMS_NBAR + k] += sum[0]; + out[(i + 2)*PARAMS_NBAR + k] += sum[2]; + out[(i + 1)*PARAMS_NBAR + k] += sum[1]; + out[(i + 3)*PARAMS_NBAR + k] += sum[3]; + } + } + return 1; +} + + + + +int PQCLEAN_FRODOKEM640AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. + // Inputs: s', e' (N_BAR x N) + // Output: out = s'*A + e' (N_BAR x N) + int i, j, kk; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int k; + uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; + uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + aes128ctx ctx128; + + aes128_keyexp(&ctx128, seed_A); + + for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { + a_cols_temp[j] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(i); // Loading values in the little-endian order + } + + for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. + for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) { + a_cols_temp[i + 1] = PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(kk); // Loading values in the little-endian order + } + + aes128_ecb((uint8_t *)a_cols, (uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t) / AES_BLOCKBYTES, &ctx128); + + for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. + for (k = 0; k < PARAMS_STRIPE_STEP; k++) { + a_cols_t[k * PARAMS_N + i] = PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(a_cols[i * PARAMS_STRIPE_STEP + k]); + } + } + + for (i = 0; i < PARAMS_NBAR; i++) { + for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) { + uint16_t sum[PARAMS_PARALLEL] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[i * PARAMS_N + j]; + sum[0] += sp * a_cols_t[(k + 0) * PARAMS_N + j]; + sum[1] += sp * a_cols_t[(k + 1) * PARAMS_N + j]; + sum[2] += sp * a_cols_t[(k + 2) * PARAMS_N + j]; + sum[3] += sp * a_cols_t[(k + 3) * PARAMS_N + j]; + } + out[i * PARAMS_N + kk + k + 0] += sum[0]; + out[i * PARAMS_N + kk + k + 2] += sum[2]; + out[i * PARAMS_N + kk + k + 1] += sum[1]; + out[i * PARAMS_N + kk + k + 3] += sum[3]; + } + } + } + return 1; +} diff --git a/crypto_kem/frodokem640aes/opt/noise.c b/crypto_kem/frodokem640aes/opt/noise.c new file mode 100644 index 00000000..86ecf4d2 --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/noise.c @@ -0,0 +1,35 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM640AES_OPT_sample_n(uint16_t *s, size_t n) { + // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. + // The distribution is specified by its CDF. + // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output. + size_t i; + unsigned int j; + + for (i = 0; i < n; ++i) { + uint16_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint16_t sign = s[i] & 0x1; // Pick the least significant bit + + // No need to compare with the last value. + for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) { + // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits. + sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15; + } + // Assuming that sign is either 0 or 1, flips sample iff sign = 1 + s[i] = ((-sign) ^ sample) + sign; + } +} diff --git a/crypto_kem/frodokem640aes/opt/params.h b/crypto_kem/frodokem640aes/opt/params.h new file mode 100644 index 00000000..f5fbb743 --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM640AES_OPT_CRYPTO_CIPHERTEXTBYTES + +#define PARAMS_N 640 +#define PARAMS_NBAR 8 +#define PARAMS_LOGQ 15 +#define PARAMS_Q (1 << PARAMS_LOGQ) +#define PARAMS_EXTRACTED_BITS 2 +#define PARAMS_STRIPE_STEP 8 +#define PARAMS_PARALLEL 4 +#define BYTES_SEED_A 16 +#define BYTES_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) +#define BYTES_PKHASH CRYPTO_BYTES + +// Selecting SHAKE XOF function for the KEM and noise sampling +#define shake shake128 + +// CDF table +#define CDF_TABLE_DATA {4643, 13363, 20579, 25843, 29227, 31145, 32103, 32525, 32689, 32745, 32762, 32766, 32767} +#define CDF_TABLE_LEN 13 + +#endif diff --git a/crypto_kem/frodokem640aes/opt/util.c b/crypto_kem/frodokem640aes/opt/util.c new file mode 100644 index 00000000..716c36dc --- /dev/null +++ b/crypto_kem/frodokem640aes/opt/util.c @@ -0,0 +1,235 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +uint16_t PQCLEAN_FRODOKEM640AES_OPT_LE_TO_UINT16(uint16_t n) { + return (((uint8_t *) &n)[0] | (((uint8_t *) &n)[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM640AES_OPT_UINT16_TO_LE(uint16_t n) { + uint16_t y; + uint8_t *z = (uint8_t *) &y; + z[0] = n & 0xFF; + z[1] = (n & 0xFF00) >> 8; + return y; +} + +void PQCLEAN_FRODOKEM640AES_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { + // Multiply by s on the right + // Inputs: b (N_BAR x N), s (N x N_BAR) + // Output: out = b*s (N_BAR x N_BAR) + int i, j, k; + + for (i = 0; i < PARAMS_NBAR; i++) { + for (j = 0; j < PARAMS_NBAR; j++) { + out[i * PARAMS_NBAR + j] = 0; + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; + } + out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { + // Multiply by s on the left + // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR) + // Output: out = s*b + e (N_BAR x N_BAR) + int i, j, k; + + for (k = 0; k < PARAMS_NBAR; k++) { + for (i = 0; i < PARAMS_NBAR; i++) { + out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; + for (j = 0; j < PARAMS_N; j++) { + out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + } + out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Add a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a + b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Subtract a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a - b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_key_encode(uint16_t *out, const uint16_t *in) { + // Encoding + unsigned int i, j, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint64_t temp, mask = ((uint64_t)1 << PARAMS_EXTRACTED_BITS) - 1; + uint16_t *pos = out; + + for (i = 0; i < nwords; i++) { + temp = 0; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + temp |= ((uint64_t)((uint8_t *)in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j); + } + for (j = 0; j < npieces_word; j++) { + *pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS)); + temp >>= PARAMS_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_key_decode(uint16_t *out, const uint16_t *in) { + // Decoding + unsigned int i, j, index = 0, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint16_t temp, maskex = ((uint16_t)1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t)1 << PARAMS_LOGQ) - 1; + uint8_t *pos = (uint8_t *)out; + uint64_t templong; + + for (i = 0; i < nwords; i++) { + templong = 0; + for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5) + temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS); + templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j); + index++; + } + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb) { + // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element. + // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied. + memset(out, 0, outlen); + + size_t i = 0; // whole bytes already filled in + size_t j = 0; // whole uint16_t already copied + uint16_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (uint8_t) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = lsb; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == 8) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb) { + // Unpack the input char vector into a uint16_t output vector, copying lsb bits + // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb). + memset(out, 0, outlen * sizeof(uint16_t)); + + size_t i = 0; // whole uint16_t already filled in + size_t j = 0; // whole bytes already copied + uint8_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb bits of w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | | | | | |**|**|... + ^ + j + w : | *| + ^ + bits + out:| *****| *****| *** | |... + ^ ^ + i b + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = 8; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == lsb) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM640AES_OPT_clear_bytes(uint8_t *mem, size_t n) { + // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. + // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. + volatile uint8_t *v = mem; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} From 57ad79ae3a3e3f3e224915a42e3f0a062b52d76b Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 21 May 2019 15:51:56 +0200 Subject: [PATCH 26/35] remove preprocessor conditionals from frodokem640shake --- .../frodokem640shake/opt/matrix_shake.c | 76 ------------------- 1 file changed, 76 deletions(-) diff --git a/crypto_kem/frodokem640shake/opt/matrix_shake.c b/crypto_kem/frodokem640shake/opt/matrix_shake.c index cf7f15b4..6b53aaca 100644 --- a/crypto_kem/frodokem640shake/opt/matrix_shake.c +++ b/crypto_kem/frodokem640shake/opt/matrix_shake.c @@ -13,8 +13,6 @@ #include "common.h" #include "params.h" -#define USE_SHAKE128_FOR_A 1 - int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. // Inputs: s, e (N x N_BAR) @@ -26,28 +24,6 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); } - #if defined(USE_AES128_FOR_A) - int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once - uint8_t aes_key_schedule[16 * 11]; - AES128_load_schedule(seed_A, aes_key_schedule); - - for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { - a_row_temp[j + 1 + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); // Loading values in the little-endian order - a_row_temp[j + 1 + 1 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); - a_row_temp[j + 1 + 2 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); - a_row_temp[j + 1 + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(j); - } - - for (i = 0; i < PARAMS_N; i += 4) { - for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time - a_row_temp[j + 0 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 0); // Loading values in the little-endian order - a_row_temp[j + 1 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 1); - a_row_temp[j + 2 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 2); - a_row_temp[j + 3 * PARAMS_N] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 3); - } - - AES128_ECB_enc_sch((uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t), aes_key_schedule, (uint8_t *)a_row); - #elif defined (USE_SHAKE128_FOR_A) uint8_t seed_A_separated[2 + BYTES_SEED_A]; uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); @@ -60,7 +36,6 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t shake128((unsigned char *)(a_row + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i + 3); shake128((unsigned char *)(a_row + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - #endif for (k = 0; k < 4 * PARAMS_N; k++) { a_row[k] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(a_row[k]); } @@ -79,10 +54,6 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t out[(i + 3)*PARAMS_NBAR + k] += sum[3]; } } - - #if defined(USE_AES128_FOR_A) - AES128_free_schedule(aes_key_schedule); - #endif return 1; } @@ -99,51 +70,6 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); } - #if defined(USE_AES128_FOR_A) - int k; - uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; - uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; - uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; - uint8_t aes_key_schedule[16 * 11]; - AES128_load_schedule(seed_A, aes_key_schedule); - - for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { - a_cols_temp[j] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(i); // Loading values in the little-endian order - } - - for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. - for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) { - a_cols_temp[i + 1] = PQCLEAN_FRODOKEM640SHAKE_OPT_UINT16_TO_LE(kk); // Loading values in the little-endian order - } - - AES128_ECB_enc_sch((uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t), aes_key_schedule, (uint8_t *)a_cols); - - for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. - for (k = 0; k < PARAMS_STRIPE_STEP; k++) { - a_cols_t[k * PARAMS_N + i] = PQCLEAN_FRODOKEM640SHAKE_OPT_LE_TO_UINT16(a_cols[i * PARAMS_STRIPE_STEP + k]); - } - } - - for (i = 0; i < PARAMS_NBAR; i++) { - for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) { - uint16_t sum[PARAMS_PARALLEL] = {0}; - for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication - uint16_t sp = s[i * PARAMS_N + j]; - sum[0] += sp * a_cols_t[(k + 0) * PARAMS_N + j]; - sum[1] += sp * a_cols_t[(k + 1) * PARAMS_N + j]; - sum[2] += sp * a_cols_t[(k + 2) * PARAMS_N + j]; - sum[3] += sp * a_cols_t[(k + 3) * PARAMS_N + j]; - } - out[i * PARAMS_N + kk + k + 0] += sum[0]; - out[i * PARAMS_N + kk + k + 2] += sum[2]; - out[i * PARAMS_N + kk + k + 1] += sum[1]; - out[i * PARAMS_N + kk + k + 3] += sum[3]; - } - } - } - AES128_free_schedule(aes_key_schedule); - - #elif defined (USE_SHAKE128_FOR_A) // SHAKE128 int t = 0; uint16_t a_cols[4 * PARAMS_N]; @@ -177,7 +103,5 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t } } } - #endif - return 1; } From df4319c47f0fdbf155a19baeb004ebb6832690d8 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 21 May 2019 15:58:20 +0200 Subject: [PATCH 27/35] add duplicate consistency check --- test/duplicate_consistency/frodokem640aes_opt.yml | 11 +++++++++++ test/duplicate_consistency/frodokem640shake_opt.yml | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/duplicate_consistency/frodokem640aes_opt.yml create mode 100644 test/duplicate_consistency/frodokem640shake_opt.yml diff --git a/test/duplicate_consistency/frodokem640aes_opt.yml b/test/duplicate_consistency/frodokem640aes_opt.yml new file mode 100644 index 00000000..6f2a554f --- /dev/null +++ b/test/duplicate_consistency/frodokem640aes_opt.yml @@ -0,0 +1,11 @@ +consistency_checks: +- source: + scheme: frodokem640aes + implementation: clean + files: + - api.h + - common.h + - params.h + - kem.c + - noise.c + - util.c diff --git a/test/duplicate_consistency/frodokem640shake_opt.yml b/test/duplicate_consistency/frodokem640shake_opt.yml new file mode 100644 index 00000000..a3aa6115 --- /dev/null +++ b/test/duplicate_consistency/frodokem640shake_opt.yml @@ -0,0 +1,11 @@ +consistency_checks: +- source: + scheme: frodokem640shake + implementation: clean + files: + - api.h + - common.h + - params.h + - kem.c + - noise.c + - util.c From 901761d88ae27dc78b6a1927e146c0d27788c438 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Tue, 21 May 2019 16:22:09 +0200 Subject: [PATCH 28/35] make VS compiler happy in matrix_shake.c --- crypto_kem/frodokem640shake/opt/matrix_shake.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto_kem/frodokem640shake/opt/matrix_shake.c b/crypto_kem/frodokem640shake/opt/matrix_shake.c index 6b53aaca..3094f2a9 100644 --- a/crypto_kem/frodokem640shake/opt/matrix_shake.c +++ b/crypto_kem/frodokem640shake/opt/matrix_shake.c @@ -17,7 +17,8 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. // Inputs: s, e (N x N_BAR) // Output: out = A*s + e (N x N_BAR) - int i, j, k; + int j, k; + uint16_t i; int16_t a_row[4 * PARAMS_N]; for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { @@ -64,8 +65,8 @@ int PQCLEAN_FRODOKEM640SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. // Inputs: s', e' (N_BAR x N) // Output: out = s'*A + e' (N_BAR x N) - int i, j, kk; - + int i, j; + uint16_t kk; for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); } From 743b28f7a8acbdf7e921e5bcd8da16a50d6c1bc6 Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 22 May 2019 07:08:17 +0200 Subject: [PATCH 29/35] make VS compiler happy in matrix_aes.c --- crypto_kem/frodokem640aes/opt/matrix_aes.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crypto_kem/frodokem640aes/opt/matrix_aes.c b/crypto_kem/frodokem640aes/opt/matrix_aes.c index d7993e5c..24372876 100644 --- a/crypto_kem/frodokem640aes/opt/matrix_aes.c +++ b/crypto_kem/frodokem640aes/opt/matrix_aes.c @@ -17,7 +17,8 @@ int PQCLEAN_FRODOKEM640AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t * // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. // Inputs: s, e (N x N_BAR) // Output: out = A*s + e (N x N_BAR) - int i, j, k; + int k; + uint16_t i, j; int16_t a_row[4 * PARAMS_N]; for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { @@ -72,8 +73,8 @@ int PQCLEAN_FRODOKEM640AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t * // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. // Inputs: s', e' (N_BAR x N) // Output: out = s'*A + e' (N_BAR x N) - int i, j, kk; - + int j; + uint16_t i, kk; for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); } From c7c080568ec3ac5167eeec8ff79c465df803decf Mon Sep 17 00:00:00 2001 From: "Matthias J. Kannwischer" Date: Wed, 22 May 2019 07:42:43 +0200 Subject: [PATCH 30/35] add opt versions of frodokem976aes, frodokem976shake, frodokem1344aes, frodokem1344shake and the corresponding duplicate checks --- crypto_kem/frodokem1344aes/META.yml | 2 + crypto_kem/frodokem1344aes/opt/LICENSE | 21 ++ crypto_kem/frodokem1344aes/opt/Makefile | 19 ++ .../opt/Makefile.Microsoft_nmake | 19 ++ crypto_kem/frodokem1344aes/opt/api.h | 20 ++ crypto_kem/frodokem1344aes/opt/common.h | 19 ++ crypto_kem/frodokem1344aes/opt/kem.c | 238 ++++++++++++++++++ crypto_kem/frodokem1344aes/opt/matrix_aes.c | 125 +++++++++ crypto_kem/frodokem1344aes/opt/noise.c | 35 +++ crypto_kem/frodokem1344aes/opt/params.h | 27 ++ crypto_kem/frodokem1344aes/opt/util.c | 235 +++++++++++++++++ crypto_kem/frodokem1344shake/META.yml | 2 + crypto_kem/frodokem1344shake/opt/LICENSE | 21 ++ crypto_kem/frodokem1344shake/opt/Makefile | 19 ++ .../opt/Makefile.Microsoft_nmake | 19 ++ crypto_kem/frodokem1344shake/opt/api.h | 20 ++ crypto_kem/frodokem1344shake/opt/common.h | 19 ++ crypto_kem/frodokem1344shake/opt/kem.c | 238 ++++++++++++++++++ .../frodokem1344shake/opt/matrix_shake.c | 108 ++++++++ crypto_kem/frodokem1344shake/opt/noise.c | 35 +++ crypto_kem/frodokem1344shake/opt/params.h | 27 ++ crypto_kem/frodokem1344shake/opt/util.c | 235 +++++++++++++++++ crypto_kem/frodokem976aes/META.yml | 2 + crypto_kem/frodokem976aes/opt/LICENSE | 21 ++ crypto_kem/frodokem976aes/opt/Makefile | 19 ++ .../opt/Makefile.Microsoft_nmake | 19 ++ crypto_kem/frodokem976aes/opt/api.h | 20 ++ crypto_kem/frodokem976aes/opt/common.h | 19 ++ crypto_kem/frodokem976aes/opt/kem.c | 238 ++++++++++++++++++ crypto_kem/frodokem976aes/opt/matrix_aes.c | 125 +++++++++ crypto_kem/frodokem976aes/opt/noise.c | 35 +++ crypto_kem/frodokem976aes/opt/params.h | 27 ++ crypto_kem/frodokem976aes/opt/util.c | 235 +++++++++++++++++ crypto_kem/frodokem976shake/META.yml | 2 + crypto_kem/frodokem976shake/opt/LICENSE | 21 ++ crypto_kem/frodokem976shake/opt/Makefile | 19 ++ .../opt/Makefile.Microsoft_nmake | 19 ++ crypto_kem/frodokem976shake/opt/api.h | 20 ++ crypto_kem/frodokem976shake/opt/common.h | 19 ++ crypto_kem/frodokem976shake/opt/kem.c | 238 ++++++++++++++++++ .../frodokem976shake/opt/matrix_shake.c | 108 ++++++++ crypto_kem/frodokem976shake/opt/noise.c | 35 +++ crypto_kem/frodokem976shake/opt/params.h | 27 ++ crypto_kem/frodokem976shake/opt/util.c | 235 +++++++++++++++++ .../frodokem1344aes_opt.yml | 16 ++ .../frodokem1344shake_opt.yml | 16 ++ .../frodokem976aes_opt.yml | 16 ++ .../frodokem976shake_opt.yml | 16 ++ 48 files changed, 3070 insertions(+) create mode 100644 crypto_kem/frodokem1344aes/opt/LICENSE create mode 100644 crypto_kem/frodokem1344aes/opt/Makefile create mode 100644 crypto_kem/frodokem1344aes/opt/Makefile.Microsoft_nmake create mode 100644 crypto_kem/frodokem1344aes/opt/api.h create mode 100644 crypto_kem/frodokem1344aes/opt/common.h create mode 100644 crypto_kem/frodokem1344aes/opt/kem.c create mode 100644 crypto_kem/frodokem1344aes/opt/matrix_aes.c create mode 100644 crypto_kem/frodokem1344aes/opt/noise.c create mode 100644 crypto_kem/frodokem1344aes/opt/params.h create mode 100644 crypto_kem/frodokem1344aes/opt/util.c create mode 100644 crypto_kem/frodokem1344shake/opt/LICENSE create mode 100644 crypto_kem/frodokem1344shake/opt/Makefile create mode 100644 crypto_kem/frodokem1344shake/opt/Makefile.Microsoft_nmake create mode 100644 crypto_kem/frodokem1344shake/opt/api.h create mode 100644 crypto_kem/frodokem1344shake/opt/common.h create mode 100644 crypto_kem/frodokem1344shake/opt/kem.c create mode 100644 crypto_kem/frodokem1344shake/opt/matrix_shake.c create mode 100644 crypto_kem/frodokem1344shake/opt/noise.c create mode 100644 crypto_kem/frodokem1344shake/opt/params.h create mode 100644 crypto_kem/frodokem1344shake/opt/util.c create mode 100644 crypto_kem/frodokem976aes/opt/LICENSE create mode 100644 crypto_kem/frodokem976aes/opt/Makefile create mode 100644 crypto_kem/frodokem976aes/opt/Makefile.Microsoft_nmake create mode 100644 crypto_kem/frodokem976aes/opt/api.h create mode 100644 crypto_kem/frodokem976aes/opt/common.h create mode 100644 crypto_kem/frodokem976aes/opt/kem.c create mode 100644 crypto_kem/frodokem976aes/opt/matrix_aes.c create mode 100644 crypto_kem/frodokem976aes/opt/noise.c create mode 100644 crypto_kem/frodokem976aes/opt/params.h create mode 100644 crypto_kem/frodokem976aes/opt/util.c create mode 100644 crypto_kem/frodokem976shake/opt/LICENSE create mode 100644 crypto_kem/frodokem976shake/opt/Makefile create mode 100644 crypto_kem/frodokem976shake/opt/Makefile.Microsoft_nmake create mode 100644 crypto_kem/frodokem976shake/opt/api.h create mode 100644 crypto_kem/frodokem976shake/opt/common.h create mode 100644 crypto_kem/frodokem976shake/opt/kem.c create mode 100644 crypto_kem/frodokem976shake/opt/matrix_shake.c create mode 100644 crypto_kem/frodokem976shake/opt/noise.c create mode 100644 crypto_kem/frodokem976shake/opt/params.h create mode 100644 crypto_kem/frodokem976shake/opt/util.c create mode 100644 test/duplicate_consistency/frodokem1344aes_opt.yml create mode 100644 test/duplicate_consistency/frodokem1344shake_opt.yml create mode 100644 test/duplicate_consistency/frodokem976aes_opt.yml create mode 100644 test/duplicate_consistency/frodokem976shake_opt.yml diff --git a/crypto_kem/frodokem1344aes/META.yml b/crypto_kem/frodokem1344aes/META.yml index 98528881..4e9c1801 100644 --- a/crypto_kem/frodokem1344aes/META.yml +++ b/crypto_kem/frodokem1344aes/META.yml @@ -23,3 +23,5 @@ auxiliary-submitters: implementations: - name: clean version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 +- name: opt + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 diff --git a/crypto_kem/frodokem1344aes/opt/LICENSE b/crypto_kem/frodokem1344aes/opt/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/crypto_kem/frodokem1344aes/opt/Makefile b/crypto_kem/frodokem1344aes/opt/Makefile new file mode 100644 index 00000000..f15cc3e3 --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem1344aes_opt.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_aes.o noise.o util.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/frodokem1344aes/opt/Makefile.Microsoft_nmake b/crypto_kem/frodokem1344aes/opt/Makefile.Microsoft_nmake new file mode 100644 index 00000000..809ae4da --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libfrodokem1344aes_opt.lib +OBJECTS=kem.obj matrix_aes.obj noise.obj util.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/frodokem1344aes/opt/api.h b/crypto_kem/frodokem1344aes/opt/api.h new file mode 100644 index 00000000..d164186c --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM1344AES_OPT_API_H +#define PQCLEAN_FRODOKEM1344AES_OPT_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_SECRETKEYBYTES 43088 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_PUBLICKEYBYTES 21520 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_BYTES 32 +#define PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_CIPHERTEXTBYTES 21632 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_ALGNAME "FrodoKEM-1344-AES" + +int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem1344aes/opt/common.h b/crypto_kem/frodokem1344aes/opt/common.h new file mode 100644 index 00000000..1ea3ac89 --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/common.h @@ -0,0 +1,19 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM1344AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM1344AES_OPT_sample_n(uint16_t *s, size_t n); +void PQCLEAN_FRODOKEM1344AES_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM1344AES_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM1344AES_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM1344AES_OPT_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM1344AES_OPT_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM1344AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM1344AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(uint16_t n); + +#endif diff --git a/crypto_kem/frodokem1344aes/opt/kem.c b/crypto_kem/frodokem1344aes/opt/kem.c new file mode 100644 index 00000000..d989588a --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/kem.c @@ -0,0 +1,238 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" +#include "randombytes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + // FrodoKEM's key generation + // Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes) + // secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH bytes) + uint8_t *pk_seedA = &pk[0]; + uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *sk_s = &sk[0]; + uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + uint8_t *sk_S = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t S[2 * PARAMS_N * PARAMS_NBAR] = {0}; // contains secret data + uint16_t *E = &S[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t randomness[2 * CRYPTO_BYTES + BYTES_SEED_A]; // contains secret data via randomness_s and randomness_seedSE + uint8_t *randomness_s = &randomness[0]; // contains secret data + uint8_t *randomness_seedSE = &randomness[CRYPTO_BYTES]; // contains secret data + uint8_t *randomness_z = &randomness[2 * CRYPTO_BYTES]; + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // Generate the secret value s, the seed for S and E, and the seed for the seed for A. Add seed_A to the public key + randombytes(randomness, CRYPTO_BYTES + CRYPTO_BYTES + BYTES_SEED_A); + shake(pk_seedA, BYTES_SEED_A, randomness_z, BYTES_SEED_A); + + // Generate S and E, and compute B = A*S + E. Generate A on-the-fly + shake_input_seedSE[0] = 0x5F; + memcpy(&shake_input_seedSE[1], randomness_seedSE, CRYPTO_BYTES); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < 2 * PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(S[i]); + } + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(E, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM1344AES_OPT_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Add s, pk and S to the secret key + memcpy(sk_s, randomness_s, CRYPTO_BYTES); + memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(S[i]); + } + memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); + + // Add H(pk) to the secret key + shake(sk_pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + + // Cleanup: + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(randomness, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + // FrodoKEM's key encapsulation + const uint8_t *pk_seedA = &pk[0]; + const uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *ct_c1 = &ct[0]; + uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t V[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via mu + uint8_t *pkh = &G2in[0]; + uint8_t *mu = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSE = &G2out[0]; // contains secret data + uint8_t *k = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // pkh <- G_1(pk), generate random mu, compute (seedSE || k) = G_2(pkh || mu) + shake(pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + randombytes(mu, BYTES_MU); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSE[0] = 0x96; + memcpy(&shake_input_seedSE[1], seedSE, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM1344AES_OPT_pack(ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Generate Epp, and compute V = Sp*B + Epp + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM1344AES_OPT_key_encode(C, (uint16_t *)mu); + PQCLEAN_FRODOKEM1344AES_OPT_add(C, V, C); + PQCLEAN_FRODOKEM1344AES_OPT_pack(ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ); + + // Compute ss = F(ct||KK) + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + memcpy(Fin_k, k, CRYPTO_BYTES); + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM1344AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + // FrodoKEM's key decapsulation + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t W[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t CC[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t BBp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *ct_c1 = &ct[0]; + const uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + const uint8_t *sk_s = &sk[0]; + const uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + const uint16_t *sk_S = (uint16_t *) &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint16_t S[PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + const uint8_t *pk_seedA = &sk_pk[0]; + const uint8_t *pk_b = &sk_pk[BYTES_SEED_A]; + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via muprime + uint8_t *pkh = &G2in[0]; + uint8_t *muprime = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSEprime = &G2out[0]; // contains secret data + uint8_t *kprime = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data + + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(sk_S[i]); + } + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM1344AES_OPT_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344AES_OPT_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344AES_OPT_mul_bs(W, Bp, S); + PQCLEAN_FRODOKEM1344AES_OPT_sub(W, C, W); + PQCLEAN_FRODOKEM1344AES_OPT_key_decode((uint16_t *)muprime, W); + + // Generate (seedSE' || k') = G_2(pkh || mu') + memcpy(pkh, sk_pkh, BYTES_PKHASH); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSEprime[0] = 0x96; + memcpy(&shake_input_seedSEprime[1], seedSEprime, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM1344AES_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344AES_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM1344AES_OPT_key_encode(CC, (uint16_t *)muprime); + PQCLEAN_FRODOKEM1344AES_OPT_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); + } + + // Is (Bp == BBp & C == CC) = true + if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { + // Load k' to do ss = F(ct || k') + memcpy(Fin_k, kprime, CRYPTO_BYTES); + } else { + // Load s to do ss = F(ct || s) + memcpy(Fin_k, sk_s, CRYPTO_BYTES); + } + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem1344aes/opt/matrix_aes.c b/crypto_kem/frodokem1344aes/opt/matrix_aes.c new file mode 100644 index 00000000..9d29da6c --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/matrix_aes.c @@ -0,0 +1,125 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "aes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM1344AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. + // Inputs: s, e (N x N_BAR) + // Output: out = A*s + e (N x N_BAR) + int k; + uint16_t i, j; + int16_t a_row[4 * PARAMS_N]; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once + aes128ctx ctx128; + + aes128_keyexp(&ctx128, seed_A); + + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { + a_row_temp[j + 1 + 0 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(j); // Loading values in the little-endian order + a_row_temp[j + 1 + 1 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 2 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 3 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(j); + } + + for (i = 0; i < PARAMS_N; i += 4) { + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time + a_row_temp[j + 0 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(i + 0); // Loading values in the little-endian order + a_row_temp[j + 1 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(i + 1); + a_row_temp[j + 2 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(i + 2); + a_row_temp[j + 3 * PARAMS_N] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(i + 3); + } + aes128_ecb((uint8_t *)a_row, (uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t) / AES_BLOCKBYTES, &ctx128); + for (k = 0; k < 4 * PARAMS_N; k++) { + a_row[k] = PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(a_row[k]); + } + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum[4] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[k * PARAMS_N + j]; + sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s + sum[1] += a_row[1 * PARAMS_N + j] * sp; + sum[2] += a_row[2 * PARAMS_N + j] * sp; + sum[3] += a_row[3 * PARAMS_N + j] * sp; + } + out[(i + 0)*PARAMS_NBAR + k] += sum[0]; + out[(i + 2)*PARAMS_NBAR + k] += sum[2]; + out[(i + 1)*PARAMS_NBAR + k] += sum[1]; + out[(i + 3)*PARAMS_NBAR + k] += sum[3]; + } + } + return 1; +} + + + + +int PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. + // Inputs: s', e' (N_BAR x N) + // Output: out = s'*A + e' (N_BAR x N) + int j; + uint16_t i, kk; + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int k; + uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; + uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + aes128ctx ctx128; + + aes128_keyexp(&ctx128, seed_A); + + for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { + a_cols_temp[j] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(i); // Loading values in the little-endian order + } + + for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. + for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) { + a_cols_temp[i + 1] = PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(kk); // Loading values in the little-endian order + } + + aes128_ecb((uint8_t *)a_cols, (uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t) / AES_BLOCKBYTES, &ctx128); + + for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. + for (k = 0; k < PARAMS_STRIPE_STEP; k++) { + a_cols_t[k * PARAMS_N + i] = PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(a_cols[i * PARAMS_STRIPE_STEP + k]); + } + } + + for (i = 0; i < PARAMS_NBAR; i++) { + for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) { + uint16_t sum[PARAMS_PARALLEL] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[i * PARAMS_N + j]; + sum[0] += sp * a_cols_t[(k + 0) * PARAMS_N + j]; + sum[1] += sp * a_cols_t[(k + 1) * PARAMS_N + j]; + sum[2] += sp * a_cols_t[(k + 2) * PARAMS_N + j]; + sum[3] += sp * a_cols_t[(k + 3) * PARAMS_N + j]; + } + out[i * PARAMS_N + kk + k + 0] += sum[0]; + out[i * PARAMS_N + kk + k + 2] += sum[2]; + out[i * PARAMS_N + kk + k + 1] += sum[1]; + out[i * PARAMS_N + kk + k + 3] += sum[3]; + } + } + } + return 1; +} diff --git a/crypto_kem/frodokem1344aes/opt/noise.c b/crypto_kem/frodokem1344aes/opt/noise.c new file mode 100644 index 00000000..1e8b66c6 --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/noise.c @@ -0,0 +1,35 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM1344AES_OPT_sample_n(uint16_t *s, size_t n) { + // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. + // The distribution is specified by its CDF. + // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output. + size_t i; + unsigned int j; + + for (i = 0; i < n; ++i) { + uint16_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint16_t sign = s[i] & 0x1; // Pick the least significant bit + + // No need to compare with the last value. + for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) { + // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits. + sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15; + } + // Assuming that sign is either 0 or 1, flips sample iff sign = 1 + s[i] = ((-sign) ^ sample) + sign; + } +} diff --git a/crypto_kem/frodokem1344aes/opt/params.h b/crypto_kem/frodokem1344aes/opt/params.h new file mode 100644 index 00000000..08e6d4bb --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM1344AES_OPT_CRYPTO_CIPHERTEXTBYTES + +#define PARAMS_N 1344 +#define PARAMS_NBAR 8 +#define PARAMS_LOGQ 16 +#define PARAMS_Q (1 << PARAMS_LOGQ) +#define PARAMS_EXTRACTED_BITS 4 +#define PARAMS_STRIPE_STEP 8 +#define PARAMS_PARALLEL 4 +#define BYTES_SEED_A 16 +#define BYTES_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) +#define BYTES_PKHASH CRYPTO_BYTES + +// Selecting SHAKE XOF function for the KEM and noise sampling +#define shake shake256 + +// CDF table +#define CDF_TABLE_DATA {9142, 23462, 30338, 32361, 32725, 32765, 32767} +#define CDF_TABLE_LEN 7 + +#endif diff --git a/crypto_kem/frodokem1344aes/opt/util.c b/crypto_kem/frodokem1344aes/opt/util.c new file mode 100644 index 00000000..33b28109 --- /dev/null +++ b/crypto_kem/frodokem1344aes/opt/util.c @@ -0,0 +1,235 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +uint16_t PQCLEAN_FRODOKEM1344AES_OPT_LE_TO_UINT16(uint16_t n) { + return (((uint8_t *) &n)[0] | (((uint8_t *) &n)[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM1344AES_OPT_UINT16_TO_LE(uint16_t n) { + uint16_t y; + uint8_t *z = (uint8_t *) &y; + z[0] = n & 0xFF; + z[1] = (n & 0xFF00) >> 8; + return y; +} + +void PQCLEAN_FRODOKEM1344AES_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { + // Multiply by s on the right + // Inputs: b (N_BAR x N), s (N x N_BAR) + // Output: out = b*s (N_BAR x N_BAR) + int i, j, k; + + for (i = 0; i < PARAMS_NBAR; i++) { + for (j = 0; j < PARAMS_NBAR; j++) { + out[i * PARAMS_NBAR + j] = 0; + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; + } + out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { + // Multiply by s on the left + // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR) + // Output: out = s*b + e (N_BAR x N_BAR) + int i, j, k; + + for (k = 0; k < PARAMS_NBAR; k++) { + for (i = 0; i < PARAMS_NBAR; i++) { + out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; + for (j = 0; j < PARAMS_N; j++) { + out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + } + out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Add a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a + b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Subtract a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a - b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_key_encode(uint16_t *out, const uint16_t *in) { + // Encoding + unsigned int i, j, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint64_t temp, mask = ((uint64_t)1 << PARAMS_EXTRACTED_BITS) - 1; + uint16_t *pos = out; + + for (i = 0; i < nwords; i++) { + temp = 0; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + temp |= ((uint64_t)((uint8_t *)in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j); + } + for (j = 0; j < npieces_word; j++) { + *pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS)); + temp >>= PARAMS_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_key_decode(uint16_t *out, const uint16_t *in) { + // Decoding + unsigned int i, j, index = 0, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint16_t temp, maskex = ((uint16_t)1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t)1 << PARAMS_LOGQ) - 1; + uint8_t *pos = (uint8_t *)out; + uint64_t templong; + + for (i = 0; i < nwords; i++) { + templong = 0; + for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5) + temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS); + templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j); + index++; + } + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb) { + // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element. + // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied. + memset(out, 0, outlen); + + size_t i = 0; // whole bytes already filled in + size_t j = 0; // whole uint16_t already copied + uint16_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (uint8_t) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = lsb; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == 8) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb) { + // Unpack the input char vector into a uint16_t output vector, copying lsb bits + // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb). + memset(out, 0, outlen * sizeof(uint16_t)); + + size_t i = 0; // whole uint16_t already filled in + size_t j = 0; // whole bytes already copied + uint8_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb bits of w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | | | | | |**|**|... + ^ + j + w : | *| + ^ + bits + out:| *****| *****| *** | |... + ^ ^ + i b + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = 8; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == lsb) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM1344AES_OPT_clear_bytes(uint8_t *mem, size_t n) { + // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. + // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. + volatile uint8_t *v = mem; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} diff --git a/crypto_kem/frodokem1344shake/META.yml b/crypto_kem/frodokem1344shake/META.yml index 534d3f43..43a699eb 100644 --- a/crypto_kem/frodokem1344shake/META.yml +++ b/crypto_kem/frodokem1344shake/META.yml @@ -23,3 +23,5 @@ auxiliary-submitters: implementations: - name: clean version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 +- name: opt + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 diff --git a/crypto_kem/frodokem1344shake/opt/LICENSE b/crypto_kem/frodokem1344shake/opt/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/crypto_kem/frodokem1344shake/opt/Makefile b/crypto_kem/frodokem1344shake/opt/Makefile new file mode 100644 index 00000000..f8c5fd4a --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem1344shake_opt.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_shake.o noise.o util.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/frodokem1344shake/opt/Makefile.Microsoft_nmake b/crypto_kem/frodokem1344shake/opt/Makefile.Microsoft_nmake new file mode 100644 index 00000000..0142c1e1 --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libfrodokem1344shake_opt.lib +OBJECTS=kem.obj matrix_shake.obj noise.obj util.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/frodokem1344shake/opt/api.h b/crypto_kem/frodokem1344shake/opt/api.h new file mode 100644 index 00000000..76255168 --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM1344SHAKE_OPT_API_H +#define PQCLEAN_FRODOKEM1344SHAKE_OPT_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_SECRETKEYBYTES 43088 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_PUBLICKEYBYTES 21520 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_BYTES 32 +#define PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_CIPHERTEXTBYTES 21632 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_ALGNAME "FrodoKEM-1344-SHAKE" + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem1344shake/opt/common.h b/crypto_kem/frodokem1344shake/opt/common.h new file mode 100644 index 00000000..32af833b --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/common.h @@ -0,0 +1,19 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(uint16_t *s, size_t n); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(uint16_t n); + +#endif diff --git a/crypto_kem/frodokem1344shake/opt/kem.c b/crypto_kem/frodokem1344shake/opt/kem.c new file mode 100644 index 00000000..45a940ae --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/kem.c @@ -0,0 +1,238 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" +#include "randombytes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + // FrodoKEM's key generation + // Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes) + // secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH bytes) + uint8_t *pk_seedA = &pk[0]; + uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *sk_s = &sk[0]; + uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + uint8_t *sk_S = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t S[2 * PARAMS_N * PARAMS_NBAR] = {0}; // contains secret data + uint16_t *E = &S[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t randomness[2 * CRYPTO_BYTES + BYTES_SEED_A]; // contains secret data via randomness_s and randomness_seedSE + uint8_t *randomness_s = &randomness[0]; // contains secret data + uint8_t *randomness_seedSE = &randomness[CRYPTO_BYTES]; // contains secret data + uint8_t *randomness_z = &randomness[2 * CRYPTO_BYTES]; + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // Generate the secret value s, the seed for S and E, and the seed for the seed for A. Add seed_A to the public key + randombytes(randomness, CRYPTO_BYTES + CRYPTO_BYTES + BYTES_SEED_A); + shake(pk_seedA, BYTES_SEED_A, randomness_z, BYTES_SEED_A); + + // Generate S and E, and compute B = A*S + E. Generate A on-the-fly + shake_input_seedSE[0] = 0x5F; + memcpy(&shake_input_seedSE[1], randomness_seedSE, CRYPTO_BYTES); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < 2 * PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(S[i]); + } + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(E, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Add s, pk and S to the secret key + memcpy(sk_s, randomness_s, CRYPTO_BYTES); + memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(S[i]); + } + memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); + + // Add H(pk) to the secret key + shake(sk_pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + + // Cleanup: + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(randomness, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + // FrodoKEM's key encapsulation + const uint8_t *pk_seedA = &pk[0]; + const uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *ct_c1 = &ct[0]; + uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t V[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via mu + uint8_t *pkh = &G2in[0]; + uint8_t *mu = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSE = &G2out[0]; // contains secret data + uint8_t *k = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // pkh <- G_1(pk), generate random mu, compute (seedSE || k) = G_2(pkh || mu) + shake(pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + randombytes(mu, BYTES_MU); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSE[0] = 0x96; + memcpy(&shake_input_seedSE[1], seedSE, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Generate Epp, and compute V = Sp*B + Epp + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM1344SHAKE_OPT_key_encode(C, (uint16_t *)mu); + PQCLEAN_FRODOKEM1344SHAKE_OPT_add(C, V, C); + PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ); + + // Compute ss = F(ct||KK) + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + memcpy(Fin_k, k, CRYPTO_BYTES); + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + // FrodoKEM's key decapsulation + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t W[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t CC[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t BBp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *ct_c1 = &ct[0]; + const uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + const uint8_t *sk_s = &sk[0]; + const uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + const uint16_t *sk_S = (uint16_t *) &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint16_t S[PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + const uint8_t *pk_seedA = &sk_pk[0]; + const uint8_t *pk_b = &sk_pk[BYTES_SEED_A]; + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via muprime + uint8_t *pkh = &G2in[0]; + uint8_t *muprime = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSEprime = &G2out[0]; // contains secret data + uint8_t *kprime = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data + + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(sk_S[i]); + } + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_bs(W, Bp, S); + PQCLEAN_FRODOKEM1344SHAKE_OPT_sub(W, C, W); + PQCLEAN_FRODOKEM1344SHAKE_OPT_key_decode((uint16_t *)muprime, W); + + // Generate (seedSE' || k') = G_2(pkh || mu') + memcpy(pkh, sk_pkh, BYTES_PKHASH); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSEprime[0] = 0x96; + memcpy(&shake_input_seedSEprime[1], seedSEprime, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM1344SHAKE_OPT_key_encode(CC, (uint16_t *)muprime); + PQCLEAN_FRODOKEM1344SHAKE_OPT_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); + } + + // Is (Bp == BBp & C == CC) = true + if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { + // Load k' to do ss = F(ct || k') + memcpy(Fin_k, kprime, CRYPTO_BYTES); + } else { + // Load s to do ss = F(ct || s) + memcpy(Fin_k, sk_s, CRYPTO_BYTES); + } + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem1344shake/opt/matrix_shake.c b/crypto_kem/frodokem1344shake/opt/matrix_shake.c new file mode 100644 index 00000000..7fab5e5f --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/matrix_shake.c @@ -0,0 +1,108 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. + // Inputs: s, e (N x N_BAR) + // Output: out = A*s + e (N x N_BAR) + int j, k; + uint16_t i; + int16_t a_row[4 * PARAMS_N]; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + uint8_t seed_A_separated[2 + BYTES_SEED_A]; + uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; + memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); + for (i = 0; i < PARAMS_N; i += 4) { + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(i + 0); + shake128((unsigned char *)(a_row + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(i + 1); + shake128((unsigned char *)(a_row + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(i + 2); + shake128((unsigned char *)(a_row + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(i + 3); + shake128((unsigned char *)(a_row + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + for (k = 0; k < 4 * PARAMS_N; k++) { + a_row[k] = PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(a_row[k]); + } + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum[4] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[k * PARAMS_N + j]; + sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s + sum[1] += a_row[1 * PARAMS_N + j] * sp; + sum[2] += a_row[2 * PARAMS_N + j] * sp; + sum[3] += a_row[3 * PARAMS_N + j] * sp; + } + out[(i + 0)*PARAMS_NBAR + k] += sum[0]; + out[(i + 2)*PARAMS_NBAR + k] += sum[2]; + out[(i + 1)*PARAMS_NBAR + k] += sum[1]; + out[(i + 3)*PARAMS_NBAR + k] += sum[3]; + } + } + return 1; +} + + + + +int PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. + // Inputs: s', e' (N_BAR x N) + // Output: out = s'*A + e' (N_BAR x N) + int i, j; + uint16_t kk; + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int t = 0; + uint16_t a_cols[4 * PARAMS_N]; + + int k; + uint8_t seed_A_separated[2 + BYTES_SEED_A]; + uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; + memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); + for (kk = 0; kk < PARAMS_N; kk += 4) { + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(kk + 0); + shake128((unsigned char *)(a_cols + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(kk + 1); + shake128((unsigned char *)(a_cols + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(kk + 2); + shake128((unsigned char *)(a_cols + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(kk + 3); + shake128((unsigned char *)(a_cols + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + for (i = 0; i < 4 * PARAMS_N; i++) { + a_cols[i] = PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(a_cols[i]); + } + + for (i = 0; i < PARAMS_NBAR; i++) { + uint16_t sum[PARAMS_N] = {0}; + for (j = 0; j < 4; j++) { + uint16_t sp = s[i * PARAMS_N + kk + j]; + for (k = 0; k < PARAMS_N; k++) { // Matrix-vector multiplication + sum[k] += sp * a_cols[(t + j) * PARAMS_N + k]; + } + } + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_N + k] += sum[k]; + } + } + } + return 1; +} diff --git a/crypto_kem/frodokem1344shake/opt/noise.c b/crypto_kem/frodokem1344shake/opt/noise.c new file mode 100644 index 00000000..b64fe022 --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/noise.c @@ -0,0 +1,35 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_sample_n(uint16_t *s, size_t n) { + // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. + // The distribution is specified by its CDF. + // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output. + size_t i; + unsigned int j; + + for (i = 0; i < n; ++i) { + uint16_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint16_t sign = s[i] & 0x1; // Pick the least significant bit + + // No need to compare with the last value. + for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) { + // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits. + sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15; + } + // Assuming that sign is either 0 or 1, flips sample iff sign = 1 + s[i] = ((-sign) ^ sample) + sign; + } +} diff --git a/crypto_kem/frodokem1344shake/opt/params.h b/crypto_kem/frodokem1344shake/opt/params.h new file mode 100644 index 00000000..c7d91d49 --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM1344SHAKE_OPT_CRYPTO_CIPHERTEXTBYTES + +#define PARAMS_N 1344 +#define PARAMS_NBAR 8 +#define PARAMS_LOGQ 16 +#define PARAMS_Q (1 << PARAMS_LOGQ) +#define PARAMS_EXTRACTED_BITS 4 +#define PARAMS_STRIPE_STEP 8 +#define PARAMS_PARALLEL 4 +#define BYTES_SEED_A 16 +#define BYTES_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) +#define BYTES_PKHASH CRYPTO_BYTES + +// Selecting SHAKE XOF function for the KEM and noise sampling +#define shake shake256 + +// CDF table +#define CDF_TABLE_DATA {9142, 23462, 30338, 32361, 32725, 32765, 32767} +#define CDF_TABLE_LEN 7 + +#endif diff --git a/crypto_kem/frodokem1344shake/opt/util.c b/crypto_kem/frodokem1344shake/opt/util.c new file mode 100644 index 00000000..22606c95 --- /dev/null +++ b/crypto_kem/frodokem1344shake/opt/util.c @@ -0,0 +1,235 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_LE_TO_UINT16(uint16_t n) { + return (((uint8_t *) &n)[0] | (((uint8_t *) &n)[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM1344SHAKE_OPT_UINT16_TO_LE(uint16_t n) { + uint16_t y; + uint8_t *z = (uint8_t *) &y; + z[0] = n & 0xFF; + z[1] = (n & 0xFF00) >> 8; + return y; +} + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { + // Multiply by s on the right + // Inputs: b (N_BAR x N), s (N x N_BAR) + // Output: out = b*s (N_BAR x N_BAR) + int i, j, k; + + for (i = 0; i < PARAMS_NBAR; i++) { + for (j = 0; j < PARAMS_NBAR; j++) { + out[i * PARAMS_NBAR + j] = 0; + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; + } + out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { + // Multiply by s on the left + // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR) + // Output: out = s*b + e (N_BAR x N_BAR) + int i, j, k; + + for (k = 0; k < PARAMS_NBAR; k++) { + for (i = 0; i < PARAMS_NBAR; i++) { + out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; + for (j = 0; j < PARAMS_N; j++) { + out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + } + out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Add a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a + b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Subtract a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a - b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in) { + // Encoding + unsigned int i, j, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint64_t temp, mask = ((uint64_t)1 << PARAMS_EXTRACTED_BITS) - 1; + uint16_t *pos = out; + + for (i = 0; i < nwords; i++) { + temp = 0; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + temp |= ((uint64_t)((uint8_t *)in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j); + } + for (j = 0; j < npieces_word; j++) { + *pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS)); + temp >>= PARAMS_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in) { + // Decoding + unsigned int i, j, index = 0, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint16_t temp, maskex = ((uint16_t)1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t)1 << PARAMS_LOGQ) - 1; + uint8_t *pos = (uint8_t *)out; + uint64_t templong; + + for (i = 0; i < nwords; i++) { + templong = 0; + for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5) + temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS); + templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j); + index++; + } + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb) { + // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element. + // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied. + memset(out, 0, outlen); + + size_t i = 0; // whole bytes already filled in + size_t j = 0; // whole uint16_t already copied + uint16_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (uint8_t) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = lsb; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == 8) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb) { + // Unpack the input char vector into a uint16_t output vector, copying lsb bits + // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb). + memset(out, 0, outlen * sizeof(uint16_t)); + + size_t i = 0; // whole uint16_t already filled in + size_t j = 0; // whole bytes already copied + uint8_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb bits of w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | | | | | |**|**|... + ^ + j + w : | *| + ^ + bits + out:| *****| *****| *** | |... + ^ ^ + i b + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = 8; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == lsb) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM1344SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) { + // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. + // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. + volatile uint8_t *v = mem; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} diff --git a/crypto_kem/frodokem976aes/META.yml b/crypto_kem/frodokem976aes/META.yml index 78f277b1..2e6e2cfc 100644 --- a/crypto_kem/frodokem976aes/META.yml +++ b/crypto_kem/frodokem976aes/META.yml @@ -23,3 +23,5 @@ auxiliary-submitters: implementations: - name: clean version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 +- name: opt + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 diff --git a/crypto_kem/frodokem976aes/opt/LICENSE b/crypto_kem/frodokem976aes/opt/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/crypto_kem/frodokem976aes/opt/Makefile b/crypto_kem/frodokem976aes/opt/Makefile new file mode 100644 index 00000000..f61cff68 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem976aes_opt.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_aes.o noise.o util.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/frodokem976aes/opt/Makefile.Microsoft_nmake b/crypto_kem/frodokem976aes/opt/Makefile.Microsoft_nmake new file mode 100644 index 00000000..6c65e681 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libfrodokem976aes_opt.lib +OBJECTS=kem.obj matrix_aes.obj noise.obj util.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/frodokem976aes/opt/api.h b/crypto_kem/frodokem976aes/opt/api.h new file mode 100644 index 00000000..d4be07a2 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM976AES_OPT_API_H +#define PQCLEAN_FRODOKEM976AES_OPT_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_SECRETKEYBYTES 31296 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_PUBLICKEYBYTES 15632 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_BYTES 24 +#define PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_CIPHERTEXTBYTES 15744 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_ALGNAME "FrodoKEM-976-AES" + +int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem976aes/opt/common.h b/crypto_kem/frodokem976aes/opt/common.h new file mode 100644 index 00000000..141e41b0 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/common.h @@ -0,0 +1,19 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM976AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM976AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM976AES_OPT_sample_n(uint16_t *s, size_t n); +void PQCLEAN_FRODOKEM976AES_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM976AES_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM976AES_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM976AES_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM976AES_OPT_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM976AES_OPT_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM976AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM976AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(uint16_t n); + +#endif diff --git a/crypto_kem/frodokem976aes/opt/kem.c b/crypto_kem/frodokem976aes/opt/kem.c new file mode 100644 index 00000000..a6ebdc0b --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/kem.c @@ -0,0 +1,238 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" +#include "randombytes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + // FrodoKEM's key generation + // Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes) + // secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH bytes) + uint8_t *pk_seedA = &pk[0]; + uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *sk_s = &sk[0]; + uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + uint8_t *sk_S = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t S[2 * PARAMS_N * PARAMS_NBAR] = {0}; // contains secret data + uint16_t *E = &S[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t randomness[2 * CRYPTO_BYTES + BYTES_SEED_A]; // contains secret data via randomness_s and randomness_seedSE + uint8_t *randomness_s = &randomness[0]; // contains secret data + uint8_t *randomness_seedSE = &randomness[CRYPTO_BYTES]; // contains secret data + uint8_t *randomness_z = &randomness[2 * CRYPTO_BYTES]; + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // Generate the secret value s, the seed for S and E, and the seed for the seed for A. Add seed_A to the public key + randombytes(randomness, CRYPTO_BYTES + CRYPTO_BYTES + BYTES_SEED_A); + shake(pk_seedA, BYTES_SEED_A, randomness_z, BYTES_SEED_A); + + // Generate S and E, and compute B = A*S + E. Generate A on-the-fly + shake_input_seedSE[0] = 0x5F; + memcpy(&shake_input_seedSE[1], randomness_seedSE, CRYPTO_BYTES); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < 2 * PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(S[i]); + } + PQCLEAN_FRODOKEM976AES_OPT_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_sample_n(E, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM976AES_OPT_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Add s, pk and S to the secret key + memcpy(sk_s, randomness_s, CRYPTO_BYTES); + memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(S[i]); + } + memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); + + // Add H(pk) to the secret key + shake(sk_pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + + // Cleanup: + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(randomness, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + // FrodoKEM's key encapsulation + const uint8_t *pk_seedA = &pk[0]; + const uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *ct_c1 = &ct[0]; + uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t V[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via mu + uint8_t *pkh = &G2in[0]; + uint8_t *mu = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSE = &G2out[0]; // contains secret data + uint8_t *k = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // pkh <- G_1(pk), generate random mu, compute (seedSE || k) = G_2(pkh || mu) + shake(pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + randombytes(mu, BYTES_MU); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSE[0] = 0x96; + memcpy(&shake_input_seedSE[1], seedSE, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM976AES_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM976AES_OPT_pack(ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Generate Epp, and compute V = Sp*B + Epp + PQCLEAN_FRODOKEM976AES_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976AES_OPT_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM976AES_OPT_key_encode(C, (uint16_t *)mu); + PQCLEAN_FRODOKEM976AES_OPT_add(C, V, C); + PQCLEAN_FRODOKEM976AES_OPT_pack(ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ); + + // Compute ss = F(ct||KK) + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + memcpy(Fin_k, k, CRYPTO_BYTES); + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM976AES_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + // FrodoKEM's key decapsulation + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t W[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t CC[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t BBp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *ct_c1 = &ct[0]; + const uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + const uint8_t *sk_s = &sk[0]; + const uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + const uint16_t *sk_S = (uint16_t *) &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint16_t S[PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + const uint8_t *pk_seedA = &sk_pk[0]; + const uint8_t *pk_b = &sk_pk[BYTES_SEED_A]; + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via muprime + uint8_t *pkh = &G2in[0]; + uint8_t *muprime = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSEprime = &G2out[0]; // contains secret data + uint8_t *kprime = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data + + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(sk_S[i]); + } + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM976AES_OPT_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976AES_OPT_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976AES_OPT_mul_bs(W, Bp, S); + PQCLEAN_FRODOKEM976AES_OPT_sub(W, C, W); + PQCLEAN_FRODOKEM976AES_OPT_key_decode((uint16_t *)muprime, W); + + // Generate (seedSE' || k') = G_2(pkh || mu') + memcpy(pkh, sk_pkh, BYTES_PKHASH); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSEprime[0] = 0x96; + memcpy(&shake_input_seedSEprime[1], seedSEprime, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM976AES_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM976AES_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM976AES_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976AES_OPT_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM976AES_OPT_key_encode(CC, (uint16_t *)muprime); + PQCLEAN_FRODOKEM976AES_OPT_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); + } + + // Is (Bp == BBp & C == CC) = true + if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { + // Load k' to do ss = F(ct || k') + memcpy(Fin_k, kprime, CRYPTO_BYTES); + } else { + // Load s to do ss = F(ct || s) + memcpy(Fin_k, sk_s, CRYPTO_BYTES); + } + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem976aes/opt/matrix_aes.c b/crypto_kem/frodokem976aes/opt/matrix_aes.c new file mode 100644 index 00000000..a1332fc1 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/matrix_aes.c @@ -0,0 +1,125 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "aes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM976AES_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. + // Inputs: s, e (N x N_BAR) + // Output: out = A*s + e (N x N_BAR) + int k; + uint16_t i, j; + int16_t a_row[4 * PARAMS_N]; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int16_t a_row_temp[4 * PARAMS_N] = {0}; // Take four lines of A at once + aes128ctx ctx128; + + aes128_keyexp(&ctx128, seed_A); + + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { + a_row_temp[j + 1 + 0 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(j); // Loading values in the little-endian order + a_row_temp[j + 1 + 1 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 2 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(j); + a_row_temp[j + 1 + 3 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(j); + } + + for (i = 0; i < PARAMS_N; i += 4) { + for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Go through A, four rows at a time + a_row_temp[j + 0 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(i + 0); // Loading values in the little-endian order + a_row_temp[j + 1 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(i + 1); + a_row_temp[j + 2 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(i + 2); + a_row_temp[j + 3 * PARAMS_N] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(i + 3); + } + aes128_ecb((uint8_t *)a_row, (uint8_t *)a_row_temp, 4 * PARAMS_N * sizeof(int16_t) / AES_BLOCKBYTES, &ctx128); + for (k = 0; k < 4 * PARAMS_N; k++) { + a_row[k] = PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(a_row[k]); + } + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum[4] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[k * PARAMS_N + j]; + sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s + sum[1] += a_row[1 * PARAMS_N + j] * sp; + sum[2] += a_row[2 * PARAMS_N + j] * sp; + sum[3] += a_row[3 * PARAMS_N + j] * sp; + } + out[(i + 0)*PARAMS_NBAR + k] += sum[0]; + out[(i + 2)*PARAMS_NBAR + k] += sum[2]; + out[(i + 1)*PARAMS_NBAR + k] += sum[1]; + out[(i + 3)*PARAMS_NBAR + k] += sum[3]; + } + } + return 1; +} + + + + +int PQCLEAN_FRODOKEM976AES_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. + // Inputs: s', e' (N_BAR x N) + // Output: out = s'*A + e' (N_BAR x N) + int j; + uint16_t i, kk; + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int k; + uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; + uint16_t a_cols_temp[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + aes128ctx ctx128; + + aes128_keyexp(&ctx128, seed_A); + + for (i = 0, j = 0; i < PARAMS_N; i++, j += PARAMS_STRIPE_STEP) { + a_cols_temp[j] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(i); // Loading values in the little-endian order + } + + for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. + for (i = 0; i < (PARAMS_N * PARAMS_STRIPE_STEP); i += PARAMS_STRIPE_STEP) { + a_cols_temp[i + 1] = PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(kk); // Loading values in the little-endian order + } + + aes128_ecb((uint8_t *)a_cols, (uint8_t *)a_cols_temp, PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t) / AES_BLOCKBYTES, &ctx128); + + for (i = 0; i < PARAMS_N; i++) { // Transpose a_cols to have access to it in the column-major order. + for (k = 0; k < PARAMS_STRIPE_STEP; k++) { + a_cols_t[k * PARAMS_N + i] = PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(a_cols[i * PARAMS_STRIPE_STEP + k]); + } + } + + for (i = 0; i < PARAMS_NBAR; i++) { + for (k = 0; k < PARAMS_STRIPE_STEP; k += PARAMS_PARALLEL) { + uint16_t sum[PARAMS_PARALLEL] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[i * PARAMS_N + j]; + sum[0] += sp * a_cols_t[(k + 0) * PARAMS_N + j]; + sum[1] += sp * a_cols_t[(k + 1) * PARAMS_N + j]; + sum[2] += sp * a_cols_t[(k + 2) * PARAMS_N + j]; + sum[3] += sp * a_cols_t[(k + 3) * PARAMS_N + j]; + } + out[i * PARAMS_N + kk + k + 0] += sum[0]; + out[i * PARAMS_N + kk + k + 2] += sum[2]; + out[i * PARAMS_N + kk + k + 1] += sum[1]; + out[i * PARAMS_N + kk + k + 3] += sum[3]; + } + } + } + return 1; +} diff --git a/crypto_kem/frodokem976aes/opt/noise.c b/crypto_kem/frodokem976aes/opt/noise.c new file mode 100644 index 00000000..aa8aa1fd --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/noise.c @@ -0,0 +1,35 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM976AES_OPT_sample_n(uint16_t *s, size_t n) { + // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. + // The distribution is specified by its CDF. + // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output. + size_t i; + unsigned int j; + + for (i = 0; i < n; ++i) { + uint16_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint16_t sign = s[i] & 0x1; // Pick the least significant bit + + // No need to compare with the last value. + for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) { + // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits. + sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15; + } + // Assuming that sign is either 0 or 1, flips sample iff sign = 1 + s[i] = ((-sign) ^ sample) + sign; + } +} diff --git a/crypto_kem/frodokem976aes/opt/params.h b/crypto_kem/frodokem976aes/opt/params.h new file mode 100644 index 00000000..b746f1e7 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM976AES_OPT_CRYPTO_CIPHERTEXTBYTES + +#define PARAMS_N 976 +#define PARAMS_NBAR 8 +#define PARAMS_LOGQ 16 +#define PARAMS_Q (1 << PARAMS_LOGQ) +#define PARAMS_EXTRACTED_BITS 3 +#define PARAMS_STRIPE_STEP 8 +#define PARAMS_PARALLEL 4 +#define BYTES_SEED_A 16 +#define BYTES_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) +#define BYTES_PKHASH CRYPTO_BYTES + +// Selecting SHAKE XOF function for the KEM and noise sampling +#define shake shake256 + +// CDF table +#define CDF_TABLE_DATA {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767} +#define CDF_TABLE_LEN 11 + +#endif diff --git a/crypto_kem/frodokem976aes/opt/util.c b/crypto_kem/frodokem976aes/opt/util.c new file mode 100644 index 00000000..0369e652 --- /dev/null +++ b/crypto_kem/frodokem976aes/opt/util.c @@ -0,0 +1,235 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +uint16_t PQCLEAN_FRODOKEM976AES_OPT_LE_TO_UINT16(uint16_t n) { + return (((uint8_t *) &n)[0] | (((uint8_t *) &n)[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM976AES_OPT_UINT16_TO_LE(uint16_t n) { + uint16_t y; + uint8_t *z = (uint8_t *) &y; + z[0] = n & 0xFF; + z[1] = (n & 0xFF00) >> 8; + return y; +} + +void PQCLEAN_FRODOKEM976AES_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { + // Multiply by s on the right + // Inputs: b (N_BAR x N), s (N x N_BAR) + // Output: out = b*s (N_BAR x N_BAR) + int i, j, k; + + for (i = 0; i < PARAMS_NBAR; i++) { + for (j = 0; j < PARAMS_NBAR; j++) { + out[i * PARAMS_NBAR + j] = 0; + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; + } + out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { + // Multiply by s on the left + // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR) + // Output: out = s*b + e (N_BAR x N_BAR) + int i, j, k; + + for (k = 0; k < PARAMS_NBAR; k++) { + for (i = 0; i < PARAMS_NBAR; i++) { + out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; + for (j = 0; j < PARAMS_N; j++) { + out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + } + out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Add a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a + b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Subtract a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a - b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_key_encode(uint16_t *out, const uint16_t *in) { + // Encoding + unsigned int i, j, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint64_t temp, mask = ((uint64_t)1 << PARAMS_EXTRACTED_BITS) - 1; + uint16_t *pos = out; + + for (i = 0; i < nwords; i++) { + temp = 0; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + temp |= ((uint64_t)((uint8_t *)in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j); + } + for (j = 0; j < npieces_word; j++) { + *pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS)); + temp >>= PARAMS_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_key_decode(uint16_t *out, const uint16_t *in) { + // Decoding + unsigned int i, j, index = 0, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint16_t temp, maskex = ((uint16_t)1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t)1 << PARAMS_LOGQ) - 1; + uint8_t *pos = (uint8_t *)out; + uint64_t templong; + + for (i = 0; i < nwords; i++) { + templong = 0; + for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5) + temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS); + templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j); + index++; + } + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb) { + // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element. + // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied. + memset(out, 0, outlen); + + size_t i = 0; // whole bytes already filled in + size_t j = 0; // whole uint16_t already copied + uint16_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (uint8_t) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = lsb; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == 8) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb) { + // Unpack the input char vector into a uint16_t output vector, copying lsb bits + // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb). + memset(out, 0, outlen * sizeof(uint16_t)); + + size_t i = 0; // whole uint16_t already filled in + size_t j = 0; // whole bytes already copied + uint8_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb bits of w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | | | | | |**|**|... + ^ + j + w : | *| + ^ + bits + out:| *****| *****| *** | |... + ^ ^ + i b + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = 8; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == lsb) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM976AES_OPT_clear_bytes(uint8_t *mem, size_t n) { + // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. + // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. + volatile uint8_t *v = mem; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} diff --git a/crypto_kem/frodokem976shake/META.yml b/crypto_kem/frodokem976shake/META.yml index 35c9c8a8..a519d3e2 100644 --- a/crypto_kem/frodokem976shake/META.yml +++ b/crypto_kem/frodokem976shake/META.yml @@ -23,3 +23,5 @@ auxiliary-submitters: implementations: - name: clean version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 +- name: opt + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/d5bbd0417ba111b08a959c0042a1dcc65fb14a89 diff --git a/crypto_kem/frodokem976shake/opt/LICENSE b/crypto_kem/frodokem976shake/opt/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Microsoft Corporation. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE diff --git a/crypto_kem/frodokem976shake/opt/Makefile b/crypto_kem/frodokem976shake/opt/Makefile new file mode 100644 index 00000000..f1a31b0b --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem976shake_opt.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_shake.o noise.o util.o + +CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS) + +all: $(LIB) + +%.o: %.c $(HEADERS) + $(CC) $(CFLAGS) -c -o $@ $< + +$(LIB): $(OBJECTS) + $(AR) -r $@ $(OBJECTS) + +clean: + $(RM) $(OBJECTS) + $(RM) $(LIB) diff --git a/crypto_kem/frodokem976shake/opt/Makefile.Microsoft_nmake b/crypto_kem/frodokem976shake/opt/Makefile.Microsoft_nmake new file mode 100644 index 00000000..34550918 --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/Makefile.Microsoft_nmake @@ -0,0 +1,19 @@ +# This Makefile can be used with Microsoft Visual Studio's nmake using the command: +# nmake /f Makefile.Microsoft_nmake + +LIBRARY=libfrodokem976shake_opt.lib +OBJECTS=kem.obj matrix_shake.obj noise.obj util.obj + +CFLAGS=/nologo /I ..\..\..\common /W4 /WX + +all: $(LIBRARY) + +# Make sure objects are recompiled if headers change. +$(OBJECTS): *.h + +$(LIBRARY): $(OBJECTS) + LIB.EXE /NOLOGO /WX /OUT:$@ $** + +clean: + -DEL $(OBJECTS) + -DEL $(LIBRARY) diff --git a/crypto_kem/frodokem976shake/opt/api.h b/crypto_kem/frodokem976shake/opt/api.h new file mode 100644 index 00000000..b6bb1a7b --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM976SHAKE_OPT_API_H +#define PQCLEAN_FRODOKEM976SHAKE_OPT_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_SECRETKEYBYTES 31296 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_PUBLICKEYBYTES 15632 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_BYTES 24 +#define PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_CIPHERTEXTBYTES 15744 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_ALGNAME "FrodoKEM-976-SHAKE" + +int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem976shake/opt/common.h b/crypto_kem/frodokem976shake/opt/common.h new file mode 100644 index 00000000..b51cfdf1 --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/common.h @@ -0,0 +1,19 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(uint16_t *s, size_t n); +void PQCLEAN_FRODOKEM976SHAKE_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM976SHAKE_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM976SHAKE_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM976SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM976SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM976SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(uint16_t n); + +#endif diff --git a/crypto_kem/frodokem976shake/opt/kem.c b/crypto_kem/frodokem976shake/opt/kem.c new file mode 100644 index 00000000..69b94ee0 --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/kem.c @@ -0,0 +1,238 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: Key Encapsulation Mechanism (KEM) based on Frodo +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" +#include "randombytes.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) { + // FrodoKEM's key generation + // Outputs: public key pk ( BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 bytes) + // secret key sk (CRYPTO_BYTES + BYTES_SEED_A + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH bytes) + uint8_t *pk_seedA = &pk[0]; + uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *sk_s = &sk[0]; + uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + uint8_t *sk_S = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t S[2 * PARAMS_N * PARAMS_NBAR] = {0}; // contains secret data + uint16_t *E = &S[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t randomness[2 * CRYPTO_BYTES + BYTES_SEED_A]; // contains secret data via randomness_s and randomness_seedSE + uint8_t *randomness_s = &randomness[0]; // contains secret data + uint8_t *randomness_seedSE = &randomness[CRYPTO_BYTES]; // contains secret data + uint8_t *randomness_z = &randomness[2 * CRYPTO_BYTES]; + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // Generate the secret value s, the seed for S and E, and the seed for the seed for A. Add seed_A to the public key + randombytes(randomness, CRYPTO_BYTES + CRYPTO_BYTES + BYTES_SEED_A); + shake(pk_seedA, BYTES_SEED_A, randomness_z, BYTES_SEED_A); + + // Generate S and E, and compute B = A*S + E. Generate A on-the-fly + shake_input_seedSE[0] = 0x5F; + memcpy(&shake_input_seedSE[1], randomness_seedSE, CRYPTO_BYTES); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < 2 * PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(S[i]); + } + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(E, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM976SHAKE_OPT_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Add s, pk and S to the secret key + memcpy(sk_s, randomness_s, CRYPTO_BYTES); + memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(S[i]); + } + memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); + + // Add H(pk) to the secret key + shake(sk_pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + + // Cleanup: + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(randomness, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk) { + // FrodoKEM's key encapsulation + const uint8_t *pk_seedA = &pk[0]; + const uint8_t *pk_b = &pk[BYTES_SEED_A]; + uint8_t *ct_c1 = &ct[0]; + uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t V[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via mu + uint8_t *pkh = &G2in[0]; + uint8_t *mu = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSE = &G2out[0]; // contains secret data + uint8_t *k = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSE[1 + CRYPTO_BYTES]; // contains secret data + + // pkh <- G_1(pk), generate random mu, compute (seedSE || k) = G_2(pkh || mu) + shake(pkh, BYTES_PKHASH, pk, CRYPTO_PUBLICKEYBYTES); + randombytes(mu, BYTES_MU); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute Bp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSE[0] = 0x96; + memcpy(&shake_input_seedSE[1], seedSE, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM976SHAKE_OPT_pack(ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, Bp, PARAMS_N * PARAMS_NBAR, PARAMS_LOGQ); + + // Generate Epp, and compute V = Sp*B + Epp + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM976SHAKE_OPT_key_encode(C, (uint16_t *)mu); + PQCLEAN_FRODOKEM976SHAKE_OPT_add(C, V, C); + PQCLEAN_FRODOKEM976SHAKE_OPT_pack(ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, C, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOGQ); + + // Compute ss = F(ct||KK) + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + memcpy(Fin_k, k, CRYPTO_BYTES); + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM976SHAKE_OPT_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk) { + // FrodoKEM's key decapsulation + uint16_t B[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Bp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t W[PARAMS_NBAR * PARAMS_NBAR] = {0}; // contains secret data + uint16_t C[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t CC[PARAMS_NBAR * PARAMS_NBAR] = {0}; + uint16_t BBp[PARAMS_N * PARAMS_NBAR] = {0}; + uint16_t Sp[(2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR] = {0}; // contains secret data + uint16_t *Ep = &Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = &Sp[2 * PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *ct_c1 = &ct[0]; + const uint8_t *ct_c2 = &ct[(PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8]; + const uint8_t *sk_s = &sk[0]; + const uint8_t *sk_pk = &sk[CRYPTO_BYTES]; + const uint16_t *sk_S = (uint16_t *) &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES]; + uint16_t S[PARAMS_N * PARAMS_NBAR]; // contains secret data + const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2 * PARAMS_N * PARAMS_NBAR]; + const uint8_t *pk_seedA = &sk_pk[0]; + const uint8_t *pk_b = &sk_pk[BYTES_SEED_A]; + uint8_t G2in[BYTES_PKHASH + BYTES_MU]; // contains secret data via muprime + uint8_t *pkh = &G2in[0]; + uint8_t *muprime = &G2in[BYTES_PKHASH]; // contains secret data + uint8_t G2out[2 * CRYPTO_BYTES]; // contains secret data + uint8_t *seedSEprime = &G2out[0]; // contains secret data + uint8_t *kprime = &G2out[CRYPTO_BYTES]; // contains secret data + uint8_t Fin[CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES]; // contains secret data via Fin_k + uint8_t *Fin_ct = &Fin[0]; + uint8_t *Fin_k = &Fin[CRYPTO_CIPHERTEXTBYTES]; // contains secret data + uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data + + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + S[i] = PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(sk_S[i]); + } + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976SHAKE_OPT_mul_bs(W, Bp, S); + PQCLEAN_FRODOKEM976SHAKE_OPT_sub(W, C, W); + PQCLEAN_FRODOKEM976SHAKE_OPT_key_decode((uint16_t *)muprime, W); + + // Generate (seedSE' || k') = G_2(pkh || mu') + memcpy(pkh, sk_pkh, BYTES_PKHASH); + shake(G2out, CRYPTO_BYTES + CRYPTO_BYTES, G2in, BYTES_PKHASH + BYTES_MU); + + // Generate Sp and Ep, and compute BBp = Sp*A + Ep. Generate A on-the-fly + shake_input_seedSEprime[0] = 0x96; + memcpy(&shake_input_seedSEprime[1], seedSEprime, CRYPTO_BYTES); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + for (size_t i = 0; i < (2 * PARAMS_N + PARAMS_NBAR) * PARAMS_NBAR; i++) { + Sp[i] = PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(Sp[i]); + } + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(Ep, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM976SHAKE_OPT_key_encode(CC, (uint16_t *)muprime); + PQCLEAN_FRODOKEM976SHAKE_OPT_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); + } + + // Is (Bp == BBp & C == CC) = true + if (memcmp(Bp, BBp, 2 * PARAMS_N * PARAMS_NBAR) == 0 && memcmp(C, CC, 2 * PARAMS_NBAR * PARAMS_NBAR) == 0) { + // Load k' to do ss = F(ct || k') + memcpy(Fin_k, kprime, CRYPTO_BYTES); + } else { + // Load s to do ss = F(ct || s) + memcpy(Fin_k, sk_s, CRYPTO_BYTES); + } + shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); + + // Cleanup: + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(G2out, 2 * CRYPTO_BYTES); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem976shake/opt/matrix_shake.c b/crypto_kem/frodokem976shake/opt/matrix_shake.c new file mode 100644 index 00000000..43cf3fd2 --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/matrix_shake.c @@ -0,0 +1,108 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" + +#include "api.h" +#include "common.h" +#include "params.h" + +int PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) row-wise, multiply by s on the right. + // Inputs: s, e (N x N_BAR) + // Output: out = A*s + e (N x N_BAR) + int j, k; + uint16_t i; + int16_t a_row[4 * PARAMS_N]; + + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + uint8_t seed_A_separated[2 + BYTES_SEED_A]; + uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; + memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); + for (i = 0; i < PARAMS_N; i += 4) { + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(i + 0); + shake128((unsigned char *)(a_row + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(i + 1); + shake128((unsigned char *)(a_row + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(i + 2); + shake128((unsigned char *)(a_row + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(i + 3); + shake128((unsigned char *)(a_row + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + for (k = 0; k < 4 * PARAMS_N; k++) { + a_row[k] = PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(a_row[k]); + } + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum[4] = {0}; + for (j = 0; j < PARAMS_N; j++) { // Matrix-vector multiplication + uint16_t sp = s[k * PARAMS_N + j]; + sum[0] += a_row[0 * PARAMS_N + j] * sp; // Go through four lines with same s + sum[1] += a_row[1 * PARAMS_N + j] * sp; + sum[2] += a_row[2 * PARAMS_N + j] * sp; + sum[3] += a_row[3 * PARAMS_N + j] * sp; + } + out[(i + 0)*PARAMS_NBAR + k] += sum[0]; + out[(i + 2)*PARAMS_NBAR + k] += sum[2]; + out[(i + 1)*PARAMS_NBAR + k] += sum[1]; + out[(i + 3)*PARAMS_NBAR + k] += sum[3]; + } + } + return 1; +} + + + + +int PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { + // Generate-and-multiply: generate matrix A (N x N) column-wise, multiply by s' on the left. + // Inputs: s', e' (N_BAR x N) + // Output: out = s'*A + e' (N_BAR x N) + int i, j; + uint16_t kk; + for (i = 0; i < (PARAMS_N * PARAMS_NBAR); i += 2) { + *((uint32_t *)&out[i]) = *((uint32_t *)&e[i]); + } + + int t = 0; + uint16_t a_cols[4 * PARAMS_N]; + + int k; + uint8_t seed_A_separated[2 + BYTES_SEED_A]; + uint16_t *seed_A_origin = (uint16_t *)&seed_A_separated; + memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); + for (kk = 0; kk < PARAMS_N; kk += 4) { + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(kk + 0); + shake128((unsigned char *)(a_cols + 0 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(kk + 1); + shake128((unsigned char *)(a_cols + 1 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(kk + 2); + shake128((unsigned char *)(a_cols + 2 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + seed_A_origin[0] = PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(kk + 3); + shake128((unsigned char *)(a_cols + 3 * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + for (i = 0; i < 4 * PARAMS_N; i++) { + a_cols[i] = PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(a_cols[i]); + } + + for (i = 0; i < PARAMS_NBAR; i++) { + uint16_t sum[PARAMS_N] = {0}; + for (j = 0; j < 4; j++) { + uint16_t sp = s[i * PARAMS_N + kk + j]; + for (k = 0; k < PARAMS_N; k++) { // Matrix-vector multiplication + sum[k] += sp * a_cols[(t + j) * PARAMS_N + k]; + } + } + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_N + k] += sum[k]; + } + } + } + return 1; +} diff --git a/crypto_kem/frodokem976shake/opt/noise.c b/crypto_kem/frodokem976shake/opt/noise.c new file mode 100644 index 00000000..d75e1956 --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/noise.c @@ -0,0 +1,35 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM976SHAKE_OPT_sample_n(uint16_t *s, size_t n) { + // Fills vector s with n samples from the noise distribution which requires 16 bits to sample. + // The distribution is specified by its CDF. + // Input: pseudo-random values (2*n bytes) passed in s. The input is overwritten by the output. + size_t i; + unsigned int j; + + for (i = 0; i < n; ++i) { + uint16_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint16_t sign = s[i] & 0x1; // Pick the least significant bit + + // No need to compare with the last value. + for (j = 0; j < (unsigned int)(CDF_TABLE_LEN - 1); j++) { + // Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise. Uses the fact that CDF_TABLE[j] and s fit in 15 bits. + sample += (uint16_t)(CDF_TABLE[j] - prnd) >> 15; + } + // Assuming that sign is either 0 or 1, flips sample iff sign = 1 + s[i] = ((-sign) ^ sample) + sign; + } +} diff --git a/crypto_kem/frodokem976shake/opt/params.h b/crypto_kem/frodokem976shake/opt/params.h new file mode 100644 index 00000000..0bf83cfd --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM976SHAKE_OPT_CRYPTO_CIPHERTEXTBYTES + +#define PARAMS_N 976 +#define PARAMS_NBAR 8 +#define PARAMS_LOGQ 16 +#define PARAMS_Q (1 << PARAMS_LOGQ) +#define PARAMS_EXTRACTED_BITS 3 +#define PARAMS_STRIPE_STEP 8 +#define PARAMS_PARALLEL 4 +#define BYTES_SEED_A 16 +#define BYTES_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) +#define BYTES_PKHASH CRYPTO_BYTES + +// Selecting SHAKE XOF function for the KEM and noise sampling +#define shake shake256 + +// CDF table +#define CDF_TABLE_DATA {5638, 15915, 23689, 28571, 31116, 32217, 32613, 32731, 32760, 32766, 32767} +#define CDF_TABLE_LEN 11 + +#endif diff --git a/crypto_kem/frodokem976shake/opt/util.c b/crypto_kem/frodokem976shake/opt/util.c new file mode 100644 index 00000000..47b20190 --- /dev/null +++ b/crypto_kem/frodokem976shake/opt/util.c @@ -0,0 +1,235 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "common.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_LE_TO_UINT16(uint16_t n) { + return (((uint8_t *) &n)[0] | (((uint8_t *) &n)[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM976SHAKE_OPT_UINT16_TO_LE(uint16_t n) { + uint16_t y; + uint8_t *z = (uint8_t *) &y; + z[0] = n & 0xFF; + z[1] = (n & 0xFF00) >> 8; + return y; +} + +void PQCLEAN_FRODOKEM976SHAKE_OPT_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { + // Multiply by s on the right + // Inputs: b (N_BAR x N), s (N x N_BAR) + // Output: out = b*s (N_BAR x N_BAR) + int i, j, k; + + for (i = 0; i < PARAMS_NBAR; i++) { + for (j = 0; j < PARAMS_NBAR; j++) { + out[i * PARAMS_NBAR + j] = 0; + for (k = 0; k < PARAMS_N; k++) { + out[i * PARAMS_NBAR + j] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; + } + out[i * PARAMS_NBAR + j] = (uint32_t)(out[i * PARAMS_NBAR + j]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e) { + // Multiply by s on the left + // Inputs: b (N x N_BAR), s (N_BAR x N), e (N_BAR x N_BAR) + // Output: out = s*b + e (N_BAR x N_BAR) + int i, j, k; + + for (k = 0; k < PARAMS_NBAR; k++) { + for (i = 0; i < PARAMS_NBAR; i++) { + out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; + for (j = 0; j < PARAMS_N; j++) { + out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + } + out[k * PARAMS_NBAR + i] = (uint32_t)(out[k * PARAMS_NBAR + i]) & ((1 << PARAMS_LOGQ) - 1); + } + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_add(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Add a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a + b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_sub(uint16_t *out, const uint16_t *a, const uint16_t *b) { + // Subtract a and b + // Inputs: a, b (N_BAR x N_BAR) + // Output: c = a - b + + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_key_encode(uint16_t *out, const uint16_t *in) { + // Encoding + unsigned int i, j, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint64_t temp, mask = ((uint64_t)1 << PARAMS_EXTRACTED_BITS) - 1; + uint16_t *pos = out; + + for (i = 0; i < nwords; i++) { + temp = 0; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + temp |= ((uint64_t)((uint8_t *)in)[i * PARAMS_EXTRACTED_BITS + j]) << (8 * j); + } + for (j = 0; j < npieces_word; j++) { + *pos = (uint16_t)((temp & mask) << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS)); + temp >>= PARAMS_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_key_decode(uint16_t *out, const uint16_t *in) { + // Decoding + unsigned int i, j, index = 0, npieces_word = 8; + unsigned int nwords = (PARAMS_NBAR * PARAMS_NBAR) / 8; + uint16_t temp, maskex = ((uint16_t)1 << PARAMS_EXTRACTED_BITS) - 1, maskq = ((uint16_t)1 << PARAMS_LOGQ) - 1; + uint8_t *pos = (uint8_t *)out; + uint64_t templong; + + for (i = 0; i < nwords; i++) { + templong = 0; + for (j = 0; j < npieces_word; j++) { // temp = floor(in*2^{-11}+0.5) + temp = ((in[index] & maskq) + (1 << (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS - 1))) >> (PARAMS_LOGQ - PARAMS_EXTRACTED_BITS); + templong |= ((uint64_t)(temp & maskex)) << (PARAMS_EXTRACTED_BITS * j); + index++; + } + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb) { + // Pack the input uint16 vector into a char output vector, copying lsb bits from each input element. + // If inlen * lsb / 8 > outlen, only outlen * 8 bits are copied. + memset(out, 0, outlen); + + size_t i = 0; // whole bytes already filled in + size_t j = 0; // whole uint16_t already copied + uint16_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (uint8_t) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = lsb; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == 8) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb) { + // Unpack the input char vector into a uint16_t output vector, copying lsb bits + // for each output element from input. outlen must be at least ceil(inlen * 8 / lsb). + memset(out, 0, outlen * sizeof(uint16_t)); + + size_t i = 0; // whole uint16_t already filled in + size_t j = 0; // whole bytes already copied + uint8_t w = 0; // the leftover, not yet copied + uint8_t bits = 0; // the number of lsb bits of w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | | | | | |**|**|... + ^ + j + w : | *| + ^ + bits + out:| *****| *****| *** | |... + ^ ^ + i b + */ + uint8_t b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; + w &= ~(mask << bits); // not strictly necessary; mostly for debugging + + if (bits == 0) { + if (j < inlen) { + w = in[j]; + bits = 8; + j++; + } else { + break; // the input vector is exhausted + } + } + } + if (b == lsb) { // out[i] is filled in + i++; + } + } +} + + +void PQCLEAN_FRODOKEM976SHAKE_OPT_clear_bytes(uint8_t *mem, size_t n) { + // Clear 8-bit bytes from memory. "n" indicates the number of bytes to be zeroed. + // This function uses the volatile type qualifier to inform the compiler not to optimize out the memory clearing. + volatile uint8_t *v = mem; + + for (size_t i = 0; i < n; i++) { + v[i] = 0; + } +} diff --git a/test/duplicate_consistency/frodokem1344aes_opt.yml b/test/duplicate_consistency/frodokem1344aes_opt.yml new file mode 100644 index 00000000..9d81ab98 --- /dev/null +++ b/test/duplicate_consistency/frodokem1344aes_opt.yml @@ -0,0 +1,16 @@ +consistency_checks: +- source: + scheme: frodokem1344aes + implementation: clean + files: + - api.h + - common.h + - params.h + - kem.c + - noise.c + - util.c +- source: + scheme: frodokem640aes + implementation: opt + files: + - matrix_aes.c diff --git a/test/duplicate_consistency/frodokem1344shake_opt.yml b/test/duplicate_consistency/frodokem1344shake_opt.yml new file mode 100644 index 00000000..f0bd1883 --- /dev/null +++ b/test/duplicate_consistency/frodokem1344shake_opt.yml @@ -0,0 +1,16 @@ +consistency_checks: +- source: + scheme: frodokem1344shake + implementation: clean + files: + - api.h + - common.h + - params.h + - kem.c + - noise.c + - util.c +- source: + scheme: frodokem640shake + implementation: opt + files: + - matrix_shake.c diff --git a/test/duplicate_consistency/frodokem976aes_opt.yml b/test/duplicate_consistency/frodokem976aes_opt.yml new file mode 100644 index 00000000..a460521d --- /dev/null +++ b/test/duplicate_consistency/frodokem976aes_opt.yml @@ -0,0 +1,16 @@ +consistency_checks: +- source: + scheme: frodokem976aes + implementation: clean + files: + - api.h + - common.h + - params.h + - kem.c + - noise.c + - util.c +- source: + scheme: frodokem640aes + implementation: opt + files: + - matrix_aes.c diff --git a/test/duplicate_consistency/frodokem976shake_opt.yml b/test/duplicate_consistency/frodokem976shake_opt.yml new file mode 100644 index 00000000..afce9c53 --- /dev/null +++ b/test/duplicate_consistency/frodokem976shake_opt.yml @@ -0,0 +1,16 @@ +consistency_checks: +- source: + scheme: frodokem976shake + implementation: clean + files: + - api.h + - common.h + - params.h + - kem.c + - noise.c + - util.c +- source: + scheme: frodokem640shake + implementation: opt + files: + - matrix_shake.c From 69e00a5b7ffa87ad6e672a04e893bd6ad554c583 Mon Sep 17 00:00:00 2001 From: Ronny Wichers Schreur Date: Wed, 29 May 2019 15:10:11 +0200 Subject: [PATCH 31/35] Expand the pattern rule for the three common tests. Fixes https://github.com/PQClean/PQClean/issues/178. --- test/Makefile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/Makefile b/test/Makefile index 10fae81f..2fdd0eaa 100644 --- a/test/Makefile +++ b/test/Makefile @@ -47,7 +47,13 @@ printparams: $(DEST_DIR)/printparams_$(SCHEME)_$(IMPLEMENTATION) .PHONY: nistkat nistkat: $(DEST_DIR)/nistkat_$(SCHEME)_$(IMPLEMENTATION) -$(DEST_DIR)/test_common_%: common/%.c $(COMMON_FILES) +$(DEST_DIR)/test_common_aes: common/aes.c $(COMMON_FILES) + mkdir -p $(DEST_DIR) + $(CC) $(CFLAGS) $< $(COMMON_FILES) -o $@ +$(DEST_DIR)/test_common_fips202: common/fips202.c $(COMMON_FILES) + mkdir -p $(DEST_DIR) + $(CC) $(CFLAGS) $< $(COMMON_FILES) -o $@ +$(DEST_DIR)/test_common_sha2: common/sha2.c $(COMMON_FILES) mkdir -p $(DEST_DIR) $(CC) $(CFLAGS) $< $(COMMON_FILES) -o $@ From 6ad7937b5e9f5a5660fe44e4959a1494e9c53f73 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 30 May 2019 17:09:53 -0400 Subject: [PATCH 32/35] Fixed link to rust project in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cde8730d..3f9af715 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ Regarding #2, adding the files to your project's build system, each implementati The following projects consume implementations from PQClean and provide their own wrappers around the implementations. Their integration strategies may serve as examples for your own projects. -- **[pqcrypto crate](https://github.com/pqrust/pqcrypto)**: Rust integration that automatically generates wrappers from PQClean source code. +- **[pqcrypto crate](https://github.com/rustpq/pqcrypto)**: Rust integration that automatically generates wrappers from PQClean source code. - **[mupq](https://github.com/mupq/)**: Runs the implementations from PQClean as reference implementations to compare with microcontroller-optimized code. - **[Open Quantum Safe](https://github.com/open-quantum-safe/)**: The Open Quantum Safe project integrates implementations from PQClean into their [liboqs](https://github.com/open-quantum-safe/liboqs) C library, which then exposes them via [C++](https://github.com/open-quantum-safe/liboqs-cpp), [C# / .NET](https://github.com/open-quantum-safe/liboqs-dotnet), and [Python](https://github.com/open-quantum-safe/liboqs-python) wrappers, as well as to forks of [OpenSSL](https://github.com/open-quantum-safe/openssl) and [OpenSSH](https://github.com/open-quantum-safe/openssh-portable). From db7d3deb03653d194c4de1fd02e755c507afbd81 Mon Sep 17 00:00:00 2001 From: Ko- Date: Fri, 7 Jun 2019 11:43:10 +0200 Subject: [PATCH 33/35] Add cSHAKE{128,256} to common. --- common/sp800-185.c | 138 +++++++++++++++++++++++++++++++++++++++++++++ common/sp800-185.h | 23 ++++++++ 2 files changed, 161 insertions(+) create mode 100644 common/sp800-185.c create mode 100644 common/sp800-185.h diff --git a/common/sp800-185.c b/common/sp800-185.c new file mode 100644 index 00000000..929f8518 --- /dev/null +++ b/common/sp800-185.c @@ -0,0 +1,138 @@ +#include +#include + +#include "sp800-185.h" + +static size_t left_encode(uint8_t *encbuf, size_t value) +{ + size_t n, i, v; + + for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 ) + ; /* empty */ + if (n == 0) + n = 1; + for ( i = 1; i <= n; ++i ) + { + encbuf[i] = (uint8_t)(value >> (8 * (n-i))); + } + encbuf[0] = (uint8_t)n; + return n + 1; +} + +void cshake128_inc_init(shake128incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen) { + uint8_t encbuf[sizeof(size_t)+1]; + + shake128_inc_init(state); + + shake128_inc_absorb(state, encbuf, left_encode(encbuf, SHAKE128_RATE)); + + shake128_inc_absorb(state, encbuf, left_encode(encbuf, namelen * 8)); + shake128_inc_absorb(state, name, namelen); + + shake128_inc_absorb(state, encbuf, left_encode(encbuf, cstmlen * 8)); + shake128_inc_absorb(state, cstm, cstmlen); + + if (state->ctx[25] != 0) { + state->ctx[25] = SHAKE128_RATE - 1; + encbuf[0] = 0; + shake128_inc_absorb(state, encbuf, 1); + } +} + +void cshake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen) { + shake128_inc_absorb(state, input, inlen); +} + +void cshake128_inc_finalize(shake128incctx *state) { + state->ctx[state->ctx[25] >> 3] ^= (uint64_t)0x04 << (8 * (state->ctx[25] & 0x07)); + state->ctx[(SHAKE128_RATE - 1) >> 3] ^= (uint64_t)128 << (8 * ((SHAKE128_RATE - 1) & 0x07)); + state->ctx[25] = 0; +} + +void cshake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state) { + shake128_inc_squeeze(output, outlen, state); +} + +void cshake256_inc_init(shake256incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen) { + uint8_t encbuf[sizeof(size_t)+1]; + + shake256_inc_init(state); + + shake256_inc_absorb(state, encbuf, left_encode(encbuf, SHAKE256_RATE)); + + shake256_inc_absorb(state, encbuf, left_encode(encbuf, namelen * 8)); + shake256_inc_absorb(state, name, namelen); + + shake256_inc_absorb(state, encbuf, left_encode(encbuf, cstmlen * 8)); + shake256_inc_absorb(state, cstm, cstmlen); + + if (state->ctx[25] != 0) { + state->ctx[25] = SHAKE256_RATE - 1; + encbuf[0] = 0; + shake256_inc_absorb(state, encbuf, 1); + } +} + +void cshake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen) { + shake256_inc_absorb(state, input, inlen); +} + +void cshake256_inc_finalize(shake256incctx *state) { + state->ctx[state->ctx[25] >> 3] ^= (uint64_t)0x04 << (8 * (state->ctx[25] & 0x07)); + state->ctx[(SHAKE256_RATE - 1) >> 3] ^= (uint64_t)128 << (8 * ((SHAKE256_RATE - 1) & 0x07)); + state->ctx[25] = 0; +} + +void cshake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state) { + shake256_inc_squeeze(output, outlen, state); +} + +/************************************************* + * Name: cshake128 + * + * Description: cSHAKE128 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *name: pointer to function-name string + * - size_t namelen: length of function-name string in bytes + * - const uint8_t *cstm: pointer to non-empty customization string + * - size_t cstmlen: length of customization string in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void cshake128(uint8_t *output, size_t outlen, + const uint8_t *name, size_t namelen, + const uint8_t *cstm, size_t cstmlen, + const uint8_t *input, size_t inlen) { + shake128incctx state; + cshake128_inc_init(&state, name, namelen, cstm, cstmlen); + cshake128_inc_absorb(&state, input, inlen); + cshake128_inc_finalize(&state); + cshake128_inc_squeeze(output, outlen, &state); +} + +/************************************************* + * Name: cshake256 + * + * Description: cSHAKE256 XOF with non-incremental API + * + * Arguments: - uint8_t *output: pointer to output + * - size_t outlen: requested output length in bytes + * - const uint8_t *name: pointer to function-name string + * - size_t namelen: length of function-name string in bytes + * - const uint8_t *cstm: pointer to non-empty customization string + * - size_t cstmlen: length of customization string in bytes + * - const uint8_t *input: pointer to input + * - size_t inlen: length of input in bytes + **************************************************/ +void cshake256(uint8_t *output, size_t outlen, + const uint8_t *name, size_t namelen, + const uint8_t *cstm, size_t cstmlen, + const uint8_t *input, size_t inlen) { + shake256incctx state; + cshake256_inc_init(&state, name, namelen, cstm, cstmlen); + cshake256_inc_absorb(&state, input, inlen); + cshake256_inc_finalize(&state); + cshake256_inc_squeeze(output, outlen, &state); +} diff --git a/common/sp800-185.h b/common/sp800-185.h new file mode 100644 index 00000000..06781523 --- /dev/null +++ b/common/sp800-185.h @@ -0,0 +1,23 @@ +#ifndef SP800_185_H +#define SP800_185_H + +#include +#include + +#include "fips202.h" + +void cshake128_inc_init(shake128incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen); +void cshake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); +void cshake128_inc_finalize(shake128incctx *state); +void cshake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); + +void cshake128(uint8_t *output, size_t outlen, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen, const uint8_t *input, size_t inlen); + +void cshake256_inc_init(shake256incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen); +void cshake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); +void cshake256_inc_finalize(shake256incctx *state); +void cshake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); + +void cshake256(uint8_t *output, size_t outlen, const uint8_t *name, size_t namelen, const uint8_t* cstm, size_t cstmlen, const uint8_t *input, size_t inlen); + +#endif From eca0ebd374ed773595b5002d950dcf0e705298d8 Mon Sep 17 00:00:00 2001 From: Ko- Date: Fri, 7 Jun 2019 11:46:55 +0200 Subject: [PATCH 34/35] Add test for functions from SP800-185. --- test/Makefile | 6 +- test/Makefile.Microsoft_nmake | 4 +- test/common/sp800-185.c | 146 ++++++++++++++++++++++++++++++++++ 3 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 test/common/sp800-185.c diff --git a/test/Makefile b/test/Makefile index 2fdd0eaa..3963d9bd 100644 --- a/test/Makefile +++ b/test/Makefile @@ -10,7 +10,7 @@ SCHEME_UPPERCASE=$(shell echo $(SCHEME) | tr a-z A-Z | sed 's/-//g') IMPLEMENTATION_UPPERCASE=$(shell echo $(IMPLEMENTATION) | tr a-z A-Z | sed 's/-//g') COMMON_DIR=../common -COMMON_FILES=$(COMMON_DIR)/aes.c $(COMMON_DIR)/sha2.c $(COMMON_DIR)/fips202.c +COMMON_FILES=$(COMMON_DIR)/aes.c $(COMMON_DIR)/sha2.c $(COMMON_DIR)/fips202.c $(COMMON_DIR)/sp800-185.c COMMON_HEADERS=$(COMMON_DIR)/*.h DEST_DIR=../bin @@ -56,6 +56,9 @@ $(DEST_DIR)/test_common_fips202: common/fips202.c $(COMMON_FILES) $(DEST_DIR)/test_common_sha2: common/sha2.c $(COMMON_FILES) mkdir -p $(DEST_DIR) $(CC) $(CFLAGS) $< $(COMMON_FILES) -o $@ +$(DEST_DIR)/test_common_sp800-185: common/sp800-185.c $(COMMON_FILES) + mkdir -p $(DEST_DIR) + $(CC) $(CFLAGS) $< $(COMMON_FILES) -o $@ $(DEST_DIR)/functest_$(SCHEME)_$(IMPLEMENTATION): build-scheme crypto_$(TYPE)/functest.c $(COMMON_FILES) $(COMMON_DIR)/randombytes.c $(COMMON_HEADERS) mkdir -p $(DEST_DIR) @@ -82,6 +85,7 @@ clean: $(RM) $(DEST_DIR)/test_aes $(RM) $(DEST_DIR)/test_fips202 $(RM) $(DEST_DIR)/test_sha2 + $(RM) $(DEST_DIR)/test_sp800-185 .PHONY: distclean distclean: diff --git a/test/Makefile.Microsoft_nmake b/test/Makefile.Microsoft_nmake index d0bb5abc..3bd9f0df 100644 --- a/test/Makefile.Microsoft_nmake +++ b/test/Makefile.Microsoft_nmake @@ -12,8 +12,8 @@ IMPLEMENTATION_UPPERCASE=CLEAN SCHEME_DIR=..\crypto_$(TYPE)\$(SCHEME)\$(IMPLEMENTATION) COMMON_DIR=..\common -COMMON_OBJECTS=$(COMMON_DIR)\aes.obj $(COMMON_DIR)\fips202.obj $(COMMON_DIR)\sha2.obj -COMMON_OBJECTS_NOPATH=aes.obj fips202.obj sha2.obj +COMMON_OBJECTS=$(COMMON_DIR)\aes.obj $(COMMON_DIR)\fips202.obj $(COMMON_DIR)\sha2.obj $(COMMON_DIR)\sp800-185.obj +COMMON_OBJECTS_NOPATH=aes.obj fips202.obj sha2.obj sp800-185.obj DEST_DIR=..\bin diff --git a/test/common/sp800-185.c b/test/common/sp800-185.c new file mode 100644 index 00000000..f77d3fb4 --- /dev/null +++ b/test/common/sp800-185.c @@ -0,0 +1,146 @@ +#include +#include +#include + +#include "sp800-185.h" + +const unsigned char name[] = ""; +const unsigned char customization[] = "Email Signature"; + +const unsigned char output1[32] = { + 0xC1, 0xC3, 0x69, 0x25, 0xB6, 0x40, 0x9A, 0x04, 0xF1, 0xB5, 0x04, 0xFC, 0xBC, 0xA9, 0xD8, 0x2B, + 0x40, 0x17, 0x27, 0x7C, 0xB5, 0xED, 0x2B, 0x20, 0x65, 0xFC, 0x1D, 0x38, 0x14, 0xD5, 0xAA, 0xF5 +}; +const unsigned char output2[32] = { + 0xC5, 0x22, 0x1D, 0x50, 0xE4, 0xF8, 0x22, 0xD9, 0x6A, 0x2E, 0x88, 0x81, 0xA9, 0x61, 0x42, 0x0F, + 0x29, 0x4B, 0x7B, 0x24, 0xFE, 0x3D, 0x20, 0x94, 0xBA, 0xED, 0x2C, 0x65, 0x24, 0xCC, 0x16, 0x6B +}; +const unsigned char output3[64] = { + 0xD0, 0x08, 0x82, 0x8E, 0x2B, 0x80, 0xAC, 0x9D, 0x22, 0x18, 0xFF, 0xEE, 0x1D, 0x07, 0x0C, 0x48, + 0xB8, 0xE4, 0xC8, 0x7B, 0xFF, 0x32, 0xC9, 0x69, 0x9D, 0x5B, 0x68, 0x96, 0xEE, 0xE0, 0xED, 0xD1, + 0x64, 0x02, 0x0E, 0x2B, 0xE0, 0x56, 0x08, 0x58, 0xD9, 0xC0, 0x0C, 0x03, 0x7E, 0x34, 0xA9, 0x69, + 0x37, 0xC5, 0x61, 0xA7, 0x4C, 0x41, 0x2B, 0xB4, 0xC7, 0x46, 0x46, 0x95, 0x27, 0x28, 0x1C, 0x8C +}; +const unsigned char output4[64] = { + 0x07, 0xDC, 0x27, 0xB1, 0x1E, 0x51, 0xFB, 0xAC, 0x75, 0xBC, 0x7B, 0x3C, 0x1D, 0x98, 0x3E, 0x8B, + 0x4B, 0x85, 0xFB, 0x1D, 0xEF, 0xAF, 0x21, 0x89, 0x12, 0xAC, 0x86, 0x43, 0x02, 0x73, 0x09, 0x17, + 0x27, 0xF4, 0x2B, 0x17, 0xED, 0x1D, 0xF6, 0x3E, 0x8E, 0xC1, 0x18, 0xF0, 0x4B, 0x23, 0x63, 0x3C, + 0x1D, 0xFB, 0x15, 0x74, 0xC8, 0xFB, 0x55, 0xCB, 0x45, 0xDA, 0x8E, 0x25, 0xAF, 0xB0, 0x92, 0xBB +}; + +static int test_cshake128(void) { + unsigned char input[200]; + unsigned char output[32]; + int i; + int returncode = 0; + size_t namelen = strlen((const char *)name); + size_t cstmlen = strlen((const char *)customization); + + for (i = 0; i < 4; i++) { + input[i] = i; + } + + cshake128(output, 32, name, namelen, customization, cstmlen, input, 4); + + if (memcmp(output1, output, 32) != 0) { + puts("ERROR shake128 did not match test vector 1."); + printf(" Expected: "); + for (i = 0; i < 32; i++) { + printf("%02X", output1[i]); + } + puts(""); + printf(" Received: "); + for (i = 0; i < 32; i++) { + printf("%02X", output[i]); + } + puts(""); + returncode = 1; + } + + for (i = 0; i < 200; i++) { + input[i] = i; + } + + cshake128(output, 32, name, namelen, customization, cstmlen, input, 200); + + if (memcmp(output2, output, 32) != 0) { + puts("ERROR shake128 did not match test vector 2."); + printf(" Expected: "); + for (i = 0; i < 32; i++) { + printf("%02X", output2[i]); + } + puts(""); + printf(" Received: "); + for (i = 0; i < 32; i++) { + printf("%02X", output[i]); + } + puts(""); + returncode = 1; + } + + return returncode; +} + +static int test_cshake256(void) { + unsigned char input[200]; + unsigned char output[64]; + int i; + int returncode = 0; + size_t namelen = strlen((const char *)name); + size_t cstmlen = strlen((const char *)customization); + + for (i = 0; i < 4; i++) { + input[i] = i; + } + + cshake256(output, 64, name, namelen, customization, cstmlen, input, 4); + + if (memcmp(output3, output, 64) != 0) { + puts("ERROR shake256 did not match test vector 3."); + printf(" Expected: "); + for (i = 0; i < 64; i++) { + printf("%02X", output3[i]); + } + puts(""); + printf(" Received: "); + for (i = 0; i < 64; i++) { + printf("%02X", output[i]); + } + puts(""); + returncode = 1; + } + + for (i = 0; i < 200; i++) { + input[i] = i; + } + + cshake256(output, 64, name, namelen, customization, cstmlen, input, 200); + + if (memcmp(output4, output, 64) != 0) { + puts("ERROR shake256 did not match test vector 4."); + printf(" Expected: "); + for (i = 0; i < 64; i++) { + printf("%02X", output4[i]); + } + puts(""); + printf(" Received: "); + for (i = 0; i < 64; i++) { + printf("%02X", output[i]); + } + puts(""); + returncode = 1; + } + + return returncode; +} + +int main(void) { + int result = 0; + result += test_cshake128(); + result += test_cshake256(); + + if (result != 0) { + puts("Errors occurred"); + } + return result; +} From cf88fb781ed2f1e6571c725be34bd4c382662220 Mon Sep 17 00:00:00 2001 From: Ko- Date: Fri, 7 Jun 2019 13:45:11 +0200 Subject: [PATCH 35/35] Satisfy linter --- common/sp800-185.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common/sp800-185.c b/common/sp800-185.c index 929f8518..b21e81fc 100644 --- a/common/sp800-185.c +++ b/common/sp800-185.c @@ -3,16 +3,16 @@ #include "sp800-185.h" -static size_t left_encode(uint8_t *encbuf, size_t value) -{ +static size_t left_encode(uint8_t *encbuf, size_t value) { size_t n, i, v; - for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 ) + for (v = value, n = 0; v && (n < sizeof(size_t)); n++, v >>= 8) { ; /* empty */ - if (n == 0) + } + if (n == 0) { n = 1; - for ( i = 1; i <= n; ++i ) - { + } + for (i = 1; i <= n; i++) { encbuf[i] = (uint8_t)(value >> (8 * (n-i))); } encbuf[0] = (uint8_t)n;