Mlwe kyber (#131)

* Adding Kyber

* make prettyprint

* Remove picnic

* Fix the compilation on macOS

* Remove libm4ri-dev

* make prettyprint inconsistency, travis typo, travis add OPENSSL_DIR

* Missed one comment, should work everywhere now

* Remove .DS_Store file.
This commit is contained in:
Tancrède Lepoint 2017-07-03 15:34:26 -04:00 committed by Douglas Stebila
parent d08b510b8f
commit 8f7cff5b75
22 changed files with 1118 additions and 22 deletions

View File

@ -20,6 +20,7 @@ liboqs_la_LIBADD += src/crypto/rand_urandom_chacha20/librandchacha20.la
liboqs_la_LIBADD += src/kex_rlwe_bcns15/libbcns15.la src/kex_rlwe_newhope/libnewhope.la
liboqs_la_LIBADD += src/kex_lwe_frodo/libfrodo.la src/kex_rlwe_msrln16/libmsrln16.la
liboqs_la_LIBADD += src/kex_sidh_cln16/libcln16.la
liboqs_la_LIBADD += src/kex_mlwe_kyber/libkyber.la
if USE_MCBITS
liboqs_la_LIBADD += src/kex_code_mcbits/libmcbits.la
@ -95,6 +96,7 @@ links:
$(LN_S) -f ../../src/kex_lwe_frodo/kex_lwe_frodo.h include/oqs
$(LN_S) -f ../../src/kex_rlwe_bcns15/kex_rlwe_bcns15.h include/oqs
$(LN_S) -f ../../src/kex_sidh_cln16/kex_sidh_cln16.h include/oqs
$(LN_S) -f ../../src/kex_mlwe_kyber/kex_mlwe_kyber.h include/oqs
$(LN_S) -f .libs/liboqs.a
if USE_MCBITS
$(LN_S) -f ../../src/kex_code_mcbits/kex_code_mcbits.h include/oqs

View File

@ -126,6 +126,7 @@ SRCDIR=${SRCDIR}" src/kex_rlwe_newhope"
SRCDIR=${SRCDIR}" src/kex_lwe_frodo"
SRCDIR=${SRCDIR}" src/kex_rlwe_msrln16"
SRCDIR=${SRCDIR}" src/kex_sidh_cln16"
SRCDIR=${SRCDIR}" src/kex_mlwe_kyber"
if test x"$kex_ntru" = x"true"; then
AM_CPPFLAGS=${AM_CPPFLAGS}" -DENABLE_NTRU"
@ -176,6 +177,7 @@ AC_CONFIG_FILES([Makefile
src/kex_code_mcbits/Makefile
src/kex_ntru/Makefile
src/kex_sidh_iqc_ref/Makefile
src/kex_lwe_frodo/Makefile])
src/kex_lwe_frodo/Makefile
src/kex_mlwe_kyber/Makefile])
AC_OUTPUT

View File

@ -370,14 +370,6 @@ void OQS_SHA3_keccak_squeezeblocks(unsigned char *h, unsigned long long int nblo
}
}
void OQS_SHA3_shake128_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen) {
keccak_absorb(s, SHAKE128_RATE, input, inputByteLen, 0x1F);
}
void OQS_SHA3_shake128_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s) {
OQS_SHA3_keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE);
}
void OQS_SHA3_sha3256(unsigned char *output, const unsigned char *input, unsigned int inputByteLen) {
uint64_t s[25];
unsigned char t[SHA3_256_RATE];
@ -399,3 +391,86 @@ void OQS_SHA3_sha3512(unsigned char *output, const unsigned char *input, unsigne
for (i = 0; i < 64; i++)
output[i] = t[i];
}
void OQS_SHA3_shake128_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen) {
keccak_absorb(s, SHAKE128_RATE, input, inputByteLen, 0x1F);
}
void OQS_SHA3_shake128_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s) {
OQS_SHA3_keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE);
}
void OQS_SHA3_shake128(unsigned char *output, unsigned long long outlen,
const unsigned char *input, unsigned long long inlen) {
uint64_t s[25];
unsigned char t[SHAKE128_RATE];
unsigned long long nblocks = outlen / SHAKE128_RATE;
size_t i;
for (i = 0; i < 25; ++i)
s[i] = 0;
/* Absorb input */
keccak_absorb(s, SHAKE128_RATE, input, inlen, 0x1F);
/* Squeeze output */
OQS_SHA3_keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE);
output += nblocks * SHAKE128_RATE;
outlen -= nblocks * SHAKE128_RATE;
if (outlen) {
OQS_SHA3_keccak_squeezeblocks(t, 1, s, SHAKE128_RATE);
for (i = 0; i < outlen; i++)
output[i] = t[i];
}
}
void OQS_SHA3_cshake128_simple_absorb(uint64_t s[25],
uint16_t cstm, // 2-byte domain separator
const unsigned char *in, unsigned long long inlen) {
unsigned char *sep = (unsigned char *) s;
unsigned int i;
for (i = 0; i < 25; i++)
s[i] = 0;
/* Absorb customization (domain-separation) string */
sep[0] = 0x01;
sep[1] = 0xa8;
sep[2] = 0x01;
sep[3] = 0x00;
sep[4] = 0x01;
sep[5] = 16; // fixed bitlen of cstm
sep[6] = cstm & 0xff;
sep[7] = cstm >> 8;
KeccakF1600_StatePermute(s);
/* Absorb input */
keccak_absorb(s, SHAKE128_RATE, in, inlen, 0x04);
}
void OQS_SHA3_cshake128_simple_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s) {
OQS_SHA3_keccak_squeezeblocks(output, nblocks, s, SHAKE128_RATE);
}
void OQS_SHA3_cshake128_simple(unsigned char *output, unsigned long long outlen,
uint16_t cstm, // 2-byte domain separator
const unsigned char *in, unsigned long long inlen) {
uint64_t s[25];
unsigned char t[SHAKE128_RATE];
unsigned int i;
OQS_SHA3_cshake128_simple_absorb(s, cstm, in, inlen);
/* Squeeze output */
OQS_SHA3_keccak_squeezeblocks(output, outlen / SHAKE128_RATE, s, SHAKE128_RATE);
output += (outlen / SHAKE128_RATE) * SHAKE128_RATE;
if (outlen % SHAKE128_RATE) {
OQS_SHA3_keccak_squeezeblocks(t, 1, s, SHAKE128_RATE);
for (i = 0; i < outlen % SHAKE128_RATE; i++)
output[i] = t[i];
}
}

View File

@ -13,10 +13,23 @@
#define OQS_SHA3_SHA3_256_RATE 136
#define OQS_SHA3_SHA3_512_RATE 72
void OQS_SHA3_shake128_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen);
void OQS_SHA3_keccak_squeezeblocks(unsigned char *h, unsigned long long int nblocks, uint64_t *s, unsigned int r);
void OQS_SHA3_sha3256(unsigned char *output, const unsigned char *input, unsigned int inputByteLen);
void OQS_SHA3_sha3512(unsigned char *output, const unsigned char *input, unsigned int inputByteLen);
// SHAKE128
void OQS_SHA3_shake128_absorb(uint64_t *s, const unsigned char *input, unsigned int inputByteLen);
void OQS_SHA3_shake128_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
void OQS_SHA3_shake128(unsigned char *output, unsigned long long outlen,
const unsigned char *input, unsigned long long inlen);
// cSHAKE128
void OQS_SHA3_cshake128_simple_absorb(uint64_t *s,
uint16_t cstm, // 2-byte domain separator
const unsigned char *in, unsigned long long inlen);
void OQS_SHA3_cshake128_simple_squeezeblocks(unsigned char *output, unsigned long long nblocks, uint64_t *s);
void OQS_SHA3_cshake128_simple(unsigned char *output, unsigned long long outlen,
uint16_t cstm, // 2-byte domain separator
const unsigned char *in, unsigned long long inlen);
#endif

