From: Simon Josefsson Date: Thu, 11 May 2023 11:50:55 +0000 (+0200) Subject: Add Streamlined NTRU Prime sntrup761. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dececfe57954a4564a4a4df6bf155a910ece9da7;p=thirdparty%2Fnettle.git Add Streamlined NTRU Prime sntrup761. --- diff --git a/Makefile.in b/Makefile.in index 93999850..6b8d05aa 100644 --- a/Makefile.in +++ b/Makefile.in @@ -181,7 +181,8 @@ nettle_SOURCES = aes-decrypt-internal.c aes-decrypt-table.c \ slh-shake.c slh-sha256.c \ slh-fors.c slh-merkle.c slh-wots.c slh-xmss.c \ slh-dsa.c slh-dsa-128s.c slh-dsa-128f.c \ - slh-dsa-shake-128s.c slh-dsa-shake-128f.c slh-dsa-sha2-128s.c slh-dsa-sha2-128f.c + slh-dsa-shake-128s.c slh-dsa-shake-128f.c slh-dsa-sha2-128s.c slh-dsa-sha2-128f.c \ + sntrup761.c hogweed_SOURCES = sexp.c sexp-format.c \ sexp-transport.c sexp-transport-format.c \ @@ -259,7 +260,7 @@ HEADERS = aes.h arcfour.h arctwo.h asn1.h blowfish.h balloon.h \ salsa20.h sexp.h serpent.h \ sha1.h sha2.h sha3.h slh-dsa.h sm3.h sm4.h streebog.h twofish.h \ umac.h yarrow.h xts.h poly1305.h nist-keywrap.h \ - drbg-ctr.h + drbg-ctr.h sntrup761.h INSTALL_HEADERS = $(HEADERS) version.h @IF_MINI_GMP@ mini-gmp.h diff --git a/nettle.texinfo b/nettle.texinfo index a632aa9b..2ea742b1 100644 --- a/nettle.texinfo +++ b/nettle.texinfo @@ -84,6 +84,7 @@ Reference * Keyed hash functions:: * Key derivation functions:: * Public-key algorithms:: +* Key-Encapsulation mechanisms:: * Randomness:: * ASCII encoding:: * Miscellaneous functions:: @@ -376,6 +377,7 @@ This chapter describes all the Nettle functions, grouped by family. * Keyed hash functions:: * Key derivation functions:: * Public-key algorithms:: +* Key-Encapsulation mechanisms:: * Randomness:: * ASCII encoding:: * Miscellaneous functions:: @@ -5893,6 +5895,53 @@ Verifies a message using the provided public key. Returns 1 if the signature is valid, otherwise 0. @end deftypefun +@node Key-Encapsulation mechanisms +@section Key-Encapsulation mechanisms + +@cindex Key-Encapsulation mechanisms +@cindex KEM + +Key-Encapsulation mechanisms allows a sender to take a public key as +input and produce (encapsulate) a session key wrapped in ciphertext, and +the receiver to extract (decapsulate) the session key using its private +key. + +Nettle supports the Streamlined NTRU Prime algorithm @code{sntrup761}. + +Nettle defines sntrup761 in @file{}. + +@defvr Constant SNTRUP761_SECRETKEY_SIZE +The size (1763 bytes) of the sntrup651 secret key. +@end defvr + +@defvr Constant SNTRUP761_PUBLICKEY_SIZE +The size (1158 bytes) of the sntrup651 secret key. +@end defvr + +@defvr Constant SNTRUP761_CIPHERTEXT_SIZE +The size (1039 bytes) of the sntrup651 ciphertext. +@end defvr + +@defvr Constant SNTRUP761_SIZE +The size (32 bytes) of the sntrup651 output key. +@end defvr + +@deftypefun void sntrup761_keypair (uint8_t *@var{pk}, uint8_t *@var{sk}, void *@var{random_ctx}, nettle_random_func *@var{random}); +Generate a sntrup761 public key @var{pk} and private key @var{sk}, using +randomness-generator @var{random} with context @var{random_ctx}. +@end deftypefun + +@deftypefun void sntrup761_enc (uint8_t *@var{c}, uint8_t *@var{k}, const uint8_t *@var{pk}, void *@var{random_ctx}, nettle_random_func *@var{random}); +Generate a session key @var{k} and encapsulate it into ciphertext +@var{c} for the recipient with public-key @var{pk}, using +randomness-generator @var{random} with context @var{random_ctx}. +@end deftypefun + +@deftypefun void sntrup761_dec (uint8_t *@var{k}, const uint8_t *@var{c}, const uint8_t *@var{sk}); +Decapsulate session key @var{k} from ciphertext @var{c} using the +private key @var{sk}. +@end deftypefun + @node Randomness @section Randomness diff --git a/sntrup761.c b/sntrup761.c new file mode 100644 index 00000000..96d2eb96 --- /dev/null +++ b/sntrup761.c @@ -0,0 +1,1080 @@ +/* sntrup761.c + + Copyright (C) 2023 Simon Josefsson + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * 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. + + or both in parallel, as here. + + GNU Nettle 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. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +/* + * Derived from public domain source, written by (in alphabetical order): + * - Daniel J. Bernstein + * - Chitchanok Chuengsatiansup + * - Tanja Lange + * - Christine van Vredendaal + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include "sntrup761.h" + +#include "sha2.h" + +static void +crypto_hash_sha512 (unsigned char *out, const unsigned char *in, int inlen) +{ + struct sha512_ctx ctx; + + sha512_init (&ctx); + sha512_update (&ctx, inlen, in); + sha512_digest (&ctx, out); +} + +/* from supercop-20201130/crypto_sort/int32/portable4/int32_minmax.inc */ +#define int32_MINMAX(a,b) \ +do { \ + int64_t ab = (int64_t)b ^ (int64_t)a; \ + int64_t c = (int64_t)b - (int64_t)a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +/* from supercop-20201130/crypto_sort/int32/portable4/sort.c */ +static void +crypto_sort_int32 (void *array, long long n) +{ + long long top, p, q, r, i, j; + int32_t *x = array; + + if (n < 2) + return; + top = 1; + while (top < n - top) + top += top; + + for (p = top; p >= 1; p >>= 1) + { + i = 0; + while (i + 2 * p <= n) + { + for (j = i; j < i + p; ++j) + int32_MINMAX (x[j], x[j + p]); + i += 2 * p; + } + for (j = i; j < n - p; ++j) + int32_MINMAX (x[j], x[j + p]); + + i = 0; + j = 0; + for (q = top; q > p; q >>= 1) + { + if (j != i) + for (;;) + { + if (j == n - q) + goto done; + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + int32_MINMAX (a, x[j + r]); + x[j + p] = a; + ++j; + if (j == i + p) + { + i += 2 * p; + break; + } + } + while (i + p <= n - q) + { + for (j = i; j < i + p; ++j) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + int32_MINMAX (a, x[j + r]); + x[j + p] = a; + } + i += 2 * p; + } + /* now i + p > n - q */ + j = i; + while (j < n - q) + { + int32_t a = x[j + p]; + for (r = q; r > p; r >>= 1) + int32_MINMAX (a, x[j + r]); + x[j + p] = a; + ++j; + } + + done:; + } + } +} + +/* from supercop-20201130/crypto_sort/uint32/useint32/sort.c */ + +/* can save time by vectorizing xor loops */ +/* can save time by integrating xor loops with int32_sort */ + +static void +crypto_sort_uint32 (void *array, long long n) +{ + uint32_t *x = array; + long long j; + for (j = 0; j < n; ++j) + x[j] ^= 0x80000000; + crypto_sort_int32 (array, n); + for (j = 0; j < n; ++j) + x[j] ^= 0x80000000; +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/uint32.c */ + +/* +CPU division instruction typically takes time depending on x. +This software is designed to take time independent of x. +Time still varies depending on m; user must ensure that m is constant. +Time also varies on CPUs where multiplication is variable-time. +There could be more CPU issues. +There could also be compiler issues. +*/ + +static void +uint32_divmod_uint14 (uint32_t * q, uint16_t * r, uint32_t x, uint16_t m) +{ + uint32_t v = 0x80000000; + uint32_t qpart; + uint32_t mask; + + v /= m; + + /* caller guarantees m > 0 */ + /* caller guarantees m < 16384 */ + /* vm <= 2^31 <= vm+m-1 */ + /* xvm <= 2^31 x <= xvm+x(m-1) */ + + *q = 0; + + qpart = (x * (uint64_t) v) >> 31; + /* 2^31 qpart <= xv <= 2^31 qpart + 2^31-1 */ + /* 2^31 qpart m <= xvm <= 2^31 qpart m + (2^31-1)m */ + /* 2^31 qpart m <= 2^31 x <= 2^31 qpart m + (2^31-1)m + x(m-1) */ + /* 0 <= 2^31 newx <= (2^31-1)m + x(m-1) */ + /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */ + /* 0 <= newx <= (1-1/2^31)(2^14-1) + (2^32-1)((2^14-1)-1)/2^31 */ + + x -= qpart * m; + *q += qpart; + /* x <= 49146 */ + + qpart = (x * (uint64_t) v) >> 31; + /* 0 <= newx <= (1-1/2^31)m + x(m-1)/2^31 */ + /* 0 <= newx <= m + 49146(2^14-1)/2^31 */ + /* 0 <= newx <= m + 0.4 */ + /* 0 <= newx <= m */ + + x -= qpart * m; + *q += qpart; + /* x <= m */ + + x -= m; + *q += 1; + mask = -(x >> 31); + x += mask & (uint32_t) m; + *q += mask; + /* x < m */ + + *r = x; +} + + +static uint16_t +uint32_mod_uint14 (uint32_t x, uint16_t m) +{ + uint32_t q; + uint16_t r; + uint32_divmod_uint14 (&q, &r, x, m); + return r; +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/int32.c */ + +static void +int32_divmod_uint14 (int32_t * q, uint16_t * r, int32_t x, uint16_t m) +{ + uint32_t uq, uq2; + uint16_t ur, ur2; + uint32_t mask; + + uint32_divmod_uint14 (&uq, &ur, 0x80000000 + (uint32_t) x, m); + uint32_divmod_uint14 (&uq2, &ur2, 0x80000000, m); + ur -= ur2; + uq -= uq2; + mask = -(uint32_t) (ur >> 15); + ur += mask & m; + uq += mask; + *r = ur; + *q = uq; +} + + +static uint16_t +int32_mod_uint14 (int32_t x, uint16_t m) +{ + int32_t q; + uint16_t r; + int32_divmod_uint14 (&q, &r, x, m); + return r; +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/paramsmenu.h */ +#define p 761 +#define q 4591 +#define Rounded_bytes 1007 +#define Rq_bytes 1158 +#define w 286 + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.h */ + +/* Decode(R,s,M,len) */ +/* assumes 0 < M[i] < 16384 */ +/* produces 0 <= R[i] < M[i] */ + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Decode.c */ + +static void +Decode (uint16_t * out, const unsigned char *S, const uint16_t * M, + long long len) +{ + if (len == 1) + { + if (M[0] == 1) + *out = 0; + else if (M[0] <= 256) + *out = uint32_mod_uint14 (S[0], M[0]); + else + *out = uint32_mod_uint14 (S[0] + (((uint16_t) S[1]) << 8), M[0]); + } + if (len > 1) + { + uint16_t R2[(len + 1) / 2]; + uint16_t M2[(len + 1) / 2]; + uint16_t bottomr[len / 2]; + uint32_t bottomt[len / 2]; + long long i; + for (i = 0; i < len - 1; i += 2) + { + uint32_t m = M[i] * (uint32_t) M[i + 1]; + if (m > 256 * 16383) + { + bottomt[i / 2] = 256 * 256; + bottomr[i / 2] = S[0] + 256 * S[1]; + S += 2; + M2[i / 2] = (((m + 255) >> 8) + 255) >> 8; + } + else if (m >= 16384) + { + bottomt[i / 2] = 256; + bottomr[i / 2] = S[0]; + S += 1; + M2[i / 2] = (m + 255) >> 8; + } + else + { + bottomt[i / 2] = 1; + bottomr[i / 2] = 0; + M2[i / 2] = m; + } + } + if (i < len) + M2[i / 2] = M[i]; + Decode (R2, S, M2, (len + 1) / 2); + for (i = 0; i < len - 1; i += 2) + { + uint32_t r = bottomr[i / 2]; + uint32_t r1; + uint16_t r0; + r += bottomt[i / 2] * R2[i / 2]; + uint32_divmod_uint14 (&r1, &r0, r, M[i]); + r1 = uint32_mod_uint14 (r1, M[i + 1]); /* only needed for invalid inputs */ + *out++ = r0; + *out++ = r1; + } + if (i < len) + *out++ = R2[i / 2]; + } +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.h */ + +/* Encode(s,R,M,len) */ +/* assumes 0 <= R[i] < M[i] < 16384 */ + +/* from supercop-20201130/crypto_kem/sntrup761/ref/Encode.c */ + +/* 0 <= R[i] < M[i] < 16384 */ +static void +Encode (unsigned char *out, const uint16_t * R, const uint16_t * M, + long long len) +{ + if (len == 1) + { + uint16_t r = R[0]; + uint16_t m = M[0]; + while (m > 1) + { + *out++ = r; + r >>= 8; + m = (m + 255) >> 8; + } + } + if (len > 1) + { + uint16_t R2[(len + 1) / 2]; + uint16_t M2[(len + 1) / 2]; + long long i; + for (i = 0; i < len - 1; i += 2) + { + uint32_t m0 = M[i]; + uint32_t r = R[i] + R[i + 1] * m0; + uint32_t m = M[i + 1] * m0; + while (m >= 16384) + { + *out++ = r; + r >>= 8; + m = (m + 255) >> 8; + } + R2[i / 2] = r; + M2[i / 2] = m; + } + if (i < len) + { + R2[i / 2] = R[i]; + M2[i / 2] = M[i]; + } + Encode (out, R2, M2, (len + 1) / 2); + } +} + +/* from supercop-20201130/crypto_kem/sntrup761/ref/kem.c */ + +/* ----- masks */ + +/* return -1 if x!=0; else return 0 */ +static int +int16_t_nonzero_mask (int16_t x) +{ + uint16_t u = x; /* 0, else 1...65535 */ + uint32_t v = u; /* 0, else 1...65535 */ + v = -v; /* 0, else 2^32-65535...2^32-1 */ + v >>= 31; /* 0, else 1 */ + return -v; /* 0, else -1 */ +} + +/* return -1 if x<0; otherwise return 0 */ +static int +int16_t_negative_mask (int16_t x) +{ + uint16_t u = x; + u >>= 15; + return -(int) u; + /* alternative with gcc -fwrapv: */ + /* x>>15 compiles to CPU's arithmetic right shift */ +} + +/* ----- arithmetic mod 3 */ + +typedef int8_t small; + +/* F3 is always represented as -1,0,1 */ +/* so ZZ_fromF3 is a no-op */ + +/* x must not be close to top int16_t */ +static small +F3_freeze (int16_t x) +{ + return int32_mod_uint14 (x + 1, 3) - 1; +} + +/* ----- arithmetic mod q */ + +#define q12 ((q-1)/2) +typedef int16_t Fq; +/* always represented as -q12...q12 */ +/* so ZZ_fromFq is a no-op */ + +/* x must not be close to top int32 */ +static Fq +Fq_freeze (int32_t x) +{ + return int32_mod_uint14 (x + q12, q) - q12; +} + +static Fq +Fq_recip (Fq a1) +{ + int i = 1; + Fq ai = a1; + + while (i < q - 2) + { + ai = Fq_freeze (a1 * (int32_t) ai); + i += 1; + } + return ai; +} + +/* ----- small polynomials */ + +/* 0 if Weightw_is(r), else -1 */ +static int +Weightw_mask (small * r) +{ + int weight = 0; + int i; + + for (i = 0; i < p; ++i) + weight += r[i] & 1; + return int16_t_nonzero_mask (weight - w); +} + +/* R3_fromR(R_fromRq(r)) */ +static void +R3_fromRq (small * out, const Fq * r) +{ + int i; + for (i = 0; i < p; ++i) + out[i] = F3_freeze (r[i]); +} + +/* h = f*g in the ring R3 */ +static void +R3_mult (small * h, const small * f, const small * g) +{ + small fg[p + p - 1]; + small result; + int i, j; + + for (i = 0; i < p; ++i) + { + result = 0; + for (j = 0; j <= i; ++j) + result = F3_freeze (result + f[j] * g[i - j]); + fg[i] = result; + } + for (i = p; i < p + p - 1; ++i) + { + result = 0; + for (j = i - p + 1; j < p; ++j) + result = F3_freeze (result + f[j] * g[i - j]); + fg[i] = result; + } + + for (i = p + p - 2; i >= p; --i) + { + fg[i - p] = F3_freeze (fg[i - p] + fg[i]); + fg[i - p + 1] = F3_freeze (fg[i - p + 1] + fg[i]); + } + + for (i = 0; i < p; ++i) + h[i] = fg[i]; +} + +/* returns 0 if recip succeeded; else -1 */ +static int +R3_recip (small * out, const small * in) +{ + small f[p + 1], g[p + 1], v[p + 1], r[p + 1]; + int i, loop, delta; + int sign, swap, t; + + for (i = 0; i < p + 1; ++i) + v[i] = 0; + for (i = 0; i < p + 1; ++i) + r[i] = 0; + r[0] = 1; + for (i = 0; i < p; ++i) + f[i] = 0; + f[0] = 1; + f[p - 1] = f[p] = -1; + for (i = 0; i < p; ++i) + g[p - 1 - i] = in[i]; + g[p] = 0; + + delta = 1; + + for (loop = 0; loop < 2 * p - 1; ++loop) + { + for (i = p; i > 0; --i) + v[i] = v[i - 1]; + v[0] = 0; + + sign = -g[0] * f[0]; + swap = int16_t_negative_mask (-delta) & int16_t_nonzero_mask (g[0]); + delta ^= swap & (delta ^ -delta); + delta += 1; + + for (i = 0; i < p + 1; ++i) + { + t = swap & (f[i] ^ g[i]); + f[i] ^= t; + g[i] ^= t; + t = swap & (v[i] ^ r[i]); + v[i] ^= t; + r[i] ^= t; + } + + for (i = 0; i < p + 1; ++i) + g[i] = F3_freeze (g[i] + sign * f[i]); + for (i = 0; i < p + 1; ++i) + r[i] = F3_freeze (r[i] + sign * v[i]); + + for (i = 0; i < p; ++i) + g[i] = g[i + 1]; + g[p] = 0; + } + + sign = f[0]; + for (i = 0; i < p; ++i) + out[i] = sign * v[p - 1 - i]; + + return int16_t_nonzero_mask (delta); +} + +/* ----- polynomials mod q */ + +/* h = f*g in the ring Rq */ +static void +Rq_mult_small (Fq * h, const Fq * f, const small * g) +{ + Fq fg[p + p - 1]; + Fq result; + int i, j; + + for (i = 0; i < p; ++i) + { + result = 0; + for (j = 0; j <= i; ++j) + result = Fq_freeze (result + f[j] * (int32_t) g[i - j]); + fg[i] = result; + } + for (i = p; i < p + p - 1; ++i) + { + result = 0; + for (j = i - p + 1; j < p; ++j) + result = Fq_freeze (result + f[j] * (int32_t) g[i - j]); + fg[i] = result; + } + + for (i = p + p - 2; i >= p; --i) + { + fg[i - p] = Fq_freeze (fg[i - p] + fg[i]); + fg[i - p + 1] = Fq_freeze (fg[i - p + 1] + fg[i]); + } + + for (i = 0; i < p; ++i) + h[i] = fg[i]; +} + +/* h = 3f in Rq */ +static void +Rq_mult3 (Fq * h, const Fq * f) +{ + int i; + + for (i = 0; i < p; ++i) + h[i] = Fq_freeze (3 * f[i]); +} + +/* out = 1/(3*in) in Rq */ +/* returns 0 if recip succeeded; else -1 */ +static int +Rq_recip3 (Fq * out, const small * in) +{ + Fq f[p + 1], g[p + 1], v[p + 1], r[p + 1]; + int i, loop, delta; + int swap, t; + int32_t f0, g0; + Fq scale; + + for (i = 0; i < p + 1; ++i) + v[i] = 0; + for (i = 0; i < p + 1; ++i) + r[i] = 0; + r[0] = Fq_recip (3); + for (i = 0; i < p; ++i) + f[i] = 0; + f[0] = 1; + f[p - 1] = f[p] = -1; + for (i = 0; i < p; ++i) + g[p - 1 - i] = in[i]; + g[p] = 0; + + delta = 1; + + for (loop = 0; loop < 2 * p - 1; ++loop) + { + for (i = p; i > 0; --i) + v[i] = v[i - 1]; + v[0] = 0; + + swap = int16_t_negative_mask (-delta) & int16_t_nonzero_mask (g[0]); + delta ^= swap & (delta ^ -delta); + delta += 1; + + for (i = 0; i < p + 1; ++i) + { + t = swap & (f[i] ^ g[i]); + f[i] ^= t; + g[i] ^= t; + t = swap & (v[i] ^ r[i]); + v[i] ^= t; + r[i] ^= t; + } + + f0 = f[0]; + g0 = g[0]; + for (i = 0; i < p + 1; ++i) + g[i] = Fq_freeze (f0 * g[i] - g0 * f[i]); + for (i = 0; i < p + 1; ++i) + r[i] = Fq_freeze (f0 * r[i] - g0 * v[i]); + + for (i = 0; i < p; ++i) + g[i] = g[i + 1]; + g[p] = 0; + } + + scale = Fq_recip (f[0]); + for (i = 0; i < p; ++i) + out[i] = Fq_freeze (scale * (int32_t) v[p - 1 - i]); + + return int16_t_nonzero_mask (delta); +} + +/* ----- rounded polynomials mod q */ + +static void +Round (Fq * out, const Fq * a) +{ + int i; + for (i = 0; i < p; ++i) + out[i] = a[i] - F3_freeze (a[i]); +} + +/* ----- sorting to generate short polynomial */ + +static void +Short_fromlist (small * out, const uint32_t * in) +{ + uint32_t L[p]; + int i; + + for (i = 0; i < w; ++i) + L[i] = in[i] & (uint32_t) - 2; + for (i = w; i < p; ++i) + L[i] = (in[i] & (uint32_t) - 3) | 1; + crypto_sort_uint32 (L, p); + for (i = 0; i < p; ++i) + out[i] = (L[i] & 3) - 1; +} + +/* ----- underlying hash function */ + +#define Hash_bytes 32 + +/* e.g., b = 0 means out = Hash0(in) */ +static void +Hash_prefix (unsigned char *out, int b, const unsigned char *in, int inlen) +{ + unsigned char x[inlen + 1]; + unsigned char h[64]; + int i; + + x[0] = b; + for (i = 0; i < inlen; ++i) + x[i + 1] = in[i]; + crypto_hash_sha512 (h, x, inlen + 1); + for (i = 0; i < 32; ++i) + out[i] = h[i]; +} + +/* ----- higher-level randomness */ + +static uint32_t +urandom32 (void *random_ctx, nettle_random_func * random) +{ + unsigned char c[4]; + uint32_t out[4]; + + random (random_ctx, 4, c); + out[0] = (uint32_t) c[0]; + out[1] = ((uint32_t) c[1]) << 8; + out[2] = ((uint32_t) c[2]) << 16; + out[3] = ((uint32_t) c[3]) << 24; + return out[0] + out[1] + out[2] + out[3]; +} + +static void +Short_random (small * out, void *random_ctx, nettle_random_func * random) +{ + uint32_t L[p]; + int i; + + for (i = 0; i < p; ++i) + L[i] = urandom32 (random_ctx, random); + Short_fromlist (out, L); +} + +static void +Small_random (small * out, void *random_ctx, nettle_random_func * random) +{ + int i; + + for (i = 0; i < p; ++i) + out[i] = (((urandom32 (random_ctx, random) & 0x3fffffff) * 3) >> 30) - 1; +} + +/* ----- Streamlined NTRU Prime Core */ + +/* h,(f,ginv) = KeyGen() */ +static void +KeyGen (Fq * h, small * f, small * ginv, void *random_ctx, + nettle_random_func * random) +{ + small g[p]; + Fq finv[p]; + + for (;;) + { + Small_random (g, random_ctx, random); + if (R3_recip (ginv, g) == 0) + break; + } + Short_random (f, random_ctx, random); + Rq_recip3 (finv, f); /* always works */ + Rq_mult_small (h, finv, g); +} + +/* c = Encrypt(r,h) */ +static void +Encrypt (Fq * c, const small * r, const Fq * h) +{ + Fq hr[p]; + + Rq_mult_small (hr, h, r); + Round (c, hr); +} + +/* r = Decrypt(c,(f,ginv)) */ +static void +Decrypt (small * r, const Fq * c, const small * f, const small * ginv) +{ + Fq cf[p]; + Fq cf3[p]; + small e[p]; + small ev[p]; + int mask; + int i; + + Rq_mult_small (cf, c, f); + Rq_mult3 (cf3, cf); + R3_fromRq (e, cf3); + R3_mult (ev, e, ginv); + + mask = Weightw_mask (ev); /* 0 if weight w, else -1 */ + for (i = 0; i < w; ++i) + r[i] = ((ev[i] ^ 1) & ~mask) ^ 1; + for (i = w; i < p; ++i) + r[i] = ev[i] & ~mask; +} + +/* ----- encoding small polynomials (including short polynomials) */ + +#define Small_bytes ((p+3)/4) + +/* these are the only functions that rely on p mod 4 = 1 */ + +static void +Small_encode (unsigned char *s, const small * f) +{ + small x; + int i; + + for (i = 0; i < p / 4; ++i) + { + x = *f++ + 1; + x += (*f++ + 1) << 2; + x += (*f++ + 1) << 4; + x += (*f++ + 1) << 6; + *s++ = x; + } + x = *f++ + 1; + *s++ = x; +} + +static void +Small_decode (small * f, const unsigned char *s) +{ + unsigned char x; + int i; + + for (i = 0; i < p / 4; ++i) + { + x = *s++; + *f++ = ((small) (x & 3)) - 1; + x >>= 2; + *f++ = ((small) (x & 3)) - 1; + x >>= 2; + *f++ = ((small) (x & 3)) - 1; + x >>= 2; + *f++ = ((small) (x & 3)) - 1; + } + x = *s++; + *f++ = ((small) (x & 3)) - 1; +} + +/* ----- encoding general polynomials */ + +static void +Rq_encode (unsigned char *s, const Fq * r) +{ + uint16_t R[p], M[p]; + int i; + + for (i = 0; i < p; ++i) + R[i] = r[i] + q12; + for (i = 0; i < p; ++i) + M[i] = q; + Encode (s, R, M, p); +} + +static void +Rq_decode (Fq * r, const unsigned char *s) +{ + uint16_t R[p], M[p]; + int i; + + for (i = 0; i < p; ++i) + M[i] = q; + Decode (R, s, M, p); + for (i = 0; i < p; ++i) + r[i] = ((Fq) R[i]) - q12; +} + +/* ----- encoding rounded polynomials */ + +static void +Rounded_encode (unsigned char *s, const Fq * r) +{ + uint16_t R[p], M[p]; + int i; + + for (i = 0; i < p; ++i) + R[i] = ((r[i] + q12) * 10923) >> 15; + for (i = 0; i < p; ++i) + M[i] = (q + 2) / 3; + Encode (s, R, M, p); +} + +static void +Rounded_decode (Fq * r, const unsigned char *s) +{ + uint16_t R[p], M[p]; + int i; + + for (i = 0; i < p; ++i) + M[i] = (q + 2) / 3; + Decode (R, s, M, p); + for (i = 0; i < p; ++i) + r[i] = R[i] * 3 - q12; +} + +/* ----- Streamlined NTRU Prime Core plus encoding */ + +typedef small Inputs[p]; /* passed by reference */ +#define Inputs_random Short_random +#define Inputs_encode Small_encode +#define Inputs_bytes Small_bytes + +#define Ciphertexts_bytes Rounded_bytes +#define SecretKeys_bytes (2*Small_bytes) +#define PublicKeys_bytes Rq_bytes + +/* pk,sk = ZKeyGen() */ +static void +ZKeyGen (unsigned char *pk, unsigned char *sk, void *random_ctx, + nettle_random_func * random) +{ + Fq h[p]; + small f[p], v[p]; + + KeyGen (h, f, v, random_ctx, random); + Rq_encode (pk, h); + Small_encode (sk, f); + sk += Small_bytes; + Small_encode (sk, v); +} + +/* C = ZEncrypt(r,pk) */ +static void +ZEncrypt (unsigned char *C, const Inputs r, const unsigned char *pk) +{ + Fq h[p]; + Fq c[p]; + Rq_decode (h, pk); + Encrypt (c, r, h); + Rounded_encode (C, c); +} + +/* r = ZDecrypt(C,sk) */ +static void +ZDecrypt (Inputs r, const unsigned char *C, const unsigned char *sk) +{ + small f[p], v[p]; + Fq c[p]; + + Small_decode (f, sk); + sk += Small_bytes; + Small_decode (v, sk); + Rounded_decode (c, C); + Decrypt (r, c, f, v); +} + +/* ----- confirmation hash */ + +#define Confirm_bytes 32 + +/* h = HashConfirm(r,pk,cache); cache is Hash4(pk) */ +static void +HashConfirm (unsigned char *h, const unsigned char *r, + /* const unsigned char *pk, */ const unsigned char *cache) +{ + unsigned char x[Hash_bytes * 2]; + int i; + + Hash_prefix (x, 3, r, Inputs_bytes); + for (i = 0; i < Hash_bytes; ++i) + x[Hash_bytes + i] = cache[i]; + Hash_prefix (h, 2, x, sizeof x); +} + +/* ----- session-key hash */ + +/* k = HashSession(b,y,z) */ +static void +HashSession (unsigned char *k, int b, const unsigned char *y, + const unsigned char *z) +{ + unsigned char x[Hash_bytes + Ciphertexts_bytes + Confirm_bytes]; + int i; + + Hash_prefix (x, 3, y, Inputs_bytes); + for (i = 0; i < Ciphertexts_bytes + Confirm_bytes; ++i) + x[Hash_bytes + i] = z[i]; + Hash_prefix (k, b, x, sizeof x); +} + +/* ----- Streamlined NTRU Prime */ + +/* pk,sk = KEM_KeyGen() */ +void +sntrup761_keypair (unsigned char *pk, unsigned char *sk, void *random_ctx, + nettle_random_func * random) +{ + int i; + + ZKeyGen (pk, sk, random_ctx, random); + sk += SecretKeys_bytes; + for (i = 0; i < PublicKeys_bytes; ++i) + *sk++ = pk[i]; + random (random_ctx, Inputs_bytes, sk); + sk += Inputs_bytes; + Hash_prefix (sk, 4, pk, PublicKeys_bytes); +} + +/* c,r_enc = Hide(r,pk,cache); cache is Hash4(pk) */ +static void +Hide (unsigned char *c, unsigned char *r_enc, const Inputs r, + const unsigned char *pk, const unsigned char *cache) +{ + Inputs_encode (r_enc, r); + ZEncrypt (c, r, pk); + c += Ciphertexts_bytes; + HashConfirm (c, r_enc, cache); +} + +/* c,k = Encap(pk) */ +void +sntrup761_enc (unsigned char *c, unsigned char *k, const unsigned char *pk, + void *random_ctx, nettle_random_func * random) +{ + Inputs r; + unsigned char r_enc[Inputs_bytes]; + unsigned char cache[Hash_bytes]; + + Hash_prefix (cache, 4, pk, PublicKeys_bytes); + Inputs_random (r, random_ctx, random); + Hide (c, r_enc, r, pk, cache); + HashSession (k, 1, r_enc, c); +} + +/* 0 if matching ciphertext+confirm, else -1 */ +static int +Ciphertexts_diff_mask (const unsigned char *c, const unsigned char *c2) +{ + uint16_t differentbits = 0; + int len = Ciphertexts_bytes + Confirm_bytes; + + while (len-- > 0) + differentbits |= (*c++) ^ (*c2++); + return (1 & ((differentbits - 1) >> 8)) - 1; +} + +/* k = Decap(c,sk) */ +void +sntrup761_dec (unsigned char *k, const unsigned char *c, const unsigned char *sk) +{ + const unsigned char *pk = sk + SecretKeys_bytes; + const unsigned char *rho = pk + PublicKeys_bytes; + const unsigned char *cache = rho + Inputs_bytes; + Inputs r; + unsigned char r_enc[Inputs_bytes]; + unsigned char cnew[Ciphertexts_bytes + Confirm_bytes]; + int mask; + int i; + + ZDecrypt (r, c, sk); + Hide (cnew, r_enc, r, pk, cache); + mask = Ciphertexts_diff_mask (c, cnew); + for (i = 0; i < Inputs_bytes; ++i) + r_enc[i] ^= mask & (r_enc[i] ^ rho[i]); + HashSession (k, 1 + mask, r_enc, c); +} diff --git a/sntrup761.h b/sntrup761.h new file mode 100644 index 00000000..49d49f46 --- /dev/null +++ b/sntrup761.h @@ -0,0 +1,75 @@ +/* sntrup761.h + + Copyright (C) 2023 Simon Josefsson + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * 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. + + or both in parallel, as here. + + GNU Nettle 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. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +/* + * Derived from public domain source, written by (in alphabetical order): + * - Daniel J. Bernstein + * - Chitchanok Chuengsatiansup + * - Tanja Lange + * - Christine van Vredendaal + */ + +#ifndef NETTLE_SNTRUP761_H +#define NETTLE_SNTRUP761_H + +#include "nettle-types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* Name mangling */ +#define sntrup761_keypair nettle_sntrup761_keypair +#define sntrup761_enc nettle_sntrup761_enc +#define sntrup761_dec nettle_sntrup761_dec + +#define SNTRUP761_SECRETKEY_SIZE 1763 +#define SNTRUP761_PUBLICKEY_SIZE 1158 +#define SNTRUP761_CIPHERTEXT_SIZE 1039 +#define SNTRUP761_SIZE 32 + +void +sntrup761_keypair (uint8_t *pk, uint8_t *sk, void *random_ctx, + nettle_random_func *random); + +void +sntrup761_enc (uint8_t *c, uint8_t *k, const uint8_t *pk, + void *random_ctx, nettle_random_func *random); + +void +sntrup761_dec (uint8_t *k, const uint8_t *c, const uint8_t *sk); + +#ifdef __cplusplus +} +#endif + +#endif /* NETTLE_SNTRUP761_H */ diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 20aaad38..51f75c57 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -115,6 +115,7 @@ /shake256-test /x86-ibt-test /drbg-ctr-aes256-test +/sntrup761-test /test.in /test1.out diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in index b2f0518c..3281862b 100644 --- a/testsuite/Makefile.in +++ b/testsuite/Makefile.in @@ -36,7 +36,7 @@ TS_NETTLE_SOURCES = aes-test.c aes-keywrap-test.c arcfour-test.c arctwo-test.c \ meta-aead-test.c meta-mac-test.c \ buffer-test.c yarrow-test.c xts-test.c pbkdf2-test.c \ x86-ibt-test.c drbg-ctr-aes256-test.c \ - slh-dsa-test.c + slh-dsa-test.c sntrup761-test.c TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \ rsa2sexp-test.c sexp2rsa-test.c \ diff --git a/testsuite/sntrup761-test.c b/testsuite/sntrup761-test.c new file mode 100644 index 00000000..4f9545f3 --- /dev/null +++ b/testsuite/sntrup761-test.c @@ -0,0 +1,444 @@ +/* sntrup761-test.c + + Copyright (C) 2023 Simon Josefsson + + This file is part of GNU Nettle. + + GNU Nettle is free software: you can redistribute it and/or + modify it under the terms of either: + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at your + option) any later version. + + or + + * 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. + + or both in parallel, as here. + + GNU Nettle 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. + + You should have received copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see http://www.gnu.org/licenses/. +*/ + +#include "testutils.h" + +#include "sntrup761.h" + +#include "drbg-ctr.h" + +static void +test_sntrup (struct drbg_ctr_aes256_ctx *rngctx, + nettle_random_func * rngfun, + const uint8_t * xpk, const uint8_t * xsk, + const uint8_t * xct, const uint8_t * xk) +{ + uint8_t pk[SNTRUP761_PUBLICKEY_SIZE]; + uint8_t sk[SNTRUP761_SECRETKEY_SIZE]; + uint8_t ct[SNTRUP761_CIPHERTEXT_SIZE]; + uint8_t k1[SNTRUP761_SIZE]; + uint8_t k2[SNTRUP761_SIZE]; + + sntrup761_keypair (pk, sk, rngctx, rngfun); + + if (!MEMEQ (SNTRUP761_PUBLICKEY_SIZE, pk, xpk) + || !MEMEQ (SNTRUP761_SECRETKEY_SIZE, sk, xsk)) + { + printf ("\nnstrup761_keypair:\npk = "); + print_hex (sizeof pk, pk); + printf ("\nsk = "); + print_hex (sizeof sk, sk); + abort (); + } + + sntrup761_enc (ct, k1, pk, rngctx, rngfun); + + if (!MEMEQ (SNTRUP761_CIPHERTEXT_SIZE, ct, xct) + || !MEMEQ (SNTRUP761_SIZE, k1, xk)) + { + printf ("\nnstrup761_enc:\nct = "); + print_hex (sizeof ct, ct); + printf ("\nk1 = "); + print_hex (sizeof k1, k1); + abort (); + } + + sntrup761_dec (k2, ct, sk); + + if (!MEMEQ (SNTRUP761_SIZE, k2, xk)) + { + printf ("\nnstrup761_dec:\nk2 = "); + print_hex (sizeof k2, k2); + abort (); + } + + if (!MEMEQ (SNTRUP761_SIZE, k1, k2)) + { + printf ("\nsntrup761 k1 != k2\n"); + abort (); + } +} + +void +test_main (void) +{ + struct drbg_ctr_aes256_ctx rng; + + /* https://ntruprime.cr.yp.to/nist/ntruprime-20201007/KAT/kem/sntrup761/kat_kem.rsp.html */ + + drbg_ctr_aes256_init (&rng, + H ("061550234D158C5EC95595FE04EF7A25767F2E24CC2BC479" + "D09D86DC9ABCFDE7056A8C266F9EF97ED08541DBD2E1FFA1")); + test_sntrup (&rng, (nettle_random_func *) drbg_ctr_aes256_random, + H ("36C969CF1008A6AA9551A784941C65A9BF68C2DC33FA36B5" + "D266B25171B346679F2D22BF3123A79C790D6DEC68E1BC44" + "420A6824F5357C78E3C336FEE0551E620DCB975F563682A3" + "12A3353B521C727F57CABED0C3228F09317CAE8B58158EBF" + "5B26BDC6E6365AA601ACAD2ABD37F5830D0BBFE355705C0A" + "62B76A5C910AD04E55E5DAD749C7393D2E2E8AB643E62E47" + "57AD2201CAA33203F53B4A9D4757E7274D72BDB036A31D7D" + "E11E5D1C66CF3059F33B6A2972C1E1D9C9FB2AEBC78B2C05" + "5D48D79C3A7C996C08B7DEF0791CDE895053885D8DA1D254" + "EE19C090AF34F4720B0B77139108D8498982FEAB0B54934C" + "EE3DCD24B049F981A84C928028A64A26CDF87052313C3E50" + "B2E1F539394502433C0962996C3599189B15174281B6595B" + "567B8C4CD80902860E613AE1906A55607CBF0E11AD6C0C0D" + "F38C006A5F535FA6E6FB49D10B78B9CB6473BF0630518DB6" + "FDECFD70DED201C7E35FFB3BB78D8AEC181F6DE960C316FE" + "354B7CC69E8048201965AAFEF4EA3F808737FF45255A1779" + "DE57A4B68DB587263D7B7F6CB07D8B01224DD291237EFD9C" + "01676E30154A2A7D60174536580FE64EFEDDA5FB42C13ED8" + "C5768A3CBCAE7A2343B3128CD5C1C663A07C7DC0E1E2642C" + "0D9A02F349C964154A6C4308D8ECF30F47E9A81EED2A32A2" + "BB44DFC36A28A66AE77BB139FA416B6327EEFE33632469CC" + "C21229587573C4F7752CE1CC79CA0C6BDA08CD79E25720D2" + "D9092EA2AB13F31E9A3AF1C69FC6379D8E2AD2B87B514C81" + "7A087338B7B0736B8954DE9223225B40079C92601248C14B" + "2104901E74F849D9EEE9F5636C1DAD6031AB477C573197E7" + "EB6CE535D9F0F69183DD9DF5521595E5C9E98D846CE08AA6" + "55B70CC0D8041401929690298F645D9112DBB03B189CDB1F" + "CF4D512F6874B409BF55EE1CC284A05B698B8818F043C259" + "1C9F4ABA29CF4259915D6A0BE71B6B93963C618CBB567838" + "E5EADE6500DE9AD250083A01EB3EB44C00EECB2B0F874CDA" + "165FAA6524CA13D435C938DB9469292FE97283C69222107E" + "A2F9EFCA1B6D41DCA5B149B2A8CC2244A1BC54261CC11742" + "ACD27B7F2352C33FB83FE143386479D78D6D5C3E51684B60" + "A56714182449C94327139B0289B9BDE0AE3FEF319FE2C605" + "AB5507C894D2C2761A3BD3EA30F4BA928F9F23303061617E" + "2F042DCF229AFF2C9345A6B3CDCF90D3E3BCC3A1110C8561" + "6BD585C31CDE3E69ADC12A18BFA5797DF0543435A7C874A8" + "ACF3786FCCBA4A6CEAA65E5666230AA7206AE78EB1B98CB5" + "236508E6357E18CCCFAEC5693532BE4EE38022C48FE94F62" + "B0293A088BF4D737F48748F23BCB338B58B4D666AD3C64E9" + "ECD07265F971B07AF716D4A5B719C3F5FE35744734CBA543" + "0381661E372B6F6510D61B11E4697A1A961589949DBA53B5" + "BC5BDB76FA09324387D799536506182EFF7078034B34E1DD" + "D2612B0A40E7F1A294FBA869DA2E46C4C36BB08C7E9BEF09" + "A94459E8FC2D3CC579D15284DF1F19EF77E03041511ACC39" + "BF9CA8AC8DE6A0E5EEA0BBD4289B6DAE38E9E82EB50A0397" + "B3EE6C52FBDC7DEEA2C376825E89016C859B09488548BF76" + "CA62D696DF94A61E8F0E13C69EE816CE5AA2768987B0A782" + "D74C673EC005"), + H ("55565515155545556569159955A255545545616145059455" + "6556915055895615548852955456550098544995555AA546" + "5400A5555558956510A6515596559665996A449154154144" + "655655555511056241569549446269405555551656659555" + "55A515915559565915656515424040891954545669558590" + "64258656285054569505A6A9569494466614155801155650" + "55485955259049A5545525455504526A195455554185525A" + "899625525556582484644514556589656258515459150185" + "08154A51A0448959112A286212608A52911A949119A28956" + "64165900A861541A200A52104029544600425A5A1198101A" + "1A50A094A551425A484959A1506486A618555A8990561502" + "9622A2A46696A2A6595A46682622525050489A8040562808" + "168156854185026540A1059A94AAA291811948A259816991" + "110951802409AA5A2A06290092451446655608404096898A" + "A56220562285150891914066110A0905A841044865042A26" + "88AA12441AAA46064669155555A2109659299922820036C9" + "69CF1008A6AA9551A784941C65A9BF68C2DC33FA36B5D266" + "B25171B346679F2D22BF3123A79C790D6DEC68E1BC44420A" + "6824F5357C78E3C336FEE0551E620DCB975F563682A312A3" + "353B521C727F57CABED0C3228F09317CAE8B58158EBF5B26" + "BDC6E6365AA601ACAD2ABD37F5830D0BBFE355705C0A62B7" + "6A5C910AD04E55E5DAD749C7393D2E2E8AB643E62E4757AD" + "2201CAA33203F53B4A9D4757E7274D72BDB036A31D7DE11E" + "5D1C66CF3059F33B6A2972C1E1D9C9FB2AEBC78B2C055D48" + "D79C3A7C996C08B7DEF0791CDE895053885D8DA1D254EE19" + "C090AF34F4720B0B77139108D8498982FEAB0B54934CEE3D" + "CD24B049F981A84C928028A64A26CDF87052313C3E50B2E1" + "F539394502433C0962996C3599189B15174281B6595B567B" + "8C4CD80902860E613AE1906A55607CBF0E11AD6C0C0DF38C" + "006A5F535FA6E6FB49D10B78B9CB6473BF0630518DB6FDEC" + "FD70DED201C7E35FFB3BB78D8AEC181F6DE960C316FE354B" + "7CC69E8048201965AAFEF4EA3F808737FF45255A1779DE57" + "A4B68DB587263D7B7F6CB07D8B01224DD291237EFD9C0167" + "6E30154A2A7D60174536580FE64EFEDDA5FB42C13ED8C576" + "8A3CBCAE7A2343B3128CD5C1C663A07C7DC0E1E2642C0D9A" + "02F349C964154A6C4308D8ECF30F47E9A81EED2A32A2BB44" + "DFC36A28A66AE77BB139FA416B6327EEFE33632469CCC212" + "29587573C4F7752CE1CC79CA0C6BDA08CD79E25720D2D909" + "2EA2AB13F31E9A3AF1C69FC6379D8E2AD2B87B514C817A08" + "7338B7B0736B8954DE9223225B40079C92601248C14B2104" + "901E74F849D9EEE9F5636C1DAD6031AB477C573197E7EB6C" + "E535D9F0F69183DD9DF5521595E5C9E98D846CE08AA655B7" + "0CC0D8041401929690298F645D9112DBB03B189CDB1FCF4D" + "512F6874B409BF55EE1CC284A05B698B8818F043C2591C9F" + "4ABA29CF4259915D6A0BE71B6B93963C618CBB567838E5EA" + "DE6500DE9AD250083A01EB3EB44C00EECB2B0F874CDA165F" + "AA6524CA13D435C938DB9469292FE97283C69222107EA2F9" + "EFCA1B6D41DCA5B149B2A8CC2244A1BC54261CC11742ACD2" + "7B7F2352C33FB83FE143386479D78D6D5C3E51684B60A567" + "14182449C94327139B0289B9BDE0AE3FEF319FE2C605AB55" + "07C894D2C2761A3BD3EA30F4BA928F9F23303061617E2F04" + "2DCF229AFF2C9345A6B3CDCF90D3E3BCC3A1110C85616BD5" + "85C31CDE3E69ADC12A18BFA5797DF0543435A7C874A8ACF3" + "786FCCBA4A6CEAA65E5666230AA7206AE78EB1B98CB52365" + "08E6357E18CCCFAEC5693532BE4EE38022C48FE94F62B029" + "3A088BF4D737F48748F23BCB338B58B4D666AD3C64E9ECD0" + "7265F971B07AF716D4A5B719C3F5FE35744734CBA5430381" + "661E372B6F6510D61B11E4697A1A961589949DBA53B5BC5B" + "DB76FA09324387D799536506182EFF7078034B34E1DDD261" + "2B0A40E7F1A294FBA869DA2E46C4C36BB08C7E9BEF09A944" + "59E8FC2D3CC579D15284DF1F19EF77E03041511ACC39BF9C" + "A8AC8DE6A0E5EEA0BBD4289B6DAE38E9E82EB50A0397B3EE" + "6C52FBDC7DEEA2C376825E89016C859B09488548BF76CA62" + "D696DF94A61E8F0E13C69EE816CE5AA2768987B0A782D74C" + "673EC0059FA532AE97F8BDF90F90130926654FB8B469D772" + "049D72A8375CD8459D06CC1B90633EB3A899685D21491B50" + "62A9FC73FB6E878D7A73198EFA0B569D9CE665CE126FFDC9" + "862EB00D11F457A7995555F7C92011C24E1CEC45C270FB5F" + "121F08177F97FC3F631C0EF86A92E99D557FB69A0F6FCD8B" + "1C0EF94AA7429B3A8A11614D847202D3D04A98313FC0D63A" + "BF9FD75CA321C879458BF8837B7E74CCF5179C7714FA9800" + "D1821EE3F9639D28136B7910872631F85AE7B6DD289E0103" + "4217210859D4E53C65487CE38AFF621DA76BA1C4E2E77ED5" + "380B47B8D983CCB5BB793E"), + H ("84F327D38929039EF84366AB796A96E6CC268454D5AD8D05" + "410D3E969B6D228B6CED2CBAD7BAB3B4B7EE453747D3331D" + "43B21CD2ECC3BF557D696E81773EE69F687FE1F61E63742A" + "F913A35418575467118409D4FFDBBAC5CA062DFF3F04D761" + "54D17EC34212DEBFCA967A91E461F73786D949D6A9765140" + "B9DC7849639A487058F45DDA919576090D35E783804BA7B8" + "B33B5C6A8C1EBB7C39F042696CF9F2B624D26EA5D6D10148" + "9E242CC35126B573928B6B8BF9945269AD22E7DA70CCB7DC" + "374F75641978D5F6D5F540A1169EB098570A7CFD65C9257C" + "4C196F42C6DA4F4466D8F11A17C6A75A9BDD45B5AC77A836" + "7B005ED22141A81B995A19E4DC9E6743B4B45E0329E7A00D" + "3FF90C7A917CDC9CA75A34FFFDD9A321751B5C8B2AB9E1EA" + "037CF45C04B412A97F52E7C6D66508456D9117961257B4F5" + "0BB9F500DE99B6F061C377D44F495D711AB2ED3E88CCF14D" + "F10F8C60BD00E29CD83AD160FAEF2984FAC7E897CBB8CDA1" + "44D50E4C1AD20238A2617598DA6EFE786AA82E0931B0B5D1" + "A7FA024B856353AFAEDB0A1150A42DA182353CE5A00403BB" + "6B7A13EFFC14B0FD97E1117302ED8A66FAAED88B43B34CFC" + "73CB33E49A4C34D0BFDEE2FEADC2B4C8BB1EC41215586FC6" + "6550D496373305B99CEE254EAC71D3CDAC689A777062ACAE" + "65B031B5A1A973835BE6A4BB061F178531C45DE3B33E7763" + "B483621821E037FE5EF48FD971D8D2BEFDA63250E9B1181D" + "8B8086BED9CDA8CDE6644CDE8EBF7C1F1038AFE798A2A4C4" + "92B603B7F4F8805D0FDF19D8274888CEBEC3043CC9ACF024" + "BD30D8B0D28D311985930110386598775CF84E0848B11E09" + "0905A65F56142FC17D2573536FC51E7D5B2E0FF7B0947115" + "5008561156FBAEC215031ED0D844EB14D6C609173355FFF8" + "AE22C6E5BCCD19B2832E5FBE625C2C0E516E1369D1FCF49A" + "5FDBAF8CF572F04317DB8ED70EE1605B96D077B4F054C72B" + "139F5BCAA5BB627E39BE5BCC97AF922C5E70835BD918281B" + "95E557FC86A43C75980A0D9F0F9162F230014CD867DD07DB" + "23260934546C04499D6B8627B8D5DEC73FA45327F8498352" + "9BAF3AA10E885724FE76055099D136CCAACC159B4CE38784" + "404CC9B04723910F990AF77C64D42A29D784FC897955758F" + "1D2A12BB7C6F6A8E5B94EFA740F662CF0DA2D099C61EE1CC" + "6B661A64F0887B805AF53C7B64C4456DAF228582C1B2212A" + "8F718E56DF6B72D7EFA0C5D26582CE96AEFCE13CB2830C3F" + "B32E5115AACC20D3A335F7A4C12E0CD1DE532D8D9D42D69B" + "C2D0BE0AC7DF3B8F416B9A53DB261C47272725A8A8829867" + "8351B42103219092076B6ECE744D993388A8F2C475079CB8" + "BC4DC492A4797147C01EA3508225826F7A3D32BF502B0F45" + "52F36FC9F6FB91E82DB1949338B45436EC0FF63B53F900F2" + "7F8147D420F93D33C83794980E94143FD361F944DDB56D31" + "14EE974C96A155"), + H ("344CA5E25F6DA5EA95E4A695B1C5446ECA9859334532E4A9" + "537669F012C743A2")); + + drbg_ctr_aes256_init (&rng, + H ("D81C4D8D734FCBFBEADE3D3F8A039FAA2A2C9957E835AD55" + "B22E75BF57BB556AC81ADDE6AEEB4A5A875C3BFCADFA958F")); + test_sntrup (&rng, (nettle_random_func *) drbg_ctr_aes256_random, + H ("D2530F125EE5F208B1976A66BCBC917161F6929E636BA8C7" + "3470DE18065F6057528D718744E9248DFFF6BB55C188CEAC" + "B9419863C3C456B46A21354834ADA6B2132C67747C9EE70D" + "02560268EE650E56C84BCE6A6700C5E612999110E53A866A" + "E6B4F778230367B8B886C4FEC089C6267F91C7F24D6CE53C" + "754D9CCCDD25756D76CD211D5954F0E8A11343679C1F692C" + "E5C0D0E42A02381144E1E0201B6F49F00628A86E09918488" + "BC3E1E1071561700544C2CE50F4B7BAE4757CA7A0DD0A221" + "260E0574D1F8F81AF072FCBA8061B5B8BB450FDCC6732D35" + "CDBBBC4EF1798EA7E263BCF369059EED3A86E2C61C72CBFC" + "D69521C3A1FD4868AF5638148043162B8B6E39F82B56D6C9" + "C7724807F623C06CC08FF619F7961EC972B1BD2856F87D5E" + "6940DC15B9575264A4AB0CA229C5B02C9AA5BB8DA2BD8EB0" + "9A7A5E824C2D666A17C4845CA9530F3A5E45BE5A380B83C8" + "1B3965180C706E2CC9ABF4DC8A1559CCF176EFD0FAAD1B8E" + "184AAA08E24CA6F5D070E040D64CD65A1628E99F3BACAB5A" + "7206B5C7D1F7D282651448E259A839E128774530C931C4E4" + "E6F60AB9CDEB645AA24012C3A0983750C04914C59E34AF67" + "B9128CE906AD162D70E582C42E21898EF8023A9D1BC3B5F5" + "BDE6415CD168F1DE726A2ECB27C48A73356FBBEE8F405A6F" + "8C34F8F5A864C109045618B03FBFDCBAFD8BC93465863407" + "0D40E5C62A03F9B544C325BCC56D8C70D67DA39879356E98" + "71B016A0CCF3FE1C6AB941B69417FF514B616C9CFE9EA066" + "FBB4B081B25D584E40430B0950A7EBFBFA9B4E4EE003F297" + "BA668F7139F26F218026DC9BFDBBBE6FD1CDE03CAC981429" + "9126E8CBDAFFD54101E07C09B65B88C9743B85C464E44C72" + "56F506F07BC7D3877E2578D589CD2001E5124C9E647FAC21" + "34B34E74DC188478E538BBFB750B47600191C51B71F18460" + "CECD5FBDABAA48D6DD6DBE7E26CEF9498220379F1FF25AFA" + "CA60CEFFA408CEB677E4CAFB3A43B3E5FAA5B731EA608A94" + "5EDF645136ADC77B07DB34E191D9E786ED7CFD97E2330548" + "FFE021997E2E8B774E4A5F1666A91F05D471874E765DF42C" + "7C3D9EF37CD946E0D69C9EA83CEC9B1AA41A25F1A3A458C9" + "935CBC7D294B64D628DA7F1B0FA4F24E6375DF31AE82815F" + "5DFF4ACD0DD9BD8A8740CB92633D1E000191B837021F143F" + "64B08388A78B9A0F55FE7B824FA9D4E85709EAC46EAB5B24" + "C46BBC2D1D8D39FEC8BA130EB68A7F55769606F07CB7B8CA" + "0AD99739C68A365E415983B964F1F2D261145057B7A76D72" + "300AD49D9FFFFFFE9C41BD48B82F8450274C6C25DCECE61D" + "4C443FEE0D3C359FDD4E4409AD607AE7A707B83B8629134D" + "ACCBD54C618EEF0B2F04E848F7B62C494DEC89F2830BACED" + "B3B876670309B36F7D70BE0219F5D05A3C1E5BB58B1CF053" + "FE92D2E3F934AA2047F963172E04B7457FED3956C08A705C" + "9C441F1FEE07E05344C63817F5DA7F298D5323BF88FB490E" + "1C628015ECD09C5D89978EB42A2DFD32E0820B005BDB60FF" + "FB15EBE1A123C6107530FE48C72C925FB85465749EF1A46C" + "6BA7F0F31D911D9E78608DAA64EC87CB3C82ABEC988FA365" + "6734A038FB5A3F072B7E9E9F383227EA3D5ACE37A6A5536B" + "9E3AA926E900"), + H ("645159996555659148569656954105506019451895595549" + "848669516585555885215216015254544569A65216995559" + "854155141511559254664659655555655555614616559508" + "95559696596565645699555A1596555A966566614655A409" + "51559554669590615659A551555125556595551955569915" + "A5614089A15501582951945A155586595555556541104911" + "69A0115656649156245559244155A584145650516445A555" + "555955485655455681166469511A59642155555501990285" + "891A514062416580150298400062840021A908660880A85A" + "28008958212528A0A604218026444A2AA5452A9522051201" + "99055041A99129298A989A895206621800648A98A8806986" + "4862A4651468A14114268209A55249440A89519065056895" + "86229848816266852198A2A2096459194A55040291048662" + "2949A09448210A94429A444126A4A66A0AA18921A4A54514" + "595A81248446A86601905118A2850492910185041822A524" + "22565641A195969068850240588648408A14990A6801D253" + "0F125EE5F208B1976A66BCBC917161F6929E636BA8C73470" + "DE18065F6057528D718744E9248DFFF6BB55C188CEACB941" + "9863C3C456B46A21354834ADA6B2132C67747C9EE70D0256" + "0268EE650E56C84BCE6A6700C5E612999110E53A866AE6B4" + "F778230367B8B886C4FEC089C6267F91C7F24D6CE53C754D" + "9CCCDD25756D76CD211D5954F0E8A11343679C1F692CE5C0" + "D0E42A02381144E1E0201B6F49F00628A86E09918488BC3E" + "1E1071561700544C2CE50F4B7BAE4757CA7A0DD0A221260E" + "0574D1F8F81AF072FCBA8061B5B8BB450FDCC6732D35CDBB" + "BC4EF1798EA7E263BCF369059EED3A86E2C61C72CBFCD695" + "21C3A1FD4868AF5638148043162B8B6E39F82B56D6C9C772" + "4807F623C06CC08FF619F7961EC972B1BD2856F87D5E6940" + "DC15B9575264A4AB0CA229C5B02C9AA5BB8DA2BD8EB09A7A" + "5E824C2D666A17C4845CA9530F3A5E45BE5A380B83C81B39" + "65180C706E2CC9ABF4DC8A1559CCF176EFD0FAAD1B8E184A" + "AA08E24CA6F5D070E040D64CD65A1628E99F3BACAB5A7206" + "B5C7D1F7D282651448E259A839E128774530C931C4E4E6F6" + "0AB9CDEB645AA24012C3A0983750C04914C59E34AF67B912" + "8CE906AD162D70E582C42E21898EF8023A9D1BC3B5F5BDE6" + "415CD168F1DE726A2ECB27C48A73356FBBEE8F405A6F8C34" + "F8F5A864C109045618B03FBFDCBAFD8BC934658634070D40" + "E5C62A03F9B544C325BCC56D8C70D67DA39879356E9871B0" + "16A0CCF3FE1C6AB941B69417FF514B616C9CFE9EA066FBB4" + "B081B25D584E40430B0950A7EBFBFA9B4E4EE003F297BA66" + "8F7139F26F218026DC9BFDBBBE6FD1CDE03CAC9814299126" + "E8CBDAFFD54101E07C09B65B88C9743B85C464E44C7256F5" + "06F07BC7D3877E2578D589CD2001E5124C9E647FAC2134B3" + "4E74DC188478E538BBFB750B47600191C51B71F18460CECD" + "5FBDABAA48D6DD6DBE7E26CEF9498220379F1FF25AFACA60" + "CEFFA408CEB677E4CAFB3A43B3E5FAA5B731EA608A945EDF" + "645136ADC77B07DB34E191D9E786ED7CFD97E2330548FFE0" + "21997E2E8B774E4A5F1666A91F05D471874E765DF42C7C3D" + "9EF37CD946E0D69C9EA83CEC9B1AA41A25F1A3A458C9935C" + "BC7D294B64D628DA7F1B0FA4F24E6375DF31AE82815F5DFF" + "4ACD0DD9BD8A8740CB92633D1E000191B837021F143F64B0" + "8388A78B9A0F55FE7B824FA9D4E85709EAC46EAB5B24C46B" + "BC2D1D8D39FEC8BA130EB68A7F55769606F07CB7B8CA0AD9" + "9739C68A365E415983B964F1F2D261145057B7A76D72300A" + "D49D9FFFFFFE9C41BD48B82F8450274C6C25DCECE61D4C44" + "3FEE0D3C359FDD4E4409AD607AE7A707B83B8629134DACCB" + "D54C618EEF0B2F04E848F7B62C494DEC89F2830BACEDB3B8" + "76670309B36F7D70BE0219F5D05A3C1E5BB58B1CF053FE92" + "D2E3F934AA2047F963172E04B7457FED3956C08A705C9C44" + "1F1FEE07E05344C63817F5DA7F298D5323BF88FB490E1C62" + "8015ECD09C5D89978EB42A2DFD32E0820B005BDB60FFFB15" + "EBE1A123C6107530FE48C72C925FB85465749EF1A46C6BA7" + "F0F31D911D9E78608DAA64EC87CB3C82ABEC988FA3656734" + "A038FB5A3F072B7E9E9F383227EA3D5ACE37A6A5536B9E3A" + "A926E900B736895EF729F2159BA82A0D090B0D4A26FFC467" + "511911F39D3EC248467A576EE1F8DCA10DD0C3BE961080D9" + "25B823AD9538477F258DD445AF4872DFDEB8E4A819DDE314" + "766683246379B03AA738907ED3671359999FF298C4A44133" + "417821912013E792C90D939815BC3AEBB565E1D6B42BB356" + "CC6A6C79EB6D640001C9D0ED847B4D39B2C38FC2123609EF" + "94608B766EBEB91DD12D228123D29D14C1B4169D8417D260" + "54304B5C900E5CF78159735D0FFA15B691369BC66811A9F1" + "1ADB3ED280E3151830BAC71B6E5EE77238F632911067ED8C" + "525887CF983CFE4A2572D3"), + H ("8CE9955F6DC23A0E49D9B263C43026609612696FD84D37DF" + "A1192BA0D9412D2125E25A7C64209A92E5F1C6F170D5C4C8" + "91D5050E336F628544620D6B0A9C5058DBBB51C4F540AE3C" + "19BD941E7CD3105A7BCD1774FF05B0B65E310A1D6F88253C" + "FA36C2E7F34130B14613B188D8B9D6C9BE040CE2446F33F7" + "5E2A61AF7D7C11FFF54505F1E1EEE49172234915D722599C" + "6BD77D0BCEBEC69435BAC571A194939861CE3ED3960C0FD0" + "FDB8D7CBD272659BBB881C29A70ECB62388062C4ABB2A565" + "A0D9CE73E23E9CA7D589DE524E8289762499F867697003DB" + "B87E1657313D05E5E8E7C7FF407DF7931EB6842C82521936" + "9E92D2E65E29CFCF31DCD0F40706AF8B4F70D9E8AF6147AC" + "7D8B1900773D9EE2CE6C4EEC38C4FF44F2E397D95684CE5E" + "E6FD5FE4975216819BAE496D2CE888A6F630FE448A4872BB" + "C5164A70A33A9988A3C4AEA17A8688346191CD4BE2F8D021" + "CC97D5A20BFFFFC628ED6F267145C41BCFB83161C2326294" + "3B530DF4BD4B6BDD85D78A2DAF0499B8DE97AFE6191AFD3A" + "35E8268A4D08EC55DBA8BEC15BDE4F823D4B3C62F7990EF7" + "A655D03DD4897F640ABDD60D58A3244F745CEA09ACCDD56D" + "E4D8F08F43025E084E91634E25FC7B39BCAFFC1803E8D480" + "6786548263D6BF8D8ACC84FA9A01D786F438FEDB811DF9FC" + "0EFFCF9C6A787B17228B260D6ACCE43075E7F80CC57C6821" + "01CD9CDF12B2D3F931AAAE1A2434AAE772C11CCEE49E2503" + "DAE5CBC98E41F6AD6E885B1F011E9883CE078B33D99FC414" + "71CCA14FC0DC12789464CE92B93A08E8F3D25822827A0827" + "3FA2E5114909F0D4A378A482F0EBDF781991E1E28B3F72CA" + "D3886575FF7E59F2B8607CE314D8292E27C1D6187EC5C76C" + "B1347185D760D69F91B7F455DDE52257B03CBB9845B78867" + "EABAA28535B6DEA69D14693666B1E978503F65412C5AFF4A" + "FEC1F537C416EAC390D5EEA0C3B4694DB4FAB95CAC381D12" + "F42F176F27A4BEE0C0A0A458B51E5C71D82724593014C154" + "30BECDBB472659D91B093192590A43A6E56BB6AD3C6C5BAA" + "7AA49D888E1CFA656200680A31ECDB99A4B0109133523653" + "D9769A945ADEC3890734841B94ACC62A8AB0805F0E9E9E3B" + "4471552DA0B5E78935C149E3D4DFCB20F75BDA04A86611B4" + "192BC6AF2B5C3C1C4424E40E8AF9E1A7A3E57B9AACA0B730" + "585931386329C19846D1BF091084C12380D7B2FB3348E7BC" + "25EF9BC39FEBA174B8FC9A191A11C345E0E3CB3170593928" + "429F0729BB96D771BAFCB84633B80377658EBB5866631AE2" + "EBAE05940AFDBA13F34A0341E923EA2C31F11E2A1A421C45" + "22AB50153A77B7950834CBF23A16D01462A0FCD270BCF66B" + "9F6E0A5A39F5989D75643DFC8EC4D5B051AE94C6DB74D777" + "9C54016EAD109D10AC190B07816CDCD2B8EC9BC596090DF0" + "0FE23B4E862FE7E0D7EBCBF6B2A1A565435DA662CB34489B" + "B570286BA114F8"), + H ("16C15126F734E51268BA916CE3B39A72E171AE79B8C2B6A6" + "8B34AB0DC5621B7E")); +}