Browse Source

Add ntruhps4096821

tags/v0.0.1
Douglas Stebila 5 years ago
parent
commit
ea8fd5886c
20 changed files with 1002 additions and 0 deletions
  1. +22
    -0
      crypto_kem/ntruhps4096821/META.yml
  2. +1
    -0
      crypto_kem/ntruhps4096821/clean/LICENSE
  3. +19
    -0
      crypto_kem/ntruhps4096821/clean/Makefile
  4. +19
    -0
      crypto_kem/ntruhps4096821/clean/Makefile.Microsoft_nmake
  5. +19
    -0
      crypto_kem/ntruhps4096821/clean/api.h
  6. +50
    -0
      crypto_kem/ntruhps4096821/clean/crypto_sort.c
  7. +6
    -0
      crypto_kem/ntruhps4096821/clean/crypto_sort.h
  8. +60
    -0
      crypto_kem/ntruhps4096821/clean/kem.c
  9. +174
    -0
      crypto_kem/ntruhps4096821/clean/owcpa.c
  10. +20
    -0
      crypto_kem/ntruhps4096821/clean/owcpa.h
  11. +32
    -0
      crypto_kem/ntruhps4096821/clean/pack3.c
  12. +36
    -0
      crypto_kem/ntruhps4096821/clean/packq.c
  13. +34
    -0
      crypto_kem/ntruhps4096821/clean/params.h
  14. +345
    -0
      crypto_kem/ntruhps4096821/clean/poly.c
  15. +38
    -0
      crypto_kem/ntruhps4096821/clean/poly.h
  16. +54
    -0
      crypto_kem/ntruhps4096821/clean/sample.c
  17. +16
    -0
      crypto_kem/ntruhps4096821/clean/sample.h
  18. +29
    -0
      crypto_kem/ntruhps4096821/clean/verify.c
  19. +12
    -0
      crypto_kem/ntruhps4096821/clean/verify.h
  20. +16
    -0
      test/duplicate_consistency/ntruhps4096821_clean.yml

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

@@ -0,0 +1,22 @@
name: ntru-hps4096821
type: kem
claimed-nist-level: 5
length-public-key: 1230
length-ciphertext: 1230
length-shared-secret: 32
testvectors-sha256: 099c3d9b6700608f9c7c95b89efbda75841a1e620a0d3bb0b6e7d403ca249e3f
nistkat-sha256: 0c5b6b159fab6eb677da469ec35aaa7e6b16162b315dcdb55a3b5da857e10519
principal-submitter: John M. Schanck
auxiliary-submitters:
- Cong Chen
- Oussama Danba
- Jeffrey Hoffstein
- Andreas Hülsing
- Joost Rijneveld
- Peter Schwabe
- William Whyte
- Zhenfei Zhang
implementations:
- name: clean
version: https://csrc.nist.gov/CSRC/media/Projects/Post-Quantum-Cryptography/documents/round-2/submissions/NTRU-Round2.zip reference implemntation
length-secret-key: 1590

+ 1
- 0
crypto_kem/ntruhps4096821/clean/LICENSE View File

@@ -0,0 +1 @@
Public Domain

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

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

LIB=libntruhps4096821_clean.a
HEADERS=api.h crypto_sort.h owcpa.h params.h poly.h sample.h verify.h
OBJECTS=crypto_sort.o kem.o owcpa.o pack3.o packq.o poly.o sample.o verify.o

CFLAGS=-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/ntruhps4096821/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=libntruhps4096821_clean.lib
OBJECTS=crypto_sort.obj kem.obj owcpa.obj pack3.obj packq.obj poly.obj sample.obj verify.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)

+ 19
- 0
crypto_kem/ntruhps4096821/clean/api.h View File

@@ -0,0 +1,19 @@
#ifndef PQCLEAN_NTRUHPS4096821_CLEAN_API_H
#define PQCLEAN_NTRUHPS4096821_CLEAN_API_H

#include <stdint.h>

#define PQCLEAN_NTRUHPS4096821_CLEAN_CRYPTO_SECRETKEYBYTES 1590
#define PQCLEAN_NTRUHPS4096821_CLEAN_CRYPTO_PUBLICKEYBYTES 1230
#define PQCLEAN_NTRUHPS4096821_CLEAN_CRYPTO_CIPHERTEXTBYTES 1230
#define PQCLEAN_NTRUHPS4096821_CLEAN_CRYPTO_BYTES 32

#define PQCLEAN_NTRUHPS4096821_CLEAN_CRYPTO_ALGNAME "NTRU-HPS4096821"

int PQCLEAN_NTRUHPS4096821_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);

int PQCLEAN_NTRUHPS4096821_CLEAN_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk);

int PQCLEAN_NTRUHPS4096821_CLEAN_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk);

#endif

+ 50
- 0
crypto_kem/ntruhps4096821/clean/crypto_sort.c View File

@@ -0,0 +1,50 @@
// XXX: Temporary placeholder for a faster sort.
// Copied from supercop-20190110/crypto_sort/int32/portable3