View File

@ -6,6 +6,7 @@
#include <oqs/kex_rlwe_msrln16.h>
#include <oqs/kex_rlwe_newhope.h>
#include <oqs/kex_sidh_cln16.h>
#include <oqs/kex_mlwe_kyber.h>
#ifdef ENABLE_CODE_MCBITS
#include <oqs/kex_code_mcbits.h>
@ -41,7 +42,6 @@ OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8
#else
assert(0);
#endif
case OQS_KEX_alg_ntru:
#ifdef ENABLE_NTRU
return OQS_KEX_ntru_new(rand);
@ -54,7 +54,8 @@ OQS_KEX *OQS_KEX_new(OQS_RAND *rand, enum OQS_KEX_alg_name alg_name, const uint8
#else
assert(0);
#endif
case OQS_KEX_alg_mlwe_kyber:
return OQS_KEX_mlwe_kyber_new(rand);
default:
assert(0);
return NULL;

View File

@ -22,6 +22,7 @@ enum OQS_KEX_alg_name {
OQS_KEX_alg_code_mcbits,
OQS_KEX_alg_ntru,
OQS_KEX_alg_sidh_iqc_ref,
OQS_KEX_alg_mlwe_kyber,
};
typedef struct OQS_KEX OQS_KEX;

View File

@ -35,6 +35,7 @@ struct kex_testcase kex_testcases[] = {
#ifdef ENABLE_NTRU
{OQS_KEX_alg_ntru, NULL, 0, NULL, "ntru", 0, 25},
#endif
{OQS_KEX_alg_mlwe_kyber, NULL, 0, NULL, "mlwe_kyber", 0, 100},
};
#define KEX_TEST_ITERATIONS 100

View File

@ -0,0 +1,7 @@
The files in this directory (except kex_mlwe_kyber.*) were originally published in https://github.com/pq-crystals/kyber
The following license applies to all files in the src/kex_mlwe_kyber directory.
Public domain.

View File

@ -0,0 +1,8 @@
AUTOMAKE_OPTIONS = foreign
noinst_LTLIBRARIES = libkyber.la
libkyber_la_SOURCES = kex_mlwe_kyber.c
libkyber_la_CPPFLAGS = -I../../include -I.
libkyber_la_CPPFLAGS += $(AM_CPPFLAGS)

179
src/kex_mlwe_kyber/indcpa.c Normal file
View File

@ -0,0 +1,179 @@
#include "params.h"
#include <oqs/rand.h>
#include <oqs/sha3.h>
static void pack_pk(unsigned char *r, const polyvec *pk, const unsigned char *seed) {
int i;
polyvec_compress(r, pk);
for (i = 0; i < KYBER_SEEDBYTES; i++)
r[i + KYBER_POLYVECCOMPRESSEDBYTES] = seed[i];
}
static void unpack_pk(polyvec *pk, unsigned char *seed, const unsigned char *packedpk) {
int i;
polyvec_decompress(pk, packedpk);
for (i = 0; i < KYBER_SEEDBYTES; i++)
seed[i] = packedpk[i + KYBER_POLYVECCOMPRESSEDBYTES];
}
static void pack_ciphertext(unsigned char *r, const polyvec *b, const poly *v) {
polyvec_compress(r, b);
poly_compress(r + KYBER_POLYVECCOMPRESSEDBYTES, v);
}
static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) {
polyvec_decompress(b, c);
poly_decompress(v, c + KYBER_POLYVECCOMPRESSEDBYTES);
}
static void pack_sk(unsigned char *r, const polyvec *sk) {
polyvec_tobytes(r, sk);
}
static void unpack_sk(polyvec *sk, const unsigned char *packedsk) {
polyvec_frombytes(sk, packedsk);
}
#define gen_a(A, B) gen_matrix(A, B, 0)
#define gen_at(A, B) gen_matrix(A, B, 1)
/* Generate entry a_{i,j} of matrix A as Parse(SHAKE128(seed|i|j)) */
void gen_matrix(polyvec *a, const unsigned char *seed, int transposed) //XXX: Not static for benchmarking
{
unsigned int pos = 0, ctr;
uint16_t val;
unsigned int nblocks = 4;
uint8_t buf[OQS_SHA3_SHAKE128_RATE * nblocks];
int i, j;
uint16_t dsep;
uint64_t state[25]; // CSHAKE state
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_D; j++) {
ctr = pos = 0;
if (transposed)
dsep = j + (i << 8);
else
dsep = i + (j << 8);
OQS_SHA3_cshake128_simple_absorb(state, dsep, seed, KYBER_SEEDBYTES);
OQS_SHA3_cshake128_simple_squeezeblocks(buf, nblocks, state);
while (ctr < KYBER_N) {
val = (buf[pos] | ((uint16_t) buf[pos + 1] << 8)) & 0x1fff;
if (val < KYBER_Q) {
a[i].vec[j].coeffs[ctr++] = val;
}
pos += 2;
if (pos > OQS_SHA3_SHAKE128_RATE * nblocks - 2) {
nblocks = 1;
OQS_SHA3_cshake128_simple_squeezeblocks(buf, nblocks, state);
pos = 0;
}
}
}
}
}
void indcpa_keypair(unsigned char *pk,
unsigned char *sk, OQS_RAND *rand) {
polyvec a[KYBER_D], e, pkpv, skpv;
unsigned char seed[KYBER_SEEDBYTES];
unsigned char noiseseed[KYBER_COINBYTES];
int i;
unsigned char nonce = 0;
rand->rand_n(rand, seed, KYBER_SEEDBYTES);
OQS_SHA3_shake128(seed, KYBER_SEEDBYTES, seed, KYBER_SEEDBYTES); /* Don't send output of system RNG */
rand->rand_n(rand, noiseseed, KYBER_COINBYTES);
gen_a(a, seed);
for (i = 0; i < KYBER_D; i++)
poly_getnoise(skpv.vec + i, noiseseed, nonce++);
polyvec_ntt(&skpv);
for (i = 0; i < KYBER_D; i++)
poly_getnoise(e.vec + i, noiseseed, nonce++);
// matrix-vector multiplication
for (i = 0; i < KYBER_D; i++)
polyvec_pointwise_acc(&pkpv.vec[i], &skpv, a + i);
polyvec_invntt(&pkpv);
polyvec_add(&pkpv, &pkpv, &e);
pack_sk(sk, &skpv);
pack_pk(pk, &pkpv, seed);
}
void indcpa_enc(unsigned char *c,
const unsigned char *m,
const unsigned char *pk,
const unsigned char *coins) {
polyvec sp, pkpv, ep, at[KYBER_D], bp;
poly v, k, epp;
unsigned char seed[KYBER_SEEDBYTES];
int i;
unsigned char nonce = 0;
unpack_pk(&pkpv, seed, pk);
poly_frommsg(&k, m);
for (i = 0; i < KYBER_D; i++)
bitrev_vector(pkpv.vec[i].coeffs);
polyvec_ntt(&pkpv);
gen_at(at, seed);
for (i = 0; i < KYBER_D; i++)
poly_getnoise(sp.vec + i, coins, nonce++);
polyvec_ntt(&sp);
for (i = 0; i < KYBER_D; i++)
poly_getnoise(ep.vec + i, coins, nonce++);
// matrix-vector multiplication
for (i = 0; i < KYBER_D; i++)
polyvec_pointwise_acc(&bp.vec[i], &sp, at + i);
polyvec_invntt(&bp);
polyvec_add(&bp, &bp, &ep);
polyvec_pointwise_acc(&v, &pkpv, &sp);
poly_invntt(&v);
poly_getnoise(&epp, coins, nonce++);
poly_add(&v, &v, &epp);
poly_add(&v, &v, &k);
pack_ciphertext(c, &bp, &v);
}
void indcpa_dec(unsigned char *m,
const unsigned char *c,
const unsigned char *sk) {
polyvec bp, skpv;
poly v, mp;
size_t i;
unpack_ciphertext(&bp, &v, c);
unpack_sk(&skpv, sk);
for (i = 0; i < KYBER_D; i++)
bitrev_vector(bp.vec[i].coeffs);
polyvec_ntt(&bp);
polyvec_pointwise_acc(&mp, &skpv, &bp);
poly_invntt(&mp);
poly_sub(&mp, &mp, &v);
poly_tomsg(m, &mp);
}

