Browse Source

Kyberv2 (#150)

* Replaced round-1 Kyber code with round-2 Kyber code (not yet cleaned/namespaced)

* Namespacing for Kyber

* Some more work on round-2 Kyber (more namespacing)

* Added missing files

* Round-2 Kyber768 now passing all tests under Linux

* Various small tweaks to make MS compiler happy

* Two more tweaks for MS compiler

* Added Kyber512 and Kyber1024 (round-2 versions)

* Making MS compiler happy

* More fixes for MS compiler

* Replaced round-1 Kyber code with round-2 Kyber code (not yet cleaned/namespaced)

* Namespacing for Kyber

* Some more work on round-2 Kyber (more namespacing)

* Added missing files

* Round-2 Kyber768 now passing all tests under Linux

* Various small tweaks to make MS compiler happy

* Two more tweaks for MS compiler

* Added Kyber512 and Kyber1024 (round-2 versions)

* Making MS compiler happy

* More fixes for MS compiler

* Started more cleanup work on Kyber768

* Replaced round-1 Kyber code with round-2 Kyber code (not yet cleaned/namespaced)

* Namespacing for Kyber

* Some more work on round-2 Kyber (more namespacing)

* Added missing files

* Round-2 Kyber768 now passing all tests under Linux

* Various small tweaks to make MS compiler happy

* Two more tweaks for MS compiler

* Added Kyber512 and Kyber1024 (round-2 versions)

* Replaced round-1 Kyber code with round-2 Kyber code (not yet cleaned/namespaced)

* Namespacing for Kyber

* Some more work on round-2 Kyber (more namespacing)

* Added missing files

* Round-2 Kyber768 now passing all tests under Linux

* Various small tweaks to make MS compiler happy

* Two more tweaks for MS compiler

* Added Kyber512 and Kyber1024 (round-2 versions)

* Making MS compiler happy

* Making MS compiler happy

* More fixes for MS compiler

* More fixes for MS compiler

* Started more cleanup work on Kyber768

* Kyber768 passing all tests locally

* Kyber512 passes all tests locally

* Kyber1024 now also passing all tests locally

* Now passing all tests with -Wmissing-prototypes

* Local tests (on Linux) passing again
master
cryptojedi 5 years ago
committed by Thom Wiggers
parent
commit
56a3715ddc
69 changed files with 4060 additions and 829 deletions
  1. +22
    -0
      crypto_kem/kyber1024/META.yml
  2. +15
    -0
      crypto_kem/kyber1024/clean/LICENSE
  3. +19
    -0
      crypto_kem/kyber1024/clean/Makefile
  4. +19
    -0
      crypto_kem/kyber1024/clean/Makefile.Microsoft_nmake
  5. +18
    -0
      crypto_kem/kyber1024/clean/api.h
  6. +53
    -0
      crypto_kem/kyber1024/clean/cbd.c
  7. +8
    -0
      crypto_kem/kyber1024/clean/cbd.h
  8. +305
    -0
      crypto_kem/kyber1024/clean/indcpa.c
  9. +16
    -0
      crypto_kem/kyber1024/clean/indcpa.h
  10. +100
    -0
      crypto_kem/kyber1024/clean/kem.c
  11. +157
    -0
      crypto_kem/kyber1024/clean/ntt.c
  12. +13
    -0
      crypto_kem/kyber1024/clean/ntt.h
  13. +31
    -0
      crypto_kem/kyber1024/clean/params.h
  14. +289
    -0
      crypto_kem/kyber1024/clean/poly.c
  15. +38
    -0
      crypto_kem/kyber1024/clean/poly.h
  16. +196
    -0
      crypto_kem/kyber1024/clean/polyvec.c
  17. +27
    -0
      crypto_kem/kyber1024/clean/polyvec.h
  18. +62
    -0
      crypto_kem/kyber1024/clean/reduce.c
  19. +15
    -0
      crypto_kem/kyber1024/clean/reduce.h
  20. +64
    -0
      crypto_kem/kyber1024/clean/symmetric-fips202.c
  21. +28
    -0
      crypto_kem/kyber1024/clean/symmetric.h
  22. +51
    -0
      crypto_kem/kyber1024/clean/verify.c
  23. +10
    -0
      crypto_kem/kyber1024/clean/verify.h
  24. +22
    -0
      crypto_kem/kyber512/META.yml
  25. +15
    -0
      crypto_kem/kyber512/clean/LICENSE
  26. +19
    -0
      crypto_kem/kyber512/clean/Makefile
  27. +19
    -0
      crypto_kem/kyber512/clean/Makefile.Microsoft_nmake
  28. +18
    -0
      crypto_kem/kyber512/clean/api.h
  29. +53
    -0
      crypto_kem/kyber512/clean/cbd.c
  30. +8
    -0
      crypto_kem/kyber512/clean/cbd.h
  31. +305
    -0
      crypto_kem/kyber512/clean/indcpa.c
  32. +16
    -0
      crypto_kem/kyber512/clean/indcpa.h
  33. +100
    -0
      crypto_kem/kyber512/clean/kem.c
  34. +157
    -0
      crypto_kem/kyber512/clean/ntt.c
  35. +13
    -0
      crypto_kem/kyber512/clean/ntt.h
  36. +31
    -0
      crypto_kem/kyber512/clean/params.h
  37. +287
    -0
      crypto_kem/kyber512/clean/poly.c
  38. +38
    -0
      crypto_kem/kyber512/clean/poly.h
  39. +186
    -0
      crypto_kem/kyber512/clean/polyvec.c
  40. +27
    -0
      crypto_kem/kyber512/clean/polyvec.h
  41. +62
    -0
      crypto_kem/kyber512/clean/reduce.c
  42. +15
    -0
      crypto_kem/kyber512/clean/reduce.h
  43. +64
    -0
      crypto_kem/kyber512/clean/symmetric-fips202.c
  44. +26
    -0
      crypto_kem/kyber512/clean/symmetric.h
  45. +51
    -0
      crypto_kem/kyber512/clean/verify.c
  46. +10
    -0
      crypto_kem/kyber512/clean/verify.h
  47. +3
    -3
      crypto_kem/kyber768/META.yml
  48. +2
    -2
      crypto_kem/kyber768/clean/Makefile
  49. +1
    -1
      crypto_kem/kyber768/clean/Makefile.Microsoft_nmake
  50. +8
    -9
      crypto_kem/kyber768/clean/api.h
  51. +40
    -46
      crypto_kem/kyber768/clean/cbd.c
  52. +0
    -1
      crypto_kem/kyber768/clean/cbd.h
  53. +178
    -183
      crypto_kem/kyber768/clean/indcpa.c
  54. +57
    -63
      crypto_kem/kyber768/clean/kem.c
  55. +136
    -59
      crypto_kem/kyber768/clean/ntt.c
  56. +6
    -2
      crypto_kem/kyber768/clean/ntt.h
  57. +12
    -8
      crypto_kem/kyber768/clean/params.h
  58. +203
    -151
      crypto_kem/kyber768/clean/poly.c
  59. +10
    -4
      crypto_kem/kyber768/clean/poly.h
  60. +124
    -100
      crypto_kem/kyber768/clean/polyvec.c
  61. +5
    -2
      crypto_kem/kyber768/clean/polyvec.h
  62. +0
    -100
      crypto_kem/kyber768/clean/precomp.c
  63. +50
    -58
      crypto_kem/kyber768/clean/reduce.c
  64. +6
    -3
      crypto_kem/kyber768/clean/reduce.h
  65. +64
    -0
      crypto_kem/kyber768/clean/symmetric-fips202.c
  66. +26
    -0
      crypto_kem/kyber768/clean/symmetric.h
  67. +30
    -29
      crypto_kem/kyber768/clean/verify.c
  68. +1
    -1
      crypto_kem/kyber768/clean/verify.h
  69. +0
    -4
      test/test_nistkat.py

+ 22
- 0
crypto_kem/kyber1024/META.yml View File

@@ -0,0 +1,22 @@
name: Kyber1024
type: kem
claimed-nist-level: 5
length-public-key: 1568
length-ciphertext: 1568
length-secret-key: 3168
length-shared-secret: 32
nistkat-sha256: b4b4fc1c2cbbb182252d2822ccb8cb704bcfe876122635c5dfa48ddc09b6e73f
principal-submitter: Peter Schwabe
auxiliary-submitters:
- Roberto Avanzi
- Joppe Bos
- Léo Ducas
- Eike Kiltz
- Tancrède Lepoint
- Vadim Lyubashevsky
- John M. Schanck
- Gregor Seiler
- Damien Stehlé
implementations:
- name: clean
version: https://github.com/pq-crystals/kyber/commit/46e283ab575ec92dfe82fb12229ae2d9d6246682

+ 15
- 0
crypto_kem/kyber1024/clean/LICENSE View File

@@ -0,0 +1,15 @@
Public Domain
Authors: Joppe Bos,
Léo Ducas,
Eike Kiltz ,
Tancrède Lepoint,
Vadim Lyubashevsky,
John Schanck,
Peter Schwabe,
Gregor Seiler,
Damien Stehlé

For Keccak and AES we are using public-domain
code from sources and by authors listed in
comments on top of the respective files.


+ 19
- 0
crypto_kem/kyber1024/clean/Makefile View File

@@ -0,0 +1,19 @@
# This Makefile can be used with GNU Make or BSD Make

LIB=libkyber1024_clean.a
HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h symmetric.h
OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o verify.o symmetric-fips202.o

CFLAGS=-O3 -Wall -Wextra -Wpedantic -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS)

all: $(LIB)

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<

$(LIB): $(OBJECTS)
$(AR) -r $@ $(OBJECTS)

clean:
$(RM) $(OBJECTS)
$(RM) $(LIB)

+ 19
- 0
crypto_kem/kyber1024/clean/Makefile.Microsoft_nmake View File

@@ -0,0 +1,19 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# nmake /f Makefile.Microsoft_nmake

LIBRARY=libkyber1024_clean.lib
OBJECTS=cbd.obj indcpa.obj kem.obj ntt.obj poly.obj polyvec.obj reduce.obj verify.obj symmetric-fips202.obj

CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

# Make sure objects are recompiled if headers change.
$(OBJECTS): *.h

$(LIBRARY): $(OBJECTS)
LIB.EXE /NOLOGO /WX /OUT:$@ $**

clean:
-DEL $(OBJECTS)
-DEL $(LIBRARY)

+ 18
- 0
crypto_kem/kyber1024/clean/api.h View File

@@ -0,0 +1,18 @@
#ifndef PQCLEAN_KYBER1024_CLEAN_API_H
#define PQCLEAN_KYBER1024_CLEAN_API_H

#define PQCLEAN_KYBER1024_CLEAN_CRYPTO_SECRETKEYBYTES 3168
#define PQCLEAN_KYBER1024_CLEAN_CRYPTO_PUBLICKEYBYTES 1568
#define PQCLEAN_KYBER1024_CLEAN_CRYPTO_CIPHERTEXTBYTES 1568
#define PQCLEAN_KYBER1024_CLEAN_CRYPTO_BYTES 32

#define PQCLEAN_KYBER1024_CLEAN_CRYPTO_ALGNAME "Kyber1024"

int PQCLEAN_KYBER1024_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);

int PQCLEAN_KYBER1024_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);

int PQCLEAN_KYBER1024_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);


#endif

+ 53
- 0
crypto_kem/kyber1024/clean/cbd.c View File

@@ -0,0 +1,53 @@
#include "cbd.h"

#include "params.h"

#include <stdint.h>

/*************************************************
* Name: load32_littleendian
*
* Description: load bytes into a 32-bit integer
* in little-endian order
*
* Arguments: - const unsigned char *x: pointer to input byte array
*
* Returns 32-bit unsigned integer loaded from x
**************************************************/
static uint32_t load32_littleendian(const unsigned char *x) {
uint32_t r;
r = (uint32_t)x[0];
r |= (uint32_t)x[1] << 8;
r |= (uint32_t)x[2] << 16;
r |= (uint32_t)x[3] << 24;
return r;
}

/*************************************************
* Name: cbd
*
* Description: Given an array of uniformly random bytes, compute
* polynomial with coefficients distributed according to
* a centered binomial distribution with parameter KYBER_ETA
* specialized for KYBER_ETA=2
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *buf: pointer to input byte array
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_cbd(poly *r, const unsigned char *buf) {
uint32_t d, t;
int16_t a, b;
int i, j;

for (i = 0; i < KYBER_N / 8; i++) {
t = load32_littleendian(buf + 4 * i);
d = t & 0x55555555;
d += (t >> 1) & 0x55555555;

for (j = 0; j < 8; j++) {
a = (d >> 4 * j) & 0x3;
b = (d >> (4 * j + 2)) & 0x3;
r->coeffs[8 * i + j] = a - b;
}
}
}

+ 8
- 0
crypto_kem/kyber1024/clean/cbd.h View File

@@ -0,0 +1,8 @@
#ifndef CBD_H
#define CBD_H

#include "poly.h"

void PQCLEAN_KYBER1024_CLEAN_cbd(poly *r, const unsigned char *buf);

#endif

+ 305
- 0
crypto_kem/kyber1024/clean/indcpa.c View File

@@ -0,0 +1,305 @@
#include "indcpa.h"

#include "ntt.h"
#include "poly.h"
#include "polyvec.h"
#include "randombytes.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: pack_pk
*
* Description: Serialize the public key as concatenation of the
* serialized vector of polynomials pk
* and the public seed used to generate the matrix A.
*
* Arguments: unsigned char *r: pointer to the output serialized public key
* const poly *pk: pointer to the input public-key polynomial
* const unsigned char *seed: pointer to the input public seed
**************************************************/
static void pack_pk(unsigned char *r, polyvec *pk, const unsigned char *seed) {
int i;
PQCLEAN_KYBER1024_CLEAN_polyvec_tobytes(r, pk);
for (i = 0; i < KYBER_SYMBYTES; i++) {
r[i + KYBER_POLYVECBYTES] = seed[i];
}
}

/*************************************************
* Name: unpack_pk
*
* Description: De-serialize public key from a byte array;
* approximate inverse of pack_pk
*
* Arguments: - polyvec *pk: pointer to output public-key vector of polynomials
* - unsigned char *seed: pointer to output seed to generate matrix A
* - const unsigned char *packedpk: pointer to input serialized public key
**************************************************/
static void unpack_pk(polyvec *pk, unsigned char *seed, const unsigned char *packedpk) {
int i;
PQCLEAN_KYBER1024_CLEAN_polyvec_frombytes(pk, packedpk);
for (i = 0; i < KYBER_SYMBYTES; i++) {
seed[i] = packedpk[i + KYBER_POLYVECBYTES];
}
}

/*************************************************
* Name: pack_sk
*
* Description: Serialize the secret key
*
* Arguments: - unsigned char *r: pointer to output serialized secret key
* - const polyvec *sk: pointer to input vector of polynomials (secret key)
**************************************************/
static void pack_sk(unsigned char *r, polyvec *sk) {
PQCLEAN_KYBER1024_CLEAN_polyvec_tobytes(r, sk);
}

/*************************************************
* Name: unpack_sk
*
* Description: De-serialize the secret key;
* inverse of pack_sk
*
* Arguments: - polyvec *sk: pointer to output vector of polynomials (secret key)
* - const unsigned char *packedsk: pointer to input serialized secret key
**************************************************/
static void unpack_sk(polyvec *sk, const unsigned char *packedsk) {
PQCLEAN_KYBER1024_CLEAN_polyvec_frombytes(sk, packedsk);
}

/*************************************************
* Name: pack_ciphertext
*
* Description: Serialize the ciphertext as concatenation of the
* compressed and serialized vector of polynomials b
* and the compressed and serialized polynomial v
*
* Arguments: unsigned char *r: pointer to the output serialized ciphertext
* const poly *pk: pointer to the input vector of polynomials b
* const unsigned char *seed: pointer to the input polynomial v
**************************************************/
static void pack_ciphertext(unsigned char *r, polyvec *b, poly *v) {
PQCLEAN_KYBER1024_CLEAN_polyvec_compress(r, b);
PQCLEAN_KYBER1024_CLEAN_poly_compress(r + KYBER_POLYVECCOMPRESSEDBYTES, v);
}

/*************************************************
* Name: unpack_ciphertext
*
* Description: De-serialize and decompress ciphertext from a byte array;
* approximate inverse of pack_ciphertext
*
* Arguments: - polyvec *b: pointer to the output vector of polynomials b
* - poly *v: pointer to the output polynomial v
* - const unsigned char *c: pointer to the input serialized ciphertext
**************************************************/
static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) {
PQCLEAN_KYBER1024_CLEAN_polyvec_decompress(b, c);
PQCLEAN_KYBER1024_CLEAN_poly_decompress(v, c + KYBER_POLYVECCOMPRESSEDBYTES);
}

/*************************************************
* Name: rej_uniform
*
* Description: Run rejection sampling on uniform random bytes to generate
* uniform random integers mod q
*
* Arguments: - int16_t *r: pointer to output buffer
* - unsigned int len: requested number of 16-bit integers (uniform mod q)
* - const unsigned char *buf: pointer to input buffer (assumed to be uniform random bytes)
* - unsigned int buflen: length of input buffer in bytes
*
* Returns number of sampled 16-bit integers (at most len)
**************************************************/
static unsigned int rej_uniform(int16_t *r, unsigned int len, const unsigned char *buf, unsigned int buflen) {
unsigned int ctr, pos;
uint16_t val;

ctr = pos = 0;
while (ctr < len && pos + 2 <= buflen) {
val = buf[pos] | ((uint16_t)buf[pos + 1] << 8);
pos += 2;

if (val < 19 * KYBER_Q) {
val -= (val >> 12) * KYBER_Q; // Barrett reduction
r[ctr++] = (int16_t)val;
}
}

return ctr;
}

#define gen_a(A,B) PQCLEAN_KYBER1024_CLEAN_gen_matrix(A,B,0)
#define gen_at(A,B) PQCLEAN_KYBER1024_CLEAN_gen_matrix(A,B,1)

#define GENMATRIX_MAXNBLOCKS ((530 + XOF_BLOCKBYTES) / XOF_BLOCKBYTES) /* 530 is expected number of required bytes */


/*************************************************
* Name: gen_matrix
*
* Description: Deterministically generate matrix A (or the transpose of A)
* from a seed. Entries of the matrix are polynomials that look
* uniformly random. Performs rejection sampling on output of
* a XOF
*
* Arguments: - polyvec *a: pointer to ouptput matrix A
* - const unsigned char *seed: pointer to input seed
* - int transposed: boolean deciding whether A or A^T is generated
**************************************************/
static void PQCLEAN_KYBER1024_CLEAN_gen_matrix(polyvec *a, const unsigned char *seed, int transposed) {
unsigned int ctr;
unsigned char i, j;
unsigned char buf[XOF_BLOCKBYTES * GENMATRIX_MAXNBLOCKS + 1];
xof_state state;

for (i = 0; i < KYBER_K; i++) {
for (j = 0; j < KYBER_K; j++) {
if (transposed) {
xof_absorb(&state, seed, i, j);
} else {
xof_absorb(&state, seed, j, i);
}

xof_squeezeblocks(buf, GENMATRIX_MAXNBLOCKS, &state);
ctr = rej_uniform(a[i].vec[j].coeffs, KYBER_N, buf, GENMATRIX_MAXNBLOCKS * XOF_BLOCKBYTES);

while (ctr < KYBER_N) {
xof_squeezeblocks(buf, 1, &state);
ctr += rej_uniform(a[i].vec[j].coeffs + ctr, KYBER_N - ctr, buf, XOF_BLOCKBYTES);
}
}
}
}