#include <stdint.h>

#include "crypto_sort.h"

#define int32_MINMAX(a,b) \
do { \
int32_t ab = (b) ^ (a); \
int32_t c = (b) - (a); \
c ^= ab & (c ^ (b)); \
c >>= 31; \
c &= ab; \
(a) ^= c; \
(b) ^= c; \
} while(0)

void PQCLEAN_NTRUHPS4096821_CLEAN_crypto_sort(void *array, long long n) {
long long top, p, q, r, i;
int32_t *x = array;

if (n < 2) {
return;
}
top = 1;
while (top < n - top) {
top += top;
}

for (p = top; p > 0; p >>= 1) {
for (i = 0; i < n - p; ++i) {
if (!(i & p)) {
int32_MINMAX(x[i], x[i + p]);
}
}
i = 0;
for (q = top; q > p; q >>= 1) {
for (; i < n - q; ++i) {
if (!(i & p)) {
int32_t a = x[i + p];
for (r = q; r > p; r >>= 1) {
int32_MINMAX(a, x[i + r]);
}
x[i + p] = a;
}
}
}
}
}

+ 6
- 0
crypto_kem/ntruhps4096821/clean/crypto_sort.h View File

@@ -0,0 +1,6 @@
#ifndef CRYPTO_SORT
#define CRYPTO_SORT

void PQCLEAN_NTRUHPS4096821_CLEAN_crypto_sort(void *array, long long n);

#endif

+ 60
- 0
crypto_kem/ntruhps4096821/clean/kem.c View File

@@ -0,0 +1,60 @@
#include <stdint.h>

#include "api.h"
#include "fips202.h"
#include "owcpa.h"
#include "params.h"
#include "randombytes.h"
#include "verify.h"

// API FUNCTIONS
int PQCLEAN_NTRUHPS4096821_CLEAN_crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
uint8_t seed[NTRU_SAMPLE_FG_BYTES];

randombytes(seed, NTRU_SAMPLE_FG_BYTES);
PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_keypair(pk, sk, seed);

randombytes(sk + NTRU_OWCPA_SECRETKEYBYTES, NTRU_PRFKEYBYTES);

return 0;
}

int PQCLEAN_NTRUHPS4096821_CLEAN_crypto_kem_enc(uint8_t *c, uint8_t *k, const uint8_t *pk) {
uint8_t rm[NTRU_OWCPA_MSGBYTES];
uint8_t rm_seed[NTRU_SAMPLE_RM_BYTES];

randombytes(rm_seed, NTRU_SAMPLE_RM_BYTES);
PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_samplemsg(rm, rm_seed);

sha3_256(k, rm, NTRU_OWCPA_MSGBYTES);

PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_enc(c, rm, pk);

return 0;
}

int PQCLEAN_NTRUHPS4096821_CLEAN_crypto_kem_dec(uint8_t *k, const uint8_t *c, const uint8_t *sk) {
int i, fail;
uint8_t rm[NTRU_OWCPA_MSGBYTES];
uint8_t buf[NTRU_PRFKEYBYTES + NTRU_CIPHERTEXTBYTES];
uint8_t *cmp = buf + NTRU_PRFKEYBYTES;

fail = PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_dec(rm, c, sk);
/* If fail = 0 then c = Enc(h, rm), there is no need to re-encapsulate. */
/* See comment in PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_dec for details. */

sha3_256(k, rm, NTRU_OWCPA_MSGBYTES);

/* shake(secret PRF key || input ciphertext) */
for (i = 0; i < NTRU_PRFKEYBYTES; i++) {
buf[i] = sk[i + NTRU_OWCPA_SECRETKEYBYTES];
}
for (i = 0; i < NTRU_CIPHERTEXTBYTES; i++) {
cmp[i] = c[i];
}
sha3_256(rm, cmp, NTRU_PRFKEYBYTES + NTRU_CIPHERTEXTBYTES);

PQCLEAN_NTRUHPS4096821_CLEAN_cmov(k, rm, NTRU_SHAREDKEYBYTES, (unsigned char) fail);

return 0;
}

+ 174
- 0
crypto_kem/ntruhps4096821/clean/owcpa.c View File

@@ -0,0 +1,174 @@
#include "owcpa.h"
#include "poly.h"
#include "sample.h"

static int owcpa_check_r(const poly *r) {
/* Check that r is in message space. */
/* Note: Assumes that r has coefficients in {0, 1, ..., q-1} */
int i;
uint64_t t = 0;
uint16_t c;
for (i = 0; i < NTRU_N; i++) {
c = MODQ(r->coeffs[i] + 1);
t |= c & (NTRU_Q - 4); /* 0 if c is in {0,1,2,3} */
t |= (c + 1) & 0x4; /* 0 if c is in {0,1,2} */
}
t |= r->coeffs[NTRU_N - 1]; /* Coefficient n-1 must be zero */
t = (~t + 1); // two's complement
t >>= 63;
return (int) t;
}

