From 812c7f54ac736380abd2581aa070448be9a3eb32 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 22:56:28 -0400 Subject: [PATCH 01/12] Global search and replace on sed --- test/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Makefile b/test/Makefile index add8a886..e08bb25b 100644 --- a/test/Makefile +++ b/test/Makefile @@ -6,8 +6,8 @@ SCHEME=kyber768 IMPLEMENTATION=clean SCHEME_DIR="../crypto_$(TYPE)/$(SCHEME)/$(IMPLEMENTATION)" -SCHEME_UPPERCASE=$(shell echo $(SCHEME) | tr a-z A-Z | sed 's/-//') -IMPLEMENTATION_UPPERCASE=$(shell echo $(IMPLEMENTATION) | tr a-z A-Z | sed 's/-//') +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)/fips202.c $(COMMON_DIR)/sha2.c From a2399091a730270e2203692e68752019ec73a85c Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 22:56:45 -0400 Subject: [PATCH 02/12] Initial FrodoKEM-640-SHAKE implementation --- crypto_kem/frodokem640shake/META.yml | 22 ++ crypto_kem/frodokem640shake/clean/LICENSE | 21 ++ crypto_kem/frodokem640shake/clean/Makefile | 19 ++ crypto_kem/frodokem640shake/clean/api.h | 20 ++ crypto_kem/frodokem640shake/clean/common.h | 17 ++ crypto_kem/frodokem640shake/clean/kem.c | 218 +++++++++++++++++ .../frodokem640shake/clean/matrix_shake.c | 72 ++++++ crypto_kem/frodokem640shake/clean/noise.c | 33 +++ crypto_kem/frodokem640shake/clean/params.h | 27 +++ crypto_kem/frodokem640shake/clean/util.c | 221 ++++++++++++++++++ 10 files changed, 670 insertions(+) create mode 100644 crypto_kem/frodokem640shake/META.yml create mode 100644 crypto_kem/frodokem640shake/clean/LICENSE create mode 100644 crypto_kem/frodokem640shake/clean/Makefile create mode 100644 crypto_kem/frodokem640shake/clean/api.h create mode 100644 crypto_kem/frodokem640shake/clean/common.h create mode 100644 crypto_kem/frodokem640shake/clean/kem.c create mode 100644 crypto_kem/frodokem640shake/clean/matrix_shake.c create mode 100644 crypto_kem/frodokem640shake/clean/noise.c create mode 100644 crypto_kem/frodokem640shake/clean/params.h create mode 100644 crypto_kem/frodokem640shake/clean/util.c diff --git a/crypto_kem/frodokem640shake/META.yml b/crypto_kem/frodokem640shake/META.yml new file mode 100644 index 00000000..87c37449 --- /dev/null +++ b/crypto_kem/frodokem640shake/META.yml @@ -0,0 +1,22 @@ +name: FrodoKEM-640-SHAKE +type: kem +claimed-nist-level: 1 +length-public-key: 9616 +length-ciphertext: 9720 +testvectors-sha256: 521ff891de20efe74e6584d09612dae989427ac76261a41630c4e4d6a4fc78a4 +principal-submitter: Douglas Stebila, University of Waterloo +auxiliary-submitters: + - Erdem Alkim + - Joppe W. Bos, NXP Semiconductors + - Léo Ducas, CWI + - Patrick Longa, Microsoft Research + - Ilya Mironov, Google + - Michael Naehrig, Microsoft Research + - Valeria Nikolaenko + - Chris Peikert, University of Michigan + - Ananth Raghunathan, Google + - Karen Easterbrook, Microsoft Research + - Brian LaMacchia, Microsoft Research +implementations: + - name: clean + version: https://github.com/Microsoft/PQCrypto-LWEKE/commit/437e228fca580a82435cab09f30ae14b03183119 diff --git a/crypto_kem/frodokem640shake/clean/LICENSE b/crypto_kem/frodokem640shake/clean/LICENSE new file mode 100644 index 00000000..5cf7c8db --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/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/clean/Makefile b/crypto_kem/frodokem640shake/clean/Makefile new file mode 100644 index 00000000..1c9112d5 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/Makefile @@ -0,0 +1,19 @@ +# This Makefile can be used with GNU Make or BSD Make + +LIB=libfrodokem640shake_clean.a +HEADERS=api.h params.h common.h +OBJECTS=kem.o matrix_shake.o noise.o util.o + +CFLAGS=-Wall -Wextra -Wpedantic -Werror -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/clean/api.h b/crypto_kem/frodokem640shake/clean/api.h new file mode 100644 index 00000000..74bbdab2 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/api.h @@ -0,0 +1,20 @@ +#ifndef PQCLEAN_FRODOKEM640SHAKE_CLEAN_API_H +#define PQCLEAN_FRODOKEM640SHAKE_CLEAN_API_H + +#include +#include + +#define PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_SECRETKEYBYTES 19888 // sizeof(s) + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR + BYTES_PKHASH +#define PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_PUBLICKEYBYTES 9616 // sizeof(seed_A) + (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 +#define PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_BYTES 16 +#define PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_CIPHERTEXTBYTES 9720 // (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8 + (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8 + +#define PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_ALGNAME "FrodoKEM-640-SHAKE" + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk); + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk); + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk); + +#endif diff --git a/crypto_kem/frodokem640shake/clean/common.h b/crypto_kem/frodokem640shake/clean/common.h new file mode 100644 index 00000000..03f73da8 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/common.h @@ -0,0 +1,17 @@ +#ifndef COMMON_H +#define COMMON_H + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, const size_t n); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); + +#endif diff --git a/crypto_kem/frodokem640shake/clean/kem.c b/crypto_kem/frodokem640shake/clean/kem.c new file mode 100644 index 00000000..e1eb8d83 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/kem.c @@ -0,0 +1,218 @@ +/******************************************************************************************** +* 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 "params.h" +#include "common.h" + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char* pk, unsigned char* 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 = (uint16_t *)&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); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(S, PARAMS_N*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(E, PARAMS_N*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(B, S, E, pk); + + // Encode the second part of the public key + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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); + 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_CLEAN_clear_bytes((uint8_t *)S, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)E, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(randomness, 2*CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *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 = (uint16_t *)&Sp[PARAMS_N*PARAMS_NBAR]; // contains secret data + uint16_t *Epp = (uint16_t *)&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); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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_CLEAN_sample_n(Epp, PARAMS_NBAR*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(B, PARAMS_N*PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(V, B, Sp, Epp); + + // Encode mu, and compute C = V + enc(mu) (mod q) + PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(C, (uint16_t*)mu); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(C, V, C); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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_CLEAN_clear_bytes((uint8_t *)V, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(mu, BYTES_MU); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(G2out, 2*CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); + return 0; +} + + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *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 = (uint16_t *)&Sp[PARAMS_N*PARAMS_NBAR]; // contains secret data + uint16_t *Epp = (uint16_t *)&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]; + 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 + + // Compute W = C - Bp*S (mod q), and decode the randomness mu + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(Bp, PARAMS_N*PARAMS_NBAR, ct_c1, (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(C, PARAMS_NBAR*PARAMS_NBAR, ct_c2, (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(W, Bp, sk_S); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(W, C, W); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); + + // Generate Epp, and compute W = Sp*B + Epp + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Epp, PARAMS_NBAR*PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(B, PARAMS_N*PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(W, B, Sp, Epp); + + // Encode mu, and compute CC = W + enc(mu') (mod q) + PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(CC, (uint16_t*)muprime); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(CC, W, CC); + + // Prepare input to F + memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); + + // Reducing BBp modulo q + for (int 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_CLEAN_clear_bytes((uint8_t *)W, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(muprime, BYTES_MU); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(G2out, 2*CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(Fin_k, CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); + return 0; +} diff --git a/crypto_kem/frodokem640shake/clean/matrix_shake.c b/crypto_kem/frodokem640shake/clean/matrix_shake.c new file mode 100644 index 00000000..d81eb8d5 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/matrix_shake.c @@ -0,0 +1,72 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: matrix arithmetic functions used by the KEM +*********************************************************************************************/ + +#include +#include + +#include "fips202.h" + +#include "api.h" +#include "params.h" + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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[PARAMS_N * 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 (i = 0; i < PARAMS_N; i++) { + seed_A_origin[0] = (uint16_t) i; + shake128((unsigned char*)(A + i*PARAMS_N), (unsigned long long)(2*PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + } + memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); + + for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum = 0; + for (j = 0; j < PARAMS_N; j++) { + sum += A[i*PARAMS_N + j] * s[k*PARAMS_N + j]; + } + out[i*PARAMS_NBAR + k] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on. + } + } + + return 1; +} + + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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; + int16_t A[PARAMS_N * 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 (i = 0; i < PARAMS_N; i++) { + seed_A_origin[0] = (uint16_t) i; + shake128((unsigned char*)(A + i*PARAMS_N), (unsigned long long)(2*PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + } + memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); + + for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum = 0; + for (j = 0; j < PARAMS_N; j++) { + sum += A[j*PARAMS_N + i] * s[k*PARAMS_N + j]; + } + out[k*PARAMS_N + i] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on. + } + } + + return 1; +} diff --git a/crypto_kem/frodokem640shake/clean/noise.c b/crypto_kem/frodokem640shake/clean/noise.c new file mode 100644 index 00000000..f2cc96b8 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/noise.c @@ -0,0 +1,33 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: noise sampling functions +*********************************************************************************************/ + +#include + +#include "api.h" +#include "params.h" + +static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; + +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, const 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. + unsigned int i, j; + + for (i = 0; i < n; ++i) { + uint8_t sample = 0; + uint16_t prnd = s[i] >> 1; // Drop the least significant bit + uint8_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/clean/params.h b/crypto_kem/frodokem640shake/clean/params.h new file mode 100644 index 00000000..ebd981b9 --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/params.h @@ -0,0 +1,27 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define CRYPTO_SECRETKEYBYTES PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_SECRETKEYBYTES +#define CRYPTO_PUBLICKEYBYTES PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_PUBLICKEYBYTES +#define CRYPTO_BYTES PQCLEAN_FRODOKEM640SHAKE_CLEAN_CRYPTO_BYTES +#define CRYPTO_CIPHERTEXTBYTES PQCLEAN_FRODOKEM640SHAKE_CLEAN_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/clean/util.c b/crypto_kem/frodokem640shake/clean/util.c new file mode 100644 index 00000000..2f13887f --- /dev/null +++ b/crypto_kem/frodokem640shake/clean/util.c @@ -0,0 +1,221 @@ +/******************************************************************************************** +* FrodoKEM: Learning with Errors Key Encapsulation +* +* Abstract: additional functions for FrodoKEM +*********************************************************************************************/ + +#include +#include + +#include "api.h" +#include "params.h" + +#define min(x, y) (((x) < (y)) ? (x) : (y)) + + +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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_EXTRACTED_BITS; + pos++; + } + } +} + + +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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_CLEAN_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char 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 + unsigned char bits = 0; // the number of lsb in w + + while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { + /* + in: | | |********|********| + ^ + j + w : | ****| + ^ + bits + out:|**|**|**|**|**|**|**|**|* | + ^^ + ib + */ + unsigned char b = 0; // bits in out[i] already filled in + while (b < 8) { + int nbits = min(8 - b, bits); + uint16_t mask = (1 << nbits) - 1; + unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (8 - b - nbits)); + b += nbits; + bits -= 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_CLEAN_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char 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 + unsigned char w = 0; // the leftover, not yet copied + unsigned char 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 + */ + unsigned char b = 0; // bits in out[i] already filled in + while (b < lsb) { + int nbits = min(lsb - b, bits); + uint16_t mask = (1 << nbits) - 1; + unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + out[i] = out[i] + (t << (lsb - b - nbits)); + b += nbits; + bits -= 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_CLEAN_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 7485f353667e0689e41db659f50c9fee314ef813 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 23:27:16 -0400 Subject: [PATCH 03/12] Apply astyle --- crypto_kem/frodokem640shake/clean/common.h | 2 +- crypto_kem/frodokem640shake/clean/kem.c | 146 +++++++++--------- .../frodokem640shake/clean/matrix_shake.c | 84 +++++----- crypto_kem/frodokem640shake/clean/noise.c | 8 +- crypto_kem/frodokem640shake/clean/util.c | 102 ++++++------ 5 files changed, 173 insertions(+), 169 deletions(-) diff --git a/crypto_kem/frodokem640shake/clean/common.h b/crypto_kem/frodokem640shake/clean/common.h index 03f73da8..9eeccdec 100644 --- a/crypto_kem/frodokem640shake/clean/common.h +++ b/crypto_kem/frodokem640shake/clean/common.h @@ -4,7 +4,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, const size_t n); -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(uint16_t *out, const uint16_t *a, const uint16_t *b); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); diff --git a/crypto_kem/frodokem640shake/clean/kem.c b/crypto_kem/frodokem640shake/clean/kem.c index e1eb8d83..cb50c3ac 100644 --- a/crypto_kem/frodokem640shake/clean/kem.c +++ b/crypto_kem/frodokem640shake/clean/kem.c @@ -14,23 +14,23 @@ #include "params.h" #include "common.h" -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char* pk, unsigned char* 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) +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *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 = (uint16_t *)&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 *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 = (uint16_t *)&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 *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 @@ -40,48 +40,48 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char* pk, unsigne // 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); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(S, PARAMS_N*PARAMS_NBAR); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(E, PARAMS_N*PARAMS_NBAR); + shake((uint8_t *)S, 2 * PARAMS_N * PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(S, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(E, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(B, S, E, pk); // Encode the second part of the public key - PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, B, PARAMS_N*PARAMS_NBAR, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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); - memcpy(sk_S, S, 2*PARAMS_N*PARAMS_NBAR); + 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_CLEAN_clear_bytes((uint8_t *)S, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)E, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(randomness, 2*CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)E, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(randomness, 2 * CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); return 0; } -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) -{ // FrodoKEM's key encapsulation +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *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 = (uint16_t *)&Sp[PARAMS_N*PARAMS_NBAR]; // contains secret data - uint16_t *Epp = (uint16_t *)&Sp[2*PARAMS_N*PARAMS_NBAR]; // contains secret data + 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 = (uint16_t *)&Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = (uint16_t *)&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 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 @@ -97,21 +97,21 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned ch // 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); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N*PARAMS_NBAR); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N*PARAMS_NBAR); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSE, 1 + CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(ct_c1, (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8, Bp, PARAMS_N*PARAMS_NBAR, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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_CLEAN_sample_n(Epp, PARAMS_NBAR*PARAMS_NBAR); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(B, PARAMS_N*PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(V, B, Sp, Epp); // Encode mu, and compute C = V + enc(mu) (mod q) - PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(C, (uint16_t*)mu); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(C, (uint16_t *)mu); PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(C, V, C); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(ct_c2, (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8, C, PARAMS_NBAR*PARAMS_NBAR, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_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); @@ -119,41 +119,41 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned ch shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); // Cleanup: - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)V, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)V, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(mu, BYTES_MU); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(G2out, 2*CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(G2out, 2 * CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(Fin_k, CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(shake_input_seedSE, 1 + CRYPTO_BYTES); return 0; } -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *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 = (uint16_t *)&Sp[PARAMS_N*PARAMS_NBAR]; // contains secret data - uint16_t *Epp = (uint16_t *)&Sp[2*PARAMS_N*PARAMS_NBAR]; // contains secret data +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *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 = (uint16_t *)&Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data + uint16_t *Epp = (uint16_t *)&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 *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]; - const uint8_t *sk_pkh = &sk[CRYPTO_BYTES + CRYPTO_PUBLICKEYBYTES + 2*PARAMS_N*PARAMS_NBAR]; + 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 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 @@ -162,11 +162,11 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig uint8_t shake_input_seedSEprime[1 + CRYPTO_BYTES]; // contains secret data // Compute W = C - Bp*S (mod q), and decode the randomness mu - PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(Bp, PARAMS_N*PARAMS_NBAR, ct_c1, (PARAMS_LOGQ*PARAMS_N*PARAMS_NBAR)/8, PARAMS_LOGQ); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(C, PARAMS_NBAR*PARAMS_NBAR, ct_c2, (PARAMS_LOGQ*PARAMS_NBAR*PARAMS_NBAR)/8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(W, Bp, sk_S); PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(W, C, W); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode((uint16_t*)muprime, W); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode((uint16_t *)muprime, W); // Generate (seedSE' || k') = G_2(pkh || mu') memcpy(pkh, sk_pkh, BYTES_PKHASH); @@ -175,28 +175,30 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig // 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); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N*PARAMS_NBAR); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N*PARAMS_NBAR); + shake((uint8_t *)Sp, (2 * PARAMS_N + PARAMS_NBAR)*PARAMS_NBAR * sizeof(uint16_t), shake_input_seedSEprime, 1 + CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); // Generate Epp, and compute W = Sp*B + Epp - PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Epp, PARAMS_NBAR*PARAMS_NBAR); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(B, PARAMS_N*PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Epp, PARAMS_NBAR * PARAMS_NBAR); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(B, PARAMS_N * PARAMS_NBAR, pk_b, CRYPTO_PUBLICKEYBYTES - BYTES_SEED_A, PARAMS_LOGQ); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(W, B, Sp, Epp); // Encode mu, and compute CC = W + enc(mu') (mod q) - PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(CC, (uint16_t*)muprime); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(CC, (uint16_t *)muprime); PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(CC, W, CC); // Prepare input to F memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); // Reducing BBp modulo q - for (int i = 0; i < PARAMS_N*PARAMS_NBAR; i++) BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ)-1); + for (int 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) { + 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 { @@ -206,12 +208,12 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig shake(ss, CRYPTO_BYTES, Fin, CRYPTO_CIPHERTEXTBYTES + CRYPTO_BYTES); // Cleanup: - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)W, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N*PARAMS_NBAR*sizeof(uint16_t)); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR*PARAMS_NBAR*sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(muprime, BYTES_MU); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(G2out, 2*CRYPTO_BYTES); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(G2out, 2 * CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(Fin_k, CRYPTO_BYTES); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(shake_input_seedSEprime, 1 + CRYPTO_BYTES); return 0; diff --git a/crypto_kem/frodokem640shake/clean/matrix_shake.c b/crypto_kem/frodokem640shake/clean/matrix_shake.c index d81eb8d5..43fe3e9b 100644 --- a/crypto_kem/frodokem640shake/clean/matrix_shake.c +++ b/crypto_kem/frodokem640shake/clean/matrix_shake.c @@ -12,61 +12,61 @@ #include "api.h" #include "params.h" -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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 PQCLEAN_FRODOKEM640SHAKE_CLEAN_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[PARAMS_N * PARAMS_N] = {0}; - + int16_t A[PARAMS_N * PARAMS_N] = {0}; + uint8_t seed_A_separated[2 + BYTES_SEED_A]; - uint16_t* seed_A_origin = (uint16_t*)&seed_A_separated; + 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++) { seed_A_origin[0] = (uint16_t) i; - shake128((unsigned char*)(A + i*PARAMS_N), (unsigned long long)(2*PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); - } - memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); - - for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e - for (k = 0; k < PARAMS_NBAR; k++) { - uint16_t sum = 0; - for (j = 0; j < PARAMS_N; j++) { - sum += A[i*PARAMS_N + j] * s[k*PARAMS_N + j]; - } - out[i*PARAMS_NBAR + k] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on. - } - } - - return 1; -} - - -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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; - int16_t A[PARAMS_N * 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 (i = 0; i < PARAMS_N; i++) { - seed_A_origin[0] = (uint16_t) i; - shake128((unsigned char*)(A + i*PARAMS_N), (unsigned long long)(2*PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e for (k = 0; k < PARAMS_NBAR; k++) { uint16_t sum = 0; - for (j = 0; j < PARAMS_N; j++) { - sum += A[j*PARAMS_N + i] * s[k*PARAMS_N + j]; + for (j = 0; j < PARAMS_N; j++) { + sum += A[i * PARAMS_N + j] * s[k * PARAMS_N + j]; } - out[k*PARAMS_N + i] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on. + out[i * PARAMS_NBAR + k] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on. } } - + + return 1; +} + + +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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; + int16_t A[PARAMS_N * 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 (i = 0; i < PARAMS_N; i++) { + seed_A_origin[0] = (uint16_t) i; + shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + } + memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); + + for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e + for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t sum = 0; + for (j = 0; j < PARAMS_N; j++) { + sum += A[j * PARAMS_N + i] * s[k * PARAMS_N + j]; + } + out[k * PARAMS_N + i] += sum; // Adding e. No need to reduce modulo 2^15, extra bits are taken care of during packing later on. + } + } + return 1; } diff --git a/crypto_kem/frodokem640shake/clean/noise.c b/crypto_kem/frodokem640shake/clean/noise.c index f2cc96b8..66919a37 100644 --- a/crypto_kem/frodokem640shake/clean/noise.c +++ b/crypto_kem/frodokem640shake/clean/noise.c @@ -11,10 +11,10 @@ static uint16_t CDF_TABLE[CDF_TABLE_LEN] = CDF_TABLE_DATA; -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, const 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. +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, const 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. unsigned int i, j; for (i = 0; i < n; ++i) { diff --git a/crypto_kem/frodokem640shake/clean/util.c b/crypto_kem/frodokem640shake/clean/util.c index 2f13887f..9ecb43e1 100644 --- a/crypto_kem/frodokem640shake/clean/util.c +++ b/crypto_kem/frodokem640shake/clean/util.c @@ -13,77 +13,78 @@ #define min(x, y) (((x) < (y)) ? (x) : (y)) -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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) +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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; + 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] += b[i * PARAMS_N + k] * s[j * PARAMS_N + k]; } - out[i*PARAMS_NBAR + j] = (uint32_t)(out[i*PARAMS_NBAR + j]) & ((1<>= PARAMS_EXTRACTED_BITS; pos++; } @@ -91,12 +92,12 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *in } -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in) -{ // Decoding +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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; + 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++) { @@ -106,15 +107,16 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in 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; + for (j = 0; j < PARAMS_EXTRACTED_BITS; j++) { + pos[i * PARAMS_EXTRACTED_BITS + j] = (templong >> (8 * j)) & 0xFF; + } } } -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char 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. +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char 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 @@ -161,9 +163,9 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen } -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char 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). +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char 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 @@ -210,10 +212,10 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, c } -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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; +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_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 e153dfdf5658eb6112fbf49cafc8e39623eca48e Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 23:40:12 -0400 Subject: [PATCH 04/12] Apply clang-tidy --- .clang-tidy | 4 ++-- crypto_kem/frodokem640shake/clean/common.h | 6 +++--- crypto_kem/frodokem640shake/clean/kem.c | 12 ++++++------ crypto_kem/frodokem640shake/clean/params.h | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index c871d305..11453622 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,5 +1,5 @@ --- -Checks: '*,-llvm-header-guard,-hicpp-*,-readability-function-size,-google-readability-todo' +Checks: '*,-llvm-header-guard,-hicpp-*,-readability-function-size,-google-readability-todo-,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers,-readability-isolate-declaration' WarningsAsErrors: '*' HeaderFilterRegex: '.*' AnalyzeTemporaryDtors: false @@ -282,7 +282,7 @@ CheckOptions: value: '1' - key: readability-inconsistent-declaration-parameter-name.Strict value: '0' - - key: readability-simplify-boolean-expr.ChainedConditionalAssignment + - key: readability-inconsistent-declaration-parameter-name.Strict value: '0' - key: readability-simplify-boolean-expr.ChainedConditionalReturn value: '0' diff --git a/crypto_kem/frodokem640shake/clean/common.h b/crypto_kem/frodokem640shake/clean/common.h index 9eeccdec..2529d71b 100644 --- a/crypto_kem/frodokem640shake/clean/common.h +++ b/crypto_kem/frodokem640shake/clean/common.h @@ -3,15 +3,15 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A); -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, const size_t n); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(uint16_t *s, size_t n); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sb_plus_e(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(uint16_t *out, const uint16_t *a, const uint16_t *b); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in); -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb); -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, size_t outlen, const uint16_t *in, size_t inlen, unsigned char lsb); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const unsigned char *in, size_t inlen, unsigned char lsb); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); #endif diff --git a/crypto_kem/frodokem640shake/clean/kem.c b/crypto_kem/frodokem640shake/clean/kem.c index cb50c3ac..c3ab8d50 100644 --- a/crypto_kem/frodokem640shake/clean/kem.c +++ b/crypto_kem/frodokem640shake/clean/kem.c @@ -11,8 +11,8 @@ #include "randombytes.h" #include "api.h" -#include "params.h" #include "common.h" +#include "params.h" int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { // FrodoKEM's key generation @@ -26,7 +26,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigne 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 = (uint16_t *)&S[PARAMS_N * PARAMS_NBAR]; // 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 @@ -76,8 +76,8 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned ch 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 = (uint16_t *)&Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data - uint16_t *Epp = (uint16_t *)&Sp[2 * PARAMS_N * PARAMS_NBAR]; // 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 @@ -140,8 +140,8 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig 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 = (uint16_t *)&Sp[PARAMS_N * PARAMS_NBAR]; // contains secret data - uint16_t *Epp = (uint16_t *)&Sp[2 * PARAMS_N * PARAMS_NBAR]; // 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]; diff --git a/crypto_kem/frodokem640shake/clean/params.h b/crypto_kem/frodokem640shake/clean/params.h index ebd981b9..81a30054 100644 --- a/crypto_kem/frodokem640shake/clean/params.h +++ b/crypto_kem/frodokem640shake/clean/params.h @@ -14,7 +14,7 @@ #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_MU ((PARAMS_EXTRACTED_BITS * PARAMS_NBAR * PARAMS_NBAR) / 8) #define BYTES_PKHASH CRYPTO_BYTES // Selecting SHAKE XOF function for the KEM and noise sampling From f0ba4f205180556080c83022c875537c2c941d58 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 23:48:52 -0400 Subject: [PATCH 05/12] Add Windows Makefile --- .../clean/Makefile.Microsoft_nmake | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake diff --git a/crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake b/crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake new file mode 100644 index 00000000..2b9d19c8 --- /dev/null +++ b/crypto_kem/frodokem640shake/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=lifrodokem640shake_clean.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) From ca798ee18a29470ea61eaabc25bd34cd9846da65 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 23:51:34 -0400 Subject: [PATCH 06/12] Fix Windows warnings --- crypto_kem/frodokem640shake/clean/util.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crypto_kem/frodokem640shake/clean/util.c b/crypto_kem/frodokem640shake/clean/util.c index 9ecb43e1..864909cb 100644 --- a/crypto_kem/frodokem640shake/clean/util.c +++ b/crypto_kem/frodokem640shake/clean/util.c @@ -140,10 +140,10 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen while (b < 8) { int nbits = min(8 - b, bits); uint16_t mask = (1 << nbits) - 1; - unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + unsigned char t = (unsigned char) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out out[i] = out[i] + (t << (8 - b - nbits)); - b += nbits; - bits -= nbits; + b += (unsigned char) nbits; + bits -= (unsigned char) nbits; w &= ~(mask << bits); // not strictly necessary; mostly for debugging if (bits == 0) { @@ -191,8 +191,8 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, c uint16_t mask = (1 << nbits) - 1; unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out out[i] = out[i] + (t << (lsb - b - nbits)); - b += nbits; - bits -= nbits; + b += (unsigned char) nbits; + bits -= (unsigned char) nbits; w &= ~(mask << bits); // not strictly necessary; mostly for debugging if (bits == 0) { From 028fb2120ebb826dfccfdde9b2e5b798886685a3 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Thu, 21 Mar 2019 23:53:53 -0400 Subject: [PATCH 07/12] Fix typo --- crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake b/crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake index 2b9d19c8..71082121 100644 --- a/crypto_kem/frodokem640shake/clean/Makefile.Microsoft_nmake +++ b/crypto_kem/frodokem640shake/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=lifrodokem640shake_clean.lib +LIBRARY=libfrodokem640shake_clean.lib OBJECTS=kem.obj matrix_shake.obj noise.obj util.obj CFLAGS=/nologo /I ..\..\..\common /W4 /WX From 9cb1c56ac18e21b14ecd699c2e187d9965f56571 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 31 Mar 2019 21:44:36 -0400 Subject: [PATCH 08/12] Make Frodo code endian-agnostic --- crypto_kem/frodokem640shake/clean/common.h | 2 ++ crypto_kem/frodokem640shake/clean/kem.c | 24 ++++++++++++++++--- .../frodokem640shake/clean/matrix_shake.c | 11 +++++++-- crypto_kem/frodokem640shake/clean/util.c | 11 +++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/crypto_kem/frodokem640shake/clean/common.h b/crypto_kem/frodokem640shake/clean/common.h index 2529d71b..c3671abc 100644 --- a/crypto_kem/frodokem640shake/clean/common.h +++ b/crypto_kem/frodokem640shake/clean/common.h @@ -13,5 +13,7 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, size_t outlen, const uint16_t *in, size_t inlen, unsigned char lsb); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const unsigned char *in, size_t inlen, unsigned char lsb); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); +uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(uint16_t n); +uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(uint16_t n); #endif diff --git a/crypto_kem/frodokem640shake/clean/kem.c b/crypto_kem/frodokem640shake/clean/kem.c index c3ab8d50..20803408 100644 --- a/crypto_kem/frodokem640shake/clean/kem.c +++ b/crypto_kem/frodokem640shake/clean/kem.c @@ -41,6 +41,9 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigne 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_CLEAN_LE_TO_UINT16(S[i]); + } PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(S, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(E, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(B, S, E, pk); @@ -51,6 +54,9 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigne // 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++) { + sk_S[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(sk_S[i]); + } memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); // Add H(pk) to the secret key @@ -97,7 +103,10 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned ch // 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); + 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_CLEAN_LE_TO_UINT16(Sp[i]); + } PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(Bp, Sp, Ep, pk_seedA); @@ -147,6 +156,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig 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]; @@ -161,10 +171,14 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig 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_CLEAN_LE_TO_UINT16(sk_S[i]); + } + // Compute W = C - Bp*S (mod q), and decode the randomness mu PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(Bp, PARAMS_N * PARAMS_NBAR, ct_c1, (PARAMS_LOGQ * PARAMS_N * PARAMS_NBAR) / 8, PARAMS_LOGQ); PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(C, PARAMS_NBAR * PARAMS_NBAR, ct_c2, (PARAMS_LOGQ * PARAMS_NBAR * PARAMS_NBAR) / 8, PARAMS_LOGQ); - PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(W, Bp, sk_S); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_bs(W, Bp, S); PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(W, C, W); PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode((uint16_t *)muprime, W); @@ -175,7 +189,10 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig // 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); + 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_CLEAN_LE_TO_UINT16(Sp[i]); + } PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Sp, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_sample_n(Ep, PARAMS_N * PARAMS_NBAR); PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(BBp, Sp, Ep, pk_seedA); @@ -210,6 +227,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig // Cleanup: PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)W, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Sp, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); + PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)S, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Ep, PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes((uint8_t *)Epp, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(muprime, BYTES_MU); diff --git a/crypto_kem/frodokem640shake/clean/matrix_shake.c b/crypto_kem/frodokem640shake/clean/matrix_shake.c index 43fe3e9b..44be64a3 100644 --- a/crypto_kem/frodokem640shake/clean/matrix_shake.c +++ b/crypto_kem/frodokem640shake/clean/matrix_shake.c @@ -10,6 +10,7 @@ #include "fips202.h" #include "api.h" +#include "common.h" #include "params.h" int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16_t *s, const uint16_t *e, const uint8_t *seed_A) { @@ -23,9 +24,12 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16 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++) { - seed_A_origin[0] = (uint16_t) i; + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(i); shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } + for (i = 0; i < PARAMS_N * PARAMS_N; i++) { + A[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(A[i]); + } memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e @@ -53,9 +57,12 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16 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++) { - seed_A_origin[0] = (uint16_t) i; + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(i); shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } + for (i = 0; i < PARAMS_N * PARAMS_N; i++) { + A[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(A[i]); + } memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); for (i = 0; i < PARAMS_N; i++) { // Matrix multiplication-addition A*s + e diff --git a/crypto_kem/frodokem640shake/clean/util.c b/crypto_kem/frodokem640shake/clean/util.c index 864909cb..26d49a62 100644 --- a/crypto_kem/frodokem640shake/clean/util.c +++ b/crypto_kem/frodokem640shake/clean/util.c @@ -12,6 +12,17 @@ #define min(x, y) (((x) < (y)) ? (x) : (y)) +uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(const uint16_t n) { + return (((uint8_t *) &(n))[0] | (((uint8_t *) &(n))[1] << 8)); +} + +uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(const 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_CLEAN_mul_bs(uint16_t *out, const uint16_t *b, const uint16_t *s) { // Multiply by s on the right From 1e5e9d96f86493817d9c1802f896a85797775b90 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 31 Mar 2019 21:52:35 -0400 Subject: [PATCH 09/12] Fix compiler warnings and bug --- crypto_kem/frodokem640shake/clean/kem.c | 2 +- crypto_kem/frodokem640shake/clean/matrix_shake.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crypto_kem/frodokem640shake/clean/kem.c b/crypto_kem/frodokem640shake/clean/kem.c index 20803408..8dd0ba2e 100644 --- a/crypto_kem/frodokem640shake/clean/kem.c +++ b/crypto_kem/frodokem640shake/clean/kem.c @@ -55,7 +55,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigne memcpy(sk_s, randomness_s, CRYPTO_BYTES); memcpy(sk_pk, pk, CRYPTO_PUBLICKEYBYTES); for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { - sk_S[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(sk_S[i]); + S[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(S[i]); } memcpy(sk_S, S, 2 * PARAMS_N * PARAMS_NBAR); diff --git a/crypto_kem/frodokem640shake/clean/matrix_shake.c b/crypto_kem/frodokem640shake/clean/matrix_shake.c index 44be64a3..e21d2bc8 100644 --- a/crypto_kem/frodokem640shake/clean/matrix_shake.c +++ b/crypto_kem/frodokem640shake/clean/matrix_shake.c @@ -17,7 +17,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16 // 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; + uint16_t i, j, k; int16_t A[PARAMS_N * PARAMS_N] = {0}; uint8_t seed_A_separated[2 + BYTES_SEED_A]; @@ -50,7 +50,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16 // 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; + uint16_t i, j, k; int16_t A[PARAMS_N * PARAMS_N] = {0}; uint8_t seed_A_separated[2 + BYTES_SEED_A]; From 41bc57689cc028490cb77531da95297c2ccb3445 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 31 Mar 2019 21:55:55 -0400 Subject: [PATCH 10/12] Fix more compiler warnings --- crypto_kem/frodokem640shake/clean/matrix_shake.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crypto_kem/frodokem640shake/clean/matrix_shake.c b/crypto_kem/frodokem640shake/clean/matrix_shake.c index e21d2bc8..78c67174 100644 --- a/crypto_kem/frodokem640shake/clean/matrix_shake.c +++ b/crypto_kem/frodokem640shake/clean/matrix_shake.c @@ -17,14 +17,14 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16 // 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) - uint16_t i, j, k; + int i, j, k; int16_t A[PARAMS_N * 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 (i = 0; i < PARAMS_N; i++) { - seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(i); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE((uint16_t) i); shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } for (i = 0; i < PARAMS_N * PARAMS_N; i++) { @@ -50,14 +50,14 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16 // 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) - uint16_t i, j, k; + int i, j, k; int16_t A[PARAMS_N * 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 (i = 0; i < PARAMS_N; i++) { - seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(i); + seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE((uint16_t) i); shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } for (i = 0; i < PARAMS_N * PARAMS_N; i++) { From 06973e6127e295369e3c0d980378600c1d168070 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 31 Mar 2019 22:00:39 -0400 Subject: [PATCH 11/12] Force make clean on test_compile_lib Helpful for local builds, even though it has no effect on fresh CI builds --- test/test_compile_lib.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_compile_lib.py b/test/test_compile_lib.py index 11a2666c..7151975e 100644 --- a/test/test_compile_lib.py +++ b/test/test_compile_lib.py @@ -14,6 +14,7 @@ def test_compile_lib(): def check_compile_lib(implementation): + helpers.make('clean', working_dir=implementation.path()) helpers.make(working_dir=implementation.path()) From 4162be0401cbfbe14bcc53e48c1a61283e9bc981 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Tue, 2 Apr 2019 14:06:06 -0400 Subject: [PATCH 12/12] Switch for int and unsigned char to size_to and uint8_t --- crypto_kem/frodokem640shake/clean/common.h | 4 +-- crypto_kem/frodokem640shake/clean/kem.c | 8 ++--- .../frodokem640shake/clean/matrix_shake.c | 4 +-- crypto_kem/frodokem640shake/clean/util.c | 30 +++++++++---------- test/crypto_kem/functest.c | 4 +-- test/crypto_sign/functest.c | 4 +-- 6 files changed, 27 insertions(+), 27 deletions(-) diff --git a/crypto_kem/frodokem640shake/clean/common.h b/crypto_kem/frodokem640shake/clean/common.h index c3671abc..aa19ea07 100644 --- a/crypto_kem/frodokem640shake/clean/common.h +++ b/crypto_kem/frodokem640shake/clean/common.h @@ -10,8 +10,8 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(uint16_t *out, const uint16_t *a, const void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(uint16_t *out, const uint16_t *a, const uint16_t *b); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_encode(uint16_t *out, const uint16_t *in); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in); -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, size_t outlen, const uint16_t *in, size_t inlen, unsigned char lsb); -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const unsigned char *in, size_t inlen, unsigned char lsb); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(uint8_t *out, size_t outlen, const uint16_t *in, size_t inlen, uint8_t lsb); +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, size_t outlen, const uint8_t *in, size_t inlen, uint8_t lsb); void PQCLEAN_FRODOKEM640SHAKE_CLEAN_clear_bytes(uint8_t *mem, size_t n); uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(uint16_t n); uint16_t PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE(uint16_t n); diff --git a/crypto_kem/frodokem640shake/clean/kem.c b/crypto_kem/frodokem640shake/clean/kem.c index 8dd0ba2e..ff2b9f46 100644 --- a/crypto_kem/frodokem640shake/clean/kem.c +++ b/crypto_kem/frodokem640shake/clean/kem.c @@ -14,7 +14,7 @@ #include "common.h" #include "params.h" -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) { +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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) @@ -71,7 +71,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigne } -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) { +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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]; @@ -140,7 +140,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned ch } -int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) { +int PQCLEAN_FRODOKEM640SHAKE_CLEAN_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}; @@ -210,7 +210,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_crypto_kem_dec(unsigned char *ss, const unsig memcpy(Fin_ct, ct, CRYPTO_CIPHERTEXTBYTES); // Reducing BBp modulo q - for (int i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { + for (size_t i = 0; i < PARAMS_N * PARAMS_NBAR; i++) { BBp[i] = BBp[i] & ((1 << PARAMS_LOGQ) - 1); } diff --git a/crypto_kem/frodokem640shake/clean/matrix_shake.c b/crypto_kem/frodokem640shake/clean/matrix_shake.c index 78c67174..5524b975 100644 --- a/crypto_kem/frodokem640shake/clean/matrix_shake.c +++ b/crypto_kem/frodokem640shake/clean/matrix_shake.c @@ -25,7 +25,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_as_plus_e(uint16_t *out, const uint16 memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); for (i = 0; i < PARAMS_N; i++) { seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE((uint16_t) i); - shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + shake128((uint8_t *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } for (i = 0; i < PARAMS_N * PARAMS_N; i++) { A[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(A[i]); @@ -58,7 +58,7 @@ int PQCLEAN_FRODOKEM640SHAKE_CLEAN_mul_add_sa_plus_e(uint16_t *out, const uint16 memcpy(&seed_A_separated[2], seed_A, BYTES_SEED_A); for (i = 0; i < PARAMS_N; i++) { seed_A_origin[0] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_UINT16_TO_LE((uint16_t) i); - shake128((unsigned char *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); + shake128((uint8_t *)(A + i * PARAMS_N), (unsigned long long)(2 * PARAMS_N), seed_A_separated, 2 + BYTES_SEED_A); } for (i = 0; i < PARAMS_N * PARAMS_N; i++) { A[i] = PQCLEAN_FRODOKEM640SHAKE_CLEAN_LE_TO_UINT16(A[i]); diff --git a/crypto_kem/frodokem640shake/clean/util.c b/crypto_kem/frodokem640shake/clean/util.c index 26d49a62..ba038d1d 100644 --- a/crypto_kem/frodokem640shake/clean/util.c +++ b/crypto_kem/frodokem640shake/clean/util.c @@ -65,7 +65,7 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_add(uint16_t *out, const uint16_t *a, const // Inputs: a, b (N_BAR x N_BAR) // Output: c = a + b - for (int i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { out[i] = (a[i] + b[i]) & ((1 << PARAMS_LOGQ) - 1); } } @@ -76,7 +76,7 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_sub(uint16_t *out, const uint16_t *a, const // Inputs: a, b (N_BAR x N_BAR) // Output: c = a - b - for (int i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { + for (size_t i = 0; i < (PARAMS_NBAR * PARAMS_NBAR); i++) { out[i] = (a[i] - b[i]) & ((1 << PARAMS_LOGQ) - 1); } } @@ -125,7 +125,7 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_key_decode(uint16_t *out, const uint16_t *in } -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb) { +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(uint8_t *out, const size_t outlen, const uint16_t *in, const size_t inlen, const 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); @@ -133,7 +133,7 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t 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 - unsigned char bits = 0; // the number of lsb in w + uint8_t bits = 0; // the number of lsb in w while (i < outlen && (j < inlen || ((j == inlen) && (bits > 0)))) { /* @@ -147,14 +147,14 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen ^^ ib */ - unsigned char b = 0; // bits in out[i] already filled in + 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; - unsigned char t = (unsigned char) ((w >> (bits - nbits)) & mask); // the bits to copy from w to out + 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 += (unsigned char) nbits; - bits -= (unsigned char) nbits; + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; w &= ~(mask << bits); // not strictly necessary; mostly for debugging if (bits == 0) { @@ -174,15 +174,15 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_pack(unsigned char *out, const size_t outlen } -void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb) { +void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, const uint8_t *in, const size_t inlen, const 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 - unsigned char w = 0; // the leftover, not yet copied - unsigned char bits = 0; // the number of lsb bits of w + 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)))) { /* @@ -196,14 +196,14 @@ void PQCLEAN_FRODOKEM640SHAKE_CLEAN_unpack(uint16_t *out, const size_t outlen, c ^ ^ i b */ - unsigned char b = 0; // bits in out[i] already filled in + 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; - unsigned char t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out + uint8_t t = (w >> (bits - nbits)) & mask; // the bits to copy from w to out out[i] = out[i] + (t << (lsb - b - nbits)); - b += (unsigned char) nbits; - bits -= (unsigned char) nbits; + b += (uint8_t) nbits; + bits -= (uint8_t) nbits; w &= ~(mask << bits); // not strictly necessary; mostly for debugging if (bits == 0) { diff --git a/test/crypto_kem/functest.c b/test/crypto_kem/functest.c index 74cef3f6..7f50608b 100644 --- a/test/crypto_kem/functest.c +++ b/test/crypto_kem/functest.c @@ -15,13 +15,13 @@ const uint8_t canary[8] = { * make sure it is not touched by the implementations. */ static void write_canary(uint8_t *d) { - for (int i = 0; i < 8; i++) { + for (size_t i = 0; i < 8; i++) { d[i] = canary[i]; } } static int check_canary(const uint8_t *d) { - for (int i = 0; i < 8; i++) { + for (size_t i = 0; i < 8; i++) { if (d[i] != canary[i]) { return -1; } diff --git a/test/crypto_sign/functest.c b/test/crypto_sign/functest.c index 57e9e0da..9fb3a1b9 100644 --- a/test/crypto_sign/functest.c +++ b/test/crypto_sign/functest.c @@ -17,13 +17,13 @@ const uint8_t canary[8] = { * make sure it is not touched by the implementations. */ static void write_canary(uint8_t *d) { - for (int i = 0; i < 8; i++) { + for (size_t i = 0; i < 8; i++) { d[i] = canary[i]; } } static int check_canary(const uint8_t *d) { - for (int i = 0; i < 8; i++) { + for (size_t i = 0; i < 8; i++) { if (d[i] != canary[i]) { return -1; }