mirror of
https://github.com/open-quantum-safe/liboqs.git
synced 2025-10-08 00:03:38 -04:00
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:
parent
d08b510b8f
commit
8f7cff5b75
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
7
src/kex_mlwe_kyber/LICENSE.txt
Normal file
7
src/kex_mlwe_kyber/LICENSE.txt
Normal 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.
|
8
src/kex_mlwe_kyber/Makefile.am
Normal file
8
src/kex_mlwe_kyber/Makefile.am
Normal 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
179
src/kex_mlwe_kyber/indcpa.c
Normal 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);
|
||||
}
|
159
src/kex_mlwe_kyber/kex_mlwe_kyber.c
Normal file
159
src/kex_mlwe_kyber/kex_mlwe_kyber.c
Normal 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);
|
||||
}
|
24
src/kex_mlwe_kyber/kex_mlwe_kyber.h
Normal file
24
src/kex_mlwe_kyber/kex_mlwe_kyber.h
Normal 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
|
86
src/kex_mlwe_kyber/kyber.c
Normal file
86
src/kex_mlwe_kyber/kyber.c
Normal 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
67
src/kex_mlwe_kyber/ntt.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
src/kex_mlwe_kyber/params.h
Normal file
37
src/kex_mlwe_kyber/params.h
Normal 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
169
src/kex_mlwe_kyber/poly.c
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
196
src/kex_mlwe_kyber/polyvec.c
Normal file
196
src/kex_mlwe_kyber/polyvec.c
Normal 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]);
|
||||
}
|
9
src/kex_mlwe_kyber/precomp.c
Normal file
9
src/kex_mlwe_kyber/precomp.c
Normal 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};
|
36
src/kex_mlwe_kyber/reduce.c
Normal file
36
src/kex_mlwe_kyber/reduce.c
Normal 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;
|
||||
}
|
24
src/kex_mlwe_kyber/verify.c
Normal file
24
src/kex_mlwe_kyber/verify.c
Normal 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]);
|
||||
}
|
@ -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
Loading…
x
Reference in New Issue
Block a user