static int owcpa_check_m(const poly *m) {
/* Check that m is in message space. */
/* Note: Assumes that m has coefficients in {0,1,2}. */
int i;
uint64_t t = 0;
uint16_t p1 = 0;
uint16_t m1 = 0;
for (i = 0; i < NTRU_N; i++) {
p1 += m->coeffs[i] & 0x01;
m1 += (m->coeffs[i] & 0x02) >> 1;
}
/* Need p1 = m1 and p1 + m1 = NTRU_WEIGHT */
t |= p1 ^ m1;
t |= (p1 + m1) ^ NTRU_WEIGHT;
t = (~t + 1); // two's complement
t >>= 63;
return (int) t;
}

void PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_samplemsg(unsigned char msg[NTRU_OWCPA_MSGBYTES],
const unsigned char seed[NTRU_SAMPLE_RM_BYTES]) {
poly r, m;

PQCLEAN_NTRUHPS4096821_CLEAN_sample_rm(&r, &m, seed);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(msg, &r);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(msg + NTRU_PACK_TRINARY_BYTES, &m);
}

void PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_keypair(unsigned char *pk,
unsigned char *sk,
const unsigned char seed[NTRU_SAMPLE_FG_BYTES]) {
int i;

poly x1, x2, x3, x4, x5;

poly *f = &x1, *invf_mod3 = &x2;
poly *g = &x3, *G = &x2;
poly *Gf = &x3, *invGf = &x4, *tmp = &x5;
poly *invh = &x3, *h = &x3;

PQCLEAN_NTRUHPS4096821_CLEAN_sample_fg(f, g, seed);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_inv(invf_mod3, f);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(sk, f);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(sk + NTRU_PACK_TRINARY_BYTES, invf_mod3);

/* Lift coeffs of f and g from Z_p to Z_q */
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(f);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(g);

/* G = 3*g */
for (i = 0; i < NTRU_N; i++) {
G->coeffs[i] = MODQ(3 * g->coeffs[i]);
}

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(Gf, G, f);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_inv(invGf, Gf);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(tmp, invGf, f);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_mul(invh, tmp, f);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_tobytes(sk + 2 * NTRU_PACK_TRINARY_BYTES, invh);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(tmp, invGf, G);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(h, tmp, G);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_tobytes(pk, h);
}


void PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_enc(unsigned char *c,
const unsigned char *rm,
const unsigned char *pk) {
int i;
poly x1, x2, x3;
poly *h = &x1, *liftm = &x1;
poly *r = &x2, *m = &x2;
poly *ct = &x3;

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_frombytes(h, pk);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_frombytes(r, rm);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(r);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(ct, r, h);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_frombytes(m, rm + NTRU_PACK_TRINARY_BYTES);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_lift(liftm, m);
for (i = 0; i < NTRU_N; i++) {
ct->coeffs[i] = MODQ(ct->coeffs[i] + liftm->coeffs[i]);
}

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_tobytes(c, ct);
}

int PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_dec(unsigned char *rm,
const unsigned char *ciphertext,
const unsigned char *secretkey) {
int i;
int fail;
poly x1, x2, x3, x4;

poly *c = &x1, *f = &x2, *cf = &x3;
poly *mf = &x2, *finv3 = &x3, *m = &x4;
poly *liftm = &x2, *invh = &x3, *r = &x4;
poly *b = &x1;

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_frombytes(c, ciphertext);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_frombytes(f, secretkey);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(f);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(cf, c, f);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_to_S3(mf, cf);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_frombytes(finv3, secretkey + NTRU_PACK_TRINARY_BYTES);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_mul(m, mf, finv3);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(rm + NTRU_PACK_TRINARY_BYTES, m);

/* NOTE: For the IND-CCA2 KEM we must ensure that c = Enc(h, (r,m)). */
/* We can avoid re-computing r*h + Lift(m) as long as we check that */
/* r (defined as b/h mod (q, Phi_n)) and m are in the message space. */
/* (m can take any value in S3 in NTRU_HRSS) */
fail = 0;
fail |= owcpa_check_m(m);

/* b = c - Lift(m) mod (q, x^n - 1) */
PQCLEAN_NTRUHPS4096821_CLEAN_poly_lift(liftm, m);
for (i = 0; i < NTRU_N; i++) {
b->coeffs[i] = MODQ(c->coeffs[i] - liftm->coeffs[i]);
}

/* r = b / h mod (q, Phi_n) */
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_frombytes(invh, secretkey + 2 * NTRU_PACK_TRINARY_BYTES);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_mul(r, b, invh);

/* NOTE: Our definition of r as b/h mod (q, Phi_n) follows Figure 4 of */
/* [Sch18] https://eprint.iacr.org/2018/1174/20181203:032458. */
/* This differs from Figure 10 of Saito--Xagawa--Yamakawa */
/* [SXY17] https://eprint.iacr.org/2017/1005/20180516:055500 */
/* where r gets a final reduction modulo p. */
/* We need this change to use Proposition 1 of [Sch18]. */

/* Proposition 1 of [Sch18] shows that re-encryption with (r,m) yields c. */
/* if and only if fail==0 after the following call to owcpa_check_r */
/* The procedure given in Fig. 8 of [Sch18] can be skipped because we have */
/* c(1) = 0 due to the use of poly_Rq_sum_zero_{to,from}bytes. */
fail |= owcpa_check_r(r);

PQCLEAN_NTRUHPS4096821_CLEAN_poly_trinary_Zq_to_Z3(r);
PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(rm, r);

return fail;
}

