mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-08-04 01:34:11 +02:00
Falcon: consolidate the native C into a single falcon.c
Merge the nine wc_falcon_*.c cores into wolfcrypt/src/falcon.c, matching the one-file-per-algorithm convention (ed25519.c, wc_mldsa.c). Sign and keygen are gated internally on WOLFSSL_FALCON_VERIFY_ONLY and the internal helpers become static. The fpr/fft/poly primitives stay external (shared with the separate AVX2/NEON FFT backends) so their three headers are retained; the other five internal headers are removed.
This commit is contained in:
@@ -16,16 +16,7 @@ ASM_SRCS := start.S
|
|||||||
# Full native Falcon (keygen + sign + verify) + SHAKE256 + runtime.
|
# Full native Falcon (keygen + sign + verify) + SHAKE256 + runtime.
|
||||||
WOLFSSL_SRCS := \
|
WOLFSSL_SRCS := \
|
||||||
../../wolfcrypt/src/falcon.c \
|
../../wolfcrypt/src/falcon.c \
|
||||||
../../wolfcrypt/src/wc_falcon.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_fpr.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_fft.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_fft_neon.c \
|
../../wolfcrypt/src/wc_falcon_fft_neon.c \
|
||||||
../../wolfcrypt/src/wc_falcon_poly.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_sampler.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_codec.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_keygen.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_sign.c \
|
|
||||||
../../wolfcrypt/src/wc_falcon_bigint.c \
|
|
||||||
../../wolfcrypt/src/sha3.c \
|
../../wolfcrypt/src/sha3.c \
|
||||||
../../wolfcrypt/src/sha256.c \
|
../../wolfcrypt/src/sha256.c \
|
||||||
../../wolfcrypt/src/hash.c \
|
../../wolfcrypt/src/hash.c \
|
||||||
|
|||||||
@@ -1143,17 +1143,6 @@ function(generate_lib_src_list LIB_SOURCES)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(BUILD_FALCON)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_fpr.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_fft.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_poly.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_sampler.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_codec.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_bigint.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_keygen.c)
|
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_falcon_sign.c)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(BUILD_WC_MLKEM)
|
if(BUILD_WC_MLKEM)
|
||||||
list(APPEND LIB_SOURCES wolfcrypt/src/wc_mlkem.c)
|
list(APPEND LIB_SOURCES wolfcrypt/src/wc_mlkem.c)
|
||||||
|
|||||||
@@ -1342,18 +1342,6 @@ endif BUILD_INTELASM
|
|||||||
endif !BUILD_X86_ASM
|
endif !BUILD_X86_ASM
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_FALCON
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_fpr.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_fft.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_poly.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_sampler.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_codec.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_bigint.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_keygen.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_sign.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_WC_LMS
|
if BUILD_WC_LMS
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms.c
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms_impl.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms_impl.c
|
||||||
@@ -2145,18 +2133,6 @@ endif BUILD_INTELASM
|
|||||||
endif !BUILD_X86_ASM
|
endif !BUILD_X86_ASM
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_FALCON
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_fpr.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_fft.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_poly.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_sampler.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_codec.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_bigint.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_keygen.c
|
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_falcon_sign.c
|
|
||||||
endif
|
|
||||||
|
|
||||||
if BUILD_WC_LMS
|
if BUILD_WC_LMS
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms.c
|
||||||
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms_impl.c
|
src_libwolfssl@LIBSUFFIX@_la_SOURCES += wolfcrypt/src/wc_lms_impl.c
|
||||||
|
|||||||
+8056
-6
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,370 +0,0 @@
|
|||||||
/* wc_falcon_codec.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon encode/decode routines for the signing and
|
|
||||||
* key-generation paths. These are faithful ports of the Falcon reference
|
|
||||||
* implementation (codec.c): modq_encode, comp_encode, trim_i8_encode and
|
|
||||||
* trim_i8_decode, plus the secret-key decoder that drives them.
|
|
||||||
*
|
|
||||||
* The verification-side decoders (modq_decode, comp_decode) are static
|
|
||||||
* functions in wc_falcon.c and are deliberately not duplicated here. */
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY) && !defined(WOLF_CRYPTO_CB_ONLY_FALCON)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/falcon.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_codec.h>
|
|
||||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
||||||
|
|
||||||
/* Maximum bit width used to encode f and g, indexed by logn (0..10).
|
|
||||||
* From the Falcon reference (codec.c). */
|
|
||||||
static const byte falcon_max_fg_bits[] = {
|
|
||||||
0, /* unused */
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
7,
|
|
||||||
7,
|
|
||||||
6,
|
|
||||||
6,
|
|
||||||
5
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Maximum bit width used to encode F (and G), indexed by logn (0..10).
|
|
||||||
* From the Falcon reference (codec.c). */
|
|
||||||
static const byte falcon_max_FG_bits[] = {
|
|
||||||
0, /* unused */
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8,
|
|
||||||
8
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Pack the public key polynomial h: n coefficients, 14 bits each, packed
|
|
||||||
* most-significant bit first. Inverse of falcon_modq_decode. Returns the number
|
|
||||||
* of bytes written, or 0 on a coefficient >= q or output overflow. */
|
|
||||||
size_t falcon_modq_encode(byte* out, size_t max_out, const word16* x,
|
|
||||||
unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn;
|
|
||||||
size_t out_len = ((n * 14) + 7) >> 3;
|
|
||||||
size_t u, v;
|
|
||||||
word32 acc = 0;
|
|
||||||
int acc_len = 0;
|
|
||||||
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
if (x[u] >= FALCON_Q) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out_len > max_out) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
v = 0;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
acc = (acc << 14) | (word32)x[u];
|
|
||||||
acc_len += 14;
|
|
||||||
while (acc_len >= 8) {
|
|
||||||
acc_len -= 8;
|
|
||||||
out[v++] = (byte)(acc >> acc_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acc_len > 0) {
|
|
||||||
out[v++] = (byte)(acc << (8 - acc_len));
|
|
||||||
}
|
|
||||||
return out_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Compress the signature polynomial s2 with Golomb-Rice coding (k=7). Exact
|
|
||||||
* inverse of the reference comp_decode. Returns the number of bytes written, or
|
|
||||||
* 0 if any |x[i]| > 2047 or the output buffer overflows. */
|
|
||||||
size_t falcon_comp_encode(byte* out, size_t max_out, const sword16* x,
|
|
||||||
unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn;
|
|
||||||
size_t u, v;
|
|
||||||
word32 acc = 0;
|
|
||||||
unsigned acc_len = 0;
|
|
||||||
|
|
||||||
/* All coefficients must fit in the -2047..+2047 range. */
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
if (x[u] < -2047 || x[u] > 2047) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
v = 0;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
int t;
|
|
||||||
unsigned w;
|
|
||||||
|
|
||||||
/* Sign bit (1 for negative), then the low 7 bits of |x|. */
|
|
||||||
acc <<= 1;
|
|
||||||
t = (int)x[u];
|
|
||||||
if (t < 0) {
|
|
||||||
t = -t;
|
|
||||||
acc |= 1;
|
|
||||||
}
|
|
||||||
w = (unsigned)t;
|
|
||||||
|
|
||||||
acc <<= 7;
|
|
||||||
acc |= w & 127u;
|
|
||||||
w >>= 7;
|
|
||||||
acc_len += 8;
|
|
||||||
|
|
||||||
/* Unary high part: w zero bits then a terminating one. The absolute
|
|
||||||
* value is at most 2047, so w <= 15 here and at most 16 bits are added;
|
|
||||||
* combined with the 8 bits above and up to 7 carried bits, the 32-bit
|
|
||||||
* accumulator never overflows. */
|
|
||||||
acc <<= (w + 1);
|
|
||||||
acc |= 1;
|
|
||||||
acc_len += w + 1;
|
|
||||||
|
|
||||||
while (acc_len >= 8) {
|
|
||||||
acc_len -= 8;
|
|
||||||
if (v >= max_out) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
out[v++] = (byte)(acc >> acc_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Flush any remaining bits, left-aligned in the final byte. */
|
|
||||||
if (acc_len > 0) {
|
|
||||||
if (v >= max_out) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
out[v++] = (byte)(acc << (8 - acc_len));
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Pack n signed 8-bit coefficients, each in 'bits' bits, MSB first. The valid
|
|
||||||
* range is -(2^(bits-1)-1) .. +(2^(bits-1)-1); the most-negative value is not
|
|
||||||
* representable. Returns bytes written, or 0 on range violation / overflow. */
|
|
||||||
size_t falcon_trim_i8_encode(byte* out, size_t max_out, const sword8* x,
|
|
||||||
unsigned logn, unsigned bits)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn;
|
|
||||||
size_t out_len = ((n * bits) + 7) >> 3;
|
|
||||||
size_t u, v;
|
|
||||||
int minv, maxv;
|
|
||||||
word32 acc = 0, mask;
|
|
||||||
unsigned acc_len = 0;
|
|
||||||
|
|
||||||
/* Callers only pass falcon_max_fg_bits/falcon_max_FG_bits values (5..8);
|
|
||||||
* guard the shifts below against out-of-range widths anyway. */
|
|
||||||
if (bits < 2 || bits > 8) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
maxv = (1 << (bits - 1)) - 1;
|
|
||||||
minv = -maxv;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
if (x[u] < minv || x[u] > maxv) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (out_len > max_out) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask = ((word32)1 << bits) - 1;
|
|
||||||
v = 0;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
acc = (acc << bits) | ((word32)(byte)x[u] & mask);
|
|
||||||
acc_len += bits;
|
|
||||||
while (acc_len >= 8) {
|
|
||||||
acc_len -= 8;
|
|
||||||
out[v++] = (byte)(acc >> acc_len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (acc_len > 0) {
|
|
||||||
out[v++] = (byte)(acc << (8 - acc_len));
|
|
||||||
}
|
|
||||||
return out_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Unpack n signed 8-bit coefficients packed at 'bits' bits each (MSB first).
|
|
||||||
* The most-negative value -2^(bits-1) is rejected. Trailing pad bits in the
|
|
||||||
* final byte must be zero. Returns bytes consumed, or 0 on any violation. */
|
|
||||||
size_t falcon_trim_i8_decode(sword8* x, unsigned logn, unsigned bits,
|
|
||||||
const byte* in, size_t max_in)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn;
|
|
||||||
size_t in_len = ((n * bits) + 7) >> 3;
|
|
||||||
size_t u, v;
|
|
||||||
word32 acc = 0, mask1, mask2;
|
|
||||||
unsigned acc_len = 0;
|
|
||||||
|
|
||||||
/* Same defensive width guard as falcon_trim_i8_encode. */
|
|
||||||
if (bits < 2 || bits > 8) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (in_len > max_in) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mask1 = ((word32)1 << bits) - 1;
|
|
||||||
mask2 = (word32)1 << (bits - 1);
|
|
||||||
u = 0;
|
|
||||||
v = 0;
|
|
||||||
while (u < n) {
|
|
||||||
acc = (acc << 8) | (word32)in[v++];
|
|
||||||
acc_len += 8;
|
|
||||||
while (acc_len >= bits && u < n) {
|
|
||||||
word32 w;
|
|
||||||
|
|
||||||
acc_len -= bits;
|
|
||||||
w = (acc >> acc_len) & mask1;
|
|
||||||
/* Sign-extend from the high bit. */
|
|
||||||
w |= (word32)(-(sword32)(w & mask2));
|
|
||||||
if (w == (word32)(-(sword32)mask2)) {
|
|
||||||
/* The -2^(bits-1) value is forbidden. */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
x[u++] = (sword8)(sword32)w;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Extra bits in the last consumed byte must be zero. */
|
|
||||||
if ((acc & (((word32)1 << acc_len) - 1)) != 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return in_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Decode a Falcon secret key into its (f, g, F) basis polynomials. The encoding
|
|
||||||
* is: header byte (0x50 | logn), then trim_i8(f, max_fg_bits[logn]),
|
|
||||||
* trim_i8(g, max_fg_bits[logn]), trim_i8(F, max_FG_bits[logn]). G is not stored
|
|
||||||
* (it is recomputed from f, g, F at use time). The header and an exact length
|
|
||||||
* match are both validated. */
|
|
||||||
int falcon_privkey_decode(const byte* sk, size_t sklen, sword8* f, sword8* g,
|
|
||||||
sword8* F, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t u, v;
|
|
||||||
|
|
||||||
if (sk == NULL || f == NULL || g == NULL || F == NULL) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
if (logn < 1 || logn > 10) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
if (sklen < 1) {
|
|
||||||
return BUFFER_E;
|
|
||||||
}
|
|
||||||
if (sk[0] != (byte)(0x50 | logn)) {
|
|
||||||
return ASN_PARSE_E;
|
|
||||||
}
|
|
||||||
|
|
||||||
u = 1;
|
|
||||||
v = falcon_trim_i8_decode(f, logn, falcon_max_fg_bits[logn],
|
|
||||||
sk + u, sklen - u);
|
|
||||||
if (v == 0) {
|
|
||||||
return ASN_PARSE_E;
|
|
||||||
}
|
|
||||||
u += v;
|
|
||||||
|
|
||||||
v = falcon_trim_i8_decode(g, logn, falcon_max_fg_bits[logn],
|
|
||||||
sk + u, sklen - u);
|
|
||||||
if (v == 0) {
|
|
||||||
return ASN_PARSE_E;
|
|
||||||
}
|
|
||||||
u += v;
|
|
||||||
|
|
||||||
v = falcon_trim_i8_decode(F, logn, falcon_max_FG_bits[logn],
|
|
||||||
sk + u, sklen - u);
|
|
||||||
if (v == 0) {
|
|
||||||
return ASN_PARSE_E;
|
|
||||||
}
|
|
||||||
u += v;
|
|
||||||
|
|
||||||
/* The whole secret key must be consumed exactly. */
|
|
||||||
if (u != sklen) {
|
|
||||||
return ASN_PARSE_E;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Encode a Falcon secret key from its (f, g, F) basis: header byte
|
|
||||||
* (0x50 | logn), then trim_i8(f), trim_i8(g) at max_fg_bits[logn] and
|
|
||||||
* trim_i8(F) at max_FG_bits[logn]. Returns the number of bytes written, or 0 on
|
|
||||||
* range violation / output overflow. */
|
|
||||||
size_t falcon_privkey_encode(byte* sk, size_t max_sk, const sword8* f,
|
|
||||||
const sword8* g, const sword8* F, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t u, v;
|
|
||||||
|
|
||||||
if (sk == NULL || f == NULL || g == NULL || F == NULL) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (logn < 1 || logn > 10) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (max_sk < 1) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sk[0] = (byte)(0x50 | logn);
|
|
||||||
u = 1;
|
|
||||||
|
|
||||||
v = falcon_trim_i8_encode(sk + u, max_sk - u, f, logn,
|
|
||||||
falcon_max_fg_bits[logn]);
|
|
||||||
if (v == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
u += v;
|
|
||||||
|
|
||||||
v = falcon_trim_i8_encode(sk + u, max_sk - u, g, logn,
|
|
||||||
falcon_max_fg_bits[logn]);
|
|
||||||
if (v == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
u += v;
|
|
||||||
|
|
||||||
v = falcon_trim_i8_encode(sk + u, max_sk - u, F, logn,
|
|
||||||
falcon_max_FG_bits[logn]);
|
|
||||||
if (v == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
u += v;
|
|
||||||
|
|
||||||
return u;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
@@ -1,635 +0,0 @@
|
|||||||
/* wc_falcon_fft.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon FFT over the fpr seam. See wolfssl/wolfcrypt/wc_falcon_fft.h.
|
|
||||||
* Algorithm and twiddle-table layout validated against a schoolbook negacyclic
|
|
||||||
* reference (round-trip and FFT-based multiplication) for n in {8,512,1024}. */
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY) && !defined(WOLF_CRYPTO_CB_ONLY_FALCON)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fft.h>
|
|
||||||
|
|
||||||
/* Complex helpers over the fpr seam. d may alias a/b inputs only via temps. */
|
|
||||||
#define FPC_ADD(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
(d_re) = fpr_add(_ar, _br); \
|
|
||||||
(d_im) = fpr_add(_ai, _bi); \
|
|
||||||
} while (0)
|
|
||||||
#define FPC_SUB(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
(d_re) = fpr_sub(_ar, _br); \
|
|
||||||
(d_im) = fpr_sub(_ai, _bi); \
|
|
||||||
} while (0)
|
|
||||||
/* (a_re + i a_im) * (b_re + i b_im) */
|
|
||||||
#define FPC_MUL(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
(d_re) = fpr_sub(fpr_mul(_ar, _br), fpr_mul(_ai, _bi)); \
|
|
||||||
(d_im) = fpr_add(fpr_mul(_ar, _bi), fpr_mul(_ai, _br)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* falcon_gm_tab[2*p+0]=cos, [2*p+1]=sin; angle=pi*(2*brev_u(i)+1)/(2m).
|
|
||||||
* Generated table of correctly-rounded IEEE-754 twiddle factors, n<=1024.
|
|
||||||
* Exported (declared in wc_falcon_fft.h) for use by the poly_split/merge ops. */
|
|
||||||
const fpr falcon_gm_tab[2048] = {
|
|
||||||
0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
|
|
||||||
0x3FE6A09E667F3BCDULL, 0x3FE6A09E667F3BCCULL, 0xBFE6A09E667F3BCCULL, 0x3FE6A09E667F3BCDULL,
|
|
||||||
0x3FED906BCF328D46ULL, 0x3FD87DE2A6AEA963ULL, 0xBFD87DE2A6AEA962ULL, 0x3FED906BCF328D46ULL,
|
|
||||||
0x3FD87DE2A6AEA964ULL, 0x3FED906BCF328D46ULL, 0xBFED906BCF328D46ULL, 0x3FD87DE2A6AEA965ULL,
|
|
||||||
0x3FEF6297CFF75CB0ULL, 0x3FC8F8B83C69A60AULL, 0xBFC8F8B83C69A608ULL, 0x3FEF6297CFF75CB0ULL,
|
|
||||||
0x3FE1C73B39AE68C9ULL, 0x3FEA9B66290EA1A3ULL, 0xBFEA9B66290EA1A4ULL, 0x3FE1C73B39AE68C8ULL,
|
|
||||||
0x3FEA9B66290EA1A3ULL, 0x3FE1C73B39AE68C8ULL, 0xBFE1C73B39AE68C6ULL, 0x3FEA9B66290EA1A5ULL,
|
|
||||||
0x3FC8F8B83C69A60DULL, 0x3FEF6297CFF75CB0ULL, 0xBFEF6297CFF75CB0ULL, 0x3FC8F8B83C69A617ULL,
|
|
||||||
0x3FEFD88DA3D12526ULL, 0x3FB917A6BC29B42CULL, 0xBFB917A6BC29B42FULL, 0x3FEFD88DA3D12526ULL,
|
|
||||||
0x3FE44CF325091DD6ULL, 0x3FE8BC806B151741ULL, 0xBFE8BC806B151741ULL, 0x3FE44CF325091DD6ULL,
|
|
||||||
0x3FEC38B2F180BDB1ULL, 0x3FDE2B5D3806F63BULL, 0xBFDE2B5D3806F63CULL, 0x3FEC38B2F180BDB1ULL,
|
|
||||||
0x3FD294062ED59F05ULL, 0x3FEE9F4156C62DDBULL, 0xBFEE9F4156C62DDAULL, 0x3FD294062ED59F06ULL,
|
|
||||||
0x3FEE9F4156C62DDAULL, 0x3FD294062ED59F05ULL, 0xBFD294062ED59F02ULL, 0x3FEE9F4156C62DDBULL,
|
|
||||||
0x3FDE2B5D3806F63EULL, 0x3FEC38B2F180BDB0ULL, 0xBFEC38B2F180BDB0ULL, 0x3FDE2B5D3806F63FULL,
|
|
||||||
0x3FE8BC806B151741ULL, 0x3FE44CF325091DD6ULL, 0xBFE44CF325091DD5ULL, 0x3FE8BC806B151742ULL,
|
|
||||||
0x3FB917A6BC29B438ULL, 0x3FEFD88DA3D12525ULL, 0xBFEFD88DA3D12525ULL, 0x3FB917A6BC29B43CULL,
|
|
||||||
0x3FEFF621E3796D7EULL, 0x3FA91F65F10DD814ULL, 0xBFA91F65F10DD813ULL, 0x3FEFF621E3796D7EULL,
|
|
||||||
0x3FE57D69348CEC9FULL, 0x3FE7B5DF226AAFAFULL, 0xBFE7B5DF226AAFADULL, 0x3FE57D69348CECA1ULL,
|
|
||||||
0x3FECED7AF43CC773ULL, 0x3FDB5D1009E15CC0ULL, 0xBFDB5D1009E15CBCULL, 0x3FECED7AF43CC774ULL,
|
|
||||||
0x3FD58F9A75AB1FDDULL, 0x3FEE212104F686E5ULL, 0xBFEE212104F686E4ULL, 0x3FD58F9A75AB1FE2ULL,
|
|
||||||
0x3FEF0A7EFB9230D7ULL, 0x3FCF19F97B215F1AULL, 0xBFCF19F97B215F1AULL, 0x3FEF0A7EFB9230D7ULL,
|
|
||||||
0x3FE073879922FFEDULL, 0x3FEB728345196E3EULL, 0xBFEB728345196E3DULL, 0x3FE073879922FFEEULL,
|
|
||||||
0x3FE9B3E047F38741ULL, 0x3FE30FF7FCE17035ULL, 0xBFE30FF7FCE17035ULL, 0x3FE9B3E047F38741ULL,
|
|
||||||
0x3FC2C8106E8E613AULL, 0x3FEFA7557F08A517ULL, 0xBFEFA7557F08A517ULL, 0x3FC2C8106E8E613CULL,
|
|
||||||
0x3FEFA7557F08A517ULL, 0x3FC2C8106E8E613AULL, 0xBFC2C8106E8E6136ULL, 0x3FEFA7557F08A517ULL,
|
|
||||||
0x3FE30FF7FCE17036ULL, 0x3FE9B3E047F38740ULL, 0xBFE9B3E047F38740ULL, 0x3FE30FF7FCE17036ULL,
|
|
||||||
0x3FEB728345196E3EULL, 0x3FE073879922FFEDULL, 0xBFE073879922FFEDULL, 0x3FEB728345196E3EULL,
|
|
||||||
0x3FCF19F97B215F1EULL, 0x3FEF0A7EFB9230D7ULL, 0xBFEF0A7EFB9230D7ULL, 0x3FCF19F97B215F21ULL,
|
|
||||||
0x3FEE212104F686E5ULL, 0x3FD58F9A75AB1FDDULL, 0xBFD58F9A75AB1FDBULL, 0x3FEE212104F686E5ULL,
|
|
||||||
0x3FDB5D1009E15CC2ULL, 0x3FECED7AF43CC773ULL, 0xBFECED7AF43CC773ULL, 0x3FDB5D1009E15CBFULL,
|
|
||||||
0x3FE7B5DF226AAFAFULL, 0x3FE57D69348CEC9FULL, 0xBFE57D69348CECA0ULL, 0x3FE7B5DF226AAFAEULL,
|
|
||||||
0x3FA91F65F10DD824ULL, 0x3FEFF621E3796D7EULL, 0xBFEFF621E3796D7EULL, 0x3FA91F65F10DD80DULL,
|
|
||||||
0x3FEFFD886084CD0DULL, 0x3F992155F7A3667EULL, 0xBF992155F7A36654ULL, 0x3FEFFD886084CD0DULL,
|
|
||||||
0x3FE610B7551D2CDFULL, 0x3FE72D0837EFFF96ULL, 0xBFE72D0837EFFF95ULL, 0x3FE610B7551D2CE0ULL,
|
|
||||||
0x3FED4134D14DC93AULL, 0x3FD9EF7943A8ED8AULL, 0xBFD9EF7943A8ED88ULL, 0x3FED4134D14DC93AULL,
|
|
||||||
0x3FD7088530FA45A1ULL, 0x3FEDDB13B6CCC23CULL, 0xBFEDDB13B6CCC23CULL, 0x3FD7088530FA45A2ULL,
|
|
||||||
0x3FEF38F3AC64E589ULL, 0x3FCC0B826A7E4F63ULL, 0xBFCC0B826A7E4F5EULL, 0x3FEF38F3AC64E589ULL,
|
|
||||||
0x3FE11EB3541B4B23ULL, 0x3FEB090A581501FFULL, 0xBFEB090A58150200ULL, 0x3FE11EB3541B4B22ULL,
|
|
||||||
0x3FEA29A7A0462782ULL, 0x3FE26D054CDD12DFULL, 0xBFE26D054CDD12DFULL, 0x3FEA29A7A0462782ULL,
|
|
||||||
0x3FC5E214448B3FCBULL, 0x3FEF8764FA714BA9ULL, 0xBFEF8764FA714BA9ULL, 0x3FC5E214448B3FC6ULL,
|
|
||||||
0x3FEFC26470E19FD3ULL, 0x3FBF564E56A9730EULL, 0xBFBF564E56A9730BULL, 0x3FEFC26470E19FD3ULL,
|
|
||||||
0x3FE3AFFA292050B9ULL, 0x3FE93A22499263FBULL, 0xBFE93A22499263FBULL, 0x3FE3AFFA292050BAULL,
|
|
||||||
0x3FEBD7C0AC6F952AULL, 0x3FDF8BA4DBF89ABAULL, 0xBFDF8BA4DBF89AB9ULL, 0x3FEBD7C0AC6F952AULL,
|
|
||||||
0x3FD111D262B1F678ULL, 0x3FEED740E7684963ULL, 0xBFEED740E7684963ULL, 0x3FD111D262B1F679ULL,
|
|
||||||
0x3FEE6288EC48E112ULL, 0x3FD4135C94176602ULL, 0xBFD4135C94176600ULL, 0x3FEE6288EC48E112ULL,
|
|
||||||
0x3FDCC66E9931C45EULL, 0x3FEC954B213411F5ULL, 0xBFEC954B213411F4ULL, 0x3FDCC66E9931C463ULL,
|
|
||||||
0x3FE83B0E0BFF976EULL, 0x3FE4E6CABBE3E5E9ULL, 0xBFE4E6CABBE3E5E7ULL, 0x3FE83B0E0BFF976FULL,
|
|
||||||
0x3FB2D52092CE19F8ULL, 0x3FEFE9CDAD01883AULL, 0xBFEFE9CDAD01883AULL, 0x3FB2D52092CE1A0CULL,
|
|
||||||
0x3FEFE9CDAD01883AULL, 0x3FB2D52092CE19F6ULL, 0xBFB2D52092CE19EFULL, 0x3FEFE9CDAD01883AULL,
|
|
||||||
0x3FE4E6CABBE3E5E9ULL, 0x3FE83B0E0BFF976DULL, 0xBFE83B0E0BFF976EULL, 0x3FE4E6CABBE3E5E8ULL,
|
|
||||||
0x3FEC954B213411F5ULL, 0x3FDCC66E9931C45DULL, 0xBFDCC66E9931C460ULL, 0x3FEC954B213411F4ULL,
|
|
||||||
0x3FD4135C94176603ULL, 0x3FEE6288EC48E112ULL, 0xBFEE6288EC48E112ULL, 0x3FD4135C94176600ULL,
|
|
||||||
0x3FEED740E7684963ULL, 0x3FD111D262B1F677ULL, 0xBFD111D262B1F676ULL, 0x3FEED740E7684963ULL,
|
|
||||||
0x3FDF8BA4DBF89ABBULL, 0x3FEBD7C0AC6F9529ULL, 0xBFEBD7C0AC6F9529ULL, 0x3FDF8BA4DBF89ABCULL,
|
|
||||||
0x3FE93A22499263FCULL, 0x3FE3AFFA292050B9ULL, 0xBFE3AFFA292050B8ULL, 0x3FE93A22499263FCULL,
|
|
||||||
0x3FBF564E56A97314ULL, 0x3FEFC26470E19FD3ULL, 0xBFEFC26470E19FD3ULL, 0x3FBF564E56A97319ULL,
|
|
||||||
0x3FEF8764FA714BA9ULL, 0x3FC5E214448B3FC6ULL, 0xBFC5E214448B3FC7ULL, 0x3FEF8764FA714BA9ULL,
|
|
||||||
0x3FE26D054CDD12DFULL, 0x3FEA29A7A0462782ULL, 0xBFEA29A7A0462781ULL, 0x3FE26D054CDD12E0ULL,
|
|
||||||
0x3FEB090A58150200ULL, 0x3FE11EB3541B4B22ULL, 0xBFE11EB3541B4B21ULL, 0x3FEB090A58150201ULL,
|
|
||||||
0x3FCC0B826A7E4F62ULL, 0x3FEF38F3AC64E589ULL, 0xBFEF38F3AC64E588ULL, 0x3FCC0B826A7E4F6CULL,
|
|
||||||
0x3FEDDB13B6CCC23DULL, 0x3FD7088530FA459EULL, 0xBFD7088530FA459FULL, 0x3FEDDB13B6CCC23CULL,
|
|
||||||
0x3FD9EF7943A8ED8AULL, 0x3FED4134D14DC93AULL, 0xBFED4134D14DC93AULL, 0x3FD9EF7943A8ED8BULL,
|
|
||||||
0x3FE72D0837EFFF97ULL, 0x3FE610B7551D2CDEULL, 0xBFE610B7551D2CDFULL, 0x3FE72D0837EFFF96ULL,
|
|
||||||
0x3F992155F7A36677ULL, 0x3FEFFD886084CD0DULL, 0xBFEFFD886084CD0DULL, 0x3F992155F7A36689ULL,
|
|
||||||
0x3FEFFF62169B92DBULL, 0x3F8921D1FCDEC784ULL, 0xBF8921D1FCDEC749ULL, 0x3FEFFF62169B92DBULL,
|
|
||||||
0x3FE6591925F0783EULL, 0x3FE6E74454EAA8AEULL, 0xBFE6E74454EAA8AEULL, 0x3FE6591925F0783EULL,
|
|
||||||
0x3FED696173C9E68BULL, 0x3FD9372A63BC93D7ULL, 0xBFD9372A63BC93D5ULL, 0x3FED696173C9E68BULL,
|
|
||||||
0x3FD7C3A9311DCCE8ULL, 0x3FEDB6526238A09AULL, 0xBFEDB6526238A09AULL, 0x3FD7C3A9311DCCEAULL,
|
|
||||||
0x3FEF4E603B0B2F2DULL, 0x3FCA82A025B00451ULL, 0xBFCA82A025B0044DULL, 0x3FEF4E603B0B2F2DULL,
|
|
||||||
0x3FE1734D63DEDB49ULL, 0x3FEAD2BC9E21D510ULL, 0xBFEAD2BC9E21D511ULL, 0x3FE1734D63DEDB48ULL,
|
|
||||||
0x3FEA63091B02FAE2ULL, 0x3FE21A799933EB58ULL, 0xBFE21A799933EB59ULL, 0x3FEA63091B02FAE1ULL,
|
|
||||||
0x3FC76DD9DE50BF35ULL, 0x3FEF7599A3A12077ULL, 0xBFEF7599A3A12077ULL, 0x3FC76DD9DE50BF2FULL,
|
|
||||||
0x3FEFCE15FD6DA67BULL, 0x3FBC3785C79EC2D5ULL, 0xBFBC3785C79EC2D5ULL, 0x3FEFCE15FD6DA67BULL,
|
|
||||||
0x3FE3FED9534556D5ULL, 0x3FE8FBCCA3EF940CULL, 0xBFE8FBCCA3EF940DULL, 0x3FE3FED9534556D4ULL,
|
|
||||||
0x3FEC08C426725549ULL, 0x3FDEDC1952EF78D5ULL, 0xBFDEDC1952EF78D5ULL, 0x3FEC08C426725549ULL,
|
|
||||||
0x3FD1D3443F4CDB3DULL, 0x3FEEBBD8C8DF0B74ULL, 0xBFEEBBD8C8DF0B74ULL, 0x3FD1D3443F4CDB3FULL,
|
|
||||||
0x3FEE817BAB4CD10DULL, 0x3FD35410C2E18152ULL, 0xBFD35410C2E18152ULL, 0x3FEE817BAB4CD10DULL,
|
|
||||||
0x3FDD79775B86E389ULL, 0x3FEC678B3488739BULL, 0xBFEC678B3488739AULL, 0x3FDD79775B86E38DULL,
|
|
||||||
0x3FE87C400FBA2EBFULL, 0x3FE49A449B9B0938ULL, 0xBFE49A449B9B0937ULL, 0x3FE87C400FBA2EC0ULL,
|
|
||||||
0x3FB5F6D00A9AA418ULL, 0x3FEFE1CAFCBD5B09ULL, 0xBFEFE1CAFCBD5B09ULL, 0x3FB5F6D00A9AA42CULL,
|
|
||||||
0x3FEFF095658E71ADULL, 0x3FAF656E79F820E0ULL, 0xBFAF656E79F820D9ULL, 0x3FEFF095658E71ADULL,
|
|
||||||
0x3FE5328292A35596ULL, 0x3FE7F8ECE3571770ULL, 0xBFE7F8ECE357176FULL, 0x3FE5328292A35598ULL,
|
|
||||||
0x3FECC1F0F3FCFC5CULL, 0x3FDC1249D8011EE7ULL, 0xBFDC1249D8011EE2ULL, 0x3FECC1F0F3FCFC5DULL,
|
|
||||||
0x3FD4D1E24278E76BULL, 0x3FEE426A4B2BC17EULL, 0xBFEE426A4B2BC17DULL, 0x3FD4D1E24278E770ULL,
|
|
||||||
0x3FEEF178A3E473C2ULL, 0x3FD04FB80E37FDAEULL, 0xBFD04FB80E37FDADULL, 0x3FEEF178A3E473C2ULL,
|
|
||||||
0x3FE01CFC874C3EB7ULL, 0x3FEBA5AA673590D2ULL, 0xBFEBA5AA673590D2ULL, 0x3FE01CFC874C3EB8ULL,
|
|
||||||
0x3FE9777EF4C7D742ULL, 0x3FE36058B10659F3ULL, 0xBFE36058B10659F2ULL, 0x3FE9777EF4C7D742ULL,
|
|
||||||
0x3FC139F0CEDAF578ULL, 0x3FEFB5797195D741ULL, 0xBFEFB5797195D741ULL, 0x3FC139F0CEDAF57AULL,
|
|
||||||
0x3FEF97F924C9099BULL, 0x3FC45576B1293E5AULL, 0xBFC45576B1293E54ULL, 0x3FEF97F924C9099BULL,
|
|
||||||
0x3FE2BEDB25FAF3EAULL, 0x3FE9EF43EF29AF94ULL, 0xBFE9EF43EF29AF93ULL, 0x3FE2BEDB25FAF3EBULL,
|
|
||||||
0x3FEB3E4D3EF55712ULL, 0x3FE0C9704D5D898FULL, 0xBFE0C9704D5D898DULL, 0x3FEB3E4D3EF55712ULL,
|
|
||||||
0x3FCD934FE5454317ULL, 0x3FEF2252F7763AD9ULL, 0xBFEF2252F7763AD9ULL, 0x3FCD934FE5454319ULL,
|
|
||||||
0x3FEDFEAE622DBE2BULL, 0x3FD64C7DDD3F27C6ULL, 0xBFD64C7DDD3F27C3ULL, 0x3FEDFEAE622DBE2BULL,
|
|
||||||
0x3FDAA6C82B6D3FCCULL, 0x3FED17E7743E35DBULL, 0xBFED17E7743E35DCULL, 0x3FDAA6C82B6D3FC9ULL,
|
|
||||||
0x3FE771E75F037261ULL, 0x3FE5C77BBE65018CULL, 0xBFE5C77BBE65018CULL, 0x3FE771E75F037261ULL,
|
|
||||||
0x3FA2D865759455E4ULL, 0x3FEFFA72EFFEF75DULL, 0xBFEFFA72EFFEF75DULL, 0x3FA2D865759455CDULL,
|
|
||||||
0x3FEFFA72EFFEF75DULL, 0x3FA2D865759455CDULL, 0xBFA2D865759455D2ULL, 0x3FEFFA72EFFEF75DULL,
|
|
||||||
0x3FE5C77BBE65018DULL, 0x3FE771E75F037261ULL, 0xBFE771E75F037260ULL, 0x3FE5C77BBE65018EULL,
|
|
||||||
0x3FED17E7743E35DCULL, 0x3FDAA6C82B6D3FC9ULL, 0xBFDAA6C82B6D3FC6ULL, 0x3FED17E7743E35DDULL,
|
|
||||||
0x3FD64C7DDD3F27C5ULL, 0x3FEDFEAE622DBE2BULL, 0xBFEDFEAE622DBE2AULL, 0x3FD64C7DDD3F27CAULL,
|
|
||||||
0x3FEF2252F7763ADAULL, 0x3FCD934FE5454311ULL, 0xBFCD934FE5454312ULL, 0x3FEF2252F7763ADAULL,
|
|
||||||
0x3FE0C9704D5D898EULL, 0x3FEB3E4D3EF55712ULL, 0xBFEB3E4D3EF55712ULL, 0x3FE0C9704D5D898FULL,
|
|
||||||
0x3FE9EF43EF29AF94ULL, 0x3FE2BEDB25FAF3EAULL, 0xBFE2BEDB25FAF3EAULL, 0x3FE9EF43EF29AF94ULL,
|
|
||||||
0x3FC45576B1293E58ULL, 0x3FEF97F924C9099BULL, 0xBFEF97F924C9099BULL, 0x3FC45576B1293E5BULL,
|
|
||||||
0x3FEFB5797195D741ULL, 0x3FC139F0CEDAF576ULL, 0xBFC139F0CEDAF574ULL, 0x3FEFB5797195D741ULL,
|
|
||||||
0x3FE36058B10659F3ULL, 0x3FE9777EF4C7D741ULL, 0xBFE9777EF4C7D741ULL, 0x3FE36058B10659F4ULL,
|
|
||||||
0x3FEBA5AA673590D3ULL, 0x3FE01CFC874C3EB7ULL, 0xBFE01CFC874C3EB6ULL, 0x3FEBA5AA673590D3ULL,
|
|
||||||
0x3FD04FB80E37FDAFULL, 0x3FEEF178A3E473C2ULL, 0xBFEEF178A3E473C2ULL, 0x3FD04FB80E37FDB0ULL,
|
|
||||||
0x3FEE426A4B2BC17EULL, 0x3FD4D1E24278E76AULL, 0xBFD4D1E24278E769ULL, 0x3FEE426A4B2BC17FULL,
|
|
||||||
0x3FDC1249D8011EE8ULL, 0x3FECC1F0F3FCFC5CULL, 0xBFECC1F0F3FCFC5DULL, 0x3FDC1249D8011EE5ULL,
|
|
||||||
0x3FE7F8ECE3571771ULL, 0x3FE5328292A35596ULL, 0xBFE5328292A35597ULL, 0x3FE7F8ECE3571770ULL,
|
|
||||||
0x3FAF656E79F820EAULL, 0x3FEFF095658E71ADULL, 0xBFEFF095658E71ADULL, 0x3FAF656E79F820D3ULL,
|
|
||||||
0x3FEFE1CAFCBD5B09ULL, 0x3FB5F6D00A9AA419ULL, 0xBFB5F6D00A9AA40FULL, 0x3FEFE1CAFCBD5B09ULL,
|
|
||||||
0x3FE49A449B9B0939ULL, 0x3FE87C400FBA2EBFULL, 0xBFE87C400FBA2EBFULL, 0x3FE49A449B9B0938ULL,
|
|
||||||
0x3FEC678B3488739BULL, 0x3FDD79775B86E389ULL, 0xBFDD79775B86E38AULL, 0x3FEC678B3488739BULL,
|
|
||||||
0x3FD35410C2E18154ULL, 0x3FEE817BAB4CD10CULL, 0xBFEE817BAB4CD10DULL, 0x3FD35410C2E18151ULL,
|
|
||||||
0x3FEEBBD8C8DF0B74ULL, 0x3FD1D3443F4CDB3DULL, 0xBFD1D3443F4CDB3BULL, 0x3FEEBBD8C8DF0B75ULL,
|
|
||||||
0x3FDEDC1952EF78D7ULL, 0x3FEC08C426725549ULL, 0xBFEC08C426725548ULL, 0x3FDEDC1952EF78D8ULL,
|
|
||||||
0x3FE8FBCCA3EF940DULL, 0x3FE3FED9534556D4ULL, 0xBFE3FED9534556D3ULL, 0x3FE8FBCCA3EF940EULL,
|
|
||||||
0x3FBC3785C79EC2DEULL, 0x3FEFCE15FD6DA67BULL, 0xBFEFCE15FD6DA67BULL, 0x3FBC3785C79EC2E2ULL,
|
|
||||||
0x3FEF7599A3A12077ULL, 0x3FC76DD9DE50BF31ULL, 0xBFC76DD9DE50BF30ULL, 0x3FEF7599A3A12077ULL,
|
|
||||||
0x3FE21A799933EB59ULL, 0x3FEA63091B02FAE2ULL, 0xBFEA63091B02FAE0ULL, 0x3FE21A799933EB5BULL,
|
|
||||||
0x3FEAD2BC9E21D511ULL, 0x3FE1734D63DEDB49ULL, 0xBFE1734D63DEDB47ULL, 0x3FEAD2BC9E21D512ULL,
|
|
||||||
0x3FCA82A025B00451ULL, 0x3FEF4E603B0B2F2DULL, 0xBFEF4E603B0B2F2CULL, 0x3FCA82A025B0045BULL,
|
|
||||||
0x3FEDB6526238A09BULL, 0x3FD7C3A9311DCCE7ULL, 0xBFD7C3A9311DCCE6ULL, 0x3FEDB6526238A09BULL,
|
|
||||||
0x3FD9372A63BC93D7ULL, 0x3FED696173C9E68BULL, 0xBFED696173C9E68BULL, 0x3FD9372A63BC93D8ULL,
|
|
||||||
0x3FE6E74454EAA8AEULL, 0x3FE6591925F0783EULL, 0xBFE6591925F0783DULL, 0x3FE6E74454EAA8AFULL,
|
|
||||||
0x3F8921D1FCDEC78FULL, 0x3FEFFF62169B92DBULL, 0xBFEFFF62169B92DBULL, 0x3F8921D1FCDEC7B3ULL,
|
|
||||||
0x3FEFFFD8858E8A92ULL, 0x3F7921F0FE670071ULL, 0xBF7921F0FE670012ULL, 0x3FEFFFD8858E8A92ULL,
|
|
||||||
0x3FE67CF78491AF10ULL, 0x3FE6C40D73C18275ULL, 0xBFE6C40D73C18276ULL, 0x3FE67CF78491AF0FULL,
|
|
||||||
0x3FED7D0B02B8ECFAULL, 0x3FD8DAA52EC8A4AFULL, 0xBFD8DAA52EC8A4AEULL, 0x3FED7D0B02B8ECFAULL,
|
|
||||||
0x3FD820E3B04EAAC5ULL, 0x3FEDA383A9668987ULL, 0xBFEDA383A9668988ULL, 0x3FD820E3B04EAAC2ULL,
|
|
||||||
0x3FEF58A2B1789E84ULL, 0x3FC9BDCBF2DC4366ULL, 0xBFC9BDCBF2DC4363ULL, 0x3FEF58A2B1789E84ULL,
|
|
||||||
0x3FE19D5A09F2B9B8ULL, 0x3FEAB7325916C0D4ULL, 0xBFEAB7325916C0D4ULL, 0x3FE19D5A09F2B9B9ULL,
|
|
||||||
0x3FEA7F58529FE69DULL, 0x3FE1F0F08BBC861BULL, 0xBFE1F0F08BBC861AULL, 0x3FEA7F58529FE69DULL,
|
|
||||||
0x3FC83366E89C64C8ULL, 0x3FEF6C3F7DF5BBB7ULL, 0xBFEF6C3F7DF5BBB7ULL, 0x3FC83366E89C64CBULL,
|
|
||||||
0x3FEFD37914220B84ULL, 0x3FBAA7B724495C04ULL, 0xBFBAA7B724495C05ULL, 0x3FEFD37914220B84ULL,
|
|
||||||
0x3FE425FF178E6BB2ULL, 0x3FE8DC45331698CCULL, 0xBFE8DC45331698CBULL, 0x3FE425FF178E6BB3ULL,
|
|
||||||
0x3FEC20DE3FA971B0ULL, 0x3FDE83E0EAF85113ULL, 0xBFDE83E0EAF85110ULL, 0x3FEC20DE3FA971B0ULL,
|
|
||||||
0x3FD233BBABC3BB71ULL, 0x3FEEADB2E8E7A88EULL, 0xBFEEADB2E8E7A88DULL, 0x3FD233BBABC3BB76ULL,
|
|
||||||
0x3FEE9084361DF7F3ULL, 0x3FD2F422DAEC0386ULL, 0xBFD2F422DAEC0387ULL, 0x3FEE9084361DF7F2ULL,
|
|
||||||
0x3FDDD28F1481CC57ULL, 0x3FEC5042012B6907ULL, 0xBFEC5042012B6907ULL, 0x3FDDD28F1481CC58ULL,
|
|
||||||
0x3FE89C7E9A4DD4ABULL, 0x3FE473B51B987347ULL, 0xBFE473B51B987347ULL, 0x3FE89C7E9A4DD4AAULL,
|
|
||||||
0x3FB787586A5D5B1FULL, 0x3FEFDD539FF1F456ULL, 0xBFEFDD539FF1F456ULL, 0x3FB787586A5D5B23ULL,
|
|
||||||
0x3FEFF3830F8D575CULL, 0x3FAC428D12C0D7E2ULL, 0xBFAC428D12C0D7DFULL, 0x3FEFF3830F8D575CULL,
|
|
||||||
0x3FE5581038975137ULL, 0x3FE7D7836CC33DB2ULL, 0xBFE7D7836CC33DB2ULL, 0x3FE5581038975138ULL,
|
|
||||||
0x3FECD7D9898B32F6ULL, 0x3FDBB7CF2304BD01ULL, 0xBFDBB7CF2304BD00ULL, 0x3FECD7D9898B32F6ULL,
|
|
||||||
0x3FD530D880AF3C24ULL, 0x3FEE31EAE870CE25ULL, 0xBFEE31EAE870CE25ULL, 0x3FD530D880AF3C25ULL,
|
|
||||||
0x3FEEFE220C0B95EDULL, 0x3FCFDCDC1ADFEDF8ULL, 0xBFCFDCDC1ADFEDF7ULL, 0x3FEEFE220C0B95EDULL,
|
|
||||||
0x3FE0485626AE221AULL, 0x3FEB8C38D27504E9ULL, 0xBFEB8C38D27504E7ULL, 0x3FE0485626AE221DULL,
|
|
||||||
0x3FE995CF2ED80D22ULL, 0x3FE338400D0C8E57ULL, 0xBFE338400D0C8E55ULL, 0x3FE995CF2ED80D24ULL,
|
|
||||||
0x3FC20116D4EC7BCFULL, 0x3FEFAE8E8E46CFBBULL, 0xBFEFAE8E8E46CFBAULL, 0x3FC20116D4EC7BDAULL,
|
|
||||||
0x3FEF9FCE55ADB2C8ULL, 0x3FC38EDBB0CD8D14ULL, 0xBFC38EDBB0CD8D0FULL, 0x3FEF9FCE55ADB2C8ULL,
|
|
||||||
0x3FE2E780E3E8EA17ULL, 0x3FE9D1B1F5EA80D5ULL, 0xBFE9D1B1F5EA80D6ULL, 0x3FE2E780E3E8EA16ULL,
|
|
||||||
0x3FEB5889FE921405ULL, 0x3FE09E907417C5E1ULL, 0xBFE09E907417C5E1ULL, 0x3FEB5889FE921405ULL,
|
|
||||||
0x3FCE56CA1E101A20ULL, 0x3FEF168F53F7205DULL, 0xBFEF168F53F7205DULL, 0x3FCE56CA1E101A1AULL,
|
|
||||||
0x3FEE100CCA2980ACULL, 0x3FD5EE27379EA693ULL, 0xBFD5EE27379EA691ULL, 0x3FEE100CCA2980ACULL,
|
|
||||||
0x3FDB020D6C7F400BULL, 0x3FED02D4FEB2BD92ULL, 0xBFED02D4FEB2BD92ULL, 0x3FDB020D6C7F400CULL,
|
|
||||||
0x3FE79400574F55E5ULL, 0x3FE5A28D2A5D7250ULL, 0xBFE5A28D2A5D724FULL, 0x3FE79400574F55E6ULL,
|
|
||||||
0x3FA5FC00D290CD57ULL, 0x3FEFF871DADB81DFULL, 0xBFEFF871DADB81DFULL, 0x3FA5FC00D290CD60ULL,
|
|
||||||
0x3FEFFC251DF1D3F8ULL, 0x3F9F693731D1CF01ULL, 0xBF9F693731D1CED1ULL, 0x3FEFFC251DF1D3F8ULL,
|
|
||||||
0x3FE5EC3495837074ULL, 0x3FE74F948DA8D28DULL, 0xBFE74F948DA8D28DULL, 0x3FE5EC3495837074ULL,
|
|
||||||
0x3FED2CB220E0EF9FULL, 0x3FDA4B4127DEA1E4ULL, 0xBFDA4B4127DEA1E2ULL, 0x3FED2CB220E0EF9FULL,
|
|
||||||
0x3FD6AA9D7DC77E19ULL, 0x3FEDED05F7DE47D9ULL, 0xBFEDED05F7DE47DAULL, 0x3FD6AA9D7DC77E17ULL,
|
|
||||||
0x3FEF2DC9C9089A9DULL, 0x3FCCCF8CB312B286ULL, 0xBFCCCF8CB312B280ULL, 0x3FEF2DC9C9089A9DULL,
|
|
||||||
0x3FE0F426BB2A8E7FULL, 0x3FEB23CD470013B3ULL, 0xBFEB23CD470013B3ULL, 0x3FE0F426BB2A8E7FULL,
|
|
||||||
0x3FEA0C95EABAF937ULL, 0x3FE2960727629CA8ULL, 0xBFE2960727629CA7ULL, 0x3FEA0C95EABAF938ULL,
|
|
||||||
0x3FC51BDF8597C5F8ULL, 0x3FEF8FD5FFAE41DBULL, 0xBFEF8FD5FFAE41DAULL, 0x3FC51BDF8597C5FAULL,
|
|
||||||
0x3FEFBC1617E44186ULL, 0x3FC072A047BA831DULL, 0xBFC072A047BA831BULL, 0x3FEFBC1617E44186ULL,
|
|
||||||
0x3FE3884185DFEB22ULL, 0x3FE958EFE48E6DD7ULL, 0xBFE958EFE48E6DD5ULL, 0x3FE3884185DFEB24ULL,
|
|
||||||
0x3FEBBED7C49380EAULL, 0x3FDFE2F64BE71210ULL, 0xBFDFE2F64BE7120BULL, 0x3FEBBED7C49380EBULL,
|
|
||||||
0x3FD0B0D9CFDBDB91ULL, 0x3FEEE482E25A9DBCULL, 0xBFEEE482E25A9DBBULL, 0x3FD0B0D9CFDBDB96ULL,
|
|
||||||
0x3FEE529F04729FFCULL, 0x3FD472B8A5571054ULL, 0xBFD472B8A5571053ULL, 0x3FEE529F04729FFDULL,
|
|
||||||
0x3FDC6C7F4997000BULL, 0x3FECABC169A0B900ULL, 0xBFECABC169A0B900ULL, 0x3FDC6C7F4997000CULL,
|
|
||||||
0x3FE81A1B33B57ACCULL, 0x3FE50CC09F59A09BULL, 0xBFE50CC09F59A09BULL, 0x3FE81A1B33B57ACCULL,
|
|
||||||
0x3FB1440134D709B6ULL, 0x3FEFED58ECB673C4ULL, 0xBFEFED58ECB673C4ULL, 0x3FB1440134D709BBULL,
|
|
||||||
0x3FEFE5F3AF2E3940ULL, 0x3FB4661179272096ULL, 0xBFB466117927208EULL, 0x3FEFE5F3AF2E3941ULL,
|
|
||||||
0x3FE4C0A145EC0005ULL, 0x3FE85BC51AE958CCULL, 0xBFE85BC51AE958CBULL, 0x3FE4C0A145EC0005ULL,
|
|
||||||
0x3FEC7E8E52233CF3ULL, 0x3FDD2016E8E9DB5BULL, 0xBFDD2016E8E9DB59ULL, 0x3FEC7E8E52233CF4ULL,
|
|
||||||
0x3FD3B3CEFA0414B9ULL, 0x3FEE7227DB6A9744ULL, 0xBFEE7227DB6A9744ULL, 0x3FD3B3CEFA0414BAULL,
|
|
||||||
0x3FEEC9B2D3C3BF84ULL, 0x3FD172A0D7765177ULL, 0xBFD172A0D7765175ULL, 0x3FEEC9B2D3C3BF84ULL,
|
|
||||||
0x3FDF3405963FD069ULL, 0x3FEBF064E15377DDULL, 0xBFEBF064E15377DDULL, 0x3FDF3405963FD066ULL,
|
|
||||||
0x3FE91B166FD49DA2ULL, 0x3FE3D78238C58343ULL, 0xBFE3D78238C58344ULL, 0x3FE91B166FD49DA1ULL,
|
|
||||||
0x3FBDC70ECBAE9FD1ULL, 0x3FEFC8646CFEB721ULL, 0xBFEFC8646CFEB721ULL, 0x3FBDC70ECBAE9FC5ULL,
|
|
||||||
0x3FEF7EA629E63D6EULL, 0x3FC6A81304F64AB2ULL, 0xBFC6A81304F64AB2ULL, 0x3FEF7EA629E63D6EULL,
|
|
||||||
0x3FE243D5FB98AC20ULL, 0x3FEA4678C8119AC8ULL, 0xBFEA4678C8119AC8ULL, 0x3FE243D5FB98AC1FULL,
|
|
||||||
0x3FEAEE04B43C1474ULL, 0x3FE14915AF336CEBULL, 0xBFE14915AF336CEBULL, 0x3FEAEE04B43C1474ULL,
|
|
||||||
0x3FCB4732EF3D6722ULL, 0x3FEF43D085FF92DDULL, 0xBFEF43D085FF92DDULL, 0x3FCB4732EF3D6724ULL,
|
|
||||||
0x3FEDC8D7CB410260ULL, 0x3FD766340F2418F6ULL, 0xBFD766340F2418F6ULL, 0x3FEDC8D7CB410260ULL,
|
|
||||||
0x3FD993716141BDFEULL, 0x3FED556F52E93EB1ULL, 0xBFED556F52E93EB0ULL, 0x3FD993716141BE03ULL,
|
|
||||||
0x3FE70A42B3176D7AULL, 0x3FE63503A31C1BE9ULL, 0xBFE63503A31C1BE7ULL, 0x3FE70A42B3176D7BULL,
|
|
||||||
0x3F92D936BBE30EFDULL, 0x3FEFFE9CB44B51A1ULL, 0xBFEFFE9CB44B51A1ULL, 0x3F92D936BBE30F4EULL,
|
|
||||||
0x3FEFFE9CB44B51A1ULL, 0x3F92D936BBE30EFDULL, 0xBF92D936BBE30ED9ULL, 0x3FEFFE9CB44B51A1ULL,
|
|
||||||
0x3FE63503A31C1BE9ULL, 0x3FE70A42B3176D7AULL, 0xBFE70A42B3176D7AULL, 0x3FE63503A31C1BE9ULL,
|
|
||||||
0x3FED556F52E93EB1ULL, 0x3FD993716141BDFEULL, 0xBFD993716141BDFCULL, 0x3FED556F52E93EB1ULL,
|
|
||||||
0x3FD766340F2418F8ULL, 0x3FEDC8D7CB410260ULL, 0xBFEDC8D7CB410260ULL, 0x3FD766340F2418F5ULL,
|
|
||||||
0x3FEF43D085FF92DDULL, 0x3FCB4732EF3D6722ULL, 0xBFCB4732EF3D671EULL, 0x3FEF43D085FF92DDULL,
|
|
||||||
0x3FE14915AF336CECULL, 0x3FEAEE04B43C1473ULL, 0xBFEAEE04B43C1473ULL, 0x3FE14915AF336CECULL,
|
|
||||||
0x3FEA4678C8119AC8ULL, 0x3FE243D5FB98AC1FULL, 0xBFE243D5FB98AC1EULL, 0x3FEA4678C8119AC9ULL,
|
|
||||||
0x3FC6A81304F64AB6ULL, 0x3FEF7EA629E63D6EULL, 0xBFEF7EA629E63D6EULL, 0x3FC6A81304F64AB9ULL,
|
|
||||||
0x3FEFC8646CFEB721ULL, 0x3FBDC70ECBAE9FC8ULL, 0xBFBDC70ECBAE9FC8ULL, 0x3FEFC8646CFEB721ULL,
|
|
||||||
0x3FE3D78238C58344ULL, 0x3FE91B166FD49DA2ULL, 0xBFE91B166FD49DA0ULL, 0x3FE3D78238C58346ULL,
|
|
||||||
0x3FEBF064E15377DDULL, 0x3FDF3405963FD068ULL, 0xBFDF3405963FD063ULL, 0x3FEBF064E15377DEULL,
|
|
||||||
0x3FD172A0D7765177ULL, 0x3FEEC9B2D3C3BF84ULL, 0xBFEEC9B2D3C3BF83ULL, 0x3FD172A0D776517CULL,
|
|
||||||
0x3FEE7227DB6A9744ULL, 0x3FD3B3CEFA0414B7ULL, 0xBFD3B3CEFA0414B7ULL, 0x3FEE7227DB6A9744ULL,
|
|
||||||
0x3FDD2016E8E9DB5BULL, 0x3FEC7E8E52233CF3ULL, 0xBFEC7E8E52233CF3ULL, 0x3FDD2016E8E9DB5CULL,
|
|
||||||
0x3FE85BC51AE958CCULL, 0x3FE4C0A145EC0004ULL, 0xBFE4C0A145EC0004ULL, 0x3FE85BC51AE958CDULL,
|
|
||||||
0x3FB4661179272096ULL, 0x3FEFE5F3AF2E3940ULL, 0xBFEFE5F3AF2E3940ULL, 0x3FB466117927209BULL,
|
|
||||||
0x3FEFED58ECB673C4ULL, 0x3FB1440134D709B2ULL, 0xBFB1440134D709ADULL, 0x3FEFED58ECB673C4ULL,
|
|
||||||
0x3FE50CC09F59A09BULL, 0x3FE81A1B33B57ACBULL, 0xBFE81A1B33B57ACBULL, 0x3FE50CC09F59A09CULL,
|
|
||||||
0x3FECABC169A0B901ULL, 0x3FDC6C7F4997000AULL, 0xBFDC6C7F49970009ULL, 0x3FECABC169A0B901ULL,
|
|
||||||
0x3FD472B8A5571055ULL, 0x3FEE529F04729FFCULL, 0xBFEE529F04729FFCULL, 0x3FD472B8A5571056ULL,
|
|
||||||
0x3FEEE482E25A9DBCULL, 0x3FD0B0D9CFDBDB90ULL, 0xBFD0B0D9CFDBDB8FULL, 0x3FEEE482E25A9DBCULL,
|
|
||||||
0x3FDFE2F64BE71210ULL, 0x3FEBBED7C49380EAULL, 0xBFEBBED7C49380EBULL, 0x3FDFE2F64BE7120EULL,
|
|
||||||
0x3FE958EFE48E6DD7ULL, 0x3FE3884185DFEB22ULL, 0xBFE3884185DFEB23ULL, 0x3FE958EFE48E6DD6ULL,
|
|
||||||
0x3FC072A047BA831FULL, 0x3FEFBC1617E44186ULL, 0xBFEFBC1617E44186ULL, 0x3FC072A047BA831AULL,
|
|
||||||
0x3FEF8FD5FFAE41DBULL, 0x3FC51BDF8597C5F2ULL, 0xBFC51BDF8597C5F3ULL, 0x3FEF8FD5FFAE41DBULL,
|
|
||||||
0x3FE2960727629CA8ULL, 0x3FEA0C95EABAF936ULL, 0xBFEA0C95EABAF937ULL, 0x3FE2960727629CA8ULL,
|
|
||||||
0x3FEB23CD470013B4ULL, 0x3FE0F426BB2A8E7DULL, 0xBFE0F426BB2A8E7EULL, 0x3FEB23CD470013B4ULL,
|
|
||||||
0x3FCCCF8CB312B284ULL, 0x3FEF2DC9C9089A9DULL, 0xBFEF2DC9C9089A9DULL, 0x3FCCCF8CB312B286ULL,
|
|
||||||
0x3FEDED05F7DE47DAULL, 0x3FD6AA9D7DC77E16ULL, 0xBFD6AA9D7DC77E17ULL, 0x3FEDED05F7DE47DAULL,
|
|
||||||
0x3FDA4B4127DEA1E4ULL, 0x3FED2CB220E0EF9FULL, 0xBFED2CB220E0EF9EULL, 0x3FDA4B4127DEA1E8ULL,
|
|
||||||
0x3FE74F948DA8D28DULL, 0x3FE5EC3495837074ULL, 0xBFE5EC3495837073ULL, 0x3FE74F948DA8D28EULL,
|
|
||||||
0x3F9F693731D1CEF4ULL, 0x3FEFFC251DF1D3F8ULL, 0xBFEFFC251DF1D3F8ULL, 0x3F9F693731D1CF46ULL,
|
|
||||||
0x3FEFF871DADB81DFULL, 0x3FA5FC00D290CD43ULL, 0xBFA5FC00D290CD45ULL, 0x3FEFF871DADB81DFULL,
|
|
||||||
0x3FE5A28D2A5D7251ULL, 0x3FE79400574F55E4ULL, 0xBFE79400574F55E5ULL, 0x3FE5A28D2A5D7250ULL,
|
|
||||||
0x3FED02D4FEB2BD92ULL, 0x3FDB020D6C7F4009ULL, 0xBFDB020D6C7F4009ULL, 0x3FED02D4FEB2BD92ULL,
|
|
||||||
0x3FD5EE27379EA693ULL, 0x3FEE100CCA2980ACULL, 0xBFEE100CCA2980ACULL, 0x3FD5EE27379EA694ULL,
|
|
||||||
0x3FEF168F53F7205DULL, 0x3FCE56CA1E101A1BULL, 0xBFCE56CA1E101A1CULL, 0x3FEF168F53F7205DULL,
|
|
||||||
0x3FE09E907417C5E0ULL, 0x3FEB5889FE921405ULL, 0xBFEB5889FE921404ULL, 0x3FE09E907417C5E2ULL,
|
|
||||||
0x3FE9D1B1F5EA80D6ULL, 0x3FE2E780E3E8EA16ULL, 0xBFE2E780E3E8EA15ULL, 0x3FE9D1B1F5EA80D7ULL,
|
|
||||||
0x3FC38EDBB0CD8D13ULL, 0x3FEF9FCE55ADB2C8ULL, 0xBFEF9FCE55ADB2C8ULL, 0x3FC38EDBB0CD8D1DULL,
|
|
||||||
0x3FEFAE8E8E46CFBBULL, 0x3FC20116D4EC7BCEULL, 0xBFC20116D4EC7BCBULL, 0x3FEFAE8E8E46CFBBULL,
|
|
||||||
0x3FE338400D0C8E57ULL, 0x3FE995CF2ED80D22ULL, 0xBFE995CF2ED80D23ULL, 0x3FE338400D0C8E56ULL,
|
|
||||||
0x3FEB8C38D27504E9ULL, 0x3FE0485626AE221AULL, 0xBFE0485626AE221BULL, 0x3FEB8C38D27504E8ULL,
|
|
||||||
0x3FCFDCDC1ADFEDFCULL, 0x3FEEFE220C0B95ECULL, 0xBFEEFE220C0B95EDULL, 0x3FCFDCDC1ADFEDF6ULL,
|
|
||||||
0x3FEE31EAE870CE25ULL, 0x3FD530D880AF3C24ULL, 0xBFD530D880AF3C22ULL, 0x3FEE31EAE870CE25ULL,
|
|
||||||
0x3FDBB7CF2304BD02ULL, 0x3FECD7D9898B32F6ULL, 0xBFECD7D9898B32F5ULL, 0x3FDBB7CF2304BD03ULL,
|
|
||||||
0x3FE7D7836CC33DB3ULL, 0x3FE5581038975137ULL, 0xBFE5581038975136ULL, 0x3FE7D7836CC33DB3ULL,
|
|
||||||
0x3FAC428D12C0D7F0ULL, 0x3FEFF3830F8D575CULL, 0xBFEFF3830F8D575CULL, 0x3FAC428D12C0D7F9ULL,
|
|
||||||
0x3FEFDD539FF1F456ULL, 0x3FB787586A5D5B21ULL, 0xBFB787586A5D5B16ULL, 0x3FEFDD539FF1F456ULL,
|
|
||||||
0x3FE473B51B987347ULL, 0x3FE89C7E9A4DD4AAULL, 0xBFE89C7E9A4DD4A9ULL, 0x3FE473B51B987348ULL,
|
|
||||||
0x3FEC5042012B6907ULL, 0x3FDDD28F1481CC58ULL, 0xBFDDD28F1481CC55ULL, 0x3FEC5042012B6908ULL,
|
|
||||||
0x3FD2F422DAEC0389ULL, 0x3FEE9084361DF7F2ULL, 0xBFEE9084361DF7F2ULL, 0x3FD2F422DAEC038AULL,
|
|
||||||
0x3FEEADB2E8E7A88EULL, 0x3FD233BBABC3BB72ULL, 0xBFD233BBABC3BB6FULL, 0x3FEEADB2E8E7A88EULL,
|
|
||||||
0x3FDE83E0EAF85116ULL, 0x3FEC20DE3FA971AFULL, 0xBFEC20DE3FA971B0ULL, 0x3FDE83E0EAF85113ULL,
|
|
||||||
0x3FE8DC45331698CCULL, 0x3FE425FF178E6BB1ULL, 0xBFE425FF178E6BB2ULL, 0x3FE8DC45331698CCULL,
|
|
||||||
0x3FBAA7B724495C0EULL, 0x3FEFD37914220B84ULL, 0xBFEFD37914220B84ULL, 0x3FBAA7B724495C03ULL,
|
|
||||||
0x3FEF6C3F7DF5BBB7ULL, 0x3FC83366E89C64C5ULL, 0xBFC83366E89C64C4ULL, 0x3FEF6C3F7DF5BBB7ULL,
|
|
||||||
0x3FE1F0F08BBC861BULL, 0x3FEA7F58529FE69DULL, 0xBFEA7F58529FE69CULL, 0x3FE1F0F08BBC861CULL,
|
|
||||||
0x3FEAB7325916C0D4ULL, 0x3FE19D5A09F2B9B8ULL, 0xBFE19D5A09F2B9B7ULL, 0x3FEAB7325916C0D5ULL,
|
|
||||||
0x3FC9BDCBF2DC4368ULL, 0x3FEF58A2B1789E84ULL, 0xBFEF58A2B1789E84ULL, 0x3FC9BDCBF2DC436AULL,
|
|
||||||
0x3FEDA383A9668988ULL, 0x3FD820E3B04EAAC4ULL, 0xBFD820E3B04EAAC3ULL, 0x3FEDA383A9668988ULL,
|
|
||||||
0x3FD8DAA52EC8A4B0ULL, 0x3FED7D0B02B8ECF9ULL, 0xBFED7D0B02B8ECF8ULL, 0x3FD8DAA52EC8A4B5ULL,
|
|
||||||
0x3FE6C40D73C18275ULL, 0x3FE67CF78491AF10ULL, 0xBFE67CF78491AF0EULL, 0x3FE6C40D73C18277ULL,
|
|
||||||
0x3F7921F0FE67009FULL, 0x3FEFFFD8858E8A92ULL, 0xBFEFFFD8858E8A92ULL, 0x3F7921F0FE6701E6ULL,
|
|
||||||
0x3FEFFFF621621D02ULL, 0x3F6921F8BECCA4BAULL, 0xBF6921F8BECCA515ULL, 0x3FEFFFF621621D02ULL,
|
|
||||||
0x3FE68ED1EAA19C72ULL, 0x3FE6B25CED2FE29BULL, 0xBFE6B25CED2FE29AULL, 0x3FE68ED1EAA19C73ULL,
|
|
||||||
0x3FED86C48445A450ULL, 0x3FD8AC4B86D5ED44ULL, 0xBFD8AC4B86D5ED45ULL, 0x3FED86C48445A44FULL,
|
|
||||||
0x3FD84F6AAAF3903EULL, 0x3FED9A00DD8B3D46ULL, 0xBFED9A00DD8B3D45ULL, 0x3FD84F6AAAF39043ULL,
|
|
||||||
0x3FEF5DA6ED43685DULL, 0x3FC95B49E9B62AF9ULL, 0xBFC95B49E9B62AFBULL, 0x3FEF5DA6ED43685DULL,
|
|
||||||
0x3FE1B250171373BFULL, 0x3FEAA9547A2CB98EULL, 0xBFEAA9547A2CB98EULL, 0x3FE1B250171373BFULL,
|
|
||||||
0x3FEA8D676E545AD2ULL, 0x3FE1DC1B64DC4872ULL, 0xBFE1DC1B64DC4872ULL, 0x3FEA8D676E545AD2ULL,
|
|
||||||
0x3FC8961727C41802ULL, 0x3FEF677556883CEEULL, 0xBFEF677556883CEEULL, 0x3FC8961727C41805ULL,
|
|
||||||
0x3FEFD60D2DA75C9EULL, 0x3FB9DFB6EB24A85CULL, 0xBFB9DFB6EB24A857ULL, 0x3FEFD60D2DA75C9EULL,
|
|
||||||
0x3FE4397F5B2A4380ULL, 0x3FE8CC6A75184654ULL, 0xBFE8CC6A75184654ULL, 0x3FE4397F5B2A4380ULL,
|
|
||||||
0x3FEC2CD14931E3F1ULL, 0x3FDE57A86D3CD824ULL, 0xBFDE57A86D3CD823ULL, 0x3FEC2CD14931E3F2ULL,
|
|
||||||
0x3FD263E6995554BBULL, 0x3FEEA68393E65800ULL, 0xBFEEA68393E65800ULL, 0x3FD263E6995554BCULL,
|
|
||||||
0x3FEE97EC36016B30ULL, 0x3FD2C41A4E954520ULL, 0xBFD2C41A4E95451FULL, 0x3FEE97EC36016B31ULL,
|
|
||||||
0x3FDDFEFF66A941DEULL, 0x3FEC44833141C004ULL, 0xBFEC44833141C005ULL, 0x3FDDFEFF66A941DCULL,
|
|
||||||
0x3FE8AC871EDE1D88ULL, 0x3FE4605A692B32A2ULL, 0xBFE4605A692B32A3ULL, 0x3FE8AC871EDE1D87ULL,
|
|
||||||
0x3FB84F8712C130A5ULL, 0x3FEFDAFA7514538CULL, 0xBFEFDAFA7514538CULL, 0x3FB84F8712C1309AULL,
|
|
||||||
0x3FEFF4DC54B1BED3ULL, 0x3FAAB101BD5F8317ULL, 0xBFAAB101BD5F8304ULL, 0x3FEFF4DC54B1BED3ULL,
|
|
||||||
0x3FE56AC35197649EULL, 0x3FE7C6B89CE2D333ULL, 0xBFE7C6B89CE2D333ULL, 0x3FE56AC35197649EULL,
|
|
||||||
0x3FECE2B32799A060ULL, 0x3FDB8A7814FD5693ULL, 0xBFDB8A7814FD5695ULL, 0x3FECE2B32799A060ULL,
|
|
||||||
0x3FD5604012F467B6ULL, 0x3FEE298F4439197AULL, 0xBFEE298F4439197AULL, 0x3FD5604012F467B4ULL,
|
|
||||||
0x3FEF045A14CF738CULL, 0x3FCF7B7480BD3801ULL, 0xBFCF7B7480BD37FDULL, 0x3FEF045A14CF738CULL,
|
|
||||||
0x3FE05DF3EC31B8B8ULL, 0x3FEB7F6686E792E9ULL, 0xBFEB7F6686E792E9ULL, 0x3FE05DF3EC31B8B8ULL,
|
|
||||||
0x3FE9A4DFA42B06B2ULL, 0x3FE32421EC49A61FULL, 0xBFE32421EC49A61EULL, 0x3FE9A4DFA42B06B3ULL,
|
|
||||||
0x3FC264994DFD340EULL, 0x3FEFAAFBCB0CFDDBULL, 0xBFEFAAFBCB0CFDDBULL, 0x3FC264994DFD3410ULL,
|
|
||||||
0x3FEFA39BAC7A1791ULL, 0x3FC32B7BF94516A7ULL, 0xBFC32B7BF94516A7ULL, 0x3FEFA39BAC7A1791ULL,
|
|
||||||
0x3FE2FBC24B441015ULL, 0x3FE9C2D110F075C3ULL, 0xBFE9C2D110F075C1ULL, 0x3FE2FBC24B441017ULL,
|
|
||||||
0x3FEB658F14FDBC47ULL, 0x3FE089112032B08CULL, 0xBFE089112032B08AULL, 0x3FEB658F14FDBC48ULL,
|
|
||||||
0x3FCEB86B462DE348ULL, 0x3FEF1090BC898F5FULL, 0xBFEF1090BC898F5EULL, 0x3FCEB86B462DE352ULL,
|
|
||||||
0x3FEE18A02FDC66D9ULL, 0x3FD5BEE78B9DB3B6ULL, 0xBFD5BEE78B9DB3B6ULL, 0x3FEE18A02FDC66D9ULL,
|
|
||||||
0x3FDB2F971DB31972ULL, 0x3FECF830E8CE467BULL, 0xBFECF830E8CE467AULL, 0x3FDB2F971DB31973ULL,
|
|
||||||
0x3FE7A4F707BF97D2ULL, 0x3FE59001D5F723DFULL, 0xBFE59001D5F723DFULL, 0x3FE7A4F707BF97D3ULL,
|
|
||||||
0x3FA78DBAA5874688ULL, 0x3FEFF753BB1B9164ULL, 0xBFEFF753BB1B9164ULL, 0x3FA78DBAA5874691ULL,
|
|
||||||
0x3FEFFCE09CE2A679ULL, 0x3F9C454F4CE53B1CULL, 0xBF9C454F4CE53B10ULL, 0x3FEFFCE09CE2A679ULL,
|
|
||||||
0x3FE5FE7CBDE56A10ULL, 0x3FE73E558E079942ULL, 0xBFE73E558E079940ULL, 0x3FE5FE7CBDE56A11ULL,
|
|
||||||
0x3FED36FC7BCBFBDCULL, 0x3FDA1D6543B50AC0ULL, 0xBFDA1D6543B50ABFULL, 0x3FED36FC7BCBFBDCULL,
|
|
||||||
0x3FD6D998638A0CB6ULL, 0x3FEDE4160F6D8D81ULL, 0xBFEDE4160F6D8D80ULL, 0x3FD6D998638A0CBBULL,
|
|
||||||
0x3FEF33685A3AAEF0ULL, 0x3FCC6D90535D74DCULL, 0xBFCC6D90535D74DBULL, 0x3FEF33685A3AAEF0ULL,
|
|
||||||
0x3FE1097248D0A957ULL, 0x3FEB16742A4CA2F4ULL, 0xBFEB16742A4CA2F4ULL, 0x3FE1097248D0A957ULL,
|
|
||||||
0x3FEA1B26D2C0A75EULL, 0x3FE2818BEF4D3CBAULL, 0xBFE2818BEF4D3CB9ULL, 0x3FEA1B26D2C0A75EULL,
|
|
||||||
0x3FC57F008654CBE0ULL, 0x3FEF8BA737CB4B77ULL, 0xBFEF8BA737CB4B77ULL, 0x3FC57F008654CBE2ULL,
|
|
||||||
0x3FEFBF470F0A8D88ULL, 0x3FC00EE8AD6FB85BULL, 0xBFC00EE8AD6FB855ULL, 0x3FEFBF470F0A8D88ULL,
|
|
||||||
0x3FE39C23E3D63029ULL, 0x3FE94990E3AC4A6CULL, 0xBFE94990E3AC4A6BULL, 0x3FE39C23E3D6302AULL,
|
|
||||||
0x3FEBCB54CB0D2327ULL, 0x3FDFB7575C24D2DEULL, 0xBFDFB7575C24D2DBULL, 0x3FEBCB54CB0D2328ULL,
|
|
||||||
0x3FD0E15B4E1749D0ULL, 0x3FEEDDEB6A078650ULL, 0xBFEEDDEB6A078650ULL, 0x3FD0E15B4E1749D1ULL,
|
|
||||||
0x3FEE5A9D550467D3ULL, 0x3FD44310DC8936F0ULL, 0xBFD44310DC8936EEULL, 0x3FEE5A9D550467D4ULL,
|
|
||||||
0x3FDC997FC386538BULL, 0x3FECA08F19B9C448ULL, 0xBFECA08F19B9C449ULL, 0x3FDC997FC3865388ULL,
|
|
||||||
0x3FE82A9C13F545FFULL, 0x3FE4F9CC25CCA486ULL, 0xBFE4F9CC25CCA487ULL, 0x3FE82A9C13F545FFULL,
|
|
||||||
0x3FB20C9674ED4457ULL, 0x3FEFEB9D2530410FULL, 0xBFEFEB9D2530410FULL, 0x3FB20C9674ED444CULL,
|
|
||||||
0x3FEFE7EA85482D60ULL, 0x3FB39D9F12C5A299ULL, 0xBFB39D9F12C5A29AULL, 0x3FEFE7EA85482D60ULL,
|
|
||||||
0x3FE4D3BC6D589F80ULL, 0x3FE84B7111AF83F9ULL, 0xBFE84B7111AF83FAULL, 0x3FE4D3BC6D589F80ULL,
|
|
||||||
0x3FEC89F587029C13ULL, 0x3FDCF34BAEE1CD21ULL, 0xBFDCF34BAEE1CD21ULL, 0x3FEC89F587029C13ULL,
|
|
||||||
0x3FD3E39BE96EC271ULL, 0x3FEE6A61C55D53A7ULL, 0xBFEE6A61C55D53A7ULL, 0x3FD3E39BE96EC272ULL,
|
|
||||||
0x3FEED0835E999009ULL, 0x3FD1423EEFC69378ULL, 0xBFD1423EEFC69378ULL, 0x3FEED0835E999009ULL,
|
|
||||||
0x3FDF5FDEE656CDA2ULL, 0x3FEBE41B611154C1ULL, 0xBFEBE41B611154BFULL, 0x3FDF5FDEE656CDA7ULL,
|
|
||||||
0x3FE92AA41FC5A815ULL, 0x3FE3C3C44981C517ULL, 0xBFE3C3C44981C516ULL, 0x3FE92AA41FC5A816ULL,
|
|
||||||
0x3FBE8EB7FDE4AA3EULL, 0x3FEFC56E3B7D9AF6ULL, 0xBFEFC56E3B7D9AF6ULL, 0x3FBE8EB7FDE4AA52ULL,
|
|
||||||
0x3FEF830F4A40C60CULL, 0x3FC6451A831D830DULL, 0xBFC6451A831D8309ULL, 0x3FEF830F4A40C60CULL,
|
|
||||||
0x3FE258734CBB7111ULL, 0x3FEA38184A593BC5ULL, 0xBFEA38184A593BC6ULL, 0x3FE258734CBB710FULL,
|
|
||||||
0x3FEAFB8FD89F57B6ULL, 0x3FE133E9CFEE254EULL, 0xBFE133E9CFEE2550ULL, 0x3FEAFB8FD89F57B6ULL,
|
|
||||||
0x3FCBA96334F15DB0ULL, 0x3FEF3E6BBC1BBC65ULL, 0xBFEF3E6BBC1BBC65ULL, 0x3FCBA96334F15DAAULL,
|
|
||||||
0x3FEDD1FEF38A915AULL, 0x3FD73763C9261092ULL, 0xBFD73763C9261090ULL, 0x3FEDD1FEF38A915AULL,
|
|
||||||
0x3FD9C17D440DF9F4ULL, 0x3FED4B5B1B187524ULL, 0xBFED4B5B1B187523ULL, 0x3FD9C17D440DF9F5ULL,
|
|
||||||
0x3FE71BAC960E41BFULL, 0x3FE622E44FEC22FFULL, 0xBFE622E44FEC22FEULL, 0x3FE71BAC960E41C0ULL,
|
|
||||||
0x3F95FD4D21FAB242ULL, 0x3FEFFE1C6870CB77ULL, 0xBFEFFE1C6870CB77ULL, 0x3F95FD4D21FAB254ULL,
|
|
||||||
0x3FEFFF0943C53BD1ULL, 0x3F8F6A296AB997CAULL, 0xBF8F6A296AB997C9ULL, 0x3FEFFF0943C53BD1ULL,
|
|
||||||
0x3FE64715437F535BULL, 0x3FE6F8CA99C95B75ULL, 0xBFE6F8CA99C95B74ULL, 0x3FE64715437F535CULL,
|
|
||||||
0x3FED5F7172888A7FULL, 0x3FD96555B7AB948FULL, 0xBFD96555B7AB948FULL, 0x3FED5F7172888A7FULL,
|
|
||||||
0x3FD794F5E613DFAEULL, 0x3FEDBF9E4395759BULL, 0xBFEDBF9E4395759AULL, 0x3FD794F5E613DFB3ULL,
|
|
||||||
0x3FEF492206BCABB4ULL, 0x3FCAE4F1D5F3B9ABULL, 0xBFCAE4F1D5F3B9ABULL, 0x3FEF492206BCABB4ULL,
|
|
||||||
0x3FE15E36E4DBE2BDULL, 0x3FEAE068F345ECEEULL, 0xBFEAE068F345ECEFULL, 0x3FE15E36E4DBE2BCULL,
|
|
||||||
0x3FEA54C91090F524ULL, 0x3FE22F2D662C13E1ULL, 0xBFE22F2D662C13E1ULL, 0x3FEA54C91090F523ULL,
|
|
||||||
0x3FC70AFD8D08C4FFULL, 0x3FEF7A299C1A322AULL, 0xBFEF7A299C1A322AULL, 0x3FC70AFD8D08C501ULL,
|
|
||||||
0x3FEFCB4703914354ULL, 0x3FBCFF533B307DC1ULL, 0xBFBCFF533B307DB9ULL, 0x3FEFCB4703914354ULL,
|
|
||||||
0x3FE3EB33EABE0681ULL, 0x3FE90B7943575EFEULL, 0xBFE90B7943575EFDULL, 0x3FE3EB33EABE0681ULL,
|
|
||||||
0x3FEBFC9D25A1B147ULL, 0x3FDF081906BFF7FDULL, 0xBFDF081906BFF7FCULL, 0x3FEBFC9D25A1B148ULL,
|
|
||||||
0x3FD1A2F7FBE8F245ULL, 0x3FEEC2CF4B1AF6B2ULL, 0xBFEEC2CF4B1AF6B2ULL, 0x3FD1A2F7FBE8F246ULL,
|
|
||||||
0x3FEE79DB29A5165AULL, 0x3FD383F5E353B6AAULL, 0xBFD383F5E353B6A8ULL, 0x3FEE79DB29A5165AULL,
|
|
||||||
0x3FDD4CD02BA8609EULL, 0x3FEC7315899EAAD7ULL, 0xBFEC7315899EAAD7ULL, 0x3FDD4CD02BA8609CULL,
|
|
||||||
0x3FE86C0A1D9AA195ULL, 0x3FE4AD79516722F0ULL, 0xBFE4AD79516722F1ULL, 0x3FE86C0A1D9AA195ULL,
|
|
||||||
0x3FB52E774A4D4D12ULL, 0x3FEFE3E92BE9D886ULL, 0xBFEFE3E92BE9D886ULL, 0x3FB52E774A4D4D06ULL,
|
|
||||||
0x3FEFEF0102826191ULL, 0x3FB07B614E463064ULL, 0xBFB07B614E463057ULL, 0x3FEFEF0102826191ULL,
|
|
||||||
0x3FE51FA81CD99AA6ULL, 0x3FE8098B756E52FAULL, 0xBFE8098B756E52FBULL, 0x3FE51FA81CD99AA6ULL,
|
|
||||||
0x3FECB6E20A00DA99ULL, 0x3FDC3F6D47263129ULL, 0xBFDC3F6D4726312AULL, 0x3FECB6E20A00DA99ULL,
|
|
||||||
0x3FD4A253D11B82F6ULL, 0x3FEE4A8DFF81CE5EULL, 0xBFEE4A8DFF81CE5EULL, 0x3FD4A253D11B82F3ULL,
|
|
||||||
0x3FEEEB074C50A544ULL, 0x3FD0804E05EB661EULL, 0xBFD0804E05EB661BULL, 0x3FEEEB074C50A545ULL,
|
|
||||||
0x3FE00740C82B82E2ULL, 0x3FEBB249A0B6C40CULL, 0xBFEBB249A0B6C40CULL, 0x3FE00740C82B82E2ULL,
|
|
||||||
0x3FE9683F42BD7FE1ULL, 0x3FE374531B817F8DULL, 0xBFE374531B817F8CULL, 0x3FE9683F42BD7FE2ULL,
|
|
||||||
0x3FC0D64DBCB2678CULL, 0x3FEFB8D18D66ADB7ULL, 0xBFEFB8D18D66ADB7ULL, 0x3FC0D64DBCB2678EULL,
|
|
||||||
0x3FEF93F14F85AC08ULL, 0x3FC4B8B17F79FA88ULL, 0xBFC4B8B17F79FA86ULL, 0x3FEF93F14F85AC08ULL,
|
|
||||||
0x3FE2AA76E87AEB58ULL, 0x3FE9FDF4F13149DEULL, 0xBFE9FDF4F13149DDULL, 0x3FE2AA76E87AEB5AULL,
|
|
||||||
0x3FEB3115A5F37BF4ULL, 0x3FE0DED0B84BC4B5ULL, 0xBFE0DED0B84BC4B3ULL, 0x3FEB3115A5F37BF5ULL,
|
|
||||||
0x3FCD31774D2CBDF0ULL, 0x3FEF2817FC4609CDULL, 0xBFEF2817FC4609CDULL, 0x3FCD31774D2CBDFAULL,
|
|
||||||
0x3FEDF5E36A9BA59CULL, 0x3FD67B949CAD63CAULL, 0xBFD67B949CAD63C9ULL, 0x3FEDF5E36A9BA59CULL,
|
|
||||||
0x3FDA790CD3DBF31BULL, 0x3FED2255C6E5A4E0ULL, 0xBFED2255C6E5A4E0ULL, 0x3FDA790CD3DBF31CULL,
|
|
||||||
0x3FE760C52C304764ULL, 0x3FE5D9DEE73E345CULL, 0xBFE5D9DEE73E345BULL, 0x3FE760C52C304764ULL,
|
|
||||||
0x3FA14685DB42C187ULL, 0x3FEFFB55E425FDAEULL, 0xBFEFFB55E425FDAEULL, 0x3FA14685DB42C190ULL,
|
|
||||||
0x3FEFF97C4208C014ULL, 0x3FA46A396FF86179ULL, 0xBFA46A396FF8616DULL, 0x3FEFF97C4208C014ULL,
|
|
||||||
0x3FE5B50B264F7449ULL, 0x3FE782FB1B90B35AULL, 0xBFE782FB1B90B35BULL, 0x3FE5B50B264F7447ULL,
|
|
||||||
0x3FED0D672F59D2B9ULL, 0x3FDAD473125CDC08ULL, 0xBFDAD473125CDC0BULL, 0x3FED0D672F59D2B8ULL,
|
|
||||||
0x3FD61D595C88C204ULL, 0x3FEE0766D9280F54ULL, 0xBFEE0766D9280F55ULL, 0x3FD61D595C88C201ULL,
|
|
||||||
0x3FEF1C7ABE284708ULL, 0x3FCDF5163F01099AULL, 0xBFCDF5163F010996ULL, 0x3FEF1C7ABE284709ULL,
|
|
||||||
0x3FE0B405878F85ECULL, 0x3FEB4B7409DE7925ULL, 0xBFEB4B7409DE7925ULL, 0x3FE0B405878F85EDULL,
|
|
||||||
0x3FE9E082EDB42472ULL, 0x3FE2D333D34E9BB7ULL, 0xBFE2D333D34E9BB7ULL, 0x3FE9E082EDB42473ULL,
|
|
||||||
0x3FC3F22F57DB4896ULL, 0x3FEF9BED7CFBDE29ULL, 0xBFEF9BED7CFBDE29ULL, 0x3FC3F22F57DB4898ULL,
|
|
||||||
0x3FEFB20DC681D54DULL, 0x3FC19D8940BE24E7ULL, 0xBFC19D8940BE24E8ULL, 0x3FEFB20DC681D54CULL,
|
|
||||||
0x3FE34C5252C14DE2ULL, 0x3FE986AEF1457593ULL, 0xBFE986AEF1457592ULL, 0x3FE34C5252C14DE3ULL,
|
|
||||||
0x3FEB98FA1FD9155FULL, 0x3FE032AE55EDBD95ULL, 0xBFE032AE55EDBD94ULL, 0x3FEB98FA1FD9155FULL,
|
|
||||||
0x3FD01F1806B9FDD1ULL, 0x3FEEF7D6E51CA3C0ULL, 0xBFEEF7D6E51CA3BFULL, 0x3FD01F1806B9FDD6ULL,
|
|
||||||
0x3FEE3A33EC75CE85ULL, 0x3FD50163DC197047ULL, 0xBFD50163DC197048ULL, 0x3FEE3A33EC75CE85ULL,
|
|
||||||
0x3FDBE51517FFC0D9ULL, 0x3FECCCEE20C2DEA0ULL, 0xBFECCCEE20C2DE9FULL, 0x3FDBE51517FFC0DAULL,
|
|
||||||
0x3FE7E83F87B03686ULL, 0x3FE5454FF5159DFBULL, 0xBFE5454FF5159DFCULL, 0x3FE7E83F87B03686ULL,
|
|
||||||
0x3FADD406F9808EC5ULL, 0x3FEFF21614E131EDULL, 0xBFEFF21614E131EDULL, 0x3FADD406F9808ECEULL,
|
|
||||||
0x3FEFDF9922F73307ULL, 0x3FB6BF1B3E79B129ULL, 0xBFB6BF1B3E79B126ULL, 0x3FEFDF9922F73307ULL,
|
|
||||||
0x3FE48703306091FFULL, 0x3FE88C66E7481BA1ULL, 0xBFE88C66E7481BA0ULL, 0x3FE48703306091FFULL,
|
|
||||||
0x3FEC5BEF59FEF85AULL, 0x3FDDA60C5CFA10D8ULL, 0xBFDDA60C5CFA10D8ULL, 0x3FEC5BEF59FEF85AULL,
|
|
||||||
0x3FD3241FB638BAAFULL, 0x3FEE89095BAD6025ULL, 0xBFEE89095BAD6024ULL, 0x3FD3241FB638BAB0ULL,
|
|
||||||
0x3FEEB4CF515B8811ULL, 0x3FD2038583D727BDULL, 0xBFD2038583D727BDULL, 0x3FEEB4CF515B8811ULL,
|
|
||||||
0x3FDEB00695F25620ULL, 0x3FEC14D9DC465E57ULL, 0xBFEC14D9DC465E56ULL, 0x3FDEB00695F25625ULL,
|
|
||||||
0x3FE8EC109B486C49ULL, 0x3FE41272663D108CULL, 0xBFE41272663D108AULL, 0x3FE8EC109B486C4AULL,
|
|
||||||
0x3FBB6FA6EC38F64EULL, 0x3FEFD0D158D86087ULL, 0xBFEFD0D158D86087ULL, 0x3FBB6FA6EC38F663ULL,
|
|
||||||
0x3FEF70F6434B7EB7ULL, 0x3FC7D0A7BBD2CB1BULL, 0xBFC7D0A7BBD2CB16ULL, 0x3FEF70F6434B7EB7ULL,
|
|
||||||
0x3FE205BAA17560D6ULL, 0x3FEA7138DE9D60F4ULL, 0xBFEA7138DE9D60F5ULL, 0x3FE205BAA17560D6ULL,
|
|
||||||
0x3FEAC4FFBD3EFAC8ULL, 0x3FE188591F3A46E5ULL, 0xBFE188591F3A46E5ULL, 0x3FEAC4FFBD3EFAC8ULL,
|
|
||||||
0x3FCA203E1B1831DFULL, 0x3FEF538B1FAF2D07ULL, 0xBFEF538B1FAF2D07ULL, 0x3FCA203E1B1831D9ULL,
|
|
||||||
0x3FEDACF42CE68AB9ULL, 0x3FD7F24DD37341E3ULL, 0xBFD7F24DD37341E2ULL, 0x3FEDACF42CE68AB9ULL,
|
|
||||||
0x3FD908EF81EF7BD3ULL, 0x3FED733F508C0DFEULL, 0xBFED733F508C0DFEULL, 0x3FD908EF81EF7BD4ULL,
|
|
||||||
0x3FE6D5AFEF4AAFCDULL, 0x3FE66B0F3F52B386ULL, 0xBFE66B0F3F52B385ULL, 0x3FE6D5AFEF4AAFCEULL,
|
|
||||||
0x3F82D96B0E509754ULL, 0x3FEFFFA72C978C4FULL, 0xBFEFFFA72C978C4FULL, 0x3F82D96B0E509777ULL,
|
|
||||||
0x3FEFFFA72C978C4FULL, 0x3F82D96B0E509703ULL, 0xBF82D96B0E50970DULL, 0x3FEFFFA72C978C4FULL,
|
|
||||||
0x3FE66B0F3F52B387ULL, 0x3FE6D5AFEF4AAFCCULL, 0xBFE6D5AFEF4AAFCDULL, 0x3FE66B0F3F52B386ULL,
|
|
||||||
0x3FED733F508C0DFFULL, 0x3FD908EF81EF7BD1ULL, 0xBFD908EF81EF7BD1ULL, 0x3FED733F508C0DFFULL,
|
|
||||||
0x3FD7F24DD37341E4ULL, 0x3FEDACF42CE68AB9ULL, 0xBFEDACF42CE68AB9ULL, 0x3FD7F24DD37341E5ULL,
|
|
||||||
0x3FEF538B1FAF2D07ULL, 0x3FCA203E1B1831DAULL, 0xBFCA203E1B1831DBULL, 0x3FEF538B1FAF2D07ULL,
|
|
||||||
0x3FE188591F3A46E5ULL, 0x3FEAC4FFBD3EFAC7ULL, 0xBFEAC4FFBD3EFAC7ULL, 0x3FE188591F3A46E7ULL,
|
|
||||||
0x3FEA7138DE9D60F5ULL, 0x3FE205BAA17560D6ULL, 0xBFE205BAA17560D5ULL, 0x3FEA7138DE9D60F6ULL,
|
|
||||||
0x3FC7D0A7BBD2CB1BULL, 0x3FEF70F6434B7EB7ULL, 0xBFEF70F6434B7EB7ULL, 0x3FC7D0A7BBD2CB25ULL,
|
|
||||||
0x3FEFD0D158D86087ULL, 0x3FBB6FA6EC38F64CULL, 0xBFBB6FA6EC38F646ULL, 0x3FEFD0D158D86087ULL,
|
|
||||||
0x3FE41272663D108DULL, 0x3FE8EC109B486C48ULL, 0xBFE8EC109B486C49ULL, 0x3FE41272663D108CULL,
|
|
||||||
0x3FEC14D9DC465E58ULL, 0x3FDEB00695F25620ULL, 0xBFDEB00695F25622ULL, 0x3FEC14D9DC465E57ULL,
|
|
||||||
0x3FD2038583D727BFULL, 0x3FEEB4CF515B8811ULL, 0xBFEEB4CF515B8811ULL, 0x3FD2038583D727BCULL,
|
|
||||||
0x3FEE89095BAD6025ULL, 0x3FD3241FB638BAAFULL, 0xBFD3241FB638BAADULL, 0x3FEE89095BAD6025ULL,
|
|
||||||
0x3FDDA60C5CFA10DAULL, 0x3FEC5BEF59FEF85AULL, 0xBFEC5BEF59FEF859ULL, 0x3FDDA60C5CFA10DBULL,
|
|
||||||
0x3FE88C66E7481BA1ULL, 0x3FE48703306091FFULL, 0xBFE48703306091FEULL, 0x3FE88C66E7481BA2ULL,
|
|
||||||
0x3FB6BF1B3E79B12FULL, 0x3FEFDF9922F73307ULL, 0xBFEFDF9922F73307ULL, 0x3FB6BF1B3E79B134ULL,
|
|
||||||
0x3FEFF21614E131EDULL, 0x3FADD406F9808EC8ULL, 0xBFADD406F9808EB3ULL, 0x3FEFF21614E131EDULL,
|
|
||||||
0x3FE5454FF5159DFCULL, 0x3FE7E83F87B03686ULL, 0xBFE7E83F87B03685ULL, 0x3FE5454FF5159DFDULL,
|
|
||||||
0x3FECCCEE20C2DEA0ULL, 0x3FDBE51517FFC0D9ULL, 0xBFDBE51517FFC0D7ULL, 0x3FECCCEE20C2DEA0ULL,
|
|
||||||
0x3FD50163DC19704AULL, 0x3FEE3A33EC75CE85ULL, 0xBFEE3A33EC75CE84ULL, 0x3FD50163DC19704BULL,
|
|
||||||
0x3FEEF7D6E51CA3C0ULL, 0x3FD01F1806B9FDD2ULL, 0xBFD01F1806B9FDCFULL, 0x3FEEF7D6E51CA3C0ULL,
|
|
||||||
0x3FE032AE55EDBD97ULL, 0x3FEB98FA1FD9155EULL, 0xBFEB98FA1FD9155EULL, 0x3FE032AE55EDBD95ULL,
|
|
||||||
0x3FE986AEF1457594ULL, 0x3FE34C5252C14DE1ULL, 0xBFE34C5252C14DE2ULL, 0x3FE986AEF1457593ULL,
|
|
||||||
0x3FC19D8940BE24ECULL, 0x3FEFB20DC681D54CULL, 0xBFEFB20DC681D54DULL, 0x3FC19D8940BE24E7ULL,
|
|
||||||
0x3FEF9BED7CFBDE29ULL, 0x3FC3F22F57DB4893ULL, 0xBFC3F22F57DB4892ULL, 0x3FEF9BED7CFBDE29ULL,
|
|
||||||
0x3FE2D333D34E9BB8ULL, 0x3FE9E082EDB42472ULL, 0xBFE9E082EDB42472ULL, 0x3FE2D333D34E9BB8ULL,
|
|
||||||
0x3FEB4B7409DE7925ULL, 0x3FE0B405878F85ECULL, 0xBFE0B405878F85EBULL, 0x3FEB4B7409DE7926ULL,
|
|
||||||
0x3FCDF5163F01099BULL, 0x3FEF1C7ABE284708ULL, 0xBFEF1C7ABE284708ULL, 0x3FCDF5163F01099DULL,
|
|
||||||
0x3FEE0766D9280F54ULL, 0x3FD61D595C88C203ULL, 0xBFD61D595C88C202ULL, 0x3FEE0766D9280F55ULL,
|
|
||||||
0x3FDAD473125CDC09ULL, 0x3FED0D672F59D2B8ULL, 0xBFED0D672F59D2B7ULL, 0x3FDAD473125CDC0EULL,
|
|
||||||
0x3FE782FB1B90B35BULL, 0x3FE5B50B264F7448ULL, 0xBFE5B50B264F7446ULL, 0x3FE782FB1B90B35CULL,
|
|
||||||
0x3FA46A396FF8617EULL, 0x3FEFF97C4208C014ULL, 0xBFEFF97C4208C014ULL, 0x3FA46A396FF861A7ULL,
|
|
||||||
0x3FEFFB55E425FDAEULL, 0x3FA14685DB42C17EULL, 0xBFA14685DB42C175ULL, 0x3FEFFB55E425FDAEULL,
|
|
||||||
0x3FE5D9DEE73E345CULL, 0x3FE760C52C304764ULL, 0xBFE760C52C304763ULL, 0x3FE5D9DEE73E345DULL,
|
|
||||||
0x3FED2255C6E5A4E1ULL, 0x3FDA790CD3DBF31AULL, 0xBFDA790CD3DBF319ULL, 0x3FED2255C6E5A4E1ULL,
|
|
||||||
0x3FD67B949CAD63CBULL, 0x3FEDF5E36A9BA59CULL, 0xBFEDF5E36A9BA59CULL, 0x3FD67B949CAD63CCULL,
|
|
||||||
0x3FEF2817FC4609CEULL, 0x3FCD31774D2CBDEEULL, 0xBFCD31774D2CBDECULL, 0x3FEF2817FC4609CEULL,
|
|
||||||
0x3FE0DED0B84BC4B6ULL, 0x3FEB3115A5F37BF3ULL, 0xBFEB3115A5F37BF4ULL, 0x3FE0DED0B84BC4B5ULL,
|
|
||||||
0x3FE9FDF4F13149DEULL, 0x3FE2AA76E87AEB58ULL, 0xBFE2AA76E87AEB59ULL, 0x3FE9FDF4F13149DEULL,
|
|
||||||
0x3FC4B8B17F79FA8AULL, 0x3FEF93F14F85AC07ULL, 0xBFEF93F14F85AC08ULL, 0x3FC4B8B17F79FA85ULL,
|
|
||||||
0x3FEFB8D18D66ADB7ULL, 0x3FC0D64DBCB26786ULL, 0xBFC0D64DBCB26787ULL, 0x3FEFB8D18D66ADB7ULL,
|
|
||||||
0x3FE374531B817F8EULL, 0x3FE9683F42BD7FE1ULL, 0xBFE9683F42BD7FE1ULL, 0x3FE374531B817F8DULL,
|
|
||||||
0x3FEBB249A0B6C40DULL, 0x3FE00740C82B82E0ULL, 0xBFE00740C82B82E1ULL, 0x3FEBB249A0B6C40DULL,
|
|
||||||
0x3FD0804E05EB661DULL, 0x3FEEEB074C50A545ULL, 0xBFEEEB074C50A544ULL, 0x3FD0804E05EB661EULL,
|
|
||||||
0x3FEE4A8DFF81CE5EULL, 0x3FD4A253D11B82F3ULL, 0xBFD4A253D11B82F3ULL, 0x3FEE4A8DFF81CE5EULL,
|
|
||||||
0x3FDC3F6D47263128ULL, 0x3FECB6E20A00DA99ULL, 0xBFECB6E20A00DA98ULL, 0x3FDC3F6D4726312DULL,
|
|
||||||
0x3FE8098B756E52FBULL, 0x3FE51FA81CD99AA6ULL, 0xBFE51FA81CD99AA5ULL, 0x3FE8098B756E52FCULL,
|
|
||||||
0x3FB07B614E463060ULL, 0x3FEFEF0102826191ULL, 0xBFEFEF0102826191ULL, 0x3FB07B614E463075ULL,
|
|
||||||
0x3FEFE3E92BE9D886ULL, 0x3FB52E774A4D4D0AULL, 0xBFB52E774A4D4D09ULL, 0x3FEFE3E92BE9D886ULL,
|
|
||||||
0x3FE4AD79516722F1ULL, 0x3FE86C0A1D9AA195ULL, 0xBFE86C0A1D9AA193ULL, 0x3FE4AD79516722F3ULL,
|
|
||||||
0x3FEC7315899EAAD7ULL, 0x3FDD4CD02BA8609CULL, 0xBFDD4CD02BA86099ULL, 0x3FEC7315899EAAD8ULL,
|
|
||||||
0x3FD383F5E353B6ABULL, 0x3FEE79DB29A5165AULL, 0xBFEE79DB29A51659ULL, 0x3FD383F5E353B6AFULL,
|
|
||||||
0x3FEEC2CF4B1AF6B2ULL, 0x3FD1A2F7FBE8F243ULL, 0xBFD1A2F7FBE8F243ULL, 0x3FEEC2CF4B1AF6B2ULL,
|
|
||||||
0x3FDF081906BFF7FEULL, 0x3FEBFC9D25A1B147ULL, 0xBFEBFC9D25A1B147ULL, 0x3FDF081906BFF7FEULL,
|
|
||||||
0x3FE90B7943575EFEULL, 0x3FE3EB33EABE0680ULL, 0xBFE3EB33EABE0680ULL, 0x3FE90B7943575EFEULL,
|
|
||||||
0x3FBCFF533B307DC2ULL, 0x3FEFCB4703914354ULL, 0xBFEFCB4703914354ULL, 0x3FBCFF533B307DC6ULL,
|
|
||||||
0x3FEF7A299C1A322AULL, 0x3FC70AFD8D08C4FFULL, 0xBFC70AFD8D08C4FBULL, 0x3FEF7A299C1A322AULL,
|
|
||||||
0x3FE22F2D662C13E1ULL, 0x3FEA54C91090F523ULL, 0xBFEA54C91090F522ULL, 0x3FE22F2D662C13E3ULL,
|
|
||||||
0x3FEAE068F345ECEFULL, 0x3FE15E36E4DBE2BCULL, 0xBFE15E36E4DBE2BBULL, 0x3FEAE068F345ECF0ULL,
|
|
||||||
0x3FCAE4F1D5F3B9AFULL, 0x3FEF492206BCABB4ULL, 0xBFEF492206BCABB4ULL, 0x3FCAE4F1D5F3B9B2ULL,
|
|
||||||
0x3FEDBF9E4395759BULL, 0x3FD794F5E613DFAEULL, 0xBFD794F5E613DFACULL, 0x3FEDBF9E4395759BULL,
|
|
||||||
0x3FD96555B7AB9491ULL, 0x3FED5F7172888A7EULL, 0xBFED5F7172888A7FULL, 0x3FD96555B7AB948EULL,
|
|
||||||
0x3FE6F8CA99C95B75ULL, 0x3FE64715437F535BULL, 0xBFE64715437F535BULL, 0x3FE6F8CA99C95B75ULL,
|
|
||||||
0x3F8F6A296AB9980FULL, 0x3FEFFF0943C53BD1ULL, 0xBFEFFF0943C53BD1ULL, 0x3F8F6A296AB997B3ULL,
|
|
||||||
0x3FEFFE1C6870CB77ULL, 0x3F95FD4D21FAB226ULL, 0xBF95FD4D21FAB21FULL, 0x3FEFFE1C6870CB77ULL,
|
|
||||||
0x3FE622E44FEC22FFULL, 0x3FE71BAC960E41BFULL, 0xBFE71BAC960E41BEULL, 0x3FE622E44FEC2300ULL,
|
|
||||||
0x3FED4B5B1B187524ULL, 0x3FD9C17D440DF9F2ULL, 0xBFD9C17D440DF9F2ULL, 0x3FED4B5B1B187524ULL,
|
|
||||||
0x3FD73763C9261092ULL, 0x3FEDD1FEF38A915AULL, 0xBFEDD1FEF38A9159ULL, 0x3FD73763C9261093ULL,
|
|
||||||
0x3FEF3E6BBC1BBC65ULL, 0x3FCBA96334F15DADULL, 0xBFCBA96334F15DACULL, 0x3FEF3E6BBC1BBC65ULL,
|
|
||||||
0x3FE133E9CFEE254FULL, 0x3FEAFB8FD89F57B6ULL, 0xBFEAFB8FD89F57B5ULL, 0x3FE133E9CFEE2551ULL,
|
|
||||||
0x3FEA38184A593BC5ULL, 0x3FE258734CBB7110ULL, 0xBFE258734CBB710EULL, 0x3FEA38184A593BC7ULL,
|
|
||||||
0x3FC6451A831D830EULL, 0x3FEF830F4A40C60CULL, 0xBFEF830F4A40C60CULL, 0x3FC6451A831D8318ULL,
|
|
||||||
0x3FEFC56E3B7D9AF6ULL, 0x3FBE8EB7FDE4AA3EULL, 0xBFBE8EB7FDE4AA35ULL, 0x3FEFC56E3B7D9AF6ULL,
|
|
||||||
0x3FE3C3C44981C518ULL, 0x3FE92AA41FC5A815ULL, 0xBFE92AA41FC5A815ULL, 0x3FE3C3C44981C517ULL,
|
|
||||||
0x3FEBE41B611154C0ULL, 0x3FDF5FDEE656CDA3ULL, 0xBFDF5FDEE656CDA4ULL, 0x3FEBE41B611154C0ULL,
|
|
||||||
0x3FD1423EEFC6937AULL, 0x3FEED0835E999009ULL, 0xBFEED0835E999009ULL, 0x3FD1423EEFC69378ULL,
|
|
||||||
0x3FEE6A61C55D53A7ULL, 0x3FD3E39BE96EC271ULL, 0xBFD3E39BE96EC26FULL, 0x3FEE6A61C55D53A8ULL,
|
|
||||||
0x3FDCF34BAEE1CD23ULL, 0x3FEC89F587029C13ULL, 0xBFEC89F587029C12ULL, 0x3FDCF34BAEE1CD24ULL,
|
|
||||||
0x3FE84B7111AF83FAULL, 0x3FE4D3BC6D589F7FULL, 0xBFE4D3BC6D589F7EULL, 0x3FE84B7111AF83FBULL,
|
|
||||||
0x3FB39D9F12C5A2A2ULL, 0x3FEFE7EA85482D60ULL, 0xBFEFE7EA85482D60ULL, 0x3FB39D9F12C5A2A7ULL,
|
|
||||||
0x3FEFEB9D2530410FULL, 0x3FB20C9674ED444CULL, 0xBFB20C9674ED444FULL, 0x3FEFEB9D2530410FULL,
|
|
||||||
0x3FE4F9CC25CCA487ULL, 0x3FE82A9C13F545FFULL, 0xBFE82A9C13F545FEULL, 0x3FE4F9CC25CCA488ULL,
|
|
||||||
0x3FECA08F19B9C449ULL, 0x3FDC997FC3865388ULL, 0xBFDC997FC3865385ULL, 0x3FECA08F19B9C44AULL,
|
|
||||||
0x3FD44310DC8936F0ULL, 0x3FEE5A9D550467D3ULL, 0xBFEE5A9D550467D3ULL, 0x3FD44310DC8936F4ULL,
|
|
||||||
0x3FEEDDEB6A078651ULL, 0x3FD0E15B4E1749CDULL, 0xBFD0E15B4E1749CEULL, 0x3FEEDDEB6A078651ULL,
|
|
||||||
0x3FDFB7575C24D2DDULL, 0x3FEBCB54CB0D2327ULL, 0xBFEBCB54CB0D2327ULL, 0x3FDFB7575C24D2DEULL,
|
|
||||||
0x3FE94990E3AC4A6CULL, 0x3FE39C23E3D63029ULL, 0xBFE39C23E3D63029ULL, 0x3FE94990E3AC4A6CULL,
|
|
||||||
0x3FC00EE8AD6FB85AULL, 0x3FEFBF470F0A8D88ULL, 0xBFEFBF470F0A8D88ULL, 0x3FC00EE8AD6FB85CULL,
|
|
||||||
0x3FEF8BA737CB4B78ULL, 0x3FC57F008654CBDEULL, 0xBFC57F008654CBDBULL, 0x3FEF8BA737CB4B78ULL,
|
|
||||||
0x3FE2818BEF4D3CBAULL, 0x3FEA1B26D2C0A75EULL, 0xBFEA1B26D2C0A75DULL, 0x3FE2818BEF4D3CBBULL,
|
|
||||||
0x3FEB16742A4CA2F5ULL, 0x3FE1097248D0A956ULL, 0xBFE1097248D0A956ULL, 0x3FEB16742A4CA2F5ULL,
|
|
||||||
0x3FCC6D90535D74DFULL, 0x3FEF33685A3AAEF0ULL, 0xBFEF33685A3AAEF0ULL, 0x3FCC6D90535D74E1ULL,
|
|
||||||
0x3FEDE4160F6D8D82ULL, 0x3FD6D998638A0CB5ULL, 0xBFD6D998638A0CB4ULL, 0x3FEDE4160F6D8D82ULL,
|
|
||||||
0x3FDA1D6543B50AC1ULL, 0x3FED36FC7BCBFBDBULL, 0xBFED36FC7BCBFBDCULL, 0x3FDA1D6543B50ABEULL,
|
|
||||||
0x3FE73E558E079942ULL, 0x3FE5FE7CBDE56A0FULL, 0xBFE5FE7CBDE56A10ULL, 0x3FE73E558E079941ULL,
|
|
||||||
0x3F9C454F4CE53B33ULL, 0x3FEFFCE09CE2A679ULL, 0xBFEFFCE09CE2A679ULL, 0x3F9C454F4CE53B05ULL,
|
|
||||||
0x3FEFF753BB1B9164ULL, 0x3FA78DBAA5874685ULL, 0xBFA78DBAA5874676ULL, 0x3FEFF753BB1B9164ULL,
|
|
||||||
0x3FE59001D5F723E0ULL, 0x3FE7A4F707BF97D2ULL, 0xBFE7A4F707BF97D1ULL, 0x3FE59001D5F723E0ULL,
|
|
||||||
0x3FECF830E8CE467BULL, 0x3FDB2F971DB31972ULL, 0xBFDB2F971DB31970ULL, 0x3FECF830E8CE467BULL,
|
|
||||||
0x3FD5BEE78B9DB3B8ULL, 0x3FEE18A02FDC66D9ULL, 0xBFEE18A02FDC66D9ULL, 0x3FD5BEE78B9DB3B9ULL,
|
|
||||||
0x3FEF1090BC898F5FULL, 0x3FCEB86B462DE348ULL, 0xBFCEB86B462DE344ULL, 0x3FEF1090BC898F5FULL,
|
|
||||||
0x3FE089112032B08DULL, 0x3FEB658F14FDBC47ULL, 0xBFEB658F14FDBC47ULL, 0x3FE089112032B08BULL,
|
|
||||||
0x3FE9C2D110F075C3ULL, 0x3FE2FBC24B441015ULL, 0xBFE2FBC24B441016ULL, 0x3FE9C2D110F075C2ULL,
|
|
||||||
0x3FC32B7BF94516ABULL, 0x3FEFA39BAC7A1791ULL, 0xBFEFA39BAC7A1791ULL, 0x3FC32B7BF94516A5ULL,
|
|
||||||
0x3FEFAAFBCB0CFDDCULL, 0x3FC264994DFD340AULL, 0xBFC264994DFD3409ULL, 0x3FEFAAFBCB0CFDDCULL,
|
|
||||||
0x3FE32421EC49A620ULL, 0x3FE9A4DFA42B06B1ULL, 0xBFE9A4DFA42B06B2ULL, 0x3FE32421EC49A620ULL,
|
|
||||||
0x3FEB7F6686E792EAULL, 0x3FE05DF3EC31B8B6ULL, 0xBFE05DF3EC31B8B7ULL, 0x3FEB7F6686E792E9ULL,
|
|
||||||
0x3FCF7B7480BD3801ULL, 0x3FEF045A14CF738CULL, 0xBFEF045A14CF738BULL, 0x3FCF7B7480BD3803ULL,
|
|
||||||
0x3FEE298F4439197AULL, 0x3FD5604012F467B4ULL, 0xBFD5604012F467B4ULL, 0x3FEE298F4439197AULL,
|
|
||||||
0x3FDB8A7814FD5693ULL, 0x3FECE2B32799A060ULL, 0xBFECE2B32799A05FULL, 0x3FDB8A7814FD5698ULL,
|
|
||||||
0x3FE7C6B89CE2D333ULL, 0x3FE56AC35197649EULL, 0xBFE56AC35197649DULL, 0x3FE7C6B89CE2D334ULL,
|
|
||||||
0x3FAAB101BD5F8316ULL, 0x3FEFF4DC54B1BED3ULL, 0xBFEFF4DC54B1BED2ULL, 0x3FAAB101BD5F833EULL,
|
|
||||||
0x3FEFDAFA7514538CULL, 0x3FB84F8712C130A0ULL, 0xBFB84F8712C1309DULL, 0x3FEFDAFA7514538CULL,
|
|
||||||
0x3FE4605A692B32A2ULL, 0x3FE8AC871EDE1D87ULL, 0xBFE8AC871EDE1D86ULL, 0x3FE4605A692B32A4ULL,
|
|
||||||
0x3FEC44833141C004ULL, 0x3FDDFEFF66A941DDULL, 0xBFDDFEFF66A941D9ULL, 0x3FEC44833141C005ULL,
|
|
||||||
0x3FD2C41A4E954521ULL, 0x3FEE97EC36016B30ULL, 0xBFEE97EC36016B2FULL, 0x3FD2C41A4E954526ULL,
|
|
||||||
0x3FEEA68393E65800ULL, 0x3FD263E6995554BAULL, 0xBFD263E6995554B9ULL, 0x3FEEA68393E65800ULL,
|
|
||||||
0x3FDE57A86D3CD825ULL, 0x3FEC2CD14931E3F1ULL, 0xBFEC2CD14931E3F1ULL, 0x3FDE57A86D3CD826ULL,
|
|
||||||
0x3FE8CC6A75184655ULL, 0x3FE4397F5B2A4380ULL, 0xBFE4397F5B2A437FULL, 0x3FE8CC6A75184655ULL,
|
|
||||||
0x3FB9DFB6EB24A860ULL, 0x3FEFD60D2DA75C9EULL, 0xBFEFD60D2DA75C9EULL, 0x3FB9DFB6EB24A864ULL,
|
|
||||||
0x3FEF677556883CEEULL, 0x3FC8961727C41804ULL, 0xBFC8961727C417FEULL, 0x3FEF677556883CEEULL,
|
|
||||||
0x3FE1DC1B64DC4872ULL, 0x3FEA8D676E545AD2ULL, 0xBFEA8D676E545AD1ULL, 0x3FE1DC1B64DC4874ULL,
|
|
||||||
0x3FEAA9547A2CB98EULL, 0x3FE1B250171373BEULL, 0xBFE1B250171373BDULL, 0x3FEAA9547A2CB98FULL,
|
|
||||||
0x3FC95B49E9B62AFFULL, 0x3FEF5DA6ED43685CULL, 0xBFEF5DA6ED43685CULL, 0x3FC95B49E9B62B02ULL,
|
|
||||||
0x3FED9A00DD8B3D46ULL, 0x3FD84F6AAAF3903FULL, 0xBFD84F6AAAF3903CULL, 0x3FED9A00DD8B3D47ULL,
|
|
||||||
0x3FD8AC4B86D5ED47ULL, 0x3FED86C48445A44FULL, 0xBFED86C48445A450ULL, 0x3FD8AC4B86D5ED44ULL,
|
|
||||||
0x3FE6B25CED2FE29CULL, 0x3FE68ED1EAA19C71ULL, 0xBFE68ED1EAA19C71ULL, 0x3FE6B25CED2FE29BULL,
|
|
||||||
0x3F6921F8BECCA62FULL, 0x3FEFFFF621621D02ULL, 0xBFEFFFF621621D02ULL, 0x3F6921F8BECCA4BCULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
#if !defined(WOLFSSL_FALCON_FFT_AVX2) && !defined(WOLFSSL_FALCON_FFT_NEON)
|
|
||||||
/* When the AVX2 backend is selected, falcon_FFT/falcon_iFFT are provided by
|
|
||||||
* wc_falcon_fft_avx2.c instead; the twiddle table above is still shared. */
|
|
||||||
|
|
||||||
/* In-place forward FFT: coefficient representation -> FFT representation. */
|
|
||||||
void falcon_FFT(fpr* f, unsigned logn)
|
|
||||||
{
|
|
||||||
unsigned u;
|
|
||||||
size_t t, n, hn, m;
|
|
||||||
|
|
||||||
n = (size_t)1 << logn;
|
|
||||||
hn = n >> 1;
|
|
||||||
t = hn;
|
|
||||||
for (u = 1, m = 2; u < logn; u++, m <<= 1) {
|
|
||||||
size_t ht = t >> 1, hm = m >> 1, i1, j1;
|
|
||||||
for (i1 = 0, j1 = 0; i1 < hm; i1++, j1 += t) {
|
|
||||||
size_t j, j2 = j1 + ht;
|
|
||||||
fpr s_re = falcon_gm_tab[((m + i1) << 1) + 0];
|
|
||||||
fpr s_im = falcon_gm_tab[((m + i1) << 1) + 1];
|
|
||||||
for (j = j1; j < j2; j++) {
|
|
||||||
fpr x_re = f[j], x_im = f[j + hn];
|
|
||||||
fpr y_re = f[j + ht], y_im = f[j + ht + hn];
|
|
||||||
FPC_MUL(y_re, y_im, y_re, y_im, s_re, s_im);
|
|
||||||
FPC_ADD(f[j], f[j + hn], x_re, x_im, y_re, y_im);
|
|
||||||
FPC_SUB(f[j + ht], f[j + ht + hn], x_re, x_im, y_re, y_im);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t = ht;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* In-place inverse FFT: exact reversal of falcon_FFT, then scale by 2^-(logn-1).
|
|
||||||
* Each inverse butterfly is (a+b) and (a-b)*conj(s). */
|
|
||||||
void falcon_iFFT(fpr* f, unsigned logn)
|
|
||||||
{
|
|
||||||
int u;
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1;
|
|
||||||
|
|
||||||
for (u = (int)logn - 1; u >= 1; u--) {
|
|
||||||
size_t m = (size_t)1 << u, hm = m >> 1;
|
|
||||||
size_t t = hn >> u; /* butterfly stride */
|
|
||||||
size_t i1, j1;
|
|
||||||
for (i1 = 0, j1 = 0; i1 < hm; i1++, j1 += (t << 1)) {
|
|
||||||
size_t j, j2 = j1 + t;
|
|
||||||
fpr s_re = falcon_gm_tab[((m + i1) << 1) + 0];
|
|
||||||
fpr s_im = fpr_neg(falcon_gm_tab[((m + i1) << 1) + 1]);
|
|
||||||
for (j = j1; j < j2; j++) {
|
|
||||||
fpr a_re = f[j], a_im = f[j + hn];
|
|
||||||
fpr b_re = f[j + t], b_im = f[j + t + hn];
|
|
||||||
fpr d_re, d_im;
|
|
||||||
FPC_ADD(f[j], f[j + hn], a_re, a_im, b_re, b_im);
|
|
||||||
FPC_SUB(d_re, d_im, a_re, a_im, b_re, b_im);
|
|
||||||
FPC_MUL(f[j + t], f[j + t + hn], d_re, d_im, s_re, s_im);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
fpr ni = fpr_inv(fpr_of((sword64)hn)); /* 1 / 2^(logn-1) (exact) */
|
|
||||||
size_t j;
|
|
||||||
for (j = 0; j < n; j++) {
|
|
||||||
f[j] = fpr_mul(f[j], ni);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* !WOLFSSL_FALCON_FFT_AVX2 */
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
@@ -1,652 +0,0 @@
|
|||||||
/* wc_falcon_fpr.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Integer-emulated IEEE-754 binary64 backend for the Falcon
|
|
||||||
* floating-point primitive seam (wolfssl/wolfcrypt/wc_falcon_fpr.h).
|
|
||||||
*
|
|
||||||
* This is the portable, FP-unit-free, fully deterministic and constant-time
|
|
||||||
* backend: every operation is performed with integer arithmetic only (64-bit
|
|
||||||
* mantissa multiply-accumulate, shifts and CLZ-style normalization). No
|
|
||||||
* hardware FPU is used and there is no branch or memory access that depends on
|
|
||||||
* an operand value, so results are bit-identical to round-to-nearest-even
|
|
||||||
* IEEE-754 binary64 on every platform.
|
|
||||||
*
|
|
||||||
* The algorithm is a port of the well-known Falcon reference "fpr" emulated
|
|
||||||
* implementation by Thomas Pornin (MIT licensed), adapted to wolfSSL house
|
|
||||||
* style (word64 / sword64 / word32). See https://falcon-sign.info/ and the
|
|
||||||
* NIST PQC / Falcon round-3 reference code. */
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLF_CRYPTO_CB_ONLY_FALCON)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fpr.h>
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Low-level helpers. */
|
|
||||||
/* */
|
|
||||||
/* These shift helpers tolerate a (possibly secret) shift count in 0..63 in */
|
|
||||||
/* constant time: a variable shift is split into a fixed conditional 32-bit */
|
|
||||||
/* part plus a 0..31 part, avoiding both undefined behaviour and any */
|
|
||||||
/* operand-dependent timing on platforms whose shift is data dependent. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Right-shift a 64-bit unsigned value by n (0..63), constant-time. */
|
|
||||||
static WC_INLINE fpr fpr_ursh(word64 x, int n)
|
|
||||||
{
|
|
||||||
x ^= (x ^ (x >> 32)) & ((word64)0 - (word64)(n >> 5));
|
|
||||||
return x >> (n & 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Right-shift a 64-bit signed value by n (0..63), constant-time. */
|
|
||||||
static WC_INLINE sword64 fpr_irsh(sword64 x, int n)
|
|
||||||
{
|
|
||||||
x ^= (x ^ (x >> 32)) & ((sword64)0 - (sword64)(n >> 5));
|
|
||||||
return x >> (n & 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Left-shift a 64-bit unsigned value by n (0..63), constant-time. */
|
|
||||||
static WC_INLINE word64 fpr_ulsh(word64 x, int n)
|
|
||||||
{
|
|
||||||
x ^= (x ^ (x << 32)) & ((word64)0 - (word64)(n >> 5));
|
|
||||||
return x << (n & 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Pack a sign s (0/1), unbiased exponent e and mantissa m (2^54 <= m < 2^55,
|
|
||||||
* with the low 3 bits carrying guard/round/sticky information) into the
|
|
||||||
* IEEE-754 binary64 bit pattern, applying round-to-nearest-even.
|
|
||||||
*
|
|
||||||
* If m == 0 a (signed) zero is produced. If e < -1076 the value underflows to
|
|
||||||
* a (signed) zero. */
|
|
||||||
static WC_INLINE fpr FPR(int s, int e, word64 m)
|
|
||||||
{
|
|
||||||
fpr x;
|
|
||||||
word32 t;
|
|
||||||
unsigned int f;
|
|
||||||
|
|
||||||
/* If e >= -1076 the value is "normal"; otherwise it would be subnormal,
|
|
||||||
* which we clamp down to zero. */
|
|
||||||
e += 1076;
|
|
||||||
t = (word32)e >> 31;
|
|
||||||
m &= (word64)t - 1;
|
|
||||||
|
|
||||||
/* If m == 0 we want a zero: force e to 0 too (the sign is conserved). */
|
|
||||||
t = (word32)(m >> 54);
|
|
||||||
e &= -(int)t;
|
|
||||||
|
|
||||||
/* The 52 stored mantissa bits come from m. Its top set bit (bit 54)
|
|
||||||
* increments the exponent field by one when added, which is what we want
|
|
||||||
* (and produces 0 for m == 0). */
|
|
||||||
x = (((word64)s << 63) | (m >> 2)) + ((word64)(word32)e << 52);
|
|
||||||
|
|
||||||
/* Round to nearest, ties to even: increment when the low 3 bits of m are
|
|
||||||
* 011, 110 or 111. A carry spilling into the exponent field is the desired
|
|
||||||
* behaviour. */
|
|
||||||
f = (unsigned int)m & 7U;
|
|
||||||
x += (0xC8U >> f) & 1U;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normalize mantissa m so its top bit (bit 63) is set, adjusting exponent e so
|
|
||||||
* that m * 2^e is preserved. A zero m is left unchanged. Constant-time. */
|
|
||||||
#define FPR_NORM64(m, e) do { \
|
|
||||||
word32 nt_; \
|
|
||||||
\
|
|
||||||
(e) -= 63; \
|
|
||||||
\
|
|
||||||
nt_ = (word32)((m) >> 32); \
|
|
||||||
nt_ = (nt_ | (word32)(0U - nt_)) >> 31; \
|
|
||||||
(m) ^= ((m) ^ ((m) << 32)) & ((word64)nt_ - 1); \
|
|
||||||
(e) += (int)(nt_ << 5); \
|
|
||||||
\
|
|
||||||
nt_ = (word32)((m) >> 48); \
|
|
||||||
nt_ = (nt_ | (word32)(0U - nt_)) >> 31; \
|
|
||||||
(m) ^= ((m) ^ ((m) << 16)) & ((word64)nt_ - 1); \
|
|
||||||
(e) += (int)(nt_ << 4); \
|
|
||||||
\
|
|
||||||
nt_ = (word32)((m) >> 56); \
|
|
||||||
nt_ = (nt_ | (word32)(0U - nt_)) >> 31; \
|
|
||||||
(m) ^= ((m) ^ ((m) << 8)) & ((word64)nt_ - 1); \
|
|
||||||
(e) += (int)(nt_ << 3); \
|
|
||||||
\
|
|
||||||
nt_ = (word32)((m) >> 60); \
|
|
||||||
nt_ = (nt_ | (word32)(0U - nt_)) >> 31; \
|
|
||||||
(m) ^= ((m) ^ ((m) << 4)) & ((word64)nt_ - 1); \
|
|
||||||
(e) += (int)(nt_ << 2); \
|
|
||||||
\
|
|
||||||
nt_ = (word32)((m) >> 62); \
|
|
||||||
nt_ = (nt_ | (word32)(0U - nt_)) >> 31; \
|
|
||||||
(m) ^= ((m) ^ ((m) << 2)) & ((word64)nt_ - 1); \
|
|
||||||
(e) += (int)(nt_ << 1); \
|
|
||||||
\
|
|
||||||
nt_ = (word32)((m) >> 63); \
|
|
||||||
(m) ^= ((m) ^ ((m) << 1)) & ((word64)nt_ - 1); \
|
|
||||||
(e) += (int)(nt_); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Constructors / conversions. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
#ifndef WOLFSSL_FALCON_FPR_DOUBLE /* inline backend provides fpr_scaled */
|
|
||||||
fpr fpr_scaled(sword64 i, int sc)
|
|
||||||
{
|
|
||||||
/* Convert i * 2^sc to fpr: take the sign and absolute value, normalize the
|
|
||||||
* magnitude so the top bit is set, round down to a 55-bit mantissa (with a
|
|
||||||
* sticky low bit) and pack. The source integer is assumed not to be
|
|
||||||
* -2^63. */
|
|
||||||
int s, e;
|
|
||||||
word32 t;
|
|
||||||
word64 m;
|
|
||||||
|
|
||||||
/* Sign and absolute value (-i == 1 + ~i). */
|
|
||||||
s = (int)((word64)i >> 63);
|
|
||||||
i ^= -(sword64)s;
|
|
||||||
i += s;
|
|
||||||
|
|
||||||
/* Suppose i != 0 for now: normalize it so the top bit is set. */
|
|
||||||
m = (word64)i;
|
|
||||||
e = 9 + sc;
|
|
||||||
FPR_NORM64(m, e);
|
|
||||||
|
|
||||||
/* m is now in 2^63..2^64-1; divide by 512 into the 2^54..2^55-1 range,
|
|
||||||
* folding any dropped bit into the sticky low bit. */
|
|
||||||
m |= ((word32)m & 0x1FF) + 0x1FF;
|
|
||||||
m >>= 9;
|
|
||||||
|
|
||||||
/* Corrective action for i == 0: clamp e and m to zero. */
|
|
||||||
t = (word32)((word64)((word64)i | (word64)(0 - (word64)i)) >> 63);
|
|
||||||
m &= (word64)0 - (word64)t;
|
|
||||||
e &= -(int)t;
|
|
||||||
|
|
||||||
/* FPR() handles exponents that are too low. */
|
|
||||||
return FPR(s, e, m);
|
|
||||||
}
|
|
||||||
#endif /* !WOLFSSL_FALCON_FPR_DOUBLE */
|
|
||||||
|
|
||||||
#if !defined(WOLFSSL_FALCON_FPR_ASM) && !defined(WOLFSSL_FALCON_FPR_DOUBLE)
|
|
||||||
/* The scalar fpr operations below are supplied by the per-architecture assembly
|
|
||||||
* backend (wc_falcon_fpr_x86_64_asm.S, WOLFSSL_FALCON_FPR_ASM) or by the inline
|
|
||||||
* native-double backend (WOLFSSL_FALCON_FPR_DOUBLE) when either is set;
|
|
||||||
* otherwise this constant-time integer emulation is used. fpr_expm_p63 and the
|
|
||||||
* fpr constants (below) always come from this file. */
|
|
||||||
fpr fpr_of(sword64 i)
|
|
||||||
{
|
|
||||||
return fpr_scaled(i, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sword64 fpr_rint(fpr x)
|
|
||||||
{
|
|
||||||
word64 m, d;
|
|
||||||
int e;
|
|
||||||
word32 s, dd, f;
|
|
||||||
|
|
||||||
/* Assuming the value fits in -(2^63-1)..+(2^63-1), extract the mantissa as
|
|
||||||
* a 63-bit integer and right-shift it as needed. */
|
|
||||||
m = ((x << 10) | ((word64)1 << 62)) & (((word64)1 << 63) - 1);
|
|
||||||
e = 1085 - ((int)(x >> 52) & 0x7FF);
|
|
||||||
|
|
||||||
/* A shift of more than 63 bits sets m to zero (also covers x == 0). */
|
|
||||||
m &= (word64)0 - (word64)((word32)(e - 64) >> 31);
|
|
||||||
e &= 63;
|
|
||||||
|
|
||||||
/* Right-shift m by e, rounding to nearest with ties to even. We build a
|
|
||||||
* word holding all dropped bits plus the lowest kept bit, then shrink it
|
|
||||||
* to three bits, the lowest being sticky. */
|
|
||||||
d = fpr_ulsh(m, 63 - e);
|
|
||||||
dd = (word32)d | ((word32)(d >> 32) & 0x1FFFFFFF);
|
|
||||||
f = (word32)(d >> 61) | ((dd | (word32)(0U - dd)) >> 31);
|
|
||||||
m = fpr_ursh(m, e) + (word64)((0xC8U >> f) & 1U);
|
|
||||||
|
|
||||||
/* Apply the sign bit. */
|
|
||||||
s = (word32)(x >> 63);
|
|
||||||
return ((sword64)m ^ -(sword64)s) + (sword64)s;
|
|
||||||
}
|
|
||||||
|
|
||||||
sword64 fpr_floor(fpr x)
|
|
||||||
{
|
|
||||||
word64 t;
|
|
||||||
sword64 xi;
|
|
||||||
int e, cc;
|
|
||||||
|
|
||||||
/* Extract the value as a signed scaled integer in the 2^62..2^63-1 range
|
|
||||||
* (absolute value), so only a right-shift is needed afterwards. */
|
|
||||||
e = (int)(x >> 52) & 0x7FF;
|
|
||||||
t = x >> 63;
|
|
||||||
xi = (sword64)(((x << 10) | ((word64)1 << 62)) & (((word64)1 << 63) - 1));
|
|
||||||
xi = (xi ^ -(sword64)t) + (sword64)t;
|
|
||||||
cc = 1085 - e;
|
|
||||||
|
|
||||||
/* An arithmetic right-shift implements floor() (round toward -inf) for
|
|
||||||
* both positive and negative values. */
|
|
||||||
xi = fpr_irsh(xi, cc & 63);
|
|
||||||
|
|
||||||
/* If the true shift count was 64 or more, replace xi with 0 (nonnegative)
|
|
||||||
* or -1 (negative). This also fixes the bogus implicit-bit assumption for
|
|
||||||
* a zero input. */
|
|
||||||
xi ^= (xi ^ -(sword64)t) & -(sword64)((word32)(63 - cc) >> 31);
|
|
||||||
return xi;
|
|
||||||
}
|
|
||||||
|
|
||||||
sword64 fpr_trunc(fpr x)
|
|
||||||
{
|
|
||||||
word64 t, xu;
|
|
||||||
int e, cc;
|
|
||||||
|
|
||||||
/* Extract the absolute value as a scaled integer in the 2^62..2^63-1
|
|
||||||
* range, then right-shift. */
|
|
||||||
e = (int)(x >> 52) & 0x7FF;
|
|
||||||
xu = ((x << 10) | ((word64)1 << 62)) & (((word64)1 << 63) - 1);
|
|
||||||
cc = 1085 - e;
|
|
||||||
xu = fpr_ursh(xu, cc & 63);
|
|
||||||
|
|
||||||
/* If the exponent is too low (cc > 63), clamp to zero (also covers
|
|
||||||
* x == 0). */
|
|
||||||
xu &= (word64)0 - (word64)((word32)(cc - 64) >> 31);
|
|
||||||
|
|
||||||
/* Apply the sign. */
|
|
||||||
t = x >> 63;
|
|
||||||
xu = (xu ^ ((word64)0 - t)) + t;
|
|
||||||
return (sword64)xu;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Arithmetic. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
fpr fpr_add(fpr x, fpr y)
|
|
||||||
{
|
|
||||||
word64 m, xu, yu, za;
|
|
||||||
word32 cs;
|
|
||||||
int ex, ey, sx, sy, cc;
|
|
||||||
|
|
||||||
/* Ensure x has the larger absolute value, so the exponent of y is no
|
|
||||||
* greater than that of x. We also conditionally swap when abs(x) == abs(y)
|
|
||||||
* and the sign of x is 1, which guarantees the result keeps the sign of x
|
|
||||||
* (and is +0 in the exact-cancellation case). */
|
|
||||||
m = ((word64)1 << 63) - 1;
|
|
||||||
za = (x & m) - (y & m);
|
|
||||||
cs = (word32)(za >> 63)
|
|
||||||
| ((1U - (word32)(((word64)0 - za) >> 63)) & (word32)(x >> 63));
|
|
||||||
m = (x ^ y) & ((word64)0 - (word64)cs);
|
|
||||||
x ^= m;
|
|
||||||
y ^= m;
|
|
||||||
|
|
||||||
/* Extract sign bits, biased exponents and mantissas. The mantissas are
|
|
||||||
* scaled up to the 2^55..2^56-1 range. A zero operand gets mantissa 0 and
|
|
||||||
* exponent -1078. */
|
|
||||||
ex = (int)(x >> 52);
|
|
||||||
sx = ex >> 11;
|
|
||||||
ex &= 0x7FF;
|
|
||||||
m = (word64)(word32)((ex + 0x7FF) >> 11) << 52;
|
|
||||||
xu = ((x & (((word64)1 << 52) - 1)) | m) << 3;
|
|
||||||
ex -= 1078;
|
|
||||||
ey = (int)(y >> 52);
|
|
||||||
sy = ey >> 11;
|
|
||||||
ey &= 0x7FF;
|
|
||||||
m = (word64)(word32)((ey + 0x7FF) >> 11) << 52;
|
|
||||||
yu = ((y & (((word64)1 << 52) - 1)) | m) << 3;
|
|
||||||
ey -= 1078;
|
|
||||||
|
|
||||||
/* x has the larger exponent; right-shift y to align. A shift of 60 bits or
|
|
||||||
* more clamps y to zero. */
|
|
||||||
cc = ex - ey;
|
|
||||||
yu &= (word64)0 - (word64)((word32)(cc - 60) >> 31);
|
|
||||||
cc &= 63;
|
|
||||||
|
|
||||||
/* The lowest bit of yu becomes sticky over the shifted-out bits. */
|
|
||||||
m = fpr_ulsh(1, cc) - 1;
|
|
||||||
yu |= (yu & m) + m;
|
|
||||||
yu = fpr_ursh(yu, cc);
|
|
||||||
|
|
||||||
/* Same sign: add mantissas; differing signs: subtract. */
|
|
||||||
xu += yu - ((yu << 1) & ((word64)0 - (word64)(sx ^ sy)));
|
|
||||||
|
|
||||||
/* Renormalize the (possibly cancelled or carried) result. */
|
|
||||||
FPR_NORM64(xu, ex);
|
|
||||||
|
|
||||||
/* Scale down to the 2^54..2^55-1 range, keeping a sticky low bit. */
|
|
||||||
xu |= ((word32)xu & 0x1FF) + 0x1FF;
|
|
||||||
xu >>= 9;
|
|
||||||
ex += 9;
|
|
||||||
|
|
||||||
/* The result keeps the sign of x (the swap above made the -0 corner cases
|
|
||||||
* impossible); FPR() clamps a too-low exponent to zero without altering
|
|
||||||
* the sign. */
|
|
||||||
return FPR(sx, ex, xu);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_sub(fpr x, fpr y)
|
|
||||||
{
|
|
||||||
y ^= (word64)1 << 63;
|
|
||||||
return fpr_add(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_neg(fpr x)
|
|
||||||
{
|
|
||||||
x ^= (word64)1 << 63;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_half(fpr x)
|
|
||||||
{
|
|
||||||
/* Halving subtracts 1 from the exponent; handle zero specially. */
|
|
||||||
word32 t;
|
|
||||||
|
|
||||||
x -= (word64)1 << 52;
|
|
||||||
t = (((word32)(x >> 52) & 0x7FF) + 1) >> 11;
|
|
||||||
x &= (word64)t - 1;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_double(fpr x)
|
|
||||||
{
|
|
||||||
/* Doubling increments the exponent; handle zero specially. Infinities and
|
|
||||||
* NaNs are not a concern for this backend. */
|
|
||||||
x += (word64)((((unsigned int)(x >> 52) & 0x7FFU) + 0x7FFU) >> 11) << 52;
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_mul(fpr x, fpr y)
|
|
||||||
{
|
|
||||||
word64 xu, yu, w, zu, zv;
|
|
||||||
word32 x0, x1, y0, y1, z0, z1, z2;
|
|
||||||
int ex, ey, d, e, s;
|
|
||||||
|
|
||||||
/* Extract mantissas (with implicit bit) as 53-bit integers. */
|
|
||||||
xu = (x & (((word64)1 << 52) - 1)) | ((word64)1 << 52);
|
|
||||||
yu = (y & (((word64)1 << 52) - 1)) | ((word64)1 << 52);
|
|
||||||
|
|
||||||
/* Multiply the two 53-bit integers using 25-bit low halves so the low
|
|
||||||
* limbs (z0, z1) only ever matter for the sticky bit. */
|
|
||||||
x0 = (word32)xu & 0x01FFFFFF;
|
|
||||||
x1 = (word32)(xu >> 25);
|
|
||||||
y0 = (word32)yu & 0x01FFFFFF;
|
|
||||||
y1 = (word32)(yu >> 25);
|
|
||||||
w = (word64)x0 * (word64)y0;
|
|
||||||
z0 = (word32)w & 0x01FFFFFF;
|
|
||||||
z1 = (word32)(w >> 25);
|
|
||||||
w = (word64)x0 * (word64)y1;
|
|
||||||
z1 += (word32)w & 0x01FFFFFF;
|
|
||||||
z2 = (word32)(w >> 25);
|
|
||||||
w = (word64)x1 * (word64)y0;
|
|
||||||
z1 += (word32)w & 0x01FFFFFF;
|
|
||||||
z2 += (word32)(w >> 25);
|
|
||||||
zu = (word64)x1 * (word64)y1;
|
|
||||||
z2 += (z1 >> 25);
|
|
||||||
z1 &= 0x01FFFFFF;
|
|
||||||
zu += z2;
|
|
||||||
|
|
||||||
/* The product is in 2^104..2^106-1. Keep the top part (zu); fold the low
|
|
||||||
* limbs into a sticky bit. */
|
|
||||||
zu |= ((z0 | z1) + 0x01FFFFFF) >> 25;
|
|
||||||
|
|
||||||
/* Normalize zu to 2^54..2^55-1; it may be one bit too large. The
|
|
||||||
* conditional right-shift preserves the sticky bit. */
|
|
||||||
zv = (zu >> 1) | (zu & 1);
|
|
||||||
w = zu >> 55;
|
|
||||||
zu ^= (zu ^ zv) & ((word64)0 - w);
|
|
||||||
|
|
||||||
/* Aggregate scaling factor: sum the exponents, remove 2*(1023+52), then
|
|
||||||
* add 50 + w (the right-shift amounts applied above). */
|
|
||||||
ex = (int)((x >> 52) & 0x7FF);
|
|
||||||
ey = (int)((y >> 52) & 0x7FF);
|
|
||||||
e = ex + ey - 2100 + (int)w;
|
|
||||||
|
|
||||||
/* Result sign is the XOR of the operand signs. */
|
|
||||||
s = (int)((x ^ y) >> 63);
|
|
||||||
|
|
||||||
/* Corrective action: if either operand is zero, clamp the mantissa. */
|
|
||||||
d = ((ex + 0x7FF) & (ey + 0x7FF)) >> 11;
|
|
||||||
zu &= (word64)0 - (word64)d;
|
|
||||||
|
|
||||||
return FPR(s, e, zu);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_sqr(fpr x)
|
|
||||||
{
|
|
||||||
return fpr_mul(x, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_div(fpr x, fpr y)
|
|
||||||
{
|
|
||||||
word64 xu, yu, q, q2, w;
|
|
||||||
int i, ex, ey, e, d, s;
|
|
||||||
|
|
||||||
/* Extract mantissas (with implicit bit). */
|
|
||||||
xu = (x & (((word64)1 << 52) - 1)) | ((word64)1 << 52);
|
|
||||||
yu = (y & (((word64)1 << 52) - 1)) | ((word64)1 << 52);
|
|
||||||
|
|
||||||
/* Bit-by-bit long division of xu by yu, for 55 bits. */
|
|
||||||
q = 0;
|
|
||||||
for (i = 0; i < 55; i++) {
|
|
||||||
word64 b;
|
|
||||||
|
|
||||||
b = ((xu - yu) >> 63) - 1;
|
|
||||||
xu -= b & yu;
|
|
||||||
q |= b & 1;
|
|
||||||
xu <<= 1;
|
|
||||||
q <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make the 56th (extra) bit sticky: set it iff the remainder is nonzero. */
|
|
||||||
q |= (xu | ((word64)0 - xu)) >> 63;
|
|
||||||
|
|
||||||
/* Normalize q to the 2^54..2^55-1 range (conditional shift, sticky-aware);
|
|
||||||
* the top bit may be zero but then the next bit is one. */
|
|
||||||
q2 = (q >> 1) | (q & 1);
|
|
||||||
w = q >> 55;
|
|
||||||
q ^= (q ^ q2) & ((word64)0 - w);
|
|
||||||
|
|
||||||
/* Scaling: exponent biases cancel; remove 55 (division shift) and add w. */
|
|
||||||
ex = (int)((x >> 52) & 0x7FF);
|
|
||||||
ey = (int)((y >> 52) & 0x7FF);
|
|
||||||
e = ex - ey - 55 + (int)w;
|
|
||||||
|
|
||||||
/* Result sign is the XOR of the operand signs. */
|
|
||||||
s = (int)((x ^ y) >> 63);
|
|
||||||
|
|
||||||
/* Corrective action for x == 0 (division by zero is excluded by the
|
|
||||||
* caller's contract). */
|
|
||||||
d = (ex + 0x7FF) >> 11;
|
|
||||||
s &= d;
|
|
||||||
e &= -d;
|
|
||||||
q &= (word64)0 - (word64)d;
|
|
||||||
|
|
||||||
return FPR(s, e, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_inv(fpr x)
|
|
||||||
{
|
|
||||||
/* 1.0 / x: fpr_one is the bit pattern of the double 1.0. */
|
|
||||||
return fpr_div(fpr_one, x);
|
|
||||||
}
|
|
||||||
|
|
||||||
fpr fpr_sqrt(fpr x)
|
|
||||||
{
|
|
||||||
word64 xu, q, s, r;
|
|
||||||
int i, ex, e;
|
|
||||||
|
|
||||||
/* Extract the mantissa and the true exponent (mantissa in 1..2). The sign
|
|
||||||
* is ignored: the operand is assumed nonnegative. */
|
|
||||||
xu = (x & (((word64)1 << 52) - 1)) | ((word64)1 << 52);
|
|
||||||
ex = (int)((x >> 52) & 0x7FF);
|
|
||||||
e = ex - 1023;
|
|
||||||
|
|
||||||
/* If the exponent is odd, double the mantissa and decrement the exponent,
|
|
||||||
* then halve the exponent for the square root. */
|
|
||||||
xu += xu & ((word64)0 - (word64)(e & 1));
|
|
||||||
e >>= 1;
|
|
||||||
|
|
||||||
/* Double the mantissa: now in 2^53..2^55-1, representing a value in
|
|
||||||
* [1, 4) with 53 fractional bits. */
|
|
||||||
xu <<= 1;
|
|
||||||
|
|
||||||
/* Compute the square root bit by bit. */
|
|
||||||
q = 0;
|
|
||||||
s = 0;
|
|
||||||
r = (word64)1 << 53;
|
|
||||||
for (i = 0; i < 54; i++) {
|
|
||||||
word64 t, b;
|
|
||||||
|
|
||||||
t = s + r;
|
|
||||||
b = ((xu - t) >> 63) - 1;
|
|
||||||
s += (r << 1) & b;
|
|
||||||
xu -= t & b;
|
|
||||||
q += r & b;
|
|
||||||
xu <<= 1;
|
|
||||||
r >>= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* q is a rounded-low 54-bit value (leading 1, 52 fractional digits and a
|
|
||||||
* guard bit); add a sticky bit for the remaining operand. */
|
|
||||||
q <<= 1;
|
|
||||||
q |= (xu | ((word64)0 - xu)) >> 63;
|
|
||||||
|
|
||||||
/* q is now an integer in 2^54..2^55-1; bias the exponent by 54. */
|
|
||||||
e -= 54;
|
|
||||||
|
|
||||||
/* Corrective action for an operand of value zero. */
|
|
||||||
q &= (word64)0 - (word64)((ex + 0x7FF) >> 11);
|
|
||||||
|
|
||||||
return FPR(0, e, q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Predicates. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
int fpr_lt(fpr x, fpr y)
|
|
||||||
{
|
|
||||||
/* For equal signs a signed comparison of the bit patterns yields the
|
|
||||||
* correct order (and x - y does not overflow). For differing signs the
|
|
||||||
* sign of x decides. For two negatives the order is reversed, so we
|
|
||||||
* combine sgn(x-y) and sgn(y-x). */
|
|
||||||
int cc0, cc1;
|
|
||||||
sword64 sx;
|
|
||||||
sword64 sy;
|
|
||||||
|
|
||||||
sx = (sword64)x;
|
|
||||||
sy = (sword64)y;
|
|
||||||
sy &= ~((sx ^ sy) >> 63); /* sy = 0 if the signs differ */
|
|
||||||
|
|
||||||
cc0 = (int)((sx - sy) >> 63) & 1; /* neither subtraction overflows when */
|
|
||||||
cc1 = (int)((sy - sx) >> 63) & 1; /* the signs are the same */
|
|
||||||
|
|
||||||
return cc0 ^ ((cc0 ^ cc1) & (int)((x & y) >> 63));
|
|
||||||
}
|
|
||||||
#endif /* !WOLFSSL_FALCON_FPR_ASM */
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Sampler support: ccs * exp(-x) in fixed point scaled by 2^63. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Top 64 bits of the 128-bit product z*y. This is the inner operation of the
|
|
||||||
* Bernoulli-exp polynomial and the hottest scalar op in signing. On 64-bit
|
|
||||||
* targets it is a single multiply instruction; the portable 32x32 fallback
|
|
||||||
* (one MUL becomes four) is kept for platforms without a 128-bit integer type
|
|
||||||
* (e.g. Cortex-M). Both paths are constant-time and bit-identical. */
|
|
||||||
#if defined(__SIZEOF_INT128__)
|
|
||||||
#define FALCON_MULHI(z, y) \
|
|
||||||
((word64)(((unsigned __int128)(word64)(z) * (unsigned __int128)(word64)(y)) >> 64))
|
|
||||||
#else
|
|
||||||
static WC_INLINE word64 falcon_mulhi(word64 z, word64 y)
|
|
||||||
{
|
|
||||||
word32 z0 = (word32)z, z1 = (word32)(z >> 32);
|
|
||||||
word32 y0 = (word32)y, y1 = (word32)(y >> 32);
|
|
||||||
word64 a = ((word64)z0 * (word64)y1) + (((word64)z0 * (word64)y0) >> 32);
|
|
||||||
word64 b = ((word64)z1 * (word64)y0);
|
|
||||||
word64 c = (a >> 32) + (b >> 32);
|
|
||||||
c += (((word64)(word32)a + (word64)(word32)b) >> 32);
|
|
||||||
c += (word64)z1 * (word64)y1;
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
#define FALCON_MULHI(z, y) falcon_mulhi((z), (y))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
word64 fpr_expm_p63(fpr x, fpr ccs)
|
|
||||||
{
|
|
||||||
/* Polynomial approximation of exp(-x), coefficients from FACCT
|
|
||||||
* (https://eprint.iacr.org/2018/1234, https://github.com/raykzhao/gaussian)
|
|
||||||
* scaled up by 2^63 and converted to integers. The maximum observed
|
|
||||||
* deviation from the true value over the 0..log(2) range is below
|
|
||||||
* 2^(-50). */
|
|
||||||
static const word64 C[] = {
|
|
||||||
0x00000004741183A3u,
|
|
||||||
0x00000036548CFC06u,
|
|
||||||
0x0000024FDCBF140Au,
|
|
||||||
0x0000171D939DE045u,
|
|
||||||
0x0000D00CF58F6F84u,
|
|
||||||
0x000680681CF796E3u,
|
|
||||||
0x002D82D8305B0FEAu,
|
|
||||||
0x011111110E066FD0u,
|
|
||||||
0x0555555555070F00u,
|
|
||||||
0x155555555581FF00u,
|
|
||||||
0x400000000002B400u,
|
|
||||||
0x7FFFFFFFFFFF4800u,
|
|
||||||
0x8000000000000000u
|
|
||||||
};
|
|
||||||
|
|
||||||
word64 z, y;
|
|
||||||
|
|
||||||
/* Horner evaluation of the degree-12 polynomial; each step keeps the top
|
|
||||||
* 64 bits of z*y. Fully unrolled (the loop bound is a compile-time 13). */
|
|
||||||
y = C[0];
|
|
||||||
z = (word64)fpr_trunc(fpr_mul(x, fpr_ptwo63)) << 1;
|
|
||||||
y = C[1] - FALCON_MULHI(z, y);
|
|
||||||
y = C[2] - FALCON_MULHI(z, y);
|
|
||||||
y = C[3] - FALCON_MULHI(z, y);
|
|
||||||
y = C[4] - FALCON_MULHI(z, y);
|
|
||||||
y = C[5] - FALCON_MULHI(z, y);
|
|
||||||
y = C[6] - FALCON_MULHI(z, y);
|
|
||||||
y = C[7] - FALCON_MULHI(z, y);
|
|
||||||
y = C[8] - FALCON_MULHI(z, y);
|
|
||||||
y = C[9] - FALCON_MULHI(z, y);
|
|
||||||
y = C[10] - FALCON_MULHI(z, y);
|
|
||||||
y = C[11] - FALCON_MULHI(z, y);
|
|
||||||
y = C[12] - FALCON_MULHI(z, y);
|
|
||||||
|
|
||||||
/* Apply the scaling factor ccs (converted to the same fixed-point format)
|
|
||||||
* with a final 64x64->high-64 multiplication. */
|
|
||||||
z = (word64)fpr_trunc(fpr_mul(ccs, fpr_ptwo63)) << 1;
|
|
||||||
y = FALCON_MULHI(z, y);
|
|
||||||
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Named constants: IEEE-754 binary64 bit patterns. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
const fpr fpr_zero = 0;
|
|
||||||
const fpr fpr_one = 4607182418800017408U; /* 1.0 */
|
|
||||||
const fpr fpr_two = 4611686018427387904U; /* 2.0 */
|
|
||||||
const fpr fpr_onehalf = 4602678819172646912U; /* 0.5 */
|
|
||||||
const fpr fpr_invsqrt2 = 4604544271217802189U; /* 1/sqrt(2) */
|
|
||||||
const fpr fpr_invsqrt8 = 4600040671590431693U; /* 1/sqrt(8) */
|
|
||||||
const fpr fpr_ptwo31 = 4746794007248502784U; /* 2^31 */
|
|
||||||
const fpr fpr_ptwo31m1 = 4746794007244308480U; /* 2^31 - 1 */
|
|
||||||
const fpr fpr_mtwo31m1 = 13970166044099084288U; /* -(2^31 - 1) */
|
|
||||||
const fpr fpr_ptwo63m1 = 4890909195324358656U; /* 2^63 - 1 */
|
|
||||||
const fpr fpr_mtwo63m1 = 14114281232179134464U; /* -(2^63 - 1) */
|
|
||||||
const fpr fpr_ptwo63 = 4890909195324358656U; /* 2^63 */
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON */
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,310 +0,0 @@
|
|||||||
/* wc_falcon_poly.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon FFT-domain polynomial operations over the fpr seam. Faithful
|
|
||||||
* port of the poly_* functions from the MIT-licensed Falcon reference (fft.c,
|
|
||||||
* Thomas Pornin). See wolfssl/wolfcrypt/wc_falcon_poly.h. */
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY) && !defined(WOLF_CRYPTO_CB_ONLY_FALCON)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_poly.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fft.h> /* falcon_gm_tab */
|
|
||||||
|
|
||||||
/* Complex helpers (temps make the macros alias-safe). */
|
|
||||||
#define FPC_ADD(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
(d_re) = fpr_add(_ar, _br); \
|
|
||||||
(d_im) = fpr_add(_ai, _bi); \
|
|
||||||
} while (0)
|
|
||||||
#define FPC_SUB(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
(d_re) = fpr_sub(_ar, _br); \
|
|
||||||
(d_im) = fpr_sub(_ai, _bi); \
|
|
||||||
} while (0)
|
|
||||||
#define FPC_MUL(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
(d_re) = fpr_sub(fpr_mul(_ar, _br), fpr_mul(_ai, _bi)); \
|
|
||||||
(d_im) = fpr_add(fpr_mul(_ar, _bi), fpr_mul(_ai, _br)); \
|
|
||||||
} while (0)
|
|
||||||
/* (a) / (b) for complex a,b. */
|
|
||||||
#define FPC_DIV(d_re, d_im, a_re, a_im, b_re, b_im) do { \
|
|
||||||
fpr _ar = (a_re), _ai = (a_im), _br = (b_re), _bi = (b_im); \
|
|
||||||
fpr _m = fpr_inv(fpr_add(fpr_mul(_br, _br), fpr_mul(_bi, _bi))); \
|
|
||||||
_br = fpr_mul(_br, _m); \
|
|
||||||
_bi = fpr_neg(fpr_mul(_bi, _m)); \
|
|
||||||
(d_re) = fpr_sub(fpr_mul(_ar, _br), fpr_mul(_ai, _bi)); \
|
|
||||||
(d_im) = fpr_add(fpr_mul(_ar, _bi), fpr_mul(_ai, _br)); \
|
|
||||||
} while (0)
|
|
||||||
|
|
||||||
void falcon_poly_add(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_add_avx2(a, b, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, u;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
a[u] = fpr_add(a[u], b[u]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_sub(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_sub_avx2(a, b, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, u;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
a[u] = fpr_sub(a[u], b[u]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_neg(fpr* a, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn, u;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
a[u] = fpr_neg(a[u]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_adj_fft(fpr* a, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = hn; u < n; u++) {
|
|
||||||
a[u] = fpr_neg(a[u]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_mul_fft(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_mul_fft_avx2(a, b, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr a_re = a[u], a_im = a[u + hn];
|
|
||||||
fpr b_re = b[u], b_im = b[u + hn];
|
|
||||||
FPC_MUL(a[u], a[u + hn], a_re, a_im, b_re, b_im);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_muladj_fft(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_muladj_fft_avx2(a, b, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr a_re = a[u], a_im = a[u + hn];
|
|
||||||
fpr b_re = b[u], b_im = fpr_neg(b[u + hn]);
|
|
||||||
FPC_MUL(a[u], a[u + hn], a_re, a_im, b_re, b_im);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_mulselfadj_fft(fpr* a, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_mulselfadj_fft_avx2(a, logn);
|
|
||||||
#else
|
|
||||||
/* a * adj(a) = |a|^2 (real). */
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr a_re = a[u], a_im = a[u + hn];
|
|
||||||
a[u] = fpr_add(fpr_mul(a_re, a_re), fpr_mul(a_im, a_im));
|
|
||||||
a[u + hn] = fpr_zero;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_mulconst(fpr* a, fpr x, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_mulconst_avx2(a, x, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, u;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
a[u] = fpr_mul(a[u], x);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_div_fft(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr a_re = a[u], a_im = a[u + hn];
|
|
||||||
fpr b_re = b[u], b_im = b[u + hn];
|
|
||||||
FPC_DIV(a[u], a[u + hn], a_re, a_im, b_re, b_im);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_invnorm2_fft(fpr* d, const fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_invnorm2_fft_avx2(d, a, b, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr a_re = a[u], a_im = a[u + hn];
|
|
||||||
fpr b_re = b[u], b_im = b[u + hn];
|
|
||||||
d[u] = fpr_inv(fpr_add(
|
|
||||||
fpr_add(fpr_mul(a_re, a_re), fpr_mul(a_im, a_im)),
|
|
||||||
fpr_add(fpr_mul(b_re, b_re), fpr_mul(b_im, b_im))));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_add_muladj_fft(fpr* d, const fpr* F, const fpr* G,
|
|
||||||
const fpr* f, const fpr* g, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_add_muladj_fft_avx2(d, F, G, f, g, logn);
|
|
||||||
#else
|
|
||||||
/* d = F*adj(f) + G*adj(g). */
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr F_re = F[u], F_im = F[u + hn];
|
|
||||||
fpr G_re = G[u], G_im = G[u + hn];
|
|
||||||
fpr f_re = f[u], f_im = f[u + hn];
|
|
||||||
fpr g_re = g[u], g_im = g[u + hn];
|
|
||||||
fpr a_re, a_im, b_re, b_im;
|
|
||||||
FPC_MUL(a_re, a_im, F_re, F_im, f_re, fpr_neg(f_im));
|
|
||||||
FPC_MUL(b_re, b_im, G_re, G_im, g_re, fpr_neg(g_im));
|
|
||||||
d[u] = fpr_add(a_re, b_re);
|
|
||||||
d[u + hn] = fpr_add(a_im, b_im);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_mul_autoadj_fft(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
/* b is self-adjoint (real); only its lower half is meaningful. */
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
a[u] = fpr_mul(a[u], b[u]);
|
|
||||||
a[u + hn] = fpr_mul(a[u + hn], b[u]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_div_autoadj_fft(fpr* a, const fpr* b, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr ib = fpr_inv(b[u]);
|
|
||||||
a[u] = fpr_mul(a[u], ib);
|
|
||||||
a[u + hn] = fpr_mul(a[u + hn], ib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_LDL_fft(const fpr* g00, fpr* g01, fpr* g11, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr g00_re = g00[u], g00_im = g00[u + hn];
|
|
||||||
fpr g01_re = g01[u], g01_im = g01[u + hn];
|
|
||||||
fpr g11_re = g11[u], g11_im = g11[u + hn];
|
|
||||||
fpr mu_re, mu_im, xx_re, xx_im;
|
|
||||||
FPC_DIV(mu_re, mu_im, g01_re, g01_im, g00_re, g00_im);
|
|
||||||
FPC_MUL(xx_re, xx_im, mu_re, mu_im, g01_re, fpr_neg(g01_im));
|
|
||||||
FPC_SUB(g11[u], g11[u + hn], g11_re, g11_im, xx_re, xx_im);
|
|
||||||
g01[u] = mu_re;
|
|
||||||
g01[u + hn] = fpr_neg(mu_im);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_LDLmv_fft(fpr* d11, fpr* l10, const fpr* g00, const fpr* g01,
|
|
||||||
const fpr* g11, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_LDLmv_fft_avx2(d11, l10, g00, g01, g11, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, u;
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
fpr g00_re = g00[u], g00_im = g00[u + hn];
|
|
||||||
fpr g01_re = g01[u], g01_im = g01[u + hn];
|
|
||||||
fpr g11_re = g11[u], g11_im = g11[u + hn];
|
|
||||||
fpr mu_re, mu_im, xx_re, xx_im;
|
|
||||||
FPC_DIV(mu_re, mu_im, g01_re, g01_im, g00_re, g00_im);
|
|
||||||
FPC_MUL(xx_re, xx_im, mu_re, mu_im, g01_re, fpr_neg(g01_im));
|
|
||||||
FPC_SUB(d11[u], d11[u + hn], g11_re, g11_im, xx_re, xx_im);
|
|
||||||
l10[u] = mu_re;
|
|
||||||
l10[u + hn] = fpr_neg(mu_im);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_split_fft(fpr* f0, fpr* f1, const fpr* f, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_split_fft_avx2(f0, f1, f, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, qn = hn >> 1, u;
|
|
||||||
/* Base case (logn==1, qn==0): single coefficient halves. */
|
|
||||||
f0[0] = f[0];
|
|
||||||
f1[0] = f[hn];
|
|
||||||
for (u = 0; u < qn; u++) {
|
|
||||||
fpr a_re = f[(u << 1) + 0], a_im = f[(u << 1) + 0 + hn];
|
|
||||||
fpr b_re = f[(u << 1) + 1], b_im = f[(u << 1) + 1 + hn];
|
|
||||||
fpr t_re, t_im;
|
|
||||||
FPC_ADD(t_re, t_im, a_re, a_im, b_re, b_im);
|
|
||||||
f0[u] = fpr_half(t_re);
|
|
||||||
f0[u + qn] = fpr_half(t_im);
|
|
||||||
FPC_SUB(t_re, t_im, a_re, a_im, b_re, b_im);
|
|
||||||
FPC_MUL(t_re, t_im, t_re, t_im,
|
|
||||||
falcon_gm_tab[((u + hn) << 1) + 0],
|
|
||||||
fpr_neg(falcon_gm_tab[((u + hn) << 1) + 1]));
|
|
||||||
f1[u] = fpr_half(t_re);
|
|
||||||
f1[u + qn] = fpr_half(t_im);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void falcon_poly_merge_fft(fpr* f, const fpr* f0, const fpr* f1, unsigned logn)
|
|
||||||
{
|
|
||||||
#if defined(WOLFSSL_FALCON_FFT_AVX2)
|
|
||||||
falcon_poly_merge_fft_avx2(f, f0, f1, logn);
|
|
||||||
#else
|
|
||||||
size_t n = (size_t)1 << logn, hn = n >> 1, qn = hn >> 1, u;
|
|
||||||
/* Base case (logn==1, qn==0). */
|
|
||||||
f[0] = f0[0];
|
|
||||||
f[hn] = f1[0];
|
|
||||||
for (u = 0; u < qn; u++) {
|
|
||||||
fpr a_re = f0[u], a_im = f0[u + qn];
|
|
||||||
fpr b_re, b_im, t_re, t_im;
|
|
||||||
FPC_MUL(b_re, b_im, f1[u], f1[u + qn],
|
|
||||||
falcon_gm_tab[((u + hn) << 1) + 0],
|
|
||||||
falcon_gm_tab[((u + hn) << 1) + 1]);
|
|
||||||
FPC_ADD(t_re, t_im, a_re, a_im, b_re, b_im);
|
|
||||||
f[(u << 1) + 0] = t_re;
|
|
||||||
f[(u << 1) + 0 + hn] = t_im;
|
|
||||||
FPC_SUB(t_re, t_im, a_re, a_im, b_re, b_im);
|
|
||||||
f[(u << 1) + 1] = t_re;
|
|
||||||
f[(u << 1) + 1 + hn] = t_im;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
@@ -1,388 +0,0 @@
|
|||||||
/* wc_falcon_sampler.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Discrete Gaussian sampler (SamplerZ) for Falcon signing.
|
|
||||||
*
|
|
||||||
* This is a faithful port of the constant-time reference sampler written by
|
|
||||||
* Thomas Pornin for the Falcon submission (MIT licensed). The identical code
|
|
||||||
* is distributed in PQClean as the gaussian0_sampler / BerExp / sampler trio
|
|
||||||
* (e.g. crypto_sign/falcon-512/clean/sign.c). It has been adapted to wolfSSL
|
|
||||||
* house style (word32/word64/sword64, WOLFSSL_LOCAL linkage) and re-targeted
|
|
||||||
* onto two wolfSSL seams:
|
|
||||||
*
|
|
||||||
* 1. The floating-point seam wolfssl/wolfcrypt/wc_falcon_fpr.h. All real
|
|
||||||
* arithmetic goes through fpr_* (round-to-nearest-even IEEE-754 binary64,
|
|
||||||
* bit-exact and branch-free in the default integer-emulated backend), and
|
|
||||||
* the Bernoulli test uses fpr_expm_p63().
|
|
||||||
* 2. A SHAKE256 randomness stream (wolfssl/wolfcrypt/sha3.h) seeded from a
|
|
||||||
* WC_RNG (wolfssl/wolfcrypt/random.h), replacing the reference's ChaCha20
|
|
||||||
* PRNG. The sampler algorithm is agnostic to the byte source; only the
|
|
||||||
* uniform-byte contract matters for correctness and security.
|
|
||||||
*
|
|
||||||
* CONSTANT TIME / SIDE CHANNELS
|
|
||||||
* - gaussian0() consumes a fixed 9 random bytes and runs a fixed-length,
|
|
||||||
* branch-free table scan (comparison via borrow bits), so its running time
|
|
||||||
* and PRNG consumption are independent of the sampled value.
|
|
||||||
* - BerExp() and sampler() perform no branch or memory access that depends
|
|
||||||
* on the secret center (mu) or secret inverse-sigma (isigma): the only
|
|
||||||
* data-dependent control flow is the rejection-sampling retry loop and
|
|
||||||
* BerExp's lazy byte comparison, both of which depend solely on fresh
|
|
||||||
* uniform random bytes (the rejection probability is deliberately
|
|
||||||
* decorrelated from mu/sigma by the sigma_min scaling factor ccs). This is
|
|
||||||
* the standard Falcon argument; see the reference comments reproduced
|
|
||||||
* below.
|
|
||||||
* - The fpr backend supplies constant-time, value-independent arithmetic, so
|
|
||||||
* no floating-point operation leaks operand values through timing.
|
|
||||||
*
|
|
||||||
* This translation unit is the signing-only sampler and is therefore excluded
|
|
||||||
* from verify-only builds. */
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY) && !defined(WOLF_CRYPTO_CB_ONLY_FALCON)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_sampler.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fpr.h>
|
|
||||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
||||||
|
|
||||||
#ifdef NO_INLINE
|
|
||||||
#include <wolfssl/wolfcrypt/misc.h>
|
|
||||||
#else
|
|
||||||
#define WOLFSSL_MISC_INCLUDED
|
|
||||||
#include <wolfcrypt/src/misc.c>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* fpr constants needed by the sampler that are not exported by the seam. */
|
|
||||||
/* */
|
|
||||||
/* These are IEEE-754 binary64 bit patterns, identical to the values used by */
|
|
||||||
/* the Falcon reference (fpr.h). Each has been verified by decoding the bit */
|
|
||||||
/* pattern back to the documented decimal value (shown in the comment). */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* log(2) = 0.6931471805599453 */
|
|
||||||
static const fpr falcon_fpr_log2 = (fpr)4604418534313441775U;
|
|
||||||
/* 1/log(2) = 1.4426950408889634 */
|
|
||||||
static const fpr falcon_fpr_inv_log2 = (fpr)4609176140021203710U;
|
|
||||||
/* 1/(2*sigma0^2) with sigma0 = 1.8205 -> 0.15086504887537272 */
|
|
||||||
static const fpr falcon_fpr_inv_2sqrsigma0 = (fpr)4594603506513722306U;
|
|
||||||
|
|
||||||
/* sigma_min, indexed by logn (degree = 2^logn). These match the Falcon
|
|
||||||
* specification's sigma_min(n) table; entries decode to a smooth monotonic
|
|
||||||
* curve from 1.1165 (n=2) to 1.2983 (n=1024). Falcon uses logn 9 and 10:
|
|
||||||
* logn = 9 (Falcon-512 ) : 1.2778336969128337
|
|
||||||
* logn = 10 (Falcon-1024) : 1.298280334344292 */
|
|
||||||
static const fpr falcon_fpr_sigma_min[11] = {
|
|
||||||
(fpr)0U, /* logn 0 : unused */
|
|
||||||
(fpr)4607707126469777035U, /* logn 1 : 1.1165085072 */
|
|
||||||
(fpr)4607777455861499430U, /* logn 2 : 1.1321247692 */
|
|
||||||
(fpr)4607846828256951418U, /* logn 3 : 1.1475285354 */
|
|
||||||
(fpr)4607949175006100261U, /* logn 4 : 1.1702540789 */
|
|
||||||
(fpr)4608049571757433526U, /* logn 5 : 1.1925466358 */
|
|
||||||
(fpr)4608148125896792003U, /* logn 6 : 1.2144300508 */
|
|
||||||
(fpr)4608244935301382692U, /* logn 7 : 1.2359260568 */
|
|
||||||
(fpr)4608340089478362016U, /* logn 8 : 1.2570545284 */
|
|
||||||
(fpr)4608433670533905013U, /* logn 9 : 1.2778336969 */
|
|
||||||
(fpr)4608525754002622308U /* logn 10: 1.2982803343 */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* SHAKE256 pseudo-random byte stream. */
|
|
||||||
/* */
|
|
||||||
/* Construction: absorb FALCON_PRNG_SEED_LEN fresh bytes from WC_RNG into a */
|
|
||||||
/* SHAKE256 sponge, then squeeze the output in fixed FALCON_PRNG_BLOCKS-block */
|
|
||||||
/* batches. get_u64 reads 8 stream bytes little-endian; get_u8 reads one. */
|
|
||||||
/* The refill is a fixed-size squeeze, hence constant-time; consumption order */
|
|
||||||
/* (and thus how many bytes are discarded at a refill boundary) never */
|
|
||||||
/* depends on a secret. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* Squeeze a fresh batch of blocks into the buffer. Constant-time. */
|
|
||||||
static int falcon_prng_refill(falcon_prng* p)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Once the sticky error is latched the stream is already invalid and the
|
|
||||||
* result will be rejected; don't keep re-issuing failing squeezes. */
|
|
||||||
if (p->err != 0) {
|
|
||||||
p->ptr = 0;
|
|
||||||
p->len = 0;
|
|
||||||
return p->err;
|
|
||||||
}
|
|
||||||
ret = wc_Shake256_SqueezeBlocks(&p->shake, p->buf, FALCON_PRNG_BLOCKS);
|
|
||||||
p->ptr = 0;
|
|
||||||
p->len = (ret == 0) ? (word32)FALCON_PRNG_BUFLEN : 0;
|
|
||||||
/* Latch the first failure. get_u8/get_u64 have no error return, so a squeeze
|
|
||||||
* failure is made sticky here and checked by the signer (falcon_sign_core),
|
|
||||||
* which rejects any signature produced from an invalid PRNG state instead of
|
|
||||||
* consuming stale buffer bytes. */
|
|
||||||
if (ret != 0)
|
|
||||||
p->err = ret;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int falcon_prng_init(falcon_prng* p, WC_RNG* rng)
|
|
||||||
{
|
|
||||||
byte seed[FALCON_PRNG_SEED_LEN];
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (p == NULL || rng == NULL)
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
|
|
||||||
p->ptr = 0;
|
|
||||||
p->len = 0;
|
|
||||||
p->err = 0;
|
|
||||||
|
|
||||||
ret = wc_RNG_GenerateBlock(rng, seed, (word32)sizeof(seed));
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = wc_InitShake256(&p->shake, NULL, INVALID_DEVID);
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = wc_Shake256_Absorb(&p->shake, seed, (word32)sizeof(seed));
|
|
||||||
if (ret == 0)
|
|
||||||
ret = falcon_prng_refill(p);
|
|
||||||
/* On failure past a successful init the caller never sees a live
|
|
||||||
* context (falcon_native_sign_msg only frees the sponge when this
|
|
||||||
* function succeeded), so release it here. This matters in
|
|
||||||
* WOLFSSL_ASYNC_CRYPT builds where wc_InitShake256 allocates a
|
|
||||||
* device context. */
|
|
||||||
if (ret != 0)
|
|
||||||
wc_Shake256_Free(&p->shake);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ForceZero(seed, (word32)sizeof(seed));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte falcon_prng_get_u8(falcon_prng* p)
|
|
||||||
{
|
|
||||||
byte v;
|
|
||||||
|
|
||||||
/* On a refill failure len becomes 0 and p->err is latched; the buffer read
|
|
||||||
* below stays in bounds (ptr reset to 0) but yields a discarded value --
|
|
||||||
* falcon_sign_core checks p->err and rejects the resulting signature. */
|
|
||||||
if (p->ptr + 1U > p->len)
|
|
||||||
(void)falcon_prng_refill(p);
|
|
||||||
v = p->buf[p->ptr];
|
|
||||||
p->ptr += 1U;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
word64 falcon_prng_get_u64(falcon_prng* p)
|
|
||||||
{
|
|
||||||
word64 v;
|
|
||||||
word32 i;
|
|
||||||
|
|
||||||
if (p->ptr + 8U > p->len)
|
|
||||||
(void)falcon_prng_refill(p);
|
|
||||||
i = p->ptr;
|
|
||||||
v = (word64)p->buf[i + 0]
|
|
||||||
| ((word64)p->buf[i + 1] << 8)
|
|
||||||
| ((word64)p->buf[i + 2] << 16)
|
|
||||||
| ((word64)p->buf[i + 3] << 24)
|
|
||||||
| ((word64)p->buf[i + 4] << 32)
|
|
||||||
| ((word64)p->buf[i + 5] << 40)
|
|
||||||
| ((word64)p->buf[i + 6] << 48)
|
|
||||||
| ((word64)p->buf[i + 7] << 56);
|
|
||||||
p->ptr += 8U;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* gaussian0: base half-Gaussian sampler (centered on 0, sigma0 = 1.8205). */
|
|
||||||
/* */
|
|
||||||
/* Faithful port of Pornin's reference gaussian0_sampler. The RCDT (reverse */
|
|
||||||
/* cumulative distribution table) "dist[]" below is copied VERBATIM from the */
|
|
||||||
/* Falcon reference implementation (18 rows; each row is a 72-bit threshold */
|
|
||||||
/* stored as three 24-bit limbs, most significant limb first). It is the */
|
|
||||||
/* same table that appears in PQClean's */
|
|
||||||
/* crypto_sign/falcon-512/clean/sign.c */
|
|
||||||
/* and in the original Falcon round-3 reference. Do not edit these numbers. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
int falcon_gaussian0(falcon_prng* p)
|
|
||||||
{
|
|
||||||
/* RCDT for the half-Gaussian of standard deviation sigma0 = 1.8205,
|
|
||||||
* verbatim from the Falcon reference (Thomas Pornin). Each row holds a
|
|
||||||
* 72-bit value as (hi24, mid24, lo24). */
|
|
||||||
static const word32 dist[] = {
|
|
||||||
10745844u, 3068844u, 3741698u,
|
|
||||||
5559083u, 1580863u, 8248194u,
|
|
||||||
2260429u, 13669192u, 2736639u,
|
|
||||||
708981u, 4421575u, 10046180u,
|
|
||||||
169348u, 7122675u, 4136815u,
|
|
||||||
30538u, 13063405u, 7650655u,
|
|
||||||
4132u, 14505003u, 7826148u,
|
|
||||||
417u, 16768101u, 11363290u,
|
|
||||||
31u, 8444042u, 8086568u,
|
|
||||||
1u, 12844466u, 265321u,
|
|
||||||
0u, 1232676u, 13644283u,
|
|
||||||
0u, 38047u, 9111839u,
|
|
||||||
0u, 870u, 6138264u,
|
|
||||||
0u, 14u, 12545723u,
|
|
||||||
0u, 0u, 3104126u,
|
|
||||||
0u, 0u, 28824u,
|
|
||||||
0u, 0u, 198u,
|
|
||||||
0u, 0u, 1u
|
|
||||||
};
|
|
||||||
|
|
||||||
word32 v0, v1, v2, hi;
|
|
||||||
word64 lo;
|
|
||||||
word32 u;
|
|
||||||
int z;
|
|
||||||
|
|
||||||
/* Get a random 72-bit value, into three 24-bit limbs v0..v2. */
|
|
||||||
lo = falcon_prng_get_u64(p);
|
|
||||||
hi = (word32)falcon_prng_get_u8(p);
|
|
||||||
v0 = (word32)lo & 0xFFFFFFu;
|
|
||||||
v1 = (word32)(lo >> 24) & 0xFFFFFFu;
|
|
||||||
v2 = (word32)(lo >> 48) | (hi << 16);
|
|
||||||
|
|
||||||
/* Sampled value is z, the number of leading table thresholds that the
|
|
||||||
* uniform 72-bit value (v0..v2) is strictly less than. Done with borrow
|
|
||||||
* bits, fully branch-free. */
|
|
||||||
z = 0;
|
|
||||||
for (u = 0; u < (word32)((sizeof dist) / sizeof(dist[0])); u += 3) {
|
|
||||||
word32 w0, w1, w2, cc;
|
|
||||||
|
|
||||||
w0 = dist[u + 2];
|
|
||||||
w1 = dist[u + 1];
|
|
||||||
w2 = dist[u + 0];
|
|
||||||
cc = (v0 - w0) >> 31;
|
|
||||||
cc = (v1 - w1 - cc) >> 31;
|
|
||||||
cc = (v2 - w2 - cc) >> 31;
|
|
||||||
z += (int)cc;
|
|
||||||
}
|
|
||||||
return z;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* BerExp: Bernoulli test, returns 1 with probability ccs * exp(-x). */
|
|
||||||
/* */
|
|
||||||
/* Faithful port of Pornin's reference BerExp. x >= 0 is guaranteed by the */
|
|
||||||
/* caller. The only data-dependent loop is the lazy 8-bit comparison, whose */
|
|
||||||
/* iteration count depends on fresh random bytes, not on secrets. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
static int falcon_berexp(falcon_prng* p, fpr x, fpr ccs)
|
|
||||||
{
|
|
||||||
int s, i;
|
|
||||||
fpr r;
|
|
||||||
word32 sw, w;
|
|
||||||
word64 z;
|
|
||||||
|
|
||||||
/* Reduce x modulo log(2): x = s*log(2) + r, with s an integer and
|
|
||||||
* 0 <= r < log(2). Since x >= 0 we can use fpr_trunc (toward zero). */
|
|
||||||
s = (int)fpr_trunc(fpr_mul(x, falcon_fpr_inv_log2));
|
|
||||||
r = fpr_sub(x, fpr_mul(fpr_of((sword64)s), falcon_fpr_log2));
|
|
||||||
|
|
||||||
/* It may happen (rarely) that s >= 64; if so, BerExp would be non-zero
|
|
||||||
* with probability below 2^-64, so we simply saturate s at 63. */
|
|
||||||
sw = (word32)s;
|
|
||||||
sw ^= (sw ^ 63u) & (word32)(0U - ((63u - sw) >> 31));
|
|
||||||
s = (int)sw;
|
|
||||||
|
|
||||||
/* exp(-r), scaled to 2^63, scaled up to 2^64, then >> s to obtain
|
|
||||||
* exp(-x) = 2^-s * exp(-r). The "-1" keeps the value on 64 bits. */
|
|
||||||
z = ((fpr_expm_p63(r, ccs) << 1) - 1) >> s;
|
|
||||||
|
|
||||||
/* Compare exp(-x) against fresh random bytes, 8 bits at a time; the sign
|
|
||||||
* of the difference yields the sampled bit. */
|
|
||||||
i = 64;
|
|
||||||
do {
|
|
||||||
i -= 8;
|
|
||||||
w = (word32)falcon_prng_get_u8(p) - ((word32)(z >> i) & 0xFFu);
|
|
||||||
} while ((w == 0) && (i > 0));
|
|
||||||
|
|
||||||
return (int)(w >> 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* sampler (SamplerZ): discrete Gaussian of center mu, std dev 1/isigma. */
|
|
||||||
/* */
|
|
||||||
/* Faithful port of Pornin's reference sampler. ctx is an falcon_sampler_ctx. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
int falcon_sampler_z(void* ctx, fpr mu, fpr isigma)
|
|
||||||
{
|
|
||||||
falcon_sampler_ctx* spc = (falcon_sampler_ctx*)ctx;
|
|
||||||
int s;
|
|
||||||
fpr r, dss, ccs;
|
|
||||||
|
|
||||||
/* Center is mu = s + r, with s an integer and 0 <= r < 1. */
|
|
||||||
s = (int)fpr_floor(mu);
|
|
||||||
r = fpr_sub(mu, fpr_of((sword64)s));
|
|
||||||
|
|
||||||
/* dss = 1/(2*sigma^2) = 0.5 * isigma^2. */
|
|
||||||
dss = fpr_half(fpr_sqr(isigma));
|
|
||||||
|
|
||||||
/* ccs = sigma_min / sigma = sigma_min * isigma. */
|
|
||||||
ccs = fpr_mul(isigma, spc->sigma_min);
|
|
||||||
|
|
||||||
/* Sample on center r. */
|
|
||||||
for (;;) {
|
|
||||||
int z0, z, b;
|
|
||||||
fpr x;
|
|
||||||
|
|
||||||
/* A wedged PRNG (latched sticky error) turns every squeezed byte into
|
|
||||||
* a constant, which can make the rejection test below deterministic --
|
|
||||||
* and, if it rejects, this loop endless. Bail out instead: the value
|
|
||||||
* returned is discarded, as falcon_sign_core rejects the entire
|
|
||||||
* signature whenever p.err is set. */
|
|
||||||
if (spc->p.err != 0) {
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Half-Gaussian sample, plus a random bit b turning it bimodal:
|
|
||||||
* b = 1 -> use z0+1 (centered on 1), b = 0 -> use -z0 (centered 0). */
|
|
||||||
z0 = falcon_gaussian0(&spc->p);
|
|
||||||
b = (int)falcon_prng_get_u8(&spc->p) & 1;
|
|
||||||
z = b + ((b << 1) - 1) * z0;
|
|
||||||
|
|
||||||
/* Rejection sampling. Keep z with probability exp(-x), where
|
|
||||||
* x = ((z-r)^2)/(2*sigma^2) - (z0^2)/(2*sigma0^2).
|
|
||||||
* The sigma_min scaling in ccs decorrelates the rejection rate from
|
|
||||||
* mu/sigma, keeping the whole sampler constant-time. */
|
|
||||||
x = fpr_mul(fpr_sqr(fpr_sub(fpr_of((sword64)z), r)), dss);
|
|
||||||
x = fpr_sub(x, fpr_mul(fpr_of((sword64)(z0 * z0)),
|
|
||||||
falcon_fpr_inv_2sqrsigma0));
|
|
||||||
if (falcon_berexp(&spc->p, x, ccs)) {
|
|
||||||
/* Rejection was centered on r; the actual center is mu = s + r. */
|
|
||||||
return s + z;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
/* Context initialisation. */
|
|
||||||
/* ------------------------------------------------------------------------ */
|
|
||||||
int falcon_sampler_init(falcon_sampler_ctx* spc, int logn, WC_RNG* rng)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (spc == NULL || rng == NULL)
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
if (logn < 1 || logn > 10)
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
|
|
||||||
spc->sigma_min = falcon_fpr_sigma_min[logn];
|
|
||||||
ret = falcon_prng_init(&spc->p, rng);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
@@ -1,886 +0,0 @@
|
|||||||
/* wc_falcon_sign.c
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon signing orchestration. See wolfssl/wolfcrypt/wc_falcon_sign.h.
|
|
||||||
*
|
|
||||||
* Faithful port of the signature-generation core of the MIT-licensed Falcon
|
|
||||||
* reference implementation sign.c (Thomas Pornin, Falcon Project, 2017-2019):
|
|
||||||
* expand_privkey (B0 basis in FFT + ffLDL tree), ffSampling_fft and
|
|
||||||
* do_sign_tree. The big-integer NTRU completion of G (complete_private) is done
|
|
||||||
* here over the FFT seam. All floating-point work flows through the abstract
|
|
||||||
* fpr_* seam (wc_falcon_fpr / fft / poly); the discrete Gaussian sampler and its
|
|
||||||
* SHAKE256-backed randomness come from wc_falcon_sampler. */
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY) && !defined(WOLF_CRYPTO_CB_ONLY_FALCON)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_sign.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fpr.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fft.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_poly.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_sampler.h>
|
|
||||||
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
||||||
|
|
||||||
#define MKN(logn) ((size_t)1 << (logn))
|
|
||||||
|
|
||||||
#define FALCON_Q 12289
|
|
||||||
|
|
||||||
/* Safety bound on the sign-tree restart loop. The per-iteration restart
|
|
||||||
* probability is well below 1 (expected iteration count ~1), so the chance of
|
|
||||||
* legitimately reaching even a few dozen restarts is astronomically small; this
|
|
||||||
* bound is never approached in normal operation. It only guarantees termination
|
|
||||||
* if the sampler can no longer produce accepting candidates (e.g. a failed PRNG
|
|
||||||
* squeeze), in which case falcon_sign_core additionally rejects the result via
|
|
||||||
* the PRNG's sticky error. */
|
|
||||||
#define FALCON_SIGN_MAX_RESTARTS 4096UL
|
|
||||||
|
|
||||||
/* IEEE-754 binary64 bit patterns (the fpr seam carries doubles as word64).
|
|
||||||
* These mirror named constants from the reference fpr.h that are not part of
|
|
||||||
* the public wc_falcon_fpr.h API. fpr_invsqrt2 / fpr_invsqrt8 ARE exported by
|
|
||||||
* the seam and are used directly. */
|
|
||||||
static const fpr fpr_q = 4667981563525332992ULL; /* (double)12289 */
|
|
||||||
static const fpr fpr_inverse_of_q = 4545632735260551042ULL; /* 1/12289 */
|
|
||||||
|
|
||||||
/* 1/sigma, indexed by logn (1..10). Ported from the reference fpr.h. */
|
|
||||||
static const fpr fpr_inv_sigma[] = {
|
|
||||||
0, /* unused */
|
|
||||||
4574611497772390042ULL,
|
|
||||||
4574501679055810265ULL,
|
|
||||||
4574396282908341804ULL,
|
|
||||||
4574245855758572086ULL,
|
|
||||||
4574103865040221165ULL,
|
|
||||||
4573969550563515544ULL,
|
|
||||||
4573842244705920822ULL,
|
|
||||||
4573721358406441454ULL,
|
|
||||||
4573606369665796042ULL,
|
|
||||||
4573496814039276259ULL
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Acceptance bound for the (squared) l2-norm of the signature, indexed by logn
|
|
||||||
* (1..10). Inclusive bounds (= floor(beta^2)). Ported from the reference
|
|
||||||
* common.c l2bound[]. */
|
|
||||||
static const word32 l2bound[] = {
|
|
||||||
0, /* unused */
|
|
||||||
101498u,
|
|
||||||
208714u,
|
|
||||||
428865u,
|
|
||||||
892039u,
|
|
||||||
1852696u,
|
|
||||||
3842630u,
|
|
||||||
7959734u,
|
|
||||||
16468416u,
|
|
||||||
34034726u,
|
|
||||||
70265242u
|
|
||||||
};
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
|
||||||
/* complete_private: recompute G from (f, g, F). */
|
|
||||||
|
|
||||||
/* The keygen NTRU solver produces (F, G) such that f*G - g*F = q, hence
|
|
||||||
* G = (g*F + q) / f. We recompute it over the FFT seam, add the constant q to
|
|
||||||
* the real (lower) half of the FFT representation, divide by f, inverse-FFT and
|
|
||||||
* round to integers. */
|
|
||||||
int falcon_complete_private(sword8* G, const sword8* f, const sword8* g,
|
|
||||||
const sword8* F, unsigned logn, void* heap)
|
|
||||||
{
|
|
||||||
size_t n, hn, u;
|
|
||||||
fpr* t1;
|
|
||||||
fpr* t2;
|
|
||||||
fpr* t3;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (G == NULL || f == NULL || g == NULL || F == NULL
|
|
||||||
|| logn < 1 || logn > 10) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = MKN(logn);
|
|
||||||
hn = n >> 1;
|
|
||||||
|
|
||||||
/* Three working polynomials. */
|
|
||||||
t1 = (fpr*)XMALLOC((size_t)3 * n * sizeof(fpr), heap,
|
|
||||||
DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
if (t1 == NULL) {
|
|
||||||
return MEMORY_E;
|
|
||||||
}
|
|
||||||
t2 = t1 + n;
|
|
||||||
t3 = t2 + n;
|
|
||||||
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
t1[u] = fpr_of(g[u]); /* g */
|
|
||||||
t2[u] = fpr_of(F[u]); /* F */
|
|
||||||
t3[u] = fpr_of(f[u]); /* f */
|
|
||||||
}
|
|
||||||
falcon_FFT(t1, logn);
|
|
||||||
falcon_FFT(t2, logn);
|
|
||||||
falcon_FFT(t3, logn);
|
|
||||||
|
|
||||||
/* t1 <- g*F. */
|
|
||||||
falcon_poly_mul_fft(t1, t2, logn);
|
|
||||||
|
|
||||||
/* t1 <- g*F + q. The constant polynomial q evaluates to q (a real value) at
|
|
||||||
* every FFT point, so only the real (lower) half is incremented. */
|
|
||||||
for (u = 0; u < hn; u++) {
|
|
||||||
t1[u] = fpr_add(t1[u], fpr_q);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* t1 <- (g*F + q) / f. */
|
|
||||||
falcon_poly_div_fft(t1, t3, logn);
|
|
||||||
|
|
||||||
falcon_iFFT(t1, logn);
|
|
||||||
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
sword64 z;
|
|
||||||
|
|
||||||
z = fpr_rint(t1[u]);
|
|
||||||
if (z < -127 || z > 127) {
|
|
||||||
ret = BAD_FUNC_ARG;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
G[u] = (sword8)z;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* t1 held the FFT images of the secret basis (g, F, f) and the derived G. */
|
|
||||||
wc_ForceZero(t1, (word32)((size_t)3 * n * sizeof(fpr)));
|
|
||||||
XFREE(t1, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
|
||||||
/* ffLDL tree construction (expand_privkey). */
|
|
||||||
|
|
||||||
/* Size of the ffLDL tree (number of fpr elements) for polynomials of degree
|
|
||||||
* 2^logn: s(0) = 1, s(logn) = 2^logn + 2*s(logn-1) => (logn+1)*2^logn. */
|
|
||||||
static WC_INLINE unsigned ffLDL_treesize(unsigned logn)
|
|
||||||
{
|
|
||||||
return (logn + 1) << logn;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The reference implementation expresses ffLDL construction, tree
|
|
||||||
* normalization and Fast Fourier sampling as self-recursions on logn. wolfSSL
|
|
||||||
* forbids recursion, so each is flattened here into an iteration over an
|
|
||||||
* explicit stack of frames; depth is bounded by logn <= 10, so the stacks are
|
|
||||||
* small fixed arrays. Sub-invocations run in exactly the reference order --
|
|
||||||
* for ffSampling this is a hard requirement, since the discrete Gaussian
|
|
||||||
* sampler consumes a PRNG stream and only the reference order reproduces the
|
|
||||||
* reference signatures. */
|
|
||||||
|
|
||||||
/* One pending ffLDL_fft_inner sub-invocation. */
|
|
||||||
typedef struct ffLDL_job {
|
|
||||||
fpr* tree;
|
|
||||||
fpr* g0;
|
|
||||||
fpr* g1;
|
|
||||||
unsigned logn;
|
|
||||||
} ffLDL_job;
|
|
||||||
|
|
||||||
/* Iterative equivalent of the reference ffLDL_fft_inner recursion. All work of
|
|
||||||
* an invocation happens before its two half-degree sub-invocations, so a LIFO
|
|
||||||
* list of pending jobs suffices. Expects the (auto-adjoint, quasicyclic)
|
|
||||||
* matrix in (g0, g1), which are used as modifiable temporaries. tmp[] needs
|
|
||||||
* room for at least one polynomial; it is only used within a single job, never
|
|
||||||
* across jobs. */
|
|
||||||
static void ffLDL_fft_inner(fpr* tree, fpr* g0, fpr* g1, unsigned logn,
|
|
||||||
fpr* tmp)
|
|
||||||
{
|
|
||||||
/* A job at logn > 0 replaces itself with two jobs at logn - 1, leaving at
|
|
||||||
* most one pending sibling per level plus the current job: logn + 1
|
|
||||||
* frames, <= 11 for logn <= 10. */
|
|
||||||
ffLDL_job stk[11];
|
|
||||||
int sp;
|
|
||||||
|
|
||||||
stk[0].tree = tree;
|
|
||||||
stk[0].g0 = g0;
|
|
||||||
stk[0].g1 = g1;
|
|
||||||
stk[0].logn = logn;
|
|
||||||
sp = 0;
|
|
||||||
|
|
||||||
while (sp >= 0) {
|
|
||||||
ffLDL_job job;
|
|
||||||
size_t n, hn;
|
|
||||||
|
|
||||||
job = stk[sp];
|
|
||||||
sp--;
|
|
||||||
|
|
||||||
n = MKN(job.logn);
|
|
||||||
if (n == 1) {
|
|
||||||
job.tree[0] = job.g0[0];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
hn = n >> 1;
|
|
||||||
|
|
||||||
/* d00 = g0; d11 -> tmp; L[1][0] -> tree. */
|
|
||||||
falcon_poly_LDLmv_fft(tmp, job.tree, job.g0, job.g1, job.g0, job.logn);
|
|
||||||
|
|
||||||
/* Split d00 (in g0) and d11 (in tmp), reusing g0/g1 as scratch:
|
|
||||||
* d00 -> g1, g1+hn ; d11 -> g0, g0+hn. */
|
|
||||||
falcon_poly_split_fft(job.g1, job.g1 + hn, job.g0, job.logn);
|
|
||||||
falcon_poly_split_fft(job.g0, job.g0 + hn, tmp, job.logn);
|
|
||||||
|
|
||||||
/* Queue both half-degree sub-invocations; their buffers are disjoint.
|
|
||||||
* The d11 half (in g0) is pushed first so that the d00 half (in g1)
|
|
||||||
* runs first, matching the reference order. */
|
|
||||||
sp++;
|
|
||||||
stk[sp].tree = job.tree + n + ffLDL_treesize(job.logn - 1);
|
|
||||||
stk[sp].g0 = job.g0;
|
|
||||||
stk[sp].g1 = job.g0 + hn;
|
|
||||||
stk[sp].logn = job.logn - 1;
|
|
||||||
sp++;
|
|
||||||
stk[sp].tree = job.tree + n;
|
|
||||||
stk[sp].g0 = job.g1;
|
|
||||||
stk[sp].g1 = job.g1 + hn;
|
|
||||||
stk[sp].logn = job.logn - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Compute the ffLDL tree of the auto-adjoint matrix [[g00, adj(g01)],
|
|
||||||
* [g01, g11]] (FFT representation). tmp[] needs room for at least three
|
|
||||||
* polynomials. */
|
|
||||||
static void ffLDL_fft(fpr* tree, const fpr* g00, const fpr* g01,
|
|
||||||
const fpr* g11, unsigned logn, fpr* tmp)
|
|
||||||
{
|
|
||||||
size_t n, hn;
|
|
||||||
fpr* d00;
|
|
||||||
fpr* d11;
|
|
||||||
|
|
||||||
n = MKN(logn);
|
|
||||||
if (n == 1) {
|
|
||||||
tree[0] = g00[0];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hn = n >> 1;
|
|
||||||
d00 = tmp;
|
|
||||||
d11 = tmp + n;
|
|
||||||
tmp += n << 1;
|
|
||||||
|
|
||||||
XMEMCPY(d00, g00, n * sizeof(*g00));
|
|
||||||
falcon_poly_LDLmv_fft(d11, tree, g00, g01, g11, logn);
|
|
||||||
|
|
||||||
falcon_poly_split_fft(tmp, tmp + hn, d00, logn);
|
|
||||||
falcon_poly_split_fft(d00, d00 + hn, d11, logn);
|
|
||||||
XMEMCPY(d11, tmp, n * sizeof(*tmp));
|
|
||||||
ffLDL_fft_inner(tree + n, d11, d11 + hn, logn - 1, tmp);
|
|
||||||
ffLDL_fft_inner(tree + n + ffLDL_treesize(logn - 1),
|
|
||||||
d00, d00 + hn, logn - 1, tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Normalize an ffLDL tree: each leaf x is replaced with sigma/sqrt(x). The leaf
|
|
||||||
* stores the inverse of the spec value, saving a division here and in the
|
|
||||||
* sampler. Iterative equivalent of the reference recursion: internal nodes do
|
|
||||||
* no work of their own, so a LIFO list of pending subtrees replaces the two
|
|
||||||
* tail calls (see ffLDL_fft_inner for the occupancy bound). */
|
|
||||||
static void ffLDL_binary_normalize(fpr* tree, unsigned orig_logn, unsigned logn)
|
|
||||||
{
|
|
||||||
struct {
|
|
||||||
fpr* tree;
|
|
||||||
unsigned logn;
|
|
||||||
} stk[11];
|
|
||||||
int sp;
|
|
||||||
|
|
||||||
stk[0].tree = tree;
|
|
||||||
stk[0].logn = logn;
|
|
||||||
sp = 0;
|
|
||||||
|
|
||||||
while (sp >= 0) {
|
|
||||||
fpr* t;
|
|
||||||
unsigned l;
|
|
||||||
size_t n;
|
|
||||||
|
|
||||||
t = stk[sp].tree;
|
|
||||||
l = stk[sp].logn;
|
|
||||||
sp--;
|
|
||||||
|
|
||||||
n = MKN(l);
|
|
||||||
if (n == 1) {
|
|
||||||
t[0] = fpr_mul(fpr_sqrt(t[0]), fpr_inv_sigma[orig_logn]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp++;
|
|
||||||
stk[sp].tree = t + n + ffLDL_treesize(l - 1);
|
|
||||||
stk[sp].logn = l - 1;
|
|
||||||
sp++;
|
|
||||||
stk[sp].tree = t + n;
|
|
||||||
stk[sp].logn = l - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convert a small-integer polynomial into the fpr representation. */
|
|
||||||
static void smallints_to_fpr(fpr* r, const sword8* t, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n, u;
|
|
||||||
|
|
||||||
n = MKN(logn);
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
r[u] = fpr_of(t[u]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Expanded-key layout offsets (in fpr elements). */
|
|
||||||
static WC_INLINE size_t skoff_b00(unsigned logn) { (void)logn; return 0; }
|
|
||||||
static WC_INLINE size_t skoff_b01(unsigned logn) { return MKN(logn); }
|
|
||||||
static WC_INLINE size_t skoff_b10(unsigned logn) { return 2 * MKN(logn); }
|
|
||||||
static WC_INLINE size_t skoff_b11(unsigned logn) { return 3 * MKN(logn); }
|
|
||||||
static WC_INLINE size_t skoff_tree(unsigned logn) { return 4 * MKN(logn); }
|
|
||||||
|
|
||||||
int falcon_expand_privkey(fpr* expanded, const sword8* f, const sword8* g,
|
|
||||||
const sword8* F, const sword8* G, unsigned logn, void* heap)
|
|
||||||
{
|
|
||||||
size_t n;
|
|
||||||
fpr* rf;
|
|
||||||
fpr* rg;
|
|
||||||
fpr* rF;
|
|
||||||
fpr* rG;
|
|
||||||
fpr* b00;
|
|
||||||
fpr* b01;
|
|
||||||
fpr* b10;
|
|
||||||
fpr* b11;
|
|
||||||
fpr* g00;
|
|
||||||
fpr* g01;
|
|
||||||
fpr* g11;
|
|
||||||
fpr* gxx;
|
|
||||||
fpr* tree;
|
|
||||||
fpr* tmp;
|
|
||||||
|
|
||||||
if (expanded == NULL || f == NULL || g == NULL || F == NULL || G == NULL
|
|
||||||
|| logn < 1 || logn > 10) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = MKN(logn);
|
|
||||||
|
|
||||||
/* Internal scratch: six polynomials (matches the reference 48*2^logn). */
|
|
||||||
tmp = (fpr*)XMALLOC((size_t)6 * n * sizeof(fpr), heap,
|
|
||||||
DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
if (tmp == NULL) {
|
|
||||||
return MEMORY_E;
|
|
||||||
}
|
|
||||||
|
|
||||||
b00 = expanded + skoff_b00(logn);
|
|
||||||
b01 = expanded + skoff_b01(logn);
|
|
||||||
b10 = expanded + skoff_b10(logn);
|
|
||||||
b11 = expanded + skoff_b11(logn);
|
|
||||||
tree = expanded + skoff_tree(logn);
|
|
||||||
|
|
||||||
/* B0 = [[g, -f], [G, -F]]. */
|
|
||||||
rf = b01;
|
|
||||||
rg = b00;
|
|
||||||
rF = b11;
|
|
||||||
rG = b10;
|
|
||||||
|
|
||||||
smallints_to_fpr(rf, f, logn);
|
|
||||||
smallints_to_fpr(rg, g, logn);
|
|
||||||
smallints_to_fpr(rF, F, logn);
|
|
||||||
smallints_to_fpr(rG, G, logn);
|
|
||||||
|
|
||||||
falcon_FFT(rf, logn);
|
|
||||||
falcon_FFT(rg, logn);
|
|
||||||
falcon_FFT(rF, logn);
|
|
||||||
falcon_FFT(rG, logn);
|
|
||||||
falcon_poly_neg(rf, logn);
|
|
||||||
falcon_poly_neg(rF, logn);
|
|
||||||
|
|
||||||
/* Gram matrix G = B*B^* (upper triangle: g00, g01, g11). */
|
|
||||||
g00 = tmp;
|
|
||||||
g01 = g00 + n;
|
|
||||||
g11 = g01 + n;
|
|
||||||
gxx = g11 + n;
|
|
||||||
|
|
||||||
XMEMCPY(g00, b00, n * sizeof(*b00));
|
|
||||||
falcon_poly_mulselfadj_fft(g00, logn);
|
|
||||||
XMEMCPY(gxx, b01, n * sizeof(*b01));
|
|
||||||
falcon_poly_mulselfadj_fft(gxx, logn);
|
|
||||||
falcon_poly_add(g00, gxx, logn);
|
|
||||||
|
|
||||||
XMEMCPY(g01, b00, n * sizeof(*b00));
|
|
||||||
falcon_poly_muladj_fft(g01, b10, logn);
|
|
||||||
XMEMCPY(gxx, b01, n * sizeof(*b01));
|
|
||||||
falcon_poly_muladj_fft(gxx, b11, logn);
|
|
||||||
falcon_poly_add(g01, gxx, logn);
|
|
||||||
|
|
||||||
XMEMCPY(g11, b10, n * sizeof(*b10));
|
|
||||||
falcon_poly_mulselfadj_fft(g11, logn);
|
|
||||||
XMEMCPY(gxx, b11, n * sizeof(*b11));
|
|
||||||
falcon_poly_mulselfadj_fft(gxx, logn);
|
|
||||||
falcon_poly_add(g11, gxx, logn);
|
|
||||||
|
|
||||||
/* Falcon tree, then normalization. */
|
|
||||||
ffLDL_fft(tree, g00, g01, g11, logn, gxx);
|
|
||||||
ffLDL_binary_normalize(tree, logn, logn);
|
|
||||||
|
|
||||||
/* tmp held the secret-derived Gram matrix and ffLDL intermediates. */
|
|
||||||
wc_ForceZero(tmp, (word32)((size_t)6 * n * sizeof(fpr)));
|
|
||||||
XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
|
||||||
/* Fast Fourier sampling. */
|
|
||||||
|
|
||||||
/* Base case at logn == 2 (n = 4): the two bottom levels of the sampling
|
|
||||||
* walk, fully unrolled over the four coefficients (as in the reference). */
|
|
||||||
static WC_INLINE void ffSampling_fft_deg4(falcon_samplerZ samp, void* samp_ctx,
|
|
||||||
fpr* z0, fpr* z1, const fpr* tree, const fpr* t0, const fpr* t1)
|
|
||||||
{
|
|
||||||
const fpr* tree0;
|
|
||||||
const fpr* tree1;
|
|
||||||
fpr x0, x1, y0, y1, w0, w1, w2, w3, sigma;
|
|
||||||
fpr a_re, a_im, b_re, b_im, c_re, c_im;
|
|
||||||
|
|
||||||
tree0 = tree + 4;
|
|
||||||
tree1 = tree + 8;
|
|
||||||
|
|
||||||
a_re = t1[0];
|
|
||||||
a_im = t1[2];
|
|
||||||
b_re = t1[1];
|
|
||||||
b_im = t1[3];
|
|
||||||
c_re = fpr_add(a_re, b_re);
|
|
||||||
c_im = fpr_add(a_im, b_im);
|
|
||||||
w0 = fpr_half(c_re);
|
|
||||||
w1 = fpr_half(c_im);
|
|
||||||
c_re = fpr_sub(a_re, b_re);
|
|
||||||
c_im = fpr_sub(a_im, b_im);
|
|
||||||
w2 = fpr_mul(fpr_add(c_re, c_im), fpr_invsqrt8);
|
|
||||||
w3 = fpr_mul(fpr_sub(c_im, c_re), fpr_invsqrt8);
|
|
||||||
|
|
||||||
x0 = w2;
|
|
||||||
x1 = w3;
|
|
||||||
sigma = tree1[3];
|
|
||||||
w2 = fpr_of(samp(samp_ctx, x0, sigma));
|
|
||||||
w3 = fpr_of(samp(samp_ctx, x1, sigma));
|
|
||||||
a_re = fpr_sub(x0, w2);
|
|
||||||
a_im = fpr_sub(x1, w3);
|
|
||||||
b_re = tree1[0];
|
|
||||||
b_im = tree1[1];
|
|
||||||
c_re = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im));
|
|
||||||
c_im = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re));
|
|
||||||
x0 = fpr_add(c_re, w0);
|
|
||||||
x1 = fpr_add(c_im, w1);
|
|
||||||
sigma = tree1[2];
|
|
||||||
w0 = fpr_of(samp(samp_ctx, x0, sigma));
|
|
||||||
w1 = fpr_of(samp(samp_ctx, x1, sigma));
|
|
||||||
|
|
||||||
a_re = w0;
|
|
||||||
a_im = w1;
|
|
||||||
b_re = w2;
|
|
||||||
b_im = w3;
|
|
||||||
c_re = fpr_mul(fpr_sub(b_re, b_im), fpr_invsqrt2);
|
|
||||||
c_im = fpr_mul(fpr_add(b_re, b_im), fpr_invsqrt2);
|
|
||||||
z1[0] = w0 = fpr_add(a_re, c_re);
|
|
||||||
z1[2] = w2 = fpr_add(a_im, c_im);
|
|
||||||
z1[1] = w1 = fpr_sub(a_re, c_re);
|
|
||||||
z1[3] = w3 = fpr_sub(a_im, c_im);
|
|
||||||
|
|
||||||
w0 = fpr_sub(t1[0], w0);
|
|
||||||
w1 = fpr_sub(t1[1], w1);
|
|
||||||
w2 = fpr_sub(t1[2], w2);
|
|
||||||
w3 = fpr_sub(t1[3], w3);
|
|
||||||
|
|
||||||
a_re = w0;
|
|
||||||
a_im = w2;
|
|
||||||
b_re = tree[0];
|
|
||||||
b_im = tree[2];
|
|
||||||
w0 = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im));
|
|
||||||
w2 = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re));
|
|
||||||
a_re = w1;
|
|
||||||
a_im = w3;
|
|
||||||
b_re = tree[1];
|
|
||||||
b_im = tree[3];
|
|
||||||
w1 = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im));
|
|
||||||
w3 = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re));
|
|
||||||
|
|
||||||
w0 = fpr_add(w0, t0[0]);
|
|
||||||
w1 = fpr_add(w1, t0[1]);
|
|
||||||
w2 = fpr_add(w2, t0[2]);
|
|
||||||
w3 = fpr_add(w3, t0[3]);
|
|
||||||
|
|
||||||
a_re = w0;
|
|
||||||
a_im = w2;
|
|
||||||
b_re = w1;
|
|
||||||
b_im = w3;
|
|
||||||
c_re = fpr_add(a_re, b_re);
|
|
||||||
c_im = fpr_add(a_im, b_im);
|
|
||||||
w0 = fpr_half(c_re);
|
|
||||||
w1 = fpr_half(c_im);
|
|
||||||
c_re = fpr_sub(a_re, b_re);
|
|
||||||
c_im = fpr_sub(a_im, b_im);
|
|
||||||
w2 = fpr_mul(fpr_add(c_re, c_im), fpr_invsqrt8);
|
|
||||||
w3 = fpr_mul(fpr_sub(c_im, c_re), fpr_invsqrt8);
|
|
||||||
|
|
||||||
x0 = w2;
|
|
||||||
x1 = w3;
|
|
||||||
sigma = tree0[3];
|
|
||||||
w2 = y0 = fpr_of(samp(samp_ctx, x0, sigma));
|
|
||||||
w3 = y1 = fpr_of(samp(samp_ctx, x1, sigma));
|
|
||||||
a_re = fpr_sub(x0, y0);
|
|
||||||
a_im = fpr_sub(x1, y1);
|
|
||||||
b_re = tree0[0];
|
|
||||||
b_im = tree0[1];
|
|
||||||
c_re = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im));
|
|
||||||
c_im = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re));
|
|
||||||
x0 = fpr_add(c_re, w0);
|
|
||||||
x1 = fpr_add(c_im, w1);
|
|
||||||
sigma = tree0[2];
|
|
||||||
w0 = fpr_of(samp(samp_ctx, x0, sigma));
|
|
||||||
w1 = fpr_of(samp(samp_ctx, x1, sigma));
|
|
||||||
|
|
||||||
a_re = w0;
|
|
||||||
a_im = w1;
|
|
||||||
b_re = w2;
|
|
||||||
b_im = w3;
|
|
||||||
c_re = fpr_mul(fpr_sub(b_re, b_im), fpr_invsqrt2);
|
|
||||||
c_im = fpr_mul(fpr_add(b_re, b_im), fpr_invsqrt2);
|
|
||||||
z0[0] = fpr_add(a_re, c_re);
|
|
||||||
z0[2] = fpr_add(a_im, c_im);
|
|
||||||
z0[1] = fpr_sub(a_re, c_re);
|
|
||||||
z0[3] = fpr_sub(a_im, c_im);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Base case at logn == 1 (n = 2): reachable only for the (insecure) smallest
|
|
||||||
* degree. */
|
|
||||||
static WC_INLINE void ffSampling_fft_deg2(falcon_samplerZ samp, void* samp_ctx,
|
|
||||||
fpr* z0, fpr* z1, const fpr* tree, const fpr* t0, const fpr* t1)
|
|
||||||
{
|
|
||||||
fpr x0, x1, y0, y1, sigma;
|
|
||||||
fpr a_re, a_im, b_re, b_im, c_re, c_im;
|
|
||||||
|
|
||||||
x0 = t1[0];
|
|
||||||
x1 = t1[1];
|
|
||||||
sigma = tree[3];
|
|
||||||
z1[0] = y0 = fpr_of(samp(samp_ctx, x0, sigma));
|
|
||||||
z1[1] = y1 = fpr_of(samp(samp_ctx, x1, sigma));
|
|
||||||
a_re = fpr_sub(x0, y0);
|
|
||||||
a_im = fpr_sub(x1, y1);
|
|
||||||
b_re = tree[0];
|
|
||||||
b_im = tree[1];
|
|
||||||
c_re = fpr_sub(fpr_mul(a_re, b_re), fpr_mul(a_im, b_im));
|
|
||||||
c_im = fpr_add(fpr_mul(a_re, b_im), fpr_mul(a_im, b_re));
|
|
||||||
x0 = fpr_add(c_re, t0[0]);
|
|
||||||
x1 = fpr_add(c_im, t0[1]);
|
|
||||||
sigma = tree[2];
|
|
||||||
z0[0] = fpr_of(samp(samp_ctx, x0, sigma));
|
|
||||||
z0[1] = fpr_of(samp(samp_ctx, x1, sigma));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* One flattened falcon_ffSampling_fft invocation at logn >= 3. Each frame is
|
|
||||||
* visited three times, tracked by 'stage':
|
|
||||||
* FF_SAMP_STAGE_T1: split t1 and descend into the tree1 subtree;
|
|
||||||
* FF_SAMP_STAGE_T0: merge z1, build tb0 = t0 + (t1 - z1)*L in tmp, split
|
|
||||||
* it and descend into the tree0 subtree;
|
|
||||||
* FF_SAMP_STAGE_DONE: merge z0 and pop back to the parent frame. */
|
|
||||||
typedef struct ffSampling_frame {
|
|
||||||
fpr* z0;
|
|
||||||
fpr* z1;
|
|
||||||
const fpr* tree;
|
|
||||||
const fpr* t0;
|
|
||||||
const fpr* t1;
|
|
||||||
fpr* tmp;
|
|
||||||
unsigned logn;
|
|
||||||
unsigned stage;
|
|
||||||
} ffSampling_frame;
|
|
||||||
|
|
||||||
#define FF_SAMP_STAGE_T1 0U
|
|
||||||
#define FF_SAMP_STAGE_T0 1U
|
|
||||||
#define FF_SAMP_STAGE_DONE 2U
|
|
||||||
|
|
||||||
/* Maximum frame-stack depth: one frame per level from the top logn down to 3
|
|
||||||
* (levels 2 and 1 run as the inlined base cases above), so at most logn - 2
|
|
||||||
* <= 8 frames for logn <= 10. */
|
|
||||||
#define FF_SAMP_MAX_FRAMES 8
|
|
||||||
|
|
||||||
/* Descend into a sub-invocation at 'logn': run the base case directly when
|
|
||||||
* the walk bottoms out (logn == 2), otherwise push a frame for the state
|
|
||||||
* machine in falcon_ffSampling_fft. Returns the new top-of-stack index. */
|
|
||||||
static WC_INLINE int ffSampling_descend(ffSampling_frame* stk, int sp,
|
|
||||||
falcon_samplerZ samp, void* samp_ctx, fpr* z0, fpr* z1,
|
|
||||||
const fpr* tree, const fpr* t0, const fpr* t1, unsigned logn, fpr* tmp)
|
|
||||||
{
|
|
||||||
if (logn == 2) {
|
|
||||||
ffSampling_fft_deg4(samp, samp_ctx, z0, z1, tree, t0, t1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
sp++;
|
|
||||||
stk[sp].z0 = z0;
|
|
||||||
stk[sp].z1 = z1;
|
|
||||||
stk[sp].tree = tree;
|
|
||||||
stk[sp].t0 = t0;
|
|
||||||
stk[sp].t1 = t1;
|
|
||||||
stk[sp].tmp = tmp;
|
|
||||||
stk[sp].logn = logn;
|
|
||||||
stk[sp].stage = FF_SAMP_STAGE_T1;
|
|
||||||
}
|
|
||||||
return sp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Iterative equivalent of the reference ffSampling_fft recursion. The frames
|
|
||||||
* are visited -- and hence the sampler is invoked -- in exactly the reference
|
|
||||||
* recursion order; the sampler consumes a PRNG stream, so preserving that
|
|
||||||
* order is what keeps the produced signatures identical to the reference. */
|
|
||||||
void falcon_ffSampling_fft(falcon_samplerZ samp, void* samp_ctx,
|
|
||||||
fpr* z0, fpr* z1, const fpr* tree, const fpr* t0, const fpr* t1,
|
|
||||||
unsigned logn, fpr* tmp)
|
|
||||||
{
|
|
||||||
ffSampling_frame stk[FF_SAMP_MAX_FRAMES];
|
|
||||||
int sp;
|
|
||||||
|
|
||||||
/* Degrees handled entirely by the inlined base cases. */
|
|
||||||
if (logn == 2) {
|
|
||||||
ffSampling_fft_deg4(samp, samp_ctx, z0, z1, tree, t0, t1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (logn == 1) {
|
|
||||||
ffSampling_fft_deg2(samp, samp_ctx, z0, z1, tree, t0, t1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
/* Callers validate 1 <= logn <= 10 (falcon_do_sign_tree); this keeps the
|
|
||||||
* frame stack in bounds regardless. */
|
|
||||||
if (logn < 1 || logn > 10) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sp = ffSampling_descend(stk, -1, samp, samp_ctx, z0, z1, tree, t0, t1,
|
|
||||||
logn, tmp);
|
|
||||||
|
|
||||||
while (sp >= 0) {
|
|
||||||
ffSampling_frame* f;
|
|
||||||
size_t n, hn;
|
|
||||||
|
|
||||||
f = &stk[sp];
|
|
||||||
n = (size_t)1 << f->logn;
|
|
||||||
hn = n >> 1;
|
|
||||||
|
|
||||||
switch (f->stage) {
|
|
||||||
case FF_SAMP_STAGE_T1:
|
|
||||||
f->stage = FF_SAMP_STAGE_T0;
|
|
||||||
/* Split t1 into z1, then sample the halves against the tree1
|
|
||||||
* subtree; the sampled halves land in tmp, tmp + hn. */
|
|
||||||
falcon_poly_split_fft(f->z1, f->z1 + hn, f->t1, f->logn);
|
|
||||||
sp = ffSampling_descend(stk, sp, samp, samp_ctx,
|
|
||||||
f->tmp, f->tmp + hn,
|
|
||||||
f->tree + n + ffLDL_treesize(f->logn - 1),
|
|
||||||
f->z1, f->z1 + hn, f->logn - 1, f->tmp + n);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case FF_SAMP_STAGE_T0:
|
|
||||||
f->stage = FF_SAMP_STAGE_DONE;
|
|
||||||
/* Merge the sampled halves back into z1. */
|
|
||||||
falcon_poly_merge_fft(f->z1, f->tmp, f->tmp + hn, f->logn);
|
|
||||||
|
|
||||||
/* tb0 = t0 + (t1 - z1) * L, built in tmp[]. */
|
|
||||||
XMEMCPY(f->tmp, f->t1, n * sizeof(*f->t1));
|
|
||||||
falcon_poly_sub(f->tmp, f->z1, f->logn);
|
|
||||||
falcon_poly_mul_fft(f->tmp, f->tree, f->logn);
|
|
||||||
falcon_poly_add(f->tmp, f->t0, f->logn);
|
|
||||||
|
|
||||||
/* Split tb0 into z0, then sample the halves against the tree0
|
|
||||||
* subtree. */
|
|
||||||
falcon_poly_split_fft(f->z0, f->z0 + hn, f->tmp, f->logn);
|
|
||||||
sp = ffSampling_descend(stk, sp, samp, samp_ctx,
|
|
||||||
f->tmp, f->tmp + hn, f->tree + n,
|
|
||||||
f->z0, f->z0 + hn, f->logn - 1, f->tmp + n);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* FF_SAMP_STAGE_DONE: merge the sampled halves back into z0;
|
|
||||||
* this invocation is complete. */
|
|
||||||
falcon_poly_merge_fft(f->z0, f->tmp, f->tmp + hn, f->logn);
|
|
||||||
sp--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ==================================================================== */
|
|
||||||
/* do_sign_tree / sign_core. */
|
|
||||||
|
|
||||||
/* is_short_half: squared l2-norm of (s1, s2) where the s1 partial sum (sqn) is
|
|
||||||
* already accumulated and saturates to 2^32-1. Returns 1 if within bound. */
|
|
||||||
static int is_short_half(word32 sqn, const sword16* s2, unsigned logn)
|
|
||||||
{
|
|
||||||
size_t n, u;
|
|
||||||
word32 ng;
|
|
||||||
|
|
||||||
n = (size_t)1 << logn;
|
|
||||||
ng = (word32)(0 - (sqn >> 31));
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
sword32 z;
|
|
||||||
|
|
||||||
z = s2[u];
|
|
||||||
sqn += (word32)(z * z);
|
|
||||||
ng |= sqn;
|
|
||||||
}
|
|
||||||
sqn |= (word32)(0 - (ng >> 31));
|
|
||||||
|
|
||||||
return sqn <= l2bound[logn];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Single signing attempt over the expanded key. Returns 1 if the produced
|
|
||||||
* (s1, s2) is short enough (s2 written), 0 if the caller should retry. tmp[]
|
|
||||||
* needs room for six polynomials. */
|
|
||||||
static int do_sign_tree_once(falcon_samplerZ samp, void* samp_ctx, sword16* s2,
|
|
||||||
const fpr* expanded, const word16* hm, unsigned logn, fpr* tmp)
|
|
||||||
{
|
|
||||||
size_t n, u;
|
|
||||||
fpr* t0;
|
|
||||||
fpr* t1;
|
|
||||||
fpr* tx;
|
|
||||||
fpr* ty;
|
|
||||||
const fpr* b00;
|
|
||||||
const fpr* b01;
|
|
||||||
const fpr* b10;
|
|
||||||
const fpr* b11;
|
|
||||||
const fpr* tree;
|
|
||||||
fpr ni;
|
|
||||||
word32 sqn, ng;
|
|
||||||
sword16* s1tmp;
|
|
||||||
sword16* s2tmp;
|
|
||||||
|
|
||||||
n = MKN(logn);
|
|
||||||
t0 = tmp;
|
|
||||||
t1 = t0 + n;
|
|
||||||
b00 = expanded + skoff_b00(logn);
|
|
||||||
b01 = expanded + skoff_b01(logn);
|
|
||||||
b10 = expanded + skoff_b10(logn);
|
|
||||||
b11 = expanded + skoff_b11(logn);
|
|
||||||
tree = expanded + skoff_tree(logn);
|
|
||||||
|
|
||||||
/* Target vector [hm, 0]. */
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
t0[u] = fpr_of(hm[u]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Apply the basis to obtain the real target (after q-normalization). */
|
|
||||||
falcon_FFT(t0, logn);
|
|
||||||
ni = fpr_inverse_of_q;
|
|
||||||
XMEMCPY(t1, t0, n * sizeof(*t0));
|
|
||||||
falcon_poly_mul_fft(t1, b01, logn);
|
|
||||||
falcon_poly_mulconst(t1, fpr_neg(ni), logn);
|
|
||||||
falcon_poly_mul_fft(t0, b11, logn);
|
|
||||||
falcon_poly_mulconst(t0, ni, logn);
|
|
||||||
|
|
||||||
tx = t1 + n;
|
|
||||||
ty = tx + n;
|
|
||||||
|
|
||||||
/* Sampling; output written to [tx, ty]. */
|
|
||||||
falcon_ffSampling_fft(samp, samp_ctx, tx, ty, tree, t0, t1, logn, ty + n);
|
|
||||||
|
|
||||||
/* Lattice point corresponding to that short vector. */
|
|
||||||
XMEMCPY(t0, tx, n * sizeof(*tx));
|
|
||||||
XMEMCPY(t1, ty, n * sizeof(*ty));
|
|
||||||
falcon_poly_mul_fft(tx, b00, logn);
|
|
||||||
falcon_poly_mul_fft(ty, b10, logn);
|
|
||||||
falcon_poly_add(tx, ty, logn);
|
|
||||||
XMEMCPY(ty, t0, n * sizeof(*t0));
|
|
||||||
falcon_poly_mul_fft(ty, b01, logn);
|
|
||||||
|
|
||||||
XMEMCPY(t0, tx, n * sizeof(*tx));
|
|
||||||
falcon_poly_mul_fft(t1, b11, logn);
|
|
||||||
falcon_poly_add(t1, ty, logn);
|
|
||||||
|
|
||||||
falcon_iFFT(t0, logn);
|
|
||||||
falcon_iFFT(t1, logn);
|
|
||||||
|
|
||||||
/* s1 = hm - round(t0); accumulate squared norm with saturation. */
|
|
||||||
s1tmp = (sword16*)tx;
|
|
||||||
sqn = 0;
|
|
||||||
ng = 0;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
sword32 z;
|
|
||||||
|
|
||||||
z = (sword32)hm[u] - (sword32)fpr_rint(t0[u]);
|
|
||||||
sqn += (word32)(z * z);
|
|
||||||
ng |= sqn;
|
|
||||||
s1tmp[u] = (sword16)z;
|
|
||||||
}
|
|
||||||
sqn |= (word32)(0 - (ng >> 31));
|
|
||||||
|
|
||||||
/* s2 = -round(t1) (written into tmp; never into s2[] until accepted, so a
|
|
||||||
* retry preserves hm[]). */
|
|
||||||
s2tmp = (sword16*)tmp;
|
|
||||||
for (u = 0; u < n; u++) {
|
|
||||||
s2tmp[u] = (sword16)(0 - fpr_rint(t1[u]));
|
|
||||||
}
|
|
||||||
if (is_short_half(sqn, s2tmp, logn)) {
|
|
||||||
XMEMCPY(s2, s2tmp, n * sizeof(*s2));
|
|
||||||
XMEMCPY(tmp, s1tmp, n * sizeof(*s1tmp));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int falcon_do_sign_tree(falcon_samplerZ samp, void* samp_ctx, sword16* s2,
|
|
||||||
const fpr* expanded, const word16* hm, unsigned logn, fpr* tmp,
|
|
||||||
const int* samplerErr)
|
|
||||||
{
|
|
||||||
if (samp == NULL || s2 == NULL || expanded == NULL || hm == NULL
|
|
||||||
|| tmp == NULL || logn < 1 || logn > 10) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Loop until the candidate (s1, s2) is short enough. With degrees 512 and
|
|
||||||
* 1024 a restart is very rare (expected iteration count is ~1), so the
|
|
||||||
* bound below is astronomically beyond any legitimate run; it exists only
|
|
||||||
* so a wedged sampler -- e.g. a PRNG whose SHAKE256 squeeze started failing,
|
|
||||||
* yielding candidates that never pass the norm bound -- terminates instead
|
|
||||||
* of spinning forever. */
|
|
||||||
{
|
|
||||||
unsigned long iter;
|
|
||||||
for (iter = 0; iter < FALCON_SIGN_MAX_RESTARTS; iter++) {
|
|
||||||
if (do_sign_tree_once(samp, samp_ctx, s2, expanded, hm, logn, tmp)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Fail fast on a sampler PRNG error (non-secret, already latched):
|
|
||||||
* no point burning restarts on candidates built from invalid
|
|
||||||
* randomness. */
|
|
||||||
if (samplerErr != NULL && *samplerErr != 0) {
|
|
||||||
return *samplerErr;
|
|
||||||
}
|
|
||||||
#ifdef WOLFSSL_FALCON_SIGN_STATS
|
|
||||||
/* Optional instrumentation for test harnesses: counts the rare
|
|
||||||
* ffSampling restarts. Not compiled into production builds. */
|
|
||||||
extern unsigned long falcon_sign_restart_count;
|
|
||||||
falcon_sign_restart_count++;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Exhausted the restart bound: treat as an operational failure. */
|
|
||||||
return WC_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
int falcon_sign_core(falcon_sampler_ctx* spc, const fpr* expanded,
|
|
||||||
const word16* c, sword16* s2, fpr* tmp, unsigned logn)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (spc == NULL) {
|
|
||||||
return BAD_FUNC_ARG;
|
|
||||||
}
|
|
||||||
ret = falcon_do_sign_tree(falcon_sampler_z, spc, s2, expanded, c, logn, tmp,
|
|
||||||
&spc->p.err);
|
|
||||||
/* Reject the signature if the sampler's PRNG failed at any point: the
|
|
||||||
* squeezed bytes it consumed would be invalid, so the result is unsafe. */
|
|
||||||
if (ret == 0 && spc->p.err != 0) {
|
|
||||||
ret = spc->p.err;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
@@ -254,16 +254,14 @@ nobase_include_HEADERS+= wolfssl/wolfcrypt/port/riscv/riscv-64-asm.h
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if BUILD_FALCON
|
if BUILD_FALCON
|
||||||
# Internal Falcon headers (the public API is wolfssl/wolfcrypt/falcon.h, listed
|
# Internal Falcon headers kept for the separate AVX2/NEON FFT backends, which
|
||||||
# unconditionally above). Automake distributes both branches of a conditional,
|
# share the fpr primitives, the falcon_gm_tab twiddle table, and the poly seam
|
||||||
# so these are still included in "make dist" when Falcon is disabled.
|
# with the merged falcon.c. The rest of the Falcon internals now live as static
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_bigint.h
|
# code inside falcon.c. The public API is wolfssl/wolfcrypt/falcon.h (above).
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_codec.h
|
# Automake distributes both branches of a conditional, so these are still
|
||||||
|
# included in "make dist" when Falcon is disabled.
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_fft.h
|
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_fft.h
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_fpr.h
|
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_fpr.h
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_keygen.h
|
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_poly.h
|
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_poly.h
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_sampler.h
|
|
||||||
nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_falcon_sign.h
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,138 +0,0 @@
|
|||||||
/* wc_falcon_bigint.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file wolfssl/wolfcrypt/wc_falcon_bigint.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Self-contained big-integer / RNS arithmetic for native Falcon
|
|
||||||
* key generation.
|
|
||||||
*
|
|
||||||
* Falcon key generation solves the NTRU equation g*F - f*G = q, which is
|
|
||||||
* performed by the Falcon "ntru_solve" routine. That routine relies on a
|
|
||||||
* specialized integer-only big-number layer using a residue number system
|
|
||||||
* (RNS) of 31-bit prime moduli, with a small-modulus NTT for fast
|
|
||||||
* polynomial arithmetic and an extended-binary-GCD (Bezout) solver.
|
|
||||||
*
|
|
||||||
* The algorithms and limb conventions here are ported faithfully from the
|
|
||||||
* Falcon reference implementation keygen.c by Thomas Pornin (MIT licensed):
|
|
||||||
* - big integers are little-endian arrays of word32 "limbs", each limb
|
|
||||||
* holding 31 bits of value (the top bit is unused for carry handling);
|
|
||||||
* - products use word64; signed reductions use sword32 / sword64;
|
|
||||||
* - the RNS primes p satisfy 2^30 < p < 2^31 and p = 1 mod 2048.
|
|
||||||
*
|
|
||||||
* This module is INTEGER-ONLY and independent of the floating-point seam.
|
|
||||||
* It is excluded from verify-only builds (keygen is not needed there). */
|
|
||||||
|
|
||||||
#ifndef WOLF_CRYPT_WC_FALCON_BIGINT_H
|
|
||||||
#define WOLF_CRYPT_WC_FALCON_BIGINT_H
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* One entry of the RNS small-prime table. Fields mirror the Falcon
|
|
||||||
* reference small_prime structure:
|
|
||||||
* p A prime modulus, with 2^30 < p < 2^31 and p = 1 mod 2048.
|
|
||||||
* g A primitive root of phi = X^N+1 in the field Z_p.
|
|
||||||
* s The inverse of the product of all previous primes in the table,
|
|
||||||
* computed modulo p and in Montgomery representation.
|
|
||||||
* The table is sorted in decreasing order of p and terminated with a
|
|
||||||
* { 0, 0, 0 } sentinel. */
|
|
||||||
typedef struct falcon_small_prime {
|
|
||||||
word32 p;
|
|
||||||
word32 g;
|
|
||||||
word32 s;
|
|
||||||
} falcon_small_prime;
|
|
||||||
|
|
||||||
/* RNS prime table (terminated with a { 0, 0, 0 } sentinel). */
|
|
||||||
WOLFSSL_LOCAL extern const falcon_small_prime FALCON_PRIMES[];
|
|
||||||
|
|
||||||
/* ---- modular small-integer helpers (single 31-bit prime modulus) ---- */
|
|
||||||
WOLFSSL_LOCAL word32 modp_set(sword32 x, word32 p);
|
|
||||||
WOLFSSL_LOCAL sword32 modp_norm(word32 x, word32 p);
|
|
||||||
WOLFSSL_LOCAL word32 modp_ninv31(word32 p);
|
|
||||||
WOLFSSL_LOCAL word32 modp_R(word32 p);
|
|
||||||
WOLFSSL_LOCAL word32 modp_add(word32 a, word32 b, word32 p);
|
|
||||||
WOLFSSL_LOCAL word32 modp_sub(word32 a, word32 b, word32 p);
|
|
||||||
WOLFSSL_LOCAL word32 modp_montymul(word32 a, word32 b, word32 p, word32 p0i);
|
|
||||||
WOLFSSL_LOCAL word32 modp_R2(word32 p, word32 p0i);
|
|
||||||
WOLFSSL_LOCAL word32 modp_Rx(unsigned int x, word32 p, word32 p0i, word32 R2);
|
|
||||||
/* Modular division a/b mod p (returns 0 when b == 0). This is the
|
|
||||||
* reference's modular-inverse helper (the canonical Falcon keygen.c has no
|
|
||||||
* separately named "modp_get_inv"; modp_div(R,b,...) yields 1/b). */
|
|
||||||
WOLFSSL_LOCAL word32 modp_div(word32 a, word32 b, word32 p, word32 p0i,
|
|
||||||
word32 R);
|
|
||||||
|
|
||||||
/* ---- small-modulus NTT used in the RNS ---- */
|
|
||||||
WOLFSSL_LOCAL void modp_mkgm2(word32* gm, word32* igm, unsigned int logn,
|
|
||||||
word32 g, word32 p, word32 p0i);
|
|
||||||
WOLFSSL_LOCAL void modp_NTT2_ext(word32* a, size_t stride, const word32* gm,
|
|
||||||
unsigned int logn, word32 p, word32 p0i);
|
|
||||||
WOLFSSL_LOCAL void modp_iNTT2_ext(word32* a, size_t stride, const word32* igm,
|
|
||||||
unsigned int logn, word32 p, word32 p0i);
|
|
||||||
|
|
||||||
/* Convenience wrappers for unit-stride polynomials. */
|
|
||||||
#define modp_NTT2(a, gm, logn, p, p0i) \
|
|
||||||
modp_NTT2_ext(a, 1, gm, logn, p, p0i)
|
|
||||||
#define modp_iNTT2(a, igm, logn, p, p0i) \
|
|
||||||
modp_iNTT2_ext(a, 1, igm, logn, p, p0i)
|
|
||||||
|
|
||||||
/* ---- big-integer (zint) helpers ---- */
|
|
||||||
WOLFSSL_LOCAL word32 zint_sub(word32* a, const word32* b, size_t len,
|
|
||||||
word32 ctl);
|
|
||||||
WOLFSSL_LOCAL word32 zint_mul_small(word32* m, size_t mlen, word32 x);
|
|
||||||
WOLFSSL_LOCAL word32 zint_mod_small_unsigned(const word32* d, size_t dlen,
|
|
||||||
word32 p, word32 p0i, word32 R2);
|
|
||||||
WOLFSSL_LOCAL word32 zint_mod_small_signed(const word32* d, size_t dlen,
|
|
||||||
word32 p, word32 p0i, word32 R2, word32 Rx);
|
|
||||||
WOLFSSL_LOCAL void zint_add_mul_small(word32* x, const word32* y, size_t len,
|
|
||||||
word32 s);
|
|
||||||
WOLFSSL_LOCAL void zint_norm_zero(word32* x, const word32* p, size_t len);
|
|
||||||
WOLFSSL_LOCAL void zint_rebuild_CRT(word32* xx, size_t xlen, size_t xstride,
|
|
||||||
size_t num, const falcon_small_prime* primes, int normalize_signed,
|
|
||||||
word32* tmp);
|
|
||||||
WOLFSSL_LOCAL void zint_negate(word32* a, size_t len, word32 ctl);
|
|
||||||
WOLFSSL_LOCAL word32 zint_co_reduce(word32* a, word32* b, size_t len,
|
|
||||||
sword64 xa, sword64 xb, sword64 ya, sword64 yb);
|
|
||||||
WOLFSSL_LOCAL void zint_finish_mod(word32* a, size_t len, const word32* m,
|
|
||||||
word32 neg);
|
|
||||||
WOLFSSL_LOCAL void zint_co_reduce_mod(word32* a, word32* b, const word32* m,
|
|
||||||
size_t len, word32 m0i, sword64 xa, sword64 xb, sword64 ya,
|
|
||||||
sword64 yb);
|
|
||||||
WOLFSSL_LOCAL int zint_bezout(word32* u, word32* v, const word32* x,
|
|
||||||
const word32* y, size_t len, word32* tmp);
|
|
||||||
WOLFSSL_LOCAL void zint_add_scaled_mul_small(word32* x, size_t xlen,
|
|
||||||
const word32* y, size_t ylen, sword32 k, word32 sch, word32 scl);
|
|
||||||
WOLFSSL_LOCAL void zint_sub_scaled(word32* x, size_t xlen, const word32* y,
|
|
||||||
size_t ylen, word32 sch, word32 scl);
|
|
||||||
WOLFSSL_LOCAL sword32 zint_one_to_plain(const word32* x);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
#endif /* WOLF_CRYPT_WC_FALCON_BIGINT_H */
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
/* wc_falcon_codec.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon encode/decode routines for the
|
|
||||||
* signing and key-generation paths. The verification-side decoders
|
|
||||||
* (modq_decode, comp_decode) live as static functions in wc_falcon.c and are
|
|
||||||
* not referenced here. */
|
|
||||||
|
|
||||||
#ifndef WOLF_CRYPT_WC_FALCON_CODEC_H
|
|
||||||
#define WOLF_CRYPT_WC_FALCON_CODEC_H
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Golomb-Rice (k=7) compress of the signature polynomial s2. Exact inverse of
|
|
||||||
* the reference comp_decode. Rejects any |x[i]| > 2047. Returns the number of
|
|
||||||
* bytes written, or 0 on range violation / output overflow. */
|
|
||||||
WOLFSSL_LOCAL size_t falcon_comp_encode(byte* out, size_t max_out,
|
|
||||||
const sword16* x, unsigned logn);
|
|
||||||
|
|
||||||
/* 14-bit big-endian pack of the public-key polynomial h. Each coefficient must
|
|
||||||
* be < q (12289). Returns the number of bytes written, or 0 on range violation
|
|
||||||
* / output overflow. */
|
|
||||||
WOLFSSL_LOCAL size_t falcon_modq_encode(byte* out, size_t max_out,
|
|
||||||
const word16* x, unsigned logn);
|
|
||||||
|
|
||||||
/* Signed 8-bit polynomial pack/unpack using a fixed per-coefficient bit width.
|
|
||||||
* The most-negative value -2^(bits-1) is forbidden (matching the reference). */
|
|
||||||
WOLFSSL_LOCAL size_t falcon_trim_i8_encode(byte* out, size_t max_out,
|
|
||||||
const sword8* x, unsigned logn, unsigned bits);
|
|
||||||
WOLFSSL_LOCAL size_t falcon_trim_i8_decode(sword8* x, unsigned logn,
|
|
||||||
unsigned bits, const byte* in, size_t max_in);
|
|
||||||
|
|
||||||
/* Decode a Falcon secret key: header byte (0x50 | logn), then trim_i8 encoded
|
|
||||||
* f, g (max_fg_bits[logn]) and F (max_FG_bits[logn]). Validates the header and
|
|
||||||
* that the input length is exactly consumed. Returns 0 on success or a negative
|
|
||||||
* wolfCrypt error. */
|
|
||||||
WOLFSSL_LOCAL int falcon_privkey_decode(const byte* sk, size_t sklen,
|
|
||||||
sword8* f, sword8* g, sword8* F, unsigned logn);
|
|
||||||
|
|
||||||
/* Encode a Falcon secret key from (f, g, F). Inverse of falcon_privkey_decode.
|
|
||||||
* Returns bytes written, or 0 on failure. */
|
|
||||||
WOLFSSL_LOCAL size_t falcon_privkey_encode(byte* sk, size_t max_sk,
|
|
||||||
const sword8* f, const sword8* g, const sword8* F, unsigned logn);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
|
|
||||||
#endif /* WOLF_CRYPT_WC_FALCON_CODEC_H */
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
/* wc_falcon_keygen.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file wolfssl/wolfcrypt/wc_falcon_keygen.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon key-pair generation.
|
|
||||||
*
|
|
||||||
* Generates an (f, g, F, G) NTRU lattice basis together with the public key
|
|
||||||
* h = g/f mod q. The procedure is a faithful port of the key-generation half
|
|
||||||
* of the MIT-licensed Falcon reference implementation keygen.c (Thomas
|
|
||||||
* Pornin):
|
|
||||||
*
|
|
||||||
* - sample f, g from a discrete Gaussian of standard deviation
|
|
||||||
* 1.17*sqrt(q/(2n)), driven by a SHAKE256 stream seeded from a WC_RNG;
|
|
||||||
* - reject (f, g) until the resultant with X^n+1 is odd, the (g,-f) norm
|
|
||||||
* and the orthogonalized vector norm are below the 1.17*sqrt(q) bound,
|
|
||||||
* and f is invertible modulo q;
|
|
||||||
* - solve the NTRU equation f*G - g*F = q with the recursive "ntru_solve"
|
|
||||||
* built on the validated big-integer / RNS layer (wc_falcon_bigint);
|
|
||||||
* - return the basis and the public polynomial h.
|
|
||||||
*
|
|
||||||
* This module is excluded from verify-only builds (keygen is not needed
|
|
||||||
* there) and depends on the floating-point seam (wc_falcon_fpr / fft / poly). */
|
|
||||||
|
|
||||||
#ifndef WOLF_CRYPT_WC_FALCON_KEYGEN_H
|
|
||||||
#define WOLF_CRYPT_WC_FALCON_KEYGEN_H
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Generate a complete Falcon key pair of degree n = 2^logn.
|
|
||||||
*
|
|
||||||
* rng initialized WC_RNG used to seed the SHAKE256 sampler stream.
|
|
||||||
* f,g output secret polynomials (n signed coefficients each).
|
|
||||||
* F,G output NTRU completion polynomials (n signed coefficients each);
|
|
||||||
* G may be reconstructed internally but is always written out here.
|
|
||||||
* h output public key polynomial (n coefficients in [0, q)); may be
|
|
||||||
* NULL if only the (f,g,F,G) basis is required.
|
|
||||||
* logn base-2 logarithm of the ring degree (1..10; 9 and 10 are the
|
|
||||||
* Falcon-512 and Falcon-1024 levels).
|
|
||||||
*
|
|
||||||
* The routine loops, drawing fresh (f,g) until every acceptance test passes
|
|
||||||
* and the NTRU equation is solved, exactly as the reference does. Returns 0
|
|
||||||
* on success or a negative wolfCrypt error code. */
|
|
||||||
WOLFSSL_LOCAL int falcon_keygen(WC_RNG* rng, sword8* f, sword8* g,
|
|
||||||
sword8* F, sword8* G, word16* h, unsigned logn);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
#endif /* WOLF_CRYPT_WC_FALCON_KEYGEN_H */
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
/* wc_falcon_sampler.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file wolfssl/wolfcrypt/wc_falcon_sampler.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Discrete Gaussian sampler for Falcon signing (SamplerZ).
|
|
||||||
*
|
|
||||||
* This is a faithful port of the constant-time reference sampler by Thomas
|
|
||||||
* Pornin (MIT-licensed Falcon reference implementation; the same code ships in
|
|
||||||
* PQClean as PQCLEAN_FALCONxxx_CLEAN_gaussian0_sampler / BerExp / sampler).
|
|
||||||
* The floating-point work is done exclusively through the abstract fpr_* seam
|
|
||||||
* (wolfssl/wolfcrypt/wc_falcon_fpr.h), so the sampler inherits the deterministic
|
|
||||||
* bit-exact, branch-free IEEE-754 behaviour of whatever fpr backend is active.
|
|
||||||
*
|
|
||||||
* SECURITY: the sampler is constant-time with respect to the secret center
|
|
||||||
* (mu) and the secret inverse standard deviation (isigma). There are no
|
|
||||||
* secret-dependent branches or memory accesses; see the notes in
|
|
||||||
* wc_falcon_sampler.c. Randomness is drawn from a SHAKE256 stream seeded from a
|
|
||||||
* WC_RNG instance. This file is compiled only on the signing side. */
|
|
||||||
|
|
||||||
#ifndef WOLF_CRYPT_WC_FALCON_SAMPLER_H
|
|
||||||
#define WOLF_CRYPT_WC_FALCON_SAMPLER_H
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fpr.h>
|
|
||||||
#include <wolfssl/wolfcrypt/sha3.h>
|
|
||||||
#include <wolfssl/wolfcrypt/random.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* PRNG buffer: an integral number of SHAKE256 squeeze blocks (rate = 136
|
|
||||||
* bytes). 136 is divisible by 8, so 8-byte reads never straddle the boundary
|
|
||||||
* that triggers a refill. */
|
|
||||||
#define FALCON_PRNG_BLOCKS 8
|
|
||||||
#define FALCON_PRNG_BUFLEN (FALCON_PRNG_BLOCKS * WC_SHA3_256_BLOCK_SIZE)
|
|
||||||
|
|
||||||
/* SHAKE256-backed pseudo-random byte stream.
|
|
||||||
*
|
|
||||||
* Construction: the SHAKE256 sponge absorbs a seed obtained from WC_RNG
|
|
||||||
* (FALCON_PRNG_SEED_LEN fresh random bytes), then is squeezed in fixed-size
|
|
||||||
* blocks. get_u8 returns the next stream byte; get_u64 returns the next 8
|
|
||||||
* stream bytes interpreted little-endian. */
|
|
||||||
typedef struct falcon_prng {
|
|
||||||
wc_Shake shake; /* SHAKE256 sponge state */
|
|
||||||
byte buf[FALCON_PRNG_BUFLEN];/* squeezed stream buffer */
|
|
||||||
word32 ptr; /* index of next byte to consume */
|
|
||||||
word32 len; /* number of valid bytes in buf */
|
|
||||||
int err; /* sticky: first refill error, or 0 */
|
|
||||||
} falcon_prng;
|
|
||||||
|
|
||||||
/* Sampler context: the PRNG plus the parameter-set-dependent sigma_min. */
|
|
||||||
typedef struct falcon_sampler_ctx {
|
|
||||||
falcon_prng p;
|
|
||||||
fpr sigma_min; /* sigma_min for the active logn */
|
|
||||||
} falcon_sampler_ctx;
|
|
||||||
|
|
||||||
/* Seed length (bytes) drawn from WC_RNG to key the SHAKE256 stream. */
|
|
||||||
#define FALCON_PRNG_SEED_LEN 56
|
|
||||||
|
|
||||||
/* PRNG primitives. */
|
|
||||||
WOLFSSL_LOCAL int falcon_prng_init(falcon_prng* p, WC_RNG* rng);
|
|
||||||
WOLFSSL_LOCAL byte falcon_prng_get_u8(falcon_prng* p);
|
|
||||||
WOLFSSL_LOCAL word64 falcon_prng_get_u64(falcon_prng* p);
|
|
||||||
|
|
||||||
/* Initialise a sampler context for the given degree (logn = 9 or 10), seeding
|
|
||||||
* the PRNG from rng. Returns 0 on success or a negative wolfCrypt error. */
|
|
||||||
WOLFSSL_LOCAL int falcon_sampler_init(falcon_sampler_ctx* spc, int logn,
|
|
||||||
WC_RNG* rng);
|
|
||||||
|
|
||||||
/* The base half-Gaussian sampler (z >= 0, sigma0 = 1.8205). Exposed for test
|
|
||||||
* harnesses; consumes 9 PRNG bytes. */
|
|
||||||
WOLFSSL_LOCAL int falcon_gaussian0(falcon_prng* p);
|
|
||||||
|
|
||||||
/* SamplerZ: return an integer sampled from the discrete Gaussian of center mu
|
|
||||||
* and standard deviation 1/isigma. ctx is a (falcon_sampler_ctx*). */
|
|
||||||
WOLFSSL_LOCAL int falcon_sampler_z(void* ctx, fpr mu, fpr isigma);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
#endif /* WOLF_CRYPT_WC_FALCON_SAMPLER_H */
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
/* wc_falcon_sign.h
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006-2026 wolfSSL Inc.
|
|
||||||
*
|
|
||||||
* This file is part of wolfSSL.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* wolfSSL 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 a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*!
|
|
||||||
\file wolfssl/wolfcrypt/wc_falcon_sign.h
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Falcon signing orchestration (the "tree" signer).
|
|
||||||
*
|
|
||||||
* Faithful port of the signature-generation core of the MIT-licensed Falcon
|
|
||||||
* reference implementation sign.c (Thomas Pornin, Falcon Project, 2017-2019):
|
|
||||||
*
|
|
||||||
* - falcon_complete_private: recompute G from (f, g, F) using the NTRU
|
|
||||||
* relation f*G - g*F = q (so G = (g*F + q)/f), via the FFT seam.
|
|
||||||
* - falcon_expand_privkey: build the B0 = [[g, -f], [G, -F]] basis in FFT
|
|
||||||
* representation, the Gram matrix G = B*B^*, and the normalized ffLDL
|
|
||||||
* tree (the "expanded private key").
|
|
||||||
* - falcon_ffSampling_fft: the Fast Fourier sampling walk driving the
|
|
||||||
* discrete Gaussian sampler over the ffLDL tree. The reference expresses
|
|
||||||
* this (and the ffLDL construction) as recursions; per wolfSSL's
|
|
||||||
* no-recursion rule they are implemented as explicit-stack iterations
|
|
||||||
* that visit sub-problems in the exact reference order.
|
|
||||||
* - falcon_do_sign_tree / falcon_sign_core: produce the signature short
|
|
||||||
* vector s2, looping over the sampler until the (s1, s2) squared l2-norm
|
|
||||||
* is within the Falcon acceptance bound.
|
|
||||||
*
|
|
||||||
* The floating-point work flows exclusively through the abstract fpr_* seam
|
|
||||||
* (wc_falcon_fpr.h), the FFT (wc_falcon_fft.h) and the FFT-domain polynomial
|
|
||||||
* primitives (wc_falcon_poly.h); randomness for the sampler comes from the
|
|
||||||
* SHAKE256-backed sampler context (wc_falcon_sampler.h). This module is
|
|
||||||
* compiled only on the signing side. */
|
|
||||||
|
|
||||||
#ifndef WOLF_CRYPT_WC_FALCON_SIGN_H
|
|
||||||
#define WOLF_CRYPT_WC_FALCON_SIGN_H
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/types.h>
|
|
||||||
|
|
||||||
#if defined(HAVE_FALCON) && !defined(WOLFSSL_FALCON_VERIFY_ONLY)
|
|
||||||
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_fpr.h>
|
|
||||||
#include <wolfssl/wolfcrypt/wc_falcon_sampler.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Number of fpr elements in an expanded private key for degree n = 2^logn.
|
|
||||||
* Layout: the four B0 matrix polynomials (b00, b01, b10, b11), each of n
|
|
||||||
* elements, followed by the ffLDL tree of (logn+1)*2^logn elements. The total
|
|
||||||
* is therefore (logn+5)*2^logn fpr (matching the reference's (8*logn+40)*2^logn
|
|
||||||
* bytes). */
|
|
||||||
#define FALCON_EXPANDED_KEY_FPR(logn) (((size_t)((logn) + 5)) << (logn))
|
|
||||||
|
|
||||||
/* Number of fpr elements of scratch required by falcon_do_sign_tree /
|
|
||||||
* falcon_sign_core (six polynomials of degree n), matching the reference's
|
|
||||||
* 48*2^logn bytes. */
|
|
||||||
#define FALCON_SIGN_TMP_FPR(logn) ((size_t)6 << (logn))
|
|
||||||
|
|
||||||
/* The discrete-Gaussian sampler callback type used by ffSampling. The second
|
|
||||||
* argument is the center mu, the third the inverse standard deviation isigma.
|
|
||||||
* falcon_sampler_z (wc_falcon_sampler.h) implements this contract. */
|
|
||||||
typedef int (*falcon_samplerZ)(void* ctx, fpr mu, fpr isigma);
|
|
||||||
|
|
||||||
/* Recompute the NTRU completion polynomial G from (f, g, F) such that
|
|
||||||
* f*G - g*F = q (G = (g*F + q)/f), computed over the FFT seam and rounded to
|
|
||||||
* integers. G receives n signed coefficients. For a well-formed key the
|
|
||||||
* quotient is exact; a rounded coefficient outside the [-127, 127] range is
|
|
||||||
* rejected (this also catches a grossly inconsistent/corrupt key). Returns 0 on
|
|
||||||
* success, or a negative wolfCrypt error on out-of-range coefficient or memory
|
|
||||||
* allocation failure. */
|
|
||||||
WOLFSSL_LOCAL int falcon_complete_private(sword8* G, const sword8* f,
|
|
||||||
const sword8* g, const sword8* F, unsigned logn, void* heap);
|
|
||||||
|
|
||||||
/* Expand the private basis (f, g, F, G) into 'expanded' (which must hold
|
|
||||||
* FALCON_EXPANDED_KEY_FPR(logn) fpr elements): the B0 matrix in FFT
|
|
||||||
* representation and the normalized ffLDL tree. Allocates an internal scratch
|
|
||||||
* of FALCON_SIGN_TMP_FPR(logn) fpr. Returns 0 on success or a negative
|
|
||||||
* wolfCrypt error. */
|
|
||||||
WOLFSSL_LOCAL int falcon_expand_privkey(fpr* expanded, const sword8* f,
|
|
||||||
const sword8* g, const sword8* F, const sword8* G, unsigned logn,
|
|
||||||
void* heap);
|
|
||||||
|
|
||||||
/* Fast Fourier sampling: sample the target (t0, t1) against the ffLDL 'tree',
|
|
||||||
* writing the sampled lattice coordinates into (z0, z1). 'tmp' needs room for
|
|
||||||
* at least two polynomials of degree 2^logn. Iterative (explicit-stack)
|
|
||||||
* equivalent of the reference ffSampling_fft recursion; sampler invocation
|
|
||||||
* order is identical to the reference. */
|
|
||||||
WOLFSSL_LOCAL void falcon_ffSampling_fft(falcon_samplerZ samp, void* samp_ctx,
|
|
||||||
fpr* z0, fpr* z1, const fpr* tree, const fpr* t0, const fpr* t1,
|
|
||||||
unsigned logn, fpr* tmp);
|
|
||||||
|
|
||||||
/* Produce the signature short vector s2 (n sword16 values) from the expanded
|
|
||||||
* key and hashed point hm (n word16 values in [0, q)). Loops over the sampler
|
|
||||||
* until the (s1, s2) squared l2-norm is within the Falcon bound. 'tmp' must
|
|
||||||
* hold FALCON_SIGN_TMP_FPR(logn) fpr. 'samplerErr', if non-NULL, points at the
|
|
||||||
* sampler's sticky error flag; the loop bails out as soon as it becomes
|
|
||||||
* non-zero (a wedged PRNG) instead of running to the restart bound. Returns 0
|
|
||||||
* on success. */
|
|
||||||
WOLFSSL_LOCAL int falcon_do_sign_tree(falcon_samplerZ samp, void* samp_ctx,
|
|
||||||
sword16* s2, const fpr* expanded, const word16* hm, unsigned logn,
|
|
||||||
fpr* tmp, const int* samplerErr);
|
|
||||||
|
|
||||||
/* Convenience top-level: sign hashed point c with the expanded key, using the
|
|
||||||
* provided (already initialized) sampler context, writing s2. 'tmp' must hold
|
|
||||||
* FALCON_SIGN_TMP_FPR(logn) fpr. Returns 0 on success. */
|
|
||||||
WOLFSSL_LOCAL int falcon_sign_core(falcon_sampler_ctx* spc, const fpr* expanded,
|
|
||||||
const word16* c, sword16* s2, fpr* tmp, unsigned logn);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
} /* extern "C" */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* HAVE_FALCON && !WOLFSSL_FALCON_VERIFY_ONLY */
|
|
||||||
#endif /* WOLF_CRYPT_WC_FALCON_SIGN_H */
|
|
||||||
@@ -79,15 +79,6 @@ if(CONFIG_WOLFSSL)
|
|||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ed448.c)
|
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/ed448.c)
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/error.c)
|
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/error.c)
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/falcon.c)
|
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/falcon.c)
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_bigint.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_codec.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_fft.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_fpr.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_keygen.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_poly.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_sampler.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/wc_falcon_sign.c)
|
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_448.c)
|
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_448.c)
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_low_mem.c)
|
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_low_mem.c)
|
||||||
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_operations.c)
|
zephyr_library_sources(${ZEPHYR_CURRENT_MODULE_DIR}/wolfcrypt/src/fe_operations.c)
|
||||||
|
|||||||
Reference in New Issue
Block a user