/*************************************************
* Name: indcpa_keypair
*
* Description: Generates public and private key for the CPA-secure
* public-key encryption scheme underlying Kyber
*
* Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_indcpa_keypair(unsigned char *pk, unsigned char *sk) {
polyvec a[KYBER_K], e, pkpv, skpv;
unsigned char buf[2 * KYBER_SYMBYTES];
unsigned char *publicseed = buf;
unsigned char *noiseseed = buf + KYBER_SYMBYTES;
int i;
unsigned char nonce = 0;

randombytes(buf, KYBER_SYMBYTES);
hash_g(buf, buf, KYBER_SYMBYTES);

gen_a(a, publicseed);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_getnoise(skpv.vec + i, noiseseed, nonce++);
}
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_getnoise(e.vec + i, noiseseed, nonce++);
}

PQCLEAN_KYBER1024_CLEAN_polyvec_ntt(&skpv);
PQCLEAN_KYBER1024_CLEAN_polyvec_ntt(&e);

// matrix-vector multiplication
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc(&pkpv.vec[i], &a[i], &skpv);
PQCLEAN_KYBER1024_CLEAN_poly_frommont(&pkpv.vec[i]);
}

PQCLEAN_KYBER1024_CLEAN_polyvec_add(&pkpv, &pkpv, &e);
PQCLEAN_KYBER1024_CLEAN_polyvec_reduce(&pkpv);

pack_sk(sk, &skpv);
pack_pk(pk, &pkpv, publicseed);
}

/*************************************************
* Name: indcpa_enc
*
* Description: Encryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *c: pointer to output ciphertext (of length KYBER_INDCPA_BYTES bytes)
* - const unsigned char *m: pointer to input message (of length KYBER_INDCPA_MSGBYTES bytes)
* - const unsigned char *pk: pointer to input public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - const unsigned char *coin: pointer to input random coins used as seed (of length KYBER_SYMBYTES bytes)
* to deterministically generate all randomness
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_indcpa_enc(unsigned char *c,
const unsigned char *m,
const unsigned char *pk,
const unsigned char *coins) {
polyvec sp, pkpv, ep, at[KYBER_K], bp;
poly v, k, epp;
unsigned char seed[KYBER_SYMBYTES];
int i;
unsigned char nonce = 0;

unpack_pk(&pkpv, seed, pk);
PQCLEAN_KYBER1024_CLEAN_poly_frommsg(&k, m);
gen_at(at, seed);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_getnoise(sp.vec + i, coins, nonce++);
}
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_getnoise(ep.vec + i, coins, nonce++);
}
PQCLEAN_KYBER1024_CLEAN_poly_getnoise(&epp, coins, nonce++);

PQCLEAN_KYBER1024_CLEAN_polyvec_ntt(&sp);

// matrix-vector multiplication
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc(&bp.vec[i], &at[i], &sp);
}

PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc(&v, &pkpv, &sp);

PQCLEAN_KYBER1024_CLEAN_polyvec_invntt(&bp);
PQCLEAN_KYBER1024_CLEAN_poly_invntt(&v);

PQCLEAN_KYBER1024_CLEAN_polyvec_add(&bp, &bp, &ep);
PQCLEAN_KYBER1024_CLEAN_poly_add(&v, &v, &epp);
PQCLEAN_KYBER1024_CLEAN_poly_add(&v, &v, &k);
PQCLEAN_KYBER1024_CLEAN_polyvec_reduce(&bp);
PQCLEAN_KYBER1024_CLEAN_poly_reduce(&v);

pack_ciphertext(c, &bp, &v);
}

/*************************************************
* Name: indcpa_dec
*
* Description: Decryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *m: pointer to output decrypted message (of length KYBER_INDCPA_MSGBYTES)
* - const unsigned char *c: pointer to input ciphertext (of length KYBER_INDCPA_BYTES)
* - const unsigned char *sk: pointer to input secret key (of length KYBER_INDCPA_SECRETKEYBYTES)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_indcpa_dec(unsigned char *m,
const unsigned char *c,
const unsigned char *sk) {
polyvec bp, skpv;
poly v, mp;

unpack_ciphertext(&bp, &v, c);
unpack_sk(&skpv, sk);

PQCLEAN_KYBER1024_CLEAN_polyvec_ntt(&bp);
PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc(&mp, &skpv, &bp);
PQCLEAN_KYBER1024_CLEAN_poly_invntt(&mp);

PQCLEAN_KYBER1024_CLEAN_poly_sub(&mp, &v, &mp);
PQCLEAN_KYBER1024_CLEAN_poly_reduce(&mp);

PQCLEAN_KYBER1024_CLEAN_poly_tomsg(m, &mp);
}

+ 16
- 0
crypto_kem/kyber1024/clean/indcpa.h View File

@@ -0,0 +1,16 @@
#ifndef INDCPA_H
#define INDCPA_H

void PQCLEAN_KYBER1024_CLEAN_indcpa_keypair(unsigned char *pk,
unsigned char *sk);

void PQCLEAN_KYBER1024_CLEAN_indcpa_enc(unsigned char *c,
const unsigned char *m,
const unsigned char *pk,
const unsigned char *coins);

void PQCLEAN_KYBER1024_CLEAN_indcpa_dec(unsigned char *m,
const unsigned char *c,
const unsigned char *sk);

#endif

+ 100
- 0
crypto_kem/kyber1024/clean/kem.c View File

@@ -0,0 +1,100 @@
#include "api.h"
#include "indcpa.h"
#include "params.h"
#include "randombytes.h"
#include "symmetric.h"
#include "verify.h"

#include <stdlib.h>

/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure Kyber key encapsulation mechanism
*
* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_KYBER1024_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
size_t i;
PQCLEAN_KYBER1024_CLEAN_indcpa_keypair(pk, sk);
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i];
}
hash_h(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
randombytes(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */
return 0;
}

/*************************************************
* Name: crypto_kem_enc
*
* Description: Generates cipher text and shared
* secret for given public key
*
* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_KYBER1024_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
unsigned char buf[2 * KYBER_SYMBYTES];

randombytes(buf, KYBER_SYMBYTES);
hash_h(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */

hash_h(buf + KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
hash_g(kr, buf, 2 * KYBER_SYMBYTES);

PQCLEAN_KYBER1024_CLEAN_indcpa_enc(ct, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */

hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */
kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
return 0;
}

/*************************************************
* Name: crypto_kem_dec
*
* Description: Generates shared secret for given
* cipher text and private key
*
* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0.
*
* On failure, ss will contain a pseudo-random value.
**************************************************/
int PQCLEAN_KYBER1024_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
size_t i;
unsigned char fail;
unsigned char cmp[KYBER_CIPHERTEXTBYTES];
unsigned char buf[2 * KYBER_SYMBYTES];
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES;

PQCLEAN_KYBER1024_CLEAN_indcpa_dec(buf, ct, sk);

for (i = 0; i < KYBER_SYMBYTES; i++) { /* Multitarget countermeasure for coins + contributory KEM */
buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + i]; /* Save hash by storing H(pk) in sk */
}
hash_g(kr, buf, 2 * KYBER_SYMBYTES);

PQCLEAN_KYBER1024_CLEAN_indcpa_enc(cmp, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */

fail = PQCLEAN_KYBER1024_CLEAN_verify(ct, cmp, KYBER_CIPHERTEXTBYTES);

hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */

PQCLEAN_KYBER1024_CLEAN_cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */

kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
return 0;
}

+ 157
- 0
crypto_kem/kyber1024/clean/ntt.c View File

@@ -0,0 +1,157 @@
#include "ntt.h"

#include "params.h"
#include "reduce.h"

#include <stdint.h>

/* Code to generate zetas and zetas_inv used in the number-theoretic transform:

#define KYBER_ROOT_OF_UNITY 17

static const uint16_t tree[128] = {
0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120,
4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124,
2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122,
6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126,
1, 65, 33, 97, 17, 81, 49, 113, 9, 73, 41, 105, 25, 89, 57, 121,
5, 69, 37, 101, 21, 85, 53, 117, 13, 77, 45, 109, 29, 93, 61, 125,
3, 67, 35, 99, 19, 83, 51, 115, 11, 75, 43, 107, 27, 91, 59, 123,
7, 71, 39, 103, 23, 87, 55, 119, 15, 79, 47, 111, 31, 95, 63, 127};


static int16_t fqmul(int16_t a, int16_t b) {
return montgomery_reduce((int32_t)a*b);
}

void init_ntt() {
unsigned int i, j, k;
int16_t tmp[128];

tmp[0] = MONT;
for(i = 1; i < 128; ++i)
tmp[i] = fqmul(tmp[i-1], KYBER_ROOT_OF_UNITY*MONT % KYBER_Q);

for(i = 0; i < 128; ++i)
zetas[i] = tmp[tree[i]];

k = 0;
for(i = 64; i >= 1; i >>= 1)
for(j = i; j < 2*i; ++j)
zetas_inv[k++] = -tmp[128 - tree[j]];

zetas_inv[127] = MONT * (MONT * (KYBER_Q - 1) * ((KYBER_Q - 1)/128) % KYBER_Q) % KYBER_Q;
}

*/
int16_t PQCLEAN_KYBER1024_CLEAN_zetas[128] = {
2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962, 2127, 1855, 1468,
573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017, 732, 608, 1787, 411, 3124, 1758,
1223, 652, 2777, 1015, 2036, 1491, 3047, 1785, 516, 3321, 3009, 2663, 1711, 2167, 126, 1469,
2476, 3239, 3058, 830, 107, 1908, 3082, 2378, 2931, 961, 1821, 2604, 448, 2264, 677, 2054,
2226, 430, 555, 843, 2078, 871, 1550, 105, 422, 587, 177, 3094, 3038, 2869, 1574, 1653,
3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349, 418, 329, 3173, 3254,
817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193, 1218, 1994, 2455, 220, 2142, 1670,
2144, 1799, 2051, 794, 1819, 2475, 2459, 478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628
};

int16_t PQCLEAN_KYBER1024_CLEAN_zetas_inv[128] = {
1701, 1807, 1460, 2371, 2338, 2333, 308, 108, 2851, 870, 854, 1510, 2535, 1278, 1530, 1185,
1659, 1187, 3109, 874, 1335, 2111, 136, 1215, 2945, 1465, 1285, 2007, 2719, 2726, 2232, 2512,
75, 156, 3000, 2911, 2980, 872, 2685, 1590, 2210, 602, 1846, 777, 147, 2170, 2551, 246,
1676, 1755, 460, 291, 235, 3152, 2742, 2907, 3224, 1779, 2458, 1251, 2486, 2774, 2899, 1103,
1275, 2652, 1065, 2881, 725, 1508, 2368, 398, 951, 247, 1421, 3222, 2499, 271, 90, 853,
1860, 3203, 1162, 1618, 666, 320, 8, 2813, 1544, 282, 1838, 1293, 2314, 552, 2677, 2106,
1571, 205, 2918, 1542, 2721, 2597, 2312, 681, 130, 1602, 1871, 829, 2946, 3065, 1325, 2756,
1861, 1474, 1202, 2367, 3147, 1752, 2707, 171, 3127, 3042, 1907, 1836, 1517, 359, 758, 1441
};


/*************************************************
* Name: fqmul
*
* Description: Multiplication followed by Montgomery reduction
*
* Arguments: - int16_t a: first factor
* - int16_t b: second factor
*
* Returns 16-bit integer congruent to a*b*R^{-1} mod q
**************************************************/
static int16_t fqmul(int16_t a, int16_t b) {
return PQCLEAN_KYBER1024_CLEAN_montgomery_reduce((int32_t)a * b);
}

/*************************************************
* Name: ntt
*
* Description: Inplace number-theoretic transform (NTT) in Rq
* input is in standard order, output is in bitreversed order
*
* Arguments: - int16_t *poly: pointer to input/output vector of 256 elements of Zq
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_ntt(int16_t *poly) {
unsigned int len, start, j, k;
int16_t t, zeta;

k = 1;
for (len = 128; len >= 2; len >>= 1) {
for (start = 0; start < 256; start = j + len) {
zeta = PQCLEAN_KYBER1024_CLEAN_zetas[k++];
for (j = start; j < start + len; ++j) {
t = fqmul(zeta, poly[j + len]);
poly[j + len] = poly[j] - t;
poly[j] = poly[j] + t;
}
}
}
}

/*************************************************
* Name: invntt
*
* Description: Inplace inverse number-theoretic transform in Rq
* input is in bitreversed order, output is in standard order
*
* Arguments: - int16_t *poly: pointer to input/output vector of 256 elements of Zq
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_invntt(int16_t *poly) {
unsigned int start, len, j, k;
int16_t t, zeta;

k = 0;
for (len = 2; len <= 128; len <<= 1) {
for (start = 0; start < 256; start = j + len) {
zeta = PQCLEAN_KYBER1024_CLEAN_zetas_inv[k++];
for (j = start; j < start + len; ++j) {
t = poly[j];
poly[j] = PQCLEAN_KYBER1024_CLEAN_barrett_reduce(t + poly[j + len]);
poly[j + len] = t - poly[j + len];
poly[j + len] = fqmul(zeta, poly[j + len]);
}
}
}

for (j = 0; j < 256; ++j) {
poly[j] = fqmul(poly[j], PQCLEAN_KYBER1024_CLEAN_zetas_inv[127]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_basemul
*
* Description: Multiplication of polynomials in Zq[X]/((X^2-zeta))
* used for multiplication of elements in Rq in NTT domain
*
* Arguments: - int16_t r[2]: pointer to the output polynomial
* - const int16_t a[2]: pointer to the first factor
* - const int16_t b[2]: pointer to the second factor
* - int16_t zeta: integer defining the reduction polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta) {
r[0] = fqmul(a[1], b[1]);
r[0] = fqmul(r[0], zeta);
r[0] += fqmul(a[0], b[0]);

r[1] = fqmul(a[0], b[1]);
r[1] += fqmul(a[1], b[0]);
}

+ 13
- 0
crypto_kem/kyber1024/clean/ntt.h View File

@@ -0,0 +1,13 @@
#ifndef NTT_H
#define NTT_H

#include <stdint.h>

extern int16_t PQCLEAN_KYBER1024_CLEAN_zetas[128];
extern int16_t PQCLEAN_KYBER1024_CLEAN_zetas_inv[128];

void PQCLEAN_KYBER1024_CLEAN_ntt(int16_t *poly);
void PQCLEAN_KYBER1024_CLEAN_invntt(int16_t *poly);
void PQCLEAN_KYBER1024_CLEAN_basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta);

#endif

+ 31
- 0
crypto_kem/kyber1024/clean/params.h View File

@@ -0,0 +1,31 @@
#ifndef PARAMS_H
#define PARAMS_H

#define KYBER_K 4 /* Change this for different security strengths */

/* Don't change parameters below this line */

#define KYBER_N 256
#define KYBER_Q 3329

#define KYBER_ETA 2

#define KYBER_SYMBYTES 32 /* size in bytes of hashes, and seeds */
#define KYBER_SSBYTES 32 /* size in bytes of shared key */

#define KYBER_POLYBYTES 384
#define KYBER_POLYVECBYTES (KYBER_K * KYBER_POLYBYTES)

#define KYBER_POLYCOMPRESSEDBYTES 160
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_K * 352)

#define KYBER_INDCPA_MSGBYTES KYBER_SYMBYTES
#define KYBER_INDCPA_PUBLICKEYBYTES (KYBER_POLYVECBYTES + KYBER_SYMBYTES)
#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 + 2*KYBER_SYMBYTES) /* 32 bytes of additional space to save H(pk) */
#define KYBER_CIPHERTEXTBYTES KYBER_INDCPA_BYTES

#endif

+ 289
- 0
crypto_kem/kyber1024/clean/poly.c View File

@@ -0,0 +1,289 @@
#include "poly.h"

