newhope: Remove legacy Newhope key exchange method

This commit is contained in:
Andreas Steffen
2024-11-22 14:05:36 +01:00
committed by Tobias Brunner
parent 4833f29b15
commit 8e3a373e18
48 changed files with 15 additions and 4110 deletions
@@ -1,32 +0,0 @@
AM_CPPFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libstrongswan/math/libnttfft
AM_CFLAGS = \
$(PLUGIN_CFLAGS)
# these files are also used by the tests, we can't directly refer to them
# because of the subdirectory, which would cause distclean to fail
noinst_LTLIBRARIES = libnewhope.la
libnewhope_la_SOURCES = \
newhope_ke.h newhope_ke.c \
newhope_noise.h newhope_noise.c \
newhope_reconciliation.h newhope_reconciliation.c
libnewhope_la_LIBADD = \
$(top_builddir)/src/libstrongswan/math/libnttfft/libnttfft.la
if MONOLITHIC
noinst_LTLIBRARIES += libstrongswan-newhope.la
else
plugin_LTLIBRARIES = libstrongswan-newhope.la
endif
libstrongswan_newhope_la_SOURCES = \
newhope_plugin.h newhope_plugin.c
libstrongswan_newhope_la_LDFLAGS = -module -avoid-version
libstrongswan_newhope_la_LIBADD = libnewhope.la
@@ -1,623 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Based on public domain code by Erdem Alkim, Léo Ducas, Thomas Pöppelmann,
* and Peter Schwabe.
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "newhope_ke.h"
#include "newhope_noise.h"
#include "newhope_reconciliation.h"
#include <ntt_fft.h>
#include <ntt_fft_reduce.h>
#include <crypto/key_exchange.h>
#include <utils/debug.h>
static const int seed_len = 32; /* 256 bits */
static const int poly_len = 1792; /* size of 1024 packed 14-bit coefficients */
static const int rec_len = 256; /* size of 1024 packed 2-bit coefficients */
typedef struct private_newhope_ke_t private_newhope_ke_t;
/**
* Private data of an newhope_ke_t object.
*/
struct private_newhope_ke_t {
/**
* Public newhope_ke_t interface.
*/
newhope_ke_t public;
/**
* FFT parameter set
*/
const ntt_fft_params_t *params;
/**
* Secret noise polynomial s
*/
uint32_t *s;
/**
* Output polynomial u = a * NTT(s') + NTT(e')
*/
uint32_t *u;
/**
* Error reconciliation help bits
*/
uint8_t *r;
/**
* Shared secret
*/
chunk_t shared_secret;
};
/**
* Derive 14-bit coefficients of polynomial a from 256 bit random seed
* using the SHAKE128 extended output function
*/
static uint32_t* derive_a_poly(private_newhope_ke_t *this, chunk_t seed)
{
uint32_t *a;
uint8_t x[2];
int i = 0;
xof_t *xof;
xof = lib->crypto->create_xof(lib->crypto, XOF_SHAKE_128);
if (!xof)
{
DBG1(DBG_LIB, "could not instantiate SHAKE128 XOF");
return NULL;
}
if (!xof->set_seed(xof, seed))
{
DBG1(DBG_LIB, "could not set seed of SHAKE128 XOF");
xof->destroy(xof);
return NULL;
}
/* allocate dynamic memory for polynomial a */
a = (uint32_t*)malloc(this->params->n * sizeof(uint32_t));
while (i < this->params->n)
{
if (!xof->get_bytes(xof, sizeof(x), x))
{
DBG1(DBG_LIB, "could not get bytes from SHAKE128 XOF");
xof->destroy(xof);
free(a);
return NULL;
}
/*
* Treat x as a 16 bit unsigned little endian integer
* and truncate to 14 bits
*/
a[i] = uletoh16(x) & 0x3fff;
if (a[i] < this->params->q)
{
i++;
}
}
xof->destroy(xof);
return a;
}
/**
* Pack four 14-bit coefficients into seven consecutive bytes
*
* 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |L 0 0 0 0 0 0 0|L 1 H 0 0 0 0 0|M 1 1 1 1 1 1 1|L 2 2 2 H 1 1 1|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* |M 2 2 2 2 2 2 2|L 3 3 3 3 3 H 2|H 3 3 3 3 3 3 3|L 0 0 0 0 0 0 0|
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
static void pack_poly(private_newhope_ke_t *this, uint8_t *x, uint32_t *p)
{
int i;
for (i = 0; i < this->params->n; i += 4)
{
*x++ = (p[i] & 0xff );
*x++ = (p[i] >> 8) | (p[i+1] << 6);
*x++ = (p[i+1] >> 2);
*x++ = (p[i+1] >> 10) | (p[i+2] << 4);
*x++ = (p[i+2] >> 4);
*x++ = (p[i+2] >> 12) | (p[i+3] << 2);
*x++ = (p[i+3] >> 6);
}
}
/**
* Unpack seven consecutive bytes into four 14-bit coefficients
*/
static uint32_t* unpack_poly(private_newhope_ke_t * this, uint8_t *x)
{
uint32_t *p;
int i;
p = (uint32_t*)malloc(this->params->n * sizeof(uint32_t));
for (i = 0; i < this->params->n; i += 4)
{
p[i] = x[0] | (((uint32_t)x[1] & 0x3f) << 8);
p[i+1] = (x[1] >> 6) | (((uint32_t)x[2]) << 2)
| (((uint32_t)x[3] & 0x0f) << 10);
p[i+2] = (x[3] >> 4) | (((uint32_t)x[4]) << 4)
| (((uint32_t)x[5] & 0x03) << 12);
p[i+3] = (x[5] >> 2) | (((uint32_t)x[6]) << 6);
x += 7;
}
for (i = 0; i < this->params->n; i++)
{
if (p[i] >= this->params->q)
{
DBG1(DBG_LIB, "polynomial coefficient must be smaller than %u",
this->params->q);
free(p);
return NULL;
}
}
return p;
}
/**
* Multiply and add polynomials in the frequency domain
*/
static uint32_t* multiply_add_poly(private_newhope_ke_t *this,
uint32_t *a, uint32_t *e)
{
ntt_fft_t *fft;
uint32_t *b, t;
int i;
/* transform s and h to frequency domain */
fft = ntt_fft_create(this->params);
fft->transform(fft, this->s, this->s, FALSE);
fft->transform(fft, e, e, FALSE);
fft->destroy(fft);
b = (uint32_t*)malloc(this->params->n * sizeof(uint32_t));
/* compute b = a * s + e in the frequency domain */
for (i = 0; i < this->params->n; i++)
{
/* convert a[i] to Montgomery domain */
t = ntt_fft_mreduce(a[i] * this->params->r2, this->params);
/* compute b[i] = a[i] * s[i] + e[i] in Montgomery domain */
t = ntt_fft_mreduce(t * this->s[i], this->params) + e[i];
/* exit Montgomery domain before transmitting polynomial b */
b[i] = ntt_fft_mreduce(t, this->params);
}
memwipe(e, this->params->n * sizeof(uint32_t));
return b;
}
/**
* Multiply polynomials in the frequency domain and return to time domain
*/
static uint32_t* multiply_ntt_inv_poly(private_newhope_ke_t *this, uint32_t *b)
{
ntt_fft_t *fft;
uint32_t *v, t;
int i;
v = (uint32_t*)malloc(this->params->n * sizeof(uint32_t));
for (i = 0; i < this->params->n; i++)
{
/* convert b[i] to Montgomery domain */
t = ntt_fft_mreduce(b[i] * this->params->r2, this->params);
/* compute v[i] = b[i] * s[i] in Montgomery domain */
v[i] = ntt_fft_mreduce(t * this->s[i], this->params);
}
/* transform v back to time domain */
fft = ntt_fft_create(this->params);
fft->transform(fft, v, v, TRUE);
fft->destroy(fft);
return v;
}
/**
* Pack four 2-bit coefficients into one byte
*/
static void pack_rec(private_newhope_ke_t *this, uint8_t *x, uint8_t *r)
{
int i;
for (i = 0; i < this->params->n; i += 4)
{
*x++ = r[i] | r[i+1] << 2 | r[i+2] << 4 | r[i+3] << 6;
}
}
static uint8_t* unpack_rec(private_newhope_ke_t *this, uint8_t *x)
{
uint8_t *r;
int i;
r = (uint8_t*)malloc(this->params->n);
for (i = 0; i < this->params->n; i += 4)
{
r[i] = (*x) & 0x03;
r[i+1] = (*x >> 2) & 0x03;
r[i+2] = (*x >> 4) & 0x03;
r[i+3] = (*x >> 6) & 0x03;
x++;
}
return r;
}
METHOD(key_exchange_t, get_public_key, bool,
private_newhope_ke_t *this, chunk_t *value)
{
uint16_t n, q;
int i;
/* Define some often-used constants */
n = this->params->n;
q = this->params->q;
/* are we the initiator? */
if (this->u == NULL)
{
rng_t *rng;
uint32_t *a = NULL, *b = NULL, *e = NULL;
uint8_t noise_seed_buf[seed_len];
chunk_t noise_seed = { noise_seed_buf, seed_len};
chunk_t a_seed;
newhope_noise_t *noise = NULL;
bool success = FALSE;
/* allocate space for public output value */
*value = chunk_alloc(poly_len + seed_len);
a_seed = chunk_create(value->ptr + poly_len, seed_len);
/* create polynomial a from 256 bit random seed */
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (!rng)
{
DBG1(DBG_LIB, "could not instantiate random source");
return FALSE;
}
if (!rng->get_bytes(rng, seed_len, a_seed.ptr))
{
DBG1(DBG_LIB, "could not generate seed for polynomial a");
goto end;
}
a = derive_a_poly(this, a_seed);
if (a == NULL)
{
goto end;
}
/* generate random seed for the derivation of noise polynomials */
if (!rng->get_bytes(rng, seed_len, noise_seed.ptr))
{
DBG1(DBG_LIB, "could not generate seed for noise polynomials");
goto end;
}
/* create noise polynomial generator */
noise = newhope_noise_create(noise_seed);
if (!noise)
{
goto end;
}
/* create noise polynomial s from seed with nonce = 0x00 */
this->s = noise->get_binomial_words(noise, 0x00, n, q);
if (this->s == NULL)
{
goto end;
}
/* create noise polynomial e from seed with nonce = 0x01 */
e = noise->get_binomial_words(noise, 0x01, n, q);
if (e == NULL)
{
goto end;
}
/* compute b = a * NTT(s) + NTT(e) */
b = multiply_add_poly(this, a, e);
DBG3(DBG_LIB, " i a[i] b[i]");
for (i = 0; i < n; i++)
{
DBG3(DBG_LIB, "%4d %5u %5u", i, a[i], b[i]);
}
/* pack coefficients of polynomial b */
pack_poly(this, value->ptr, b);
success = TRUE;
end:
rng->destroy(rng);
DESTROY_IF(noise);
free(a);
free(b);
free(e);
if (!success)
{
chunk_free(value);
}
return success;
}
else
{
DBG3(DBG_LIB, " i u[i] r[i]");
for (i = 0; i < n; i++)
{
DBG3(DBG_LIB, "%4d %5u %5u", i, this->u[i], this->r[i]);
}
/* allocate space for public output value */
*value = chunk_alloc(poly_len + rec_len);
/* pack coefficients of polynomial u */
pack_poly(this, value->ptr, this->u);
/* pack coefficients of polynomial r */
pack_rec(this, value->ptr + poly_len, this->r);
return TRUE;
}
}
METHOD(key_exchange_t, get_shared_secret, bool,
private_newhope_ke_t *this, chunk_t *secret)
{
if (this->shared_secret.len == 0)
{
*secret = chunk_empty;
return FALSE;
}
*secret = chunk_clone(this->shared_secret);
return TRUE;
}
METHOD(key_exchange_t, set_public_key, bool,
private_newhope_ke_t *this, chunk_t value)
{
newhope_reconciliation_t * rec;
uint16_t n, q;
int i;
/* Define some often-used constants */
n = this->params->n;
q = this->params->q;
/* are we the responder? */
if (this->s == NULL)
{
uint32_t *a = NULL, *b = NULL, *e1 = NULL, *e2 = NULL, *v = NULL, t;
uint8_t *rbits = NULL;
uint8_t noise_seed_buf[seed_len];
chunk_t noise_seed = { noise_seed_buf, seed_len };
chunk_t a_seed;
newhope_noise_t *noise = NULL;
rng_t *rng = NULL;
bool success = FALSE;
if (value.len != poly_len + seed_len)
{
DBG1(DBG_LIB, "received %N KE payload of incorrect size",
key_exchange_method_names, NH_128_BIT);
return FALSE;
}
a_seed = chunk_create(value.ptr + poly_len, seed_len);
a = derive_a_poly(this, a_seed);
if (a == NULL)
{
return FALSE;
}
b = unpack_poly(this, value.ptr);
if (b == NULL)
{
goto end;
}
/* debug output of polynomials a and b */
DBG3(DBG_LIB, " i a[i] b[i]");
for (i = 0; i < n; i++)
{
DBG3(DBG_LIB, "%4d %5u %5u", i, a[i], b[i]);
}
/* generate random seed for the derivation of noise polynomials */
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (!rng)
{
DBG1(DBG_LIB, "could not instantiate random source");
goto end;
}
if (!rng->get_bytes(rng, seed_len, noise_seed.ptr))
{
DBG1(DBG_LIB, "could not generate seed for noise polynomials");
goto end;
}
/* create noise polynomial generator */
noise = newhope_noise_create(noise_seed);
if (!noise)
{
goto end;
}
/* create noise polynomial s' from seed with nonce = 0x00 */
this->s = noise->get_binomial_words(noise, 0x00, n, q);
if (this->s == NULL)
{
goto end;
}
/* create noise polynomial e' from seed with nonce = 0x01 */
e1 = noise->get_binomial_words(noise, 0x01, n, q);
if (e1 == NULL)
{
goto end;
}
/* create noise polynomial e'' from seed with nonce = 0x02 */
e2 = noise->get_binomial_words(noise, 0x02, n, q);
if (e2 == NULL)
{
goto end;
}
/* compute u = a * NTT(s') + NTT(e') */
this->u = multiply_add_poly(this, a, e1);
/* compute v = NTT_inv( b * NTT(s') ) */
v = multiply_ntt_inv_poly(this, b);
/* compute v = v + e'' */
for (i = 0; i < n; i++)
{
t = v[i] + e2[i];
v[i] = (t < q) ? t : t - q;
}
memwipe(e2, n * sizeof(uint32_t));
/* create uniform noise bytes from seed with nonce = 0x02 */
rbits = noise->get_uniform_bytes(noise, 0x03, n/(4*8));
rec = newhope_reconciliation_create(n, q);
this->r = rec->help_reconcile(rec, v, rbits);
free(rbits);
this->shared_secret = rec->reconcile(rec, v, this->r);
rec->destroy(rec);
DBG4(DBG_LIB, "key: %B", &this->shared_secret);
success = TRUE;
end:
DESTROY_IF(rng);
DESTROY_IF(noise);
free(a);
free(b);
free(e1);
free(e2);
free(v);
return success;
}
else
{
uint32_t *v;
if (value.len != poly_len + rec_len)
{
DBG1(DBG_LIB, "received %N KE payload of incorrect size",
key_exchange_method_names, NH_128_BIT);
return FALSE;
}
this->u = unpack_poly(this, value.ptr);
if (this->u == NULL)
{
return FALSE;
}
this->r = unpack_rec(this, value.ptr + poly_len);
if (this->r == NULL)
{
return FALSE;
}
DBG3(DBG_LIB, " i u[i] r[i]");
for (i = 0; i < n; i++)
{
DBG3(DBG_LIB, "%4d %5u %5u", i, this->u[i], this->r[i]);
}
/* compute v' = NTT_inv( u * NTT(s) ) */
v = multiply_ntt_inv_poly(this, this->u);
rec = newhope_reconciliation_create(n, q);
this->shared_secret = rec->reconcile(rec, v, this->r);
free(v);
rec->destroy(rec);
DBG4(DBG_LIB, "key: %B", &this->shared_secret);
return TRUE;
}
}
METHOD(key_exchange_t, get_method, key_exchange_method_t,
private_newhope_ke_t *this)
{
return NH_128_BIT;
}
METHOD(key_exchange_t, destroy, void,
private_newhope_ke_t *this)
{
chunk_clear(&this->shared_secret);
memwipe(this->s, this->params->n * sizeof(uint32_t));
free(this->s);
free(this->u);
free(this->r);
free(this);
}
/*
* Described in header.
*/
newhope_ke_t *newhope_ke_create(key_exchange_method_t ke, chunk_t g, chunk_t p)
{
private_newhope_ke_t *this;
INIT(this,
.public = {
.ke = {
.get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key,
.get_public_key = _get_public_key,
.get_method = _get_method,
.destroy = _destroy,
},
},
.params = &ntt_fft_12289_1024,
);
return &this->public;
}
@@ -1,51 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup newhope_ke newhope_ke
* @{ @ingroup newhope_p
*/
#ifndef NEWHOPE_KE_H_
#define NEWHOPE_KE_H_
typedef struct newhope_ke_t newhope_ke_t;
#include <library.h>
/**
* Implementation of a key exchange algorithm using the New Hope algorithm
*/
struct newhope_ke_t {
/**
* Implements key_exchange_t interface.
*/
key_exchange_t ke;
};
/**
* Creates a new newhope_ke_t object.
*
* @param ke New Hope key exchange number
* @param g not used
* @param p not used
* @return newhope_ke_t object, NULL if not supported
*/
newhope_ke_t *newhope_ke_create(key_exchange_method_t ke, chunk_t g, chunk_t p);
#endif /** NEWHOPE_KE_H_ @}*/
@@ -1,161 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Based on public domain code by Erdem Alkim, Léo Ducas, Thomas Pöppelmann,
* and Peter Schwabe.
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "newhope_noise.h"
typedef struct private_newhope_noise_t private_newhope_noise_t;
static const int seed_len = 32; /* 256 bits */
static const int nonce_len = 12; /* 96 bits */
/**
* Private data of an newhope_noise_t object.
*/
struct private_newhope_noise_t {
/**
* Public newhope_noise_t interface.
*/
newhope_noise_t public;
/**
* 256 bit seed and 96 bit nonce (44 bytes)
*/
chunk_t seed;
/**
* ChaCha20 stream
*/
xof_t *xof;
};
METHOD(newhope_noise_t, get_uniform_bytes, uint8_t*,
private_newhope_noise_t *this, uint8_t nonce, uint16_t n)
{
uint8_t *bytes;
this->seed.ptr[seed_len] = nonce;
if (!this->xof->set_seed(this->xof, this->seed))
{
DBG1(DBG_LIB, "could not set seed of CHACHA20 XOF");
return NULL;
}
/* allocate dynamic memory for the noise polynomial */
bytes = (uint8_t*)malloc(n);
if (!this->xof->get_bytes(this->xof, n, bytes))
{
DBG1(DBG_LIB, "could not get bytes from SHAKE128 XOF");
free(bytes);
return NULL;
}
return bytes;
}
METHOD(newhope_noise_t, get_binomial_words, uint32_t*,
private_newhope_noise_t *this, uint8_t nonce, uint16_t n, uint16_t q)
{
uint32_t *np, a, b, d, t;
uint8_t x[4];
int i = 0, j;
this->seed.ptr[seed_len] = nonce;
if (!this->xof->set_seed(this->xof, this->seed))
{
DBG1(DBG_LIB, "could not set seed of CHACHA20 XOF");
return NULL;
}
/* allocate dynamic memory for the noise polynomial */
np = (uint32_t*)malloc(n * sizeof(uint32_t));
for (i = 0; i < n; i++)
{
if (!this->xof->get_bytes(this->xof, sizeof(x), x))
{
DBG1(DBG_LIB, "could not get bytes from SHAKE128 XOF");
free(np);
return NULL;
}
/* Treat x as a 32 bit unsigned little endian integer */
t = uletoh32(x);
/* Compute Psi_16 distribution */
d = 0;
for (j = 0; j < 8; j++)
{
d += (t >> j) & 0x01010101;
}
a = ((d >> 8) & 0xff) + (d & 0xff);
b = ((d >> 16) & 0xff) + (d >> 24);
np[i] = (a >= b) ? a - b : a + q - b;
}
return np;
}
METHOD(newhope_noise_t, destroy, void,
private_newhope_noise_t *this)
{
this->xof->destroy(this->xof);
chunk_free(&this->seed);
free(this);
}
/*
* Described in header.
*/
newhope_noise_t *newhope_noise_create(chunk_t seed)
{
private_newhope_noise_t *this;
xof_t *xof;
if (seed.len != seed_len)
{
DBG1(DBG_LIB, "seed for ChaCha20 stream must be 256 bits");
return NULL;
}
xof = lib->crypto->create_xof(lib->crypto, XOF_CHACHA20);
if (!xof)
{
DBG1(DBG_LIB, "could not instantiate ChaCha20 stream");
return NULL;
}
INIT(this,
.public = {
.get_uniform_bytes = _get_uniform_bytes,
.get_binomial_words = _get_binomial_words,
.destroy = _destroy,
},
.xof = xof,
.seed = chunk_alloc(seed_len + nonce_len),
);
/* initialize seed for ChaCha 20 stream */
memcpy(this->seed.ptr, seed.ptr, seed_len);
memset(this->seed.ptr + seed_len, 0x00, nonce_len);
return &this->public;
}
@@ -1,71 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup newhope_noise newhope_noise
* @{ @ingroup newhope_p
*/
#ifndef NEWHOPE_NOISE_H_
#define NEWHOPE_NOISE_H_
typedef struct newhope_noise_t newhope_noise_t;
#include <library.h>
/**
* Generate pseudo random noise using a ChaCha20 stream
* initialized with a 256 bit seed and an 8 bit nonce
*/
struct newhope_noise_t {
/**
* Return n pseudo random bytes with a uniform distribution
*
* @param nonce Nonce determining the pseudo random stream
* @param n Number of pseudo random bytes to be returned
* @return Return array with n pseudo random bytes
*/
uint8_t* (*get_uniform_bytes)(newhope_noise_t *this, uint8_t nonce,
uint16_t n);
/**
* Return n pseudo random 32-bit words with a Psi16 binomial distribution
*
* @param nonce Nonce determining the pseudo random stream
* @param n Number of pseudo random Psi16 words to be returned
* @param q Prime number q determining the ring
* @return Return array with n pseudo random 32 bit words
*/
uint32_t* (*get_binomial_words)(newhope_noise_t *this, uint8_t nonce,
uint16_t n, uint16_t q);
/**
* Destroy a newhope_noise_t object
*/
void (*destroy)(newhope_noise_t *this);
};
/**
* Creates a new newhope_noise_t object.
*
* @param seed 256 bit seed (32 byte chunk)
* @return newhope_noise_t object, NULL if not supported
*/
newhope_noise_t *newhope_noise_create(chunk_t seed);
#endif /** NEWHOPE_NOISE_H_ @}*/
@@ -1,79 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "newhope_plugin.h"
#include "newhope_ke.h"
#include <library.h>
typedef struct private_newhope_plugin_t private_newhope_plugin_t;
/**
* private data of newhope_plugin
*/
struct private_newhope_plugin_t {
/**
* public functions
*/
newhope_plugin_t public;
};
METHOD(plugin_t, get_name, char*,
private_newhope_plugin_t *this)
{
return "newhope";
}
METHOD(plugin_t, get_features, int,
private_newhope_plugin_t *this, plugin_feature_t *features[])
{
static plugin_feature_t f[] = {
PLUGIN_REGISTER(KE, newhope_ke_create),
PLUGIN_PROVIDE(KE, NH_128_BIT),
PLUGIN_DEPENDS(XOF, XOF_SHAKE_128),
PLUGIN_DEPENDS(XOF, XOF_CHACHA20),
};
*features = f;
return countof(f);
}
METHOD(plugin_t, destroy, void,
private_newhope_plugin_t *this)
{
free(this);
}
/*
* see header file
*/
plugin_t *newhope_plugin_create()
{
private_newhope_plugin_t *this;
INIT(this,
.public = {
.plugin = {
.get_name = _get_name,
.get_features = _get_features,
.destroy = _destroy,
},
},
);
return &this->public.plugin;
}
@@ -1,43 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup newhope_p newhope
* @ingroup plugins
*
* @defgroup newhope_plugin newhope_plugin
* @{ @ingroup newhope_p
*/
#ifndef NEWHOPE_PLUGIN_H_
#define NEWHOPE_PLUGIN_H_
#include <plugins/plugin.h>
typedef struct newhope_plugin_t newhope_plugin_t;
/**
* Plugin implementing New Hope-based key exchange
*/
struct newhope_plugin_t {
/**
* implements plugin interface
*/
plugin_t plugin;
};
#endif /** NEWHOPE_PLUGIN_H_ @}*/
@@ -1,218 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Based on public domain code by Erdem Alkim, Léo Ducas, Thomas Pöppelmann,
* and Peter Schwabe.
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*
*/
#include "newhope_reconciliation.h"
typedef struct private_newhope_reconciliation_t private_newhope_reconciliation_t;
/**
* Private data of an newhope_reconciliation_t object.
*/
struct private_newhope_reconciliation_t {
/**
* Public newhope_reconciliation_t interface.
*/
newhope_reconciliation_t public;
/**
* Array sizes
*/
int n, n4;
/**
* Multiples of modulus q
*/
int32_t q, q2, q4, q8, q16;
};
static inline int32_t rec_abs(int32_t v)
{
int32_t mask = v >> 31;
return (v ^ mask) - mask;
}
/**
* Auxiliary function used by help_reconcile() method
*/
static int32_t rec_f(private_newhope_reconciliation_t *this,
int32_t v, uint8_t r, int32_t *v0, int32_t *v1)
{
int32_t x, xit, t, b;
x = 8 * v + 2 * r;
/* compute t = x/q */
b = x * 2730;
t = b >> 25;
b = x - t * this->q;
b = this->q - 1 - b;
b >>= 31;
t -= b;
r = t & 0x01;
xit = (t >> 1);
*v0 = xit + r ; /* v0 = round(x/(2q)) */
t -= 1;
r = t & 0x01;
*v1 = ( t>> 1) + r;
return rec_abs(x - (*v0) * this->q2);
}
/**
* Auxiliary function used by reconcile() method
*/
static int32_t rec_g(private_newhope_reconciliation_t *this, int32_t x)
{
int32_t t, r, b;
/* t = x/(4*q) */
b = x * 2730;
t = b >> 27;
b = x - t * this->q4;
b = this->q4 - 1 - b;
b >>= 31;
t -= b;
r = t & 0x01;
t = (t >> 1) + r; /* t = round(x/(8q)) */
t *= this->q8;
return abs(t - x);
}
METHOD(newhope_reconciliation_t, help_reconcile, uint8_t*,
private_newhope_reconciliation_t *this, uint32_t *v, uint8_t *rbits)
{
int32_t v0[4], v1[4], v_tmp[4], k;
int i, i0, i1, i2, i3, j;
uint8_t *r, rbit;
/* allocate output vector */
r = (uint8_t*)malloc(this->n);
for (i = 0; i < this->n4/8; i++)
{
for (j = 0; j < 8; j++)
{
i0 = 8*i + j;
i1 = i0 + this->n4;
i2 = i1 + this->n4;
i3 = i2 + this->n4;
/* iterate through all 256 random bits */
rbit = (rbits[i] >> j) & 0x01;
k = rec_f(this, v[i0], rbit, &v0[0], &v1[0]);
k += rec_f(this, v[i1], rbit, &v0[1], &v1[1]);
k += rec_f(this, v[i2], rbit, &v0[2], &v1[2]);
k += rec_f(this, v[i3], rbit, &v0[3], &v1[3]);
k = (this->q2 - 1 - k) >> 31;
v_tmp[0] = ((~k) & v0[0]) ^ (k & v1[0]);
v_tmp[1] = ((~k) & v0[1]) ^ (k & v1[1]);
v_tmp[2] = ((~k) & v0[2]) ^ (k & v1[2]);
v_tmp[3] = ((~k) & v0[3]) ^ (k & v1[3]);
r[i0] = (v_tmp[0] - v_tmp[3]) & 0x03;
r[i1] = (v_tmp[1] - v_tmp[3]) & 0x03;
r[i2] = (v_tmp[2] - v_tmp[3]) & 0x03;
r[i3] = (v_tmp[3] - k + v_tmp[3]) & 0x03;
}
}
return r;
}
METHOD(newhope_reconciliation_t, reconcile, chunk_t,
private_newhope_reconciliation_t *this, uint32_t *v, uint8_t *r)
{
size_t key_len;
uint8_t *key;
int32_t tmp[4], t;
int i, i0, i1, i2, i3, j;
key_len = this->n4 / 8;
key = (uint8_t*)malloc(key_len);
memset(key, 0x00, key_len);
for (i = 0; i < key_len; i++)
{
for (j = 0; j < 8; j++)
{
i0 = 8*i + j;
i1 = i0 + this->n4;
i2 = i1 + this->n4;
i3 = i2 + this->n4;
tmp[0] = this->q16 + 8 * (int32_t)v[i0] -
this->q * (2*r[i0] + r[i3]);
tmp[1] = this->q16 + 8 * (int32_t)v[i1] -
this->q * (2*r[i1] + r[i3]);
tmp[2] = this->q16 + 8 * (int32_t)v[i2] -
this->q * (2*r[i2] + r[i3]);
tmp[3] = this->q16 + 8 * (int32_t)v[i3] -
this->q * ( r[i3]);
t = rec_g(this, tmp[0]) + rec_g(this, tmp[1]) +
rec_g(this, tmp[2]) + rec_g(this, tmp[3]) - this->q8;
key[i] |= ((t >> 31) & 0x01) << j;
}
}
return chunk_create(key, key_len);
}
METHOD(newhope_reconciliation_t, destroy, void,
private_newhope_reconciliation_t *this)
{
free(this);
}
/*
* Described in header.
*/
newhope_reconciliation_t *newhope_reconciliation_create(int n, int32_t q)
{
private_newhope_reconciliation_t *this;
INIT(this,
.public = {
.help_reconcile = _help_reconcile,
.reconcile = _reconcile,
.destroy = _destroy,
},
.n = n,
.n4 = n / 4,
.q = q,
.q2 = 2 * q,
.q4 = 4 * q,
.q8 = 8 * q,
.q16 = 16 * q,
);
return &this->public;
}
@@ -1,71 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
/**
* @defgroup newhope_reconciliation newhope_reconciliation
* @{ @ingroup newhope_p
*/
#ifndef NEWHOPE_RECONCILIATION_H_
#define NEWHOPE_RECONCILIATION_H_
typedef struct newhope_reconciliation_t newhope_reconciliation_t;
#include <library.h>
/**
* Class assisting the error reconciliation
* resulting in a key exchange error rate < 2^(-60)
*/
struct newhope_reconciliation_t {
/**
* Generate reconciliation polynomial
*
* @param v polynomial v
* @param rbits pseudo random bit array
* @return return array with reconciliation polynomial
*/
uint8_t* (*help_reconcile)(newhope_reconciliation_t *this,
uint32_t *v, uint8_t *rbits);
/**
* Use reconciliation polynomial r to derive shared secret
*
* @param v polynomial v or v'
* @param r reconciliation polynomial r
* @return Return shared secret
*/
chunk_t (*reconcile)(newhope_reconciliation_t *this,
uint32_t *v, uint8_t *r);
/**
* Destroy a newhope_reconciliation_t object
*/
void (*destroy)(newhope_reconciliation_t *this);
};
/**
* Creates a new newhope_reconciliation_t object.
*
* @param n array size
* @param q prime modulus
* @return newhope_reconciliation_t object
*/
newhope_reconciliation_t *newhope_reconciliation_create(int n, int32_t q);
#endif /** NEWHOPE_RECONCILIATION_H_ @}*/
@@ -1 +0,0 @@
newhope_tests
@@ -1,25 +0,0 @@
TESTS = newhope_tests
check_PROGRAMS = $(TESTS)
newhope_tests_SOURCES = \
suites/test_newhope_ke.c \
suites/test_newhope_noise.c \
suites/test_newhope_reconciliation.c \
newhope_tests.h newhope_tests.c
newhope_tests_CFLAGS = \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libstrongswan/tests \
-I$(top_srcdir)/src/libstrongswan/math/libnttfft \
-I$(top_srcdir)/src/libstrongswan/plugins/newhope \
-DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
-DPLUGINS=\""${s_plugins}\"" \
@COVERAGE_CFLAGS@
newhope_tests_LDFLAGS = @COVERAGE_LDFLAGS@
newhope_tests_LDADD = \
$(top_builddir)/src/libstrongswan/libstrongswan.la \
$(top_builddir)/src/libstrongswan/tests/libtest.la \
$(top_builddir)/src/libstrongswan/math/libnttfft/libnttfft.la \
../libnewhope.la
@@ -1,61 +0,0 @@
/*
* Copyright (C) 2014 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <test_runner.h>
#include <library.h>
/* declare test suite constructors */
#define TEST_SUITE(x) test_suite_t* x();
#include "newhope_tests.h"
#undef TEST_SUITE
static test_configuration_t tests[] = {
#define TEST_SUITE(x) \
{ .suite = x, },
#include "newhope_tests.h"
{ .suite = NULL, }
};
static bool test_runner_init(bool init)
{
if (init)
{
char *plugins, *plugindir;
plugins = lib->settings->get_str(lib->settings,
"tests.load", PLUGINS);
plugindir = lib->settings->get_str(lib->settings,
"tests.plugindir", PLUGINDIR);
plugin_loader_add_plugindirs(plugindir, plugins);
if (!lib->plugins->load(lib->plugins, plugins))
{
return FALSE;
}
}
else
{
lib->processor->set_threads(lib->processor, 0);
lib->processor->cancel(lib->processor);
lib->plugins->unload(lib->plugins);
}
return TRUE;
}
int main(int argc, char *argv[])
{
return test_runner_run("newhope", tests, test_runner_init);
}
@@ -1,19 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
TEST_SUITE(newhope_ke_suite_create)
TEST_SUITE(newhope_noise_suite_create)
TEST_SUITE(newhope_reconciliation_suite_create)
@@ -1,194 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "test_suite.h"
#include <newhope_ke.h>
#include <library.h>
#include <time.h>
const int count = 1000;
START_TEST(test_newhope_ke_good)
{
chunk_t i_msg, r_msg, i_shared_secret, r_shared_secret;
key_exchange_t *i_nh, *r_nh;
struct timespec start, stop;
int i;
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &start);
for (i = 0; i < count; i++)
{
i_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(i_nh != NULL);
ck_assert(i_nh->get_method(i_nh) == NH_128_BIT);
ck_assert(i_nh->get_public_key(i_nh, &i_msg));
ck_assert(i_msg.len = 1824);
r_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(r_nh != NULL);
ck_assert(r_nh->set_public_key(r_nh, i_msg));
ck_assert(r_nh->get_public_key(r_nh, &r_msg));
ck_assert(r_msg.len == 2048);
ck_assert(r_nh->get_shared_secret(r_nh, &r_shared_secret));
ck_assert(r_shared_secret.len == 32);
ck_assert(i_nh->set_public_key(i_nh, r_msg));
ck_assert(i_nh->get_shared_secret(i_nh, &i_shared_secret));
ck_assert(i_shared_secret.len == 32);
ck_assert(chunk_equals(i_shared_secret, r_shared_secret));
/* cleanup */
chunk_clear(&i_shared_secret);
chunk_clear(&r_shared_secret);
chunk_free(&i_msg);
chunk_free(&r_msg);
i_nh->destroy(i_nh);
r_nh->destroy(r_nh);
}
clock_gettime(CLOCK_THREAD_CPUTIME_ID, &stop);
DBG0(DBG_LIB, "%d Newhope DH loops in %d ms\n", count,
(stop.tv_nsec - start.tv_nsec) / 1000000 +
(stop.tv_sec - start.tv_sec) * 1000);
}
END_TEST
START_TEST(test_newhope_ke_wrong)
{
chunk_t i_msg, r_msg, i_shared_secret, r_shared_secret;
key_exchange_t *i_nh, *r_nh;
i_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(i_nh != NULL);
ck_assert(i_nh->get_public_key(i_nh, &i_msg));
r_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(r_nh != NULL);
ck_assert(r_nh->set_public_key(r_nh, i_msg));
ck_assert(r_nh->get_public_key(r_nh, &r_msg));
/* destroy 1st instance of i_nh */
i_nh->destroy(i_nh);
chunk_free(&i_msg);
/* create 2nd instance of i_nh */
i_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(i_nh != NULL);
ck_assert(i_nh->get_public_key(i_nh, &i_msg));
ck_assert(i_nh->set_public_key(i_nh, r_msg));
ck_assert(r_nh->get_shared_secret(r_nh, &r_shared_secret));
ck_assert(i_nh->get_shared_secret(i_nh, &i_shared_secret));
ck_assert(!chunk_equals(i_shared_secret, r_shared_secret));
/* cleanup */
chunk_clear(&i_shared_secret);
chunk_clear(&r_shared_secret);
chunk_free(&i_msg);
chunk_free(&r_msg);
i_nh->destroy(i_nh);
r_nh->destroy(r_nh);
}
END_TEST
START_TEST(test_newhope_ke_fail_i)
{
key_exchange_t *i_nh;
char buf_ff[2048];
int i;
chunk_t i_msg;
chunk_t r_msg[] = {
chunk_empty,
chunk_from_chars(0x00),
chunk_create(buf_ff, 2047),
chunk_create(buf_ff, 2048),
};
memset(buf_ff, 0xff, sizeof(buf_ff));
for (i = 0; i < countof(r_msg); i++)
{
i_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(i_nh != NULL);
ck_assert(i_nh->get_public_key(i_nh, &i_msg));
ck_assert(!i_nh->set_public_key(i_nh, r_msg[i]));
chunk_free(&i_msg);
i_nh->destroy(i_nh);
}
}
END_TEST
START_TEST(test_newhope_ke_fail_r)
{
key_exchange_t *r_nh;
char buf_ff[1824];
int i;
chunk_t i_msg[] = {
chunk_empty,
chunk_from_chars(0x00),
chunk_create(buf_ff, 1823),
chunk_create(buf_ff, 1824),
};
memset(buf_ff, 0xff, sizeof(buf_ff));
for (i = 0; i < countof(i_msg); i++)
{
r_nh = lib->crypto->create_ke(lib->crypto, NH_128_BIT);
ck_assert(r_nh != NULL);
ck_assert(!r_nh->set_public_key(r_nh, i_msg[i]));
r_nh->destroy(r_nh);
}
}
END_TEST
Suite *newhope_ke_suite_create()
{
Suite *s;
TCase *tc;
s = suite_create("newhope_ke");
tc = tcase_create("ke_good");
test_case_set_timeout(tc, 30);
tcase_add_test(tc, test_newhope_ke_good);
suite_add_tcase(s, tc);
tc = tcase_create("ke_wrong");
tcase_add_test(tc, test_newhope_ke_wrong);
suite_add_tcase(s, tc);
tc = tcase_create("ke_fail_i");
tcase_add_test(tc, test_newhope_ke_fail_i);
suite_add_tcase(s, tc);
tc = tcase_create("ke_fail_r");
tcase_add_test(tc, test_newhope_ke_fail_r);
suite_add_tcase(s, tc);
return s;
}
@@ -1,677 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "test_suite.h"
#include <newhope_noise.h>
#include <library.h>
static const uint16_t n = 1024;
static const uint16_t q = 12289;
static const size_t seed_len = 32;
typedef struct {
uint8_t key;
uint8_t nonce;
uint8_t uniform[64];
uint32_t poly[1024];
} noise_t;
static noise_t noises[] = {
{ 0x00, 0x00, /* polynomial s */
{ 0x9f, 0x07, 0xe7, 0xbe, 0x55, 0x51, 0x38, 0x7a, 0x98, 0xba,
0x97, 0x7c, 0x73, 0x2d, 0x08, 0x0d, 0xcb, 0x0f, 0x29, 0xa0,
0x48, 0xe3, 0x65, 0x69, 0x12, 0xc6, 0x53, 0x3e, 0x32, 0xee,
0x7a, 0xed, 0x29, 0xb7, 0x21, 0x76, 0x9c, 0xe6, 0x4e, 0x43,
0xd5, 0x71, 0x33, 0xb0, 0x74, 0xd8, 0x39, 0xd5, 0x31, 0xed,
0x1f, 0x28, 0x51, 0x0a, 0xfb, 0x45, 0xac, 0xe1, 0x0a, 0x1f,
0x4b, 0x79, 0x4d, 0x6f },
{ 12286, 12288, 12287, 5, 4, 12288, 12286, 12287, 2, 2,
2, 12288, 2, 12284, 1, 12288, 12288, 12288, 6, 12288,
0, 4, 1, 12285, 12286, 2, 12284, 12287, 1, 5,
5, 12286, 12288, 2, 12286, 0, 3, 1, 0, 2,
0, 0, 4, 12283, 12284, 4, 0, 12288, 3, 12288,
0, 4, 1, 12288, 12286, 0, 3, 1, 12286, 12287,
12285, 3, 2, 3, 12286, 0, 6, 6, 12288, 12284,
0, 12282, 1, 0, 4, 1, 0, 3, 2, 2,
3, 3, 2, 12288, 3, 1, 12287, 12285, 0, 12288,
0, 0, 12288, 12287, 12284, 12286, 0, 12288, 4, 4,
12288, 5, 12286, 2, 12288, 5, 1, 12283, 1, 12288,
1, 12288, 12287, 12285, 2, 2, 12285, 12284, 0, 12285,
12287, 0, 1, 0, 2, 12288, 12288, 12287, 0, 4,
12288, 12285, 12288, 0, 2, 1, 12287, 3, 1, 3,
5, 12286, 1, 0, 12286, 0, 4, 0, 12288, 1,
12288, 4, 5, 12283, 12288, 1, 3, 12283, 12286, 5,
1, 12286, 12287, 12286, 0, 12287, 12285, 1, 0, 0,
1, 3, 0, 0, 0, 12284, 12286, 2, 4, 12288,
6, 1, 2, 12288, 1, 12287, 12286, 12284, 12287, 1,
3, 12284, 0, 0, 6, 12286, 7, 5, 2, 3,
12285, 12287, 12285, 2, 3, 12283, 2, 12284, 12288, 3,
12288, 1, 4, 12287, 2, 12288, 12288, 1, 12286, 12284,
2, 1, 5, 12286, 0, 12288, 0, 0, 0, 12287,
1, 0, 3, 0, 0, 6, 2, 12283, 1, 3,
3, 12284, 3, 1, 12286, 2, 12288, 0, 6, 1,
1, 12285, 12287, 12288, 4, 2, 12288, 3, 12286, 12288,
12287, 3, 3, 2, 7, 4, 12287, 12286, 12287, 2,
2, 12287, 1, 12288, 1, 12287, 12283, 12287, 12288, 1,
12283, 0, 12286, 12288, 4, 12287, 12286, 12286, 2, 2,
12287, 5, 12288, 4, 0, 12287, 1, 3, 12286, 2,
1, 1, 12288, 12287, 5, 12288, 0, 0, 1, 0,
12286, 6, 2, 1, 2, 5, 12286, 6, 12286, 12288,
0, 12286, 3, 12283, 12288, 12284, 0, 7, 2, 6,
1, 12288, 12285, 12284, 1, 0, 0, 2, 12288, 12288,
12288, 3, 3, 1, 3, 12286, 4, 3, 12284, 4,
1, 12287, 12287, 12285, 0, 12287, 12287, 12287, 12286, 12288,
1, 12287, 1, 0, 12288, 2, 0, 4, 0, 12287,
12285, 12285, 5, 3, 12282, 0, 12287, 5, 12287, 1,
12283, 12288, 12288, 3, 1, 1, 3, 12288, 12283, 5,
12288, 12288, 5, 5, 1, 12286, 12286, 12288, 1, 2,
1, 3, 12287, 12288, 12284, 12287, 1, 12287, 0, 12286,
12285, 1, 12287, 12282, 12286, 12287, 0, 12285, 4, 2,
1, 12282, 0, 1, 12288, 12285, 12284, 12286, 12286, 12287,
12288, 1, 12288, 4, 12287, 4, 12287, 12287, 0, 1,
12287, 3, 1, 12286, 12286, 4, 6, 12288, 1, 12285,
12286, 12287, 0, 12287, 12287, 1, 12286, 5, 0, 2,
12283, 12284, 1, 12286, 0, 12287, 12286, 12288, 1, 4,
4, 12283, 2, 6, 1, 12288, 12286, 2, 7, 2,
1, 12288, 5, 12284, 12288, 12288, 1, 7, 3, 12283,
1, 12286, 2, 12288, 12287, 1, 12286, 1, 12286, 12288,
12287, 3, 2, 2, 0, 12284, 12287, 1, 1, 12284,
12286, 1, 2, 1, 0, 12285, 1, 0, 1, 2,
2, 4, 12288, 1, 12288, 5, 0, 12287, 12288, 2,
0, 12288, 12287, 0, 12288, 12288, 0, 0, 12285, 4,
2, 12288, 0, 2, 0, 12288, 1, 3, 12287, 12288,
12288, 12288, 12286, 0, 12285, 12286, 12287, 3, 0, 12286,
2, 1, 12285, 2, 12288, 0, 5, 0, 1, 12288,
12288, 4, 3, 3, 12286, 2, 12288, 4, 12288, 6,
2, 12286, 4, 12287, 2, 12287, 0, 12284, 12288, 0,
12286, 12288, 3, 4, 12286, 12288, 1, 3, 12286, 3,
4, 1, 1, 6, 3, 1, 1, 0, 12288, 4,
0, 12288, 0, 0, 0, 12288, 2, 4, 2, 12287,
0, 0, 3, 2, 3, 4, 0, 3, 2, 12288,
2, 4, 6, 12286, 12284, 12287, 1, 0, 0, 4,
1, 3, 12282, 1, 2, 2, 0, 3, 12282, 2,
12287, 2, 12288, 4, 12288, 3, 3, 12283, 12288, 12288,
12286, 12287, 5, 4, 3, 3, 12288, 12284, 2, 2,
0, 12288, 1, 3, 3, 4, 12284, 12288, 0, 1,
12284, 0, 12286, 12287, 0, 0, 12287, 0, 1, 6,
12288, 1, 12284, 12287, 12282, 12288, 4, 12287, 1, 12286,
1, 12286, 12286, 1, 4, 0, 12288, 1, 12288, 1,
12285, 3, 1, 0, 1, 0, 12288, 12287, 2, 2,
0, 12288, 3, 12284, 2, 12288, 12288, 12288, 12287, 3,
3, 0, 12286, 12286, 1, 2, 12286, 12287, 0, 1,
12288, 12287, 12287, 12288, 12288, 1, 9, 1, 12288, 12287,
2, 1, 1, 0, 12287, 12287, 2, 2, 12288, 12285,
1, 12287, 4, 0, 2, 1, 1, 3, 12284, 12286,
1, 2, 12288, 12287, 4, 1, 12285, 0, 1, 2,
12288, 1, 3, 0, 12286, 0, 12288, 12286, 12287, 12286,
1, 12284, 1, 2, 2, 12288, 0, 12288, 1, 12284,
2, 3, 12287, 1, 12285, 12288, 0, 1, 12284, 2,
12288, 12286, 12286, 3, 12288, 12282, 3, 12287, 12288, 12287,
4, 12287, 1, 2, 9, 12283, 12286, 12286, 0, 4,
12288, 12288, 4, 0, 1, 1, 2, 12284, 1, 1,
0, 12288, 1, 0, 12287, 1, 1, 5, 2, 1,
12288, 3, 12287, 5, 4, 1, 4, 12287, 12285, 3,
12286, 1, 3, 0, 12287, 0, 12286, 12287, 12287, 12287,
3, 2, 12286, 12284, 2, 12288, 1, 1, 12288, 3,
1, 3, 12284, 3, 12282, 12288, 3, 0, 2, 12288,
0, 5, 0, 2, 0, 12281, 12285, 4, 3, 4,
2, 12284, 0, 0, 2, 2, 12287, 12284, 2, 12286,
1, 12288, 1, 12286, 12286, 12287, 4, 0, 6, 3,
0, 3, 12288, 12288, 12288, 12287, 3, 1, 1, 1,
2, 12287, 12284, 3, 12286, 12280, 3, 12284, 12287, 12288,
5, 12288, 12284, 2, 12285, 4, 3, 12286, 6, 2,
1, 12287, 0, 1, 2, 12286, 1, 0, 12287, 0,
1, 1, 12286, 2, 12285, 0, 1, 12288, 0, 1,
12288, 1, 12288, 12287, 12287, 12285, 12282, 12288, 2, 12288,
2, 12284, 1, 12284, 12287, 12286, 12288, 0, 12288, 1,
12283, 12286, 5, 3, 0, 12286, 12286, 3, 1, 0,
1, 12288, 12288, 4, 1, 12286, 12287, 12285, 2, 0,
2, 12287, 1, 12285, 12288, 12286, 12288, 2, 2, 12285,
3, 12286, 12285, 12287 }
},
{ 0x00, 0x01, /* polynomial e */
{ 0x46, 0xf0, 0xf6, 0xef, 0xee, 0x15, 0xc8, 0xf1, 0xb1, 0x98,
0xcb, 0x49, 0xd9, 0x2b, 0x99, 0x08, 0x67, 0x90, 0x51, 0x59,
0x44, 0x0c, 0xc7, 0x23, 0x91, 0x6d, 0xc0, 0x01, 0x28, 0x26,
0x98, 0x10, 0x39, 0xce, 0x17, 0x66, 0xaa, 0x25, 0x42, 0xb0,
0x5d, 0xb3, 0xbd, 0x80, 0x9a, 0xb1, 0x42, 0x48, 0x9d, 0x5d,
0xbf, 0xe1, 0x27, 0x3e, 0x73, 0x99, 0x63, 0x7b, 0x4b, 0x32,
0x13, 0x76, 0x8a, 0xaa },
{ 12283, 1, 12288, 4, 0, 12285, 5, 1, 1, 2,
3, 4, 12288, 0, 3, 1, 1, 0, 12286, 6,
1, 0, 1, 0, 4, 2, 12288, 3, 0, 5,
1, 5, 2, 12285, 4, 12288, 3, 2, 12288, 2,
12288, 12285, 12287, 6, 12282, 1, 12286, 7, 12287, 4,
2, 2, 12288, 12285, 0, 2, 0, 12288, 1, 12287,
12287, 2, 1, 2, 1, 12285, 12288, 12286, 1, 2,
12287, 12288, 12288, 1, 0, 12287, 0, 4, 2, 6,
12287, 12285, 12283, 12285, 5, 12283, 12286, 1, 12283, 2,
3, 12286, 12285, 2, 5, 12286, 3, 0, 3, 12286,
5, 12285, 12287, 12288, 1, 5, 3, 5, 1, 1,
1, 12288, 5, 0, 12288, 3, 2, 12288, 12285, 12288,
5, 6, 0, 2, 1, 12287, 12288, 12287, 3, 12284,
2, 0, 3, 0, 0, 12288, 0, 2, 2, 2,
0, 1, 2, 2, 0, 0, 12287, 12285, 0, 4,
1, 12283, 3, 5, 12288, 12286, 12287, 6, 2, 0,
0, 12287, 2, 2, 12288, 0, 2, 12288, 12287, 12288,
12288, 1, 12288, 1, 12288, 2, 4, 2, 1, 1,
0, 12287, 3, 2, 6, 2, 1, 12288, 12285, 6,
0, 1, 12284, 12287, 12287, 12286, 5, 4, 0, 5,
12287, 12286, 12288, 12286, 0, 3, 1, 12287, 12287, 12288,
12288, 12286, 1, 0, 3, 12287, 3, 1, 12283, 1,
12288, 5, 1, 4, 12286, 12287, 2, 0, 0, 0,
12281, 12286, 0, 8, 5, 0, 4, 0, 12287, 5,
1, 3, 2, 12286, 12286, 12288, 12285, 12285, 12287, 0,
12284, 12287, 1, 0, 2, 1, 12286, 12288, 2, 12285,
0, 0, 0, 1, 0, 6, 1, 12288, 12287, 12287,
0, 3, 12288, 12288, 12287, 0, 12287, 1, 3, 0,
0, 12286, 12286, 4, 4, 12287, 1, 3, 4, 12287,
12284, 2, 12288, 12286, 12283, 12285, 1, 3, 1, 12288,
0, 3, 3, 12284, 12285, 5, 3, 12288, 3, 4,
3, 1, 12288, 0, 12288, 1, 0, 0, 3, 0,
3, 2, 12287, 12288, 0, 12288, 0, 2, 12285, 4,
0, 12287, 12287, 1, 1, 1, 12287, 12285, 4, 12282,
3, 1, 1, 12288, 2, 4, 12285, 12286, 3, 1,
0, 12287, 12283, 12285, 2, 5, 1, 1, 12288, 12288,
0, 8, 3, 12287, 12285, 12287, 12286, 12284, 1, 12286,
1, 12288, 2, 3, 12288, 12288, 2, 12288, 12284, 12285,
0, 3, 12288, 12288, 2, 3, 7, 12287, 3, 3,
3, 12284, 0, 0, 1, 12283, 5, 0, 1, 12288,
3, 12286, 12287, 12286, 0, 0, 12287, 12283, 4, 12283,
0, 0, 3, 12285, 5, 12286, 12282, 12288, 1, 12287,
12288, 1, 5, 2, 12287, 2, 12288, 7, 12288, 3,
5, 1, 0, 12287, 1, 12287, 3, 2, 4, 2,
12287, 12286, 12288, 2, 5, 1, 12286, 4, 0, 2,
6, 12286, 2, 12286, 3, 12288, 5, 12285, 0, 2,
12287, 5, 12286, 12284, 7, 12285, 12286, 12284, 12287, 1,
12288, 12284, 12286, 2, 4, 2, 2, 12283, 12286, 2,
2, 12283, 1, 12286, 1, 0, 12284, 3, 0, 4,
1, 0, 4, 12288, 0, 12287, 12287, 12287, 12286, 12284,
12288, 3, 1, 12285, 0, 3, 8, 4, 2, 12288,
3, 12287, 12287, 2, 3, 12288, 12286, 2, 12286, 12288,
0, 1, 12287, 12285, 0, 12285, 12288, 12287, 1, 12287,
0, 12284, 0, 1, 1, 12285, 0, 0, 0, 12287,
12287, 3, 0, 4, 12288, 1, 12288, 12285, 12283, 0,
12286, 12286, 12285, 12285, 12287, 1, 0, 2, 3, 1,
2, 12286, 12288, 3, 12286, 12288, 12288, 6, 2, 2,
0, 12288, 2, 5, 12288, 0, 12284, 12282, 12286, 1,
12288, 12288, 12286, 12288, 3, 12286, 2, 0, 12283, 0,
4, 2, 12288, 0, 12286, 0, 4, 3, 12286, 12287,
4, 12288, 3, 2, 12283, 1, 1, 1, 3, 12286,
4, 0, 12288, 12285, 12287, 0, 0, 12286, 4, 0,
12286, 2, 12288, 12288, 12285, 12283, 5, 3, 12286, 12288,
4, 1, 12283, 0, 12288, 0, 12287, 12287, 0, 3,
12287, 12287, 2, 2, 3, 0, 1, 4, 12288, 3,
3, 0, 12284, 12285, 4, 12288, 1, 12287, 0, 1,
12283, 1, 12284, 12287, 12286, 12285, 0, 0, 3, 12285,
3, 1, 12288, 12287, 12284, 12282, 5, 3, 3, 2,
12285, 4, 12288, 0, 3, 12288, 4, 0, 12283, 12288,
2, 12285, 12288, 12282, 0, 2, 12285, 3, 1, 12284,
1, 5, 7, 12286, 5, 12285, 1, 2, 0, 4,
12283, 12287, 12286, 2, 12280, 12287, 12288, 2, 12285, 12286,
2, 1, 2, 1, 2, 2, 3, 3, 0, 0,
4, 2, 12288, 12286, 4, 0, 1, 12288, 2, 12287,
12288, 12288, 1, 3, 12283, 12288, 1, 12287, 1, 1,
3, 12288, 12288, 1, 2, 1, 1, 12283, 7, 12286,
12288, 1, 12288, 12287, 12284, 7, 2, 12285, 12286, 0,
0, 0, 2, 4, 12288, 0, 12284, 12285, 12286, 2,
12284, 2, 4, 6, 3, 12287, 12288, 12285, 1, 2,
12286, 0, 0, 12287, 12288, 0, 12286, 2, 1, 1,
1, 3, 1, 12285, 4, 0, 12287, 12288, 12287, 0,
12288, 12287, 12288, 12287, 12288, 12288, 0, 12287, 12284, 0,
12288, 12285, 3, 2, 4, 2, 12284, 3, 1, 3,
4, 12288, 12285, 12284, 12287, 1, 4, 0, 2, 12288,
4, 12288, 12287, 3, 1, 0, 0, 12284, 12287, 2,
4, 12287, 2, 12288, 0, 2, 2, 3, 12287, 12286,
8, 12286, 12285, 0, 12285, 2, 3, 5, 12287, 12288,
6, 12288, 12284, 0, 0, 3, 1, 2, 12284, 2,
1, 3, 2, 0, 0, 12288, 12287, 12288, 1, 12288,
4, 3, 12284, 1, 3, 12288, 12283, 12288, 1, 1,
2, 1, 1, 3, 1, 12288, 0, 12288, 2, 0,
0, 12284, 12283, 3, 12288, 0, 2, 12287, 0, 0,
12286, 12286, 0, 0, 2, 4, 12288, 1, 2, 3,
2, 12286, 12286, 1, 2, 4, 12288, 12288, 12284, 12287,
6, 2, 12288, 12286, 0, 0, 3, 12286, 12288, 12287,
12286, 12287, 3, 1, 12286, 0, 4, 3, 12286, 5,
2, 1, 12287, 12286, 4, 12287, 0, 5, 12288, 0,
12288, 2, 2, 1, 1, 0, 0, 12288, 12288, 12288,
0, 0, 12288, 12287, 5, 1, 12288, 1, 10, 1,
0, 0, 2, 2, 2, 0, 12288, 4, 2, 12283,
3, 1, 1, 12285, 2, 12285, 5, 7, 5, 12288,
0, 12287, 5, 1, 12288, 12286, 12287, 0, 0, 0,
12287, 1, 3, 12288 }
},
{ 0x01, 0x00, /* polynomial s' */
{ 0x3a, 0xeb, 0x52, 0x24, 0xec, 0xf8, 0x49, 0x92, 0x9b, 0x9d,
0x82, 0x8d, 0xb1, 0xce, 0xd4, 0xdd, 0x83, 0x20, 0x25, 0xe8,
0x01, 0x8b, 0x81, 0x60, 0xb8, 0x22, 0x84, 0xf3, 0xc9, 0x49,
0xaa, 0x5a, 0x8e, 0xca, 0x00, 0xbb, 0xb4, 0xa7, 0x3b, 0xda,
0xd1, 0x92, 0xb5, 0xc4, 0x2f, 0x73, 0xf2, 0xfd, 0x4e, 0x27,
0x36, 0x44, 0xc8, 0xb3, 0x61, 0x25, 0xa6, 0x4a, 0xdd, 0xeb,
0x00, 0x6c, 0x13, 0xa0 },
{ 5, 4, 4, 12288, 12286, 1, 12287, 12288, 2, 12288,
12288, 12287, 2, 2, 12284, 12288, 12288, 3, 2, 3,
12287, 2, 2, 0, 0, 2, 5, 12285, 5, 12287,
2, 12282, 12286, 2, 1, 2, 1, 1, 12288, 12285,
12287, 12286, 2, 0, 0, 12285, 0, 0, 12287, 12286,
12285, 12286, 2, 12288, 12288, 0, 1, 2, 12286, 2,
1, 0, 0, 2, 1, 12288, 1, 12287, 1, 0,
0, 2, 12285, 2, 2, 12288, 12286, 3, 12287, 0,
1, 1, 0, 2, 12287, 2, 1, 2, 3, 0,
0, 1, 12288, 12288, 2, 12287, 12286, 12286, 6, 12288,
0, 0, 4, 0, 12286, 0, 4, 12288, 12288, 5,
12287, 12288, 12285, 2, 12285, 12288, 1, 0, 2, 12288,
12286, 1, 3, 12285, 2, 2, 1, 1, 12288, 12288,
12287, 1, 12288, 3, 0, 12285, 4, 12285, 12287, 2,
2, 12287, 12287, 12286, 12288, 12284, 2, 12286, 4, 1,
0, 12286, 12284, 3, 12286, 3, 12286, 3, 4, 1,
12288, 12282, 2, 2, 12284, 0, 12286, 12283, 3, 0,
4, 2, 4, 2, 12285, 10, 12288, 8, 3, 2,
2, 0, 1, 0, 0, 12286, 2, 12284, 4, 1,
12287, 12287, 1, 1, 12286, 1, 0, 12285, 12288, 12286,
12287, 2, 1, 12284, 12288, 12285, 12285, 3, 0, 1,
4, 4, 1, 0, 2, 1, 12288, 1, 12287, 0,
12286, 4, 2, 3, 3, 12285, 12288, 12288, 5, 2,
0, 4, 3, 12287, 12287, 5, 2, 3, 12284, 0,
8, 1, 1, 0, 5, 12288, 12288, 12288, 12286, 6,
3, 12288, 12286, 12287, 4, 12288, 2, 12288, 12284, 12287,
4, 12288, 0, 0, 3, 0, 4, 4, 12287, 0,
3, 0, 12285, 12287, 12288, 12288, 0, 0, 12287, 12288,
12286, 0, 0, 12285, 12288, 4, 12287, 1, 2, 12288,
12285, 5, 4, 12283, 2, 0, 12288, 2, 0, 0,
12286, 12284, 3, 3, 3, 12287, 1, 1, 0, 1,
3, 12288, 4, 4, 0, 2, 0, 1, 12286, 12284,
2, 2, 12287, 3, 2, 12288, 3, 12286, 2, 12286,
12288, 4, 3, 12288, 2, 12288, 2, 1, 12288, 12288,
7, 12288, 12288, 0, 12288, 1, 12284, 12288, 12288, 12287,
12287, 1, 12285, 12287, 12287, 1, 0, 2, 12286, 3,
12288, 12288, 12287, 3, 5, 0, 0, 12287, 2, 12287,
12288, 8, 12287, 1, 2, 12288, 12284, 3, 0, 12287,
12284, 3, 0, 2, 1, 3, 4, 12287, 12286, 12288,
12286, 0, 0, 12287, 12285, 0, 12286, 2, 1, 12287,
12288, 5, 12287, 12287, 12286, 2, 12283, 0, 0, 12286,
2, 12284, 5, 0, 1, 12287, 0, 3, 1, 12285,
12288, 0, 3, 12287, 2, 12286, 0, 1, 12288, 1,
12284, 12281, 12284, 12288, 12285, 2, 5, 4, 12286, 0,
12287, 12288, 12286, 12285, 3, 12282, 1, 12287, 2, 0,
6, 12288, 4, 12286, 3, 12288, 12286, 12284, 3, 1,
6, 3, 2, 1, 2, 1, 1, 12288, 12287, 1,
3, 3, 1, 0, 0, 12288, 3, 12284, 12285, 12284,
1, 3, 12286, 0, 1, 12285, 12287, 1, 12285, 2,
0, 1, 12287, 1, 4, 3, 1, 12287, 0, 5,
1, 12288, 2, 1, 1, 4, 3, 12286, 3, 3,
2, 12287, 3, 12286, 0, 12288, 12285, 2, 3, 12286,
0, 12287, 5, 4, 1, 1, 12287, 12288, 2, 0,
0, 0, 2, 0, 12286, 4, 12288, 12288, 12285, 12286,
2, 12288, 12288, 0, 12288, 12286, 12284, 12287, 1, 5,
0, 12285, 12287, 2, 4, 3, 12285, 12287, 12288, 0,
12288, 12287, 12286, 2, 12288, 12286, 12284, 1, 2, 12287,
4, 1, 4, 4, 12284, 2, 0, 12288, 3, 1,
0, 4, 1, 6, 0, 12286, 12288, 12287, 12287, 0,
12284, 12285, 2, 12286, 1, 0, 3, 12288, 1, 2,
12284, 12286, 12285, 12283, 12285, 0, 12285, 2, 0, 2,
1, 3, 1, 12286, 12288, 1, 4, 0, 0, 12287,
12287, 12286, 0, 1, 12286, 0, 2, 12288, 2, 12287,
0, 0, 12286, 12287, 4, 6, 12286, 0, 12288, 0,
0, 12287, 2, 3, 4, 1, 3, 12286, 4, 0,
12288, 12286, 12287, 12287, 12288, 4, 12285, 1, 12286, 12286,
2, 12288, 0, 0, 1, 5, 12285, 1, 12281, 3,
12281, 2, 3, 0, 12284, 12288, 5, 0, 0, 12288,
0, 0, 12288, 12286, 3, 12287, 0, 2, 12288, 0,
3, 12288, 12286, 0, 12286, 12287, 12284, 0, 12286, 1,
12287, 12282, 12287, 12288, 0, 5, 12288, 2, 1, 12288,
1, 12285, 5, 2, 12286, 12285, 12287, 0, 2, 12288,
1, 12288, 1, 12286, 0, 2, 12287, 12287, 6, 12286,
12288, 0, 12286, 4, 6, 12287, 12287, 2, 2, 12285,
1, 12288, 12285, 12286, 5, 12288, 1, 2, 1, 7,
12286, 5, 12288, 12287, 12286, 12284, 1, 2, 12287, 4,
1, 1, 0, 1, 2, 12285, 2, 12288, 12284, 1,
1, 12287, 12286, 12285, 12287, 1, 12287, 3, 1, 12286,
0, 12286, 3, 3, 12288, 2, 12288, 5, 12288, 1,
2, 0, 12287, 1, 12287, 7, 2, 3, 0, 12287,
2, 12284, 12284, 12281, 12286, 12285, 12287, 12287, 0, 12288,
3, 4, 3, 2, 3, 1, 12288, 12286, 0, 12288,
12286, 1, 12286, 6, 12287, 1, 6, 5, 3, 1,
12286, 2, 1, 3, 1, 12286, 12285, 3, 2, 0,
0, 12284, 1, 1, 3, 3, 1, 1, 12288, 0,
12284, 1, 12288, 0, 0, 12287, 0, 4, 12285, 0,
4, 12283, 1, 1, 0, 12285, 0, 12286, 0, 0,
1, 0, 12286, 0, 12288, 3, 4, 0, 2, 1,
12287, 2, 12288, 1, 0, 12288, 0, 12288, 6, 12288,
12287, 12286, 3, 12284, 0, 12288, 12284, 12286, 12287, 12288,
12288, 12288, 4, 0, 2, 6, 12286, 1, 4, 12288,
2, 1, 0, 5, 2, 1, 12285, 0, 0, 12285,
4, 12286, 5, 1, 3, 2, 12287, 2, 0, 2,
7, 12283, 12288, 12288, 3, 0, 3, 12288, 3, 12286,
12288, 12287, 12288, 3, 0, 2, 4, 1, 12284, 2,
12288, 12286, 12287, 1, 1, 12288, 0, 12288, 12283, 6,
2, 1, 12288, 3, 12287, 12288, 1, 1, 12285, 0,
12286, 12287, 12288, 1, 2, 12287, 0, 4, 0, 12286,
2, 1, 12288, 12285, 12287, 0, 2, 12287, 6, 2,
0, 12287, 12288, 2, 12288, 12284, 12288, 12285, 4, 1,
12288, 12284, 12287, 4, 12284, 1, 3, 12284, 12282, 0,
12286, 12287, 2, 12286, 3, 4, 2, 12288, 3, 3,
1, 3, 12287, 12283 }
},
{ 0x01, 0x01, /* polynomial e' */
{ 0x58, 0xd8, 0x6a, 0xcd, 0xe2, 0x79, 0x61, 0x98, 0xfd, 0xea,
0xcf, 0x2a, 0xc0, 0xfd, 0xf0, 0x72, 0x86, 0x32, 0xdc, 0xe9,
0xc6, 0x45, 0x81, 0x80, 0x67, 0x06, 0x72, 0x28, 0xa6, 0xfe,
0x41, 0x2b, 0x78, 0x88, 0x58, 0x6d, 0x58, 0x47, 0x3e, 0xb7,
0x46, 0x60, 0xd8, 0x2f, 0xa0, 0x83, 0xe4, 0xbc, 0x81, 0xdd,
0xc6, 0x29, 0x8b, 0xee, 0xf9, 0xec, 0x90, 0x39, 0x9d, 0x46,
0xbf, 0x2d, 0x7c, 0xdf },
{ 12287, 3, 3, 1, 12285, 4, 1, 5, 12287, 12285,
12285, 12285, 1, 12288, 12287, 12288, 2, 3, 12283, 12288,
12285, 0, 0, 12286, 12287, 12288, 12288, 12288, 12288, 1,
12288, 2, 2, 5, 5, 0, 12287, 12286, 3, 3,
2, 2, 1, 0, 2, 12287, 12285, 3, 1, 3,
5, 2, 12287, 12287, 2, 0, 4, 2, 0, 0,
1, 5, 12288, 6, 4, 12287, 1, 0, 12283, 0,
1, 12286, 2, 0, 2, 1, 12284, 12282, 0, 6,
1, 2, 5, 12288, 6, 12288, 12284, 2, 1, 2,
12288, 12283, 12288, 3, 12288, 12288, 2, 12286, 12283, 1,
12285, 0, 0, 12286, 12288, 12286, 12288, 12286, 4, 0,
1, 12285, 3, 1, 2, 12285, 12287, 12284, 12287, 12285,
12286, 1, 12288, 3, 5, 5, 3, 12285, 12286, 12288,
0, 1, 12287, 12284, 2, 4, 12288, 12287, 0, 12288,
12288, 12285, 12288, 12284, 3, 0, 2, 0, 2, 0,
1, 1, 1, 12287, 1, 12284, 12285, 0, 12284, 1,
12284, 2, 12288, 5, 4, 1, 1, 12284, 1, 3,
2, 6, 3, 2, 3, 12284, 0, 0, 4, 2,
6, 2, 2, 2, 6, 12288, 0, 1, 12286, 1,
5, 1, 12283, 2, 0, 12284, 1, 12286, 4, 1,
2, 4, 6, 12288, 12288, 12284, 1, 0, 3, 12286,
1, 0, 3, 12288, 12287, 2, 2, 0, 12285, 12286,
0, 12288, 4, 2, 12282, 12287, 1, 12288, 12287, 12286,
12284, 1, 4, 2, 7, 12288, 12283, 12288, 5, 12288,
12288, 12287, 3, 2, 12287, 5, 12287, 12286, 12288, 12287,
0, 12282, 12288, 12288, 0, 3, 12287, 2, 12287, 12284,
6, 12285, 2, 3, 3, 12284, 2, 4, 12286, 5,
0, 2, 12287, 3, 0, 12284, 12286, 0, 2, 12286,
12287, 3, 1, 4, 1, 12286, 12288, 1, 2, 0,
12285, 12287, 2, 0, 0, 0, 3, 12286, 12287, 2,
0, 0, 0, 12286, 4, 1, 12287, 0, 0, 2,
5, 0, 12284, 1, 1, 12288, 2, 12286, 12288, 2,
2, 12282, 1, 12286, 4, 12286, 3, 12287, 12287, 12286,
5, 5, 0, 12288, 3, 12285, 1, 12287, 7, 12286,
2, 12287, 1, 12285, 2, 12287, 12288, 0, 4, 12281,
0, 12286, 3, 1, 12285, 2, 2, 12285, 5, 0,
12285, 2, 12288, 1, 3, 12287, 1, 12288, 1, 5,
12287, 1, 0, 3, 2, 12286, 12286, 12288, 3, 0,
12287, 12288, 0, 12286, 12285, 0, 12286, 12288, 3, 12287,
12288, 2, 6, 0, 2, 12285, 1, 1, 7, 7,
12284, 12284, 5, 0, 12288, 12288, 4, 3, 1, 2,
12287, 0, 12288, 12284, 2, 5, 1, 2, 0, 12288,
1, 12284, 2, 3, 0, 12287, 12285, 2, 12288, 12288,
7, 1, 12287, 1, 12286, 2, 3, 4, 12288, 12288,
12286, 12286, 3, 12288, 1, 12286, 12286, 0, 12283, 12288,
2, 0, 7, 2, 12287, 0, 0, 12286, 4, 1,
12288, 12288, 1, 2, 12287, 12282, 3, 5, 0, 12288,
12288, 12286, 12286, 12286, 4, 2, 0, 1, 12284, 3,
12283, 5, 12287, 2, 2, 12288, 1, 12284, 1, 0,
1, 3, 12288, 2, 12287, 1, 12286, 12288, 0, 12287,
12288, 2, 2, 12286, 0, 12287, 12288, 12284, 0, 2,
2, 2, 1, 3, 12285, 12285, 1, 12285, 2, 6,
2, 0, 12288, 0, 0, 3, 2, 12287, 1, 12286,
0, 12287, 0, 1, 12285, 12287, 6, 12288, 2, 0,
12286, 2, 4, 12288, 2, 5, 12285, 12286, 0, 12284,
12288, 3, 3, 3, 12287, 4, 2, 0, 12283, 2,
12287, 0, 1, 12287, 2, 12288, 12287, 3, 2, 7,
7, 1, 12287, 12288, 2, 6, 1, 3, 2, 0,
2, 2, 3, 12288, 3, 4, 2, 0, 5, 12285,
3, 12285, 3, 12285, 1, 1, 12287, 12285, 2, 12285,
5, 0, 7, 2, 12284, 0, 12285, 7, 1, 12288,
12288, 0, 12288, 12287, 5, 0, 2, 0, 2, 12286,
1, 12286, 0, 12286, 12285, 4, 12286, 2, 12288, 12287,
12287, 1, 12286, 12287, 12287, 12286, 12287, 12288, 6, 5,
2, 5, 12283, 12286, 12286, 12288, 1, 0, 3, 12286,
5, 0, 12287, 12288, 12288, 12287, 12286, 2, 1, 0,
1, 2, 3, 1, 12286, 2, 1, 6, 12288, 1,
12286, 1, 12288, 0, 1, 0, 12283, 0, 2, 12288,
3, 1, 12287, 12288, 4, 0, 3, 12286, 0, 1,
12283, 4, 1, 4, 12287, 5, 0, 12287, 12288, 3,
3, 12282, 1, 4, 2, 3, 0, 2, 6, 12282,
12285, 12288, 12287, 12288, 2, 12285, 1, 0, 12287, 12288,
12286, 0, 0, 4, 12288, 12287, 1, 0, 2, 5,
2, 12287, 1, 7, 12284, 0, 12287, 12286, 2, 1,
12287, 0, 1, 12284, 12287, 12287, 12285, 12285, 3, 12282,
12286, 1, 1, 12288, 12282, 12287, 1, 1, 2, 2,
3, 1, 12287, 5, 12282, 0, 0, 12287, 1, 3,
12288, 3, 12285, 12286, 2, 0, 12288, 12288, 5, 12285,
4, 12288, 12287, 0, 1, 4, 1, 2, 12288, 0,
2, 1, 12288, 4, 6, 12288, 1, 12287, 4, 1,
12285, 12288, 3, 0, 12288, 12285, 2, 0, 12286, 2,
1, 12288, 1, 12288, 12284, 3, 0, 2, 2, 12288,
12287, 12286, 4, 12288, 2, 0, 0, 3, 4, 0,
12288, 12282, 6, 2, 12283, 12287, 2, 6, 1, 2,
12288, 2, 12283, 3, 12287, 3, 4, 0, 0, 12285,
0, 12288, 12287, 12284, 12286, 3, 1, 12286, 2, 0,
12287, 12286, 12286, 12288, 5, 2, 12288, 12286, 0, 12287,
0, 3, 2, 12287, 12286, 0, 1, 12287, 2, 0,
12286, 5, 12285, 12288, 12288, 12288, 12286, 4, 1, 12285,
12284, 12288, 12286, 1, 1, 12287, 2, 12286, 3, 2,
12283, 12283, 4, 2, 12283, 5, 0, 1, 0, 5,
12287, 1, 1, 0, 3, 10, 12287, 3, 12288, 12288,
12287, 2, 2, 0, 4, 12288, 12283, 12288, 1, 12287,
3, 0, 0, 1, 12288, 12284, 0, 12286, 12287, 0,
12287, 2, 1, 7, 12288, 12287, 0, 4, 12287, 12286,
3, 4, 12287, 12288, 12285, 12287, 12288, 12285, 12286, 7,
1, 1, 12288, 3, 12287, 3, 1, 4, 2, 5,
12282, 3, 0, 12286, 12288, 0, 12285, 0, 2, 3,
0, 12286, 3, 2, 12285, 0, 0, 12287, 1, 0,
0, 6, 2, 12287, 12284, 7, 5, 0, 1, 6,
2, 4, 1, 12286, 12288, 2, 12287, 3, 4, 12283,
0, 12288, 2, 2, 12286, 0, 2, 2, 12288, 12285,
12287, 12285, 12288, 0 }
},
{ 0x01, 0x02, /* polynomial e'' */
{ 0x20, 0x37, 0x77, 0x8a, 0x9c, 0x19, 0xde, 0xf0, 0x65, 0x9e,
0x0f, 0xa5, 0xfc, 0x0e, 0x78, 0xfe, 0x55, 0x89, 0xc9, 0x88,
0x41, 0xa2, 0x5a, 0x1e, 0xa4, 0x66, 0xcd, 0x3a, 0x29, 0x42,
0xd1, 0x25, 0xf2, 0x84, 0xd7, 0xee, 0xd5, 0x53, 0x86, 0x5b,
0xa3, 0x93, 0x4e, 0xee, 0xc7, 0x5b, 0xe5, 0x52, 0x68, 0x19,
0xdf, 0x63, 0xfb, 0x91, 0x3d, 0xe9, 0x5d, 0xd6, 0xeb, 0x81,
0x3d, 0xac, 0xf1, 0xad },
{ 12286, 12286, 1, 12287, 1, 12286, 12287, 12287, 12284, 1,
12287, 2, 12284, 0, 2, 12288, 0, 1, 0, 12285,
12288, 4, 2, 12287, 12282, 12288, 12285, 12288, 2, 12288,
6, 7, 12286, 12286, 1, 4, 12287, 12287, 3, 1,
3, 3, 2, 12285, 0, 1, 12288, 1, 1, 12287,
0, 0, 1, 0, 12287, 12283, 12283, 12288, 12287, 0,
0, 2, 12286, 3, 3, 0, 12286, 12282, 3, 6,
3, 3, 12285, 1, 1, 12288, 1, 0, 12288, 0,
12287, 4, 1, 0, 12285, 12288, 1, 1, 1, 3,
12286, 0, 12288, 0, 12287, 12287, 3, 5, 1, 12287,
12287, 0, 0, 0, 12283, 0, 0, 12288, 0, 12287,
12286, 12284, 12286, 0, 12286, 3, 5, 12287, 0, 12287,
1, 3, 2, 6, 1, 12287, 1, 1, 12285, 4,
12282, 12288, 12288, 3, 2, 12287, 3, 3, 12288, 12286,
2, 5, 12288, 12287, 12288, 3, 0, 12283, 3, 3,
1, 0, 12288, 2, 2, 12287, 12286, 4, 12287, 12288,
0, 0, 12286, 1, 4, 4, 12286, 12287, 4, 12288,
2, 1, 1, 12288, 12287, 3, 12287, 12286, 12285, 12288,
4, 1, 0, 12287, 3, 12286, 12287, 4, 0, 12287,
12286, 12287, 3, 1, 1, 12285, 12287, 0, 12285, 2,
5, 2, 12285, 3, 2, 12285, 12287, 2, 0, 12288,
2, 5, 2, 12283, 1, 1, 0, 12286, 12288, 3,
1, 12286, 12283, 0, 1, 2, 2, 1, 12287, 12287,
4, 4, 1, 0, 0, 12288, 12287, 12284, 12284, 7,
0, 12288, 5, 4, 12288, 12288, 1, 0, 1, 1,
2, 12288, 12288, 5, 1, 0, 12287, 3, 3, 0,
1, 12288, 12288, 3, 12285, 12288, 3, 5, 4, 1,
12285, 12285, 12288, 12285, 12288, 12285, 4, 1, 3, 12285,
4, 0, 12288, 12286, 5, 12287, 12285, 12288, 4, 12288,
0, 12287, 12286, 0, 12286, 12283, 0, 12287, 12284, 1,
12288, 12288, 3, 12286, 1, 2, 12286, 3, 1, 12285,
12286, 12285, 0, 12285, 12288, 0, 2, 12283, 0, 1,
2, 1, 2, 3, 3, 12285, 0, 0, 0, 12288,
12283, 4, 12286, 2, 1, 3, 3, 12284, 2, 4,
3, 12286, 12282, 12286, 0, 12286, 12287, 3, 12288, 12288,
2, 12287, 12286, 3, 0, 12286, 1, 1, 0, 12287,
2, 0, 0, 1, 12286, 1, 0, 12283, 0, 12288,
2, 5, 12288, 12287, 2, 1, 12288, 2, 2, 5,
2, 12286, 12286, 2, 12284, 12287, 0, 12284, 0, 12284,
12286, 12286, 12288, 12287, 12287, 2, 1, 12287, 12287, 1,
5, 0, 0, 12288, 2, 12285, 6, 2, 12288, 12288,
12286, 2, 12285, 0, 0, 0, 12288, 3, 12286, 1,
1, 0, 3, 0, 12286, 12288, 12287, 3, 2, 12287,
12288, 1, 12288, 12282, 2, 0, 12288, 12286, 12285, 12281,
4, 1, 7, 12283, 12287, 12288, 1, 6, 0, 12288,
5, 1, 1, 12286, 12286, 0, 12287, 12285, 12287, 1,
12288, 12286, 12286, 12288, 2, 12287, 12287, 12288, 12286, 12288,
12282, 12284, 12286, 0, 12285, 12285, 3, 12288, 12287, 12288,
2, 0, 2, 0, 12288, 12286, 3, 12288, 12286, 12287,
1, 1, 1, 0, 5, 5, 12285, 12288, 3, 12286,
1, 2, 12285, 1, 4, 12288, 1, 4, 1, 3,
4, 12286, 0, 7, 2, 12288, 2, 12287, 0, 2,
12283, 12286, 0, 12288, 12286, 4, 1, 12284, 7, 12285,
0, 12284, 12287, 0, 0, 3, 4, 12284, 0, 1,
0, 1, 12285, 1, 12286, 12284, 12287, 0, 7, 1,
4, 12282, 12288, 0, 2, 12285, 12288, 12287, 12287, 12283,
0, 1, 3, 12285, 12286, 3, 12288, 12288, 12284, 12286,
12288, 1, 0, 2, 12287, 0, 12286, 4, 12288, 0,
12284, 0, 0, 2, 12286, 0, 0, 12286, 12287, 1,
12288, 0, 12284, 1, 12288, 12288, 1, 1, 12282, 12284,
12288, 12285, 12285, 12288, 1, 12286, 2, 0, 0, 12284,
2, 12288, 0, 0, 12285, 0, 3, 0, 0, 12285,
12286, 5, 3, 12287, 5, 2, 12287, 0, 1, 12286,
12287, 1, 12286, 1, 12288, 0, 0, 12282, 5, 12282,
12287, 12288, 12287, 1, 0, 3, 4, 6, 1, 1,
12287, 12284, 12286, 12287, 12286, 2, 1, 12288, 3, 0,
3, 0, 12286, 1, 0, 12288, 1, 12284, 4, 0,
4, 12288, 1, 4, 1, 12286, 4, 0, 2, 1,
1, 4, 12287, 2, 1, 12288, 4, 3, 2, 12287,
0, 1, 12287, 1, 12285, 12286, 2, 2, 0, 12286,
12287, 0, 12288, 12285, 5, 12288, 0, 0, 12288, 3,
12288, 0, 4, 0, 12288, 12286, 12287, 0, 0, 2,
12283, 0, 12281, 1, 1, 3, 4, 2, 12284, 5,
12288, 2, 3, 4, 12287, 3, 12288, 12287, 12288, 2,
12286, 2, 0, 12286, 12286, 5, 12288, 2, 12288, 7,
12286, 12286, 4, 12288, 12288, 12288, 5, 12287, 7, 12286,
12282, 2, 12284, 0, 12288, 0, 2, 12283, 2, 5,
4, 1, 12288, 12283, 5, 12288, 12288, 0, 0, 0,
6, 1, 12286, 6, 4, 12287, 2, 12288, 12287, 12286,
4, 5, 0, 1, 2, 1, 4, 12286, 1, 2,
1, 1, 0, 12288, 12282, 1, 1, 3, 12284, 12288,
0, 12287, 1, 12286, 12288, 6, 1, 5, 12287, 12285,
2, 12288, 12288, 12284, 0, 12287, 2, 3, 5, 1,
12286, 1, 12287, 0, 12284, 1, 5, 12283, 1, 1,
12287, 12283, 12288, 0, 12287, 3, 0, 12288, 12286, 12287,
8, 0, 0, 12288, 1, 3, 2, 3, 12287, 9,
2, 3, 4, 12288, 3, 0, 12288, 12283, 0, 0,
2, 4, 12287, 2, 12287, 12286, 12287, 2, 12287, 2,
3, 1, 3, 1, 0, 1, 1, 5, 3, 12285,
1, 12281, 12287, 12286, 1, 4, 12287, 12286, 12285, 4,
2, 0, 12288, 12288, 12286, 12287, 12288, 1, 3, 4,
0, 1, 12285, 4, 3, 12284, 1, 12288, 12285, 12288,
0, 12281, 12288, 12285, 12285, 1, 12284, 12286, 12287, 0,
0, 12287, 1, 12282, 4, 4, 12288, 1, 4, 12286,
5, 4, 1, 5, 3, 1, 0, 6, 12288, 0,
12288, 2, 12286, 12287, 6, 0, 12288, 0, 12287, 1,
4, 0, 12282, 4, 1, 12286, 1, 12282, 3, 12285,
12283, 12286, 12288, 4, 12284, 12286, 12286, 0, 12286, 0,
0, 1, 12286, 1, 1, 4, 12284, 0, 3, 2,
12288, 1, 2, 12287, 2, 1, 12288, 0, 1, 2,
12286, 0, 6, 12285, 0, 1, 4, 0, 0, 3,
2, 12287, 12285, 7, 1, 3, 1, 0, 12286, 12288,
0, 12287, 1, 12286 }
}
};
START_TEST(test_newhope_noise_uniform)
{
newhope_noise_t *noise;
uint8_t seed_buf[seed_len], *uniform;
chunk_t seed = { seed_buf, seed_len };
memset(seed_buf, 0x00, seed_len - 1);
seed_buf[seed_len - 1] = noises[_i].key;
noise = newhope_noise_create(seed);
ck_assert(noise != NULL);
uniform = noise->get_uniform_bytes(noise, noises[_i].nonce, 64);
ck_assert(uniform != NULL);
ck_assert(memeq(uniform, noises[_i].uniform, 64));
free(uniform);
noise->destroy(noise);
}
END_TEST
START_TEST(test_newhope_noise_poly)
{
newhope_noise_t *noise;
uint8_t seed_buf[seed_len];
uint32_t *poly;
int i;
chunk_t seed = { seed_buf, seed_len };
memset(seed_buf, 0x00, seed_len - 1);
seed_buf[seed_len - 1] = noises[_i].key;
noise = newhope_noise_create(seed);
ck_assert(noise != NULL);
poly = noise->get_binomial_words(noise, noises[_i].nonce, n, q);
ck_assert(poly != NULL);
for (i = 0; i < n; i++)
{
ck_assert(poly[i] == noises[_i].poly[i]);
}
free(poly);
noise->destroy(noise);
}
END_TEST
static size_t seed_lengths[] = { 0, 1, 31, 33 };
START_TEST(test_newhope_noise_fail)
{
newhope_noise_t *noise;
chunk_t seed;
seed = chunk_alloc(seed_lengths[_i]);
memset(seed.ptr, 0x00, seed.len);
noise = newhope_noise_create(seed);
ck_assert(noise == NULL);
chunk_free(&seed);
}
END_TEST
Suite *newhope_noise_suite_create()
{
Suite *s;
TCase *tc;
s = suite_create("newhope_noise");
tc = tcase_create("noise_uniform");
tcase_add_loop_test(tc, test_newhope_noise_uniform, 0, countof(noises));
suite_add_tcase(s, tc);
tc = tcase_create("noise_poly");
tcase_add_loop_test(tc, test_newhope_noise_poly, 0, countof(noises));
suite_add_tcase(s, tc);
tc = tcase_create("noise_fail");
tcase_add_loop_test(tc, test_newhope_noise_fail, 0, countof(seed_lengths));
suite_add_tcase(s, tc);
return s;
}
@@ -1,345 +0,0 @@
/*
* Copyright (C) 2016 Andreas Steffen
*
* Copyright (C) secunet Security Networks AG
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include "test_suite.h"
#include <newhope_reconciliation.h>
#include <library.h>
static const uint16_t n = 1024;
static const uint16_t q = 12289;
static uint32_t r_v[] = {
7832, 2714, 1942, 12135, 6869, 11272, 11601, 1783, 9639, 1465,
4603, 8158, 1418, 6162, 3907, 6653, 1091, 3026, 4540, 4797,
2751, 29, 768, 5580, 1304, 5262, 1644, 11294, 12257, 10466,
170, 8458, 7185, 6850, 8790, 11277, 10980, 5507, 10693, 9766,
7230, 3980, 796, 11125, 8042, 9022, 10207, 7577, 5041, 192,
10308, 7905, 8520, 3814, 3372, 11772, 11290, 418, 2744, 4782,
3072, 10921, 10721, 6100, 1021, 7943, 7426, 2142, 6618, 757,
5033, 9336, 9332, 3410, 6613, 11776, 1525, 9567, 5371, 1290,
3685, 11054, 11228, 10703, 70, 11215, 8992, 2855, 2962, 10104,
10083, 8146, 7599, 3428, 4316, 10056, 1245, 9776, 7867, 1381,
6540, 11273, 6626, 3708, 5348, 4521, 3760, 1771, 12037, 2681,
3044, 10226, 5133, 5013, 7851, 7187, 1965, 6776, 223, 3003,
4800, 10128, 9592, 8917, 10664, 7076, 2081, 5621, 2694, 8245,
10979, 929, 10593, 10429, 6890, 6222, 5891, 6633, 12124, 1508,
508, 9650, 2480, 10302, 3958, 4519, 5309, 8675, 6963, 5281,
8265, 4851, 7173, 2537, 1176, 259, 6422, 6782, 1429, 7231,
4948, 8137, 11341, 12090, 5395, 8087, 3098, 6724, 7462, 9973,
149, 7331, 562, 9753, 1227, 768, 7520, 12107, 6199, 6503,
9876, 306, 3876, 1903, 6306, 10288, 10184, 9401, 68, 5246,
630, 10136, 133, 12082, 648, 8537, 3896, 4482, 12011, 5407,
5305, 4301, 6551, 714, 5902, 11915, 3121, 5428, 5441, 5140,
10139, 2091, 875, 9478, 11576, 8663, 10514, 1018, 8780, 6445,
2501, 4204, 1276, 7474, 10594, 3808, 4367, 11469, 4875, 1899,
9136, 1507, 6235, 6367, 3851, 7341, 9925, 4629, 9588, 3150,
4739, 6109, 4850, 9944, 11565, 4995, 8383, 9623, 6248, 3020,
1730, 3368, 3431, 8617, 6478, 7182, 8720, 1927, 6493, 9285,
9779, 2800, 3730, 1754, 3772, 3124, 7569, 10008, 9240, 2493,
4402, 5851, 2050, 8630, 5054, 8421, 1536, 7671, 5467, 9075,
5881, 4355, 4554, 11354, 4048, 10335, 11033, 4252, 2558, 4363,
10448, 327, 1675, 4755, 8227, 7705, 398, 10398, 9913, 4129,
6571, 10743, 280, 6634, 796, 7264, 3916, 11349, 1415, 1187,
692, 9980, 1647, 4267, 1001, 12229, 6040, 268, 1308, 531,
3141, 7209, 1941, 4684, 10261, 1415, 8381, 4919, 11450, 1494,
8237, 11023, 3380, 4448, 10101, 9232, 11040, 7799, 4958, 741,
2234, 10436, 11442, 5073, 2908, 2355, 31, 7222, 5457, 3746,
8920, 122, 8960, 5708, 1750, 11161, 4847, 3199, 7954, 2151,
9419, 11678, 8997, 12016, 9690, 9605, 10718, 3735, 1617, 9574,
10384, 11604, 9311, 687, 7145, 11891, 6529, 5052, 1342, 8735,
7644, 6062, 6338, 8563, 2502, 5284, 220, 5224, 3771, 11067,
11609, 2972, 3799, 2566, 7488, 6369, 7704, 6095, 3598, 12112,
8545, 2026, 746, 3206, 2814, 8740, 1491, 5950, 8413, 4043,
12036, 6082, 4131, 1941, 6942, 9396, 11267, 8912, 7344, 10371,
9205, 9520, 12038, 4345, 8024, 10999, 8408, 4673, 6682, 8893,
8668, 10099, 7658, 11896, 4276, 2042, 10707, 9793, 3152, 11961,
3269, 5512, 5736, 5938, 9457, 10439, 10777, 6656, 3174, 9043,
6046, 2519, 11912, 5244, 6214, 2071, 11317, 5285, 891, 6184,
3819, 1563, 1474, 654, 5147, 2380, 10760, 4816, 3378, 1414,
7784, 10067, 1809, 6320, 4789, 9359, 2747, 9424, 9074, 9473,
3300, 6244, 104, 7612, 1105, 4276, 573, 1988, 923, 12047,
7948, 4860, 3949, 4971, 6956, 2831, 2034, 289, 10946, 6970,
3191, 5122, 2175, 1300, 6198, 256, 6433, 11646, 9119, 9723,
1046, 5967, 1124, 6449, 2817, 692, 4649, 3089, 5050, 11261,
2220, 3052, 12012, 10110, 1394, 2877, 10089, 11696, 4462, 5504,
66, 2500, 5384, 7461, 5712, 8649, 9536, 7670, 2385, 3469,
782, 2876, 7772, 6118, 142, 5396, 10951, 10556, 3450, 10602,
1604, 7909, 3323, 39, 10258, 2262, 7113, 11313, 10203, 10846,
9275, 4316, 965, 6006, 4458, 7926, 3171, 1797, 4659, 5336,
5543, 250, 9230, 10720, 11970, 4511, 4311, 11763, 1283, 4044,
2643, 3744, 4490, 5984, 8868, 8760, 11738, 6037, 9164, 7601,
7544, 11117, 7322, 2081, 4034, 10791, 11491, 7027, 1615, 5338,
8528, 3424, 2126, 927, 1650, 6068, 3812, 10958, 7574, 11032,
6954, 6132, 2598, 9458, 11346, 1974, 3273, 1040, 10331, 8587,
11017, 6864, 8246, 5328, 11330, 6779, 8761, 4342, 4595, 8610,
161, 4622, 6411, 10708, 7896, 11431, 12097, 9500, 3376, 9561,
10730, 2248, 3069, 1434, 8838, 566, 6397, 5881, 4956, 4203,
8362, 6047, 3484, 4784, 9901, 8989, 862, 8817, 12186, 9876,
9748, 1905, 5696, 9028, 5721, 2940, 10235, 2326, 2134, 6167,
1019, 10851, 1253, 5588, 9149, 6532, 3959, 11598, 4068, 3299,
8264, 9787, 7089, 2829, 6755, 6156, 455, 5900, 2839, 5921,
2140, 7428, 2688, 11175, 9247, 6727, 11711, 1762, 6244, 3336,
2308, 9922, 7883, 7007, 10890, 7013, 8452, 2743, 1482, 6927,
7846, 6128, 5114, 4868, 7487, 4584, 6785, 460, 6747, 8894,
9855, 12242, 3365, 1450, 6614, 3974, 5200, 3247, 2779, 8695,
828, 10940, 2304, 376, 3027, 3898, 10351, 1879, 10262, 2512,
5487, 4280, 10297, 8480, 9481, 7905, 197, 8361, 4927, 705,
9671, 6722, 2589, 8772, 1078, 333, 8696, 6267, 7420, 4471,
8994, 5038, 5318, 1846, 2574, 8779, 10724, 825, 7399, 7073,
4422, 8385, 5171, 8849, 11344, 10735, 8483, 2241, 11738, 6581,
10699, 2777, 6531, 4678, 7608, 10871, 3501, 9239, 7252, 11828,
7873, 9606, 4526, 5958, 8505, 11233, 9638, 2421, 5652, 3095,
9049, 11347, 6274, 1405, 11114, 11208, 5703, 10774, 3011, 11633,
5741, 9601, 5507, 4527, 3501, 5707, 8698, 178, 12091, 325,
6056, 635, 3772, 12169, 10509, 6528, 3573, 3675, 3389, 3161,
1148, 2687, 3509, 6639, 10452, 11804, 5355, 1085, 9580, 7106,
1396, 8279, 4881, 3402, 7803, 8801, 6142, 7623, 4386, 9291,
1502, 500, 11809, 6655, 2674, 10061, 1650, 5422, 8936, 10011,
1193, 9619, 1435, 8285, 4038, 9984, 9732, 4477, 1251, 7106,
7817, 10062, 3378, 5608, 2395, 2563, 1957, 3768, 4160, 7267,
11631, 2171, 4771, 6927, 4330, 10482, 6204, 11022, 7895, 1924,
3648, 1991, 6628, 10136, 2916, 5416, 7827, 1479, 2312, 9991,
7915, 5431, 10911, 10979, 4527, 436, 10521, 5725, 2201, 10198,
662, 1691, 8867, 10008, 9359, 5291, 567, 5725, 10329, 4772,
2813, 7323, 5646, 1861, 9922, 1831, 9356, 1219, 4107, 9999,
4569, 9092, 833, 1602, 4258, 1443, 1484, 4036, 5415, 3767,
9992, 412, 9343, 2251, 10513, 9067, 1494, 11893, 744, 1978,
11259, 3614, 7459, 5254, 4232, 5148, 4119, 11550, 6425, 4933,
4292, 10521, 9657, 9632, 4613, 7738, 5561, 8806, 3501, 3731,
11329, 2693, 11581, 6393, 10176, 10773, 1790, 1809, 9186, 12085,
5418, 7223, 1077, 1527, 10917, 4236, 7668, 11754, 6655, 7696,
1809, 11512, 3618, 5857, 7512, 1044, 7970, 6825, 4897, 2870,
126, 8619, 10445, 3883, 4238, 4051, 399, 1580, 9893, 11046,
2955, 6520, 5435, 1891, 1254, 12135, 4122, 10512, 11960, 6196,
3443, 10118, 1689, 10877
};
static uint32_t i_v[] = {
8355, 2010, 1416, 12110, 6361, 11296, 11668, 1446, 9822, 947,
5422, 8211, 1824, 6158, 3458, 6435, 685, 2707, 4804, 4929,
3204, 12158, 674, 5703, 1125, 5085, 1358, 10956, 12216, 11164,
12112, 8359, 7018, 7038, 9099, 11789, 10574, 5991, 10736, 9335,
7898, 4429, 587, 11156, 7912, 9063, 9673, 6792, 5530, 648,
10203, 7284, 7935, 4177, 3514, 11488, 10998, 12254, 2913, 4827,
2446, 10965, 10718, 5569, 1023, 8150, 7440, 1928, 6384, 802,
4726, 9738, 10374, 3842, 6761, 11788, 1133, 9413, 5818, 1099,
3710, 11315, 11667, 10285, 12431, 11195, 9193, 2842, 2267, 9902,
10076, 7409, 6751, 3748, 4487, 9961, 1547, 10060, 7443, 1276,
6827, 10798, 6323, 4038, 5508, 4006, 3300, 1774, 255, 2688,
3238, 10275, 4911, 5648, 7842, 7506, 1769, 6425, 195, 3176,
4455, 10337, 9451, 8912, 10445, 7646, 2837, 5109, 3033, 8668,
10295, 744, 10869, 10204, 6825, 6326, 6299, 7208, 11886, 1246,
704, 9626, 2538, 10932, 3903, 4545, 5111, 9006, 6698, 5008,
8464, 4679, 7230, 2223, 707, 705, 6592, 6207, 1114, 7645,
5374, 7595, 11064, 746, 5585, 8248, 2921, 7004, 6595, 9985,
506, 7147, 793, 9605, 596, 962, 8223, 11771, 6438, 6663,
9519, 12013, 4302, 2216, 6633, 10351, 10096, 9645, 347, 4601,
596, 10448, 12051, 12376, 1544, 8939, 5114, 4052, 11408, 5947,
5368, 4270, 6747, 423, 6283, 11211, 2574, 5974, 5533, 5143,
9757, 2155, 729, 9776, 11989, 8808, 11057, 1519, 9187, 5996,
2966, 3865, 1409, 8023, 10648, 4397, 5082, 10832, 4769, 2068,
9226, 1790, 5911, 6534, 3780, 7312, 9388, 5014, 9054, 3445,
4659, 6203, 5234, 9490, 11060, 4214, 8978, 9789, 6201, 3088,
1988, 3057, 3762, 8725, 7322, 7583, 8233, 1394, 6534, 9221,
9736, 2738, 3837, 2595, 4012, 3674, 7505, 10231, 8080, 2402,
3977, 5928, 1942, 8421, 5507, 8422, 1238, 6909, 5800, 9613,
6083, 4382, 4669, 11670, 4032, 10762, 11623, 4387, 3728, 4656,
9701, 722, 1255, 4495, 8158, 7762, 792, 10307, 9813, 3904,
6081, 11003, 12045, 6718, 1089, 7327, 4381, 11188, 943, 1740,
563, 10251, 756, 5027, 848, 325, 6547, 12288, 1222, 12189,
3641, 7314, 2049, 5254, 10043, 1068, 7906, 4741, 11639, 1981,
7660, 10911, 2746, 4536, 10068, 9700, 11057, 8114, 5556, 253,
2292, 10686, 11848, 5306, 3092, 2570, 12167, 7101, 5245, 3463,
8627, 12513, 9010, 5356, 1633, 10462, 4545, 3614, 7245, 1887,
9738, 11902, 8716, 12035, 9958, 9421, 11063, 3759, 883, 9754,
10730, 11706, 9132, 540, 6726, 11382, 7038, 4407, 1225, 8606,
7689, 5894, 6553, 7908, 2454, 4939, 613, 5811, 3580, 11792,
11364, 3153, 3698, 2604, 7470, 6053, 7699, 6018, 4289, 11497,
8580, 2249, 718, 2444, 2972, 8812, 1710, 6317, 8718, 4194,
12288, 5837, 3698, 2216, 7402, 9045, 11194, 8500, 7238, 10686,
9409, 9867, 12264, 3859, 7673, 11659, 8496, 4618, 6465, 8811,
9114, 10740, 7738, 11850, 4142, 2493, 11136, 9623, 3071, 11701,
2925, 5043, 6151, 6221, 9642, 10846, 11145, 6315, 3741, 9123,
5131, 2585, 11337, 4786, 5844, 1485, 11505, 5205, 797, 5955,
3717, 1756, 1551, 1122, 5057, 2585, 10857, 5129, 3557, 1254,
7750, 9688, 2462, 6415, 4345, 9460, 2957, 8793, 9210, 9242,
3487, 6506, 11888, 7563, 1078, 4486, 406, 2261, 867, 11965,
7979, 4533, 3654, 4747, 6636, 3166, 2114, 380, 9715, 7132,
2982, 5024, 1817, 1231, 6210, 12377, 6280, 10882, 9937, 9587,
633, 5668, 899, 6176, 2431, 956, 5022, 3094, 4658, 11168,
2989, 2654, 11990, 10494, 1691, 3017, 10044, 11882, 4020, 5342,
11911, 2426, 5748, 7592, 6340, 9214, 9357, 7169, 2109, 3210,
415, 3024, 7791, 5684, 246, 5134, 11335, 10092, 3133, 10427,
1502, 7739, 3272, 169, 9521, 2550, 7327, 11309, 10815, 10146,
9157, 4579, 1022, 6447, 4233, 8488, 2958, 1715, 4215, 4965,
5728, 551, 8942, 10845, 11881, 4472, 4331, 304, 1183, 3798,
1968, 3993, 4889, 6145, 8841, 8816, 11283, 6578, 9212, 8161,
7003, 11574, 7764, 1678, 4138, 10444, 11880, 7101, 1390, 4743,
8320, 3026, 2338, 1203, 1562, 6502, 3103, 10770, 7608, 11097,
6745, 6037, 2926, 9489, 10782, 1853, 3482, 524, 11063, 8299,
11092, 6838, 7779, 4598, 11245, 7274, 8908, 3886, 4440, 8651,
11949, 5344, 6954, 11015, 8333, 11347, 12677, 8716, 3514, 9892,
10366, 2029, 2875, 1540, 9013, 250, 6393, 5618, 4565, 3687,
8340, 6420, 3632, 5032, 9408, 9738, 961, 8653, 12315, 10459,
9883, 2074, 5357, 9341, 4850, 2514, 9746, 2605, 2394, 5928,
808, 10443, 1589, 5673, 9176, 6593, 3404, 12254, 4230, 3630,
7958, 10065, 7471, 2432, 6626, 6517, 382, 6131, 2888, 5440,
1571, 7341, 2841, 11202, 9462, 7180, 11206, 1433, 6183, 3882,
2105, 9906, 8076, 7074, 10572, 7262, 8456, 2979, 1095, 6891,
8025, 5914, 5380, 4300, 7363, 4989, 6788, 1043, 6836, 8710,
10099, 12310, 3997, 2102, 7002, 4041, 4948, 2601, 2958, 8665,
984, 10820, 1940, 541, 3377, 3533, 9357, 2049, 10721, 2732,
5355, 4280, 10281, 8056, 9557, 7749, 611, 8255, 4854, 708,
9199, 7033, 2582, 8343, 820, 944, 8651, 5547, 7052, 4723,
8972, 5594, 5314, 1938, 2539, 8789, 10341, 12368, 7475, 6903,
4436, 8346, 5391, 8336, 10864, 10397, 8517, 2078, 12127, 6612,
10511, 2970, 6576, 5166, 7744, 10934, 3186, 9515, 6831, 12085,
7284, 9791, 4755, 6341, 8713, 11526, 9392, 2122, 5743, 2776,
9581, 11396, 7006, 1465, 11235, 10997, 5776, 10401, 2929, 11732,
5847, 9512, 6068, 3934, 3730, 5813, 9195, 410, 11698, 896,
6321, 1310, 3478, 11649, 10201, 6850, 3612, 3451, 3569, 3266,
747, 3151, 3352, 6497, 10445, 11501, 5306, 1026, 9712, 7294,
813, 8005, 5090, 2905, 7903, 8358, 6290, 7756, 3955, 9471,
1858, 699, 11847, 7292, 2165, 10556, 1038, 5289, 8693, 9698,
1702, 10228, 1412, 8681, 3330, 10042, 8888, 4257, 1201, 7422,
7956, 10019, 3011, 5956, 2188, 2407, 1986, 3847, 4345, 7427,
12091, 1763, 3885, 6731, 4172, 10828, 6129, 10972, 7878, 2189,
3988, 2125, 6536, 10663, 3100, 5129, 7656, 1053, 2303, 10149,
8087, 5666, 11151, 10962, 4905, 779, 10113, 5451, 1509, 9590,
735, 1626, 8419, 10607, 9293, 5778, 907, 5527, 10408, 5454,
2266, 7131, 6332, 2055, 10105, 1188, 9842, 2059, 4417, 10026,
4339, 9779, 680, 1731, 4958, 1589, 1866, 3797, 5058, 3735,
9899, 543, 9330, 2436, 10757, 9010, 1270, 12232, 1122, 2222,
10945, 3733, 7454, 5251, 4185, 5118, 4331, 12022, 5900, 4767,
4393, 10252, 9957, 9653, 4674, 7705, 5694, 9123, 3882, 3137,
11627, 2712, 11985, 6346, 9990, 10760, 1869, 1778, 8899, 12168,
5207, 7250, 1088, 1131, 11567, 4337, 8286, 11660, 7152, 8010,
2286, 11335, 2984, 5740, 7114, 806, 7579, 7119, 5122, 2917,
541, 7913, 10555, 3684, 4720, 3954, 517, 1526, 9712, 10854,
1921, 6897, 4704, 2141, 1602, 11880, 4548, 10569, 11521, 6408,
3609, 9752, 1960, 10934
};
static uint8_t rbits[] = {
0x3f, 0xff, 0xaf, 0x0f, 0x6b, 0xb2, 0xb8, 0x46, 0x53, 0x44,
0x95, 0x98, 0x0a, 0x85, 0x0c, 0xfc, 0xc4, 0x86, 0xcc, 0x69,
0xc6, 0xd9, 0xfa, 0xee, 0x19, 0xa6, 0x34, 0x0f, 0x35, 0xc4,
0xdc, 0x08
};
static uint8_t r_ref[] = {
0, 3, 3, 1, 1, 1, 0, 1, 0, 3, 2, 0, 1, 1, 3, 0, 2, 1, 0, 3,
2, 1, 2, 3, 3, 0, 2, 0, 1, 3, 3, 2, 3, 3, 0, 3, 0, 2, 2, 0,
1, 1, 2, 0, 1, 1, 2, 1, 3, 0, 0, 3, 1, 1, 0, 0, 0, 2, 0, 1,
0, 2, 3, 1, 3, 0, 3, 1, 0, 0, 2, 1, 3, 3, 1, 3, 2, 1, 0, 2,
0, 0, 3, 3, 0, 1, 2, 2, 0, 1, 0, 3, 2, 2, 1, 1, 3, 0, 3, 3,
2, 2, 0, 2, 1, 0, 0, 0, 3, 0, 3, 1, 2, 1, 1, 0, 3, 3, 2, 1,
3, 3, 2, 2, 1, 3, 0, 0, 2, 2, 3, 1, 1, 2, 2, 2, 0, 2, 0, 2,
0, 0, 1, 2, 2, 2, 3, 1, 2, 0, 3, 0, 1, 3, 2, 3, 3, 1, 1, 2,
0, 0, 2, 1, 2, 2, 0, 2, 2, 2, 2, 1, 1, 3, 1, 3, 3, 1, 2, 2,
3, 0, 1, 0, 0, 2, 2, 1, 3, 2, 2, 2, 3, 1, 1, 0, 0, 3, 2, 3,
0, 0, 3, 3, 2, 2, 2, 2, 1, 1, 0, 1, 2, 1, 3, 2, 0, 3, 0, 2,
3, 3, 3, 3, 2, 3, 3, 3, 3, 2, 1, 0, 2, 3, 2, 1, 2, 0, 3, 0,
2, 2, 1, 1, 2, 1, 2, 0, 1, 2, 1, 3, 0, 0, 2, 3, 0, 3, 1, 0,
2, 2, 2, 1, 2, 0, 3, 1, 0, 0, 3, 0, 2, 3, 1, 0, 2, 3, 3, 0,
0, 0, 3, 0, 2, 3, 2, 0, 2, 2, 1, 0, 1, 2, 1, 3, 3, 3, 1, 2,
1, 2, 3, 1, 1, 2, 2, 0, 3, 0, 3, 3, 1, 3, 3, 3, 1, 3, 0, 3,
0, 0, 1, 2, 1, 0, 3, 0, 0, 2, 1, 3, 3, 3, 1, 1, 2, 3, 1, 0,
1, 1, 3, 3, 0, 3, 1, 3, 1, 2, 2, 2, 1, 3, 1, 2, 1, 3, 0, 1,
2, 2, 2, 3, 3, 2, 2, 3, 1, 2, 2, 1, 2, 1, 0, 0, 0, 1, 3, 2,
0, 3, 1, 1, 2, 1, 3, 2, 3, 2, 0, 1, 0, 1, 3, 0, 2, 3, 1, 3,
0, 1, 1, 3, 1, 1, 1, 0, 2, 3, 2, 1, 2, 0, 3, 3, 2, 0, 1, 0,
3, 3, 3, 1, 2, 2, 1, 0, 3, 3, 0, 2, 3, 1, 1, 1, 3, 3, 1, 3,
3, 0, 1, 0, 2, 0, 1, 1, 0, 0, 3, 2, 2, 3, 0, 2, 2, 0, 1, 1,
1, 3, 1, 1, 1, 0, 1, 2, 3, 2, 2, 3, 1, 1, 3, 3, 3, 1, 2, 0,
0, 0, 2, 2, 2, 3, 2, 0, 0, 1, 3, 0, 0, 0, 2, 0, 1, 0, 3, 0,
3, 1, 0, 1, 1, 1, 2, 2, 2, 0, 0, 2, 2, 0, 3, 1, 0, 2, 2, 0,
2, 0, 0, 1, 1, 0, 1, 2, 3, 2, 3, 2, 3, 3, 3, 0, 2, 1, 2, 2,
1, 0, 1, 1, 1, 2, 1, 3, 2, 0, 3, 3, 0, 0, 1, 1, 1, 2, 2, 2,
0, 1, 1, 2, 0, 2, 0, 1, 2, 0, 1, 3, 2, 2, 3, 0, 0, 1, 1, 2,
3, 1, 2, 0, 3, 0, 2, 1, 0, 0, 0, 1, 1, 1, 1, 3, 0, 0, 0, 3,
2, 3, 2, 1, 0, 3, 1, 1, 1, 1, 3, 0, 0, 1, 1, 1, 0, 3, 2, 2,
3, 1, 1, 3, 0, 1, 1, 3, 0, 3, 2, 2, 0, 3, 1, 3, 1, 0, 0, 1,
1, 0, 0, 1, 0, 3, 2, 2, 0, 1, 3, 0, 1, 3, 3, 2, 1, 3, 1, 1,
3, 3, 2, 1, 1, 3, 1, 0, 2, 1, 1, 3, 3, 3, 1, 3, 1, 3, 0, 1,
2, 2, 0, 3, 3, 2, 1, 1, 1, 3, 0, 2, 0, 3, 3, 1, 2, 3, 1, 3,
0, 0, 0, 1, 3, 3, 0, 2, 3, 0, 1, 3, 0, 0, 3, 0, 2, 2, 3, 3,
3, 3, 2, 1, 0, 3, 1, 1, 1, 2, 2, 0, 3, 2, 0, 2, 2, 3, 1, 0,
3, 3, 1, 2, 3, 0, 1, 1, 0, 3, 3, 1, 1, 3, 0, 2, 1, 2, 2, 2,
2, 3, 2, 3, 0, 0, 3, 1, 1, 0, 3, 2, 3, 2, 3, 3, 2, 2, 3, 1,
3, 2, 1, 0, 1, 0, 2, 2, 1, 3, 1, 2, 3, 3, 1, 3, 2, 1, 3, 2,
2, 3, 1, 1, 3, 3, 3, 3, 2, 0, 0, 3, 3, 3, 2, 3, 2, 0, 3, 0,
3, 1, 2, 0, 3, 0, 2, 2, 2, 3, 1, 2, 2, 1, 3, 3, 0, 1, 3, 0,
0, 1, 3, 2, 1, 1, 0, 1, 3, 3, 1, 1, 0, 1, 2, 2, 2, 0, 2, 3,
1, 2, 1, 1, 3, 2, 3, 3, 1, 0, 1, 3, 2, 3, 2, 2, 1, 2, 3, 1,
3, 2, 3, 1, 3, 3, 0, 3, 1, 1, 3, 2, 1, 2, 2, 0, 1, 1, 2, 3,
1, 3, 0, 0, 3, 0, 3, 0, 1, 2, 0, 2, 2, 3, 2, 0, 0, 0, 3, 0,
2, 0, 0, 2, 2, 2, 3, 1, 3, 2, 3, 2, 0, 1, 2, 1, 1, 3, 0, 3,
2, 0, 2, 2, 3, 2, 1, 0, 1, 1, 0, 2, 0, 3, 2, 0, 2, 3, 1, 3,
2, 2, 2, 2, 3, 1, 0, 2, 3, 3, 3, 2, 0, 0, 3, 3, 1, 2, 2, 3,
0, 1, 1, 1, 3, 2, 1, 0, 0, 1, 2, 3, 3, 0, 1, 1, 1, 1, 0, 1,
0, 2, 3, 3, 3, 3, 0, 2, 3, 0, 1, 0, 0, 1, 1, 3, 2, 2, 0, 0,
2, 2, 1, 3
};
static chunk_t shared_secret = chunk_from_chars(
0x14, 0x22, 0x06, 0xe3, 0x48, 0xf3, 0xfa, 0xfc, 0x21, 0x0d,
0x5d, 0x51, 0x19, 0x7f, 0x16, 0x4e, 0xe6, 0xd3, 0x10, 0xa9,
0xf5, 0xab, 0xfc, 0x96, 0x11, 0x1b, 0xc3, 0x4a, 0x89, 0xf9,
0x66, 0x55
);
START_TEST(test_newhope_rec_good)
{
newhope_reconciliation_t *rec;
chunk_t i_shared_secret, r_shared_secret;
uint8_t *r;
rec = newhope_reconciliation_create(n, q);
ck_assert(rec != NULL);
r = rec->help_reconcile(rec, r_v, rbits);
ck_assert(memeq(r, r_ref, n));
r_shared_secret = rec->reconcile(rec, r_v, r);
ck_assert(chunk_equals(r_shared_secret, shared_secret));
i_shared_secret = rec->reconcile(rec, i_v, r);
ck_assert(chunk_equals(i_shared_secret, shared_secret));
/* cleanup */
rec->destroy(rec);
chunk_free(&i_shared_secret);
chunk_free(&r_shared_secret);
free(r);
}
END_TEST
Suite *newhope_reconciliation_suite_create()
{
Suite *s;
TCase *tc;
s = suite_create("newhope_reconciliation");
tc = tcase_create("rec_good");
tcase_add_test(tc, test_newhope_rec_good);
suite_add_tcase(s, tc);
return s;
}