From 9cb1c56ac18e21b14ecd699c2e187d9965f56571 Mon Sep 17 00:00:00 2001 From: Douglas Stebila Date: Sun, 31 Mar 2019 21:44:36 -0400 Subject: [PATCH] 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