#include "cbd.h"
#include "ntt.h"
#include "params.h"
#include "reduce.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_compress
*
* Description: Compression and subsequent serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYCOMPRESSEDBYTES bytes)
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_compress(unsigned char *r, poly *a) {
uint8_t t[8];
int i, j, k = 0;

PQCLEAN_KYBER1024_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_N; i += 8) {
for (j = 0; j < 8; j++) {
t[j] = ((((uint32_t)a->coeffs[i + j] << 5) + KYBER_Q / 2) / KYBER_Q) & 31;
}

r[k] = t[0] | (t[1] << 5);
r[k + 1] = (t[1] >> 3) | (t[2] << 2) | (t[3] << 7);
r[k + 2] = (t[3] >> 1) | (t[4] << 4);
r[k + 3] = (t[4] >> 4) | (t[5] << 1) | (t[6] << 6);
r[k + 4] = (t[6] >> 2) | (t[7] << 3);
k += 5;
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_decompress
*
* Description: De-serialization and subsequent decompression of a polynomial;
* approximate inverse of PQCLEAN_KYBER1024_CLEAN_poly_compress
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array (of length KYBER_POLYCOMPRESSEDBYTES bytes)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_decompress(poly *r, const unsigned char *a) {
int i;
for (i = 0; i < KYBER_N; i += 8) {
r->coeffs[i + 0] = (((a[0] & 31) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 1] = ((((a[0] >> 5) | ((a[1] & 3) << 3)) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 2] = ((((a[1] >> 2) & 31) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 3] = ((((a[1] >> 7) | ((a[2] & 15) << 1)) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 4] = ((((a[2] >> 4) | ((a[3] & 1) << 4)) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 5] = ((((a[3] >> 1) & 31) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 6] = ((((a[3] >> 6) | ((a[4] & 7) << 2)) * KYBER_Q) + 16) >> 5;
r->coeffs[i + 7] = (((a[4] >> 3) * KYBER_Q) + 16) >> 5;
a += 5;
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_tobytes
*
* Description: Serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYBYTES bytes)
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_tobytes(unsigned char *r, poly *a) {
int i;
uint16_t t0, t1;

PQCLEAN_KYBER1024_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_N / 2; i++) {
t0 = a->coeffs[2 * i];
t1 = a->coeffs[2 * i + 1];
r[3 * i] = t0 & 0xff;
r[3 * i + 1] = (t0 >> 8) | ((t1 & 0xf) << 4);
r[3 * i + 2] = (t1 >> 4) & 0xff;
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_frombytes
*
* Description: De-serialization of a polynomial;
* inverse of PQCLEAN_KYBER1024_CLEAN_poly_tobytes
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array (of KYBER_POLYBYTES bytes)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_frombytes(poly *r, const unsigned char *a) {
int i;

for (i = 0; i < KYBER_N / 2; i++) {
r->coeffs[2 * i] = a[3 * i] | ((uint16_t)a[3 * i + 1] & 0x0f) << 8;
r->coeffs[2 * i + 1] = a[3 * i + 1] >> 4 | ((uint16_t)a[3 * i + 2] & 0xff) << 4;
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_getnoise
*
* Description: Sample a polynomial deterministically from a seed and a nonce,
* with output polynomial close to centered binomial distribution
* with parameter KYBER_ETA
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *seed: pointer to input seed (pointing to array of length KYBER_SYMBYTES bytes)
* - unsigned char nonce: one-byte input nonce
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) {
unsigned char buf[KYBER_ETA * KYBER_N / 4];

prf(buf, KYBER_ETA * KYBER_N / 4, seed, nonce);
PQCLEAN_KYBER1024_CLEAN_cbd(r, buf);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_ntt
*
* Description: Computes negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in normal order, output in bitreversed order
*
* Arguments: - uint16_t *r: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_ntt(poly *r) {
PQCLEAN_KYBER1024_CLEAN_ntt(r->coeffs);
PQCLEAN_KYBER1024_CLEAN_poly_reduce(r);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_invntt
*
* Description: Computes inverse of negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in bitreversed order, output in normal order
*
* Arguments: - uint16_t *a: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_invntt(poly *r) {
PQCLEAN_KYBER1024_CLEAN_invntt(r->coeffs);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_basemul
*
* Description: Multiplication of two polynomials in NTT domain
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_basemul(poly *r, const poly *a, const poly *b) {
unsigned int i;

for (i = 0; i < KYBER_N / 4; ++i) {
PQCLEAN_KYBER1024_CLEAN_basemul(r->coeffs + 4 * i, a->coeffs + 4 * i, b->coeffs + 4 * i, PQCLEAN_KYBER1024_CLEAN_zetas[64 + i]);
PQCLEAN_KYBER1024_CLEAN_basemul(r->coeffs + 4 * i + 2, a->coeffs + 4 * i + 2, b->coeffs + 4 * i + 2, - PQCLEAN_KYBER1024_CLEAN_zetas[64 + i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_frommont
*
* Description: Inplace conversion of all coefficients of a polynomial
* from Montgomery domain to normal domain
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_frommont(poly *r) {
int i;
const int16_t f = (1ULL << 32) % KYBER_Q;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER1024_CLEAN_montgomery_reduce((int32_t)r->coeffs[i] * f);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_reduce
*
* Description: Applies Barrett reduction to all coefficients of a polynomial
* for details of the Barrett reduction see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_reduce(poly *r) {
int i;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER1024_CLEAN_barrett_reduce(r->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_csubq
*
* Description: Applies conditional subtraction of q to each coefficient of a polynomial
* for details of conditional subtraction of q see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_csubq(poly *r) {
int i;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER1024_CLEAN_csubq(r->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_add
*
* Description: Add two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_add(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_sub
*
* Description: Subtract two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = a->coeffs[i] - b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_frommsg
*
* Description: Convert 32-byte message to polynomial
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *msg: pointer to input message
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) {
int i, j;
uint16_t mask;

for (i = 0; i < KYBER_SYMBYTES; i++) {
for (j = 0; j < 8; j++) {
mask = -((msg[i] >> j) & 1);
r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2);
}
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_poly_tomsg
*
* Description: Convert polynomial to 32-byte message
*
* Arguments: - unsigned char *msg: pointer to output message
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) {
uint16_t t;
int i, j;

PQCLEAN_KYBER1024_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_SYMBYTES; i++) {
msg[i] = 0;
for (j = 0; j < 8; j++) {
t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
msg[i] |= t << j;
}
}
}

+ 38
- 0
crypto_kem/kyber1024/clean/poly.h View File

@@ -0,0 +1,38 @@
#ifndef POLY_H
#define POLY_H

#include "params.h"

#include <stdint.h>

/*
* Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial
* coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1]
*/
typedef struct {
int16_t coeffs[KYBER_N];
} poly;

void PQCLEAN_KYBER1024_CLEAN_poly_compress(unsigned char *r, poly *a);
void PQCLEAN_KYBER1024_CLEAN_poly_decompress(poly *r, const unsigned char *a);

void PQCLEAN_KYBER1024_CLEAN_poly_tobytes(unsigned char *r, poly *a);
void PQCLEAN_KYBER1024_CLEAN_poly_frombytes(poly *r, const unsigned char *a);

void PQCLEAN_KYBER1024_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]);
void PQCLEAN_KYBER1024_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a);

void PQCLEAN_KYBER1024_CLEAN_poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce);

void PQCLEAN_KYBER1024_CLEAN_poly_ntt(poly *r);
void PQCLEAN_KYBER1024_CLEAN_poly_invntt(poly *r);
void PQCLEAN_KYBER1024_CLEAN_poly_basemul(poly *r, const poly *a, const poly *b);
void PQCLEAN_KYBER1024_CLEAN_poly_frommont(poly *r);

void PQCLEAN_KYBER1024_CLEAN_poly_reduce(poly *r);
void PQCLEAN_KYBER1024_CLEAN_poly_csubq(poly *r);

void PQCLEAN_KYBER1024_CLEAN_poly_add(poly *r, const poly *a, const poly *b);
void PQCLEAN_KYBER1024_CLEAN_poly_sub(poly *r, const poly *a, const poly *b);

#endif

+ 196
- 0
crypto_kem/kyber1024/clean/polyvec.c View File

@@ -0,0 +1,196 @@
#include "polyvec.h"

#include "poly.h"

#include <stdint.h>

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_compress
*
* Description: Compress and serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECCOMPRESSEDBYTES)
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_compress(unsigned char *r, polyvec *a) {
int i, j, k;

PQCLEAN_KYBER1024_CLEAN_polyvec_csubq(a);

uint16_t t[8];
for (i = 0; i < KYBER_K; i++) {
for (j = 0; j < KYBER_N / 8; j++) {
for (k = 0; k < 8; k++) {
t[k] = ((((uint32_t)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)) & 0xff;
r[11 * j + 2] = ((t[1] >> 5) | ((t[2] & 0x03) << 6)) & 0xff;
r[11 * j + 3] = (t[2] >> 2) & 0xff;
r[11 * j + 4] = ((t[2] >> 10) | ((t[3] & 0x7f) << 1)) & 0xff;
r[11 * j + 5] = ((t[3] >> 7) | ((t[4] & 0x0f) << 4)) & 0xff;
r[11 * j + 6] = ((t[4] >> 4) | ((t[5] & 0x01) << 7)) & 0xff;
r[11 * j + 7] = (t[5] >> 1) & 0xff;
r[11 * j + 8] = ((t[5] >> 9) | ((t[6] & 0x3f) << 2)) & 0xff;
r[11 * j + 9] = ((t[6] >> 6) | ((t[7] & 0x07) << 5)) & 0xff;
r[11 * j + 10] = (t[7] >> 3) & 0xff;
}
r += 352;
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_decompress
*
* Description: De-serialize and decompress vector of polynomials;
* approximate inverse of PQCLEAN_KYBER1024_CLEAN_polyvec_compress
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - unsigned char *a: pointer to input byte array (of length KYBER_POLYVECCOMPRESSEDBYTES)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_K; 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;
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_tobytes
*
* Description: Serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECBYTES)
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_tobytes(unsigned char *r, polyvec *a) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_tobytes(r + i * KYBER_POLYBYTES, &a->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_frombytes
*
* Description: De-serialize vector of polynomials;
* inverse of PQCLEAN_KYBER1024_CLEAN_polyvec_tobytes
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const polyvec *a: pointer to input vector of polynomials (of length KYBER_POLYVECBYTES)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_frombytes(&r->vec[i], a + i * KYBER_POLYBYTES);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_ntt
*
* Description: Apply forward NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_ntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_ntt(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_invntt
*
* Description: Apply inverse NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_invntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_invntt(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc
*
* Description: Pointwise multiply elements of a and b and accumulate into r
*
* Arguments: - poly *r: pointer to output polynomial
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b) {
int i;
poly t;

PQCLEAN_KYBER1024_CLEAN_poly_basemul(r, &a->vec[0], &b->vec[0]);
for (i = 1; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_basemul(&t, &a->vec[i], &b->vec[i]);
PQCLEAN_KYBER1024_CLEAN_poly_add(r, r, &t);
}

PQCLEAN_KYBER1024_CLEAN_poly_reduce(r);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_reduce
*
* Description: Applies Barrett reduction to each coefficient
* of each element of a vector of polynomials
* for details of the Barrett reduction see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_reduce(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_reduce(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_csubq
*
* Description: Applies conditional subtraction of q to each coefficient
* of each element of a vector of polynomials
* for details of conditional subtraction of q see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_csubq(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_csubq(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_polyvec_add
*
* Description: Add vectors of polynomials
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER1024_CLEAN_poly_add(&r->vec[i], &a->vec[i], &b->vec[i]);
}
}

+ 27
- 0
crypto_kem/kyber1024/clean/polyvec.h View File

@@ -0,0 +1,27 @@
#ifndef POLYVEC_H
#define POLYVEC_H

#include "params.h"
#include "poly.h"

typedef struct {
poly vec[KYBER_K];
} polyvec;

void PQCLEAN_KYBER1024_CLEAN_polyvec_compress(unsigned char *r, polyvec *a);
void PQCLEAN_KYBER1024_CLEAN_polyvec_decompress(polyvec *r, const unsigned char *a);

void PQCLEAN_KYBER1024_CLEAN_polyvec_tobytes(unsigned char *r, polyvec *a);
void PQCLEAN_KYBER1024_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a);

void PQCLEAN_KYBER1024_CLEAN_polyvec_ntt(polyvec *r);
void PQCLEAN_KYBER1024_CLEAN_polyvec_invntt(polyvec *r);

void PQCLEAN_KYBER1024_CLEAN_polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b);

void PQCLEAN_KYBER1024_CLEAN_polyvec_reduce(polyvec *r);
void PQCLEAN_KYBER1024_CLEAN_polyvec_csubq(polyvec *r);

void PQCLEAN_KYBER1024_CLEAN_polyvec_add(polyvec *r, const polyvec *a, const polyvec *b);

#endif

+ 62
- 0
crypto_kem/kyber1024/clean/reduce.c View File

@@ -0,0 +1,62 @@
#include "reduce.h"

#include "params.h"

#include <stdint.h>

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_montgomery_reduce
*
* Description: Montgomery reduction; given a 32-bit integer a, computes
* 16-bit integer congruent to a * R^-1 mod q,
* where R=2^16
*
* Arguments: - int32_t a: input integer to be reduced; has to be in {-q2^15,...,q2^15-1}
*
* Returns: integer in {-q+1,...,q-1} congruent to a * R^-1 modulo q.
**************************************************/
int16_t PQCLEAN_KYBER1024_CLEAN_montgomery_reduce(int32_t a) {
int32_t t;
int16_t u;

u = (int16_t)(a * QINV);
t = (int32_t)u * KYBER_Q;
t = a - t;
t >>= 16;
return (int16_t)t;
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_barrett_reduce
*
* Description: Barrett reduction; given a 16-bit integer a, computes
* 16-bit integer congruent to a mod q in {0,...,q}
*
* Arguments: - int16_t a: input integer to be reduced
*
* Returns: integer in {0,...,q} congruent to a modulo q.
**************************************************/
int16_t PQCLEAN_KYBER1024_CLEAN_barrett_reduce(int16_t a) {
int32_t t;
const int32_t v = (1U << 26) / KYBER_Q + 1;

t = v * a;
t >>= 26;
t *= KYBER_Q;
return (int16_t)(a - t);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_csubq
*
* Description: Conditionallly subtract q
*
* Arguments: - int16_t x: input integer
*
* Returns: a - q if a >= q, else a
**************************************************/
int16_t PQCLEAN_KYBER1024_CLEAN_csubq(int16_t a) {
a -= KYBER_Q;
a += (a >> 15) & KYBER_Q;
return a;
}

+ 15
- 0
crypto_kem/kyber1024/clean/reduce.h View File

@@ -0,0 +1,15 @@
#ifndef REDUCE_H
#define REDUCE_H

#include <stdint.h>

#define MONT 2285 // 2^16 % Q
#define QINV 62209 // q^(-1) mod 2^16

int16_t PQCLEAN_KYBER1024_CLEAN_montgomery_reduce(int32_t a);

int16_t PQCLEAN_KYBER1024_CLEAN_barrett_reduce(int16_t a);

int16_t PQCLEAN_KYBER1024_CLEAN_csubq(int16_t a);

#endif

+ 64
- 0
crypto_kem/kyber1024/clean/symmetric-fips202.c View File

@@ -0,0 +1,64 @@
#include "fips202.h"
#include "symmetric.h"

#include <stdlib.h>

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb
*
* Description: Absorb step of the SHAKE128 specialized for the Kyber context.
*
* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state
* - const unsigned char *input: pointer to KYBER_SYMBYTES input to be absorbed into s
* - unsigned char i additional byte of input
* - unsigned char j additional byte of input
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y) {
unsigned char extseed[KYBER_SYMBYTES + 2];
int i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extseed[i] = input[i];
}
extseed[i++] = x;
extseed[i] = y;
shake128_absorb(s->s, extseed, KYBER_SYMBYTES + 2);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks
*
* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of SHAKE128_RATE bytes each.
* Modifies the state. Can be called multiple times to keep squeezing,
* i.e., is incremental.
*
* Arguments: - unsigned char *output: pointer to output blocks
* - size_t nblocks: number of blocks to be squeezed (written to output)
* - keccak_state *s: pointer to in/output Keccak state
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s) {
shake128_squeezeblocks(output, nblocks, s->s);
}

/*************************************************
* Name: PQCLEAN_KYBER1024_CLEAN_shake256_prf
*
* Description: Usage of SHAKE256 as a PRF, concatenates secret and public input
* and then generates outlen bytes of SHAKE256 output
*
* Arguments: - unsigned char *output: pointer to output
* - size_t outlen: number of requested output bytes
* - const unsigned char * key: pointer to the key (of length KYBER_SYMBYTES)
* - const unsigned char nonce: single-byte nonce (public PRF input)
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce) {
unsigned char extkey[KYBER_SYMBYTES + 1];
size_t i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extkey[i] = key[i];
}
extkey[i] = nonce;

shake256(output, outlen, extkey, KYBER_SYMBYTES + 1);
}

+ 28
- 0
crypto_kem/kyber1024/clean/symmetric.h View File

@@ -0,0 +1,28 @@
#ifndef SYMMETRIC_H
#define SYMMETRIC_H

#include "fips202.h"
#include "params.h"

#include <stdlib.h>

typedef struct {
uint64_t s[25];
} keccak_state;

void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y);
void PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s);
void PQCLEAN_KYBER1024_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce);

#define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES)
#define hash_g(OUT, IN, INBYTES) sha3_512(OUT, IN, INBYTES)
#define xof_absorb(STATE, IN, X, Y) PQCLEAN_KYBER1024_CLEAN_kyber_shake128_absorb(STATE, IN, X, Y)
#define xof_squeezeblocks(OUT, OUTBLOCKS, STATE) PQCLEAN_KYBER1024_CLEAN_kyber_shake128_squeezeblocks(OUT, OUTBLOCKS, STATE)
#define prf(OUT, OUTBYTES, KEY, NONCE) PQCLEAN_KYBER1024_CLEAN_shake256_prf(OUT, OUTBYTES, KEY, NONCE)
#define kdf(OUT, IN, INBYTES) shake256(OUT, KYBER_SSBYTES, IN, INBYTES)

#define XOF_BLOCKBYTES 168

typedef keccak_state xof_state;

#endif /* SYMMETRIC_H */

+ 51
- 0
crypto_kem/kyber1024/clean/verify.c View File

@@ -0,0 +1,51 @@
#include "verify.h"

#include <stdint.h>
#include <stdlib.h>

/*************************************************
* Name: verify
*
* Description: Compare two arrays for equality in constant time.
*
* Arguments: const unsigned char *a: pointer to first byte array
* const unsigned char *b: pointer to second byte array
* size_t len: length of the byte arrays
*
* Returns 0 if the byte arrays are equal, 1 otherwise
**************************************************/
unsigned char PQCLEAN_KYBER1024_CLEAN_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 + 1); // Two's complement
r >>= 63;
return (unsigned char)r;
}

/*************************************************
* Name: cmov
*
* Description: Copy len bytes from x to r if b is 1;
* don't modify x if b is 0. Requires b to be in {0,1};
* assumes two's complement representation of negative integers.
* Runs in constant time.
*
* Arguments: unsigned char *r: pointer to output byte array
* const unsigned char *x: pointer to input byte array
* size_t len: Amount of bytes to be copied
* unsigned char b: Condition bit; has to be in {0,1}
**************************************************/
void PQCLEAN_KYBER1024_CLEAN_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]);
}
}

+ 10
- 0
crypto_kem/kyber1024/clean/verify.h View File

@@ -0,0 +1,10 @@
#ifndef VERIFY_H
#define VERIFY_H

#include <stdio.h>

unsigned char PQCLEAN_KYBER1024_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);

void PQCLEAN_KYBER1024_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);

#endif

+ 22
- 0
crypto_kem/kyber512/META.yml View File

@@ -0,0 +1,22 @@
name: Kyber512
type: kem
claimed-nist-level: 1
length-public-key: 800
length-ciphertext: 736
length-secret-key: 1632
length-shared-secret: 32
nistkat-sha256: bdd9b46001de4595a4f185aec8d5d04d217705e65e10711c99fa3f0ac3d61c21
principal-submitter: Peter Schwabe
auxiliary-submitters:
- Roberto Avanzi
- Joppe Bos
- Léo Ducas
- Eike Kiltz
- Tancrède Lepoint
- Vadim Lyubashevsky
- John M. Schanck
- Gregor Seiler
- Damien Stehlé
implementations:
- name: clean
version: https://github.com/pq-crystals/kyber/commit/46e283ab575ec92dfe82fb12229ae2d9d6246682

+ 15
- 0
crypto_kem/kyber512/clean/LICENSE View File

@@ -0,0 +1,15 @@
Public Domain
Authors: Joppe Bos,
Léo Ducas,
Eike Kiltz ,
Tancrède Lepoint,
Vadim Lyubashevsky,
John Schanck,
Peter Schwabe,
Gregor Seiler,
Damien Stehlé

For Keccak and AES we are using public-domain
code from sources and by authors listed in
comments on top of the respective files.


+ 19
- 0
crypto_kem/kyber512/clean/Makefile View File

@@ -0,0 +1,19 @@
# This Makefile can be used with GNU Make or BSD Make

LIB=libkyber512_clean.a
HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h symmetric.h
OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o verify.o symmetric-fips202.o

CFLAGS=-Wall -O3 -Wmissing-prototypes -Wextra -Wpedantic -Werror -std=c99 -I../../../common $(EXTRAFLAGS)

all: $(LIB)

%.o: %.c $(HEADERS)
$(CC) $(CFLAGS) -c -o $@ $<

$(LIB): $(OBJECTS)
$(AR) -r $@ $(OBJECTS)

clean:
$(RM) $(OBJECTS)
$(RM) $(LIB)

+ 19
- 0
crypto_kem/kyber512/clean/Makefile.Microsoft_nmake View File

@@ -0,0 +1,19 @@
# This Makefile can be used with Microsoft Visual Studio's nmake using the command:
# nmake /f Makefile.Microsoft_nmake

LIBRARY=libkyber512_clean.lib
OBJECTS=cbd.obj indcpa.obj kem.obj ntt.obj poly.obj polyvec.obj reduce.obj verify.obj symmetric-fips202.obj

CFLAGS=/nologo /I ..\..\..\common /W4 /WX

all: $(LIBRARY)

# Make sure objects are recompiled if headers change.
$(OBJECTS): *.h

$(LIBRARY): $(OBJECTS)
LIB.EXE /NOLOGO /WX /OUT:$@ $**

clean:
-DEL $(OBJECTS)
-DEL $(LIBRARY)

+ 18
- 0
crypto_kem/kyber512/clean/api.h View File

@@ -0,0 +1,18 @@
#ifndef PQCLEAN_KYBER512_CLEAN_API_H
#define PQCLEAN_KYBER512_CLEAN_API_H

#define PQCLEAN_KYBER512_CLEAN_CRYPTO_SECRETKEYBYTES 1632
#define PQCLEAN_KYBER512_CLEAN_CRYPTO_PUBLICKEYBYTES 800
#define PQCLEAN_KYBER512_CLEAN_CRYPTO_CIPHERTEXTBYTES 736
#define PQCLEAN_KYBER512_CLEAN_CRYPTO_BYTES 32

#define PQCLEAN_KYBER512_CLEAN_CRYPTO_ALGNAME "Kyber512"

int PQCLEAN_KYBER512_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);

int PQCLEAN_KYBER512_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);

int PQCLEAN_KYBER512_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);


#endif

+ 53
- 0
crypto_kem/kyber512/clean/cbd.c View File

@@ -0,0 +1,53 @@
#include "cbd.h"

#include "params.h"

#include <stdint.h>

/*************************************************
* Name: load32_littleendian
*
* Description: load bytes into a 32-bit integer
* in little-endian order
*
* Arguments: - const unsigned char *x: pointer to input byte array
*
* Returns 32-bit unsigned integer loaded from x
**************************************************/
static uint32_t load32_littleendian(const unsigned char *x) {
uint32_t r;
r = (uint32_t)x[0];
r |= (uint32_t)x[1] << 8;
r |= (uint32_t)x[2] << 16;
r |= (uint32_t)x[3] << 24;
return r;
}

/*************************************************
* Name: cbd
*
* Description: Given an array of uniformly random bytes, compute
* polynomial with coefficients distributed according to
* a centered binomial distribution with parameter KYBER_ETA
* specialized for KYBER_ETA=2
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *buf: pointer to input byte array
**************************************************/
void PQCLEAN_KYBER512_CLEAN_cbd(poly *r, const unsigned char *buf) {
uint32_t d, t;
int16_t a, b;
int i, j;

for (i = 0; i < KYBER_N / 8; i++) {
t = load32_littleendian(buf + 4 * i);
d = t & 0x55555555;
d += (t >> 1) & 0x55555555;

for (j = 0; j < 8; j++) {
a = (d >> 4 * j) & 0x3;
b = (d >> (4 * j + 2)) & 0x3;
r->coeffs[8 * i + j] = a - b;
}
}
}

+ 8
- 0
crypto_kem/kyber512/clean/cbd.h View File

@@ -0,0 +1,8 @@
#ifndef CBD_H
#define CBD_H

#include "poly.h"

void PQCLEAN_KYBER512_CLEAN_cbd(poly *r, const unsigned char *buf);

#endif

+ 305
- 0
crypto_kem/kyber512/clean/indcpa.c View File

@@ -0,0 +1,305 @@
#include "indcpa.h"

#include "ntt.h"
#include "poly.h"
#include "polyvec.h"
#include "randombytes.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: pack_pk
*
* Description: Serialize the public key as concatenation of the
* serialized vector of polynomials pk
* and the public seed used to generate the matrix A.
*
* Arguments: unsigned char *r: pointer to the output serialized public key
* const poly *pk: pointer to the input public-key polynomial
* const unsigned char *seed: pointer to the input public seed
**************************************************/
static void pack_pk(unsigned char *r, polyvec *pk, const unsigned char *seed) {
int i;
PQCLEAN_KYBER512_CLEAN_polyvec_tobytes(r, pk);
for (i = 0; i < KYBER_SYMBYTES; i++) {
r[i + KYBER_POLYVECBYTES] = seed[i];
}
}

/*************************************************
* Name: unpack_pk
*
* Description: De-serialize public key from a byte array;
* approximate inverse of pack_pk
*
* Arguments: - polyvec *pk: pointer to output public-key vector of polynomials
* - unsigned char *seed: pointer to output seed to generate matrix A
* - const unsigned char *packedpk: pointer to input serialized public key
**************************************************/
static void unpack_pk(polyvec *pk, unsigned char *seed, const unsigned char *packedpk) {
int i;
PQCLEAN_KYBER512_CLEAN_polyvec_frombytes(pk, packedpk);
for (i = 0; i < KYBER_SYMBYTES; i++) {
seed[i] = packedpk[i + KYBER_POLYVECBYTES];
}
}

/*************************************************
* Name: pack_sk
*
* Description: Serialize the secret key
*
* Arguments: - unsigned char *r: pointer to output serialized secret key
* - const polyvec *sk: pointer to input vector of polynomials (secret key)
**************************************************/
static void pack_sk(unsigned char *r, polyvec *sk) {
PQCLEAN_KYBER512_CLEAN_polyvec_tobytes(r, sk);
}

/*************************************************
* Name: unpack_sk
*
* Description: De-serialize the secret key;
* inverse of pack_sk
*
* Arguments: - polyvec *sk: pointer to output vector of polynomials (secret key)
* - const unsigned char *packedsk: pointer to input serialized secret key
**************************************************/
static void unpack_sk(polyvec *sk, const unsigned char *packedsk) {
PQCLEAN_KYBER512_CLEAN_polyvec_frombytes(sk, packedsk);
}

/*************************************************
* Name: pack_ciphertext
*
* Description: Serialize the ciphertext as concatenation of the
* compressed and serialized vector of polynomials b
* and the compressed and serialized polynomial v
*
* Arguments: unsigned char *r: pointer to the output serialized ciphertext
* const poly *pk: pointer to the input vector of polynomials b
* const unsigned char *seed: pointer to the input polynomial v
**************************************************/
static void pack_ciphertext(unsigned char *r, polyvec *b, poly *v) {
PQCLEAN_KYBER512_CLEAN_polyvec_compress(r, b);
PQCLEAN_KYBER512_CLEAN_poly_compress(r + KYBER_POLYVECCOMPRESSEDBYTES, v);
}

/*************************************************
* Name: unpack_ciphertext
*
* Description: De-serialize and decompress ciphertext from a byte array;
* approximate inverse of pack_ciphertext
*
* Arguments: - polyvec *b: pointer to the output vector of polynomials b
* - poly *v: pointer to the output polynomial v
* - const unsigned char *c: pointer to the input serialized ciphertext
**************************************************/
static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) {
PQCLEAN_KYBER512_CLEAN_polyvec_decompress(b, c);
PQCLEAN_KYBER512_CLEAN_poly_decompress(v, c + KYBER_POLYVECCOMPRESSEDBYTES);
}

/*************************************************
* Name: rej_uniform
*
* Description: Run rejection sampling on uniform random bytes to generate
* uniform random integers mod q
*
* Arguments: - int16_t *r: pointer to output buffer
* - unsigned int len: requested number of 16-bit integers (uniform mod q)
* - const unsigned char *buf: pointer to input buffer (assumed to be uniform random bytes)
* - unsigned int buflen: length of input buffer in bytes
*
* Returns number of sampled 16-bit integers (at most len)
**************************************************/
static unsigned int rej_uniform(int16_t *r, unsigned int len, const unsigned char *buf, unsigned int buflen) {
unsigned int ctr, pos;
uint16_t val;

ctr = pos = 0;
while (ctr < len && pos + 2 <= buflen) {
val = buf[pos] | ((uint16_t)buf[pos + 1] << 8);
pos += 2;

if (val < 19 * KYBER_Q) {
val -= (val >> 12) * KYBER_Q; // Barrett reduction
r[ctr++] = (int16_t)val;
}
}

return ctr;
}

#define gen_a(A,B) PQCLEAN_KYBER512_CLEAN_gen_matrix(A,B,0)
#define gen_at(A,B) PQCLEAN_KYBER512_CLEAN_gen_matrix(A,B,1)

#define GENMATRIX_MAXNBLOCKS ((530 + XOF_BLOCKBYTES) / XOF_BLOCKBYTES) /* 530 is expected number of required bytes */


/*************************************************
* Name: gen_matrix
*
* Description: Deterministically generate matrix A (or the transpose of A)
* from a seed. Entries of the matrix are polynomials that look
* uniformly random. Performs rejection sampling on output of
* a XOF
*
* Arguments: - polyvec *a: pointer to ouptput matrix A
* - const unsigned char *seed: pointer to input seed
* - int transposed: boolean deciding whether A or A^T is generated
**************************************************/
static void PQCLEAN_KYBER512_CLEAN_gen_matrix(polyvec *a, const unsigned char *seed, int transposed) {
unsigned int ctr;
unsigned char i, j;
unsigned char buf[XOF_BLOCKBYTES * GENMATRIX_MAXNBLOCKS + 1];
xof_state state;

for (i = 0; i < KYBER_K; i++) {
for (j = 0; j < KYBER_K; j++) {
if (transposed) {
xof_absorb(&state, seed, i, j);
} else {
xof_absorb(&state, seed, j, i);
}

xof_squeezeblocks(buf, GENMATRIX_MAXNBLOCKS, &state);
ctr = rej_uniform(a[i].vec[j].coeffs, KYBER_N, buf, GENMATRIX_MAXNBLOCKS * XOF_BLOCKBYTES);

while (ctr < KYBER_N) {
xof_squeezeblocks(buf, 1, &state);
ctr += rej_uniform(a[i].vec[j].coeffs + ctr, KYBER_N - ctr, buf, XOF_BLOCKBYTES);
}
}
}
}

/*************************************************
* Name: indcpa_keypair
*
* Description: Generates public and private key for the CPA-secure
* public-key encryption scheme underlying Kyber
*
* Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_indcpa_keypair(unsigned char *pk, unsigned char *sk) {
polyvec a[KYBER_K], e, pkpv, skpv;
unsigned char buf[2 * KYBER_SYMBYTES];
unsigned char *publicseed = buf;
unsigned char *noiseseed = buf + KYBER_SYMBYTES;
int i;
unsigned char nonce = 0;

randombytes(buf, KYBER_SYMBYTES);
hash_g(buf, buf, KYBER_SYMBYTES);

gen_a(a, publicseed);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_getnoise(skpv.vec + i, noiseseed, nonce++);
}
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_getnoise(e.vec + i, noiseseed, nonce++);
}

PQCLEAN_KYBER512_CLEAN_polyvec_ntt(&skpv);
PQCLEAN_KYBER512_CLEAN_polyvec_ntt(&e);

// matrix-vector multiplication
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc(&pkpv.vec[i], &a[i], &skpv);
PQCLEAN_KYBER512_CLEAN_poly_frommont(&pkpv.vec[i]);
}

PQCLEAN_KYBER512_CLEAN_polyvec_add(&pkpv, &pkpv, &e);
PQCLEAN_KYBER512_CLEAN_polyvec_reduce(&pkpv);

pack_sk(sk, &skpv);
pack_pk(pk, &pkpv, publicseed);
}

/*************************************************
* Name: indcpa_enc
*
* Description: Encryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *c: pointer to output ciphertext (of length KYBER_INDCPA_BYTES bytes)
* - const unsigned char *m: pointer to input message (of length KYBER_INDCPA_MSGBYTES bytes)
* - const unsigned char *pk: pointer to input public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - const unsigned char *coin: pointer to input random coins used as seed (of length KYBER_SYMBYTES bytes)
* to deterministically generate all randomness
**************************************************/
void PQCLEAN_KYBER512_CLEAN_indcpa_enc(unsigned char *c,
const unsigned char *m,
const unsigned char *pk,
const unsigned char *coins) {
polyvec sp, pkpv, ep, at[KYBER_K], bp;
poly v, k, epp;
unsigned char seed[KYBER_SYMBYTES];
int i;
unsigned char nonce = 0;

unpack_pk(&pkpv, seed, pk);
PQCLEAN_KYBER512_CLEAN_poly_frommsg(&k, m);
gen_at(at, seed);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_getnoise(sp.vec + i, coins, nonce++);
}
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_getnoise(ep.vec + i, coins, nonce++);
}
PQCLEAN_KYBER512_CLEAN_poly_getnoise(&epp, coins, nonce++);

PQCLEAN_KYBER512_CLEAN_polyvec_ntt(&sp);

// matrix-vector multiplication
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc(&bp.vec[i], &at[i], &sp);
}

PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc(&v, &pkpv, &sp);

PQCLEAN_KYBER512_CLEAN_polyvec_invntt(&bp);
PQCLEAN_KYBER512_CLEAN_poly_invntt(&v);

PQCLEAN_KYBER512_CLEAN_polyvec_add(&bp, &bp, &ep);
PQCLEAN_KYBER512_CLEAN_poly_add(&v, &v, &epp);
PQCLEAN_KYBER512_CLEAN_poly_add(&v, &v, &k);
PQCLEAN_KYBER512_CLEAN_polyvec_reduce(&bp);
PQCLEAN_KYBER512_CLEAN_poly_reduce(&v);

pack_ciphertext(c, &bp, &v);
}

/*************************************************
* Name: indcpa_dec
*
* Description: Decryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *m: pointer to output decrypted message (of length KYBER_INDCPA_MSGBYTES)
* - const unsigned char *c: pointer to input ciphertext (of length KYBER_INDCPA_BYTES)
* - const unsigned char *sk: pointer to input secret key (of length KYBER_INDCPA_SECRETKEYBYTES)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_indcpa_dec(unsigned char *m,
const unsigned char *c,
const unsigned char *sk) {
polyvec bp, skpv;
poly v, mp;

unpack_ciphertext(&bp, &v, c);
unpack_sk(&skpv, sk);

PQCLEAN_KYBER512_CLEAN_polyvec_ntt(&bp);
PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc(&mp, &skpv, &bp);
PQCLEAN_KYBER512_CLEAN_poly_invntt(&mp);

PQCLEAN_KYBER512_CLEAN_poly_sub(&mp, &v, &mp);
PQCLEAN_KYBER512_CLEAN_poly_reduce(&mp);

PQCLEAN_KYBER512_CLEAN_poly_tomsg(m, &mp);
}

+ 16
- 0
crypto_kem/kyber512/clean/indcpa.h View File

@@ -0,0 +1,16 @@
#ifndef INDCPA_H
#define INDCPA_H

void PQCLEAN_KYBER512_CLEAN_indcpa_keypair(unsigned char *pk,
unsigned char *sk);

void PQCLEAN_KYBER512_CLEAN_indcpa_enc(unsigned char *c,
const unsigned char *m,
const unsigned char *pk,
const unsigned char *coins);

void PQCLEAN_KYBER512_CLEAN_indcpa_dec(unsigned char *m,
const unsigned char *c,
const unsigned char *sk);

#endif

+ 100
- 0
crypto_kem/kyber512/clean/kem.c View File

@@ -0,0 +1,100 @@
#include "api.h"
#include "indcpa.h"
#include "params.h"
#include "randombytes.h"
#include "symmetric.h"
#include "verify.h"

#include <stdlib.h>

/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure Kyber key encapsulation mechanism
*
* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_KYBER512_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
size_t i;
PQCLEAN_KYBER512_CLEAN_indcpa_keypair(pk, sk);
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i];
}
hash_h(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
randombytes(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */
return 0;
}

/*************************************************
* Name: crypto_kem_enc
*
* Description: Generates cipher text and shared
* secret for given public key
*
* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_KYBER512_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
unsigned char buf[2 * KYBER_SYMBYTES];

randombytes(buf, KYBER_SYMBYTES);
hash_h(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */

hash_h(buf + KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
hash_g(kr, buf, 2 * KYBER_SYMBYTES);

PQCLEAN_KYBER512_CLEAN_indcpa_enc(ct, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */

hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */
kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
return 0;
}

/*************************************************
* Name: crypto_kem_dec
*
* Description: Generates shared secret for given
* cipher text and private key
*
* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0.
*
* On failure, ss will contain a pseudo-random value.
**************************************************/
int PQCLEAN_KYBER512_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
size_t i;
unsigned char fail;
unsigned char cmp[KYBER_CIPHERTEXTBYTES];
unsigned char buf[2 * KYBER_SYMBYTES];
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES;

PQCLEAN_KYBER512_CLEAN_indcpa_dec(buf, ct, sk);

for (i = 0; i < KYBER_SYMBYTES; i++) { /* Multitarget countermeasure for coins + contributory KEM */
buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + i]; /* Save hash by storing H(pk) in sk */
}
hash_g(kr, buf, 2 * KYBER_SYMBYTES);

PQCLEAN_KYBER512_CLEAN_indcpa_enc(cmp, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */

fail = PQCLEAN_KYBER512_CLEAN_verify(ct, cmp, KYBER_CIPHERTEXTBYTES);

hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */

PQCLEAN_KYBER512_CLEAN_cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */

kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
return 0;
}

+ 157
- 0
crypto_kem/kyber512/clean/ntt.c View File

@@ -0,0 +1,157 @@
#include "ntt.h"

#include "params.h"
#include "reduce.h"

#include <stdint.h>

/* Code to generate zetas and zetas_inv used in the number-theoretic transform:

#define KYBER_ROOT_OF_UNITY 17

static const uint16_t tree[128] = {
0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120,
4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124,
2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122,
6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126,
1, 65, 33, 97, 17, 81, 49, 113, 9, 73, 41, 105, 25, 89, 57, 121,
5, 69, 37, 101, 21, 85, 53, 117, 13, 77, 45, 109, 29, 93, 61, 125,
3, 67, 35, 99, 19, 83, 51, 115, 11, 75, 43, 107, 27, 91, 59, 123,
7, 71, 39, 103, 23, 87, 55, 119, 15, 79, 47, 111, 31, 95, 63, 127};


static int16_t fqmul(int16_t a, int16_t b) {
return montgomery_reduce((int32_t)a*b);
}

void init_ntt() {
unsigned int i, j, k;
int16_t tmp[128];

tmp[0] = MONT;
for(i = 1; i < 128; ++i)
tmp[i] = fqmul(tmp[i-1], KYBER_ROOT_OF_UNITY*MONT % KYBER_Q);

for(i = 0; i < 128; ++i)
zetas[i] = tmp[tree[i]];

k = 0;
for(i = 64; i >= 1; i >>= 1)
for(j = i; j < 2*i; ++j)
zetas_inv[k++] = -tmp[128 - tree[j]];

zetas_inv[127] = MONT * (MONT * (KYBER_Q - 1) * ((KYBER_Q - 1)/128) % KYBER_Q) % KYBER_Q;
}

*/
int16_t PQCLEAN_KYBER512_CLEAN_zetas[128] = {
2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962, 2127, 1855, 1468,
573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017, 732, 608, 1787, 411, 3124, 1758,
1223, 652, 2777, 1015, 2036, 1491, 3047, 1785, 516, 3321, 3009, 2663, 1711, 2167, 126, 1469,
2476, 3239, 3058, 830, 107, 1908, 3082, 2378, 2931, 961, 1821, 2604, 448, 2264, 677, 2054,
2226, 430, 555, 843, 2078, 871, 1550, 105, 422, 587, 177, 3094, 3038, 2869, 1574, 1653,
3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349, 418, 329, 3173, 3254,
817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193, 1218, 1994, 2455, 220, 2142, 1670,
2144, 1799, 2051, 794, 1819, 2475, 2459, 478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628
};

int16_t PQCLEAN_KYBER512_CLEAN_zetas_inv[128] = {
1701, 1807, 1460, 2371, 2338, 2333, 308, 108, 2851, 870, 854, 1510, 2535, 1278, 1530, 1185,
1659, 1187, 3109, 874, 1335, 2111, 136, 1215, 2945, 1465, 1285, 2007, 2719, 2726, 2232, 2512,
75, 156, 3000, 2911, 2980, 872, 2685, 1590, 2210, 602, 1846, 777, 147, 2170, 2551, 246,
1676, 1755, 460, 291, 235, 3152, 2742, 2907, 3224, 1779, 2458, 1251, 2486, 2774, 2899, 1103,
1275, 2652, 1065, 2881, 725, 1508, 2368, 398, 951, 247, 1421, 3222, 2499, 271, 90, 853,
1860, 3203, 1162, 1618, 666, 320, 8, 2813, 1544, 282, 1838, 1293, 2314, 552, 2677, 2106,
1571, 205, 2918, 1542, 2721, 2597, 2312, 681, 130, 1602, 1871, 829, 2946, 3065, 1325, 2756,
1861, 1474, 1202, 2367, 3147, 1752, 2707, 171, 3127, 3042, 1907, 1836, 1517, 359, 758, 1441
};


/*************************************************
* Name: fqmul
*
* Description: Multiplication followed by Montgomery reduction
*
* Arguments: - int16_t a: first factor
* - int16_t b: second factor
*
* Returns 16-bit integer congruent to a*b*R^{-1} mod q
**************************************************/
static int16_t fqmul(int16_t a, int16_t b) {
return PQCLEAN_KYBER512_CLEAN_montgomery_reduce((int32_t)a * b);
}

/*************************************************
* Name: ntt
*
* Description: Inplace number-theoretic transform (NTT) in Rq
* input is in standard order, output is in bitreversed order
*
* Arguments: - int16_t *poly: pointer to input/output vector of 256 elements of Zq
**************************************************/
void PQCLEAN_KYBER512_CLEAN_ntt(int16_t *poly) {
unsigned int len, start, j, k;
int16_t t, zeta;

k = 1;
for (len = 128; len >= 2; len >>= 1) {
for (start = 0; start < 256; start = j + len) {
zeta = PQCLEAN_KYBER512_CLEAN_zetas[k++];
for (j = start; j < start + len; ++j) {
t = fqmul(zeta, poly[j + len]);
poly[j + len] = poly[j] - t;
poly[j] = poly[j] + t;
}
}
}
}

/*************************************************
* Name: invntt
*
* Description: Inplace inverse number-theoretic transform in Rq
* input is in bitreversed order, output is in standard order
*
* Arguments: - int16_t *poly: pointer to input/output vector of 256 elements of Zq
**************************************************/
void PQCLEAN_KYBER512_CLEAN_invntt(int16_t *poly) {
unsigned int start, len, j, k;
int16_t t, zeta;

k = 0;
for (len = 2; len <= 128; len <<= 1) {
for (start = 0; start < 256; start = j + len) {
zeta = PQCLEAN_KYBER512_CLEAN_zetas_inv[k++];
for (j = start; j < start + len; ++j) {
t = poly[j];
poly[j] = PQCLEAN_KYBER512_CLEAN_barrett_reduce(t + poly[j + len]);
poly[j + len] = t - poly[j + len];
poly[j + len] = fqmul(zeta, poly[j + len]);
}
}
}

for (j = 0; j < 256; ++j) {
poly[j] = fqmul(poly[j], PQCLEAN_KYBER512_CLEAN_zetas_inv[127]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_basemul
*
* Description: Multiplication of polynomials in Zq[X]/((X^2-zeta))
* used for multiplication of elements in Rq in NTT domain
*
* Arguments: - int16_t r[2]: pointer to the output polynomial
* - const int16_t a[2]: pointer to the first factor
* - const int16_t b[2]: pointer to the second factor
* - int16_t zeta: integer defining the reduction polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta) {
r[0] = fqmul(a[1], b[1]);
r[0] = fqmul(r[0], zeta);
r[0] += fqmul(a[0], b[0]);

r[1] = fqmul(a[0], b[1]);
r[1] += fqmul(a[1], b[0]);
}

+ 13
- 0
crypto_kem/kyber512/clean/ntt.h View File

@@ -0,0 +1,13 @@
#ifndef NTT_H
#define NTT_H

#include <stdint.h>

extern int16_t PQCLEAN_KYBER512_CLEAN_zetas[128];
extern int16_t PQCLEAN_KYBER512_CLEAN_zetas_inv[128];

void PQCLEAN_KYBER512_CLEAN_ntt(int16_t *poly);
void PQCLEAN_KYBER512_CLEAN_invntt(int16_t *poly);
void PQCLEAN_KYBER512_CLEAN_basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta);

#endif

+ 31
- 0
crypto_kem/kyber512/clean/params.h View File

@@ -0,0 +1,31 @@
#ifndef PARAMS_H
#define PARAMS_H

#define KYBER_K 2 /* Change this for different security strengths */

/* Don't change parameters below this line */

#define KYBER_N 256
#define KYBER_Q 3329

#define KYBER_ETA 2

#define KYBER_SYMBYTES 32 /* size in bytes of hashes, and seeds */
#define KYBER_SSBYTES 32 /* size in bytes of shared key */

#define KYBER_POLYBYTES 384
#define KYBER_POLYVECBYTES (KYBER_K * KYBER_POLYBYTES)

#define KYBER_POLYCOMPRESSEDBYTES 96
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_K * 320)

#define KYBER_INDCPA_MSGBYTES KYBER_SYMBYTES
#define KYBER_INDCPA_PUBLICKEYBYTES (KYBER_POLYVECBYTES + KYBER_SYMBYTES)
#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 + 2*KYBER_SYMBYTES) /* 32 bytes of additional space to save H(pk) */
#define KYBER_CIPHERTEXTBYTES KYBER_INDCPA_BYTES

#endif

+ 287
- 0
crypto_kem/kyber512/clean/poly.c View File

@@ -0,0 +1,287 @@
#include "poly.h"

#include "cbd.h"
#include "ntt.h"
#include "params.h"
#include "reduce.h"
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_compress
*
* Description: Compression and subsequent serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYCOMPRESSEDBYTES bytes)
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_compress(unsigned char *r, poly *a) {
uint8_t t[8];
int i, j, k = 0;

PQCLEAN_KYBER512_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_N; i += 8) {
for (j = 0; j < 8; j++) {
t[j] = ((((uint32_t)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;
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_decompress
*
* Description: De-serialization and subsequent decompression of a polynomial;
* approximate inverse of PQCLEAN_KYBER512_CLEAN_poly_compress
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array (of length KYBER_POLYCOMPRESSEDBYTES bytes)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_decompress(poly *r, const unsigned char *a) {
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;
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_tobytes
*
* Description: Serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYBYTES bytes)
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_tobytes(unsigned char *r, poly *a) {
int i;
uint16_t t0, t1;

PQCLEAN_KYBER512_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_N / 2; i++) {
t0 = a->coeffs[2 * i];
t1 = a->coeffs[2 * i + 1];
r[3 * i] = t0 & 0xff;
r[3 * i + 1] = (t0 >> 8) | ((t1 & 0xf) << 4);
r[3 * i + 2] = (t1 >> 4) & 0xff;
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_frombytes
*
* Description: De-serialization of a polynomial;
* inverse of PQCLEAN_KYBER512_CLEAN_poly_tobytes
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array (of KYBER_POLYBYTES bytes)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_frombytes(poly *r, const unsigned char *a) {
int i;

for (i = 0; i < KYBER_N / 2; i++) {
r->coeffs[2 * i] = a[3 * i] | ((uint16_t)a[3 * i + 1] & 0x0f) << 8;
r->coeffs[2 * i + 1] = a[3 * i + 1] >> 4 | ((uint16_t)a[3 * i + 2] & 0xff) << 4;
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_getnoise
*
* Description: Sample a polynomial deterministically from a seed and a nonce,
* with output polynomial close to centered binomial distribution
* with parameter KYBER_ETA
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *seed: pointer to input seed (pointing to array of length KYBER_SYMBYTES bytes)
* - unsigned char nonce: one-byte input nonce
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) {
unsigned char buf[KYBER_ETA * KYBER_N / 4];

prf(buf, KYBER_ETA * KYBER_N / 4, seed, nonce);
PQCLEAN_KYBER512_CLEAN_cbd(r, buf);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_ntt
*
* Description: Computes negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in normal order, output in bitreversed order
*
* Arguments: - uint16_t *r: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_ntt(poly *r) {
PQCLEAN_KYBER512_CLEAN_ntt(r->coeffs);
PQCLEAN_KYBER512_CLEAN_poly_reduce(r);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_invntt
*
* Description: Computes inverse of negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in bitreversed order, output in normal order
*
* Arguments: - uint16_t *a: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_invntt(poly *r) {
PQCLEAN_KYBER512_CLEAN_invntt(r->coeffs);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_basemul
*
* Description: Multiplication of two polynomials in NTT domain
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_basemul(poly *r, const poly *a, const poly *b) {
unsigned int i;

for (i = 0; i < KYBER_N / 4; ++i) {
PQCLEAN_KYBER512_CLEAN_basemul(r->coeffs + 4 * i, a->coeffs + 4 * i, b->coeffs + 4 * i, PQCLEAN_KYBER512_CLEAN_zetas[64 + i]);
PQCLEAN_KYBER512_CLEAN_basemul(r->coeffs + 4 * i + 2, a->coeffs + 4 * i + 2, b->coeffs + 4 * i + 2, - PQCLEAN_KYBER512_CLEAN_zetas[64 + i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_frommont
*
* Description: Inplace conversion of all coefficients of a polynomial
* from Montgomery domain to normal domain
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_frommont(poly *r) {
int i;
const int16_t f = (1ULL << 32) % KYBER_Q;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER512_CLEAN_montgomery_reduce((int32_t)r->coeffs[i] * f);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_reduce
*
* Description: Applies Barrett reduction to all coefficients of a polynomial
* for details of the Barrett reduction see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_reduce(poly *r) {
int i;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER512_CLEAN_barrett_reduce(r->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_csubq
*
* Description: Applies conditional subtraction of q to each coefficient of a polynomial
* for details of conditional subtraction of q see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_csubq(poly *r) {
int i;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER512_CLEAN_csubq(r->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_add
*
* Description: Add two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_add(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_sub
*
* Description: Subtract two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = a->coeffs[i] - b->coeffs[i];
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_frommsg
*
* Description: Convert 32-byte message to polynomial
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *msg: pointer to input message
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) {
int i, j;
uint16_t mask;

for (i = 0; i < KYBER_SYMBYTES; i++) {
for (j = 0; j < 8; j++) {
mask = -((msg[i] >> j) & 1);
r->coeffs[8 * i + j] = mask & ((KYBER_Q + 1) / 2);
}
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_poly_tomsg
*
* Description: Convert polynomial to 32-byte message
*
* Arguments: - unsigned char *msg: pointer to output message
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) {
uint16_t t;
int i, j;

PQCLEAN_KYBER512_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_SYMBYTES; i++) {
msg[i] = 0;
for (j = 0; j < 8; j++) {
t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
msg[i] |= t << j;
}
}
}

+ 38
- 0
crypto_kem/kyber512/clean/poly.h View File

@@ -0,0 +1,38 @@
#ifndef POLY_H
#define POLY_H

#include "params.h"

#include <stdint.h>

/*
* Elements of R_q = Z_q[X]/(X^n + 1). Represents polynomial
* coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1]
*/
typedef struct {
int16_t coeffs[KYBER_N];
} poly;

void PQCLEAN_KYBER512_CLEAN_poly_compress(unsigned char *r, poly *a);
void PQCLEAN_KYBER512_CLEAN_poly_decompress(poly *r, const unsigned char *a);

void PQCLEAN_KYBER512_CLEAN_poly_tobytes(unsigned char *r, poly *a);
void PQCLEAN_KYBER512_CLEAN_poly_frombytes(poly *r, const unsigned char *a);

void PQCLEAN_KYBER512_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]);
void PQCLEAN_KYBER512_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a);

void PQCLEAN_KYBER512_CLEAN_poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce);

void PQCLEAN_KYBER512_CLEAN_poly_ntt(poly *r);
void PQCLEAN_KYBER512_CLEAN_poly_invntt(poly *r);
void PQCLEAN_KYBER512_CLEAN_poly_basemul(poly *r, const poly *a, const poly *b);
void PQCLEAN_KYBER512_CLEAN_poly_frommont(poly *r);

void PQCLEAN_KYBER512_CLEAN_poly_reduce(poly *r);
void PQCLEAN_KYBER512_CLEAN_poly_csubq(poly *r);

void PQCLEAN_KYBER512_CLEAN_poly_add(poly *r, const poly *a, const poly *b);
void PQCLEAN_KYBER512_CLEAN_poly_sub(poly *r, const poly *a, const poly *b);

#endif

+ 186
- 0
crypto_kem/kyber512/clean/polyvec.c View File

@@ -0,0 +1,186 @@
#include "polyvec.h"

#include "poly.h"

#include <stdint.h>

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_compress
*
* Description: Compress and serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECCOMPRESSEDBYTES)
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_compress(unsigned char *r, polyvec *a) {
int i, j, k;

PQCLEAN_KYBER512_CLEAN_polyvec_csubq(a);

uint16_t t[4];
for (i = 0; i < KYBER_K; i++) {
for (j = 0; j < KYBER_N / 4; j++) {
for (k = 0; k < 4; k++) {
t[k] = ((((uint32_t)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)) & 0xff;
r[5 * j + 3] = ((t[2] >> 4) | ((t[3] & 0x03) << 6)) & 0xff;
r[5 * j + 4] = (t[3] >> 2) & 0xff;
}
r += 320;
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_decompress
*
* Description: De-serialize and decompress vector of polynomials;
* approximate inverse of PQCLEAN_KYBER512_CLEAN_polyvec_compress
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - unsigned char *a: pointer to input byte array (of length KYBER_POLYVECCOMPRESSEDBYTES)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_K; 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;
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_tobytes
*
* Description: Serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECBYTES)
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_tobytes(unsigned char *r, polyvec *a) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_tobytes(r + i * KYBER_POLYBYTES, &a->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_frombytes
*
* Description: De-serialize vector of polynomials;
* inverse of PQCLEAN_KYBER512_CLEAN_polyvec_tobytes
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const polyvec *a: pointer to input vector of polynomials (of length KYBER_POLYVECBYTES)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_frombytes(&r->vec[i], a + i * KYBER_POLYBYTES);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_ntt
*
* Description: Apply forward NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_ntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_ntt(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_invntt
*
* Description: Apply inverse NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_invntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_invntt(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc
*
* Description: Pointwise multiply elements of a and b and accumulate into r
*
* Arguments: - poly *r: pointer to output polynomial
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b) {
int i;
poly t;

PQCLEAN_KYBER512_CLEAN_poly_basemul(r, &a->vec[0], &b->vec[0]);
for (i = 1; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_basemul(&t, &a->vec[i], &b->vec[i]);
PQCLEAN_KYBER512_CLEAN_poly_add(r, r, &t);
}

PQCLEAN_KYBER512_CLEAN_poly_reduce(r);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_reduce
*
* Description: Applies Barrett reduction to each coefficient
* of each element of a vector of polynomials
* for details of the Barrett reduction see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_reduce(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_reduce(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_csubq
*
* Description: Applies conditional subtraction of q to each coefficient
* of each element of a vector of polynomials
* for details of conditional subtraction of q see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_csubq(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_csubq(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_polyvec_add
*
* Description: Add vectors of polynomials
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
void PQCLEAN_KYBER512_CLEAN_polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER512_CLEAN_poly_add(&r->vec[i], &a->vec[i], &b->vec[i]);
}
}

+ 27
- 0
crypto_kem/kyber512/clean/polyvec.h View File

@@ -0,0 +1,27 @@
#ifndef POLYVEC_H
#define POLYVEC_H

#include "params.h"
#include "poly.h"

typedef struct {
poly vec[KYBER_K];
} polyvec;

void PQCLEAN_KYBER512_CLEAN_polyvec_compress(unsigned char *r, polyvec *a);
void PQCLEAN_KYBER512_CLEAN_polyvec_decompress(polyvec *r, const unsigned char *a);

void PQCLEAN_KYBER512_CLEAN_polyvec_tobytes(unsigned char *r, polyvec *a);
void PQCLEAN_KYBER512_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a);

void PQCLEAN_KYBER512_CLEAN_polyvec_ntt(polyvec *r);
void PQCLEAN_KYBER512_CLEAN_polyvec_invntt(polyvec *r);

void PQCLEAN_KYBER512_CLEAN_polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b);

void PQCLEAN_KYBER512_CLEAN_polyvec_reduce(polyvec *r);
void PQCLEAN_KYBER512_CLEAN_polyvec_csubq(polyvec *r);

void PQCLEAN_KYBER512_CLEAN_polyvec_add(polyvec *r, const polyvec *a, const polyvec *b);

#endif

+ 62
- 0
crypto_kem/kyber512/clean/reduce.c View File

@@ -0,0 +1,62 @@
#include "reduce.h"

#include "params.h"

#include <stdint.h>

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_montgomery_reduce
*
* Description: Montgomery reduction; given a 32-bit integer a, computes
* 16-bit integer congruent to a * R^-1 mod q,
* where R=2^16
*
* Arguments: - int32_t a: input integer to be reduced; has to be in {-q2^15,...,q2^15-1}
*
* Returns: integer in {-q+1,...,q-1} congruent to a * R^-1 modulo q.
**************************************************/
int16_t PQCLEAN_KYBER512_CLEAN_montgomery_reduce(int32_t a) {
int32_t t;
int16_t u;

u = (int16_t)(a * QINV);
t = (int32_t)u * KYBER_Q;
t = a - t;
t >>= 16;
return (int16_t)t;
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_barrett_reduce
*
* Description: Barrett reduction; given a 16-bit integer a, computes
* 16-bit integer congruent to a mod q in {0,...,q}
*
* Arguments: - int16_t a: input integer to be reduced
*
* Returns: integer in {0,...,q} congruent to a modulo q.
**************************************************/
int16_t PQCLEAN_KYBER512_CLEAN_barrett_reduce(int16_t a) {
int32_t t;
const int32_t v = (1U << 26) / KYBER_Q + 1;

t = v * a;
t >>= 26;
t *= KYBER_Q;
return (int16_t)(a - t);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_csubq
*
* Description: Conditionallly subtract q
*
* Arguments: - int16_t x: input integer
*
* Returns: a - q if a >= q, else a
**************************************************/
int16_t PQCLEAN_KYBER512_CLEAN_csubq(int16_t a) {
a -= KYBER_Q;
a += (a >> 15) & KYBER_Q;
return a;
}

+ 15
- 0
crypto_kem/kyber512/clean/reduce.h View File

@@ -0,0 +1,15 @@
#ifndef REDUCE_H
#define REDUCE_H

#include <stdint.h>

#define MONT 2285 // 2^16 % Q
#define QINV 62209 // q^(-1) mod 2^16

int16_t PQCLEAN_KYBER512_CLEAN_montgomery_reduce(int32_t a);

int16_t PQCLEAN_KYBER512_CLEAN_barrett_reduce(int16_t a);

int16_t PQCLEAN_KYBER512_CLEAN_csubq(int16_t a);

#endif

+ 64
- 0
crypto_kem/kyber512/clean/symmetric-fips202.c View File

@@ -0,0 +1,64 @@
#include "fips202.h"
#include "symmetric.h"

#include <stdlib.h>

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb
*
* Description: Absorb step of the SHAKE128 specialized for the Kyber context.
*
* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state
* - const unsigned char *input: pointer to KYBER_SYMBYTES input to be absorbed into s
* - unsigned char i additional byte of input
* - unsigned char j additional byte of input
**************************************************/
void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y) {
unsigned char extseed[KYBER_SYMBYTES + 2];
int i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extseed[i] = input[i];
}
extseed[i++] = x;
extseed[i] = y;
shake128_absorb(s->s, extseed, KYBER_SYMBYTES + 2);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks
*
* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of SHAKE128_RATE bytes each.
* Modifies the state. Can be called multiple times to keep squeezing,
* i.e., is incremental.
*
* Arguments: - unsigned char *output: pointer to output blocks
* - size_t nblocks: number of blocks to be squeezed (written to output)
* - keccak_state *s: pointer to in/output Keccak state
**************************************************/
void PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s) {
shake128_squeezeblocks(output, nblocks, s->s);
}

/*************************************************
* Name: PQCLEAN_KYBER512_CLEAN_shake256_prf
*
* Description: Usage of SHAKE256 as a PRF, concatenates secret and public input
* and then generates outlen bytes of SHAKE256 output
*
* Arguments: - unsigned char *output: pointer to output
* - size_t outlen: number of requested output bytes
* - const unsigned char * key: pointer to the key (of length KYBER_SYMBYTES)
* - const unsigned char nonce: single-byte nonce (public PRF input)
**************************************************/
void PQCLEAN_KYBER512_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce) {
unsigned char extkey[KYBER_SYMBYTES + 1];
size_t i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extkey[i] = key[i];
}
extkey[i] = nonce;

shake256(output, outlen, extkey, KYBER_SYMBYTES + 1);
}

+ 26
- 0
crypto_kem/kyber512/clean/symmetric.h View File

@@ -0,0 +1,26 @@
#ifndef SYMMETRIC_H
#define SYMMETRIC_H

#include "fips202.h"
#include "params.h"

typedef struct {
uint64_t s[25];
} keccak_state;

void PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y);
void PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s);
void PQCLEAN_KYBER512_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce);

#define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES)
#define hash_g(OUT, IN, INBYTES) sha3_512(OUT, IN, INBYTES)
#define xof_absorb(STATE, IN, X, Y) PQCLEAN_KYBER512_CLEAN_kyber_shake128_absorb(STATE, IN, X, Y)
#define xof_squeezeblocks(OUT, OUTBLOCKS, STATE) PQCLEAN_KYBER512_CLEAN_kyber_shake128_squeezeblocks(OUT, OUTBLOCKS, STATE)
#define prf(OUT, OUTBYTES, KEY, NONCE) PQCLEAN_KYBER512_CLEAN_shake256_prf(OUT, OUTBYTES, KEY, NONCE)
#define kdf(OUT, IN, INBYTES) shake256(OUT, KYBER_SSBYTES, IN, INBYTES)

#define XOF_BLOCKBYTES 168

typedef keccak_state xof_state;

#endif /* SYMMETRIC_H */

+ 51
- 0
crypto_kem/kyber512/clean/verify.c View File

@@ -0,0 +1,51 @@
#include "verify.h"

#include <stdint.h>
#include <stdlib.h>

/*************************************************
* Name: verify
*
* Description: Compare two arrays for equality in constant time.
*
* Arguments: const unsigned char *a: pointer to first byte array
* const unsigned char *b: pointer to second byte array
* size_t len: length of the byte arrays
*
* Returns 0 if the byte arrays are equal, 1 otherwise
**************************************************/
unsigned char PQCLEAN_KYBER512_CLEAN_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 + 1); // Two's complement
r >>= 63;
return (unsigned char)r;
}

/*************************************************
* Name: cmov
*
* Description: Copy len bytes from x to r if b is 1;
* don't modify x if b is 0. Requires b to be in {0,1};
* assumes two's complement representation of negative integers.
* Runs in constant time.
*
* Arguments: unsigned char *r: pointer to output byte array
* const unsigned char *x: pointer to input byte array
* size_t len: Amount of bytes to be copied
* unsigned char b: Condition bit; has to be in {0,1}
**************************************************/
void PQCLEAN_KYBER512_CLEAN_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]);
}
}

+ 10
- 0
crypto_kem/kyber512/clean/verify.h View File

@@ -0,0 +1,10 @@
#ifndef VERIFY_H
#define VERIFY_H

#include <stdio.h>

unsigned char PQCLEAN_KYBER512_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);

void PQCLEAN_KYBER512_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);

#endif

+ 3
- 3
crypto_kem/kyber768/META.yml View File

@@ -1,9 +1,9 @@
name: Kyber768
type: kem
claimed-nist-level: 3
length-public-key: 1088
length-public-key: 1184
length-ciphertext: 1088
length-secret-key: 2400
length-ciphertext: 1152
length-shared-secret: 32
nistkat-sha256: d6dbb9399d1ba4ee2d986de3e54a461256b91d6c2f9b90ad2410cf41e09b64d1
principal-submitter: Peter Schwabe
@@ -19,4 +19,4 @@ auxiliary-submitters:
- Damien Stehlé
implementations:
- name: clean
version: https://github.com/pq-crystals/kyber/commit/ab996e7460e5356b0e23aa034e7c2fe6922e60e6
version: https://github.com/pq-crystals/kyber/commit/46e283ab575ec92dfe82fb12229ae2d9d6246682

+ 2
- 2
crypto_kem/kyber768/clean/Makefile View File

@@ -1,8 +1,8 @@
# This Makefile can be used with GNU Make or BSD Make

LIB=libkyber768_clean.a
HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h
OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o precomp.o reduce.o verify.o
HEADERS=api.h cbd.h indcpa.h ntt.h params.h poly.h polyvec.h reduce.h verify.h symmetric.h
OBJECTS=cbd.o indcpa.o kem.o ntt.o poly.o polyvec.o reduce.o verify.o symmetric-fips202.o

CFLAGS=-O3 -Wall -Wextra -Wpedantic -Wvla -Werror -Wmissing-prototypes -std=c99 -I../../../common $(EXTRAFLAGS)



+ 1
- 1
crypto_kem/kyber768/clean/Makefile.Microsoft_nmake View File

@@ -2,7 +2,7 @@
# nmake /f Makefile.Microsoft_nmake

LIBRARY=libkyber768_clean.lib
OBJECTS=cbd.obj indcpa.obj kem.obj ntt.obj poly.obj polyvec.obj precomp.obj reduce.obj verify.obj
OBJECTS=cbd.obj indcpa.obj kem.obj ntt.obj poly.obj polyvec.obj reduce.obj verify.obj symmetric-fips202.obj

CFLAGS=/nologo /I ..\..\..\common /W4 /WX



+ 8
- 9
crypto_kem/kyber768/clean/api.h View File

@@ -1,19 +1,18 @@
#ifndef PQCLEAN_KYBER768_CLEAN_API_H
#define PQCLEAN_KYBER768_CLEAN_API_H

#include <stdint.h>

#define PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES 2400
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES 1088
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES 1152
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES 32
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_SECRETKEYBYTES 2400
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_PUBLICKEYBYTES 1184
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_CIPHERTEXTBYTES 1088
#define PQCLEAN_KYBER768_CLEAN_CRYPTO_BYTES 32

#define PQCLEAN_KYBER768_CLEAN_CRYPTO_ALGNAME "Kyber768"

int PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
int PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk);

int PQCLEAN_KYBER768_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk);

int PQCLEAN_KYBER768_CLEAN_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int PQCLEAN_KYBER768_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk);

int PQCLEAN_KYBER768_CLEAN_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);

#endif

+ 40
- 46
crypto_kem/kyber768/clean/cbd.c View File

@@ -1,59 +1,53 @@
#include "cbd.h"

#include "params.h"

#include <stdint.h>

/*************************************************
* Name: load_littleendian
*
* Description: load bytes into a 64-bit integer
* in little-endian order
*
* Arguments: - const unsigned char *x: pointer to input byte array
* - bytes: number of bytes to load, has to be <=
*8
*
* Returns 64-bit unsigned integer loaded from x
**************************************************/
static uint64_t load_littleendian(const unsigned char *x, int bytes) {
int i;
uint64_t r = x[0];
for (i = 1; i < bytes; i++) {
r |= (uint64_t)x[i] << (8 * i);
}
* Name: load32_littleendian
*
* Description: load bytes into a 32-bit integer
* in little-endian order
*
* Arguments: - const unsigned char *x: pointer to input byte array
*
* Returns 32-bit unsigned integer loaded from x
**************************************************/
static uint32_t load32_littleendian(const unsigned char *x) {
uint32_t r;
r = (uint32_t)x[0];
r |= (uint32_t)x[1] << 8;
r |= (uint32_t)x[2] << 16;
r |= (uint32_t)x[3] << 24;
return r;
}

/*************************************************
* Name: cbd
*
* Description: Given an array of uniformly random bytes, compute
* polynomial with coefficients distributed according to
* a centered binomial distribution with parameter KYBER_ETA
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *buf: pointer to input byte array
**************************************************/
* Name: cbd
*
* Description: Given an array of uniformly random bytes, compute
* polynomial with coefficients distributed according to
* a centered binomial distribution with parameter KYBER_ETA
* specialized for KYBER_ETA=2
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *buf: pointer to input byte array
**************************************************/
void PQCLEAN_KYBER768_CLEAN_cbd(poly *r, const unsigned char *buf) {
uint32_t t, d, a[4], b[4];
uint32_t d, t;
int16_t a, b;
int i, j;

for (i = 0; i < KYBER_N / 4; i++) {
t = (uint32_t)load_littleendian(buf + 4 * i, 4);
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);
for (i = 0; i < KYBER_N / 8; i++) {
t = load32_littleendian(buf + 4 * i);
d = t & 0x55555555;
d += (t >> 1) & 0x55555555;

r->coeffs[4 * i + 0] = (uint16_t)(a[0] + KYBER_Q - b[0]);
r->coeffs[4 * i + 1] = (uint16_t)(a[1] + KYBER_Q - b[1]);
r->coeffs[4 * i + 2] = (uint16_t)(a[2] + KYBER_Q - b[2]);
r->coeffs[4 * i + 3] = (uint16_t)(a[3] + KYBER_Q - b[3]);
for (j = 0; j < 8; j++) {
a = (d >> 4 * j) & 0x3;
b = (d >> (4 * j + 2)) & 0x3;
r->coeffs[8 * i + j] = a - b;
}
}
}

+ 0
- 1
crypto_kem/kyber768/clean/cbd.h View File

@@ -2,7 +2,6 @@
#define CBD_H

#include "poly.h"
#include <stdint.h>

void PQCLEAN_KYBER768_CLEAN_cbd(poly *r, const unsigned char *buf);



+ 178
- 183
crypto_kem/kyber768/clean/indcpa.c View File

@@ -1,238 +1,239 @@
#include "indcpa.h"
#include "fips202.h"
#include "ntt.h"
#include "poly.h"
#include "polyvec.h"
#include "randombytes.h"
#include <string.h>
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: pack_pk
*
* Description: Serialize the public key as concatenation of the
* compressed and serialized vector of polynomials pk
* and the public seed used to generate the matrix A.
*
* Arguments: unsigned char *r: pointer to the output serialized
*public key const poly *pk: pointer to the input public-key
*polynomial const unsigned char *seed: pointer to the input public seed
**************************************************/
static void pack_pk(unsigned char *r, const polyvec *pk, const unsigned char *seed) {
* Name: pack_pk
*
* Description: Serialize the public key as concatenation of the
* serialized vector of polynomials pk
* and the public seed used to generate the matrix A.
*
* Arguments: unsigned char *r: pointer to the output serialized public key
* const poly *pk: pointer to the input public-key polynomial
* const unsigned char *seed: pointer to the input public seed
**************************************************/
static void pack_pk(unsigned char *r, polyvec *pk, const unsigned char *seed) {
int i;
PQCLEAN_KYBER768_CLEAN_polyvec_compress(r, pk);
PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(r, pk);
for (i = 0; i < KYBER_SYMBYTES; i++) {
r[i + KYBER_POLYVECCOMPRESSEDBYTES] = seed[i];
r[i + KYBER_POLYVECBYTES] = seed[i];
}
}

/*************************************************
* Name: unpack_pk
*
* Description: De-serialize and decompress public key from a byte array;
* approximate inverse of pack_pk
*
* Arguments: - polyvec *pk: pointer to output public-key
*vector of polynomials
* - unsigned char *seed: pointer to output seed to
*generate matrix A
* - const unsigned char *packedpk: pointer to input serialized
*public key
**************************************************/
* Name: unpack_pk
*
* Description: De-serialize public key from a byte array;
* approximate inverse of pack_pk
*
* Arguments: - polyvec *pk: pointer to output public-key vector of polynomials
* - unsigned char *seed: pointer to output seed to generate matrix A
* - const unsigned char *packedpk: pointer to input serialized public key
**************************************************/
static void unpack_pk(polyvec *pk, unsigned char *seed, const unsigned char *packedpk) {
int i;
PQCLEAN_KYBER768_CLEAN_polyvec_decompress(pk, packedpk);

PQCLEAN_KYBER768_CLEAN_polyvec_frombytes(pk, packedpk);
for (i = 0; i < KYBER_SYMBYTES; i++) {
seed[i] = packedpk[i + KYBER_POLYVECCOMPRESSEDBYTES];
seed[i] = packedpk[i + KYBER_POLYVECBYTES];
}
}

/*************************************************
* Name: pack_ciphertext
*
* Description: Serialize the ciphertext as concatenation of the
* compressed and serialized vector of polynomials b
* and the compressed and serialized polynomial v
*
* Arguments: unsigned char *r: pointer to the output serialized
*ciphertext const poly *pk: pointer to the input vector of
*polynomials b const unsigned char *seed: pointer to the input polynomial v
**************************************************/
static void pack_ciphertext(unsigned char *r, const polyvec *b, const poly *v) {
* Name: pack_sk
*
* Description: Serialize the secret key
*
* Arguments: - unsigned char *r: pointer to output serialized secret key
* - const polyvec *sk: pointer to input vector of polynomials (secret key)
**************************************************/
static void pack_sk(unsigned char *r, polyvec *sk) {
PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(r, sk);
}

/*************************************************
* Name: unpack_sk
*
* Description: De-serialize the secret key;
* inverse of pack_sk
*
* Arguments: - polyvec *sk: pointer to output vector of polynomials (secret key)
* - const unsigned char *packedsk: pointer to input serialized secret key
**************************************************/
static void unpack_sk(polyvec *sk, const unsigned char *packedsk) {
PQCLEAN_KYBER768_CLEAN_polyvec_frombytes(sk, packedsk);
}

/*************************************************
* Name: pack_ciphertext
*
* Description: Serialize the ciphertext as concatenation of the
* compressed and serialized vector of polynomials b
* and the compressed and serialized polynomial v
*
* Arguments: unsigned char *r: pointer to the output serialized ciphertext
* const poly *pk: pointer to the input vector of polynomials b
* const unsigned char *seed: pointer to the input polynomial v
**************************************************/
static void pack_ciphertext(unsigned char *r, polyvec *b, poly *v) {
PQCLEAN_KYBER768_CLEAN_polyvec_compress(r, b);
PQCLEAN_KYBER768_CLEAN_poly_compress(r + KYBER_POLYVECCOMPRESSEDBYTES, v);
}

/*************************************************
* Name: unpack_ciphertext
*
* Description: De-serialize and decompress ciphertext from a byte array;
* approximate inverse of pack_ciphertext
*
* Arguments: - polyvec *b: pointer to the output vector of
*polynomials b
* - poly *v: pointer to the output polynomial v
* - const unsigned char *c: pointer to the input serialized
*ciphertext
**************************************************/
* Name: unpack_ciphertext
*
* Description: De-serialize and decompress ciphertext from a byte array;
* approximate inverse of pack_ciphertext
*
* Arguments: - polyvec *b: pointer to the output vector of polynomials b
* - poly *v: pointer to the output polynomial v
* - const unsigned char *c: pointer to the input serialized ciphertext
**************************************************/
static void unpack_ciphertext(polyvec *b, poly *v, const unsigned char *c) {
PQCLEAN_KYBER768_CLEAN_polyvec_decompress(b, c);
PQCLEAN_KYBER768_CLEAN_poly_decompress(v, c + KYBER_POLYVECCOMPRESSEDBYTES);
}

/*************************************************
* Name: pack_sk
*
* Description: Serialize the secret key
*
* Arguments: - unsigned char *r: pointer to output serialized secret key
* - const polyvec *sk: pointer to input vector of polynomials
*(secret key)
**************************************************/
static void pack_sk(unsigned char *r, const polyvec *sk) {
PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(r, sk);
}
* Name: rej_uniform
*
* Description: Run rejection sampling on uniform random bytes to generate
* uniform random integers mod q
*
* Arguments: - int16_t *r: pointer to output buffer
* - unsigned int len: requested number of 16-bit integers (uniform mod q)
* - const unsigned char *buf: pointer to input buffer (assumed to be uniform random bytes)
* - unsigned int buflen: length of input buffer in bytes
*
* Returns number of sampled 16-bit integers (at most len)
**************************************************/
static unsigned int rej_uniform(int16_t *r, unsigned int len, const unsigned char *buf, unsigned int buflen) {
unsigned int ctr, pos;
uint16_t val;

/*************************************************
* Name: unpack_sk
*
* Description: De-serialize the secret key;
* inverse of pack_sk
*
* Arguments: - polyvec *sk: pointer to output vector of
*polynomials (secret key)
* - const unsigned char *packedsk: pointer to input serialized
*secret key
**************************************************/
static void unpack_sk(polyvec *sk, const unsigned char *packedsk) {
PQCLEAN_KYBER768_CLEAN_polyvec_frombytes(sk, packedsk);
ctr = pos = 0;
while (ctr < len && pos + 2 <= buflen) {
val = buf[pos] | ((uint16_t)buf[pos + 1] << 8);
pos += 2;

if (val < 19 * KYBER_Q) {
val -= (val >> 12) * KYBER_Q; // Barrett reduction
r[ctr++] = (int16_t)val;
}
}

return ctr;
}

#define gen_a(A, B) gen_matrix(A, B, 0)
#define gen_at(A, B) gen_matrix(A, B, 1)
#define gen_a(A,B) PQCLEAN_KYBER768_CLEAN_gen_matrix(A,B,0)
#define gen_at(A,B) PQCLEAN_KYBER768_CLEAN_gen_matrix(A,B,1)

/*************************************************
* Name: gen_matrix
*
* Description: Deterministically generate matrix A (or the transpose of A)
* from a seed. Entries of the matrix are polynomials that look
* uniformly random. Performs rejection sampling on output of
* SHAKE-128
*
* Arguments: - polyvec *a: pointer to ouptput matrix A
* - const unsigned char *seed: pointer to input seed
* - int transposed: boolean deciding whether A or A^T
*is generated
**************************************************/
static void gen_matrix(polyvec *a, const unsigned char *seed, int transposed) {
unsigned int pos = 0, ctr;
uint16_t val;
unsigned int nblocks;
const unsigned int maxnblocks = 4;
uint8_t buf[SHAKE128_RATE * /* maxnblocks = */ 4];
int i, j;
uint64_t state[25]; // SHAKE state
unsigned char extseed[KYBER_SYMBYTES + 2];
#define GENMATRIX_MAXNBLOCKS ((530 + XOF_BLOCKBYTES) / XOF_BLOCKBYTES) /* 530 is expected number of required bytes */

for (i = 0; i < KYBER_SYMBYTES; i++) {
extseed[i] = seed[i];
}

/*************************************************
* Name: gen_matrix
*
* Description: Deterministically generate matrix A (or the transpose of A)
* from a seed. Entries of the matrix are polynomials that look
* uniformly random. Performs rejection sampling on output of
* a XOF
*
* Arguments: - polyvec *a: pointer to ouptput matrix A
* - const unsigned char *seed: pointer to input seed
* - int transposed: boolean deciding whether A or A^T is generated
**************************************************/
static void PQCLEAN_KYBER768_CLEAN_gen_matrix(polyvec *a, const unsigned char *seed, int transposed) {
unsigned int ctr;
unsigned char i, j;
unsigned char buf[XOF_BLOCKBYTES * GENMATRIX_MAXNBLOCKS + 1];
xof_state state;

for (i = 0; i < KYBER_K; i++) {
for (j = 0; j < KYBER_K; j++) {
ctr = pos = 0;
nblocks = maxnblocks;
if (transposed) {
extseed[KYBER_SYMBYTES] = (unsigned char)i;
extseed[KYBER_SYMBYTES + 1] = (unsigned char)j;
xof_absorb(&state, seed, i, j);
} else {
extseed[KYBER_SYMBYTES] = (unsigned char)j;
extseed[KYBER_SYMBYTES + 1] = (unsigned char)i;
xof_absorb(&state, seed, j, i);
}

shake128_absorb(state, extseed, KYBER_SYMBYTES + 2);
shake128_squeezeblocks(buf, nblocks, state);
xof_squeezeblocks(buf, GENMATRIX_MAXNBLOCKS, &state);
ctr = rej_uniform(a[i].vec[j].coeffs, KYBER_N, buf, GENMATRIX_MAXNBLOCKS * XOF_BLOCKBYTES);

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 > SHAKE128_RATE * nblocks - 2) {
nblocks = 1;
shake128_squeezeblocks(buf, nblocks, state);
pos = 0;
}
xof_squeezeblocks(buf, 1, &state);
ctr += rej_uniform(a[i].vec[j].coeffs + ctr, KYBER_N - ctr, buf, XOF_BLOCKBYTES);
}
}
}
}

/*************************************************
* Name: indcpa_keypair
*
* Description: Generates public and private key for the CPA-secure
* public-key encryption scheme underlying Kyber
*
* Arguments: - unsigned char *pk: pointer to output public key (of length
*KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (of length
*KYBER_INDCPA_SECRETKEYBYTES bytes)
**************************************************/
* Name: indcpa_keypair
*
* Description: Generates public and private key for the CPA-secure
* public-key encryption scheme underlying Kyber
*
* Arguments: - unsigned char *pk: pointer to output public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (of length KYBER_INDCPA_SECRETKEYBYTES bytes)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_indcpa_keypair(unsigned char *pk, unsigned char *sk) {
polyvec a[KYBER_K], e, pkpv, skpv;
unsigned char buf[KYBER_SYMBYTES + KYBER_SYMBYTES];
unsigned char buf[2 * KYBER_SYMBYTES];
unsigned char *publicseed = buf;
unsigned char *noiseseed = buf + KYBER_SYMBYTES;
int i;
unsigned char nonce = 0;

randombytes(buf, KYBER_SYMBYTES);
sha3_512(buf, buf, KYBER_SYMBYTES);
hash_g(buf, buf, KYBER_SYMBYTES);

gen_a(a, publicseed);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_getnoise(skpv.vec + i, noiseseed, nonce++);
}

PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&skpv);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_getnoise(e.vec + i, noiseseed, nonce++);
}

PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&skpv);
PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&e);

// matrix-vector multiplication
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(&pkpv.vec[i], &skpv, a + i);
PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(&pkpv.vec[i], &a[i], &skpv);
PQCLEAN_KYBER768_CLEAN_poly_frommont(&pkpv.vec[i]);
}

PQCLEAN_KYBER768_CLEAN_polyvec_invntt(&pkpv);
PQCLEAN_KYBER768_CLEAN_polyvec_add(&pkpv, &pkpv, &e);
PQCLEAN_KYBER768_CLEAN_polyvec_reduce(&pkpv);

pack_sk(sk, &skpv);
pack_pk(pk, &pkpv, publicseed);
}

/*************************************************
* Name: indcpa_enc
*
* Description: Encryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *c: pointer to output ciphertext (of
*length KYBER_INDCPA_BYTES bytes)
* - const unsigned char *m: pointer to input message (of length
*KYBER_INDCPA_MSGBYTES bytes)
* - const unsigned char *pk: pointer to input public key (of
*length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - const unsigned char *coin: pointer to input random coins used
*as seed (of length KYBER_SYMBYTES bytes) to deterministically generate all
*randomness
**************************************************/
void PQCLEAN_KYBER768_CLEAN_indcpa_enc(unsigned char *c, const unsigned char *m,
* Name: indcpa_enc
*
* Description: Encryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *c: pointer to output ciphertext (of length KYBER_INDCPA_BYTES bytes)
* - const unsigned char *m: pointer to input message (of length KYBER_INDCPA_MSGBYTES bytes)
* - const unsigned char *pk: pointer to input public key (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - const unsigned char *coin: pointer to input random coins used as seed (of length KYBER_SYMBYTES bytes)
* to deterministically generate all randomness
**************************************************/
void PQCLEAN_KYBER768_CLEAN_indcpa_enc(unsigned char *c,
const unsigned char *m,
const unsigned char *pk,
const unsigned char *coins) {
polyvec sp, pkpv, ep, at[KYBER_K], bp;
@@ -242,56 +243,50 @@ void PQCLEAN_KYBER768_CLEAN_indcpa_enc(unsigned char *c, const unsigned char *m,
unsigned char nonce = 0;

unpack_pk(&pkpv, seed, pk);

PQCLEAN_KYBER768_CLEAN_poly_frommsg(&k, m);

PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&pkpv);

gen_at(at, seed);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_getnoise(sp.vec + i, coins, nonce++);
}

PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&sp);

for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_getnoise(ep.vec + i, coins, nonce++);
}
PQCLEAN_KYBER768_CLEAN_poly_getnoise(&epp, coins, nonce++);

PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&sp);

// matrix-vector multiplication
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(&bp.vec[i], &sp, at + i);
PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(&bp.vec[i], &at[i], &sp);
}

PQCLEAN_KYBER768_CLEAN_polyvec_invntt(&bp);
PQCLEAN_KYBER768_CLEAN_polyvec_add(&bp, &bp, &ep);

PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(&v, &pkpv, &sp);
PQCLEAN_KYBER768_CLEAN_poly_invntt(&v);

PQCLEAN_KYBER768_CLEAN_poly_getnoise(&epp, coins, nonce++);
PQCLEAN_KYBER768_CLEAN_polyvec_invntt(&bp);
PQCLEAN_KYBER768_CLEAN_poly_invntt(&v);

PQCLEAN_KYBER768_CLEAN_polyvec_add(&bp, &bp, &ep);
PQCLEAN_KYBER768_CLEAN_poly_add(&v, &v, &epp);
PQCLEAN_KYBER768_CLEAN_poly_add(&v, &v, &k);
PQCLEAN_KYBER768_CLEAN_polyvec_reduce(&bp);
PQCLEAN_KYBER768_CLEAN_poly_reduce(&v);

pack_ciphertext(c, &bp, &v);
}

/*************************************************
* Name: indcpa_dec
*
* Description: Decryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *m: pointer to output decrypted message
*(of length KYBER_INDCPA_MSGBYTES)
* - const unsigned char *c: pointer to input ciphertext (of
*length KYBER_INDCPA_BYTES)
* - const unsigned char *sk: pointer to input secret key (of
*length KYBER_INDCPA_SECRETKEYBYTES)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_indcpa_dec(unsigned char *m, const unsigned char *c,
* Name: indcpa_dec
*
* Description: Decryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - unsigned char *m: pointer to output decrypted message (of length KYBER_INDCPA_MSGBYTES)
* - const unsigned char *c: pointer to input ciphertext (of length KYBER_INDCPA_BYTES)
* - const unsigned char *sk: pointer to input secret key (of length KYBER_INDCPA_SECRETKEYBYTES)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_indcpa_dec(unsigned char *m,
const unsigned char *c,
const unsigned char *sk) {
polyvec bp, skpv;
poly v, mp;
@@ -300,11 +295,11 @@ void PQCLEAN_KYBER768_CLEAN_indcpa_dec(unsigned char *m, const unsigned char *c,
unpack_sk(&skpv, sk);

PQCLEAN_KYBER768_CLEAN_polyvec_ntt(&bp);

PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(&mp, &skpv, &bp);
PQCLEAN_KYBER768_CLEAN_poly_invntt(&mp);

PQCLEAN_KYBER768_CLEAN_poly_sub(&mp, &mp, &v);
PQCLEAN_KYBER768_CLEAN_poly_sub(&mp, &v, &mp);
PQCLEAN_KYBER768_CLEAN_poly_reduce(&mp);

PQCLEAN_KYBER768_CLEAN_poly_tomsg(m, &mp);
}

+ 57
- 63
crypto_kem/kyber768/clean/kem.c View File

@@ -1,108 +1,102 @@
#include "api.h"
#include "fips202.h"
#include "indcpa.h"
#include "params.h"
#include "randombytes.h"
#include "symmetric.h"
#include "verify.h"

#include <stdlib.h>

#include <stdlib.h>

/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure Kyber key encapsulation mechanism
*
* Arguments: - unsigned char *pk: pointer to output public key (an already
*allocated array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (an already
*allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure Kyber key encapsulation mechanism
*
* Arguments: - unsigned char *pk: pointer to output public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
* - unsigned char *sk: pointer to output private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_KYBER768_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
size_t i;
PQCLEAN_KYBER768_CLEAN_indcpa_keypair(pk, sk);
for (i = 0; i < KYBER_INDCPA_PUBLICKEYBYTES; i++) {
sk[i + KYBER_INDCPA_SECRETKEYBYTES] = pk[i];
}
sha3_256(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
randombytes(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */
hash_h(sk + KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
randombytes(sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES); /* Value z for pseudo-random output on reject */
return 0;
}

/*************************************************
* Name: crypto_kem_enc
*
* Description: Generates cipher text and shared
* secret for given public key
*
* Arguments: - unsigned char *ct: pointer to output cipher text (an
*already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - unsigned char *ss: pointer to output shared secret (an
*already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *pk: pointer to input public key (an
*already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
* Name: crypto_kem_enc
*
* Description: Generates cipher text and shared
* secret for given public key
*
* Arguments: - unsigned char *ct: pointer to output cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *pk: pointer to input public key (an already allocated array of CRYPTO_PUBLICKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int PQCLEAN_KYBER768_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
unsigned char buf[2 * KYBER_SYMBYTES];

randombytes(buf, KYBER_SYMBYTES);
sha3_256(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */
hash_h(buf, buf, KYBER_SYMBYTES); /* Don't release system RNG output */

sha3_256(buf + KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
sha3_512(kr, buf, 2 * KYBER_SYMBYTES);
hash_h(buf + KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES); /* Multitarget countermeasure for coins + contributory KEM */
hash_g(kr, buf, 2 * KYBER_SYMBYTES);

PQCLEAN_KYBER768_CLEAN_indcpa_enc(ct, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */
PQCLEAN_KYBER768_CLEAN_indcpa_enc(ct, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */

sha3_256(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */
sha3_256(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */
kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
return 0;
}

/*************************************************
* Name: crypto_kem_dec
*
* Description: Generates shared secret for given
* cipher text and private key
*
* Arguments: - unsigned char *ss: pointer to output shared secret (an
*already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *ct: pointer to input cipher text (an
*already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - const unsigned char *sk: pointer to input private key (an
*already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0.
*
* On failure, ss will contain a pseudo-random value.
**************************************************/
* Name: crypto_kem_dec
*
* Description: Generates shared secret for given
* cipher text and private key
*
* Arguments: - unsigned char *ss: pointer to output shared secret (an already allocated array of CRYPTO_BYTES bytes)
* - const unsigned char *ct: pointer to input cipher text (an already allocated array of CRYPTO_CIPHERTEXTBYTES bytes)
* - const unsigned char *sk: pointer to input private key (an already allocated array of CRYPTO_SECRETKEYBYTES bytes)
*
* Returns 0.
*
* On failure, ss will contain a pseudo-random value.
**************************************************/
int PQCLEAN_KYBER768_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
size_t i;
int fail;
unsigned char fail;
unsigned char cmp[KYBER_CIPHERTEXTBYTES];
unsigned char buf[2 * KYBER_SYMBYTES];
unsigned char
kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins, qrom-hash */
unsigned char kr[2 * KYBER_SYMBYTES]; /* Will contain key, coins */
const unsigned char *pk = sk + KYBER_INDCPA_SECRETKEYBYTES;

PQCLEAN_KYBER768_CLEAN_indcpa_dec(buf, ct, sk);

for (i = 0; i < KYBER_SYMBYTES; i++) { /* Multitarget countermeasure for coins + contributory KEM */
buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + i]; /* Save hash by storing H(pk) in sk */
for (i = 0; i < KYBER_SYMBYTES; i++) { /* Multitarget countermeasure for coins + contributory KEM */
buf[KYBER_SYMBYTES + i] = sk[KYBER_SECRETKEYBYTES - 2 * KYBER_SYMBYTES + i]; /* Save hash by storing H(pk) in sk */
}
sha3_512(kr, buf, 2 * KYBER_SYMBYTES);
hash_g(kr, buf, 2 * KYBER_SYMBYTES);

PQCLEAN_KYBER768_CLEAN_indcpa_enc(cmp, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */
PQCLEAN_KYBER768_CLEAN_indcpa_enc(cmp, buf, pk, kr + KYBER_SYMBYTES); /* coins are in kr+KYBER_SYMBYTES */

fail = PQCLEAN_KYBER768_CLEAN_verify(ct, cmp, KYBER_CIPHERTEXTBYTES);

sha3_256(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */

PQCLEAN_KYBER768_CLEAN_cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, (unsigned char)fail); /* Overwrite pre-k with z on re-encryption failure */
hash_h(kr + KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES); /* overwrite coins in kr with H(c) */

sha3_256(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
PQCLEAN_KYBER768_CLEAN_cmov(kr, sk + KYBER_SECRETKEYBYTES - KYBER_SYMBYTES, KYBER_SYMBYTES, fail); /* Overwrite pre-k with z on re-encryption failure */

kdf(ss, kr, 2 * KYBER_SYMBYTES); /* hash concatenation of pre-k and H(c) to k */
return 0;
}

+ 136
- 59
crypto_kem/kyber768/clean/ntt.c View File

@@ -1,80 +1,157 @@
#include "ntt.h"
#include "inttypes.h"
#include "params.h"
#include "reduce.h"

extern const uint16_t PQCLEAN_KYBER768_CLEAN_omegas_inv_bitrev_montgomery[];
extern const uint16_t PQCLEAN_KYBER768_CLEAN_psis_inv_montgomery[];
extern const uint16_t PQCLEAN_KYBER768_CLEAN_zetas[];
#include <stdint.h>

/* Code to generate zetas and zetas_inv used in the number-theoretic transform:

#define KYBER_ROOT_OF_UNITY 17

static const uint16_t tree[128] = {
0, 64, 32, 96, 16, 80, 48, 112, 8, 72, 40, 104, 24, 88, 56, 120,
4, 68, 36, 100, 20, 84, 52, 116, 12, 76, 44, 108, 28, 92, 60, 124,
2, 66, 34, 98, 18, 82, 50, 114, 10, 74, 42, 106, 26, 90, 58, 122,
6, 70, 38, 102, 22, 86, 54, 118, 14, 78, 46, 110, 30, 94, 62, 126,
1, 65, 33, 97, 17, 81, 49, 113, 9, 73, 41, 105, 25, 89, 57, 121,
5, 69, 37, 101, 21, 85, 53, 117, 13, 77, 45, 109, 29, 93, 61, 125,
3, 67, 35, 99, 19, 83, 51, 115, 11, 75, 43, 107, 27, 91, 59, 123,
7, 71, 39, 103, 23, 87, 55, 119, 15, 79, 47, 111, 31, 95, 63, 127};


static int16_t fqmul(int16_t a, int16_t b) {
return montgomery_reduce((int32_t)a*b);
}

void init_ntt() {
unsigned int i, j, k;
int16_t tmp[128];

tmp[0] = MONT;
for(i = 1; i < 128; ++i)
tmp[i] = fqmul(tmp[i-1], KYBER_ROOT_OF_UNITY*MONT % KYBER_Q);

for(i = 0; i < 128; ++i)
zetas[i] = tmp[tree[i]];

k = 0;
for(i = 64; i >= 1; i >>= 1)
for(j = i; j < 2*i; ++j)
zetas_inv[k++] = -tmp[128 - tree[j]];

zetas_inv[127] = MONT * (MONT * (KYBER_Q - 1) * ((KYBER_Q - 1)/128) % KYBER_Q) % KYBER_Q;
}

*/
int16_t PQCLEAN_KYBER768_CLEAN_zetas[128] = {
2285, 2571, 2970, 1812, 1493, 1422, 287, 202, 3158, 622, 1577, 182, 962, 2127, 1855, 1468,
573, 2004, 264, 383, 2500, 1458, 1727, 3199, 2648, 1017, 732, 608, 1787, 411, 3124, 1758,
1223, 652, 2777, 1015, 2036, 1491, 3047, 1785, 516, 3321, 3009, 2663, 1711, 2167, 126, 1469,
2476, 3239, 3058, 830, 107, 1908, 3082, 2378, 2931, 961, 1821, 2604, 448, 2264, 677, 2054,
2226, 430, 555, 843, 2078, 871, 1550, 105, 422, 587, 177, 3094, 3038, 2869, 1574, 1653,
3083, 778, 1159, 3182, 2552, 1483, 2727, 1119, 1739, 644, 2457, 349, 418, 329, 3173, 3254,
817, 1097, 603, 610, 1322, 2044, 1864, 384, 2114, 3193, 1218, 1994, 2455, 220, 2142, 1670,
2144, 1799, 2051, 794, 1819, 2475, 2459, 478, 3221, 3021, 996, 991, 958, 1869, 1522, 1628
};

int16_t PQCLEAN_KYBER768_CLEAN_zetas_inv[128] = {
1701, 1807, 1460, 2371, 2338, 2333, 308, 108, 2851, 870, 854, 1510, 2535, 1278, 1530, 1185,
1659, 1187, 3109, 874, 1335, 2111, 136, 1215, 2945, 1465, 1285, 2007, 2719, 2726, 2232, 2512,
75, 156, 3000, 2911, 2980, 872, 2685, 1590, 2210, 602, 1846, 777, 147, 2170, 2551, 246,
1676, 1755, 460, 291, 235, 3152, 2742, 2907, 3224, 1779, 2458, 1251, 2486, 2774, 2899, 1103,
1275, 2652, 1065, 2881, 725, 1508, 2368, 398, 951, 247, 1421, 3222, 2499, 271, 90, 853,
1860, 3203, 1162, 1618, 666, 320, 8, 2813, 1544, 282, 1838, 1293, 2314, 552, 2677, 2106,
1571, 205, 2918, 1542, 2721, 2597, 2312, 681, 130, 1602, 1871, 829, 2946, 3065, 1325, 2756,
1861, 1474, 1202, 2367, 3147, 1752, 2707, 171, 3127, 3042, 1907, 1836, 1517, 359, 758, 1441
};


/*************************************************
* Name: ntt
*
* Description: Computes negacyclic number-theoretic transform (NTT) of
* a polynomial (vector of 256 coefficients) in place;
* inputs assumed to be in normal order, output in bitreversed
*order
*
* Arguments: - uint16_t *p: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_ntt(uint16_t *p) {
int level, start, j, k;
uint16_t zeta, t;
* Name: fqmul
*
* Description: Multiplication followed by Montgomery reduction
*
* Arguments: - int16_t a: first factor
* - int16_t b: second factor
*
* Returns 16-bit integer congruent to a*b*R^{-1} mod q
**************************************************/
static int16_t fqmul(int16_t a, int16_t b) {
return PQCLEAN_KYBER768_CLEAN_montgomery_reduce((int32_t)a * b);
}

/*************************************************
* Name: ntt
*
* Description: Inplace number-theoretic transform (NTT) in Rq
* input is in standard order, output is in bitreversed order
*
* Arguments: - int16_t *poly: pointer to input/output vector of 256 elements of Zq
**************************************************/
void PQCLEAN_KYBER768_CLEAN_ntt(int16_t *poly) {
unsigned int len, start, j, k;
int16_t t, zeta;

k = 1;
for (level = 7; level >= 0; level--) {
for (start = 0; start < KYBER_N; start = j + (1 << level)) {
for (len = 128; len >= 2; len >>= 1) {
for (start = 0; start < 256; start = j + len) {
zeta = PQCLEAN_KYBER768_CLEAN_zetas[k++];
for (j = start; j < start + (1 << level); ++j) {
t = PQCLEAN_KYBER768_CLEAN_montgomery_reduce((uint32_t)zeta * p[j + (1 << level)]);

p[j + (1 << level)] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(p[j] + 4 * KYBER_Q - t);

if (level & 1) { /* odd level */
p[j] = p[j] + t; /* Omit reduction (be lazy) */
} else {
p[j] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(p[j] + t);
}
for (j = start; j < start + len; ++j) {
t = fqmul(zeta, poly[j + len]);
poly[j + len] = poly[j] - t;
poly[j] = poly[j] + t;
}
}
}
}

/*************************************************
* Name: invntt
*
* Description: Computes inverse of negacyclic number-theoretic transform (NTT)
*of a polynomial (vector of 256 coefficients) in place; inputs assumed to be in
*bitreversed order, output in normal order
*
* Arguments: - uint16_t *a: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_invntt(uint16_t *a) {
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 = PQCLEAN_KYBER768_CLEAN_omegas_inv_bitrev_montgomery[jTwiddle++];
temp = a[j];

if (level & 1) { /* odd level */
a[j] = PQCLEAN_KYBER768_CLEAN_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)] = PQCLEAN_KYBER768_CLEAN_montgomery_reduce(t);
* Name: invntt
*
* Description: Inplace inverse number-theoretic transform in Rq
* input is in bitreversed order, output is in standard order
*
* Arguments: - int16_t *poly: pointer to input/output vector of 256 elements of Zq
**************************************************/
void PQCLEAN_KYBER768_CLEAN_invntt(int16_t *poly) {
unsigned int start, len, j, k;
int16_t t, zeta;

k = 0;
for (len = 2; len <= 128; len <<= 1) {
for (start = 0; start < 256; start = j + len) {
zeta = PQCLEAN_KYBER768_CLEAN_zetas_inv[k++];
for (j = start; j < start + len; ++j) {
t = poly[j];
poly[j] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(t + poly[j + len]);
poly[j + len] = t - poly[j + len];
poly[j + len] = fqmul(zeta, poly[j + len]);
}
}
}

for (j = 0; j < KYBER_N; j++) {
a[j] = PQCLEAN_KYBER768_CLEAN_montgomery_reduce((a[j] * PQCLEAN_KYBER768_CLEAN_psis_inv_montgomery[j]));
for (j = 0; j < 256; ++j) {
poly[j] = fqmul(poly[j], PQCLEAN_KYBER768_CLEAN_zetas_inv[127]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_basemul
*
* Description: Multiplication of polynomials in Zq[X]/((X^2-zeta))
* used for multiplication of elements in Rq in NTT domain
*
* Arguments: - int16_t r[2]: pointer to the output polynomial
* - const int16_t a[2]: pointer to the first factor
* - const int16_t b[2]: pointer to the second factor
* - int16_t zeta: integer defining the reduction polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta) {
r[0] = fqmul(a[1], b[1]);
r[0] = fqmul(r[0], zeta);
r[0] += fqmul(a[0], b[0]);

r[1] = fqmul(a[0], b[1]);
r[1] += fqmul(a[1], b[0]);
}

+ 6
- 2
crypto_kem/kyber768/clean/ntt.h View File

@@ -3,7 +3,11 @@

#include <stdint.h>

void PQCLEAN_KYBER768_CLEAN_ntt(uint16_t *p);
void PQCLEAN_KYBER768_CLEAN_invntt(uint16_t *a);
extern int16_t PQCLEAN_KYBER768_CLEAN_zetas[128];
extern int16_t PQCLEAN_KYBER768_CLEAN_zetas_inv[128];

void PQCLEAN_KYBER768_CLEAN_ntt(int16_t *poly);
void PQCLEAN_KYBER768_CLEAN_invntt(int16_t *poly);
void PQCLEAN_KYBER768_CLEAN_basemul(int16_t r[2], const int16_t a[2], const int16_t b[2], int16_t zeta);

#endif

+ 12
- 8
crypto_kem/kyber768/clean/params.h View File

@@ -3,25 +3,29 @@

#define KYBER_K 3

/* Don't change parameters below this line */

#define KYBER_N 256
#define KYBER_Q 7681
#define KYBER_Q 3329

#define KYBER_ETA 4
#define KYBER_ETA 2

#define KYBER_SYMBYTES 32 /* size in bytes of shared key, hashes, and seeds */
#define KYBER_SYMBYTES 32 /* size in bytes of hashes, and seeds */
#define KYBER_SSBYTES 32 /* size in bytes of shared key */

#define KYBER_POLYBYTES 416
#define KYBER_POLYCOMPRESSEDBYTES 96
#define KYBER_POLYBYTES 384
#define KYBER_POLYVECBYTES (KYBER_K * KYBER_POLYBYTES)
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_K * 352)

#define KYBER_POLYCOMPRESSEDBYTES 128
#define KYBER_POLYVECCOMPRESSEDBYTES (KYBER_K * 320)

#define KYBER_INDCPA_MSGBYTES KYBER_SYMBYTES
#define KYBER_INDCPA_PUBLICKEYBYTES (KYBER_POLYVECCOMPRESSEDBYTES + KYBER_SYMBYTES)
#define KYBER_INDCPA_PUBLICKEYBYTES (KYBER_POLYVECBYTES + KYBER_SYMBYTES)
#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 + 2 * KYBER_SYMBYTES) /* 32 bytes of additional space to save H(pk) */
#define KYBER_SECRETKEYBYTES (KYBER_INDCPA_SECRETKEYBYTES + KYBER_INDCPA_PUBLICKEYBYTES + 2*KYBER_SYMBYTES) /* 32 bytes of additional space to save H(pk) */
#define KYBER_CIPHERTEXTBYTES KYBER_INDCPA_BYTES

#endif

+ 203
- 151
crypto_kem/kyber768/clean/poly.c View File

@@ -1,210 +1,260 @@
#include "poly.h"

#include "cbd.h"
#include "fips202.h"
#include "ntt.h"
#include "polyvec.h"
#include "params.h"
#include "reduce.h"
#include <stdio.h>
#include "symmetric.h"

#include <stdint.h>

/*************************************************
* Name: poly_compress
*
* Description: Compression and subsequent serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_compress(unsigned char *r, const poly *a) {
uint32_t t[8];
unsigned int i, j, k = 0;
* Name: PQCLEAN_KYBER768_CLEAN_poly_compress
*
* Description: Compression and subsequent serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYCOMPRESSEDBYTES bytes)
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_compress(unsigned char *r, poly *a) {
uint8_t t[8];
int i, j, k = 0;

PQCLEAN_KYBER768_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_N; i += 8) {
for (j = 0; j < 8; j++) {
t[j] = (((PQCLEAN_KYBER768_CLEAN_freeze(a->coeffs[i + j]) << 3) + KYBER_Q / 2) / KYBER_Q) & 7;
t[j] = ((((uint32_t)a->coeffs[i + j] << 4) + KYBER_Q / 2) / KYBER_Q) & 15;
}

r[k] = (unsigned char)( t[0] | (t[1] << 3) | (t[2] << 6));
r[k + 1] = (unsigned char)((t[2] >> 2) | (t[3] << 1) | (t[4] << 4) | (t[5] << 7));
r[k + 2] = (unsigned char)((t[5] >> 1) | (t[6] << 2) | (t[7] << 5));
k += 3;
r[k] = t[0] | (t[1] << 4);
r[k + 1] = t[2] | (t[3] << 4);
r[k + 2] = t[4] | (t[5] << 4);
r[k + 3] = t[6] | (t[7] << 4);
k += 4;
}
}

/*************************************************
* Name: poly_decompress
*
* Description: De-serialization and subsequent decompression of a polynomial;
* approximate inverse of poly_compress
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_decompress
*
* Description: De-serialization and subsequent decompression of a polynomial;
* approximate inverse of PQCLEAN_KYBER768_CLEAN_poly_compress
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array (of length KYBER_POLYCOMPRESSEDBYTES bytes)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_decompress(poly *r, const unsigned char *a) {
unsigned int i;
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;
r->coeffs[i + 0] = (((a[0] & 15) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 1] = (((a[0] >> 4) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 2] = (((a[1] & 15) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 3] = (((a[1] >> 4) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 4] = (((a[2] & 15) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 5] = (((a[2] >> 4) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 6] = (((a[3] & 15) * KYBER_Q) + 8) >> 4;
r->coeffs[i + 7] = (((a[3] >> 4) * KYBER_Q) + 8) >> 4;
a += 4;
}
}

/*************************************************
* Name: poly_tobytes
*
* Description: Serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_tobytes(unsigned char *r, const poly *a) {
int i, j;
uint16_t t[8];
* Name: PQCLEAN_KYBER768_CLEAN_poly_tobytes
*
* Description: Serialization of a polynomial
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYBYTES bytes)
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_tobytes(unsigned char *r, poly *a) {
int i;
uint16_t t0, t1;

for (i = 0; i < KYBER_N / 8; i++) {
for (j = 0; j < 8; j++) {
t[j] = PQCLEAN_KYBER768_CLEAN_freeze(a->coeffs[8 * i + j]);
}
PQCLEAN_KYBER768_CLEAN_poly_csubq(a);

r[13 * i + 0] = (unsigned char)( t[0] & 0xff);
r[13 * i + 1] = (unsigned char)((t[0] >> 8) | ((t[1] & 0x07) << 5));
r[13 * i + 2] = (unsigned char)((t[1] >> 3) & 0xff);
r[13 * i + 3] = (unsigned char)((t[1] >> 11) | ((t[2] & 0x3f) << 2));
r[13 * i + 4] = (unsigned char)((t[2] >> 6) | ((t[3] & 0x01) << 7));
r[13 * i + 5] = (unsigned char)((t[3] >> 1) & 0xff);
r[13 * i + 6] = (unsigned char)((t[3] >> 9) | ((t[4] & 0x0f) << 4));
r[13 * i + 7] = (unsigned char)((t[4] >> 4) & 0xff);
r[13 * i + 8] = (unsigned char)((t[4] >> 12) | ((t[5] & 0x7f) << 1));
r[13 * i + 9] = (unsigned char)((t[5] >> 7) | ((t[6] & 0x03) << 6));
r[13 * i + 10] = (unsigned char)((t[6] >> 2) & 0xff);
r[13 * i + 11] = (unsigned char)((t[6] >> 10) | ((t[7] & 0x1f) << 3));
r[13 * i + 12] = (unsigned char)((t[7] >> 5));
for (i = 0; i < KYBER_N / 2; i++) {
t0 = a->coeffs[2 * i];
t1 = a->coeffs[2 * i + 1];
r[3 * i] = t0 & 0xff;
r[3 * i + 1] = (t0 >> 8) | ((t1 & 0xf) << 4);
r[3 * i + 2] = (t1 >> 4) & 0xff;
}
}

/*************************************************
* Name: poly_frombytes
*
* Description: De-serialization of a polynomial;
* inverse of poly_tobytes
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_frombytes
*
* Description: De-serialization of a polynomial;
* inverse of PQCLEAN_KYBER768_CLEAN_poly_tobytes
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *a: pointer to input byte array (of KYBER_POLYBYTES bytes)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_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);

for (i = 0; i < KYBER_N / 2; i++) {
r->coeffs[2 * i] = a[3 * i] | ((uint16_t)a[3 * i + 1] & 0x0f) << 8;
r->coeffs[2 * i + 1] = a[3 * i + 1] >> 4 | ((uint16_t)a[3 * i + 2] & 0xff) << 4;
}
}

/*************************************************
* Name: poly_getnoise
*
* Description: Sample a polynomial deterministically from a seed and a nonce,
* with output polynomial close to centered binomial distribution
* with parameter KYBER_ETA
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *seed: pointer to input seed
* - unsigned char nonce: one-byte input nonce
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_getnoise
*
* Description: Sample a polynomial deterministically from a seed and a nonce,
* with output polynomial close to centered binomial distribution
* with parameter KYBER_ETA
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *seed: pointer to input seed (pointing to array of length KYBER_SYMBYTES bytes)
* - unsigned char nonce: one-byte input nonce
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce) {
unsigned char buf[KYBER_ETA * KYBER_N / 4];
unsigned char extseed[KYBER_SYMBYTES + 1];
int i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extseed[i] = seed[i];
}
extseed[KYBER_SYMBYTES] = nonce;

shake256(buf, KYBER_ETA * KYBER_N / 4, extseed, KYBER_SYMBYTES + 1);

prf(buf, KYBER_ETA * KYBER_N / 4, seed, nonce);
PQCLEAN_KYBER768_CLEAN_cbd(r, buf);
}

/*************************************************
* Name: poly_ntt
*
* Description: Computes negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in normal order, output in bitreversed
*order
*
* Arguments: - uint16_t *r: pointer to in/output polynomial
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_ntt
*
* Description: Computes negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in normal order, output in bitreversed order
*
* Arguments: - uint16_t *r: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_ntt(poly *r) {
PQCLEAN_KYBER768_CLEAN_ntt(r->coeffs);
PQCLEAN_KYBER768_CLEAN_poly_reduce(r);
}

/*************************************************
* Name: poly_invntt
*
* Description: Computes inverse of negacyclic number-theoretic transform (NTT)
*of a polynomial in place; inputs assumed to be in bitreversed order, output in
*normal order
*
* Arguments: - uint16_t *a: pointer to in/output polynomial
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_invntt
*
* Description: Computes inverse of negacyclic number-theoretic transform (NTT) of
* a polynomial in place;
* inputs assumed to be in bitreversed order, output in normal order
*
* Arguments: - uint16_t *a: pointer to in/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_invntt(poly *r) {
PQCLEAN_KYBER768_CLEAN_invntt(r->coeffs);
}

/*************************************************
* Name: poly_add
*
* Description: Add two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_basemul
*
* Description: Multiplication of two polynomials in NTT domain
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_basemul(poly *r, const poly *a, const poly *b) {
unsigned int i;

for (i = 0; i < KYBER_N / 4; ++i) {
PQCLEAN_KYBER768_CLEAN_basemul(r->coeffs + 4 * i, a->coeffs + 4 * i, b->coeffs + 4 * i, PQCLEAN_KYBER768_CLEAN_zetas[64 + i]);
PQCLEAN_KYBER768_CLEAN_basemul(r->coeffs + 4 * i + 2, a->coeffs + 4 * i + 2, b->coeffs + 4 * i + 2, - PQCLEAN_KYBER768_CLEAN_zetas[64 + i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_poly_frommont
*
* Description: Inplace conversion of all coefficients of a polynomial
* from Montgomery domain to normal domain
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_frommont(poly *r) {
int i;
const int16_t f = (1ULL << 32) % KYBER_Q;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER768_CLEAN_montgomery_reduce((int32_t)r->coeffs[i] * f);
}
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_poly_reduce
*
* Description: Applies Barrett reduction to all coefficients of a polynomial
* for details of the Barrett reduction see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_reduce(poly *r) {
int i;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(r->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_poly_csubq
*
* Description: Applies conditional subtraction of q to each coefficient of a polynomial
* for details of conditional subtraction of q see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_csubq(poly *r) {
int i;

for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER768_CLEAN_csubq(r->coeffs[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_poly_add
*
* Description: Add two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_add(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(a->coeffs[i] + b->coeffs[i]);
r->coeffs[i] = a->coeffs[i] + b->coeffs[i];
}
}

/*************************************************
* Name: poly_sub
*
* Description: Subtract two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_sub
*
* Description: Subtract two polynomials
*
* Arguments: - poly *r: pointer to output polynomial
* - const poly *a: pointer to first input polynomial
* - const poly *b: pointer to second input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_sub(poly *r, const poly *a, const poly *b) {
int i;
for (i = 0; i < KYBER_N; i++) {
r->coeffs[i] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(a->coeffs[i] + 3 * KYBER_Q - b->coeffs[i]);
r->coeffs[i] = a->coeffs[i] - b->coeffs[i];
}
}

/*************************************************
* Name: poly_frommsg
*
* Description: Convert 32-byte message to polynomial
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *msg: pointer to input message
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_poly_frommsg
*
* Description: Convert 32-byte message to polynomial
*
* Arguments: - poly *r: pointer to output polynomial
* - const unsigned char *msg: pointer to input message
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]) {
uint16_t i, j, mask;
int i, j;
uint16_t mask;

for (i = 0; i < KYBER_SYMBYTES; i++) {
for (j = 0; j < 8; j++) {
@@ -215,21 +265,23 @@ void PQCLEAN_KYBER768_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_
}

/*************************************************
* Name: poly_tomsg
*
* Description: Convert polynomial to 32-byte message
*
* Arguments: - unsigned char *msg: pointer to output message
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], const poly *a) {
* Name: PQCLEAN_KYBER768_CLEAN_poly_tomsg
*
* Description: Convert polynomial to 32-byte message
*
* Arguments: - unsigned char *msg: pointer to output message
* - const poly *a: pointer to input polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a) {
uint16_t t;
int i, j;

PQCLEAN_KYBER768_CLEAN_poly_csubq(a);

for (i = 0; i < KYBER_SYMBYTES; i++) {
msg[i] = 0;
for (j = 0; j < 8; j++) {
t = (((PQCLEAN_KYBER768_CLEAN_freeze(a->coeffs[8 * i + j]) << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
t = (((a->coeffs[8 * i + j] << 1) + KYBER_Q / 2) / KYBER_Q) & 1;
msg[i] |= t << j;
}
}


+ 10
- 4
crypto_kem/kyber768/clean/poly.h View File

@@ -2,6 +2,7 @@
#define POLY_H

#include "params.h"

#include <stdint.h>

/*
@@ -9,22 +10,27 @@
* coeffs[0] + X*coeffs[1] + X^2*xoeffs[2] + ... + X^{n-1}*coeffs[n-1]
*/
typedef struct {
uint16_t coeffs[KYBER_N];
int16_t coeffs[KYBER_N];
} poly;

void PQCLEAN_KYBER768_CLEAN_poly_compress(unsigned char *r, const poly *a);
void PQCLEAN_KYBER768_CLEAN_poly_compress(unsigned char *r, poly *a);
void PQCLEAN_KYBER768_CLEAN_poly_decompress(poly *r, const unsigned char *a);

void PQCLEAN_KYBER768_CLEAN_poly_tobytes(unsigned char *r, const poly *a);
void PQCLEAN_KYBER768_CLEAN_poly_tobytes(unsigned char *r, poly *a);
void PQCLEAN_KYBER768_CLEAN_poly_frombytes(poly *r, const unsigned char *a);

void PQCLEAN_KYBER768_CLEAN_poly_frommsg(poly *r, const unsigned char msg[KYBER_SYMBYTES]);
void PQCLEAN_KYBER768_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], const poly *a);
void PQCLEAN_KYBER768_CLEAN_poly_tomsg(unsigned char msg[KYBER_SYMBYTES], poly *a);

void PQCLEAN_KYBER768_CLEAN_poly_getnoise(poly *r, const unsigned char *seed, unsigned char nonce);

void PQCLEAN_KYBER768_CLEAN_poly_ntt(poly *r);
void PQCLEAN_KYBER768_CLEAN_poly_invntt(poly *r);
void PQCLEAN_KYBER768_CLEAN_poly_basemul(poly *r, const poly *a, const poly *b);
void PQCLEAN_KYBER768_CLEAN_poly_frommont(poly *r);

void PQCLEAN_KYBER768_CLEAN_poly_reduce(poly *r);
void PQCLEAN_KYBER768_CLEAN_poly_csubq(poly *r);

void PQCLEAN_KYBER768_CLEAN_poly_add(poly *r, const poly *a, const poly *b);
void PQCLEAN_KYBER768_CLEAN_poly_sub(poly *r, const poly *a, const poly *b);


+ 124
- 100
crypto_kem/kyber768/clean/polyvec.c View File

@@ -1,77 +1,70 @@
#include "polyvec.h"
#include "cbd.h"
#include "fips202.h"
#include "reduce.h"
#include <stdio.h>
#include "poly.h"
#include <stdint.h>

/*************************************************
* Name: polyvec_compress
*
* Description: Compress and serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_compress(unsigned char *r, const polyvec *a) {
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_compress
*
* Description: Compress and serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECCOMPRESSEDBYTES)
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_compress(unsigned char *r, polyvec *a) {
int i, j, k;
uint16_t t[8];

PQCLEAN_KYBER768_CLEAN_polyvec_csubq(a);

uint16_t t[4];
for (i = 0; i < KYBER_K; i++) {
for (j = 0; j < KYBER_N / 8; j++) {
for (k = 0; k < 8; k++) {
t[k] = ((((uint32_t)PQCLEAN_KYBER768_CLEAN_freeze(a->vec[i].coeffs[8 * j + k]) << 11) + KYBER_Q / 2) / KYBER_Q) & 0x7ff;
for (j = 0; j < KYBER_N / 4; j++) {
for (k = 0; k < 4; k++) {
t[k] = ((((uint32_t)a->vec[i].coeffs[4 * j + k] << 10) + KYBER_Q / 2) / KYBER_Q) & 0x3ff;
}

r[11 * j + 0] = (unsigned char)( t[0] & 0xff);
r[11 * j + 1] = (unsigned char)((t[0] >> 8) | ((t[1] & 0x1f) << 3));
r[11 * j + 2] = (unsigned char)((t[1] >> 5) | ((t[2] & 0x03) << 6));
r[11 * j + 3] = (unsigned char)((t[2] >> 2) & 0xff);
r[11 * j + 4] = (unsigned char)((t[2] >> 10) | ((t[3] & 0x7f) << 1));
r[11 * j + 5] = (unsigned char)((t[3] >> 7) | ((t[4] & 0x0f) << 4));
r[11 * j + 6] = (unsigned char)((t[4] >> 4) | ((t[5] & 0x01) << 7));
r[11 * j + 7] = (unsigned char)((t[5] >> 1) & 0xff);
r[11 * j + 8] = (unsigned char)((t[5] >> 9) | ((t[6] & 0x3f) << 2));
r[11 * j + 9] = (unsigned char)((t[6] >> 6) | ((t[7] & 0x07) << 5));
r[11 * j + 10] = (unsigned char)((t[7] >> 3));
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)) & 0xff;
r[5 * j + 3] = ((t[2] >> 4) | ((t[3] & 0x03) << 6)) & 0xff;
r[5 * j + 4] = (t[3] >> 2) & 0xff;
}
r += 352;
r += 320;
}
}

/*************************************************
* Name: polyvec_decompress
*
* Description: De-serialize and decompress vector of polynomials;
* approximate inverse of polyvec_compress
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - unsigned char *a: pointer to input byte array
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_decompress
*
* Description: De-serialize and decompress vector of polynomials;
* approximate inverse of PQCLEAN_KYBER768_CLEAN_polyvec_compress
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - unsigned char *a: pointer to input byte array (of length KYBER_POLYVECCOMPRESSEDBYTES)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_decompress(polyvec *r, const unsigned char *a) {
int i, j;
for (i = 0; i < KYBER_K; 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;
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 += 352;
a += 320;
}
}

/*************************************************
* Name: polyvec_tobytes
*
* Description: Serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(unsigned char *r, const polyvec *a) {
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_tobytes
*
* Description: Serialize vector of polynomials
*
* Arguments: - unsigned char *r: pointer to output byte array (needs space for KYBER_POLYVECBYTES)
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(unsigned char *r, polyvec *a) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_tobytes(r + i * KYBER_POLYBYTES, &a->vec[i]);
@@ -79,14 +72,14 @@ void PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(unsigned char *r, const polyvec *a)
}

/*************************************************
* Name: polyvec_frombytes
*
* Description: De-serialize vector of polynomials;
* inverse of polyvec_tobytes
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const polyvec *a: pointer to input vector of polynomials
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_frombytes
*
* Description: De-serialize vector of polynomials;
* inverse of PQCLEAN_KYBER768_CLEAN_polyvec_tobytes
*
* Arguments: - unsigned char *r: pointer to output byte array
* - const polyvec *a: pointer to input vector of polynomials (of length KYBER_POLYVECBYTES)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a) {
int i;
for (i = 0; i < KYBER_K; i++) {
@@ -95,12 +88,12 @@ void PQCLEAN_KYBER768_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a
}

/*************************************************
* Name: polyvec_ntt
*
* Description: Apply forward NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_ntt
*
* Description: Apply forward NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_ntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
@@ -109,12 +102,12 @@ void PQCLEAN_KYBER768_CLEAN_polyvec_ntt(polyvec *r) {
}

/*************************************************
* Name: polyvec_invntt
*
* Description: Apply inverse NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_invntt
*
* Description: Apply inverse NTT to all elements of a vector of polynomials
*
* Arguments: - polyvec *r: pointer to in/output vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_invntt(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
@@ -123,37 +116,68 @@ void PQCLEAN_KYBER768_CLEAN_polyvec_invntt(polyvec *r) {
}

/*************************************************
* Name: polyvec_pointwise_acc
*
* Description: Pointwise multiply elements of a and b and accumulate into r
*
* Arguments: - poly *r: pointer to output polynomial
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc
*
* Description: Pointwise multiply elements of a and b and accumulate into r
*
* Arguments: - poly *r: pointer to output polynomial
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_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 = PQCLEAN_KYBER768_CLEAN_montgomery_reduce(4613 * (uint32_t)b->vec[0].coeffs[j]); // 4613 = 2^{2*18} % q
r->coeffs[j] = PQCLEAN_KYBER768_CLEAN_montgomery_reduce(a->vec[0].coeffs[j] * t);
for (i = 1; i < KYBER_K; i++) {
t = PQCLEAN_KYBER768_CLEAN_montgomery_reduce(4613 * (uint32_t)b->vec[i].coeffs[j]);
r->coeffs[j] += PQCLEAN_KYBER768_CLEAN_montgomery_reduce(a->vec[i].coeffs[j] * t);
}
r->coeffs[j] = PQCLEAN_KYBER768_CLEAN_barrett_reduce(r->coeffs[j]);
int i;
poly t;

PQCLEAN_KYBER768_CLEAN_poly_basemul(r, &a->vec[0], &b->vec[0]);
for (i = 1; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_basemul(&t, &a->vec[i], &b->vec[i]);
PQCLEAN_KYBER768_CLEAN_poly_add(r, r, &t);
}

PQCLEAN_KYBER768_CLEAN_poly_reduce(r);
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_reduce
*
* Description: Applies Barrett reduction to each coefficient
* of each element of a vector of polynomials
* for details of the Barrett reduction see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_reduce(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_reduce(&r->vec[i]);
}
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_csubq
*
* Description: Applies conditional subtraction of q to each coefficient
* of each element of a vector of polynomials
* for details of conditional subtraction of q see comments in reduce.c
*
* Arguments: - poly *r: pointer to input/output polynomial
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_csubq(polyvec *r) {
int i;
for (i = 0; i < KYBER_K; i++) {
PQCLEAN_KYBER768_CLEAN_poly_csubq(&r->vec[i]);
}
}

/*************************************************
* Name: polyvec_add
*
* Description: Add vectors of polynomials
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
* Name: PQCLEAN_KYBER768_CLEAN_polyvec_add
*
* Description: Add vectors of polynomials
*
* Arguments: - polyvec *r: pointer to output vector of polynomials
* - const polyvec *a: pointer to first input vector of polynomials
* - const polyvec *b: pointer to second input vector of polynomials
**************************************************/
void PQCLEAN_KYBER768_CLEAN_polyvec_add(polyvec *r, const polyvec *a, const polyvec *b) {
int i;
for (i = 0; i < KYBER_K; i++) {


+ 5
- 2
crypto_kem/kyber768/clean/polyvec.h View File

@@ -8,10 +8,10 @@ typedef struct {
poly vec[KYBER_K];
} polyvec;

void PQCLEAN_KYBER768_CLEAN_polyvec_compress(unsigned char *r, const polyvec *a);
void PQCLEAN_KYBER768_CLEAN_polyvec_compress(unsigned char *r, polyvec *a);
void PQCLEAN_KYBER768_CLEAN_polyvec_decompress(polyvec *r, const unsigned char *a);

void PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(unsigned char *r, const polyvec *a);
void PQCLEAN_KYBER768_CLEAN_polyvec_tobytes(unsigned char *r, polyvec *a);
void PQCLEAN_KYBER768_CLEAN_polyvec_frombytes(polyvec *r, const unsigned char *a);

void PQCLEAN_KYBER768_CLEAN_polyvec_ntt(polyvec *r);
@@ -19,6 +19,9 @@ void PQCLEAN_KYBER768_CLEAN_polyvec_invntt(polyvec *r);

void PQCLEAN_KYBER768_CLEAN_polyvec_pointwise_acc(poly *r, const polyvec *a, const polyvec *b);

void PQCLEAN_KYBER768_CLEAN_polyvec_reduce(polyvec *r);
void PQCLEAN_KYBER768_CLEAN_polyvec_csubq(polyvec *r);

void PQCLEAN_KYBER768_CLEAN_polyvec_add(polyvec *r, const polyvec *a, const polyvec *b);

#endif

+ 0
- 100
crypto_kem/kyber768/clean/precomp.c View File

@@ -1,100 +0,0 @@
#include "inttypes.h"
#include "ntt.h"
#include "params.h"

/* Precomputed constants for the forward NTT and inverse NTT.
* Computed using Pari/GP as follows:
*
brv=[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];

q = 7681;
n = 256;
mont = Mod(2^18,q);

g=0; for(i=2,q-1,if(znorder(Mod(i,q)) == 2*n, g=Mod(i,q); break))

zetas = lift(vector(n, i, g^(brv[i])*mont))
omegas_inv_bitrev_montgomery = lift(vector(n/2, i,
(g^2)^(-brv[2*(i-1)+1])*mont)) psis_inv_montgomery = lift(vector(n, i,
g^(-(i-1))/n*mont))

*/

const uint16_t PQCLEAN_KYBER768_CLEAN_zetas[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
};

const uint16_t PQCLEAN_KYBER768_CLEAN_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
};

const uint16_t PQCLEAN_KYBER768_CLEAN_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
};

+ 50
- 58
crypto_kem/kyber768/clean/reduce.c View File

@@ -1,70 +1,62 @@
#include "reduce.h"

#include "params.h"

static const uint32_t qinv = 7679; // -inverse_mod(q,2^18)
static const uint32_t rlog = 18;
#include <stdint.h>

/*************************************************
* Name: montgomery_reduce
*
* Description: Montgomery reduction; given a 32-bit integer a, computes
* 16-bit integer congruent to a * R^-1 mod q,
* where R=2^18 (see value of rlog)
*
* Arguments: - uint32_t a: input unsigned integer to be reduced; has to be in
*{0,...,2281446912}
*
* Returns: unsigned integer in {0,...,2^13-1} congruent to a * R^-1 modulo
*q.
**************************************************/
uint16_t PQCLEAN_KYBER768_CLEAN_montgomery_reduce(uint32_t a) {
uint32_t u;

u = (a * qinv);
u &= ((1 << rlog) - 1);
u *= KYBER_Q;
a = a + u;
return (uint16_t)(a >> rlog);
* Name: PQCLEAN_KYBER768_CLEAN_montgomery_reduce
*
* Description: Montgomery reduction; given a 32-bit integer a, computes
* 16-bit integer congruent to a * R^-1 mod q,
* where R=2^16
*
* Arguments: - int32_t a: input integer to be reduced; has to be in {-q2^15,...,q2^15-1}
*
* Returns: integer in {-q+1,...,q-1} congruent to a * R^-1 modulo q.
**************************************************/
int16_t PQCLEAN_KYBER768_CLEAN_montgomery_reduce(int32_t a) {
int32_t t;
int16_t u;

u = (int16_t)(a * QINV);
t = (int32_t)u * KYBER_Q;
t = a - t;
t >>= 16;
return (int16_t)t;
}

/*************************************************
* Name: barrett_reduce
*
* Description: Barrett reduction; given a 16-bit integer a, computes
* 16-bit integer congruent to a mod q in {0,...,11768}
*
* Arguments: - uint16_t a: input unsigned integer to be reduced
*
* Returns: unsigned integer in {0,...,11768} congruent to a modulo q.
**************************************************/
uint16_t PQCLEAN_KYBER768_CLEAN_barrett_reduce(uint16_t a) {
uint16_t u;

u = a >> 13; //((uint32_t) a * sinv) >> 16;
u *= KYBER_Q;
a -= u;
return a;
* Name: PQCLEAN_KYBER768_CLEAN_barrett_reduce
*
* Description: Barrett reduction; given a 16-bit integer a, computes
* 16-bit integer congruent to a mod q in {0,...,q}
*
* Arguments: - int16_t a: input integer to be reduced
*
* Returns: integer in {0,...,q} congruent to a modulo q.
**************************************************/
int16_t PQCLEAN_KYBER768_CLEAN_barrett_reduce(int16_t a) {
int32_t t;
const int32_t v = (1U << 26) / KYBER_Q + 1;

t = v * a;
t >>= 26;
t *= KYBER_Q;
return (int16_t)(a - t);
}

/*************************************************
* Name: freeze
*
* Description: Full reduction; given a 16-bit integer a, computes
* unsigned integer a mod q.
*
* Arguments: - uint16_t x: input unsigned integer to be reduced
*
* Returns: unsigned integer in {0,...,q-1} congruent to a modulo q.
**************************************************/
uint16_t PQCLEAN_KYBER768_CLEAN_freeze(uint16_t x) {
uint16_t m, r;
int16_t c;
r = PQCLEAN_KYBER768_CLEAN_barrett_reduce(x);

m = r - KYBER_Q;
c = m;
c >>= 15;
r = m ^ ((r ^ m) & c);

return r;
* Name: PQCLEAN_KYBER768_CLEAN_csubq
*
* Description: Conditionallly subtract q
*
* Arguments: - int16_t x: input integer
*
* Returns: a - q if a >= q, else a
**************************************************/
int16_t PQCLEAN_KYBER768_CLEAN_csubq(int16_t a) {
a -= KYBER_Q;
a += (a >> 15) & KYBER_Q;
return a;
}

+ 6
- 3
crypto_kem/kyber768/clean/reduce.h View File

@@ -3,10 +3,13 @@

#include <stdint.h>

uint16_t PQCLEAN_KYBER768_CLEAN_freeze(uint16_t x);
#define MONT 2285 // 2^16 % Q
#define QINV 62209 // q^(-1) mod 2^16

uint16_t PQCLEAN_KYBER768_CLEAN_montgomery_reduce(uint32_t a);
int16_t PQCLEAN_KYBER768_CLEAN_montgomery_reduce(int32_t a);

uint16_t PQCLEAN_KYBER768_CLEAN_barrett_reduce(uint16_t a);
int16_t PQCLEAN_KYBER768_CLEAN_barrett_reduce(int16_t a);

int16_t PQCLEAN_KYBER768_CLEAN_csubq(int16_t a);

#endif

+ 64
- 0
crypto_kem/kyber768/clean/symmetric-fips202.c View File

@@ -0,0 +1,64 @@
#include "fips202.h"
#include "symmetric.h"

#include <stdlib.h>

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb
*
* Description: Absorb step of the SHAKE128 specialized for the Kyber context.
*
* Arguments: - uint64_t *s: pointer to (uninitialized) output Keccak state
* - const unsigned char *input: pointer to KYBER_SYMBYTES input to be absorbed into s
* - unsigned char i additional byte of input
* - unsigned char j additional byte of input
**************************************************/
void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y) {
unsigned char extseed[KYBER_SYMBYTES + 2];
int i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extseed[i] = input[i];
}
extseed[i++] = x;
extseed[i] = y;
shake128_absorb(s->s, extseed, KYBER_SYMBYTES + 2);
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks
*
* Description: Squeeze step of SHAKE128 XOF. Squeezes full blocks of SHAKE128_RATE bytes each.
* Modifies the state. Can be called multiple times to keep squeezing,
* i.e., is incremental.
*
* Arguments: - unsigned char *output: pointer to output blocks
* - size_t nblocks: number of blocks to be squeezed (written to output)
* - keccak_state *s: pointer to in/output Keccak state
**************************************************/
void PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s) {
shake128_squeezeblocks(output, nblocks, s->s);
}

/*************************************************
* Name: PQCLEAN_KYBER768_CLEAN_shake256_prf
*
* Description: Usage of SHAKE256 as a PRF, concatenates secret and public input
* and then generates outlen bytes of SHAKE256 output
*
* Arguments: - unsigned char *output: pointer to output
* - size_t outlen: number of requested output bytes
* - const unsigned char * key: pointer to the key (of length KYBER_SYMBYTES)
* - const unsigned char nonce: single-byte nonce (public PRF input)
**************************************************/
void PQCLEAN_KYBER768_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce) {
unsigned char extkey[KYBER_SYMBYTES + 1];
size_t i;

for (i = 0; i < KYBER_SYMBYTES; i++) {
extkey[i] = key[i];
}
extkey[i] = nonce;

shake256(output, outlen, extkey, KYBER_SYMBYTES + 1);
}

+ 26
- 0
crypto_kem/kyber768/clean/symmetric.h View File

@@ -0,0 +1,26 @@
#ifndef SYMMETRIC_H
#define SYMMETRIC_H

#include "fips202.h"
#include "params.h"

typedef struct {
uint64_t s[25];
} keccak_state;

void PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(keccak_state *s, const unsigned char *input, unsigned char x, unsigned char y);
void PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(unsigned char *output, size_t nblocks, keccak_state *s);
void PQCLEAN_KYBER768_CLEAN_shake256_prf(unsigned char *output, size_t outlen, const unsigned char *key, unsigned char nonce);

#define hash_h(OUT, IN, INBYTES) sha3_256(OUT, IN, INBYTES)
#define hash_g(OUT, IN, INBYTES) sha3_512(OUT, IN, INBYTES)
#define xof_absorb(STATE, IN, X, Y) PQCLEAN_KYBER768_CLEAN_kyber_shake128_absorb(STATE, IN, X, Y)
#define xof_squeezeblocks(OUT, OUTBLOCKS, STATE) PQCLEAN_KYBER768_CLEAN_kyber_shake128_squeezeblocks(OUT, OUTBLOCKS, STATE)
#define prf(OUT, OUTBYTES, KEY, NONCE) PQCLEAN_KYBER768_CLEAN_shake256_prf(OUT, OUTBYTES, KEY, NONCE)
#define kdf(OUT, IN, INBYTES) shake256(OUT, KYBER_SSBYTES, IN, INBYTES)

#define XOF_BLOCKBYTES 168

typedef keccak_state xof_state;

#endif /* SYMMETRIC_H */

+ 30
- 29
crypto_kem/kyber768/clean/verify.c View File

@@ -1,45 +1,46 @@
#include <stdint.h>
#include <string.h>

#include "verify.h"

#include <stdint.h>
#include <stdlib.h>

/*************************************************
* Name: verify
*
* Description: Compare two arrays for equality in constant time.
*
* Arguments: const unsigned char *a: pointer to first byte array
* const unsigned char *b: pointer to second byte array
* size_t len: length of the byte arrays
*
* Returns 0 if the byte arrays are equal, 1 otherwise
**************************************************/
int PQCLEAN_KYBER768_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) {
* Name: verify
*
* Description: Compare two arrays for equality in constant time.
*
* Arguments: const unsigned char *a: pointer to first byte array
* const unsigned char *b: pointer to second byte array
* size_t len: length of the byte arrays
*
* Returns 0 if the byte arrays are equal, 1 otherwise
**************************************************/
unsigned char PQCLEAN_KYBER768_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len) {
uint64_t r;
size_t i;
r = 0;

r = 0;
for (i = 0; i < len; i++) {
r |= a[i] ^ b[i];
}

r = (-(int64_t)r) >> 63;
return (int)r;
r = (~r + 1); // Two's complement
r >>= 63;
return (unsigned char)r;
}

/*************************************************
* Name: cmov
*
* Description: Copy len bytes from x to r if b is 1;
* don't modify x if b is 0. Requires b to be in {0,1};
* assumes two's complement representation of negative integers.
* Runs in constant time.
*
* Arguments: unsigned char *r: pointer to output byte array
* const unsigned char *x: pointer to input byte array
* size_t len: Amount of bytes to be copied
* unsigned char b: Condition bit; has to be in {0,1}
**************************************************/
* Name: cmov
*
* Description: Copy len bytes from x to r if b is 1;
* don't modify x if b is 0. Requires b to be in {0,1};
* assumes two's complement representation of negative integers.
* Runs in constant time.
*
* Arguments: unsigned char *r: pointer to output byte array
* const unsigned char *x: pointer to input byte array
* size_t len: Amount of bytes to be copied
* unsigned char b: Condition bit; has to be in {0,1}
**************************************************/
void PQCLEAN_KYBER768_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) {
size_t i;



+ 1
- 1
crypto_kem/kyber768/clean/verify.h View File

@@ -3,7 +3,7 @@

#include <stdio.h>

int PQCLEAN_KYBER768_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);
unsigned char PQCLEAN_KYBER768_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);

void PQCLEAN_KYBER768_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);



+ 0
- 4
test/test_nistkat.py View File

@@ -25,10 +25,6 @@ def test_nistkat():

@helpers.filtered_test
def check_nistkat(implementation):
if implementation.scheme.name == "kyber768":
raise unittest.SkipTest(
"Temporarily skip NIST KAT check for kyber768 since it's "
"an outdated implementation")
helpers.make('nistkat',
TYPE=implementation.scheme.type,
SCHEME=implementation.scheme.name,


Loading…
Cancel
Save