View File

@ -0,0 +1,159 @@
#if defined(WINDOWS)
#define UNUSED
// __attribute__ not supported in VS, is there something else I should define?
#else
#define UNUSED __attribute__((unused))
#endif
#include <stdlib.h>
#include <string.h>
#if !defined(WINDOWS)
#include <strings.h>
#include <unistd.h>
#endif
#include <oqs/kex.h>
#include <oqs/rand.h>
#include "kex_mlwe_kyber.h"
#include "kyber.c"
#include "params.h"
OQS_KEX *OQS_KEX_mlwe_kyber_new(OQS_RAND *rand) {
OQS_KEX *k = malloc(sizeof(OQS_KEX));
if (k == NULL) {
return NULL;
}
k->method_name = strdup("MLWE Kyber");
k->estimated_classical_security = 178; // using https://github.com/pq-crystals/kyber/blob/master/scripts/Kyber.py
k->estimated_quantum_security = 161; // using https://github.com/pq-crystals/kyber/blob/master/scripts/Kyber.py
k->seed = NULL;
k->seed_len = 0;
k->named_parameters = 0;
k->rand = rand;
k->params = NULL;
k->alice_0 = &OQS_KEX_mlwe_kyber_alice_0;
k->bob = &OQS_KEX_mlwe_kyber_bob;
k->alice_1 = &OQS_KEX_mlwe_kyber_alice_1;
k->alice_priv_free = &OQS_KEX_mlwe_kyber_alice_priv_free;
k->free = &OQS_KEX_mlwe_kyber_free;
return k;
}
int OQS_KEX_mlwe_kyber_alice_0(UNUSED OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len) {
int ret;
/* allocate public/private key pair */
*alice_msg = malloc(KYBER_PUBLICKEYBYTES);
if (*alice_msg == NULL) {
goto err;
}
*alice_priv = malloc(KYBER_SECRETKEYBYTES);
if (*alice_priv == NULL) {
goto err;
}
/* generate public/private key pair */
keygen(*alice_msg, (unsigned char *) *alice_priv, k->rand);
*alice_msg_len = KYBER_PUBLICKEYBYTES;
ret = 1;
goto cleanup;
err:
ret = 0;
free(*alice_msg);
*alice_msg = NULL;
free(*alice_priv);
*alice_priv = NULL;
cleanup:
return ret;
}
int OQS_KEX_mlwe_kyber_bob(UNUSED 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) {
int ret;
if (alice_msg_len != KYBER_PUBLICKEYBYTES) {
goto err;
}
/* allocate message and session key */
*bob_msg = malloc(KYBER_BYTES);
if (*bob_msg == NULL) {
goto err;
}
*key = malloc(32);
if (*key == NULL) {
goto err;
}
/* generate Bob's response */
sharedb(*key, *bob_msg, alice_msg, k->rand);
*bob_msg_len = KYBER_BYTES;
*key_len = 32;
ret = 1;
goto cleanup;
err:
ret = 0;
free(*bob_msg);
*bob_msg = NULL;
free(*key);
*key = NULL;
cleanup:
return ret;
}
int OQS_KEX_mlwe_kyber_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;
if (bob_msg_len != KYBER_BYTES) {
goto err;
}
/* allocate session key */
*key = malloc(32);
if (*key == NULL) {
goto err;
}
/* generate Alice's session key */
shareda(*key, (unsigned char *) alice_priv, bob_msg);
*key_len = 32;
ret = 1;
goto cleanup;
err:
ret = 0;
free(*key);
*key = NULL;
cleanup:
return ret;
}
void OQS_KEX_mlwe_kyber_alice_priv_free(UNUSED OQS_KEX *k, void *alice_priv) {
if (alice_priv) {
free(alice_priv);
}
}
void OQS_KEX_mlwe_kyber_free(OQS_KEX *k) {
if (k) {
free(k->named_parameters);
k->named_parameters = NULL;
free(k->method_name);
k->method_name = NULL;
}
free(k);
}

View File

@ -0,0 +1,24 @@
/**
* \file kex_mlwe_kyber.h
* \brief Header for module-LWE key exchange protocol Kyber
*/
#ifndef __OQS_KEX_MLWE_KYBER_H
#define __OQS_KEX_MLWE_KYBER_H
#include <stddef.h>
#include <stdint.h>
#include <oqs/kex.h>
#include <oqs/rand.h>
OQS_KEX *OQS_KEX_mlwe_kyber_new(OQS_RAND *rand);
int OQS_KEX_mlwe_kyber_alice_0(OQS_KEX *k, void **alice_priv, uint8_t **alice_msg, size_t *alice_msg_len);
int OQS_KEX_mlwe_kyber_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);
int OQS_KEX_mlwe_kyber_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);
void OQS_KEX_mlwe_kyber_alice_priv_free(OQS_KEX *k, void *alice_priv);
void OQS_KEX_mlwe_kyber_free(OQS_KEX *k);
#endif

View File