+ 20
- 0
crypto_kem/ntruhps4096821/clean/owcpa.h View File

@@ -0,0 +1,20 @@
#ifndef OWCPA_H
#define OWCPA_H

#include "params.h"

void PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_samplemsg(unsigned char msg[NTRU_OWCPA_MSGBYTES],
const unsigned char seed[NTRU_SEEDBYTES]);

void PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_keypair(unsigned char *pk,
unsigned char *sk,
const unsigned char seed[NTRU_SEEDBYTES]);

void PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_enc(unsigned char *c,
const unsigned char *rm,
const unsigned char *pk);

int PQCLEAN_NTRUHPS4096821_CLEAN_owcpa_dec(unsigned char *rm,
const unsigned char *ciphertext,
const unsigned char *secretkey);
#endif

+ 32
- 0
crypto_kem/ntruhps4096821/clean/pack3.c View File

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

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(unsigned char msg[NTRU_OWCPA_MSGBYTES], const poly *a) {
int i;
unsigned char c;

for (i = 0; i < NTRU_PACK_DEG / 5; i++) {
c = a->coeffs[5 * i + 4] & 255;
c = (3 * c + a->coeffs[5 * i + 3]) & 255;
c = (3 * c + a->coeffs[5 * i + 2]) & 255;
c = (3 * c + a->coeffs[5 * i + 1]) & 255;
c = (3 * c + a->coeffs[5 * i + 0]) & 255;
msg[i] = c;
}

}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_frombytes(poly *r, const unsigned char msg[NTRU_OWCPA_MSGBYTES]) {
int i;
unsigned char c;

for (i = 0; i < NTRU_PACK_DEG / 5; i++) {
c = msg[i];
r->coeffs[5 * i + 0] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(c);
r->coeffs[5 * i + 1] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(c * 171 >> 9); // this is division by 3
r->coeffs[5 * i + 2] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(c * 57 >> 9); // division by 3^2
r->coeffs[5 * i + 3] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(c * 19 >> 9); // division by 3^3
r->coeffs[5 * i + 4] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(c * 203 >> 14); // etc.
}
r->coeffs[NTRU_N - 1] = 0;
}


+ 36
- 0
crypto_kem/ntruhps4096821/clean/packq.c View File

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


