diff --git a/Makefile b/Makefile index ccf08a306..e3a30c1d0 100644 --- a/Makefile +++ b/Makefile @@ -47,7 +47,7 @@ endif all: links lib tests -objs/%.o: src/%.c +objs/%.o: src/%.c | links @mkdir -p $(@D) $(CC) -c $(CFLAGS) $(INCLUDES) $< -o $@ @@ -95,7 +95,7 @@ $(KEX_RLWE_MSRLN16_OBJS): $(KEX_RLWE_MSRLN16_HEADERS) # KEX_LWE_FRODO KEX_LWE_FRODO_OBJS := $(addprefix objs/kex_lwe_frodo/, lwe.o kex_lwe_frodo.o lwe_noise.o) -KEX_LWE_FRODO_HEADERS := $(addprefix src/kex_lwe_frodo/, kex_lwe_frodo.h local.h) +KEX_LWE_FRODO_HEADERS := $(addprefix src/kex_lwe_frodo/, kex_lwe_frodo.h local.h kex_lwe_frodo_macrify.c lwe_macrify.c) $(KEX_LWE_FRODO_OBJS): $(KEX_LWE_FRODO_HEADERS) # KEX_SIDH_CLN16 diff --git a/src/kex/kex.c b/src/kex/kex.c index 658422129..6f3489509 100644 --- a/src/kex/kex.c +++ b/src/kex/kex.c @@ -18,7 +18,7 @@ OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8 case OQS_KEX_alg_rlwe_newhope: return OQS_KEX_rlwe_newhope_new(rand); case OQS_KEX_alg_lwe_frodo: - return OQS_KEX_lwe_frodo_new(rand, seed, seed_len, named_parameters); + return OQS_KEX_lwe_frodo_new_recommended(rand, seed, seed_len, named_parameters); case OQS_KEX_alg_sidh_cln16: return OQS_KEX_sidh_cln16_new(rand); default: diff --git a/src/kex_lwe_frodo/kex_lwe_frodo.c b/src/kex_lwe_frodo/kex_lwe_frodo.c index db4f401d1..c6e06614d 100644 --- a/src/kex_lwe_frodo/kex_lwe_frodo.c +++ b/src/kex_lwe_frodo/kex_lwe_frodo.c @@ -13,6 +13,7 @@ #include #include +#include #include "kex_lwe_frodo.h" #include "local.h" @@ -21,115 +22,16 @@ #include -OQS_KEX *OQS_KEX_lwe_frodo_new(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters) { - - OQS_KEX *k; - struct oqs_kex_lwe_frodo_params *params; - - if ((seed_len == 0) || (seed == NULL)) { - return NULL; - } - - k = malloc(sizeof(OQS_KEX)); - if (k == NULL) { - goto err; - } - k->named_parameters = NULL; - k->method_name = NULL; - - k->params = malloc(sizeof(struct oqs_kex_lwe_frodo_params)); - if (NULL == k->params) { - goto err; - } - params = (struct oqs_kex_lwe_frodo_params *) k->params; - params->cdf_table = NULL; - params->seed = NULL; - params->param_name = NULL; - - k->rand = rand; - k->ctx = NULL; - k->alice_priv_free = &OQS_KEX_lwe_frodo_alice_priv_free; - k->free = &OQS_KEX_lwe_frodo_free; - - if (strcmp(named_parameters, "recommended") == 0) { - - k->alice_0 = &OQS_KEX_lwe_frodo_alice_0_recommended; - k->bob = &OQS_KEX_lwe_frodo_bob_recommended; - k->alice_1 = &OQS_KEX_lwe_frodo_alice_1_recommended; - - k->method_name = strdup("LWE Frodo recommended"); - if (NULL == k->method_name) { - goto err; - } - k->estimated_classical_security = 144; - k->estimated_quantum_security = 130; - k->named_parameters = strdup(named_parameters); - if (k->named_parameters == NULL) { - goto err; - } - - params->seed = malloc(seed_len); - if (NULL == params->seed) { - goto err; - } - memcpy(params->seed, seed, seed_len); - params->seed_len = seed_len; - params->param_name = strdup("recommended"); - if (NULL == params->param_name) { - goto err; - } - params->log2_q = 15; - params->q = 1 << params->log2_q; - params->n = 752; - params->extracted_bits = 4; - params->nbar = 8; - params->key_bits = 256; - params->rec_hint_len = LWE_DIV_ROUNDUP(params->nbar * params->nbar, 8); - params->pub_len = LWE_DIV_ROUNDUP(params->n * params->nbar * params->log2_q, 8); - params->stripe_step = 8; - params->sampler_num = 12; - params->cdf_table_len = 6; - params->cdf_table = malloc(params->cdf_table_len * sizeof(uint16_t)); - if (NULL == params->cdf_table) { - goto err; - } - uint16_t cdf_table_tmp[6] = {602, 1521, 1927, 2031, 2046, 2047}; - memcpy(params->cdf_table, cdf_table_tmp, sizeof(cdf_table_tmp)); - - } else { - - goto err; - - } - - return k; - -err: - if (k) { - if (k->params) { - free(params->cdf_table); - free(params->seed); - free(params->param_name); - free(k->params); - } - free(k->named_parameters); - free(k->method_name); - free(k); - } - return NULL; - -} - // pre-process code to obtain "recommended" functions +#include "recommended.h" #define MACRIFY(NAME) NAME ## _recommended #include "kex_lwe_frodo_macrify.c" // undefine macros to avoid any confusion later +#include "recommended.h" #undef MACRIFY void OQS_KEX_lwe_frodo_alice_priv_free(UNUSED OQS_KEX *k, void *alice_priv) { - if (alice_priv) { - free(alice_priv); - } + free(alice_priv); } void OQS_KEX_lwe_frodo_free(OQS_KEX *k) { diff --git a/src/kex_lwe_frodo/kex_lwe_frodo.h b/src/kex_lwe_frodo/kex_lwe_frodo.h index 3bfe77860..cb2742d0e 100644 --- a/src/kex_lwe_frodo/kex_lwe_frodo.h +++ b/src/kex_lwe_frodo/kex_lwe_frodo.h @@ -12,7 +12,7 @@ #include #include -OQS_KEX *OQS_KEX_lwe_frodo_new(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters); +OQS_KEX *OQS_KEX_lwe_frodo_new_recommended(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters); int OQS_KEX_lwe_frodo_alice_0_recommended(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len); int OQS_KEX_lwe_frodo_bob_recommended(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len); diff --git a/src/kex_lwe_frodo/kex_lwe_frodo_macrify.c b/src/kex_lwe_frodo/kex_lwe_frodo_macrify.c index 09092e391..5c79bca4c 100644 --- a/src/kex_lwe_frodo/kex_lwe_frodo_macrify.c +++ b/src/kex_lwe_frodo/kex_lwe_frodo_macrify.c @@ -1,65 +1,133 @@ +OQS_KEX *MACRIFY(OQS_KEX_lwe_frodo_new)(OQS_RAND *rand, const uint8_t *seed, const size_t seed_len, const char *named_parameters) { + + OQS_KEX *k; + struct oqs_kex_lwe_frodo_params *params; + + if ((seed_len == 0) || (seed == NULL)) { + return NULL; + } + + k = malloc(sizeof(OQS_KEX)); + if (k == NULL) { + goto err; + } + k->named_parameters = NULL; + k->method_name = NULL; + + k->params = malloc(sizeof(struct oqs_kex_lwe_frodo_params)); + if (NULL == k->params) { + goto err; + } + params = (struct oqs_kex_lwe_frodo_params *) k->params; + params->cdf_table = NULL; + params->seed = NULL; + params->param_name = NULL; + + k->rand = rand; + k->ctx = NULL; + k->alice_priv_free = &OQS_KEX_lwe_frodo_alice_priv_free; + k->free = &OQS_KEX_lwe_frodo_free; + + if (strcmp(named_parameters, "recommended") == 0) { + + k->alice_0 = &OQS_KEX_lwe_frodo_alice_0_recommended; + k->bob = &OQS_KEX_lwe_frodo_bob_recommended; + k->alice_1 = &OQS_KEX_lwe_frodo_alice_1_recommended; + + k->method_name = strdup("LWE Frodo recommended"); + if (NULL == k->method_name) { + goto err; + } + k->estimated_classical_security = 144; + k->estimated_quantum_security = 130; + k->named_parameters = strdup(named_parameters); + if (k->named_parameters == NULL) { + goto err; + } + + params->seed = malloc(seed_len); + if (NULL == params->seed) { + goto err; + } + memcpy(params->seed, seed, seed_len); + params->seed_len = seed_len; + params->param_name = strdup("recommended"); + if (NULL == params->param_name) { + goto err; + } + params->log2_q = PARAMS_LOG2Q; + params->q = PARAMS_Q; + params->n = PARAMS_N; + params->extracted_bits = PARAMS_EXTRACTED_BITS; + params->nbar = PARAMS_NBAR; + params->key_bits = PARAMS_KEY_BITS; + params->rec_hint_len = PARAMS_REC_HINT_LENGTH; + params->pub_len = PARAMS_REC_PUB_LENGTH; + params->stripe_step = PARAMS_STRIPE_STEP; + params->sampler_num = 12; + params->cdf_table_len = 6; + params->cdf_table = malloc(params->cdf_table_len * sizeof(uint16_t)); + if (NULL == params->cdf_table) { + goto err; + } + uint16_t cdf_table_tmp[6] = {602, 1521, 1927, 2031, 2046, 2047}; + memcpy(params->cdf_table, cdf_table_tmp, sizeof(cdf_table_tmp)); + } else { + goto err; + } + return k; +err: + OQS_KEX_lwe_frodo_free(k); + return NULL; +} + + int MACRIFY(OQS_KEX_lwe_frodo_alice_0)(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len) { int ret; struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params *) k->params; - uint16_t *b = NULL, *e = NULL; *alice_priv = NULL; *alice_msg = NULL; /* allocate private key, error, and outgoing message */ - *alice_priv = malloc(params->n * params->nbar * sizeof(uint16_t)); + *alice_priv = malloc(PARAMS_N * PARAMS_NBAR * sizeof(uint16_t)); if (*alice_priv == NULL) { goto err; } - b = (uint16_t *) malloc(params->n * params->nbar * sizeof(uint16_t)); - if (b == NULL) { - goto err; - } - e = (uint16_t *) malloc(params->n * params->nbar * sizeof(uint16_t)); - if (e == NULL) { - goto err; - } - *alice_msg = malloc(params->pub_len); + uint16_t b[PARAMS_N * PARAMS_NBAR]; + uint16_t e[PARAMS_N * PARAMS_NBAR]; + + *alice_msg = malloc(PARAMS_REC_PUB_LENGTH); + *alice_msg_len = PARAMS_REC_PUB_LENGTH; if (*alice_msg == NULL) { goto err; } /* generate S and E */ - ret = oqs_kex_lwe_frodo_sample_n(*alice_priv, params->n * params->nbar, params, k->rand); - if (ret != 1) { - goto err; - } - ret = oqs_kex_lwe_frodo_sample_n(e, params->n * params->nbar, params, k->rand); - if (ret != 1) { - goto err; - } + oqs_kex_lwe_frodo_sample_n(*alice_priv, PARAMS_N * PARAMS_NBAR, params, k->rand); + oqs_kex_lwe_frodo_sample_n(e, PARAMS_N * PARAMS_NBAR, params, k->rand); /* compute B = AS + E */ - ret = MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(b, *alice_priv, e, params); - if (ret != 1) { - goto err; - } - oqs_kex_lwe_frodo_pack(*alice_msg, params->pub_len, b, params->n * params->nbar, params->log2_q); + MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(b, *alice_priv, e, params); + + oqs_kex_lwe_frodo_pack(*alice_msg, PARAMS_REC_PUB_LENGTH, b, PARAMS_N * PARAMS_NBAR, PARAMS_LOG2Q); - *alice_msg_len = params->pub_len; ret = 1; goto cleanup; err: - ret = 0; + OQS_MEM_cleanse(e, sizeof(e)); free(*alice_msg); *alice_msg = NULL; free(*alice_priv); *alice_priv = NULL; + ret = 0; cleanup: - free(e); - free(b); return ret; - } int MACRIFY(OQS_KEX_lwe_frodo_bob)(OQS_KEX *k, const uint8_t *alice_msg, const size_t alice_msg_len, uint8_t **bob_msg, size_t *bob_msg_len, uint8_t **key, size_t *key_len) { @@ -68,78 +136,46 @@ int MACRIFY(OQS_KEX_lwe_frodo_bob)(OQS_KEX *k, const uint8_t *alice_msg, const s struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params *) k->params; - uint16_t *bob_priv = NULL; uint8_t *bob_rec = NULL; - uint16_t *b = NULL, *bprime = NULL, *eprime = NULL, *eprimeprime = NULL; - uint16_t *v = NULL; *bob_msg = NULL; *key = NULL; /* check length of other party's public key */ - if (alice_msg_len != params->pub_len) { + if (alice_msg_len != PARAMS_REC_PUB_LENGTH) { goto err; } /* allocate private key, errors, outgoing message, and key */ - bob_priv = malloc(params->n * params->nbar * sizeof(uint16_t)); - if (bob_priv == NULL) { - goto err; - } - bprime = (uint16_t *) malloc(params->n * params->nbar * sizeof(uint16_t)); - if (bprime == NULL) { - goto err; - } - eprime = (uint16_t *) malloc(params->n * params->nbar * sizeof(uint16_t)); - if (eprime == NULL) { - goto err; - } - eprimeprime = (uint16_t *) malloc(params->nbar * params->nbar * sizeof(uint16_t)); - if (eprimeprime == NULL) { - goto err; - } - b = (uint16_t *) malloc(params->n * params->nbar * sizeof(uint16_t)); - if (b == NULL) { - goto err; - } - v = (uint16_t *) malloc(params->nbar * params->nbar * sizeof(uint16_t)); - if (v == NULL) { - goto err; - } - *bob_msg = malloc(params->pub_len + params->rec_hint_len); + uint16_t bob_priv[PARAMS_N * PARAMS_NBAR]; + uint16_t bprime[PARAMS_N * PARAMS_NBAR]; + uint16_t eprime[PARAMS_N * PARAMS_NBAR]; + uint16_t eprimeprime[PARAMS_N * PARAMS_NBAR]; + uint16_t b[PARAMS_N * PARAMS_NBAR]; + uint16_t v[PARAMS_N * PARAMS_NBAR]; + *bob_msg = malloc(PARAMS_REC_PUB_LENGTH + PARAMS_REC_HINT_LENGTH); if (*bob_msg == NULL) { goto err; } - bob_rec = *bob_msg + params->pub_len; - *key = malloc(params->key_bits >> 3); + bob_rec = *bob_msg + PARAMS_REC_PUB_LENGTH; + *key = malloc(PARAMS_KEY_BYTES); if (*key == NULL) { goto err; } /* generate S' and E' */ - ret = oqs_kex_lwe_frodo_sample_n(bob_priv, params->n * params->nbar, params, k->rand); - if (ret != 1) { - goto err; - } - ret = oqs_kex_lwe_frodo_sample_n(eprime, params->n * params->nbar, params, k->rand); - if (ret != 1) { - goto err; - } + oqs_kex_lwe_frodo_sample_n(bob_priv, PARAMS_N * PARAMS_NBAR, params, k->rand); + oqs_kex_lwe_frodo_sample_n(eprime, PARAMS_N * PARAMS_NBAR, params, k->rand); /* compute B' = S'A + E' */ - ret = MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(bprime, bob_priv, eprime, params); - if (ret != 1) { - goto err; - } - oqs_kex_lwe_frodo_pack(*bob_msg, params->pub_len, bprime, params->n * params->nbar, params->log2_q); + MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(bprime, bob_priv, eprime, params); + + oqs_kex_lwe_frodo_pack(*bob_msg, PARAMS_REC_PUB_LENGTH, bprime, PARAMS_N * PARAMS_NBAR, PARAMS_LOG2Q); /* generate E'' */ - ret = oqs_kex_lwe_frodo_sample_n(eprimeprime, params->nbar * params->nbar, params, k->rand); - if (ret != 1) { - goto err; - } + oqs_kex_lwe_frodo_sample_n(eprimeprime, PARAMS_NBAR * PARAMS_NBAR, params, k->rand); /* unpack B */ - oqs_kex_lwe_frodo_unpack(b, params->n * params->nbar, alice_msg, alice_msg_len, params->log2_q); + oqs_kex_lwe_frodo_unpack(b, PARAMS_N * PARAMS_NBAR, alice_msg, alice_msg_len, PARAMS_LOG2Q); /* compute V = S'B + E'' */ MACRIFY(oqs_kex_lwe_frodo_mul_add_sb_plus_e)(v, b, bob_priv, eprimeprime); @@ -150,8 +186,8 @@ int MACRIFY(OQS_KEX_lwe_frodo_bob)(OQS_KEX *k, const uint8_t *alice_msg, const s /* compute K = round(V)_{2^B} */ MACRIFY(oqs_kex_lwe_frodo_round2)(*key, v); - *bob_msg_len = params->pub_len + params->rec_hint_len; - *key_len = params->key_bits >> 3; + *bob_msg_len = PARAMS_REC_PUB_LENGTH + PARAMS_REC_HINT_LENGTH; + *key_len = PARAMS_KEY_BYTES; ret = 1; goto cleanup; @@ -160,85 +196,58 @@ err: ret = 0; free(*bob_msg); *bob_msg = NULL; - if (*key != NULL) { - memset(*key, 0, params->key_bits >> 3); - } - free(*key); + OQS_MEM_secure_free(*key, PARAMS_KEY_BYTES); *key = NULL; cleanup: - free(bob_priv); - if (eprime != NULL) { - memset(eprime, 0, params->n * params->nbar * sizeof(uint16_t)); - } - free(bprime); - free(eprime); - if (eprimeprime != NULL) { - memset(eprimeprime, 0, params->nbar * params->nbar * sizeof(uint16_t)); - } - free(eprimeprime); - free(b); - if (v != NULL) { - memset(v, 0, params->nbar * params->nbar * sizeof(uint16_t)); - } - free(v); + OQS_MEM_cleanse(eprime, sizeof(eprime)); + OQS_MEM_cleanse(eprimeprime, sizeof(eprimeprime)); + OQS_MEM_cleanse(v, sizeof(v)); return ret; } -int MACRIFY(OQS_KEX_lwe_frodo_alice_1)(OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len) { +int MACRIFY(OQS_KEX_lwe_frodo_alice_1)(UNUSED OQS_KEX *k, const void *alice_priv, const uint8_t *bob_msg, const size_t bob_msg_len, uint8_t **key, size_t *key_len) { int ret; - - struct oqs_kex_lwe_frodo_params *params = (struct oqs_kex_lwe_frodo_params *) k->params; - - uint16_t *bprime = NULL, *w = NULL; *key = NULL; /* check length of other party's public key */ - if (bob_msg_len != params->pub_len + params->rec_hint_len) { + if (bob_msg_len != PARAMS_REC_PUB_LENGTH + PARAMS_REC_HINT_LENGTH) { goto err; } /* allocate working values and session key */ - bprime = malloc(params->n * params->nbar * sizeof(uint16_t)); - if (bprime == NULL) { - goto err; - } - w = malloc(params->nbar * params->nbar * sizeof(uint16_t)); - if (w == NULL) { - goto err; - } - *key = malloc(params->key_bits >> 3); + uint16_t bprime[PARAMS_N * PARAMS_NBAR]; + uint16_t w[PARAMS_N * PARAMS_NBAR]; + + *key = malloc(PARAMS_KEY_BYTES); if (*key == NULL) { goto err; } /* unpack B' */ - oqs_kex_lwe_frodo_unpack(bprime, params->n * params->nbar, bob_msg, params->pub_len, params->log2_q); + oqs_kex_lwe_frodo_unpack(bprime, PARAMS_N * PARAMS_NBAR, bob_msg, PARAMS_REC_PUB_LENGTH, PARAMS_LOG2Q); /* compute W = B'S */ MACRIFY(oqs_kex_lwe_frodo_mul_bs)(w, bprime, (uint16_t *) alice_priv); /* compute K = rec(B'S, C) */ - const uint8_t *bob_rec = bob_msg + params->pub_len; + const uint8_t *bob_rec = bob_msg + PARAMS_REC_PUB_LENGTH; MACRIFY(oqs_kex_lwe_frodo_reconcile)(*key, w, bob_rec); - *key_len = params->key_bits >> 3; + *key_len = PARAMS_KEY_BYTES; ret = 1; goto cleanup; err: ret = 0; - memset(key, 0, params->key_bits >> 3); - free(*key); + OQS_MEM_secure_free(*key, PARAMS_KEY_BYTES); *key = NULL; cleanup: - free(w); - free(bprime); return ret; } diff --git a/src/kex_lwe_frodo/local.h b/src/kex_lwe_frodo/local.h index 8db4c611c..1d8afa47f 100644 --- a/src/kex_lwe_frodo/local.h +++ b/src/kex_lwe_frodo/local.h @@ -32,10 +32,10 @@ void oqs_kex_lwe_frodo_key_round_hints(uint16_t *vec, const size_t length, const void oqs_kex_lwe_frodo_pack(unsigned char *out, const size_t outlen, const uint16_t *in, const size_t inlen, const unsigned char lsb); void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned char *in, const size_t inlen, const unsigned char lsb); -int oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand); +void oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand); -int oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params); -int oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params); +void oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params); +void oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly_recommended(uint16_t *b, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params); void oqs_kex_lwe_frodo_mul_add_sb_plus_e_recommended(uint16_t *out, const uint16_t *b, const uint16_t *s, const uint16_t *e); void oqs_kex_lwe_frodo_mul_bs_recommended(uint16_t *out, const uint16_t *b, const uint16_t *s); diff --git a/src/kex_lwe_frodo/lwe.c b/src/kex_lwe_frodo/lwe.c index 995833f9c..f074d8bf2 100644 --- a/src/kex_lwe_frodo/lwe.c +++ b/src/kex_lwe_frodo/lwe.c @@ -71,7 +71,7 @@ void oqs_kex_lwe_frodo_pack(unsigned char *out, const size_t outlen, const uint1 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)); + out[i] += t << (8 - b - nbits); b += nbits; bits -= nbits; w &= ~(mask << bits); // not strictly necessary; mostly for debugging @@ -119,7 +119,7 @@ void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned 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)); + out[i] += t << (lsb - b - nbits); b += nbits; bits -= nbits; w &= ~(mask << bits); // not strictly necessary; mostly for debugging @@ -140,27 +140,11 @@ void oqs_kex_lwe_frodo_unpack(uint16_t *out, const size_t outlen, const unsigned } } -#define LWE_DIV_ROUNDUP(x, y) (((x) + (y)-1) / y) - // define parameters for "recommended" parameter set -#define PARAMS_N 752 -#define PARAMS_NBAR 8 -#define PARAMS_LOG2Q 15 -#define PARAMS_Q (1 << PARAMS_LOG2Q) -#define PARAMS_EXTRACTED_BITS 4 -#define PARAMS_KEY_BITS 256 -#define PARAMS_STRIPE_STEP 8 -#define PARAMS_REC_HINT_LENGTH LWE_DIV_ROUNDUP(PARAMS_NBAR * PARAMS_NBAR, 8) +#include "recommended.h" // pre-process code to obtain "recommended" functions #define MACRIFY(NAME) NAME ## _recommended #include "lwe_macrify.c" // undefine macros to avoid any confusion later -#undef PARAMS_N -#undef PARAMS_NBAR -#undef PARAMS_LOG2Q -#undef PARAMS_Q -#undef PARAMS_EXTRACTED_BITS -#undef PARAMS_KEY_BITS -#undef PARAMS_STRIPE_STEP -#undef PARAMS_REC_HINT_LENGTH +#include "recommended.h" #undef MACRIFY diff --git a/src/kex_lwe_frodo/lwe_macrify.c b/src/kex_lwe_frodo/lwe_macrify.c index 207262ff9..eaf9417ff 100644 --- a/src/kex_lwe_frodo/lwe_macrify.c +++ b/src/kex_lwe_frodo/lwe_macrify.c @@ -1,8 +1,7 @@ // [.]_2 void MACRIFY(oqs_kex_lwe_frodo_round2)(unsigned char *out, uint16_t *in) { oqs_kex_lwe_frodo_key_round(in, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS); - int i; - for (i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) { + for (int i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) { in[i] >>= PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS; // drop bits that were zeroed out } @@ -11,7 +10,6 @@ void MACRIFY(oqs_kex_lwe_frodo_round2)(unsigned char *out, uint16_t *in) { } void MACRIFY(oqs_kex_lwe_frodo_crossround2)(unsigned char *out, const uint16_t *in) { - int i; // out should have enough space for N_BAR * N_BAR bits memset((unsigned char *)out, 0, PARAMS_REC_HINT_LENGTH); @@ -19,7 +17,7 @@ void MACRIFY(oqs_kex_lwe_frodo_crossround2)(unsigned char *out, const uint16_t * uint16_t half = whole >> 1; uint16_t mask = whole - 1; - for (i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) { + for (int i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) { uint16_t remainder = in[i] & mask; out[i / 8] += (remainder >= half) << (i % 8); } @@ -27,44 +25,24 @@ void MACRIFY(oqs_kex_lwe_frodo_crossround2)(unsigned char *out, const uint16_t * void MACRIFY(oqs_kex_lwe_frodo_reconcile)(unsigned char *out, uint16_t *w, const unsigned char *hint) { oqs_kex_lwe_frodo_key_round_hints(w, PARAMS_NBAR * PARAMS_NBAR, PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS, hint); - int i; - for (i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) { + for (int i = 0; i < PARAMS_NBAR * PARAMS_NBAR; i++) { w[i] >>= PARAMS_LOG2Q - PARAMS_EXTRACTED_BITS; // drop bits that were zeroed out } oqs_kex_lwe_frodo_pack(out, PARAMS_KEY_BITS / 8, w, PARAMS_NBAR * PARAMS_NBAR, PARAMS_EXTRACTED_BITS); } // Generate-and-multiply: generate A row-wise, multiply by s on the right. -int MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params) { +void MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params) { // A (N x N) // s,e (N x N_BAR) // out = A * s + e (N x N_BAR) - int i, j, k; - int ret = 0; - uint16_t *a_row = NULL; - uint16_t *s_transpose = NULL; - - for (i = 0; i < PARAMS_N; i++) { - for (j = 0; j < PARAMS_NBAR; j++) { - out[i * PARAMS_NBAR + j] = e[i * PARAMS_NBAR + j]; - } - } - - size_t a_rowlen = PARAMS_N * sizeof(int16_t); - a_row = (uint16_t *) malloc(a_rowlen); - if (a_row == NULL) { - goto err; - } + memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); // transpose s to store it in the column-major order - s_transpose = (uint16_t *) malloc(PARAMS_NBAR * PARAMS_N * sizeof(int16_t)); - if (s_transpose == NULL) { - goto err; - } - - for (j = 0; j < PARAMS_N; j++) { - for (k = 0; k < PARAMS_NBAR; k++) { + uint16_t s_transpose[PARAMS_NBAR * PARAMS_N]; + for (int j = 0; j < PARAMS_N; j++) { + for (int k = 0; k < PARAMS_NBAR; k++) { s_transpose[k * PARAMS_N + j] = s[j * PARAMS_NBAR + k]; } } @@ -73,127 +51,78 @@ int MACRIFY(oqs_kex_lwe_frodo_mul_add_as_plus_e_on_the_fly)(uint16_t *out, const void *aes_key_schedule = NULL; OQS_AES128_load_schedule(params->seed, &aes_key_schedule, 1); - for (i = 0; i < PARAMS_N; i++) { + for (int i = 0; i < PARAMS_N; i++) { + uint16_t a_row[PARAMS_N] = {0}; // go through A's rows - memset(a_row, 0, a_rowlen); - for (j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { + for (int j = 0; j < PARAMS_N; j += PARAMS_STRIPE_STEP) { // Loading values in the little-endian order! a_row[j] = i; a_row[j + 1] = j; } - OQS_AES128_ECB_enc_sch((uint8_t *) a_row, a_rowlen, aes_key_schedule, (uint8_t *) a_row); + OQS_AES128_ECB_enc_sch((uint8_t *) a_row, sizeof(a_row), aes_key_schedule, (uint8_t *) a_row); - for (k = 0; k < PARAMS_NBAR; k++) { + for (int k = 0; k < PARAMS_NBAR; k++) { uint16_t sum = 0; - for (j = 0; j < PARAMS_N; j++) { + for (int j = 0; j < PARAMS_N; j++) { // matrix-vector multiplication happens here sum += a_row[j] * s_transpose[k * PARAMS_N + j]; } out[i * PARAMS_NBAR + k] += sum; - out[i * PARAMS_NBAR + k] %= PARAMS_Q; + //Equivalent to %= PARAMS_Q if PARAMS_Q is a power of 2 + out[i * PARAMS_NBAR + k] &= PARAMS_Q - 1; } } OQS_AES128_free_schedule(aes_key_schedule); - - ret = 1; - goto cleanup; - -err: - memset(out, 0, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); - -cleanup: - if (a_row != NULL) { - memset(a_row, 0, a_rowlen); - free(a_row); - } - - if (s_transpose != NULL) { - memset(s_transpose, 0, PARAMS_NBAR * PARAMS_N * sizeof(int16_t)); - free(s_transpose); - } - - return ret; } + // Generate-and-multiply: generate A column-wise, multiply by s' on the left. -int MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params) { +void MACRIFY(oqs_kex_lwe_frodo_mul_add_sa_plus_e_on_the_fly)(uint16_t *out, const uint16_t *s, const uint16_t *e, struct oqs_kex_lwe_frodo_params *params) { // a (N x N) // s',e' (N_BAR x N) // out = s'a + e' (N_BAR x N) - int i, j, k, kk; - int ret = 0; - uint16_t *a_cols = NULL; - uint16_t *a_cols_t = NULL; - - for (i = 0; i < PARAMS_NBAR; i++) { - for (j = 0; j < PARAMS_N; j++) { - out[i * PARAMS_N + j] = e[i * PARAMS_N + j]; - } - } - - size_t a_colslen = PARAMS_N * PARAMS_STRIPE_STEP * sizeof(int16_t); - // a_cols stores 8 columns of A at a time. - a_cols = (uint16_t *) malloc(a_colslen); - a_cols_t = (uint16_t *) malloc(a_colslen); // a_cols transposed (stored in the column-major order). - if ((a_cols == NULL) || (a_cols_t == NULL)) { - goto err; - } + memcpy(out, e, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); assert(params->seed_len == 16); + void *aes_key_schedule = NULL; OQS_AES128_load_schedule(params->seed, &aes_key_schedule, 1); - for (kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { + for (int kk = 0; kk < PARAMS_N; kk += PARAMS_STRIPE_STEP) { // Go through A's columns, 8 (== PARAMS_STRIPE_STEP) columns at a time. - memset(a_cols, 0, a_colslen); - for (i = 0; i < PARAMS_N; i++) { + // a_cols stores 8 columns of A at a time. + uint16_t a_cols[PARAMS_N * PARAMS_STRIPE_STEP] = {0}; + for (int i = 0; i < PARAMS_N; i++) { // Loading values in the little-endian order! a_cols[i * PARAMS_STRIPE_STEP] = i; a_cols[i * PARAMS_STRIPE_STEP + 1] = kk; } - OQS_AES128_ECB_enc_sch((uint8_t *) a_cols, a_colslen, aes_key_schedule, (uint8_t *) a_cols); + OQS_AES128_ECB_enc_sch((uint8_t *) a_cols, sizeof(a_cols), aes_key_schedule, (uint8_t *) a_cols); // transpose a_cols to have access to it in the column-major order. - for (i = 0; i < PARAMS_N; i++) - for (k = 0; k < PARAMS_STRIPE_STEP; k++) { + uint16_t a_cols_t[PARAMS_N * PARAMS_STRIPE_STEP]; + for (int i = 0; i < PARAMS_N; i++) { + for (int k = 0; k < PARAMS_STRIPE_STEP; k++) { a_cols_t[k * PARAMS_N + i] = a_cols[i * PARAMS_STRIPE_STEP + k]; } + } - for (i = 0; i < PARAMS_NBAR; i++) - for (k = 0; k < PARAMS_STRIPE_STEP; k++) { + for (int i = 0; i < PARAMS_NBAR; i++) { + for (int k = 0; k < PARAMS_STRIPE_STEP; k++) { uint16_t sum = 0; - for (j = 0; j < PARAMS_N; j++) { + for (int j = 0; j < PARAMS_N; j++) { sum += s[i * PARAMS_N + j] * a_cols_t[k * PARAMS_N + j]; } out[i * PARAMS_N + kk + k] += sum; - out[i * PARAMS_N + kk + k] %= PARAMS_Q; + out[i * PARAMS_N + kk + k] &= PARAMS_Q - 1; //Works as long as PARAMS_Q is a power of 2 } + } } - OQS_AES128_free_schedule(aes_key_schedule); - - ret = 1; - goto cleanup; - -err: - memset(out, 0, PARAMS_NBAR * PARAMS_N * sizeof(uint16_t)); - -cleanup: - if (a_cols != NULL) { - memset(a_cols, 0, a_colslen); - free(a_cols); - } - - if (a_cols_t != NULL) { - memset(a_cols_t, 0, a_colslen); - free(a_cols_t); - } - - return ret; } // multiply by s on the right @@ -201,14 +130,13 @@ void MACRIFY(oqs_kex_lwe_frodo_mul_bs)(uint16_t *out, const uint16_t *b, const u // b (N_BAR x N) // s (N x N_BAR) // out = bs - 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[k * PARAMS_NBAR + j]; + for (int i = 0; i < PARAMS_NBAR; i++) { + for (int j = 0; j < PARAMS_NBAR; j++) { + uint16_t sum = 0; + for (int k = 0; k < PARAMS_N; k++) { + sum += b[i * PARAMS_N + k] * s[k * PARAMS_NBAR + j]; } - out[i * PARAMS_NBAR + j] %= PARAMS_Q; // not really necessary since LWE_Q is a power of 2. + out[i * PARAMS_NBAR + j] = sum & (PARAMS_Q - 1); } } } @@ -219,15 +147,15 @@ void MACRIFY(oqs_kex_lwe_frodo_mul_add_sb_plus_e)(uint16_t *out, const uint16_t // s (N_BAR x N) // e (N_BAR x N_BAR) // out = sb + e - int i, j, k; - for (k = 0; k < PARAMS_NBAR; k++) { - for (i = 0; i < PARAMS_NBAR; i++) { - out[k * PARAMS_NBAR + i] = e[k * PARAMS_NBAR + i]; - for (j = 0; j < PARAMS_N; j++) { - out[k * PARAMS_NBAR + i] += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; + memcpy(out, e, PARAMS_NBAR * PARAMS_NBAR * sizeof(uint16_t)); + for (int k = 0; k < PARAMS_NBAR; k++) { + for (int i = 0; i < PARAMS_NBAR; i++) { + uint16_t sum = 0; + for (int j = 0; j < PARAMS_N; j++) { + sum += s[k * PARAMS_N + j] * b[j * PARAMS_NBAR + i]; } - out[k * PARAMS_NBAR + i] %= PARAMS_Q; // not really necessary since LWE_Q is a power of 2. + out[k * PARAMS_NBAR + i] += sum; + out[k * PARAMS_NBAR + i] &= PARAMS_Q - 1; // not really necessary since LWE_Q is a power of 2. } } } - diff --git a/src/kex_lwe_frodo/lwe_noise.c b/src/kex_lwe_frodo/lwe_noise.c index fa7300326..97f4c2508 100644 --- a/src/kex_lwe_frodo/lwe_noise.c +++ b/src/kex_lwe_frodo/lwe_noise.c @@ -5,33 +5,26 @@ #include #include +#include #include "local.h" -static int lwe_sample_n_inverse_8(uint16_t *s, const size_t n, const uint8_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) { - +static void lwe_sample_n_inverse_8(uint16_t *s, const size_t n, const uint8_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) { /* Fills vector s with n samples from the noise distribution which requires * 8 bits to sample. The distribution is specified by its CDF. Super-constant * timing: the CDF table is ingested for every sample. */ - size_t rndlen = n; - uint8_t *rndvec = (uint8_t *)malloc(rndlen); - if (rndvec == NULL) { - fprintf(stderr, "malloc failure\n"); - return 0; - } - OQS_RAND_n(rand, rndvec, rndlen); + uint8_t rndvec[n]; + OQS_RAND_n(rand, rndvec, sizeof(rndvec)); - size_t i, j; - - for (i = 0; i < n; ++i) { + for (size_t i = 0; i < n; ++i) { uint8_t sample = 0; uint8_t rnd = rndvec[i] >> 1; // drop the least significant bit uint8_t sign = rndvec[i] & 0x1; // pick the least significant bit // No need to compare with the last value. - for (j = 0; j < cdf_table_len - 1; j++) { + for (size_t j = 0; j < cdf_table_len - 1; j++) { // Constant time comparison: 1 if cdf_table[j] < rnd, 0 otherwise. // Critically uses the fact that cdf_table[j] and rnd fit in 7 bits. sample += (uint8_t)(cdf_table[j] - rnd) >> 7; @@ -39,30 +32,19 @@ static int lwe_sample_n_inverse_8(uint16_t *s, const size_t n, const uint8_t *cd // Assuming that sign is either 0 or 1, flips sample iff sign = 1 s[i] = ((-sign) ^ sample) + sign; } - - memset(rndvec, 0, rndlen); - free(rndvec); - return 1; + OQS_MEM_cleanse(rndvec, sizeof(rndvec)); } -static int lwe_sample_n_inverse_12(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) { +static void lwe_sample_n_inverse_12(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) { /* Fills vector s with n samples from the noise distribution which requires * 12 bits to sample. The distribution is specified by its CDF. Super-constant * timing: the CDF table is ingested for every sample. */ - size_t rndlen = 3 * ((n + 1) / 2); // 12 bits of unif randomness per output element + uint8_t rnd[3 * ((n + 1) / 2)]; // 12 bits of unif randomness per output element + OQS_RAND_n(rand, rnd, sizeof(rnd)); - uint8_t *rnd = (uint8_t *)malloc(rndlen); - if (rnd == NULL) { - fprintf(stderr, "malloc failure\n"); - return 0; - } - OQS_RAND_n(rand, rnd, rndlen); - - size_t i; - - for (i = 0; i < n; i += 2) { // two output elements at a time + for (size_t i = 0; i < n; i += 2) { // two output elements at a time uint8_t *pRnd = (rnd + 3 * i / 2); uint16_t rnd1 = (((pRnd[0] << 8) + pRnd[1]) & 0xFFE0) >> 5; // first 11 bits (0..10) @@ -71,9 +53,8 @@ static int lwe_sample_n_inverse_12(uint16_t *s, const size_t n, const uint16_t * uint8_t sample1 = 0; uint8_t sample2 = 0; - size_t j; // No need to compare with the last value. - for (j = 0; j < cdf_table_len - 1; j++) { + for (size_t j = 0; j < cdf_table_len - 1; j++) { // Constant time comparison: 1 if LWE_CDF_TABLE[j] < rnd1, 0 otherwise. // Critically uses the fact that LWE_CDF_TABLE[j] and rnd1 fit in 15 bits. sample1 += (uint16_t)(cdf_table[j] - rnd1) >> 15; @@ -90,34 +71,25 @@ static int lwe_sample_n_inverse_12(uint16_t *s, const size_t n, const uint16_t * s[i + 1] = ((-sign2) ^ sample2) + sign2; } } - - memset(rnd, 0, rndlen); - free(rnd); - return 1; + OQS_MEM_cleanse(rnd, sizeof(rnd)); } -static int lwe_sample_n_inverse_16(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) { +static void lwe_sample_n_inverse_16(uint16_t *s, const size_t n, const uint16_t *cdf_table, const size_t cdf_table_len, OQS_RAND *rand) { /* Fills vector s with n samples from the noise distribution which requires * 16 bits to sample. The distribution is specified by its CDF. Super-constant * timing: the CDF table is ingested for every sample. */ - size_t rndlen = 2 * n; - uint16_t *rndvec = (uint16_t *)malloc(rndlen); - if (rndvec == NULL) { - return 0; - } - OQS_RAND_n(rand, (uint8_t *) rndvec, rndlen); + uint16_t rndvec[ n ]; + OQS_RAND_n(rand, (uint8_t *) rndvec, sizeof(rndvec)); - size_t i, j; - - for (i = 0; i < n; ++i) { + for (size_t i = 0; i < n; ++i) { uint8_t sample = 0; uint16_t rnd = rndvec[i] >> 1; // drop the least significant bit uint8_t sign = rndvec[i] & 0x1; // pick the least significant bit // No need to compare with the last value. - for (j = 0; j < cdf_table_len - 1; j++) { + for (size_t j = 0; j < cdf_table_len - 1; j++) { // Constant time comparison: 1 if LWE_CDF_TABLE[j] < rnd, 0 otherwise. // Critically uses the fact that LWE_CDF_TABLE[j] and rnd fit in 15 bits. sample += (uint16_t)(cdf_table[j] - rnd) >> 15; @@ -125,34 +97,30 @@ static int lwe_sample_n_inverse_16(uint16_t *s, const size_t n, const uint16_t * // Assuming that sign is either 0 or 1, flips sample iff sign = 1 s[i] = ((-sign) ^ sample) + sign; } - - memset(rndvec, 0, rndlen); - free(rndvec); - return 1; + OQS_MEM_cleanse(rndvec, sizeof(rndvec)); } -int oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand) { +void oqs_kex_lwe_frodo_sample_n(uint16_t *s, const size_t n, struct oqs_kex_lwe_frodo_params *params, OQS_RAND *rand) { switch (params->sampler_num) { case 8: { // have to copy cdf_table from uint16_t to uint8_t - uint8_t *cdf_table_8 = malloc(params->cdf_table_len * sizeof(uint8_t)); - if (NULL == cdf_table_8) { - return 0; - } + uint8_t cdf_table_8[params->cdf_table_len * sizeof(uint8_t)]; for (size_t i = 0; i < params->cdf_table_len; i++) { cdf_table_8[i] = (uint8_t) params->cdf_table[i]; } - int ret = lwe_sample_n_inverse_8(s, n, cdf_table_8, params->cdf_table_len, rand); - free(cdf_table_8); - return ret; + lwe_sample_n_inverse_8(s, n, cdf_table_8, params->cdf_table_len, rand); } + break; case 12: - return lwe_sample_n_inverse_12(s, n, params->cdf_table, params->cdf_table_len, rand); + lwe_sample_n_inverse_12(s, n, params->cdf_table, params->cdf_table_len, rand); + break; case 16: - return lwe_sample_n_inverse_16(s, n, params->cdf_table, params->cdf_table_len, rand); + lwe_sample_n_inverse_16(s, n, params->cdf_table, params->cdf_table_len, rand); + break; default: - return 0; + assert(0); //ERROR + break; } } diff --git a/src/kex_lwe_frodo/recommended.h b/src/kex_lwe_frodo/recommended.h new file mode 100644 index 000000000..a1820737c --- /dev/null +++ b/src/kex_lwe_frodo/recommended.h @@ -0,0 +1,29 @@ +//Recommended parameter set. Include twice to undefine + +#ifndef OQS_LWE_FRODO_RECOMMENDED_H +#define OQS_LWE_FRODO_RECOMMENDED_H +#define PARAMS_N 752 +#define PARAMS_NBAR 8 +#define PARAMS_LOG2Q 15 +#define PARAMS_Q (1 << PARAMS_LOG2Q) +#define PARAMS_EXTRACTED_BITS 4 +#define PARAMS_KEY_BITS 256 +#define PARAMS_KEY_BYTES (PARAMS_KEY_BITS >> 3) +#define PARAMS_STRIPE_STEP 8 +#define LWE_DIV_ROUNDUP(x, y) (((x) + (y)-1) / y) +#define PARAMS_REC_HINT_LENGTH LWE_DIV_ROUNDUP(PARAMS_NBAR * PARAMS_NBAR, 8) +#define PARAMS_REC_PUB_LENGTH LWE_DIV_ROUNDUP(PARAMS_N * PARAMS_NBAR * PARAMS_LOG2Q, 8) + +#else + +#undef OQS_LWE_FRODO_RECOMMENDED_H +#undef PARAMS_N +#undef PARAMS_NBAR +#undef PARAMS_LOG2Q +#undef PARAMS_Q +#undef PARAMS_EXTRACTED_BITS +#undef PARAMS_KEY_BITS +#undef PARAMS_STRIPE_STEP +#undef LWE_DIV_ROUNDUP +#undef PARAMS_REC_HINT_LENGTH +#endif