@ -0,0 +1,86 @@
#include <stdint.h>
#include <oqs/sha3.h>
#include <oqs/rand.h>
// clang-format off
// (order of include matters)
#include "precomp.c"
#include "reduce.c"
#include "verify.c"
#include "ntt.c"
#include "poly.c"
#include "polyvec.c"
#include "indcpa.c"
// clang-format on
// API FUNCTIONS
/* Build a CCA-secure KEM from an IND-CPA-secure encryption scheme */
static void keygen(unsigned char *pk, unsigned char *sk, OQS_RAND *rand) {
size_t i;
indcpa_keypair(pk, sk, rand);
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++)
sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i];
OQS_SHA3_shake128(sk + KYBER_SECRETKEYBYTES - 64, 32, pk, KYBER_PUBLICKEYBYTES);
rand->rand_n(rand, sk + KYBER_SECRETKEYBYTES - KYBER_SHAREDKEYBYTES, KYBER_SHAREDKEYBYTES); /* Value z for pseudo-random output on reject */
}
static void sharedb(unsigned char *sharedkey, unsigned char *send,
const unsigned char *received, OQS_RAND *rand) {
unsigned char krq[96]; /* Will contain key, coins, qrom-hash */
unsigned char buf[64];
int i;
rand->rand_n(rand, buf, 32);
OQS_SHA3_shake128(buf, 32, buf, 32); /* Don't release system RNG output */
OQS_SHA3_shake128(buf + 32, 32, received, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
OQS_SHA3_shake128(krq, 96, buf, 64);
indcpa_enc(send, buf, received, krq + 32); /* coins are in krq+32 */
for (i = 0; i < 32; i++)
send[i + KYBER_INDCPA_BYTES] = krq[i + 64];
OQS_SHA3_shake128(krq + 32, 32, send, KYBER_BYTES); /* overwrite coins in krq with h(c) */
OQS_SHA3_shake128(sharedkey, 32, krq, 64); /* hash concatenation of pre-k and h(c) to k */
#ifndef STATISTICAL_TEST
OQS_SHA3_sha3256(sharedkey, sharedkey, 32);
#endif
}
static void shareda(unsigned char *sharedkey, const unsigned char *sk,
const unsigned char *received) {
int i, fail;
unsigned char cmp[KYBER_BYTES];
unsigned char buf[64];
unsigned char krq[96]; /* Will contain key, coins, qrom-hash */
const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES;
indcpa_dec(buf, received, sk);
// shake128(buf+32, 32, pk, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
for (i = 0; i < 32; i++) /* Save hash by storing h(pk) in sk */
buf[32 + i] = sk[KYBER_SECRETKEYBYTES - 64 + i];
OQS_SHA3_shake128(krq, 96, buf, 64);
indcpa_enc(cmp, buf, pk, krq + 32); /* coins are in krq+32 */
for (i = 0; i < 32; i++)
cmp[i + KYBER_INDCPA_BYTES] = krq[i + 64];
fail = verify(received, cmp, KYBER_BYTES);
OQS_SHA3_shake128(krq + 32, 32, received, KYBER_BYTES); /* overwrite coins in krq with h(c) */
cmov(krq, sk + KYBER_SECRETKEYBYTES - KYBER_SHAREDKEYBYTES, KYBER_SHAREDKEYBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */
OQS_SHA3_shake128(sharedkey, 32, krq, 64); /* hash concatenation of pre-k and h(c) to k */
#ifndef STATISTICAL_TEST
OQS_SHA3_sha3256(sharedkey, sharedkey, 32);
#endif
}

67
src/kex_mlwe_kyber/ntt.c Normal file
View File

@ -0,0 +1,67 @@
#include "params.h"
static uint16_t bitrev_table[KYBER_N] = {
0, 128, 64, 192, 32, 160, 96, 224, 16, 144, 80, 208, 48, 176, 112, 240,
8, 136, 72, 200, 40, 168, 104, 232, 24, 152, 88, 216, 56, 184, 120, 248,
4, 132, 68, 196, 36, 164, 100, 228, 20, 148, 84, 212, 52, 180, 116, 244,
12, 140, 76, 204, 44, 172, 108, 236, 28, 156, 92, 220, 60, 188, 124, 252,
2, 130, 66, 194, 34, 162, 98, 226, 18, 146, 82, 210, 50, 178, 114, 242,
10, 138, 74, 202, 42, 170, 106, 234, 26, 154, 90, 218, 58, 186, 122, 250,
6, 134, 70, 198, 38, 166, 102, 230, 22, 150, 86, 214, 54, 182, 118, 246,
14, 142, 78, 206, 46, 174, 110, 238, 30, 158, 94, 222, 62, 190, 126, 254,
1, 129, 65, 193, 33, 161, 97, 225, 17, 145, 81, 209, 49, 177, 113, 241,
9, 137, 73, 201, 41, 169, 105, 233, 25, 153, 89, 217, 57, 185, 121, 249,
5, 133, 69, 197, 37, 165, 101, 229, 21, 149, 85, 213, 53, 181, 117, 245,
13, 141, 77, 205, 45, 173, 109, 237, 29, 157, 93, 221, 61, 189, 125, 253,
3, 131, 67, 195, 35, 163, 99, 227, 19, 147, 83, 211, 51, 179, 115, 243,
11, 139, 75, 203, 43, 171, 107, 235, 27, 155, 91, 219, 59, 187, 123, 251,
7, 135, 71, 199, 39, 167, 103, 231, 23, 151, 87, 215, 55, 183, 119, 247,
15, 143, 79, 207, 47, 175, 111, 239, 31, 159, 95, 223, 63, 191, 127, 255,
};
void bitrev_vector(uint16_t *poly) {
unsigned int i, r;
uint16_t tmp;
for (i = 0; i < KYBER_N; i++) {
r = bitrev_table[i];
if (i < r) {
tmp = poly[i];
poly[i] = poly[r];
poly[r] = tmp;
}
}
}
void mul_coefficients(uint16_t *poly, const uint16_t *factors) {
unsigned int i;
for (i = 0; i < KYBER_N; i++)
poly[i] = montgomery_reduce((poly[i] * factors[i]));
}
/* GS_bo_to_no; omegas need to be in Montgomery domain */
void ntt(uint16_t *a, const uint16_t *omega) {
int start, j, jTwiddle, level;
uint16_t temp, W;
uint32_t t;
for (level = 0; level < 8; level++) {
for (start = 0; start < (1 << level); start++) {
jTwiddle = 0;
for (j = start; j < KYBER_N - 1; j += 2 * (1 << level)) {
W = omega[jTwiddle++];
temp = a[j];
if (level & 1) // odd level
a[j] = barrett_reduce((temp + a[j + (1 << level)]));
else
a[j] = (temp + a[j + (1 << level)]); // Omit reduction (be lazy)
t = (W * ((uint32_t) temp + 4 * KYBER_Q - a[j + (1 << level)]));
a[j + (1 << level)] = montgomery_reduce(t);
}
}
}
}

View File

@ -0,0 +1,37 @@
#ifndef PARAMS_H
#define PARAMS_H
#define KYBER_N 256
#define KYBER_D 3
#define KYBER_K 4 /* used in sampler */
#define KYBER_Q 7681
#define KYBER_SEEDBYTES 32
#define KYBER_NOISESEEDBYTES 32
#define KYBER_COINBYTES 32
#define KYBER_SHAREDKEYBYTES 32
#define KYBER_POLYBYTES 416
#define KYBER_POLYCOMPRESSEDBYTES 96
#define KYBER_POLYVECBYTES (KYBER_D * KYBER_POLYBYTES)
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_D * 352)
#define KYBER_INDCPA_MSGBYTES 32
#define KYBER_INDCPA_PUBLICKEYBYTES (KYBER_POLYVECCOMPRESSEDBYTES + KYBER_SEEDBYTES)
#define KYBER_INDCPA_SECRETKEYBYTES (KYBER_POLYVECBYTES)
#define KYBER_INDCPA_BYTES (KYBER_POLYVECCOMPRESSEDBYTES + KYBER_POLYCOMPRESSEDBYTES)
#define KYBER_PUBLICKEYBYTES (KYBER_INDCPA_PUBLICKEYBYTES)
#define KYBER_SECRETKEYBYTES (KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES + 32 + KYBER_SHAREDKEYBYTES)
#define KYBER_BYTES (KYBER_INDCPA_BYTES + KYBER_INDCPA_MSGBYTES) /* Second part is for Targhi-Unruh */
extern uint16_t oqs_kex_mlwe_kyber_omegas_montgomery[];
extern uint16_t oqs_kex_mlwe_kyber_omegas_inv_bitrev_montgomery[];
extern uint16_t oqs_kex_mlwe_kyber_psis_inv_montgomery[];
extern uint16_t oqs_kex_mlwe_kyber_psis_bitrev_montgomery[];
#if defined(WINDOWS)
typedef unsigned __int16 uint16_t;
#endif
#endif

169
src/kex_mlwe_kyber/poly.c Normal file
View File

@ -0,0 +1,169 @@
#include "params.h"
#include <oqs/sha3.h>
typedef struct {
uint16_t coeffs[KYBER_N];
#if defined(WINDOWS)
} poly;
#else
} poly __attribute__((aligned(32)));
#endif
/* include cbd.c */
static uint32_t load_littleendian(const unsigned char *x) {
return x[0] | (((uint32_t) x[1]) << 8) | (((uint32_t) x[2]) << 16) | (((uint32_t) x[3]) << 24);
}
void cbd(poly *r, const unsigned char *buf) {
#if KYBER_K != 4
#error "poly_getnoise in poly.c only supports k=4"
#endif
uint32_t t, d, a[4], b[4];
int i, j;
for (i = 0; i < KYBER_N / 4; i++) {
t = load_littleendian(buf + 4 * i);
d = 0;
for (j = 0; j < 4; j++)
d += (t >> j) & 0x11111111;
a[0] = d & 0xf;
b[0] = (d >> 4) & 0xf;
a[1] = (d >> 8) & 0xf;
b[1] = (d >> 12) & 0xf;
a[2] = (d >> 16) & 0xf;
b[2] = (d >> 20) & 0xf;
a[3] = (d >> 24) & 0xf;
b[3] = (d >> 28);
r->coeffs[4 * i + 0] = a[0] + KYBER_Q - b[0];
r->coeffs[4 * i + 1] = a[1] + KYBER_Q - b[1];
r->coeffs[4 * i + 2] = a[2] + KYBER_Q - b[2];
r->coeffs[4 * i + 3] = a[3] + KYBER_Q - b[3];
}
}
/* end cbd.c */
void poly_compress(unsigned char *r, const poly *a) {
uint32_t t[8];
unsigned int i, j, k = 0;
for (i = 0; i < KYBER_N; i += 8) {
for (j = 0; j < 8; j++)
t[j] = (((freeze(a->coeffs[i + j]) << 3) + KYBER_Q / 2) / KYBER_Q) & 7;
r[k] = t[0] | (t[1] << 3) | (t[2] << 6);
r[k + 1] = (t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7);
r[k + 2] = (t[5] >> 1) | (t[6] << 2) | (t[7] << 5);
k += 3;
}
}
void poly_decompress(poly *r, const unsigned char *a) {
unsigned int i;
for (i = 0; i < KYBER_N; i += 8) {
r->coeffs[i + 0] = (((a[0] & 7) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 1] = ((((a[0] >> 3) & 7) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 2] = ((((a[0] >> 6) | ((a[1] << 2) & 4)) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 3] = ((((a[1] >> 1) & 7) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 4] = ((((a[1] >> 4) & 7) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 5] = ((((a[1] >> 7) | ((a[2] << 1) & 6)) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 6] = ((((a[2] >> 2) & 7) * KYBER_Q) + 4) >> 3;
r->coeffs[i + 7] = ((((a[2] >> 5)) * KYBER_Q) + 4) >> 3;
a += 3;
}
}
void poly_tobytes(unsigned char *r, const poly *a) {
int i, j;
uint16_t t[8];
for (i = 0; i < KYBER_N / 8; i++) {
for (j = 0; j < 8; j++)
t[j] = freeze(a->coeffs[8 * i + j]);
r[13 * i + 0] = t[0] & 0xff;
r[13 * i + 1] = (t[0] >> 8) | ((t[1] & 0x07) << 5);
r[13 * i + 2] = (t[1] >> 3) & 0xff;
r[13 * i + 3] = (t[1] >> 11) | ((t[2] & 0x3f) << 2);
r[13 * i + 4] = (t[2] >> 6) | ((t[3] & 0x01) << 7);
r[13 * i + 5] = (t[3] >> 1) & 0xff;
r[13 * i + 6] = (t[3] >> 9) | ((t[4] & 0x0f) << 4);
r[13 * i + 7] = (t[4] >> 4) & 0xff;
r[13 * i + 8] = (t[4] >> 12) | ((t[5] & 0x7f) << 1);
r[13 * i + 9] = (t[5] >> 7) | ((t[6] & 0x03) << 6);
r[13 * i + 10] = (t[6] >> 2) & 0xff;
r[13 * i + 11] = (t[6] >> 10) | ((t[7] & 0x1f) << 3);
r[13 * i + 12] = (t[7] >> 5);
}
}
void poly_frombytes(poly *r, const unsigned char *a) {
int i;
for (i = 0; i < KYBER_N / 8; i++) {
r->coeffs[8 * i + 0] = a[13 * i + 0] | (((uint16_t) a[13 * i + 1] & 0x1f) << 8);
r->coeffs[8 * i + 1] = (a[13 * i + 1] >> 5) | (((uint16_t) a[13 * i + 2]) << 3) | (((uint16_t) a[13 * i + 3] & 0x03) << 11);
r->coeffs[8 * i + 2] = (a[13 * i + 3] >> 2) | (((uint16_t) a[13 * i + 4] & 0x7f) << 6);
r->coeffs[8 * i + 3] = (a[13 * i + 4] >> 7) | (((uint16_t) a[13 * i + 5]) << 1) | (((uint16_t) a[13 * i + 6] & 0x0f) << 9);
r->coeffs[8 * i + 4] = (a[13 * i + 6] >> 4) | (((uint16_t) a[13 * i + 7]) << 4) | (((uint16_t) a[13 * i + 8] & 0x01) << 12);
r->coeffs[8 * i + 5] = (a[13 * i + 8] >> 1) | (((uint16_t) a[13 * i + 9] & 0x3f) << 7);
r->coeffs[8 * i + 6] = (a[13 * i + 9] >> 6) | (((uint16_t) a[13 * i + 10]) << 2) | (((uint16_t) a[13 * i + 11] & 0x07) << 10);
r->coeffs[8 * i + 7] = (a[13 * i + 11] >> 3) | (((uint16_t) a[13 * i + 12]) << 5);
}
}
void poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) {
unsigned char buf[KYBER_N];
OQS_SHA3_cshake128_simple(buf, KYBER_N, nonce, seed, KYBER_NOISESEEDBYTES);
cbd(r, buf);
}
void poly_ntt(poly *r) {
mul_coefficients(r->coeffs, oqs_kex_mlwe_kyber_psis_bitrev_montgomery);
ntt(r->coeffs, oqs_kex_mlwe_kyber_omegas_montgomery);
}
void poly_invntt(poly *r) {
bitrev_vector(r->coeffs);
ntt(r->coeffs, oqs_kex_mlwe_kyber_omegas_inv_bitrev_montgomery);
mul_coefficients(r->coeffs, oqs_kex_mlwe_kyber_psis_inv_montgomery);
}
void poly_add(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++)
r->coeffs[i] = barrett_reduce(a->coeffs[i] + b->coeffs[i]);
}
void poly_sub(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++)
r->coeffs[i] = barrett_reduce(a->coeffs[i] + 3 * KYBER_Q - b->coeffs[i]);
}
void poly_frommsg(poly *r, const unsigned char msg[KYBER_SHAREDKEYBYTES]) {
uint16_t i, j, mask;
for (i = 0; i < KYBER_SHAREDKEYBYTES; i++) {
for (j = 0; j < 8; j++) {
mask = -((msg[i] >> j) & 1);
r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2);
}
}
}
void poly_tomsg(unsigned char msg[KYBER_SHAREDKEYBYTES], const poly *a) {
uint16_t t;
int i, j;
for (i = 0; i < KYBER_SHAREDKEYBYTES; i++) {
msg[i] = 0;
for (j = 0; j < 8; j++) {
t = (((freeze(a->coeffs[8 * i + j]) << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
msg[i] |= t << j;
}
}
}

View File

@ -0,0 +1,196 @@
#include "params.h"
typedef struct {
poly vec[KYBER_D];
#if defined(WINDOWS)
} polyvec;
#else
} polyvec __attribute__((aligned(32)));
#endif
#if (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_D * 352))
void polyvec_compress(unsigned char *r, const polyvec *a) {
int i, j, k;
uint16_t t[8];
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N / 8; j++) {
for (k = 0; k < 8; k++)
t[k] = ((((uint32_t) freeze(a->vec[i].coeffs[8 * j + k]) << 11) + KYBER_Q / 2) / KYBER_Q) & 0x7ff;
r[11 * j + 0] = t[0] & 0xff;
r[11 * j + 1] = (t[0] >> 8) | ((t[1] & 0x1f) << 3);
r[11 * j + 2] = (t[1] >> 5) | ((t[2] & 0x03) << 6);
r[11 * j + 3] = (t[2] >> 2) & 0xff;
r[11 * j + 4] = (t[2] >> 10) | ((t[3] & 0x7f) << 1);
r[11 * j + 5] = (t[3] >> 7) | ((t[4] & 0x0f) << 4);
r[11 * j + 6] = (t[4] >> 4) | ((t[5] & 0x01) << 7);
r[11 * j + 7] = (t[5] >> 1) & 0xff;
r[11 * j + 8] = (t[5] >> 9) | ((t[6] & 0x3f) << 2);
r[11 * j + 9] = (t[6] >> 6) | ((t[7] & 0x07) << 5);
r[11 * j + 10] = (t[7] >> 3);
}
r += 352;
}
}
void polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N / 8; j++) {
r->vec[i].coeffs[8 * j + 0] = (((a[11 * j + 0] | (((uint32_t) a[11 * j + 1] & 0x07) << 8)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 1] = ((((a[11 * j + 1] >> 3) | (((uint32_t) a[11 * j + 2] & 0x3f) << 5)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 2] = ((((a[11 * j + 2] >> 6) | (((uint32_t) a[11 * j + 3] & 0xff) << 2) | (((uint32_t) a[11 * j + 4] & 0x01) << 10)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 3] = ((((a[11 * j + 4] >> 1) | (((uint32_t) a[11 * j + 5] & 0x0f) << 7)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 4] = ((((a[11 * j + 5] >> 4) | (((uint32_t) a[11 * j + 6] & 0x7f) << 4)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 5] = ((((a[11 * j + 6] >> 7) | (((uint32_t) a[11 * j + 7] & 0xff) << 1) | (((uint32_t) a[11 * j + 8] & 0x03) << 9)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 6] = ((((a[11 * j + 8] >> 2) | (((uint32_t) a[11 * j + 9] & 0x1f) << 6)) * KYBER_Q) + 1024) >> 11;
r->vec[i].coeffs[8 * j + 7] = ((((a[11 * j + 9] >> 5) | (((uint32_t) a[11 * j + 10] & 0xff) << 3)) * KYBER_Q) + 1024) >> 11;
}
a += 352;
}
}
#elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_D * 320))
void polyvec_compress(unsigned char *r, const polyvec *a) {
int i, j, k;
uint16_t t[4];
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N / 4; j++) {
for (k = 0; k < 4; k++)
t[k] = ((((uint32_t) freeze(a->vec[i].coeffs[4 * j + k]) << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff;
r[5 * j + 0] = t[0] & 0xff;
r[5 * j + 1] = (t[0] >> 8) | ((t[1] & 0x3f) << 2);
r[5 * j + 2] = (t[1] >> 6) | ((t[2] & 0x0f) << 4);
r[5 * j + 3] = (t[2] >> 4) | ((t[3] & 0x03) << 6);
r[5 * j + 4] = (t[3] >> 2);
}
r += 320;
}
}
void polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N / 4; j++) {
r->vec[i].coeffs[4 * j + 0] = (((a[5 * j + 0] | (((uint32_t) a[5 * j + 1] & 0x03) << 8)) * KYBER_Q) + 512) >> 10;
r->vec[i].coeffs[4 * j + 1] = ((((a[5 * j + 1] >> 2) | (((uint32_t) a[5 * j + 2] & 0x0f) << 6)) * KYBER_Q) + 512) >> 10;
r->vec[i].coeffs[4 * j + 2] = ((((a[5 * j + 2] >> 4) | (((uint32_t) a[5 * j + 3] & 0x3f) << 4)) * KYBER_Q) + 512) >> 10;
r->vec[i].coeffs[4 * j + 3] = ((((a[5 * j + 3] >> 6) | (((uint32_t) a[5 * j + 4] & 0xff) << 2)) * KYBER_Q) + 512) >> 10;
}
a += 320;
}
}
#elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_D * 288))
void polyvec_compress(unsigned char *r, const polyvec *a) {
int i, j, k;
uint16_t t[8];
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N / 8; j++) {
for (k = 0; k < 8; k++)
t[k] = ((((uint32_t) freeze(a->vec[i].coeffs[8 * j + k]) << 9) + KYBER_Q / 2) / KYBER_Q) & 0x1ff;
r[9 * j + 0] = t[0] & 0xff;
r[9 * j + 1] = (t[0] >> 8) | ((t[1] & 0x7f) << 1);
r[9 * j + 2] = (t[1] >> 7) | ((t[2] & 0x3f) << 2);
r[9 * j + 3] = (t[2] >> 6) | ((t[3] & 0x1f) << 3);
r[9 * j + 4] = (t[3] >> 5) | ((t[4] & 0x0f) << 4);
r[9 * j + 5] = (t[4] >> 4) | ((t[5] & 0x07) << 5);
r[9 * j + 6] = (t[5] >> 3) | ((t[6] & 0x03) << 6);
r[9 * j + 7] = (t[6] >> 2) | ((t[7] & 0x01) << 7);
r[9 * j + 8] = (t[7] >> 1);
}
r += 288;
}
}
void polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N / 8; j++) {
r->vec[i].coeffs[8 * j + 0] = (((a[9 * j + 0] | (((uint32_t) a[9 * j + 1] & 0x01) << 8)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 1] = ((((a[9 * j + 1] >> 1) | (((uint32_t) a[9 * j + 2] & 0x03) << 7)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 2] = ((((a[9 * j + 2] >> 2) | (((uint32_t) a[9 * j + 3] & 0x07) << 6)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 3] = ((((a[9 * j + 3] >> 3) | (((uint32_t) a[9 * j + 4] & 0x0f) << 5)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 4] = ((((a[9 * j + 4] >> 4) | (((uint32_t) a[9 * j + 5] & 0x1f) << 4)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 5] = ((((a[9 * j + 5] >> 5) | (((uint32_t) a[9 * j + 6] & 0x3f) << 3)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 6] = ((((a[9 * j + 6] >> 6) | (((uint32_t) a[9 * j + 7] & 0x7f) << 2)) * KYBER_Q) + 256) >> 9;
r->vec[i].coeffs[8 * j + 7] = ((((a[9 * j + 7] >> 7) | (((uint32_t) a[9 * j + 8] & 0xff) << 1)) * KYBER_Q) + 256) >> 9;
}
a += 288;
}
}
#elif (KYBER_POLYVECCOMPRESSEDBYTES == (KYBER_D * 256))
void polyvec_compress(unsigned char *r, const polyvec *a) {
int i, j, k;
uint16_t t;
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N; j++) {
r[j] = ((((uint32_t) freeze(a->vec[i].coeffs[j]) << 8) + KYBER_Q / 2) / KYBER_Q) & 0xff;
}
r += 256;
}
}
void polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_D; i++) {
for (j = 0; j < KYBER_N; j++) {
r->vec[i].coeffs[j] = ((a[j] * KYBER_Q) + 128) >> 8;
}
a += 256;
}
}
#else
#error "Unsupported compression of polyvec"
#endif
void polyvec_tobytes(unsigned char *r, const polyvec *a) {
int i;
for (i = 0; i < KYBER_D; i++)
poly_tobytes(r + i * KYBER_POLYBYTES, &a->vec[i]);
}
void polyvec_frombytes(polyvec *r, const unsigned char *a) {
int i;
for (i = 0; i < KYBER_D; i++)
poly_frombytes(&r->vec[i], a + i * KYBER_POLYBYTES);
}
void polyvec_ntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_D; i++)
poly_ntt(&r->vec[i]);
}
void polyvec_invntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_D; i++)
poly_invntt(&r->vec[i]);
}
void polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b) {
int i, j;
uint16_t t;
for (j = 0; j < KYBER_N; j++) {
t = montgomery_reduce(4613 * (uint32_t) b->vec[0].coeffs[j]); // 4613 = 2^{2*18} % q
r->coeffs[j] = montgomery_reduce(a->vec[0].coeffs[j] * t);
for (i = 1; i < KYBER_D; i++) {
t = montgomery_reduce(4613 * (uint32_t) b->vec[i].coeffs[j]);
r->coeffs[j] += montgomery_reduce(a->vec[i].coeffs[j] * t);
}
r->coeffs[j] = barrett_reduce(r->coeffs[j]);
}
}
void polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) {
int i;
for (i = 0; i < KYBER_D; i++)
poly_add(&r->vec[i], &a->vec[i], &b->vec[i]);
}

View File

@ -0,0 +1,9 @@
#include "params.h"
uint16_t oqs_kex_mlwe_kyber_omegas_montgomery[KYBER_N / 2] = {990, 7427, 2634, 6819, 578, 3281, 2143, 1095, 484, 6362, 3336, 5382, 6086, 3823, 877, 5656, 3583, 7010, 6414, 263, 1285, 291, 7143, 7338, 1581, 5134, 5184, 5932, 4042, 5775, 2468, 3, 606, 729, 5383, 962, 3240, 7548, 5129, 7653, 5929, 4965, 2461, 641, 1584, 2666, 1142, 157, 7407, 5222, 5602, 5142, 6140, 5485, 4931, 1559, 2085, 5284, 2056, 3538, 7269, 3535, 7190, 1957, 3465, 6792, 1538, 4664, 2023, 7643, 3660, 7673, 1694, 6905, 3995, 3475, 5939, 1859, 6910, 4434, 1019, 1492, 7087, 4761, 657, 4859, 5798, 2640, 1693, 2607, 2782, 5400, 6466, 1010, 957, 3851, 2121, 6392, 7319, 3367, 3659, 3375, 6430, 7583, 1549, 5856, 4773, 6084, 5544, 1650, 3997, 4390, 6722, 2915, 4245, 2635, 6128, 7676, 5737, 1616, 3457, 3132, 7196, 4702, 6239, 851, 2122, 3009};
uint16_t oqs_kex_mlwe_kyber_omegas_inv_bitrev_montgomery[KYBER_N / 2] = {990, 254, 862, 5047, 6586, 5538, 4400, 7103, 2025, 6804, 3858, 1595, 2299, 4345, 1319, 7197, 7678, 5213, 1906, 3639, 1749, 2497, 2547, 6100, 343, 538, 7390, 6396, 7418, 1267, 671, 4098, 5724, 491, 4146, 412, 4143, 5625, 2397, 5596, 6122, 2750, 2196, 1541, 2539, 2079, 2459, 274, 7524, 6539, 5015, 6097, 7040, 5220, 2716, 1752, 28, 2552, 133, 4441, 6719, 2298, 6952, 7075, 4672, 5559, 6830, 1442, 2979, 485, 4549, 4224, 6065, 1944, 5, 1553, 5046, 3436, 4766, 959, 3291, 3684, 6031, 2137, 1597, 2908, 1825, 6132, 98, 1251, 4306, 4022, 4314, 362, 1289, 5560, 3830, 6724, 6671, 1215, 2281, 4899, 5074, 5988, 5041, 1883, 2822, 7024, 2920, 594, 6189, 6662, 3247, 771, 5822, 1742, 4206, 3686, 776, 5987, 8, 4021, 38, 5658, 3017, 6143, 889, 4216};
uint16_t oqs_kex_mlwe_kyber_psis_bitrev_montgomery[KYBER_N] = {990, 7427, 2634, 6819, 578, 3281, 2143, 1095, 484, 6362, 3336, 5382, 6086, 3823, 877, 5656, 3583, 7010, 6414, 263, 1285, 291, 7143, 7338, 1581, 5134, 5184, 5932, 4042, 5775, 2468, 3, 606, 729, 5383, 962, 3240, 7548, 5129, 7653, 5929, 4965, 2461, 641, 1584, 2666, 1142, 157, 7407, 5222, 5602, 5142, 6140, 5485, 4931, 1559, 2085, 5284, 2056, 3538, 7269, 3535, 7190, 1957, 3465, 6792, 1538, 4664, 2023, 7643, 3660, 7673, 1694, 6905, 3995, 3475, 5939, 1859, 6910, 4434, 1019, 1492, 7087, 4761, 657, 4859, 5798, 2640, 1693, 2607, 2782, 5400, 6466, 1010, 957, 3851, 2121, 6392, 7319, 3367, 3659, 3375, 6430, 7583, 1549, 5856, 4773, 6084, 5544, 1650, 3997, 4390, 6722, 2915, 4245, 2635, 6128, 7676, 5737, 1616, 3457, 3132, 7196, 4702, 6239, 851, 2122, 3009, 7613, 7295, 2007, 323, 5112, 3716, 2289, 6442, 6965, 2713, 7126, 3401, 963, 6596, 607, 5027, 7078, 4484, 5937, 944, 2860, 2680, 5049, 1777, 5850, 3387, 6487, 6777, 4812, 4724, 7077, 186, 6848, 6793, 3463, 5877, 1174, 7116, 3077, 5945, 6591, 590, 6643, 1337, 6036, 3991, 1675, 2053, 6055, 1162, 1679, 3883, 4311, 2106, 6163, 4486, 6374, 5006, 4576, 4288, 5180, 4102, 282, 6119, 7443, 6330, 3184, 4971, 2530, 5325, 4171, 7185, 5175, 5655, 1898, 382, 7211, 43, 5965, 6073, 1730, 332, 1577, 3304, 2329, 1699, 6150, 2379, 5113, 333, 3502, 4517, 1480, 1172, 5567, 651, 925, 4573, 599, 1367, 4109, 1863, 6929, 1605, 3866, 2065, 4048, 839, 5764, 2447, 2022, 3345, 1990, 4067, 2036, 2069, 3567, 7371, 2368, 339, 6947, 2159, 654, 7327, 2768, 6676, 987, 2214};
uint16_t oqs_kex_mlwe_kyber_psis_inv_montgomery[KYBER_N] = {1024, 4972, 5779, 6907, 4943, 4168, 315, 5580, 90, 497, 1123, 142, 4710, 5527, 2443, 4871, 698, 2489, 2394, 4003, 684, 2241, 2390, 7224, 5072, 2064, 4741, 1687, 6841, 482, 7441, 1235, 2126, 4742, 2802, 5744, 6287, 4933, 699, 3604, 1297, 2127, 5857, 1705, 3868, 3779, 4397, 2177, 159, 622, 2240, 1275, 640, 6948, 4572, 5277, 209, 2605, 1157, 7328, 5817, 3191, 1662, 2009, 4864, 574, 2487, 164, 6197, 4436, 7257, 3462, 4268, 4281, 3414, 4515, 3170, 1290, 2003, 5855, 7156, 6062, 7531, 1732, 3249, 4884, 7512, 3590, 1049, 2123, 1397, 6093, 3691, 6130, 6541, 3946, 6258, 3322, 1788, 4241, 4900, 2309, 1400, 1757, 400, 502, 6698, 2338, 3011, 668, 7444, 4580, 6516, 6795, 2959, 4136, 3040, 2279, 6355, 3943, 2913, 6613, 7416, 4084, 6508, 5556, 4054, 3782, 61, 6567, 2212, 779, 632, 5709, 5667, 4923, 4911, 6893, 4695, 4164, 3536, 2287, 7594, 2848, 3267, 1911, 3128, 546, 1991, 156, 4958, 5531, 6903, 483, 875, 138, 250, 2234, 2266, 7222, 2842, 4258, 812, 6703, 232, 5207, 6650, 2585, 1900, 6225, 4932, 7265, 4701, 3173, 4635, 6393, 227, 7313, 4454, 4284, 6759, 1224, 5223, 1447, 395, 2608, 4502, 4037, 189, 3348, 54, 6443, 2210, 6230, 2826, 1780, 3002, 5995, 1955, 6102, 6045, 3938, 5019, 4417, 1434, 1262, 1507, 5847, 5917, 7157, 7177, 6434, 7537, 741, 4348, 1309, 145, 374, 2236, 4496, 5028, 6771, 6923, 7421, 1978, 1023, 3857, 6876, 1102, 7451, 4704, 6518, 1344, 765, 384, 5705, 1207, 1630, 4734, 1563, 6839, 5933, 1954, 4987, 7142, 5814, 7527, 4953, 7637, 4707, 2182, 5734, 2818, 541, 4097, 5641};

View File

@ -0,0 +1,36 @@
#include "params.h"
static const uint32_t qinv = 7679; // -inverse_mod(q,2^18)
static const uint32_t rlog = 18;
uint16_t montgomery_reduce(uint32_t a) {
uint32_t u;
u = (a * qinv);
u &= ((1 << rlog) - 1);
u *= KYBER_Q;
a = a + u;
return a >> rlog;
}
uint16_t barrett_reduce(uint16_t a) {
uint32_t u;
u = a >> 13;
u *= KYBER_Q;
a -= u;
return a;
}
uint16_t freeze(uint16_t x) {
uint16_t m, r;
int16_t c;
r = barrett_reduce(x);
m = r - KYBER_Q;
c = m;
c >>= 15;
r = m ^ ((r ^ m) & c);
return r;
}

View File

@ -0,0 +1,24 @@
#include <string.h>
#include <stdint.h>
/* returns 0 for equal strings, 1 for non-equal strings */
int verify(const unsigned char *a, const unsigned char *b, size_t len) {
uint64_t r;
size_t i;
r = 0;
for (i = 0; i < len; i++)
r |= a[i] ^ b[i];
r = (-r) >> 63;
return r;
}
/* b = 1 means mov, b = 0 means don't mov*/
void cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) {
size_t i;
b = -b;
for (i = 0; i < len; i++)
r[i] ^= b & (x[i] ^ r[i]);
}

View File

@ -37,7 +37,7 @@ static void bitrev_vector(uint16_t *poly) {
uint16_t tmp;
for (i = 0; i < PARAM_N; i++) {
r = bitrev_table[i];
r = oqs_kex_rlwe_newhope_bitrev_table[i];
if (i < r) {
tmp = poly[i];
poly[i] = poly[r];
@ -215,14 +215,14 @@ static void poly_add(poly *r, const poly *a, const poly *b) {
}
static void poly_ntt(poly *r) {
mul_coefficients(r->coeffs, psis_bitrev_montgomery);
ntt((uint16_t *) r->coeffs, omegas_montgomery);
mul_coefficients(r->coeffs, oqs_kex_rlwe_newhope_psis_bitrev_montgomery);
ntt((uint16_t *) r->coeffs, oqs_kex_rlwe_newhope_omegas_montgomery);
}
static void poly_invntt(poly *r) {
bitrev_vector(r->coeffs);
ntt((uint16_t *) r->coeffs, omegas_inv_montgomery);
mul_coefficients(r->coeffs, psis_inv_montgomery);
ntt((uint16_t *) r->coeffs, oqs_kex_rlwe_newhope_omegas_inv_montgomery);
mul_coefficients(r->coeffs, oqs_kex_rlwe_newhope_psis_inv_montgomery);
}
// Error Correction:

File diff suppressed because one or more lines are too long