void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_tobytes(unsigned char *r, const poly *a) {
int i;

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

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_frombytes(poly *r, const unsigned char *a) {
int i;
for (i = 0; i < NTRU_PACK_DEG / 2; i++) {
r->coeffs[2 * i + 0] = (a[3 * i + 0] >> 0) | (((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);
}
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_tobytes(unsigned char *r, const poly *a) {
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_tobytes(r, a);
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_frombytes(poly *r, const unsigned char *a) {
int i;
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_frombytes(r, a);

/* Set r[n-1] so that the sum of coefficients is zero mod q */
r->coeffs[NTRU_N - 1] = 0;
for (i = 0; i < NTRU_PACK_DEG; i++) {
r->coeffs[NTRU_N - 1] += r->coeffs[i];
}
r->coeffs[NTRU_N - 1] = MODQ(-(r->coeffs[NTRU_N - 1]));
}

+ 34
- 0
crypto_kem/ntruhps4096821/clean/params.h View File

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

#define NTRU_HPS
#define NTRU_N 821
#define NTRU_LOGQ 12

/* Do not modify below this line */

#define NTRU_Q (1 << NTRU_LOGQ)
#define NTRU_WEIGHT (NTRU_Q/8 - 2)

#define NTRU_SEEDBYTES 32
#define NTRU_PRFKEYBYTES 32
#define NTRU_SHAREDKEYBYTES 32

#define NTRU_SAMPLE_IID_BYTES (NTRU_N-1)
#define NTRU_SAMPLE_FT_BYTES ((30*(NTRU_N-1)+7)/8)
#define NTRU_SAMPLE_FG_BYTES (NTRU_SAMPLE_IID_BYTES+NTRU_SAMPLE_FT_BYTES)
#define NTRU_SAMPLE_RM_BYTES (NTRU_SAMPLE_IID_BYTES+NTRU_SAMPLE_FT_BYTES)

#define NTRU_PACK_DEG (NTRU_N-1)
#define NTRU_PACK_TRINARY_BYTES ((NTRU_PACK_DEG+4)/5)

#define NTRU_OWCPA_MSGBYTES (2*NTRU_PACK_TRINARY_BYTES)
#define NTRU_OWCPA_PUBLICKEYBYTES ((NTRU_LOGQ*NTRU_PACK_DEG+7)/8)
#define NTRU_OWCPA_SECRETKEYBYTES (2*NTRU_PACK_TRINARY_BYTES + NTRU_OWCPA_PUBLICKEYBYTES)
#define NTRU_OWCPA_BYTES ((NTRU_LOGQ*NTRU_PACK_DEG+7)/8)

#define NTRU_PUBLICKEYBYTES (NTRU_OWCPA_PUBLICKEYBYTES)
#define NTRU_SECRETKEYBYTES (NTRU_OWCPA_SECRETKEYBYTES + NTRU_PRFKEYBYTES)
#define NTRU_CIPHERTEXTBYTES (NTRU_OWCPA_BYTES)

#endif

+ 345
- 0
crypto_kem/ntruhps4096821/clean/poly.c View File

@@ -0,0 +1,345 @@
#include "poly.h"
#include "fips202.h"
#include "verify.h"

uint16_t PQCLEAN_NTRUHPS4096821_CLEAN_mod3(uint16_t a) {
uint16_t r;
int16_t t, c;

r = (a >> 8) + (a & 0xff); // r mod 255 == a mod 255
r = (r >> 4) + (r & 0xf); // r' mod 15 == r mod 15
r = (r >> 2) + (r & 0x3); // r' mod 3 == r mod 3
r = (r >> 2) + (r & 0x3); // r' mod 3 == r mod 3

t = r - 3;
c = t >> 15;

return (c & r) ^ (~c & t);
}

/* Map {0, 1, 2} -> {0,1,q-1} in place */
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(poly *r) {
int i;
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = r->coeffs[i] | ((-(r->coeffs[i] >> 1)) & (NTRU_Q - 1));
}
}

/* Map {0, 1, q-1} -> {0,1,2} in place */
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_trinary_Zq_to_Z3(poly *r) {
int i;
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = 3 & (r->coeffs[i] ^ (r->coeffs[i] >> (NTRU_LOGQ - 1)));
}
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(poly *r, const poly *a, const poly *b) {
int k, i;

for (k = 0; k < NTRU_N; k++) {
r->coeffs[k] = 0;
for (i = 1; i < NTRU_N - k; i++) {
r->coeffs[k] += a->coeffs[k + i] * b->coeffs[NTRU_N - i];
}
for (i = 0; i < k + 1; i++) {
r->coeffs[k] += a->coeffs[k - i] * b->coeffs[i];
}
r->coeffs[k] = MODQ(r->coeffs[k]);
}
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_mul(poly *r, const poly *a, const poly *b) {
int i;
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(r, a, b);
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = MODQ(r->coeffs[i] - r->coeffs[NTRU_N - 1]);
}
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_mul(poly *r, const poly *a, const poly *b) {
int k, i;

for (k = 0; k < NTRU_N; k++) {
r->coeffs[k] = 0;
for (i = 1; i < NTRU_N - k; i++) {
r->coeffs[k] += a->coeffs[k + i] * b->coeffs[NTRU_N - i];
}
for (i = 0; i < k + 1; i++) {
r->coeffs[k] += a->coeffs[k - i] * b->coeffs[i];
}
}
for (k = 0; k < NTRU_N; k++) {
r->coeffs[k] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(r->coeffs[k] + 2 * r->coeffs[NTRU_N - 1]);
}
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul_x_minus_1(poly *r, const poly *a) {
int i;
uint16_t last_coeff = a->coeffs[NTRU_N - 1];

for (i = NTRU_N - 1; i > 0; i--) {
r->coeffs[i] = MODQ(a->coeffs[i - 1] + (NTRU_Q - a->coeffs[i]));
}
r->coeffs[0] = MODQ(last_coeff + (NTRU_Q - a->coeffs[0]));
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_lift(poly *r, const poly *a) {
int i;
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = a->coeffs[i];
}
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(r);
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_to_S3(poly *r, const poly *a) {
/* NOTE: Assumes input is in [0,Q-1]^N */
/* Produces output in {0,1,2}^N */
int i;

/* Center coeffs around 3Q: [0, Q-1] -> [3Q - Q/2, 3Q + Q/2) */
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = ((a->coeffs[i] >> (NTRU_LOGQ - 1)) ^ 3) << NTRU_LOGQ;
r->coeffs[i] += a->coeffs[i];
}
/* Reduce mod (3, Phi) */
r->coeffs[NTRU_N - 1] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(r->coeffs[NTRU_N - 1]);
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(r->coeffs[i] + 2 * r->coeffs[NTRU_N - 1]);
}
}

#define POLY_R2_ADD(I,A,B,S) \
for ((I)=0; (I)<NTRU_N; (I)++) { \
(A).coeffs[(I)] ^= (B).coeffs[(I)] * (S); \
}

static void cswappoly(poly *a, poly *b, int swap) {
int i;
uint16_t t;
swap = -swap;
for (i = 0; i < NTRU_N; i++) {
t = (a->coeffs[i] ^ b->coeffs[i]) & swap;
a->coeffs[i] ^= t;
b->coeffs[i] ^= t;
}
}

static inline void poly_divx(poly *a, int s) {
int i;

for (i = 1; i < NTRU_N; i++) {
a->coeffs[i - 1] = (unsigned char) ((s * a->coeffs[i]) | (!s * a->coeffs[i - 1]));
}
a->coeffs[NTRU_N - 1] = (!s * a->coeffs[NTRU_N - 1]);
}

static inline void poly_mulx(poly *a, int s) {
int i;

for (i = 1; i < NTRU_N; i++) {
a->coeffs[NTRU_N - i] = (unsigned char) ((s * a->coeffs[NTRU_N - i - 1]) | (!s * a->coeffs[NTRU_N - i]));
}
a->coeffs[0] = (!s * a->coeffs[0]);
}

static void poly_R2_inv(poly *r, const poly *a) {
/* Schroeppel--Orman--O'Malley--Spatscheck
* "Almost Inverse" algorithm as described
* by Silverman in NTRU Tech Report #14 */
// with several modifications to make it run in constant-time
int i, j;
int k = 0;
uint16_t degf = NTRU_N - 1;
uint16_t degg = NTRU_N - 1;
int sign, t, swap;
int16_t done = 0;
poly b, f, g;
poly *c = r; // save some stack space
poly *temp_r = &f;

/* b(X) := 1 */
for (i = 1; i < NTRU_N; i++) {
b.coeffs[i] = 0;
}
b.coeffs[0] = 1;

/* c(X) := 0 */
for (i = 0; i < NTRU_N; i++) {
c->coeffs[i] = 0;
}

/* f(X) := a(X) */
for (i = 0; i < NTRU_N; i++) {
f.coeffs[i] = a->coeffs[i] & 1;
}

/* g(X) := 1 + X + X^2 + ... + X^{N-1} */
for (i = 0; i < NTRU_N; i++) {
g.coeffs[i] = 1;
}

for (j = 0; j < 2 * (NTRU_N - 1) - 1; j++) {
sign = f.coeffs[0];
swap = sign & !done & ((degf - degg) >> 15);

cswappoly(&f, &g, swap);
cswappoly(&b, c, swap);
t = (degf ^ degg) & (-swap);
degf ^= t;
degg ^= t;

POLY_R2_ADD(i, f, g, sign * (!done));
POLY_R2_ADD(i, b, (*c), sign * (!done));

poly_divx(&f, !done);
poly_mulx(c, !done);
degf -= !done;
k += !done;

done = 1 - (((uint16_t) - degf) >> 15);
}

k = k - NTRU_N * ((uint16_t)(NTRU_N - k - 1) >> 15);

/* Return X^{N-k} * b(X) */
/* This is a k-coefficient rotation. We do this by looking at the binary
representation of k, rotating for every power of 2, and performing a cmov
if the respective bit is set. */
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = b.coeffs[i];
}

for (i = 0; i < 10; i++) {
for (j = 0; j < NTRU_N; j++) {
temp_r->coeffs[j] = r->coeffs[(j + (1 << i)) % NTRU_N];
}
PQCLEAN_NTRUHPS4096821_CLEAN_cmov((unsigned char *) & (r->coeffs),
(unsigned char *) & (temp_r->coeffs), sizeof(uint16_t) * NTRU_N, k & 1);
k >>= 1;
}
}

static void poly_R2_inv_to_Rq_inv(poly *r, const poly *ai, const poly *a) {

int i;
poly b, c;
poly s;

// for 0..4
// ai = ai * (2 - a*ai) mod q
for (i = 0; i < NTRU_N; i++) {
b.coeffs[i] = MODQ(NTRU_Q - a->coeffs[i]); // b = -a
}

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

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(&c, r, &b);
c.coeffs[0] += 2; // c = 2 - a*ai
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(&s, &c, r); // s = ai*c

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(&c, &s, &b);
c.coeffs[0] += 2; // c = 2 - a*s
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(r, &c, &s); // r = s*c

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(&c, r, &b);
c.coeffs[0] += 2; // c = 2 - a*r
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(&s, &c, r); // s = r*c

PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(&c, &s, &b);
c.coeffs[0] += 2; // c = 2 - a*s
PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(r, &c, &s); // r = s*c
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_inv(poly *r, const poly *a) {
poly ai2;
poly_R2_inv(&ai2, a);
poly_R2_inv_to_Rq_inv(r, &ai2, a);
}

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_inv(poly *r, const poly *a) {
/* Schroeppel--Orman--O'Malley--Spatscheck
* "Almost Inverse" algorithm as described
* by Silverman in NTRU Tech Report #14 */
// with several modifications to make it run in constant-time
int i, j;
uint16_t k = 0;
uint16_t degf = NTRU_N - 1;
uint16_t degg = NTRU_N - 1;
int sign, fsign = 0, t, swap;
int16_t done = 0;
poly b, c, f, g;
poly *temp_r = &f;

/* b(X) := 1 */
for (i = 1; i < NTRU_N; i++) {
b.coeffs[i] = 0;
}
b.coeffs[0] = 1;

/* c(X) := 0 */
for (i = 0; i < NTRU_N; i++) {
c.coeffs[i] = 0;
}

/* f(X) := a(X) */
for (i = 0; i < NTRU_N; i++) {
f.coeffs[i] = a->coeffs[i];
}

/* g(X) := 1 + X + X^2 + ... + X^{N-1} */
for (i = 0; i < NTRU_N; i++) {
g.coeffs[i] = 1;
}

for (j = 0; j < 2 * (NTRU_N - 1) - 1; j++) {
sign = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(2 * g.coeffs[0] * f.coeffs[0]);
swap = (((sign & 2) >> 1) | sign) & !done & ((degf - degg) >> 15);

cswappoly(&f, &g, swap);
cswappoly(&b, &c, swap);
t = (degf ^ degg) & (-swap);
degf ^= t;
degg ^= t;

for (i = 0; i < NTRU_N; i++) {
f.coeffs[i] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(f.coeffs[i] + ((uint16_t) (sign * (!done))) * g.coeffs[i]);
}
for (i = 0; i < NTRU_N; i++) {
b.coeffs[i] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(b.coeffs[i] + ((uint16_t) (sign * (!done))) * c.coeffs[i]);
}

poly_divx(&f, !done);
poly_mulx(&c, !done);
degf -= !done;
k += !done;

done = 1 - (((uint16_t) - degf) >> 15);
}

fsign = f.coeffs[0];
k = k - NTRU_N * ((uint16_t)(NTRU_N - k - 1) >> 15);

/* Return X^{N-k} * b(X) */
/* This is a k-coefficient rotation. We do this by looking at the binary
representation of k, rotating for every power of 2, and performing a cmov
if the respective bit is set. */
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3((uint16_t) fsign * b.coeffs[i]);
}

for (i = 0; i < 10; i++) {
for (j = 0; j < NTRU_N; j++) {
temp_r->coeffs[j] = r->coeffs[(j + (1 << i)) % NTRU_N];
}
PQCLEAN_NTRUHPS4096821_CLEAN_cmov((unsigned char *) & (r->coeffs),
(unsigned char *) & (temp_r->coeffs), sizeof(uint16_t) * NTRU_N, k & 1);
k >>= 1;
}

/* Reduce modulo Phi_n */
for (i = 0; i < NTRU_N; i++) {
r->coeffs[i] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(r->coeffs[i] + 2 * r->coeffs[NTRU_N - 1]);
}
}

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

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

#include <stdint.h>

#include "params.h"

#define MODQ(X) ((X) & (NTRU_Q-1))
uint16_t PQCLEAN_NTRUHPS4096821_CLEAN_mod3(uint16_t a);

typedef struct {
uint16_t coeffs[NTRU_N];
} poly;


void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_tobytes(unsigned char *r, const poly *a);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_frombytes(poly *r, const unsigned char *a);

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_tobytes(unsigned char *r, const poly *a);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_sum_zero_frombytes(poly *r, const unsigned char *a);

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_tobytes(unsigned char msg[NTRU_PACK_TRINARY_BYTES], const poly *a);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_frombytes(poly *r, const unsigned char msg[NTRU_PACK_TRINARY_BYTES]);

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Sq_mul(poly *r, const poly *a, const poly *b);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul(poly *r, const poly *a, const poly *b);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_mul_x_minus_1(poly *r, const poly *a);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_mul(poly *r, const poly *a, const poly *b);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_lift(poly *r, const poly *a);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_to_S3(poly *r, const poly *a);

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Rq_inv(poly *r, const poly *a);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_S3_inv(poly *r, const poly *a);

void PQCLEAN_NTRUHPS4096821_CLEAN_poly_Z3_to_Zq(poly *r);
void PQCLEAN_NTRUHPS4096821_CLEAN_poly_trinary_Zq_to_Z3(poly *r);

#endif

+ 54
- 0
crypto_kem/ntruhps4096821/clean/sample.c View File

@@ -0,0 +1,54 @@
#include "sample.h"
#include "fips202.h"

void PQCLEAN_NTRUHPS4096821_CLEAN_sample_fg(poly *f, poly *g, const unsigned char uniformbytes[NTRU_SAMPLE_FG_BYTES]) {
PQCLEAN_NTRUHPS4096821_CLEAN_sample_iid(f, uniformbytes);
PQCLEAN_NTRUHPS4096821_CLEAN_sample_fixed_type(g, uniformbytes + NTRU_SAMPLE_IID_BYTES);
}

void PQCLEAN_NTRUHPS4096821_CLEAN_sample_rm(poly *r, poly *m, const unsigned char uniformbytes[NTRU_SAMPLE_RM_BYTES]) {
PQCLEAN_NTRUHPS4096821_CLEAN_sample_iid(r, uniformbytes);
PQCLEAN_NTRUHPS4096821_CLEAN_sample_fixed_type(m, uniformbytes + NTRU_SAMPLE_IID_BYTES);
}

void PQCLEAN_NTRUHPS4096821_CLEAN_sample_iid(poly *r, const unsigned char uniformbytes[NTRU_SAMPLE_IID_BYTES]) {
int i;
/* {0,1,...,255} -> {0,1,2}; Pr[0] = 86/256, Pr[1] = Pr[-1] = 85/256 */
for (i = 0; i < NTRU_N - 1; i++) {
r->coeffs[i] = PQCLEAN_NTRUHPS4096821_CLEAN_mod3(uniformbytes[i]);
}

r->coeffs[NTRU_N - 1] = 0;
}

#include "crypto_sort.h"
void PQCLEAN_NTRUHPS4096821_CLEAN_sample_fixed_type(poly *r, const unsigned char u[NTRU_SAMPLE_FT_BYTES]) {
// Assumes NTRU_SAMPLE_FT_BYTES = ceil(30*(n-1)/8)

int32_t s[NTRU_N - 1];
int i;

// Use 30 bits of u per word
for (i = 0; i < (NTRU_N - 1) / 4; i++) {
s[4 * i + 0] = (u[15 * i + 0] << 2) + (u[15 * i + 1] << 10) + (u[15 * i + 2] << 18) + (u[15 * i + 3] << 26);
s[4 * i + 1] = ((u[15 * i + 3] & 0xc0) >> 4) + (u[15 * i + 4] << 4) + (u[15 * i + 5] << 12) + (u[15 * i + 6] << 20) + (u[15 * i + 7] << 28);
s[4 * i + 2] = ((u[15 * i + 7] & 0xf0) >> 2) + (u[15 * i + 8] << 6) + (u[15 * i + 9] << 14) + (u[15 * i + 10] << 22) + (u[15 * i + 11] << 30);
s[4 * i + 3] = (u[15 * i + 11] & 0xfc) + (u[15 * i + 12] << 8) + (u[15 * i + 13] << 15) + (u[15 * i + 14] << 24);
}

for (i = 0; i < NTRU_WEIGHT / 2; i++) {
s[i] |= 1;
}

for (i = NTRU_WEIGHT / 2; i < NTRU_WEIGHT; i++) {
s[i] |= 2;
}

PQCLEAN_NTRUHPS4096821_CLEAN_crypto_sort(s, NTRU_N - 1);

for (i = 0; i < NTRU_N - 1; i++) {
r->coeffs[i] = ((uint16_t) (s[i] & 3));
}

r->coeffs[NTRU_N - 1] = 0;
}

+ 16
- 0
crypto_kem/ntruhps4096821/clean/sample.h View File

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

#include <stdlib.h>

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

void PQCLEAN_NTRUHPS4096821_CLEAN_sample_fg(poly *f, poly *g, const unsigned char uniformbytes[NTRU_SAMPLE_FG_BYTES]);
void PQCLEAN_NTRUHPS4096821_CLEAN_sample_rm(poly *r, poly *m, const unsigned char uniformbytes[NTRU_SAMPLE_RM_BYTES]);

void PQCLEAN_NTRUHPS4096821_CLEAN_sample_iid(poly *r, const unsigned char uniformbytes[NTRU_SAMPLE_IID_BYTES]);

void PQCLEAN_NTRUHPS4096821_CLEAN_sample_fixed_type(poly *r, const unsigned char uniformbytes[NTRU_SAMPLE_FT_BYTES]);

#endif

+ 29
- 0
crypto_kem/ntruhps4096821/clean/verify.c View File

@@ -0,0 +1,29 @@
#include <stdint.h>
#include <stdlib.h>

#include "verify.h"

/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_NTRUHPS4096821_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;
}

/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_NTRUHPS4096821_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b) {
size_t i;

b = (~b + 1); // Two's complement
for (i = 0; i < len; i++) {
r[i] ^= b & (x[i] ^ r[i]);
}
}

+ 12
- 0
crypto_kem/ntruhps4096821/clean/verify.h View File

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

#include <stdio.h>

/* returns 0 for equal strings, 1 for non-equal strings */
unsigned char PQCLEAN_NTRUHPS4096821_CLEAN_verify(const unsigned char *a, const unsigned char *b, size_t len);

/* b = 1 means mov, b = 0 means don't mov*/
void PQCLEAN_NTRUHPS4096821_CLEAN_cmov(unsigned char *r, const unsigned char *x, size_t len, unsigned char b);

#endif

+ 16
- 0
test/duplicate_consistency/ntruhps4096821_clean.yml View File

@@ -0,0 +1,16 @@
consistency_checks:
- source:
scheme: ntruhps2048509
implementation: clean
files:
- crypto_sort.c
- crypto_sort.h
- kem.c
- owcpa.c
- owcpa.h
- poly.c
- poly.h
- sample.c
- sample.h
- verify.c
- verify.h

Loading…
Cancel
Save