mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-01-28 01:22:24 +01:00
For mul and sqr implementation efficiency the fixed array has extra digits beyond what is needed. When encoding, only put in the useful digits.
54836 lines
1.9 MiB
54836 lines
1.9 MiB
/* sp.c
|
|
*
|
|
* Copyright (C) 2006-2023 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 2 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
|
|
*/
|
|
|
|
/* Implementation by Sean Parkinson. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
|
|
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \
|
|
defined(WOLFSSL_HAVE_SP_ECC)
|
|
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
#include <wolfssl/wolfcrypt/cpuid.h>
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#ifdef RSA_LOW_MEM
|
|
#ifndef SP_RSA_PRIVATE_EXP_D
|
|
#define SP_RSA_PRIVATE_EXP_D
|
|
#endif
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
#define WOLFSSL_SP_SMALL
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SP_NO_MALLOC)
|
|
#undef WOLFSSL_SP_SMALL_STACK
|
|
#define WOLFSSL_SP_SMALL_STACK
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/sp.h>
|
|
|
|
#ifndef WOLFSSL_SP_ASM
|
|
#if SP_WORD_SIZE == 32
|
|
#define SP_PRINT_NUM(var, name, total, words, bits) \
|
|
do { \
|
|
int ii; \
|
|
byte nb[(bits + 7) / 8]; \
|
|
sp_digit _s[words]; \
|
|
XMEMCPY(_s, var, sizeof(_s)); \
|
|
sp_##total##_norm_##words(_s); \
|
|
sp_##total##_to_bin_##words(_s, nb); \
|
|
fprintf(stderr, name "=0x"); \
|
|
for (ii=0; ii<(bits + 7) / 8; ii++) \
|
|
fprintf(stderr, "%02x", nb[ii]); \
|
|
fprintf(stderr, "\n"); \
|
|
} while (0)
|
|
|
|
#define SP_PRINT_VAL(var, name) \
|
|
fprintf(stderr, name "=0x" SP_PRINT_FMT "\n", var)
|
|
|
|
#define SP_PRINT_INT(var, name) \
|
|
fprintf(stderr, name "=%d\n", var)
|
|
|
|
#if (((!defined(WC_NO_CACHE_RESISTANT) && \
|
|
(defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH))) || \
|
|
(defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP))) && \
|
|
!defined(WOLFSSL_RSA_PUBLIC_ONLY)) || (defined(WOLFSSL_SP_SMALL) && \
|
|
defined(WOLFSSL_HAVE_SP_ECC))
|
|
/* Mask for address to obfuscate which of the two address will be used. */
|
|
static const size_t addr_mask[2] = { 0, (size_t)-1 };
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_SP_NONBLOCK) && (!defined(WOLFSSL_SP_NO_MALLOC) || \
|
|
!defined(WOLFSSL_SP_SMALL))
|
|
#error SP non-blocking requires small and no-malloc (WOLFSSL_SP_SMALL and WOLFSSL_SP_NO_MALLOC)
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#ifndef WOLFSSL_SP_NO_2048
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_2048_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 21U) {
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_2048_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 29
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 29
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 29U) <= (word32)DIGIT_BIT) {
|
|
s += 29U;
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 29) {
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 29 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 256
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_2048_to_bin_72(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<71; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
j = 2055 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<71 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 29) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 29);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && (!defined(WOLFSSL_RSA_PUBLIC_ONLY) || !defined(WOLFSSL_SP_SMALL))) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_2048_norm_36(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 35; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 32; i += 8) {
|
|
a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
|
|
a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
|
|
a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
|
|
a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
|
|
a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
|
|
a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
|
|
a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
|
|
a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
|
|
}
|
|
a[33] += a[32] >> 29; a[32] &= 0x1fffffff;
|
|
a[34] += a[33] >> 29; a[33] &= 0x1fffffff;
|
|
a[35] += a[34] >> 29; a[34] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && (!WOLFSSL_RSA_PUBLIC_ONLY || !WOLFSSL_SP_SMALL)) || WOLFSSL_HAVE_SP_DH */
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_2048_norm_72(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 71; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 64; i += 8) {
|
|
a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
|
|
a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
|
|
a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
|
|
a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
|
|
a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
|
|
a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
|
|
a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
|
|
a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
|
|
}
|
|
a[65] += a[64] >> 29; a[64] &= 0x1fffffff;
|
|
a[66] += a[65] >> 29; a[65] &= 0x1fffffff;
|
|
a[67] += a[66] >> 29; a[66] &= 0x1fffffff;
|
|
a[68] += a[67] >> 29; a[67] &= 0x1fffffff;
|
|
a[69] += a[68] >> 29; a[68] &= 0x1fffffff;
|
|
a[70] += a[69] >> 29; a[69] &= 0x1fffffff;
|
|
a[71] += a[70] >> 29; a[70] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_12(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_uint64 t0;
|
|
sp_uint64 t1;
|
|
sp_digit t[12];
|
|
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 0];
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 1]
|
|
+ ((sp_uint64)a[ 1]) * b[ 0];
|
|
t[ 0] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 2]
|
|
+ ((sp_uint64)a[ 1]) * b[ 1]
|
|
+ ((sp_uint64)a[ 2]) * b[ 0];
|
|
t[ 1] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 3]
|
|
+ ((sp_uint64)a[ 1]) * b[ 2]
|
|
+ ((sp_uint64)a[ 2]) * b[ 1]
|
|
+ ((sp_uint64)a[ 3]) * b[ 0];
|
|
t[ 2] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 4]
|
|
+ ((sp_uint64)a[ 1]) * b[ 3]
|
|
+ ((sp_uint64)a[ 2]) * b[ 2]
|
|
+ ((sp_uint64)a[ 3]) * b[ 1]
|
|
+ ((sp_uint64)a[ 4]) * b[ 0];
|
|
t[ 3] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 5]
|
|
+ ((sp_uint64)a[ 1]) * b[ 4]
|
|
+ ((sp_uint64)a[ 2]) * b[ 3]
|
|
+ ((sp_uint64)a[ 3]) * b[ 2]
|
|
+ ((sp_uint64)a[ 4]) * b[ 1]
|
|
+ ((sp_uint64)a[ 5]) * b[ 0];
|
|
t[ 4] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 6]
|
|
+ ((sp_uint64)a[ 1]) * b[ 5]
|
|
+ ((sp_uint64)a[ 2]) * b[ 4]
|
|
+ ((sp_uint64)a[ 3]) * b[ 3]
|
|
+ ((sp_uint64)a[ 4]) * b[ 2]
|
|
+ ((sp_uint64)a[ 5]) * b[ 1]
|
|
+ ((sp_uint64)a[ 6]) * b[ 0];
|
|
t[ 5] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 7]
|
|
+ ((sp_uint64)a[ 1]) * b[ 6]
|
|
+ ((sp_uint64)a[ 2]) * b[ 5]
|
|
+ ((sp_uint64)a[ 3]) * b[ 4]
|
|
+ ((sp_uint64)a[ 4]) * b[ 3]
|
|
+ ((sp_uint64)a[ 5]) * b[ 2]
|
|
+ ((sp_uint64)a[ 6]) * b[ 1]
|
|
+ ((sp_uint64)a[ 7]) * b[ 0];
|
|
t[ 6] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 8]
|
|
+ ((sp_uint64)a[ 1]) * b[ 7]
|
|
+ ((sp_uint64)a[ 2]) * b[ 6]
|
|
+ ((sp_uint64)a[ 3]) * b[ 5]
|
|
+ ((sp_uint64)a[ 4]) * b[ 4]
|
|
+ ((sp_uint64)a[ 5]) * b[ 3]
|
|
+ ((sp_uint64)a[ 6]) * b[ 2]
|
|
+ ((sp_uint64)a[ 7]) * b[ 1]
|
|
+ ((sp_uint64)a[ 8]) * b[ 0];
|
|
t[ 7] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 9]
|
|
+ ((sp_uint64)a[ 1]) * b[ 8]
|
|
+ ((sp_uint64)a[ 2]) * b[ 7]
|
|
+ ((sp_uint64)a[ 3]) * b[ 6]
|
|
+ ((sp_uint64)a[ 4]) * b[ 5]
|
|
+ ((sp_uint64)a[ 5]) * b[ 4]
|
|
+ ((sp_uint64)a[ 6]) * b[ 3]
|
|
+ ((sp_uint64)a[ 7]) * b[ 2]
|
|
+ ((sp_uint64)a[ 8]) * b[ 1]
|
|
+ ((sp_uint64)a[ 9]) * b[ 0];
|
|
t[ 8] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 0]) * b[10]
|
|
+ ((sp_uint64)a[ 1]) * b[ 9]
|
|
+ ((sp_uint64)a[ 2]) * b[ 8]
|
|
+ ((sp_uint64)a[ 3]) * b[ 7]
|
|
+ ((sp_uint64)a[ 4]) * b[ 6]
|
|
+ ((sp_uint64)a[ 5]) * b[ 5]
|
|
+ ((sp_uint64)a[ 6]) * b[ 4]
|
|
+ ((sp_uint64)a[ 7]) * b[ 3]
|
|
+ ((sp_uint64)a[ 8]) * b[ 2]
|
|
+ ((sp_uint64)a[ 9]) * b[ 1]
|
|
+ ((sp_uint64)a[10]) * b[ 0];
|
|
t[ 9] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 0]) * b[11]
|
|
+ ((sp_uint64)a[ 1]) * b[10]
|
|
+ ((sp_uint64)a[ 2]) * b[ 9]
|
|
+ ((sp_uint64)a[ 3]) * b[ 8]
|
|
+ ((sp_uint64)a[ 4]) * b[ 7]
|
|
+ ((sp_uint64)a[ 5]) * b[ 6]
|
|
+ ((sp_uint64)a[ 6]) * b[ 5]
|
|
+ ((sp_uint64)a[ 7]) * b[ 4]
|
|
+ ((sp_uint64)a[ 8]) * b[ 3]
|
|
+ ((sp_uint64)a[ 9]) * b[ 2]
|
|
+ ((sp_uint64)a[10]) * b[ 1]
|
|
+ ((sp_uint64)a[11]) * b[ 0];
|
|
t[10] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 1]) * b[11]
|
|
+ ((sp_uint64)a[ 2]) * b[10]
|
|
+ ((sp_uint64)a[ 3]) * b[ 9]
|
|
+ ((sp_uint64)a[ 4]) * b[ 8]
|
|
+ ((sp_uint64)a[ 5]) * b[ 7]
|
|
+ ((sp_uint64)a[ 6]) * b[ 6]
|
|
+ ((sp_uint64)a[ 7]) * b[ 5]
|
|
+ ((sp_uint64)a[ 8]) * b[ 4]
|
|
+ ((sp_uint64)a[ 9]) * b[ 3]
|
|
+ ((sp_uint64)a[10]) * b[ 2]
|
|
+ ((sp_uint64)a[11]) * b[ 1];
|
|
t[11] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 2]) * b[11]
|
|
+ ((sp_uint64)a[ 3]) * b[10]
|
|
+ ((sp_uint64)a[ 4]) * b[ 9]
|
|
+ ((sp_uint64)a[ 5]) * b[ 8]
|
|
+ ((sp_uint64)a[ 6]) * b[ 7]
|
|
+ ((sp_uint64)a[ 7]) * b[ 6]
|
|
+ ((sp_uint64)a[ 8]) * b[ 5]
|
|
+ ((sp_uint64)a[ 9]) * b[ 4]
|
|
+ ((sp_uint64)a[10]) * b[ 3]
|
|
+ ((sp_uint64)a[11]) * b[ 2];
|
|
r[12] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 3]) * b[11]
|
|
+ ((sp_uint64)a[ 4]) * b[10]
|
|
+ ((sp_uint64)a[ 5]) * b[ 9]
|
|
+ ((sp_uint64)a[ 6]) * b[ 8]
|
|
+ ((sp_uint64)a[ 7]) * b[ 7]
|
|
+ ((sp_uint64)a[ 8]) * b[ 6]
|
|
+ ((sp_uint64)a[ 9]) * b[ 5]
|
|
+ ((sp_uint64)a[10]) * b[ 4]
|
|
+ ((sp_uint64)a[11]) * b[ 3];
|
|
r[13] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 4]) * b[11]
|
|
+ ((sp_uint64)a[ 5]) * b[10]
|
|
+ ((sp_uint64)a[ 6]) * b[ 9]
|
|
+ ((sp_uint64)a[ 7]) * b[ 8]
|
|
+ ((sp_uint64)a[ 8]) * b[ 7]
|
|
+ ((sp_uint64)a[ 9]) * b[ 6]
|
|
+ ((sp_uint64)a[10]) * b[ 5]
|
|
+ ((sp_uint64)a[11]) * b[ 4];
|
|
r[14] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 5]) * b[11]
|
|
+ ((sp_uint64)a[ 6]) * b[10]
|
|
+ ((sp_uint64)a[ 7]) * b[ 9]
|
|
+ ((sp_uint64)a[ 8]) * b[ 8]
|
|
+ ((sp_uint64)a[ 9]) * b[ 7]
|
|
+ ((sp_uint64)a[10]) * b[ 6]
|
|
+ ((sp_uint64)a[11]) * b[ 5];
|
|
r[15] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 6]) * b[11]
|
|
+ ((sp_uint64)a[ 7]) * b[10]
|
|
+ ((sp_uint64)a[ 8]) * b[ 9]
|
|
+ ((sp_uint64)a[ 9]) * b[ 8]
|
|
+ ((sp_uint64)a[10]) * b[ 7]
|
|
+ ((sp_uint64)a[11]) * b[ 6];
|
|
r[16] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 7]) * b[11]
|
|
+ ((sp_uint64)a[ 8]) * b[10]
|
|
+ ((sp_uint64)a[ 9]) * b[ 9]
|
|
+ ((sp_uint64)a[10]) * b[ 8]
|
|
+ ((sp_uint64)a[11]) * b[ 7];
|
|
r[17] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[ 8]) * b[11]
|
|
+ ((sp_uint64)a[ 9]) * b[10]
|
|
+ ((sp_uint64)a[10]) * b[ 9]
|
|
+ ((sp_uint64)a[11]) * b[ 8];
|
|
r[18] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[ 9]) * b[11]
|
|
+ ((sp_uint64)a[10]) * b[10]
|
|
+ ((sp_uint64)a[11]) * b[ 9];
|
|
r[19] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_uint64)a[10]) * b[11]
|
|
+ ((sp_uint64)a[11]) * b[10];
|
|
r[20] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[11]) * b[11];
|
|
r[21] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
r[22] = t0 & 0x1fffffff;
|
|
r[23] = (sp_digit)(t0 >> 29);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_add_12(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
r[ 7] = a[ 7] + b[ 7];
|
|
r[ 8] = a[ 8] + b[ 8];
|
|
r[ 9] = a[ 9] + b[ 9];
|
|
r[10] = a[10] + b[10];
|
|
r[11] = a[11] + b[11];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_sub_24(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 24; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_add_24(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 24; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_2048_norm_12(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 11; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
|
|
a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
|
|
a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
|
|
a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
|
|
a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
|
|
a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
|
|
a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
|
|
a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
|
|
a[9] += a[8] >> 29; a[8] &= 0x1fffffff;
|
|
a[10] += a[9] >> 29; a[9] &= 0x1fffffff;
|
|
a[11] += a[10] >> 29; a[10] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_2048_norm_24(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 23; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 16; i += 8) {
|
|
a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
|
|
a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
|
|
a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
|
|
a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
|
|
a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
|
|
a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
|
|
a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
|
|
a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
|
|
}
|
|
a[17] += a[16] >> 29; a[16] &= 0x1fffffff;
|
|
a[18] += a[17] >> 29; a[17] &= 0x1fffffff;
|
|
a[19] += a[18] >> 29; a[18] &= 0x1fffffff;
|
|
a[20] += a[19] >> 29; a[19] &= 0x1fffffff;
|
|
a[21] += a[20] >> 29; a[20] &= 0x1fffffff;
|
|
a[22] += a[21] >> 29; a[21] &= 0x1fffffff;
|
|
a[23] += a[22] >> 29; a[22] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit p0[24];
|
|
sp_digit p1[24];
|
|
sp_digit p2[24];
|
|
sp_digit p3[24];
|
|
sp_digit p4[24];
|
|
sp_digit p5[24];
|
|
sp_digit t0[24];
|
|
sp_digit t1[24];
|
|
sp_digit t2[24];
|
|
sp_digit a0[12];
|
|
sp_digit a1[12];
|
|
sp_digit a2[12];
|
|
sp_digit b0[12];
|
|
sp_digit b1[12];
|
|
sp_digit b2[12];
|
|
(void)sp_2048_add_12(a0, a, &a[12]);
|
|
sp_2048_norm_12(a0);
|
|
(void)sp_2048_add_12(b0, b, &b[12]);
|
|
sp_2048_norm_12(b0);
|
|
(void)sp_2048_add_12(a1, &a[12], &a[24]);
|
|
sp_2048_norm_12(a1);
|
|
(void)sp_2048_add_12(b1, &b[12], &b[24]);
|
|
sp_2048_norm_12(b1);
|
|
(void)sp_2048_add_12(a2, a0, &a[24]);
|
|
sp_2048_norm_12(a1);
|
|
(void)sp_2048_add_12(b2, b0, &b[24]);
|
|
sp_2048_norm_12(b2);
|
|
sp_2048_mul_12(p0, a, b);
|
|
sp_2048_mul_12(p2, &a[12], &b[12]);
|
|
sp_2048_mul_12(p4, &a[24], &b[24]);
|
|
sp_2048_mul_12(p1, a0, b0);
|
|
sp_2048_mul_12(p3, a1, b1);
|
|
sp_2048_mul_12(p5, a2, b2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*36U);
|
|
(void)sp_2048_sub_24(t0, p3, p2);
|
|
(void)sp_2048_sub_24(t1, p1, p2);
|
|
(void)sp_2048_sub_24(t2, p5, t0);
|
|
(void)sp_2048_sub_24(t2, t2, t1);
|
|
sp_2048_norm_24(t2);
|
|
(void)sp_2048_sub_24(t0, t0, p4);
|
|
sp_2048_norm_24(t0);
|
|
(void)sp_2048_sub_24(t1, t1, p0);
|
|
sp_2048_norm_24(t1);
|
|
(void)sp_2048_add_24(r, r, p0);
|
|
(void)sp_2048_add_24(&r[12], &r[12], t1);
|
|
(void)sp_2048_add_24(&r[24], &r[24], t2);
|
|
(void)sp_2048_add_24(&r[36], &r[36], t0);
|
|
(void)sp_2048_add_24(&r[48], &r[48], p4);
|
|
sp_2048_norm_72(r);
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 32; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[32] = a[32] + b[32];
|
|
r[33] = a[33] + b[33];
|
|
r[34] = a[34] + b[34];
|
|
r[35] = a[35] + b[35];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_add_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_sub_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_2048_norm_144(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 143; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 136; i += 8) {
|
|
a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
|
|
a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
|
|
a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
|
|
a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
|
|
a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
|
|
a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
|
|
a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
|
|
a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
|
|
}
|
|
a[137] += a[136] >> 29; a[136] &= 0x1fffffff;
|
|
a[138] += a[137] >> 29; a[137] &= 0x1fffffff;
|
|
a[139] += a[138] >> 29; a[138] &= 0x1fffffff;
|
|
a[140] += a[139] >> 29; a[139] &= 0x1fffffff;
|
|
a[141] += a[140] >> 29; a[140] &= 0x1fffffff;
|
|
a[142] += a[141] >> 29; a[141] &= 0x1fffffff;
|
|
a[143] += a[142] >> 29; a[142] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[72];
|
|
sp_digit* a1 = z1;
|
|
sp_digit b1[36];
|
|
sp_digit* z2 = r + 72;
|
|
(void)sp_2048_add_36(a1, a, &a[36]);
|
|
sp_2048_norm_36(a1);
|
|
(void)sp_2048_add_36(b1, b, &b[36]);
|
|
sp_2048_norm_36(b1);
|
|
sp_2048_mul_36(z2, &a[36], &b[36]);
|
|
sp_2048_mul_36(z0, a, b);
|
|
sp_2048_mul_36(z1, a1, b1);
|
|
(void)sp_2048_sub_72(z1, z1, z2);
|
|
(void)sp_2048_sub_72(z1, z1, z0);
|
|
(void)sp_2048_add_72(r + 36, r + 36, z1);
|
|
sp_2048_norm_144(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_sqr_12(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_uint64 t0;
|
|
sp_uint64 t1;
|
|
sp_digit t[12];
|
|
|
|
t0 = ((sp_uint64)a[ 0]) * a[ 0];
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2;
|
|
t[ 0] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 2]) * 2
|
|
+ ((sp_uint64)a[ 1]) * a[ 1];
|
|
t[ 1] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 3]
|
|
+ ((sp_uint64)a[ 1]) * a[ 2]) * 2;
|
|
t[ 2] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 4]
|
|
+ ((sp_uint64)a[ 1]) * a[ 3]) * 2
|
|
+ ((sp_uint64)a[ 2]) * a[ 2];
|
|
t[ 3] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 5]
|
|
+ ((sp_uint64)a[ 1]) * a[ 4]
|
|
+ ((sp_uint64)a[ 2]) * a[ 3]) * 2;
|
|
t[ 4] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 6]
|
|
+ ((sp_uint64)a[ 1]) * a[ 5]
|
|
+ ((sp_uint64)a[ 2]) * a[ 4]) * 2
|
|
+ ((sp_uint64)a[ 3]) * a[ 3];
|
|
t[ 5] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 7]
|
|
+ ((sp_uint64)a[ 1]) * a[ 6]
|
|
+ ((sp_uint64)a[ 2]) * a[ 5]
|
|
+ ((sp_uint64)a[ 3]) * a[ 4]) * 2;
|
|
t[ 6] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 8]
|
|
+ ((sp_uint64)a[ 1]) * a[ 7]
|
|
+ ((sp_uint64)a[ 2]) * a[ 6]
|
|
+ ((sp_uint64)a[ 3]) * a[ 5]) * 2
|
|
+ ((sp_uint64)a[ 4]) * a[ 4];
|
|
t[ 7] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 9]
|
|
+ ((sp_uint64)a[ 1]) * a[ 8]
|
|
+ ((sp_uint64)a[ 2]) * a[ 7]
|
|
+ ((sp_uint64)a[ 3]) * a[ 6]
|
|
+ ((sp_uint64)a[ 4]) * a[ 5]) * 2;
|
|
t[ 8] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 0]) * a[10]
|
|
+ ((sp_uint64)a[ 1]) * a[ 9]
|
|
+ ((sp_uint64)a[ 2]) * a[ 8]
|
|
+ ((sp_uint64)a[ 3]) * a[ 7]
|
|
+ ((sp_uint64)a[ 4]) * a[ 6]) * 2
|
|
+ ((sp_uint64)a[ 5]) * a[ 5];
|
|
t[ 9] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 0]) * a[11]
|
|
+ ((sp_uint64)a[ 1]) * a[10]
|
|
+ ((sp_uint64)a[ 2]) * a[ 9]
|
|
+ ((sp_uint64)a[ 3]) * a[ 8]
|
|
+ ((sp_uint64)a[ 4]) * a[ 7]
|
|
+ ((sp_uint64)a[ 5]) * a[ 6]) * 2;
|
|
t[10] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 1]) * a[11]
|
|
+ ((sp_uint64)a[ 2]) * a[10]
|
|
+ ((sp_uint64)a[ 3]) * a[ 9]
|
|
+ ((sp_uint64)a[ 4]) * a[ 8]
|
|
+ ((sp_uint64)a[ 5]) * a[ 7]) * 2
|
|
+ ((sp_uint64)a[ 6]) * a[ 6];
|
|
t[11] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 2]) * a[11]
|
|
+ ((sp_uint64)a[ 3]) * a[10]
|
|
+ ((sp_uint64)a[ 4]) * a[ 9]
|
|
+ ((sp_uint64)a[ 5]) * a[ 8]
|
|
+ ((sp_uint64)a[ 6]) * a[ 7]) * 2;
|
|
r[12] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 3]) * a[11]
|
|
+ ((sp_uint64)a[ 4]) * a[10]
|
|
+ ((sp_uint64)a[ 5]) * a[ 9]
|
|
+ ((sp_uint64)a[ 6]) * a[ 8]) * 2
|
|
+ ((sp_uint64)a[ 7]) * a[ 7];
|
|
r[13] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 4]) * a[11]
|
|
+ ((sp_uint64)a[ 5]) * a[10]
|
|
+ ((sp_uint64)a[ 6]) * a[ 9]
|
|
+ ((sp_uint64)a[ 7]) * a[ 8]) * 2;
|
|
r[14] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 5]) * a[11]
|
|
+ ((sp_uint64)a[ 6]) * a[10]
|
|
+ ((sp_uint64)a[ 7]) * a[ 9]) * 2
|
|
+ ((sp_uint64)a[ 8]) * a[ 8];
|
|
r[15] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 6]) * a[11]
|
|
+ ((sp_uint64)a[ 7]) * a[10]
|
|
+ ((sp_uint64)a[ 8]) * a[ 9]) * 2;
|
|
r[16] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 7]) * a[11]
|
|
+ ((sp_uint64)a[ 8]) * a[10]) * 2
|
|
+ ((sp_uint64)a[ 9]) * a[ 9];
|
|
r[17] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[ 8]) * a[11]
|
|
+ ((sp_uint64)a[ 9]) * a[10]) * 2;
|
|
r[18] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_uint64)a[ 9]) * a[11]) * 2
|
|
+ ((sp_uint64)a[10]) * a[10];
|
|
r[19] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_uint64)a[10]) * a[11]) * 2;
|
|
r[20] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_uint64)a[11]) * a[11];
|
|
r[21] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
r[22] = t0 & 0x1fffffff;
|
|
r[23] = (sp_digit)(t0 >> 29);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
/* Square a into r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit p0[24];
|
|
sp_digit p1[24];
|
|
sp_digit p2[24];
|
|
sp_digit p3[24];
|
|
sp_digit p4[24];
|
|
sp_digit p5[24];
|
|
sp_digit t0[24];
|
|
sp_digit t1[24];
|
|
sp_digit t2[24];
|
|
sp_digit a0[12];
|
|
sp_digit a1[12];
|
|
sp_digit a2[12];
|
|
(void)sp_2048_add_12(a0, a, &a[12]);
|
|
sp_2048_norm_12(a0);
|
|
(void)sp_2048_add_12(a1, &a[12], &a[24]);
|
|
sp_2048_norm_12(a1);
|
|
(void)sp_2048_add_12(a2, a0, &a[24]);
|
|
sp_2048_norm_12(a2);
|
|
sp_2048_sqr_12(p0, a);
|
|
sp_2048_sqr_12(p2, &a[12]);
|
|
sp_2048_sqr_12(p4, &a[24]);
|
|
sp_2048_sqr_12(p1, a0);
|
|
sp_2048_sqr_12(p3, a1);
|
|
sp_2048_sqr_12(p5, a2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*36U);
|
|
(void)sp_2048_sub_24(t0, p3, p2);
|
|
(void)sp_2048_sub_24(t1, p1, p2);
|
|
(void)sp_2048_sub_24(t2, p5, t0);
|
|
(void)sp_2048_sub_24(t2, t2, t1);
|
|
sp_2048_norm_24(t2);
|
|
(void)sp_2048_sub_24(t0, t0, p4);
|
|
sp_2048_norm_24(t0);
|
|
(void)sp_2048_sub_24(t1, t1, p0);
|
|
sp_2048_norm_24(t1);
|
|
(void)sp_2048_add_24(r, r, p0);
|
|
(void)sp_2048_add_24(&r[12], &r[12], t1);
|
|
(void)sp_2048_add_24(&r[24], &r[24], t2);
|
|
(void)sp_2048_add_24(&r[36], &r[36], t0);
|
|
(void)sp_2048_add_24(&r[48], &r[48], p4);
|
|
sp_2048_norm_72(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_sqr_72(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[72];
|
|
sp_digit* a1 = z1;
|
|
sp_digit* z2 = r + 72;
|
|
(void)sp_2048_add_36(a1, a, &a[36]);
|
|
sp_2048_norm_36(a1);
|
|
sp_2048_sqr_36(z2, &a[36]);
|
|
sp_2048_sqr_36(z0, a);
|
|
sp_2048_sqr_36(z1, a1);
|
|
(void)sp_2048_sub_72(z1, z1, z2);
|
|
(void)sp_2048_sub_72(z1, z1, z0);
|
|
(void)sp_2048_add_72(r + 36, r + 36, z1);
|
|
sp_2048_norm_144(r);
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_add_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_sub_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[71]) * b[71];
|
|
r[143] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 141; k >= 0; k--) {
|
|
if (k >= 72) {
|
|
i = k - 71;
|
|
imax = 71;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
if (imax - i > 15) {
|
|
int imaxlo;
|
|
lo = 0;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
|
|
for (; i <= imax && i < imaxlo + 15; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
lo &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
else {
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_sqr_72(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[71]) * a[71];
|
|
r[143] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 141; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 71) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 71;
|
|
}
|
|
if (imax - i >= 14) {
|
|
int imaxlo;
|
|
sp_uint64 hi;
|
|
|
|
hi = c >> 29;
|
|
c &= 0x1fffffff;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
|
|
t = 0;
|
|
for (; i <= imax && i < imaxlo + 14; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
hi += c >> 29;
|
|
c &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(hi >> 29);
|
|
r[k + 1] = (sp_digit)(hi & 0x1fffffff);
|
|
c <<= 29;
|
|
}
|
|
else
|
|
{
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 32; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[32] = a[32] - b[32];
|
|
r[33] = a[33] - b[33];
|
|
r[34] = a[34] - b[34];
|
|
r[35] = a[35] - b[35];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[35]) * b[35];
|
|
r[71] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 69; k >= 0; k--) {
|
|
if (k >= 36) {
|
|
i = k - 35;
|
|
imax = 35;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
if (imax - i > 15) {
|
|
int imaxlo;
|
|
lo = 0;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
|
|
for (; i <= imax && i < imaxlo + 15; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
lo &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
else {
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[35]) * a[35];
|
|
r[71] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 69; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 35) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 35;
|
|
}
|
|
if (imax - i >= 14) {
|
|
int imaxlo;
|
|
sp_uint64 hi;
|
|
|
|
hi = c >> 29;
|
|
c &= 0x1fffffff;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
|
|
t = 0;
|
|
for (; i <= imax && i < imaxlo + 14; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
hi += c >> 29;
|
|
c &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(hi >> 29);
|
|
r[k + 1] = (sp_digit)(hi & 0x1fffffff);
|
|
c <<= 29;
|
|
}
|
|
else
|
|
{
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* Caclulate the bottom digit of -1/a mod 2^n.
|
|
*
|
|
* a A single precision number.
|
|
* rho Bottom word of inverse.
|
|
*/
|
|
static void sp_2048_mont_setup(const sp_digit* a, sp_digit* rho)
|
|
{
|
|
sp_digit x;
|
|
sp_digit b;
|
|
|
|
b = a[0];
|
|
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**8 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**16 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
|
|
x &= 0x1fffffff;
|
|
|
|
/* rho = -1/m mod b */
|
|
*rho = ((sp_digit)1 << 29) - x;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_d_72(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[72] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[72] = (sp_digit)(t & 0x1fffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 2048 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_2048_mont_norm_36(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=0; i<35; i++) {
|
|
r[i] = 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 0; i < 32; i += 8) {
|
|
r[i + 0] = 0x1fffffff;
|
|
r[i + 1] = 0x1fffffff;
|
|
r[i + 2] = 0x1fffffff;
|
|
r[i + 3] = 0x1fffffff;
|
|
r[i + 4] = 0x1fffffff;
|
|
r[i + 5] = 0x1fffffff;
|
|
r[i + 6] = 0x1fffffff;
|
|
r[i + 7] = 0x1fffffff;
|
|
}
|
|
r[32] = 0x1fffffff;
|
|
r[33] = 0x1fffffff;
|
|
r[34] = 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[35] = 0x1ffL;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_2048_sub_36(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_2048_cmp_36(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=35; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
r |= (a[35] - b[35]) & (0 - (sp_digit)1);
|
|
r |= (a[34] - b[34]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[33] - b[33]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[32] - b[32]) & ~(((sp_digit)0 - r) >> 28);
|
|
for (i = 24; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_2048_cond_sub_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 0; i < 32; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
r[32] = a[32] - (b[32] & m);
|
|
r[33] = a[33] - (b[33] & m);
|
|
r[34] = a[34] - (b[34] & m);
|
|
r[35] = a[35] - (b[35] & m);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_add_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[36] += (sp_digit)t;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 32; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[32]) + r[32];
|
|
t[1] = (tb * a[33]) + r[33];
|
|
t[2] = (tb * a[34]) + r[34];
|
|
t[3] = (tb * a[35]) + r[35];
|
|
r[32] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[33] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[34] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[35] = t[3] & 0x1fffffff;
|
|
r[36] += (sp_digit)(t[3] >> 29);
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 32; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[4] += t[3] >> 29;
|
|
r[i+4] = t[4] & 0x1fffffff;
|
|
t[5] += t[4] >> 29;
|
|
r[i+5] = t[5] & 0x1fffffff;
|
|
t[6] += t[5] >> 29;
|
|
r[i+6] = t[6] & 0x1fffffff;
|
|
t[7] += t[6] >> 29;
|
|
r[i+7] = t[7] & 0x1fffffff;
|
|
t[0] = t[7] >> 29;
|
|
}
|
|
t[0] += (tb * a[32]) + r[32];
|
|
t[1] = (tb * a[33]) + r[33];
|
|
t[2] = (tb * a[34]) + r[34];
|
|
t[3] = (tb * a[35]) + r[35];
|
|
r[32] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[33] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[34] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[35] = t[3] & 0x1fffffff;
|
|
r[36] += (sp_digit)(t[3] >> 29);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 1024 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
sp_int64 n = a[35] >> 9;
|
|
n += ((sp_int64)a[36]) << 20;
|
|
|
|
for (i = 0; i < 35; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[37 + i]) << 20;
|
|
}
|
|
r[35] = (sp_digit)n;
|
|
#else
|
|
int i;
|
|
sp_int64 n = a[35] >> 9;
|
|
n += ((sp_int64)a[36]) << 20;
|
|
for (i = 0; i < 32; i += 8) {
|
|
r[i + 0] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 37]) << 20;
|
|
r[i + 1] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 38]) << 20;
|
|
r[i + 2] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 39]) << 20;
|
|
r[i + 3] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 40]) << 20;
|
|
r[i + 4] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 41]) << 20;
|
|
r[i + 5] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 42]) << 20;
|
|
r[i + 6] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 43]) << 20;
|
|
r[i + 7] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 44]) << 20;
|
|
}
|
|
r[32] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[69]) << 20;
|
|
r[33] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[70]) << 20;
|
|
r[34] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[71]) << 20;
|
|
r[35] = (sp_digit)n;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
XMEMSET(&r[36], 0, sizeof(*r) * 36U);
|
|
}
|
|
|
|
/* Reduce the number back to 2048 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_2048_mont_reduce_36(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_2048_norm_36(a + 36);
|
|
|
|
for (i=0; i<35; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_2048_mul_add_36(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1ffL;
|
|
sp_2048_mul_add_36(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
sp_2048_mont_shift_36(a, a);
|
|
over = a[35] - m[35];
|
|
sp_2048_cond_sub_36(a, a, m, ~((over - 1) >> 31));
|
|
sp_2048_norm_36(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mont_mul_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_2048_mul_36(r, a, b);
|
|
sp_2048_mont_reduce_36(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mont_sqr_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_2048_sqr_36(r, a);
|
|
sp_2048_mont_reduce_36(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_d_36(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[36] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[36] = (sp_digit)(t & 0x1fffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 36; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 32; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
r[32] = a[32] + (b[32] & m);
|
|
r[33] = a[33] + (b[33] & m);
|
|
r[34] = a[34] + (b[34] & m);
|
|
r[35] = a[35] + (b[35] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_2048_rshift_36(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
for (i=0; i<35; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<32; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (29 - n)) & 0x1fffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (29 - n)) & 0x1fffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (29 - n)) & 0x1fffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (29 - n)) & 0x1fffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (29 - n)) & 0x1fffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (29 - n)) & 0x1fffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (29 - n)) & 0x1fffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (29 - n)) & 0x1fffffff);
|
|
}
|
|
r[32] = (a[32] >> n) | ((a[33] << (29 - n)) & 0x1fffffff);
|
|
r[33] = (a[33] >> n) | ((a[34] << (29 - n)) & 0x1fffffff);
|
|
r[34] = (a[34] >> n) | ((a[35] << (29 - n)) & 0x1fffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[35] = a[35] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 29);
|
|
sp_digit t0 = (sp_digit)(d & 0x1fffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 27; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 29);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 14) + 1;
|
|
|
|
t = (sp_digit)(d >> 28);
|
|
t = (t / dv) << 14;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 13);
|
|
t = t / (dv << 1);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_2048_word_div_word_36(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_2048_div_36(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 36 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 36 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 72 + 1;
|
|
sd = t2 + 36 + 1;
|
|
|
|
sp_2048_mul_d_36(sd, d, (sp_digit)1 << 20);
|
|
sp_2048_mul_d_72(t1, a, (sp_digit)1 << 20);
|
|
dv = sd[35];
|
|
t1[36 + 36] += t1[36 + 36 - 1] >> 29;
|
|
t1[36 + 36 - 1] &= 0x1fffffff;
|
|
for (i=36; i>=0; i--) {
|
|
r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], dv);
|
|
|
|
sp_2048_mul_d_36(t2, sd, r1);
|
|
(void)sp_2048_sub_36(&t1[i], &t1[i], t2);
|
|
sp_2048_norm_36(&t1[i]);
|
|
t1[36 + i] -= t2[36];
|
|
t1[36 + i] += t1[36 + i - 1] >> 29;
|
|
t1[36 + i - 1] &= 0x1fffffff;
|
|
r1 = sp_2048_div_word_36(-t1[36 + i], -t1[36 + i - 1], dv);
|
|
r1 -= t1[36 + i];
|
|
sp_2048_mul_d_36(t2, sd, r1);
|
|
(void)sp_2048_add_36(&t1[i], &t1[i], t2);
|
|
t1[36 + i] += t1[36 + i - 1] >> 29;
|
|
t1[36 + i - 1] &= 0x1fffffff;
|
|
}
|
|
t1[36 - 1] += t1[36 - 2] >> 29;
|
|
t1[36 - 2] &= 0x1fffffff;
|
|
r1 = sp_2048_word_div_word_36(t1[36 - 1], dv);
|
|
|
|
sp_2048_mul_d_36(t2, sd, r1);
|
|
sp_2048_sub_36(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 72U);
|
|
for (i=0; i<35; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
sp_2048_cond_add_36(r, r, sd, r[35] >> 31);
|
|
|
|
sp_2048_norm_36(r);
|
|
sp_2048_rshift_36(r, r, 20);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_2048_mod_36(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_2048_div_36(a, m, NULL, r);
|
|
}
|
|
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_2048_mod_exp_36(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 72];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 36 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 36 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 36U * 2U);
|
|
}
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_36(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_2048_mod_36(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 36U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_36(t[1], t[1], norm);
|
|
err = sp_2048_mod_36(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 36 * 2);
|
|
sp_2048_mont_sqr_36(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 36 * 2);
|
|
}
|
|
|
|
sp_2048_mont_reduce_36(t[0], m, mp);
|
|
n = sp_2048_cmp_36(t[0], m);
|
|
sp_2048_cond_sub_36(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 36 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 72];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 36 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 36 * 2);
|
|
}
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_36(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_2048_mod_36(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_36(t[1], t[1], norm);
|
|
err = sp_2048_mod_36(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_2048_mul_36(t[1], a, norm);
|
|
err = sp_2048_mod_36(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 36 * 2);
|
|
sp_2048_mont_sqr_36(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 36 * 2);
|
|
}
|
|
|
|
sp_2048_mont_reduce_36(t[0], m, mp);
|
|
n = sp_2048_cmp_36(t[0], m);
|
|
sp_2048_cond_sub_36(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 36 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(32 * 72) + 72];
|
|
#endif
|
|
sp_digit* t[32];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 72) + 72), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<32; i++)
|
|
t[i] = td + i * 72;
|
|
rt = td + 2304;
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_36(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_2048_mod_36(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_36(t[1], t[1], norm);
|
|
err = sp_2048_mod_36(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_2048_mul_36(t[1], a, norm);
|
|
err = sp_2048_mod_36(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp);
|
|
sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp);
|
|
sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp);
|
|
sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp);
|
|
sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_2048_mont_sqr_36(t[10], t[ 5], m, mp);
|
|
sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_2048_mont_sqr_36(t[12], t[ 6], m, mp);
|
|
sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_2048_mont_sqr_36(t[14], t[ 7], m, mp);
|
|
sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp);
|
|
sp_2048_mont_sqr_36(t[16], t[ 8], m, mp);
|
|
sp_2048_mont_mul_36(t[17], t[ 9], t[ 8], m, mp);
|
|
sp_2048_mont_sqr_36(t[18], t[ 9], m, mp);
|
|
sp_2048_mont_mul_36(t[19], t[10], t[ 9], m, mp);
|
|
sp_2048_mont_sqr_36(t[20], t[10], m, mp);
|
|
sp_2048_mont_mul_36(t[21], t[11], t[10], m, mp);
|
|
sp_2048_mont_sqr_36(t[22], t[11], m, mp);
|
|
sp_2048_mont_mul_36(t[23], t[12], t[11], m, mp);
|
|
sp_2048_mont_sqr_36(t[24], t[12], m, mp);
|
|
sp_2048_mont_mul_36(t[25], t[13], t[12], m, mp);
|
|
sp_2048_mont_sqr_36(t[26], t[13], m, mp);
|
|
sp_2048_mont_mul_36(t[27], t[14], t[13], m, mp);
|
|
sp_2048_mont_sqr_36(t[28], t[14], m, mp);
|
|
sp_2048_mont_mul_36(t[29], t[15], t[14], m, mp);
|
|
sp_2048_mont_sqr_36(t[30], t[15], m, mp);
|
|
sp_2048_mont_mul_36(t[31], t[16], t[15], m, mp);
|
|
|
|
bits = ((bits + 4) / 5) * 5;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 36) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 5) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 72);
|
|
while ((i >= 0) || (c >= 5)) {
|
|
if (c >= 5) {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c = 24;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n = e[i--] << 3;
|
|
c = 5 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_2048_mont_sqr_36(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_36(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_36(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_36(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_36(rt, rt, m, mp);
|
|
|
|
sp_2048_mont_mul_36(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_2048_mont_reduce_36(rt, m, mp);
|
|
n = sp_2048_cmp_36(rt, m);
|
|
sp_2048_cond_sub_36(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 72);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 2048 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_2048_mont_norm_72(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=0; i<70; i++) {
|
|
r[i] = 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 0; i < 64; i += 8) {
|
|
r[i + 0] = 0x1fffffff;
|
|
r[i + 1] = 0x1fffffff;
|
|
r[i + 2] = 0x1fffffff;
|
|
r[i + 3] = 0x1fffffff;
|
|
r[i + 4] = 0x1fffffff;
|
|
r[i + 5] = 0x1fffffff;
|
|
r[i + 6] = 0x1fffffff;
|
|
r[i + 7] = 0x1fffffff;
|
|
}
|
|
r[64] = 0x1fffffff;
|
|
r[65] = 0x1fffffff;
|
|
r[66] = 0x1fffffff;
|
|
r[67] = 0x1fffffff;
|
|
r[68] = 0x1fffffff;
|
|
r[69] = 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[70] = 0x3ffffL;
|
|
r[71] = 0;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_2048_sub_72(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_2048_cmp_72(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=71; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 64; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_2048_cond_sub_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_add_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[72] += (sp_digit)t;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 68; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[68]) + r[68];
|
|
t[1] = (tb * a[69]) + r[69];
|
|
t[2] = (tb * a[70]) + r[70];
|
|
t[3] = (tb * a[71]) + r[71];
|
|
r[68] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[69] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[70] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[71] = t[3] & 0x1fffffff;
|
|
r[72] += (sp_digit)(t[3] >> 29);
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 64; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[4] += t[3] >> 29;
|
|
r[i+4] = t[4] & 0x1fffffff;
|
|
t[5] += t[4] >> 29;
|
|
r[i+5] = t[5] & 0x1fffffff;
|
|
t[6] += t[5] >> 29;
|
|
r[i+6] = t[6] & 0x1fffffff;
|
|
t[7] += t[6] >> 29;
|
|
r[i+7] = t[7] & 0x1fffffff;
|
|
t[0] = t[7] >> 29;
|
|
}
|
|
t[0] += (tb * a[64]) + r[64];
|
|
t[1] = (tb * a[65]) + r[65];
|
|
t[2] = (tb * a[66]) + r[66];
|
|
t[3] = (tb * a[67]) + r[67];
|
|
t[4] = (tb * a[68]) + r[68];
|
|
t[5] = (tb * a[69]) + r[69];
|
|
t[6] = (tb * a[70]) + r[70];
|
|
t[7] = (tb * a[71]) + r[71];
|
|
r[64] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[65] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[66] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[67] = t[3] & 0x1fffffff;
|
|
t[4] += t[3] >> 29;
|
|
r[68] = t[4] & 0x1fffffff;
|
|
t[5] += t[4] >> 29;
|
|
r[69] = t[5] & 0x1fffffff;
|
|
t[6] += t[5] >> 29;
|
|
r[70] = t[6] & 0x1fffffff;
|
|
t[7] += t[6] >> 29;
|
|
r[71] = t[7] & 0x1fffffff;
|
|
r[72] += (sp_digit)(t[7] >> 29);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 2048 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_2048_mont_shift_72(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
sp_int64 n = a[70] >> 18;
|
|
n += ((sp_int64)a[71]) << 11;
|
|
|
|
for (i = 0; i < 70; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[72 + i]) << 11;
|
|
}
|
|
r[70] = (sp_digit)n;
|
|
#else
|
|
int i;
|
|
sp_int64 n = a[70] >> 18;
|
|
n += ((sp_int64)a[71]) << 11;
|
|
for (i = 0; i < 64; i += 8) {
|
|
r[i + 0] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 72]) << 11;
|
|
r[i + 1] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 73]) << 11;
|
|
r[i + 2] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 74]) << 11;
|
|
r[i + 3] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 75]) << 11;
|
|
r[i + 4] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 76]) << 11;
|
|
r[i + 5] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 77]) << 11;
|
|
r[i + 6] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 78]) << 11;
|
|
r[i + 7] = n & 0x1fffffff;
|
|
n >>= 29; n += ((sp_int64)a[i + 79]) << 11;
|
|
}
|
|
r[64] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[136]) << 11;
|
|
r[65] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[137]) << 11;
|
|
r[66] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[138]) << 11;
|
|
r[67] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[139]) << 11;
|
|
r[68] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[140]) << 11;
|
|
r[69] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[141]) << 11;
|
|
r[70] = (sp_digit)n;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
XMEMSET(&r[71], 0, sizeof(*r) * 71U);
|
|
}
|
|
|
|
/* Reduce the number back to 2048 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_2048_mont_reduce_72(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_2048_norm_72(a + 71);
|
|
|
|
#ifdef WOLFSSL_SP_DH
|
|
if (mp != 1) {
|
|
for (i=0; i<70; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_2048_mul_add_72(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL;
|
|
sp_2048_mul_add_72(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
else {
|
|
for (i=0; i<70; i++) {
|
|
mu = a[i] & 0x1fffffff;
|
|
sp_2048_mul_add_72(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = a[i] & 0x3ffffL;
|
|
sp_2048_mul_add_72(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<70; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_2048_mul_add_72(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL;
|
|
sp_2048_mul_add_72(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
#endif
|
|
sp_2048_mont_shift_72(a, a);
|
|
over = a[70] - m[70];
|
|
sp_2048_cond_sub_72(a, a, m, ~((over - 1) >> 31));
|
|
sp_2048_norm_72(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mont_mul_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_2048_mul_72(r, a, b);
|
|
sp_2048_mont_reduce_72(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mont_sqr_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_2048_sqr_72(r, a);
|
|
sp_2048_mont_reduce_72(r, m, mp);
|
|
}
|
|
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_2048_norm_71(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 70; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 64; i += 8) {
|
|
a[i+1] += a[i+0] >> 29; a[i+0] &= 0x1fffffff;
|
|
a[i+2] += a[i+1] >> 29; a[i+1] &= 0x1fffffff;
|
|
a[i+3] += a[i+2] >> 29; a[i+2] &= 0x1fffffff;
|
|
a[i+4] += a[i+3] >> 29; a[i+3] &= 0x1fffffff;
|
|
a[i+5] += a[i+4] >> 29; a[i+4] &= 0x1fffffff;
|
|
a[i+6] += a[i+5] >> 29; a[i+5] &= 0x1fffffff;
|
|
a[i+7] += a[i+6] >> 29; a[i+6] &= 0x1fffffff;
|
|
a[i+8] += a[i+7] >> 29; a[i+7] &= 0x1fffffff;
|
|
}
|
|
a[65] += a[64] >> 29; a[64] &= 0x1fffffff;
|
|
a[66] += a[65] >> 29; a[65] &= 0x1fffffff;
|
|
a[67] += a[66] >> 29; a[66] &= 0x1fffffff;
|
|
a[68] += a[67] >> 29; a[67] &= 0x1fffffff;
|
|
a[69] += a[68] >> 29; a[68] &= 0x1fffffff;
|
|
a[70] += a[69] >> 29; a[69] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_2048_mul_d_144(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 144; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[144] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 144; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[144] = (sp_digit)(t & 0x1fffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_2048_cond_add_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_2048_cond_add_72(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_2048_rshift_72(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
for (i=0; i<71; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<64; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (29 - n)) & 0x1fffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (29 - n)) & 0x1fffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (29 - n)) & 0x1fffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (29 - n)) & 0x1fffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (29 - n)) & 0x1fffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (29 - n)) & 0x1fffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (29 - n)) & 0x1fffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (29 - n)) & 0x1fffffff);
|
|
}
|
|
r[64] = (a[64] >> n) | ((a[65] << (29 - n)) & 0x1fffffff);
|
|
r[65] = (a[65] >> n) | ((a[66] << (29 - n)) & 0x1fffffff);
|
|
r[66] = (a[66] >> n) | ((a[67] << (29 - n)) & 0x1fffffff);
|
|
r[67] = (a[67] >> n) | ((a[68] << (29 - n)) & 0x1fffffff);
|
|
r[68] = (a[68] >> n) | ((a[69] << (29 - n)) & 0x1fffffff);
|
|
r[69] = (a[69] >> n) | ((a[70] << (29 - n)) & 0x1fffffff);
|
|
r[70] = (a[70] >> n) | ((a[71] << (29 - n)) & 0x1fffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[71] = a[71] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_2048_div_word_72(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 29);
|
|
sp_digit t0 = (sp_digit)(d & 0x1fffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 27; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 29);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 14) + 1;
|
|
|
|
t = (sp_digit)(d >> 28);
|
|
t = (t / dv) << 14;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 13);
|
|
t = t / (dv << 1);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_2048_word_div_word_72(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_2048_div_72(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 72 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 72 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 144 + 1;
|
|
sd = t2 + 72 + 1;
|
|
|
|
sp_2048_mul_d_72(sd, d, (sp_digit)1 << 11);
|
|
sp_2048_mul_d_144(t1, a, (sp_digit)1 << 11);
|
|
dv = sd[70];
|
|
t1[71 + 71] += t1[71 + 71 - 1] >> 29;
|
|
t1[71 + 71 - 1] &= 0x1fffffff;
|
|
for (i=71; i>=0; i--) {
|
|
r1 = sp_2048_div_word_72(t1[71 + i], t1[71 + i - 1], dv);
|
|
|
|
sp_2048_mul_d_72(t2, sd, r1);
|
|
(void)sp_2048_sub_72(&t1[i], &t1[i], t2);
|
|
sp_2048_norm_71(&t1[i]);
|
|
t1[71 + i] += t1[71 + i - 1] >> 29;
|
|
t1[71 + i - 1] &= 0x1fffffff;
|
|
r1 = sp_2048_div_word_72(-t1[71 + i], -t1[71 + i - 1], dv);
|
|
r1 -= t1[71 + i];
|
|
sp_2048_mul_d_72(t2, sd, r1);
|
|
(void)sp_2048_add_72(&t1[i], &t1[i], t2);
|
|
t1[71 + i] += t1[71 + i - 1] >> 29;
|
|
t1[71 + i - 1] &= 0x1fffffff;
|
|
}
|
|
t1[71 - 1] += t1[71 - 2] >> 29;
|
|
t1[71 - 2] &= 0x1fffffff;
|
|
r1 = sp_2048_word_div_word_72(t1[71 - 1], dv);
|
|
|
|
sp_2048_mul_d_72(t2, sd, r1);
|
|
sp_2048_sub_72(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 144U);
|
|
for (i=0; i<70; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
sp_2048_cond_add_72(r, r, sd, r[70] >> 31);
|
|
|
|
sp_2048_norm_71(r);
|
|
sp_2048_rshift_72(r, r, 11);
|
|
r[71] = 0;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_2048_mod_72(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_2048_div_72(a, m, NULL, r);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
|
|
defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_2048_mod_exp_72(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 144];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 72 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 72 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 72U * 2U);
|
|
}
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_72(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_2048_mod_72(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 72U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_72(t[1], t[1], norm);
|
|
err = sp_2048_mod_72(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_2048_mont_mul_72(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 72 * 2);
|
|
sp_2048_mont_sqr_72(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 72 * 2);
|
|
}
|
|
|
|
sp_2048_mont_reduce_72(t[0], m, mp);
|
|
n = sp_2048_cmp_72(t[0], m);
|
|
sp_2048_cond_sub_72(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 72 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 144];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 72 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 72 * 2);
|
|
}
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_72(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_2048_mod_72(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_72(t[1], t[1], norm);
|
|
err = sp_2048_mod_72(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_2048_mul_72(t[1], a, norm);
|
|
err = sp_2048_mod_72(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_2048_mont_mul_72(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 72 * 2);
|
|
sp_2048_mont_sqr_72(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 72 * 2);
|
|
}
|
|
|
|
sp_2048_mont_reduce_72(t[0], m, mp);
|
|
n = sp_2048_cmp_72(t[0], m);
|
|
sp_2048_cond_sub_72(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 72 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(16 * 144) + 144];
|
|
#endif
|
|
sp_digit* t[16];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 144) + 144), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<16; i++)
|
|
t[i] = td + i * 144;
|
|
rt = td + 2304;
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_72(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_2048_mod_72(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_72(t[1], t[1], norm);
|
|
err = sp_2048_mod_72(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_2048_mul_72(t[1], a, norm);
|
|
err = sp_2048_mod_72(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mont_sqr_72(t[ 2], t[ 1], m, mp);
|
|
sp_2048_mont_mul_72(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_2048_mont_sqr_72(t[ 4], t[ 2], m, mp);
|
|
sp_2048_mont_mul_72(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_2048_mont_sqr_72(t[ 6], t[ 3], m, mp);
|
|
sp_2048_mont_mul_72(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_2048_mont_sqr_72(t[ 8], t[ 4], m, mp);
|
|
sp_2048_mont_mul_72(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_2048_mont_sqr_72(t[10], t[ 5], m, mp);
|
|
sp_2048_mont_mul_72(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_2048_mont_sqr_72(t[12], t[ 6], m, mp);
|
|
sp_2048_mont_mul_72(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_2048_mont_sqr_72(t[14], t[ 7], m, mp);
|
|
sp_2048_mont_mul_72(t[15], t[ 8], t[ 7], m, mp);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 72) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 144);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 25;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 3;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_2048_mont_sqr_72(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_72(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_72(rt, rt, m, mp);
|
|
sp_2048_mont_sqr_72(rt, rt, m, mp);
|
|
|
|
sp_2048_mont_mul_72(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_2048_mont_reduce_72(rt, m, mp);
|
|
n = sp_2048_cmp_72(rt, m);
|
|
sp_2048_cond_sub_72(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 144);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
|
|
/* WOLFSSL_HAVE_SP_DH */
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
#ifdef WOLFSSL_HAVE_SP_RSA
|
|
/* RSA public key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* em Public exponent.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 256 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPublic_2048(const byte* in, word32 inLen, const mp_int* em,
|
|
const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[72 * 5];
|
|
#endif
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit e[1] = {0};
|
|
sp_digit mp = 0;
|
|
int i;
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 256U) {
|
|
err = MP_TO_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 29) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 256U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
r = a + 72 * 2;
|
|
m = r + 72 * 2;
|
|
norm = r;
|
|
|
|
sp_2048_from_bin(a, 72, in, inLen);
|
|
#if DIGIT_BIT >= 29
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_from_mp(m, 72, mm);
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_72(norm, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_72(a, a, norm);
|
|
err = sp_2048_mod_72(a, a, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
for (i=28; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 72 * 2);
|
|
for (i--; i>=0; i--) {
|
|
sp_2048_mont_sqr_72(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_2048_mont_mul_72(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_2048_mont_reduce_72(r, m, mp);
|
|
mp = sp_2048_cmp_72(r, m);
|
|
sp_2048_cond_sub_72(r, r, m, ~(mp >> 31));
|
|
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[72 * 5];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit e[1] = {0};
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 256U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 29) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 256U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d;
|
|
r = a + 72 * 2;
|
|
m = r + 72 * 2;
|
|
|
|
sp_2048_from_bin(a, 72, in, inLen);
|
|
#if DIGIT_BIT >= 29
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_2048_from_mp(m, 72, mm);
|
|
|
|
if (e[0] == 0x3) {
|
|
sp_2048_sqr_72(r, a);
|
|
err = sp_2048_mod_72(r, r, m);
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_72(r, a, r);
|
|
err = sp_2048_mod_72(r, r, m);
|
|
}
|
|
}
|
|
else {
|
|
sp_digit* norm = r;
|
|
int i;
|
|
sp_digit mp;
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_72(norm, m);
|
|
|
|
sp_2048_mul_72(a, a, norm);
|
|
err = sp_2048_mod_72(a, a, m);
|
|
|
|
if (err == MP_OKAY) {
|
|
for (i=28; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 144U);
|
|
for (i--; i>=0; i--) {
|
|
sp_2048_mont_sqr_72(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_2048_mont_mul_72(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_2048_mont_reduce_72(r, m, mp);
|
|
mp = sp_2048_cmp_72(r, m);
|
|
sp_2048_cond_sub_72(r, r, m, ~(mp >> 31));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
|
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
|
|
#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
|
|
/* RSA private key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* dm Private exponent.
|
|
* pm First prime.
|
|
* qm Second prime.
|
|
* dpm First prime's CRT exponent.
|
|
* dqm Second prime's CRT exponent.
|
|
* qim Inverse of second prime mod p.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 256 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPrivate_2048(const byte* in, word32 inLen, const mp_int* dm,
|
|
const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
|
|
const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[72 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 256U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 256) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 72;
|
|
m = a + 144;
|
|
r = a;
|
|
|
|
sp_2048_from_bin(a, 72, in, inLen);
|
|
sp_2048_from_mp(d, 72, dm);
|
|
sp_2048_from_mp(m, 72, mm);
|
|
err = sp_2048_mod_exp_72(r, a, d, 2048, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 72);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[72 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 256U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 256U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 72;
|
|
m = a + 144;
|
|
r = a;
|
|
|
|
sp_2048_from_bin(a, 72, in, inLen);
|
|
sp_2048_from_mp(d, 72, dm);
|
|
sp_2048_from_mp(m, 72, mm);
|
|
err = sp_2048_mod_exp_72(r, a, d, 2048, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 72);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#else
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[36 * 8];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 256U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 256) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 8, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
p = a + 72;
|
|
qi = dq = dp = p + 36;
|
|
tmpa = qi + 36;
|
|
tmpb = tmpa + 72;
|
|
r = a;
|
|
|
|
sp_2048_from_bin(a, 72, in, inLen);
|
|
sp_2048_from_mp(p, 36, pm);
|
|
sp_2048_from_mp(dp, 36, dpm);
|
|
err = sp_2048_mod_exp_36(tmpa, a, dp, 1024, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_2048_from_mp(p, 36, qm);
|
|
sp_2048_from_mp(dq, 36, dqm);
|
|
err = sp_2048_mod_exp_36(tmpb, a, dq, 1024, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_2048_from_mp(p, 36, pm);
|
|
(void)sp_2048_sub_36(tmpa, tmpa, tmpb);
|
|
sp_2048_norm_36(tmpa);
|
|
sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
|
|
sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
|
|
sp_2048_norm_36(tmpa);
|
|
|
|
sp_2048_from_mp(qi, 36, qim);
|
|
sp_2048_mul_36(tmpa, tmpa, qi);
|
|
err = sp_2048_mod_36(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_from_mp(p, 36, qm);
|
|
sp_2048_mul_36(tmpa, p, tmpa);
|
|
(void)sp_2048_add_72(r, tmpb, tmpa);
|
|
sp_2048_norm_72(r);
|
|
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 36 * 8);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[36 * 13];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* q = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 256U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 256U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 13, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = a + 72 * 2;
|
|
q = p + 36;
|
|
dp = q + 36;
|
|
dq = dp + 36;
|
|
qi = dq + 36;
|
|
tmpa = qi + 36;
|
|
tmpb = tmpa + 72;
|
|
r = a;
|
|
|
|
sp_2048_from_bin(a, 72, in, inLen);
|
|
sp_2048_from_mp(p, 36, pm);
|
|
sp_2048_from_mp(q, 36, qm);
|
|
sp_2048_from_mp(dp, 36, dpm);
|
|
sp_2048_from_mp(dq, 36, dqm);
|
|
sp_2048_from_mp(qi, 36, qim);
|
|
|
|
err = sp_2048_mod_exp_36(tmpa, a, dp, 1024, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_2048_mod_exp_36(tmpb, a, dq, 1024, q, 1);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
(void)sp_2048_sub_36(tmpa, tmpa, tmpb);
|
|
sp_2048_norm_36(tmpa);
|
|
sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
|
|
sp_2048_cond_add_36(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[35] >> 31));
|
|
sp_2048_norm_36(tmpa);
|
|
sp_2048_mul_36(tmpa, tmpa, qi);
|
|
err = sp_2048_mod_36(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_mul_36(tmpa, tmpa, q);
|
|
(void)sp_2048_add_72(r, tmpb, tmpa);
|
|
sp_2048_norm_72(r);
|
|
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 36 * 13);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
|
|
}
|
|
|
|
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
#endif /* WOLFSSL_HAVE_SP_RSA */
|
|
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
|
|
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_2048_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 29
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 71);
|
|
r->used = 71;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 29
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 71; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 29) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 29 - s;
|
|
}
|
|
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 71; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 29 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 29 - s;
|
|
}
|
|
else {
|
|
s += 29;
|
|
}
|
|
}
|
|
r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_2048(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[72 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 72 * 2;
|
|
m = e + 72;
|
|
r = b;
|
|
|
|
sp_2048_from_mp(b, 72, base);
|
|
sp_2048_from_mp(e, 72, exp);
|
|
sp_2048_from_mp(m, 72, mod);
|
|
|
|
err = sp_2048_mod_exp_72(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_2048_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 72U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[72 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 72 * 2;
|
|
m = e + 72;
|
|
r = b;
|
|
|
|
sp_2048_from_mp(b, 72, base);
|
|
sp_2048_from_mp(e, 72, exp);
|
|
sp_2048_from_mp(m, 72, mod);
|
|
|
|
err = sp_2048_mod_exp_72(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_2048_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 72U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#ifdef WOLFSSL_HAVE_SP_DH
|
|
|
|
#ifdef HAVE_FFDHE_2048
|
|
SP_NOINLINE static void sp_2048_lshift_72(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
r[72] = a[71] >> (29 - n);
|
|
for (i=71; i>0; i--) {
|
|
r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
|
|
}
|
|
#else
|
|
sp_int_digit s;
|
|
sp_int_digit t;
|
|
|
|
s = (sp_int_digit)a[71];
|
|
r[72] = s >> (29U - n);
|
|
s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]);
|
|
r[71] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]);
|
|
r[70] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]);
|
|
r[69] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]);
|
|
r[68] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]);
|
|
r[67] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]);
|
|
r[66] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]);
|
|
r[65] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]);
|
|
r[64] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]);
|
|
r[63] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]);
|
|
r[62] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]);
|
|
r[61] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]);
|
|
r[60] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]);
|
|
r[59] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]);
|
|
r[58] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]);
|
|
r[57] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]);
|
|
r[56] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]);
|
|
r[55] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]);
|
|
r[54] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]);
|
|
r[53] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]);
|
|
r[52] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]);
|
|
r[51] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]);
|
|
r[50] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]);
|
|
r[49] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]);
|
|
r[48] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]);
|
|
r[47] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]);
|
|
r[46] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]);
|
|
r[45] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]);
|
|
r[44] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]);
|
|
r[43] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]);
|
|
r[42] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
|
|
r[41] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
|
|
r[40] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
|
|
r[39] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
|
|
r[38] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
|
|
r[37] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
|
|
r[36] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
|
|
r[35] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
|
|
r[34] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
|
|
r[33] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
|
|
r[32] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
|
|
r[31] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
|
|
r[30] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
|
|
r[29] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
|
|
r[28] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
|
|
r[27] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
|
|
r[26] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
|
|
r[25] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
|
|
r[24] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
|
|
r[23] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
|
|
r[22] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
|
|
r[21] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
|
|
r[20] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
|
|
r[19] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
|
|
r[18] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
|
|
r[17] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
|
|
r[16] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
|
|
r[15] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
|
|
r[14] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
|
|
r[13] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
|
|
r[12] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
|
|
r[11] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
|
|
r[10] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
|
|
r[9] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
|
|
r[8] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
|
|
r[7] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
|
|
r[6] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
|
|
r[5] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
|
|
r[4] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
|
|
r[3] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
|
|
r[2] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
|
|
r[1] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[0] = (a[0] << n) & 0x1fffffff;
|
|
}
|
|
|
|
/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even.
|
|
*/
|
|
static int sp_2048_mod_exp_2_72(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[217];
|
|
#endif
|
|
sp_digit* norm = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
sp_digit o;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 217, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
tmp = td + 144;
|
|
XMEMSET(td, 0, sizeof(sp_digit) * 217);
|
|
|
|
sp_2048_mont_setup(m, &mp);
|
|
sp_2048_mont_norm_72(norm, m);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 72) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
sp_2048_lshift_72(r, norm, (byte)y);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 25;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 3;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_2048_mont_sqr_72(r, r, m, mp);
|
|
sp_2048_mont_sqr_72(r, r, m, mp);
|
|
sp_2048_mont_sqr_72(r, r, m, mp);
|
|
sp_2048_mont_sqr_72(r, r, m, mp);
|
|
|
|
sp_2048_lshift_72(r, r, (byte)y);
|
|
sp_2048_mul_d_72(tmp, norm, (r[71] << 11) + (r[70] >> 18));
|
|
r[71] = 0;
|
|
r[70] &= 0x3ffffL;
|
|
(void)sp_2048_add_72(r, r, tmp);
|
|
sp_2048_norm_72(r);
|
|
o = sp_2048_cmp_72(r, m);
|
|
sp_2048_cond_sub_72(r, r, m, ~(o >> 31));
|
|
}
|
|
|
|
sp_2048_mont_reduce_72(r, m, mp);
|
|
n = sp_2048_cmp_72(r, m);
|
|
sp_2048_cond_sub_72(r, r, m, ~(n >> 31));
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* HAVE_FFDHE_2048 */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base.
|
|
* exp Array of bytes that is the exponent.
|
|
* expLen Length of data, in bytes, in exponent.
|
|
* mod Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 256 bytes long.
|
|
* outLen Length, in bytes, of exponentiation result.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_DhExp_2048(const mp_int* base, const byte* exp, word32 expLen,
|
|
const mp_int* mod, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[72 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
word32 i;
|
|
int err = MP_OKAY;
|
|
|
|
if (mp_count_bits(base) > 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expLen > 256U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 2048) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 72 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 72 * 2;
|
|
m = e + 72;
|
|
r = b;
|
|
|
|
sp_2048_from_mp(b, 72, base);
|
|
sp_2048_from_bin(e, 72, exp, expLen);
|
|
sp_2048_from_mp(m, 72, mod);
|
|
|
|
#ifdef HAVE_FFDHE_2048
|
|
if (base->used == 1 && base->dp[0] == 2U &&
|
|
(m[70] >> 2) == 0xffffL) {
|
|
err = sp_2048_mod_exp_2_72(r, e, expLen * 8U, m);
|
|
}
|
|
else {
|
|
#endif
|
|
err = sp_2048_mod_exp_72(r, b, e, expLen * 8U, m, 0);
|
|
#ifdef HAVE_FFDHE_2048
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_2048_to_bin_72(r, out);
|
|
*outLen = 256;
|
|
for (i=0; i<256U && out[i] == 0U; i++) {
|
|
/* Search for first non-zero. */
|
|
}
|
|
*outLen -= i;
|
|
XMEMMOVE(out, out + i, *outLen);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 72U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_1024(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[36 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 1024) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 1024) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 1024) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 36 * 2;
|
|
m = e + 36;
|
|
r = b;
|
|
|
|
sp_2048_from_mp(b, 36, base);
|
|
sp_2048_from_mp(e, 36, exp);
|
|
sp_2048_from_mp(m, 36, mod);
|
|
|
|
err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(r + 36, 0, sizeof(*r) * 36U);
|
|
err = sp_2048_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 72U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[36 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 1024) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 1024) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 1024) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 36 * 2;
|
|
m = e + 36;
|
|
r = b;
|
|
|
|
sp_2048_from_mp(b, 36, base);
|
|
sp_2048_from_mp(e, 36, exp);
|
|
sp_2048_from_mp(m, 36, mod);
|
|
|
|
err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(r + 36, 0, sizeof(*r) * 36U);
|
|
err = sp_2048_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 72U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
|
|
|
|
#endif /* !WOLFSSL_SP_NO_2048 */
|
|
|
|
#ifndef WOLFSSL_SP_NO_3072
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 21U) {
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 29
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 29
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 29U) <= (word32)DIGIT_BIT) {
|
|
s += 29U;
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 29) {
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 29 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 384
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_3072_to_bin_106(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<105; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
j = 3079 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<106 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 29) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 29);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_53(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 52; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_106(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 105; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[105]) * b[105];
|
|
r[211] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 209; k >= 0; k--) {
|
|
if (k >= 106) {
|
|
i = k - 105;
|
|
imax = 105;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
if (imax - i > 15) {
|
|
int imaxlo;
|
|
lo = 0;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
|
|
for (; i <= imax && i < imaxlo + 15; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
lo &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
else {
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_sqr_106(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[105]) * a[105];
|
|
r[211] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 209; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 105) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 105;
|
|
}
|
|
if (imax - i >= 14) {
|
|
int imaxlo;
|
|
sp_uint64 hi;
|
|
|
|
hi = c >> 29;
|
|
c &= 0x1fffffff;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
|
|
t = 0;
|
|
for (; i <= imax && i < imaxlo + 14; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
hi += c >> 29;
|
|
c &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(hi >> 29);
|
|
r[k + 1] = (sp_digit)(hi & 0x1fffffff);
|
|
c <<= 29;
|
|
}
|
|
else
|
|
{
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
/* Caclulate the bottom digit of -1/a mod 2^n.
|
|
*
|
|
* a A single precision number.
|
|
* rho Bottom word of inverse.
|
|
*/
|
|
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
|
|
{
|
|
sp_digit x;
|
|
sp_digit b;
|
|
|
|
b = a[0];
|
|
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**8 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**16 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
|
|
x &= 0x1fffffff;
|
|
|
|
/* rho = -1/m mod b */
|
|
*rho = ((sp_digit)1 << 29) - x;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_d_106(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 106; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[106] = (sp_digit)t;
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_sub_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 53; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 3072 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_3072_mont_norm_53(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i=0; i<52; i++) {
|
|
r[i] = 0x1fffffff;
|
|
}
|
|
r[52] = 0xfffffffL;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_3072_sub_53(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_3072_cmp_53(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
for (i=52; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_sub_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 53; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_add_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 53; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[53] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 52; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[52]) + r[52];
|
|
r[52] = t[0] & 0x1fffffff;
|
|
r[53] += (sp_digit)(t[0] >> 29);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 1536 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_3072_mont_shift_53(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[52] >> 28;
|
|
n += ((sp_int64)a[53]) << 1;
|
|
|
|
for (i = 0; i < 52; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[54 + i]) << 1;
|
|
}
|
|
r[52] = (sp_digit)n;
|
|
XMEMSET(&r[53], 0, sizeof(*r) * 53U);
|
|
}
|
|
|
|
/* Reduce the number back to 3072 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_3072_mont_reduce_53(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_3072_norm_53(a + 53);
|
|
|
|
for (i=0; i<52; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_3072_mul_add_53(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffffL;
|
|
sp_3072_mul_add_53(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
sp_3072_mont_shift_53(a, a);
|
|
over = a[52] - m[52];
|
|
sp_3072_cond_sub_53(a, a, m, ~((over - 1) >> 31));
|
|
sp_3072_norm_53(a);
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[52]) * b[52];
|
|
r[105] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 103; k >= 0; k--) {
|
|
if (k >= 53) {
|
|
i = k - 52;
|
|
imax = 52;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
if (imax - i > 15) {
|
|
int imaxlo;
|
|
lo = 0;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
|
|
for (; i <= imax && i < imaxlo + 15; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
lo &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
else {
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_mul_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_mul_53(r, a, b);
|
|
sp_3072_mont_reduce_53(r, m, mp);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_sqr_53(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[52]) * a[52];
|
|
r[105] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 103; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 52) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 52;
|
|
}
|
|
if (imax - i >= 14) {
|
|
int imaxlo;
|
|
sp_uint64 hi;
|
|
|
|
hi = c >> 29;
|
|
c &= 0x1fffffff;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
|
|
t = 0;
|
|
for (; i <= imax && i < imaxlo + 14; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
hi += c >> 29;
|
|
c &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(hi >> 29);
|
|
r[k + 1] = (sp_digit)(hi & 0x1fffffff);
|
|
c <<= 29;
|
|
}
|
|
else
|
|
{
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_sqr_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_sqr_53(r, a);
|
|
sp_3072_mont_reduce_53(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_d_53(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 53; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[53] = (sp_digit)t;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_add_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 53; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_add_53(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 53; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SP_NOINLINE static void sp_3072_rshift_53(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<52; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
r[52] = a[52] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_3072_div_word_53(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 29);
|
|
sp_digit t0 = (sp_digit)(d & 0x1fffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 27; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 29);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 14) + 1;
|
|
|
|
t = (sp_digit)(d >> 28);
|
|
t = (t / dv) << 14;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 13);
|
|
t = t / (dv << 1);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_3072_word_div_word_53(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_div_53(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 53 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 53 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 106 + 1;
|
|
sd = t2 + 53 + 1;
|
|
|
|
sp_3072_mul_d_53(sd, d, (sp_digit)1 << 1);
|
|
sp_3072_mul_d_106(t1, a, (sp_digit)1 << 1);
|
|
dv = sd[52];
|
|
t1[53 + 53] += t1[53 + 53 - 1] >> 29;
|
|
t1[53 + 53 - 1] &= 0x1fffffff;
|
|
for (i=53; i>=0; i--) {
|
|
r1 = sp_3072_div_word_53(t1[53 + i], t1[53 + i - 1], dv);
|
|
|
|
sp_3072_mul_d_53(t2, sd, r1);
|
|
(void)sp_3072_sub_53(&t1[i], &t1[i], t2);
|
|
sp_3072_norm_53(&t1[i]);
|
|
t1[53 + i] -= t2[53];
|
|
t1[53 + i] += t1[53 + i - 1] >> 29;
|
|
t1[53 + i - 1] &= 0x1fffffff;
|
|
r1 = sp_3072_div_word_53(-t1[53 + i], -t1[53 + i - 1], dv);
|
|
r1 -= t1[53 + i];
|
|
sp_3072_mul_d_53(t2, sd, r1);
|
|
(void)sp_3072_add_53(&t1[i], &t1[i], t2);
|
|
t1[53 + i] += t1[53 + i - 1] >> 29;
|
|
t1[53 + i - 1] &= 0x1fffffff;
|
|
}
|
|
t1[53 - 1] += t1[53 - 2] >> 29;
|
|
t1[53 - 2] &= 0x1fffffff;
|
|
r1 = sp_3072_word_div_word_53(t1[53 - 1], dv);
|
|
|
|
sp_3072_mul_d_53(t2, sd, r1);
|
|
sp_3072_sub_53(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 106U);
|
|
for (i=0; i<52; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
sp_3072_cond_add_53(r, r, sd, r[52] >> 31);
|
|
|
|
sp_3072_norm_53(r);
|
|
sp_3072_rshift_53(r, r, 1);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_mod_53(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_3072_div_53(a, m, NULL, r);
|
|
}
|
|
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_3072_mod_exp_53(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 106];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 53 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 53 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 53U * 2U);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_53(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_53(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 53U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_53(t[1], t[1], norm);
|
|
err = sp_3072_mod_53(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_53(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 53 * 2);
|
|
sp_3072_mont_sqr_53(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 53 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_53(t[0], m, mp);
|
|
n = sp_3072_cmp_53(t[0], m);
|
|
sp_3072_cond_sub_53(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 53 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 106];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 53 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 53 * 2);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_53(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_53(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_53(t[1], t[1], norm);
|
|
err = sp_3072_mod_53(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_53(t[1], a, norm);
|
|
err = sp_3072_mod_53(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_53(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 53 * 2);
|
|
sp_3072_mont_sqr_53(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 53 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_53(t[0], m, mp);
|
|
n = sp_3072_cmp_53(t[0], m);
|
|
sp_3072_cond_sub_53(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 53 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(32 * 106) + 106];
|
|
#endif
|
|
sp_digit* t[32];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 106) + 106), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<32; i++)
|
|
t[i] = td + i * 106;
|
|
rt = td + 3392;
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_53(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_53(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_53(t[1], t[1], norm);
|
|
err = sp_3072_mod_53(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_53(t[1], a, norm);
|
|
err = sp_3072_mod_53(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mont_sqr_53(t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_mul_53(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_sqr_53(t[ 4], t[ 2], m, mp);
|
|
sp_3072_mont_mul_53(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_3072_mont_sqr_53(t[ 6], t[ 3], m, mp);
|
|
sp_3072_mont_mul_53(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_3072_mont_sqr_53(t[ 8], t[ 4], m, mp);
|
|
sp_3072_mont_mul_53(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_3072_mont_sqr_53(t[10], t[ 5], m, mp);
|
|
sp_3072_mont_mul_53(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_3072_mont_sqr_53(t[12], t[ 6], m, mp);
|
|
sp_3072_mont_mul_53(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_3072_mont_sqr_53(t[14], t[ 7], m, mp);
|
|
sp_3072_mont_mul_53(t[15], t[ 8], t[ 7], m, mp);
|
|
sp_3072_mont_sqr_53(t[16], t[ 8], m, mp);
|
|
sp_3072_mont_mul_53(t[17], t[ 9], t[ 8], m, mp);
|
|
sp_3072_mont_sqr_53(t[18], t[ 9], m, mp);
|
|
sp_3072_mont_mul_53(t[19], t[10], t[ 9], m, mp);
|
|
sp_3072_mont_sqr_53(t[20], t[10], m, mp);
|
|
sp_3072_mont_mul_53(t[21], t[11], t[10], m, mp);
|
|
sp_3072_mont_sqr_53(t[22], t[11], m, mp);
|
|
sp_3072_mont_mul_53(t[23], t[12], t[11], m, mp);
|
|
sp_3072_mont_sqr_53(t[24], t[12], m, mp);
|
|
sp_3072_mont_mul_53(t[25], t[13], t[12], m, mp);
|
|
sp_3072_mont_sqr_53(t[26], t[13], m, mp);
|
|
sp_3072_mont_mul_53(t[27], t[14], t[13], m, mp);
|
|
sp_3072_mont_sqr_53(t[28], t[14], m, mp);
|
|
sp_3072_mont_mul_53(t[29], t[15], t[14], m, mp);
|
|
sp_3072_mont_sqr_53(t[30], t[15], m, mp);
|
|
sp_3072_mont_mul_53(t[31], t[16], t[15], m, mp);
|
|
|
|
bits = ((bits + 4) / 5) * 5;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 53) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 5) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 106);
|
|
while ((i >= 0) || (c >= 5)) {
|
|
if (c >= 5) {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c = 24;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n = e[i--] << 3;
|
|
c = 5 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_3072_mont_sqr_53(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_53(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_53(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_53(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_53(rt, rt, m, mp);
|
|
|
|
sp_3072_mont_mul_53(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_3072_mont_reduce_53(rt, m, mp);
|
|
n = sp_3072_cmp_53(rt, m);
|
|
sp_3072_cond_sub_53(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 106);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_sub_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 106; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 3072 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_3072_mont_norm_106(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i=0; i<105; i++) {
|
|
r[i] = 0x1fffffff;
|
|
}
|
|
r[105] = 0x7ffffffL;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_3072_sub_106(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_3072_cmp_106(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
for (i=105; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_sub_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 106; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_add_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 106; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[106] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 104; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[104]) + r[104];
|
|
t[1] = (tb * a[105]) + r[105];
|
|
r[104] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[105] = t[1] & 0x1fffffff;
|
|
r[106] += (sp_digit)(t[1] >> 29);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 3072 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_3072_mont_shift_106(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[105] >> 27;
|
|
n += ((sp_int64)a[106]) << 2;
|
|
|
|
for (i = 0; i < 105; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[107 + i]) << 2;
|
|
}
|
|
r[105] = (sp_digit)n;
|
|
XMEMSET(&r[106], 0, sizeof(*r) * 106U);
|
|
}
|
|
|
|
/* Reduce the number back to 3072 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_3072_mont_reduce_106(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_3072_norm_106(a + 106);
|
|
|
|
#ifdef WOLFSSL_SP_DH
|
|
if (mp != 1) {
|
|
for (i=0; i<105; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_3072_mul_add_106(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7ffffffL;
|
|
sp_3072_mul_add_106(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
else {
|
|
for (i=0; i<105; i++) {
|
|
mu = a[i] & 0x1fffffff;
|
|
sp_3072_mul_add_106(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = a[i] & 0x7ffffffL;
|
|
sp_3072_mul_add_106(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<105; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_3072_mul_add_106(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7ffffffL;
|
|
sp_3072_mul_add_106(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
#endif
|
|
sp_3072_mont_shift_106(a, a);
|
|
over = a[105] - m[105];
|
|
sp_3072_cond_sub_106(a, a, m, ~((over - 1) >> 31));
|
|
sp_3072_norm_106(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_mul_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_mul_106(r, a, b);
|
|
sp_3072_mont_reduce_106(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_sqr_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_sqr_106(r, a);
|
|
sp_3072_mont_reduce_106(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_d_212(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 212; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[212] = (sp_digit)t;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_add_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 106; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_add_106(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 106; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SP_NOINLINE static void sp_3072_rshift_106(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<105; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
r[105] = a[105] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_3072_div_word_106(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 29);
|
|
sp_digit t0 = (sp_digit)(d & 0x1fffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 27; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 29);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 14) + 1;
|
|
|
|
t = (sp_digit)(d >> 28);
|
|
t = (t / dv) << 14;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 13);
|
|
t = t / (dv << 1);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_3072_word_div_word_106(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_div_106(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 106 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 106 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 212 + 1;
|
|
sd = t2 + 106 + 1;
|
|
|
|
sp_3072_mul_d_106(sd, d, (sp_digit)1 << 2);
|
|
sp_3072_mul_d_212(t1, a, (sp_digit)1 << 2);
|
|
dv = sd[105];
|
|
t1[106 + 106] += t1[106 + 106 - 1] >> 29;
|
|
t1[106 + 106 - 1] &= 0x1fffffff;
|
|
for (i=106; i>=0; i--) {
|
|
r1 = sp_3072_div_word_106(t1[106 + i], t1[106 + i - 1], dv);
|
|
|
|
sp_3072_mul_d_106(t2, sd, r1);
|
|
(void)sp_3072_sub_106(&t1[i], &t1[i], t2);
|
|
sp_3072_norm_106(&t1[i]);
|
|
t1[106 + i] -= t2[106];
|
|
t1[106 + i] += t1[106 + i - 1] >> 29;
|
|
t1[106 + i - 1] &= 0x1fffffff;
|
|
r1 = sp_3072_div_word_106(-t1[106 + i], -t1[106 + i - 1], dv);
|
|
r1 -= t1[106 + i];
|
|
sp_3072_mul_d_106(t2, sd, r1);
|
|
(void)sp_3072_add_106(&t1[i], &t1[i], t2);
|
|
t1[106 + i] += t1[106 + i - 1] >> 29;
|
|
t1[106 + i - 1] &= 0x1fffffff;
|
|
}
|
|
t1[106 - 1] += t1[106 - 2] >> 29;
|
|
t1[106 - 2] &= 0x1fffffff;
|
|
r1 = sp_3072_word_div_word_106(t1[106 - 1], dv);
|
|
|
|
sp_3072_mul_d_106(t2, sd, r1);
|
|
sp_3072_sub_106(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 212U);
|
|
for (i=0; i<105; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
sp_3072_cond_add_106(r, r, sd, r[105] >> 31);
|
|
|
|
sp_3072_norm_106(r);
|
|
sp_3072_rshift_106(r, r, 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_mod_106(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_3072_div_106(a, m, NULL, r);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_3072_mod_exp_106(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 212];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 106 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 106 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 106U * 2U);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_106(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_106(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 106U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_106(t[1], t[1], norm);
|
|
err = sp_3072_mod_106(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_106(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 106 * 2);
|
|
sp_3072_mont_sqr_106(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 106 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_106(t[0], m, mp);
|
|
n = sp_3072_cmp_106(t[0], m);
|
|
sp_3072_cond_sub_106(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 106 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 212];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 106 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 106 * 2);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_106(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_106(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_106(t[1], t[1], norm);
|
|
err = sp_3072_mod_106(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_106(t[1], a, norm);
|
|
err = sp_3072_mod_106(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_106(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 106 * 2);
|
|
sp_3072_mont_sqr_106(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 106 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_106(t[0], m, mp);
|
|
n = sp_3072_cmp_106(t[0], m);
|
|
sp_3072_cond_sub_106(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 106 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(16 * 212) + 212];
|
|
#endif
|
|
sp_digit* t[16];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 212) + 212), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<16; i++)
|
|
t[i] = td + i * 212;
|
|
rt = td + 3392;
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_106(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_106(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_106(t[1], t[1], norm);
|
|
err = sp_3072_mod_106(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_106(t[1], a, norm);
|
|
err = sp_3072_mod_106(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mont_sqr_106(t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_mul_106(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_sqr_106(t[ 4], t[ 2], m, mp);
|
|
sp_3072_mont_mul_106(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_3072_mont_sqr_106(t[ 6], t[ 3], m, mp);
|
|
sp_3072_mont_mul_106(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_3072_mont_sqr_106(t[ 8], t[ 4], m, mp);
|
|
sp_3072_mont_mul_106(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_3072_mont_sqr_106(t[10], t[ 5], m, mp);
|
|
sp_3072_mont_mul_106(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_3072_mont_sqr_106(t[12], t[ 6], m, mp);
|
|
sp_3072_mont_mul_106(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_3072_mont_sqr_106(t[14], t[ 7], m, mp);
|
|
sp_3072_mont_mul_106(t[15], t[ 8], t[ 7], m, mp);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 106) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 212);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 25;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 3;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_3072_mont_sqr_106(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_106(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_106(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_106(rt, rt, m, mp);
|
|
|
|
sp_3072_mont_mul_106(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_3072_mont_reduce_106(rt, m, mp);
|
|
n = sp_3072_cmp_106(rt, m);
|
|
sp_3072_cond_sub_106(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 212);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
#ifdef WOLFSSL_HAVE_SP_RSA
|
|
/* RSA public key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* em Public exponent.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 384 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
|
|
const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[106 * 5];
|
|
#endif
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit e[1] = {0};
|
|
sp_digit mp = 0;
|
|
int i;
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 29) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
r = a + 106 * 2;
|
|
m = r + 106 * 2;
|
|
norm = r;
|
|
|
|
sp_3072_from_bin(a, 106, in, inLen);
|
|
#if DIGIT_BIT >= 29
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(m, 106, mm);
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_106(norm, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_106(a, a, norm);
|
|
err = sp_3072_mod_106(a, a, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
for (i=28; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 106 * 2);
|
|
for (i--; i>=0; i--) {
|
|
sp_3072_mont_sqr_106(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_3072_mont_mul_106(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_3072_mont_reduce_106(r, m, mp);
|
|
mp = sp_3072_cmp_106(r, m);
|
|
sp_3072_cond_sub_106(r, r, m, ~(mp >> 31));
|
|
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[106 * 5];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit e[1] = {0};
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 29) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d;
|
|
r = a + 106 * 2;
|
|
m = r + 106 * 2;
|
|
|
|
sp_3072_from_bin(a, 106, in, inLen);
|
|
#if DIGIT_BIT >= 29
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(m, 106, mm);
|
|
|
|
if (e[0] == 0x3) {
|
|
sp_3072_sqr_106(r, a);
|
|
err = sp_3072_mod_106(r, r, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_106(r, a, r);
|
|
err = sp_3072_mod_106(r, r, m);
|
|
}
|
|
}
|
|
else {
|
|
sp_digit* norm = r;
|
|
int i;
|
|
sp_digit mp;
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_106(norm, m);
|
|
|
|
sp_3072_mul_106(a, a, norm);
|
|
err = sp_3072_mod_106(a, a, m);
|
|
|
|
if (err == MP_OKAY) {
|
|
for (i=28; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 212U);
|
|
for (i--; i>=0; i--) {
|
|
sp_3072_mont_sqr_106(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_3072_mont_mul_106(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_3072_mont_reduce_106(r, m, mp);
|
|
mp = sp_3072_cmp_106(r, m);
|
|
sp_3072_cond_sub_106(r, r, m, ~(mp >> 31));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
|
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
|
|
#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
|
|
/* RSA private key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* dm Private exponent.
|
|
* pm First prime.
|
|
* qm Second prime.
|
|
* dpm First prime's CRT exponent.
|
|
* dqm Second prime's CRT exponent.
|
|
* qim Inverse of second prime mod p.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 384 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
|
|
const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
|
|
const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[106 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 106;
|
|
m = a + 212;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 106, in, inLen);
|
|
sp_3072_from_mp(d, 106, dm);
|
|
sp_3072_from_mp(m, 106, mm);
|
|
err = sp_3072_mod_exp_106(r, a, d, 3072, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 106);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[106 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 106;
|
|
m = a + 212;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 106, in, inLen);
|
|
sp_3072_from_mp(d, 106, dm);
|
|
sp_3072_from_mp(m, 106, mm);
|
|
err = sp_3072_mod_exp_106(r, a, d, 3072, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 106);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#else
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[53 * 8];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 384) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 8, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
p = a + 106;
|
|
qi = dq = dp = p + 53;
|
|
tmpa = qi + 53;
|
|
tmpb = tmpa + 106;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 106, in, inLen);
|
|
sp_3072_from_mp(p, 53, pm);
|
|
sp_3072_from_mp(dp, 53, dpm);
|
|
err = sp_3072_mod_exp_53(tmpa, a, dp, 1536, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(p, 53, qm);
|
|
sp_3072_from_mp(dq, 53, dqm);
|
|
err = sp_3072_mod_exp_53(tmpb, a, dq, 1536, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(p, 53, pm);
|
|
(void)sp_3072_sub_53(tmpa, tmpa, tmpb);
|
|
sp_3072_norm_53(tmpa);
|
|
sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
|
|
sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
|
|
sp_3072_norm_53(tmpa);
|
|
|
|
sp_3072_from_mp(qi, 53, qim);
|
|
sp_3072_mul_53(tmpa, tmpa, qi);
|
|
err = sp_3072_mod_53(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(p, 53, qm);
|
|
sp_3072_mul_53(tmpa, p, tmpa);
|
|
(void)sp_3072_add_106(r, tmpb, tmpa);
|
|
sp_3072_norm_106(r);
|
|
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 53 * 8);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[53 * 13];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* q = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 13, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = a + 106 * 2;
|
|
q = p + 53;
|
|
dp = q + 53;
|
|
dq = dp + 53;
|
|
qi = dq + 53;
|
|
tmpa = qi + 53;
|
|
tmpb = tmpa + 106;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 106, in, inLen);
|
|
sp_3072_from_mp(p, 53, pm);
|
|
sp_3072_from_mp(q, 53, qm);
|
|
sp_3072_from_mp(dp, 53, dpm);
|
|
sp_3072_from_mp(dq, 53, dqm);
|
|
sp_3072_from_mp(qi, 53, qim);
|
|
|
|
err = sp_3072_mod_exp_53(tmpa, a, dp, 1536, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_3072_mod_exp_53(tmpb, a, dq, 1536, q, 1);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
(void)sp_3072_sub_53(tmpa, tmpa, tmpb);
|
|
sp_3072_norm_53(tmpa);
|
|
sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
|
|
sp_3072_cond_add_53(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[52] >> 31));
|
|
sp_3072_norm_53(tmpa);
|
|
sp_3072_mul_53(tmpa, tmpa, qi);
|
|
err = sp_3072_mod_53(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_53(tmpa, tmpa, q);
|
|
(void)sp_3072_add_106(r, tmpb, tmpa);
|
|
sp_3072_norm_106(r);
|
|
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 53 * 13);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
|
|
}
|
|
|
|
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
#endif /* WOLFSSL_HAVE_SP_RSA */
|
|
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
|
|
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 29
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 106);
|
|
r->used = 106;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 29
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 106; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 29) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 29 - s;
|
|
}
|
|
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 106; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 29 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 29 - s;
|
|
}
|
|
else {
|
|
s += 29;
|
|
}
|
|
}
|
|
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[106 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 106 * 2;
|
|
m = e + 106;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 106, base);
|
|
sp_3072_from_mp(e, 106, exp);
|
|
sp_3072_from_mp(m, 106, mod);
|
|
|
|
err = sp_3072_mod_exp_106(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 106U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[106 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 106 * 2;
|
|
m = e + 106;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 106, base);
|
|
sp_3072_from_mp(e, 106, exp);
|
|
sp_3072_from_mp(m, 106, mod);
|
|
|
|
err = sp_3072_mod_exp_106(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 106U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#ifdef WOLFSSL_HAVE_SP_DH
|
|
|
|
#ifdef HAVE_FFDHE_3072
|
|
SP_NOINLINE static void sp_3072_lshift_106(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
r[106] = a[105] >> (29 - n);
|
|
for (i=105; i>0; i--) {
|
|
r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
|
|
}
|
|
r[0] = (a[0] << n) & 0x1fffffff;
|
|
}
|
|
|
|
/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even.
|
|
*/
|
|
static int sp_3072_mod_exp_2_106(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[319];
|
|
#endif
|
|
sp_digit* norm = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
sp_digit o;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 319, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
tmp = td + 212;
|
|
XMEMSET(td, 0, sizeof(sp_digit) * 319);
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_106(norm, m);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 106) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
sp_3072_lshift_106(r, norm, (byte)y);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 25;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 3;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_3072_mont_sqr_106(r, r, m, mp);
|
|
sp_3072_mont_sqr_106(r, r, m, mp);
|
|
sp_3072_mont_sqr_106(r, r, m, mp);
|
|
sp_3072_mont_sqr_106(r, r, m, mp);
|
|
|
|
sp_3072_lshift_106(r, r, (byte)y);
|
|
sp_3072_mul_d_106(tmp, norm, (r[106] << 2) + (r[105] >> 27));
|
|
r[106] = 0;
|
|
r[105] &= 0x7ffffffL;
|
|
(void)sp_3072_add_106(r, r, tmp);
|
|
sp_3072_norm_106(r);
|
|
o = sp_3072_cmp_106(r, m);
|
|
sp_3072_cond_sub_106(r, r, m, ~(o >> 31));
|
|
}
|
|
|
|
sp_3072_mont_reduce_106(r, m, mp);
|
|
n = sp_3072_cmp_106(r, m);
|
|
sp_3072_cond_sub_106(r, r, m, ~(n >> 31));
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* HAVE_FFDHE_3072 */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base.
|
|
* exp Array of bytes that is the exponent.
|
|
* expLen Length of data, in bytes, in exponent.
|
|
* mod Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 384 bytes long.
|
|
* outLen Length, in bytes, of exponentiation result.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
|
|
const mp_int* mod, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[106 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
word32 i;
|
|
int err = MP_OKAY;
|
|
|
|
if (mp_count_bits(base) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 106 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 106 * 2;
|
|
m = e + 106;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 106, base);
|
|
sp_3072_from_bin(e, 106, exp, expLen);
|
|
sp_3072_from_mp(m, 106, mod);
|
|
|
|
#ifdef HAVE_FFDHE_3072
|
|
if (base->used == 1 && base->dp[0] == 2U &&
|
|
(m[105] >> 11) == 0xffffL) {
|
|
err = sp_3072_mod_exp_2_106(r, e, expLen * 8U, m);
|
|
}
|
|
else {
|
|
#endif
|
|
err = sp_3072_mod_exp_106(r, b, e, expLen * 8U, m, 0);
|
|
#ifdef HAVE_FFDHE_3072
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_106(r, out);
|
|
*outLen = 384;
|
|
for (i=0; i<384U && out[i] == 0U; i++) {
|
|
/* Search for first non-zero. */
|
|
}
|
|
*outLen -= i;
|
|
XMEMMOVE(out, out + i, *outLen);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 106U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[53 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 53 * 2;
|
|
m = e + 53;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 53, base);
|
|
sp_3072_from_mp(e, 53, exp);
|
|
sp_3072_from_mp(m, 53, mod);
|
|
|
|
err = sp_3072_mod_exp_53(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(r + 53, 0, sizeof(*r) * 53U);
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 106U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[53 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 53 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 53 * 2;
|
|
m = e + 53;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 53, base);
|
|
sp_3072_from_mp(e, 53, exp);
|
|
sp_3072_from_mp(m, 53, mod);
|
|
|
|
err = sp_3072_mod_exp_53(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(r + 53, 0, sizeof(*r) * 53U);
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 106U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
|
|
|
|
#else
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_3072_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 20U) {
|
|
r[j] &= 0xfffffff;
|
|
s = 28U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_3072_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 28
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 28
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0xfffffff;
|
|
s = 28U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 28U) <= (word32)DIGIT_BIT) {
|
|
s += 28U;
|
|
r[j] &= 0xfffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 28) {
|
|
r[j] &= 0xfffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 28 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 384
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_3072_to_bin_112(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<111; i++) {
|
|
r[i+1] += r[i] >> 28;
|
|
r[i] &= 0xfffffff;
|
|
}
|
|
j = 3079 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<110 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 28) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 28);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_56(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 48; i += 8) {
|
|
a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
|
|
a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
|
|
a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
|
|
a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
|
|
a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
|
|
a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
|
|
a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
|
|
a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
|
|
}
|
|
a[49] += a[48] >> 28; a[48] &= 0xfffffff;
|
|
a[50] += a[49] >> 28; a[49] &= 0xfffffff;
|
|
a[51] += a[50] >> 28; a[50] &= 0xfffffff;
|
|
a[52] += a[51] >> 28; a[51] &= 0xfffffff;
|
|
a[53] += a[52] >> 28; a[52] &= 0xfffffff;
|
|
a[54] += a[53] >> 28; a[53] &= 0xfffffff;
|
|
a[55] += a[54] >> 28; a[54] &= 0xfffffff;
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_55(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 48; i += 8) {
|
|
a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
|
|
a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
|
|
a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
|
|
a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
|
|
a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
|
|
a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
|
|
a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
|
|
a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
|
|
}
|
|
a[49] += a[48] >> 28; a[48] &= 0xfffffff;
|
|
a[50] += a[49] >> 28; a[49] &= 0xfffffff;
|
|
a[51] += a[50] >> 28; a[50] &= 0xfffffff;
|
|
a[52] += a[51] >> 28; a[51] &= 0xfffffff;
|
|
a[53] += a[52] >> 28; a[52] &= 0xfffffff;
|
|
a[54] += a[53] >> 28; a[53] &= 0xfffffff;
|
|
}
|
|
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_112(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 104; i += 8) {
|
|
a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
|
|
a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
|
|
a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
|
|
a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
|
|
a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
|
|
a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
|
|
a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
|
|
a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
|
|
}
|
|
a[105] += a[104] >> 28; a[104] &= 0xfffffff;
|
|
a[106] += a[105] >> 28; a[105] &= 0xfffffff;
|
|
a[107] += a[106] >> 28; a[106] &= 0xfffffff;
|
|
a[108] += a[107] >> 28; a[107] &= 0xfffffff;
|
|
a[109] += a[108] >> 28; a[108] &= 0xfffffff;
|
|
a[110] += a[109] >> 28; a[109] &= 0xfffffff;
|
|
a[111] += a[110] >> 28; a[110] &= 0xfffffff;
|
|
}
|
|
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_110(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 104; i += 8) {
|
|
a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
|
|
a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
|
|
a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
|
|
a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
|
|
a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
|
|
a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
|
|
a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
|
|
a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
|
|
}
|
|
a[105] += a[104] >> 28; a[104] &= 0xfffffff;
|
|
a[106] += a[105] >> 28; a[105] &= 0xfffffff;
|
|
a[107] += a[106] >> 28; a[106] &= 0xfffffff;
|
|
a[108] += a[107] >> 28; a[107] &= 0xfffffff;
|
|
a[109] += a[108] >> 28; a[108] &= 0xfffffff;
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_14(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_uint64 t0;
|
|
sp_uint64 t1;
|
|
sp_digit t[14];
|
|
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 0];
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 1]
|
|
+ ((sp_uint64)a[ 1]) * b[ 0];
|
|
t[ 0] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 2]
|
|
+ ((sp_uint64)a[ 1]) * b[ 1]
|
|
+ ((sp_uint64)a[ 2]) * b[ 0];
|
|
t[ 1] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 3]
|
|
+ ((sp_uint64)a[ 1]) * b[ 2]
|
|
+ ((sp_uint64)a[ 2]) * b[ 1]
|
|
+ ((sp_uint64)a[ 3]) * b[ 0];
|
|
t[ 2] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 4]
|
|
+ ((sp_uint64)a[ 1]) * b[ 3]
|
|
+ ((sp_uint64)a[ 2]) * b[ 2]
|
|
+ ((sp_uint64)a[ 3]) * b[ 1]
|
|
+ ((sp_uint64)a[ 4]) * b[ 0];
|
|
t[ 3] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 5]
|
|
+ ((sp_uint64)a[ 1]) * b[ 4]
|
|
+ ((sp_uint64)a[ 2]) * b[ 3]
|
|
+ ((sp_uint64)a[ 3]) * b[ 2]
|
|
+ ((sp_uint64)a[ 4]) * b[ 1]
|
|
+ ((sp_uint64)a[ 5]) * b[ 0];
|
|
t[ 4] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 6]
|
|
+ ((sp_uint64)a[ 1]) * b[ 5]
|
|
+ ((sp_uint64)a[ 2]) * b[ 4]
|
|
+ ((sp_uint64)a[ 3]) * b[ 3]
|
|
+ ((sp_uint64)a[ 4]) * b[ 2]
|
|
+ ((sp_uint64)a[ 5]) * b[ 1]
|
|
+ ((sp_uint64)a[ 6]) * b[ 0];
|
|
t[ 5] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 7]
|
|
+ ((sp_uint64)a[ 1]) * b[ 6]
|
|
+ ((sp_uint64)a[ 2]) * b[ 5]
|
|
+ ((sp_uint64)a[ 3]) * b[ 4]
|
|
+ ((sp_uint64)a[ 4]) * b[ 3]
|
|
+ ((sp_uint64)a[ 5]) * b[ 2]
|
|
+ ((sp_uint64)a[ 6]) * b[ 1]
|
|
+ ((sp_uint64)a[ 7]) * b[ 0];
|
|
t[ 6] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 8]
|
|
+ ((sp_uint64)a[ 1]) * b[ 7]
|
|
+ ((sp_uint64)a[ 2]) * b[ 6]
|
|
+ ((sp_uint64)a[ 3]) * b[ 5]
|
|
+ ((sp_uint64)a[ 4]) * b[ 4]
|
|
+ ((sp_uint64)a[ 5]) * b[ 3]
|
|
+ ((sp_uint64)a[ 6]) * b[ 2]
|
|
+ ((sp_uint64)a[ 7]) * b[ 1]
|
|
+ ((sp_uint64)a[ 8]) * b[ 0];
|
|
t[ 7] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 9]
|
|
+ ((sp_uint64)a[ 1]) * b[ 8]
|
|
+ ((sp_uint64)a[ 2]) * b[ 7]
|
|
+ ((sp_uint64)a[ 3]) * b[ 6]
|
|
+ ((sp_uint64)a[ 4]) * b[ 5]
|
|
+ ((sp_uint64)a[ 5]) * b[ 4]
|
|
+ ((sp_uint64)a[ 6]) * b[ 3]
|
|
+ ((sp_uint64)a[ 7]) * b[ 2]
|
|
+ ((sp_uint64)a[ 8]) * b[ 1]
|
|
+ ((sp_uint64)a[ 9]) * b[ 0];
|
|
t[ 8] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 0]) * b[10]
|
|
+ ((sp_uint64)a[ 1]) * b[ 9]
|
|
+ ((sp_uint64)a[ 2]) * b[ 8]
|
|
+ ((sp_uint64)a[ 3]) * b[ 7]
|
|
+ ((sp_uint64)a[ 4]) * b[ 6]
|
|
+ ((sp_uint64)a[ 5]) * b[ 5]
|
|
+ ((sp_uint64)a[ 6]) * b[ 4]
|
|
+ ((sp_uint64)a[ 7]) * b[ 3]
|
|
+ ((sp_uint64)a[ 8]) * b[ 2]
|
|
+ ((sp_uint64)a[ 9]) * b[ 1]
|
|
+ ((sp_uint64)a[10]) * b[ 0];
|
|
t[ 9] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 0]) * b[11]
|
|
+ ((sp_uint64)a[ 1]) * b[10]
|
|
+ ((sp_uint64)a[ 2]) * b[ 9]
|
|
+ ((sp_uint64)a[ 3]) * b[ 8]
|
|
+ ((sp_uint64)a[ 4]) * b[ 7]
|
|
+ ((sp_uint64)a[ 5]) * b[ 6]
|
|
+ ((sp_uint64)a[ 6]) * b[ 5]
|
|
+ ((sp_uint64)a[ 7]) * b[ 4]
|
|
+ ((sp_uint64)a[ 8]) * b[ 3]
|
|
+ ((sp_uint64)a[ 9]) * b[ 2]
|
|
+ ((sp_uint64)a[10]) * b[ 1]
|
|
+ ((sp_uint64)a[11]) * b[ 0];
|
|
t[10] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 0]) * b[12]
|
|
+ ((sp_uint64)a[ 1]) * b[11]
|
|
+ ((sp_uint64)a[ 2]) * b[10]
|
|
+ ((sp_uint64)a[ 3]) * b[ 9]
|
|
+ ((sp_uint64)a[ 4]) * b[ 8]
|
|
+ ((sp_uint64)a[ 5]) * b[ 7]
|
|
+ ((sp_uint64)a[ 6]) * b[ 6]
|
|
+ ((sp_uint64)a[ 7]) * b[ 5]
|
|
+ ((sp_uint64)a[ 8]) * b[ 4]
|
|
+ ((sp_uint64)a[ 9]) * b[ 3]
|
|
+ ((sp_uint64)a[10]) * b[ 2]
|
|
+ ((sp_uint64)a[11]) * b[ 1]
|
|
+ ((sp_uint64)a[12]) * b[ 0];
|
|
t[11] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 0]) * b[13]
|
|
+ ((sp_uint64)a[ 1]) * b[12]
|
|
+ ((sp_uint64)a[ 2]) * b[11]
|
|
+ ((sp_uint64)a[ 3]) * b[10]
|
|
+ ((sp_uint64)a[ 4]) * b[ 9]
|
|
+ ((sp_uint64)a[ 5]) * b[ 8]
|
|
+ ((sp_uint64)a[ 6]) * b[ 7]
|
|
+ ((sp_uint64)a[ 7]) * b[ 6]
|
|
+ ((sp_uint64)a[ 8]) * b[ 5]
|
|
+ ((sp_uint64)a[ 9]) * b[ 4]
|
|
+ ((sp_uint64)a[10]) * b[ 3]
|
|
+ ((sp_uint64)a[11]) * b[ 2]
|
|
+ ((sp_uint64)a[12]) * b[ 1]
|
|
+ ((sp_uint64)a[13]) * b[ 0];
|
|
t[12] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 1]) * b[13]
|
|
+ ((sp_uint64)a[ 2]) * b[12]
|
|
+ ((sp_uint64)a[ 3]) * b[11]
|
|
+ ((sp_uint64)a[ 4]) * b[10]
|
|
+ ((sp_uint64)a[ 5]) * b[ 9]
|
|
+ ((sp_uint64)a[ 6]) * b[ 8]
|
|
+ ((sp_uint64)a[ 7]) * b[ 7]
|
|
+ ((sp_uint64)a[ 8]) * b[ 6]
|
|
+ ((sp_uint64)a[ 9]) * b[ 5]
|
|
+ ((sp_uint64)a[10]) * b[ 4]
|
|
+ ((sp_uint64)a[11]) * b[ 3]
|
|
+ ((sp_uint64)a[12]) * b[ 2]
|
|
+ ((sp_uint64)a[13]) * b[ 1];
|
|
t[13] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 2]) * b[13]
|
|
+ ((sp_uint64)a[ 3]) * b[12]
|
|
+ ((sp_uint64)a[ 4]) * b[11]
|
|
+ ((sp_uint64)a[ 5]) * b[10]
|
|
+ ((sp_uint64)a[ 6]) * b[ 9]
|
|
+ ((sp_uint64)a[ 7]) * b[ 8]
|
|
+ ((sp_uint64)a[ 8]) * b[ 7]
|
|
+ ((sp_uint64)a[ 9]) * b[ 6]
|
|
+ ((sp_uint64)a[10]) * b[ 5]
|
|
+ ((sp_uint64)a[11]) * b[ 4]
|
|
+ ((sp_uint64)a[12]) * b[ 3]
|
|
+ ((sp_uint64)a[13]) * b[ 2];
|
|
r[14] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 3]) * b[13]
|
|
+ ((sp_uint64)a[ 4]) * b[12]
|
|
+ ((sp_uint64)a[ 5]) * b[11]
|
|
+ ((sp_uint64)a[ 6]) * b[10]
|
|
+ ((sp_uint64)a[ 7]) * b[ 9]
|
|
+ ((sp_uint64)a[ 8]) * b[ 8]
|
|
+ ((sp_uint64)a[ 9]) * b[ 7]
|
|
+ ((sp_uint64)a[10]) * b[ 6]
|
|
+ ((sp_uint64)a[11]) * b[ 5]
|
|
+ ((sp_uint64)a[12]) * b[ 4]
|
|
+ ((sp_uint64)a[13]) * b[ 3];
|
|
r[15] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 4]) * b[13]
|
|
+ ((sp_uint64)a[ 5]) * b[12]
|
|
+ ((sp_uint64)a[ 6]) * b[11]
|
|
+ ((sp_uint64)a[ 7]) * b[10]
|
|
+ ((sp_uint64)a[ 8]) * b[ 9]
|
|
+ ((sp_uint64)a[ 9]) * b[ 8]
|
|
+ ((sp_uint64)a[10]) * b[ 7]
|
|
+ ((sp_uint64)a[11]) * b[ 6]
|
|
+ ((sp_uint64)a[12]) * b[ 5]
|
|
+ ((sp_uint64)a[13]) * b[ 4];
|
|
r[16] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 5]) * b[13]
|
|
+ ((sp_uint64)a[ 6]) * b[12]
|
|
+ ((sp_uint64)a[ 7]) * b[11]
|
|
+ ((sp_uint64)a[ 8]) * b[10]
|
|
+ ((sp_uint64)a[ 9]) * b[ 9]
|
|
+ ((sp_uint64)a[10]) * b[ 8]
|
|
+ ((sp_uint64)a[11]) * b[ 7]
|
|
+ ((sp_uint64)a[12]) * b[ 6]
|
|
+ ((sp_uint64)a[13]) * b[ 5];
|
|
r[17] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 6]) * b[13]
|
|
+ ((sp_uint64)a[ 7]) * b[12]
|
|
+ ((sp_uint64)a[ 8]) * b[11]
|
|
+ ((sp_uint64)a[ 9]) * b[10]
|
|
+ ((sp_uint64)a[10]) * b[ 9]
|
|
+ ((sp_uint64)a[11]) * b[ 8]
|
|
+ ((sp_uint64)a[12]) * b[ 7]
|
|
+ ((sp_uint64)a[13]) * b[ 6];
|
|
r[18] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 7]) * b[13]
|
|
+ ((sp_uint64)a[ 8]) * b[12]
|
|
+ ((sp_uint64)a[ 9]) * b[11]
|
|
+ ((sp_uint64)a[10]) * b[10]
|
|
+ ((sp_uint64)a[11]) * b[ 9]
|
|
+ ((sp_uint64)a[12]) * b[ 8]
|
|
+ ((sp_uint64)a[13]) * b[ 7];
|
|
r[19] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[ 8]) * b[13]
|
|
+ ((sp_uint64)a[ 9]) * b[12]
|
|
+ ((sp_uint64)a[10]) * b[11]
|
|
+ ((sp_uint64)a[11]) * b[10]
|
|
+ ((sp_uint64)a[12]) * b[ 9]
|
|
+ ((sp_uint64)a[13]) * b[ 8];
|
|
r[20] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[ 9]) * b[13]
|
|
+ ((sp_uint64)a[10]) * b[12]
|
|
+ ((sp_uint64)a[11]) * b[11]
|
|
+ ((sp_uint64)a[12]) * b[10]
|
|
+ ((sp_uint64)a[13]) * b[ 9];
|
|
r[21] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[10]) * b[13]
|
|
+ ((sp_uint64)a[11]) * b[12]
|
|
+ ((sp_uint64)a[12]) * b[11]
|
|
+ ((sp_uint64)a[13]) * b[10];
|
|
r[22] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[11]) * b[13]
|
|
+ ((sp_uint64)a[12]) * b[12]
|
|
+ ((sp_uint64)a[13]) * b[11];
|
|
r[23] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = ((sp_uint64)a[12]) * b[13]
|
|
+ ((sp_uint64)a[13]) * b[12];
|
|
r[24] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[13]) * b[13];
|
|
r[25] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
r[26] = t0 & 0xfffffff;
|
|
r[27] = (sp_digit)(t0 >> 28);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_add_14(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
r[ 7] = a[ 7] + b[ 7];
|
|
r[ 8] = a[ 8] + b[ 8];
|
|
r[ 9] = a[ 9] + b[ 9];
|
|
r[10] = a[10] + b[10];
|
|
r[11] = a[11] + b[11];
|
|
r[12] = a[12] + b[12];
|
|
r[13] = a[13] + b[13];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_add_28(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 24; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[24] = a[24] + b[24];
|
|
r[25] = a[25] + b[25];
|
|
r[26] = a[26] + b[26];
|
|
r[27] = a[27] + b[27];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_sub_28(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 24; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[24] = a[24] - b[24];
|
|
r[25] = a[25] - b[25];
|
|
r[26] = a[26] - b[26];
|
|
r[27] = a[27] - b[27];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_14(sp_digit* a)
|
|
{
|
|
a[1] += a[0] >> 28; a[0] &= 0xfffffff;
|
|
a[2] += a[1] >> 28; a[1] &= 0xfffffff;
|
|
a[3] += a[2] >> 28; a[2] &= 0xfffffff;
|
|
a[4] += a[3] >> 28; a[3] &= 0xfffffff;
|
|
a[5] += a[4] >> 28; a[4] &= 0xfffffff;
|
|
a[6] += a[5] >> 28; a[5] &= 0xfffffff;
|
|
a[7] += a[6] >> 28; a[6] &= 0xfffffff;
|
|
a[8] += a[7] >> 28; a[7] &= 0xfffffff;
|
|
a[9] += a[8] >> 28; a[8] &= 0xfffffff;
|
|
a[10] += a[9] >> 28; a[9] &= 0xfffffff;
|
|
a[11] += a[10] >> 28; a[10] &= 0xfffffff;
|
|
a[12] += a[11] >> 28; a[11] &= 0xfffffff;
|
|
a[13] += a[12] >> 28; a[12] &= 0xfffffff;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_28(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[28];
|
|
sp_digit* a1 = z1;
|
|
sp_digit b1[14];
|
|
sp_digit* z2 = r + 28;
|
|
(void)sp_3072_add_14(a1, a, &a[14]);
|
|
sp_3072_norm_14(a1);
|
|
(void)sp_3072_add_14(b1, b, &b[14]);
|
|
sp_3072_norm_14(b1);
|
|
sp_3072_mul_14(z2, &a[14], &b[14]);
|
|
sp_3072_mul_14(z0, a, b);
|
|
sp_3072_mul_14(z1, a1, b1);
|
|
(void)sp_3072_sub_28(z1, z1, z2);
|
|
(void)sp_3072_sub_28(z1, z1, z0);
|
|
(void)sp_3072_add_28(r + 14, r + 14, z1);
|
|
sp_3072_norm_56(r);
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_add_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 56; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_sub_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 56; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_28(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 24; i += 8) {
|
|
a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
|
|
a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
|
|
a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
|
|
a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
|
|
a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
|
|
a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
|
|
a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
|
|
a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
|
|
}
|
|
a[25] += a[24] >> 28; a[24] &= 0xfffffff;
|
|
a[26] += a[25] >> 28; a[25] &= 0xfffffff;
|
|
a[27] += a[26] >> 28; a[26] &= 0xfffffff;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[56];
|
|
sp_digit* a1 = z1;
|
|
sp_digit b1[28];
|
|
sp_digit* z2 = r + 56;
|
|
(void)sp_3072_add_28(a1, a, &a[28]);
|
|
sp_3072_norm_28(a1);
|
|
(void)sp_3072_add_28(b1, b, &b[28]);
|
|
sp_3072_norm_28(b1);
|
|
sp_3072_mul_28(z2, &a[28], &b[28]);
|
|
sp_3072_mul_28(z0, a, b);
|
|
sp_3072_mul_28(z1, a1, b1);
|
|
(void)sp_3072_sub_56(z1, z1, z2);
|
|
(void)sp_3072_sub_56(z1, z1, z0);
|
|
(void)sp_3072_add_56(r + 28, r + 28, z1);
|
|
sp_3072_norm_112(r);
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_add_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 112; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_3072_sub_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 112; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 28 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_3072_norm_224(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 216; i += 8) {
|
|
a[i+1] += a[i+0] >> 28; a[i+0] &= 0xfffffff;
|
|
a[i+2] += a[i+1] >> 28; a[i+1] &= 0xfffffff;
|
|
a[i+3] += a[i+2] >> 28; a[i+2] &= 0xfffffff;
|
|
a[i+4] += a[i+3] >> 28; a[i+3] &= 0xfffffff;
|
|
a[i+5] += a[i+4] >> 28; a[i+4] &= 0xfffffff;
|
|
a[i+6] += a[i+5] >> 28; a[i+5] &= 0xfffffff;
|
|
a[i+7] += a[i+6] >> 28; a[i+6] &= 0xfffffff;
|
|
a[i+8] += a[i+7] >> 28; a[i+7] &= 0xfffffff;
|
|
}
|
|
a[217] += a[216] >> 28; a[216] &= 0xfffffff;
|
|
a[218] += a[217] >> 28; a[217] &= 0xfffffff;
|
|
a[219] += a[218] >> 28; a[218] &= 0xfffffff;
|
|
a[220] += a[219] >> 28; a[219] &= 0xfffffff;
|
|
a[221] += a[220] >> 28; a[220] &= 0xfffffff;
|
|
a[222] += a[221] >> 28; a[221] &= 0xfffffff;
|
|
a[223] += a[222] >> 28; a[222] &= 0xfffffff;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[112];
|
|
sp_digit* a1 = z1;
|
|
sp_digit b1[56];
|
|
sp_digit* z2 = r + 112;
|
|
(void)sp_3072_add_56(a1, a, &a[56]);
|
|
sp_3072_norm_56(a1);
|
|
(void)sp_3072_add_56(b1, b, &b[56]);
|
|
sp_3072_norm_56(b1);
|
|
sp_3072_mul_56(z2, &a[56], &b[56]);
|
|
sp_3072_mul_56(z0, a, b);
|
|
sp_3072_mul_56(z1, a1, b1);
|
|
(void)sp_3072_sub_112(z1, z1, z2);
|
|
(void)sp_3072_sub_112(z1, z1, z0);
|
|
(void)sp_3072_add_112(r + 56, r + 56, z1);
|
|
sp_3072_norm_224(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_sqr_14(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_uint64 t0;
|
|
sp_uint64 t1;
|
|
sp_digit t[14];
|
|
|
|
t0 = ((sp_uint64)a[ 0]) * a[ 0];
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2;
|
|
t[ 0] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 2]) * 2
|
|
+ ((sp_uint64)a[ 1]) * a[ 1];
|
|
t[ 1] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 3]
|
|
+ ((sp_uint64)a[ 1]) * a[ 2]) * 2;
|
|
t[ 2] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 4]
|
|
+ ((sp_uint64)a[ 1]) * a[ 3]) * 2
|
|
+ ((sp_uint64)a[ 2]) * a[ 2];
|
|
t[ 3] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 5]
|
|
+ ((sp_uint64)a[ 1]) * a[ 4]
|
|
+ ((sp_uint64)a[ 2]) * a[ 3]) * 2;
|
|
t[ 4] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 6]
|
|
+ ((sp_uint64)a[ 1]) * a[ 5]
|
|
+ ((sp_uint64)a[ 2]) * a[ 4]) * 2
|
|
+ ((sp_uint64)a[ 3]) * a[ 3];
|
|
t[ 5] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 7]
|
|
+ ((sp_uint64)a[ 1]) * a[ 6]
|
|
+ ((sp_uint64)a[ 2]) * a[ 5]
|
|
+ ((sp_uint64)a[ 3]) * a[ 4]) * 2;
|
|
t[ 6] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 8]
|
|
+ ((sp_uint64)a[ 1]) * a[ 7]
|
|
+ ((sp_uint64)a[ 2]) * a[ 6]
|
|
+ ((sp_uint64)a[ 3]) * a[ 5]) * 2
|
|
+ ((sp_uint64)a[ 4]) * a[ 4];
|
|
t[ 7] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 9]
|
|
+ ((sp_uint64)a[ 1]) * a[ 8]
|
|
+ ((sp_uint64)a[ 2]) * a[ 7]
|
|
+ ((sp_uint64)a[ 3]) * a[ 6]
|
|
+ ((sp_uint64)a[ 4]) * a[ 5]) * 2;
|
|
t[ 8] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 0]) * a[10]
|
|
+ ((sp_uint64)a[ 1]) * a[ 9]
|
|
+ ((sp_uint64)a[ 2]) * a[ 8]
|
|
+ ((sp_uint64)a[ 3]) * a[ 7]
|
|
+ ((sp_uint64)a[ 4]) * a[ 6]) * 2
|
|
+ ((sp_uint64)a[ 5]) * a[ 5];
|
|
t[ 9] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 0]) * a[11]
|
|
+ ((sp_uint64)a[ 1]) * a[10]
|
|
+ ((sp_uint64)a[ 2]) * a[ 9]
|
|
+ ((sp_uint64)a[ 3]) * a[ 8]
|
|
+ ((sp_uint64)a[ 4]) * a[ 7]
|
|
+ ((sp_uint64)a[ 5]) * a[ 6]) * 2;
|
|
t[10] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 0]) * a[12]
|
|
+ ((sp_uint64)a[ 1]) * a[11]
|
|
+ ((sp_uint64)a[ 2]) * a[10]
|
|
+ ((sp_uint64)a[ 3]) * a[ 9]
|
|
+ ((sp_uint64)a[ 4]) * a[ 8]
|
|
+ ((sp_uint64)a[ 5]) * a[ 7]) * 2
|
|
+ ((sp_uint64)a[ 6]) * a[ 6];
|
|
t[11] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 0]) * a[13]
|
|
+ ((sp_uint64)a[ 1]) * a[12]
|
|
+ ((sp_uint64)a[ 2]) * a[11]
|
|
+ ((sp_uint64)a[ 3]) * a[10]
|
|
+ ((sp_uint64)a[ 4]) * a[ 9]
|
|
+ ((sp_uint64)a[ 5]) * a[ 8]
|
|
+ ((sp_uint64)a[ 6]) * a[ 7]) * 2;
|
|
t[12] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 1]) * a[13]
|
|
+ ((sp_uint64)a[ 2]) * a[12]
|
|
+ ((sp_uint64)a[ 3]) * a[11]
|
|
+ ((sp_uint64)a[ 4]) * a[10]
|
|
+ ((sp_uint64)a[ 5]) * a[ 9]
|
|
+ ((sp_uint64)a[ 6]) * a[ 8]) * 2
|
|
+ ((sp_uint64)a[ 7]) * a[ 7];
|
|
t[13] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 2]) * a[13]
|
|
+ ((sp_uint64)a[ 3]) * a[12]
|
|
+ ((sp_uint64)a[ 4]) * a[11]
|
|
+ ((sp_uint64)a[ 5]) * a[10]
|
|
+ ((sp_uint64)a[ 6]) * a[ 9]
|
|
+ ((sp_uint64)a[ 7]) * a[ 8]) * 2;
|
|
r[14] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 3]) * a[13]
|
|
+ ((sp_uint64)a[ 4]) * a[12]
|
|
+ ((sp_uint64)a[ 5]) * a[11]
|
|
+ ((sp_uint64)a[ 6]) * a[10]
|
|
+ ((sp_uint64)a[ 7]) * a[ 9]) * 2
|
|
+ ((sp_uint64)a[ 8]) * a[ 8];
|
|
r[15] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 4]) * a[13]
|
|
+ ((sp_uint64)a[ 5]) * a[12]
|
|
+ ((sp_uint64)a[ 6]) * a[11]
|
|
+ ((sp_uint64)a[ 7]) * a[10]
|
|
+ ((sp_uint64)a[ 8]) * a[ 9]) * 2;
|
|
r[16] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 5]) * a[13]
|
|
+ ((sp_uint64)a[ 6]) * a[12]
|
|
+ ((sp_uint64)a[ 7]) * a[11]
|
|
+ ((sp_uint64)a[ 8]) * a[10]) * 2
|
|
+ ((sp_uint64)a[ 9]) * a[ 9];
|
|
r[17] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 6]) * a[13]
|
|
+ ((sp_uint64)a[ 7]) * a[12]
|
|
+ ((sp_uint64)a[ 8]) * a[11]
|
|
+ ((sp_uint64)a[ 9]) * a[10]) * 2;
|
|
r[18] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 7]) * a[13]
|
|
+ ((sp_uint64)a[ 8]) * a[12]
|
|
+ ((sp_uint64)a[ 9]) * a[11]) * 2
|
|
+ ((sp_uint64)a[10]) * a[10];
|
|
r[19] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[ 8]) * a[13]
|
|
+ ((sp_uint64)a[ 9]) * a[12]
|
|
+ ((sp_uint64)a[10]) * a[11]) * 2;
|
|
r[20] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[ 9]) * a[13]
|
|
+ ((sp_uint64)a[10]) * a[12]) * 2
|
|
+ ((sp_uint64)a[11]) * a[11];
|
|
r[21] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[10]) * a[13]
|
|
+ ((sp_uint64)a[11]) * a[12]) * 2;
|
|
r[22] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = (((sp_uint64)a[11]) * a[13]) * 2
|
|
+ ((sp_uint64)a[12]) * a[12];
|
|
r[23] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
t1 = (((sp_uint64)a[12]) * a[13]) * 2;
|
|
r[24] = t0 & 0xfffffff; t1 += t0 >> 28;
|
|
t0 = ((sp_uint64)a[13]) * a[13];
|
|
r[25] = t1 & 0xfffffff; t0 += t1 >> 28;
|
|
r[26] = t0 & 0xfffffff;
|
|
r[27] = (sp_digit)(t0 >> 28);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_sqr_28(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[28];
|
|
sp_digit* a1 = z1;
|
|
sp_digit* z2 = r + 28;
|
|
(void)sp_3072_add_14(a1, a, &a[14]);
|
|
sp_3072_norm_14(a1);
|
|
sp_3072_sqr_14(z2, &a[14]);
|
|
sp_3072_sqr_14(z0, a);
|
|
sp_3072_sqr_14(z1, a1);
|
|
(void)sp_3072_sub_28(z1, z1, z2);
|
|
(void)sp_3072_sub_28(z1, z1, z0);
|
|
(void)sp_3072_add_28(r + 14, r + 14, z1);
|
|
sp_3072_norm_56(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_sqr_56(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[56];
|
|
sp_digit* a1 = z1;
|
|
sp_digit* z2 = r + 56;
|
|
(void)sp_3072_add_28(a1, a, &a[28]);
|
|
sp_3072_norm_28(a1);
|
|
sp_3072_sqr_28(z2, &a[28]);
|
|
sp_3072_sqr_28(z0, a);
|
|
sp_3072_sqr_28(z1, a1);
|
|
(void)sp_3072_sub_56(z1, z1, z2);
|
|
(void)sp_3072_sub_56(z1, z1, z0);
|
|
(void)sp_3072_add_56(r + 28, r + 28, z1);
|
|
sp_3072_norm_112(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_sqr_112(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[112];
|
|
sp_digit* a1 = z1;
|
|
sp_digit* z2 = r + 112;
|
|
(void)sp_3072_add_56(a1, a, &a[56]);
|
|
sp_3072_norm_56(a1);
|
|
sp_3072_sqr_56(z2, &a[56]);
|
|
sp_3072_sqr_56(z0, a);
|
|
sp_3072_sqr_56(z1, a1);
|
|
(void)sp_3072_sub_112(z1, z1, z2);
|
|
(void)sp_3072_sub_112(z1, z1, z0);
|
|
(void)sp_3072_add_112(r + 56, r + 56, z1);
|
|
sp_3072_norm_224(r);
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
/* Caclulate the bottom digit of -1/a mod 2^n.
|
|
*
|
|
* a A single precision number.
|
|
* rho Bottom word of inverse.
|
|
*/
|
|
static void sp_3072_mont_setup(const sp_digit* a, sp_digit* rho)
|
|
{
|
|
sp_digit x;
|
|
sp_digit b;
|
|
|
|
b = a[0];
|
|
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**8 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**16 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
|
|
x &= 0xfffffff;
|
|
|
|
/* rho = -1/m mod b */
|
|
*rho = ((sp_digit)1 << 28) - x;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_d_112(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 112; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[112] = (sp_digit)(t & 0xfffffff);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 3072 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_3072_mont_norm_56(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i = 0; i < 48; i += 8) {
|
|
r[i + 0] = 0xfffffff;
|
|
r[i + 1] = 0xfffffff;
|
|
r[i + 2] = 0xfffffff;
|
|
r[i + 3] = 0xfffffff;
|
|
r[i + 4] = 0xfffffff;
|
|
r[i + 5] = 0xfffffff;
|
|
r[i + 6] = 0xfffffff;
|
|
r[i + 7] = 0xfffffff;
|
|
}
|
|
r[48] = 0xfffffff;
|
|
r[49] = 0xfffffff;
|
|
r[50] = 0xfffffff;
|
|
r[51] = 0xfffffff;
|
|
r[52] = 0xfffffff;
|
|
r[53] = 0xfffffff;
|
|
r[54] = 0xffffffL;
|
|
r[55] = 0;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_3072_sub_56(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_3072_cmp_56(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
for (i = 48; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 27);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_sub_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 56; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_add_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 56; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0xfffffff;
|
|
t >>= 28;
|
|
}
|
|
r[56] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 48; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0xfffffff;
|
|
t[1] += t[0] >> 28;
|
|
r[i+1] = t[1] & 0xfffffff;
|
|
t[2] += t[1] >> 28;
|
|
r[i+2] = t[2] & 0xfffffff;
|
|
t[3] += t[2] >> 28;
|
|
r[i+3] = t[3] & 0xfffffff;
|
|
t[4] += t[3] >> 28;
|
|
r[i+4] = t[4] & 0xfffffff;
|
|
t[5] += t[4] >> 28;
|
|
r[i+5] = t[5] & 0xfffffff;
|
|
t[6] += t[5] >> 28;
|
|
r[i+6] = t[6] & 0xfffffff;
|
|
t[7] += t[6] >> 28;
|
|
r[i+7] = t[7] & 0xfffffff;
|
|
t[0] = t[7] >> 28;
|
|
}
|
|
t[0] += (tb * a[48]) + r[48];
|
|
t[1] = (tb * a[49]) + r[49];
|
|
t[2] = (tb * a[50]) + r[50];
|
|
t[3] = (tb * a[51]) + r[51];
|
|
t[4] = (tb * a[52]) + r[52];
|
|
t[5] = (tb * a[53]) + r[53];
|
|
t[6] = (tb * a[54]) + r[54];
|
|
t[7] = (tb * a[55]) + r[55];
|
|
r[48] = t[0] & 0xfffffff;
|
|
t[1] += t[0] >> 28;
|
|
r[49] = t[1] & 0xfffffff;
|
|
t[2] += t[1] >> 28;
|
|
r[50] = t[2] & 0xfffffff;
|
|
t[3] += t[2] >> 28;
|
|
r[51] = t[3] & 0xfffffff;
|
|
t[4] += t[3] >> 28;
|
|
r[52] = t[4] & 0xfffffff;
|
|
t[5] += t[4] >> 28;
|
|
r[53] = t[5] & 0xfffffff;
|
|
t[6] += t[5] >> 28;
|
|
r[54] = t[6] & 0xfffffff;
|
|
t[7] += t[6] >> 28;
|
|
r[55] = t[7] & 0xfffffff;
|
|
r[56] += (sp_digit)(t[7] >> 28);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 1536 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_3072_mont_shift_56(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[54] >> 24;
|
|
n += ((sp_int64)a[55]) << 4;
|
|
for (i = 0; i < 48; i += 8) {
|
|
r[i + 0] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 56]) << 4;
|
|
r[i + 1] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 57]) << 4;
|
|
r[i + 2] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 58]) << 4;
|
|
r[i + 3] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 59]) << 4;
|
|
r[i + 4] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 60]) << 4;
|
|
r[i + 5] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 61]) << 4;
|
|
r[i + 6] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 62]) << 4;
|
|
r[i + 7] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 63]) << 4;
|
|
}
|
|
r[48] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[104]) << 4;
|
|
r[49] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[105]) << 4;
|
|
r[50] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[106]) << 4;
|
|
r[51] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[107]) << 4;
|
|
r[52] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[108]) << 4;
|
|
r[53] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[109]) << 4;
|
|
r[54] = (sp_digit)n;
|
|
XMEMSET(&r[55], 0, sizeof(*r) * 55U);
|
|
}
|
|
|
|
/* Reduce the number back to 3072 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_3072_mont_reduce_56(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_3072_norm_56(a + 55);
|
|
|
|
for (i=0; i<54; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff;
|
|
sp_3072_mul_add_56(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xffffffL;
|
|
sp_3072_mul_add_56(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
a[i] &= 0xfffffff;
|
|
sp_3072_mont_shift_56(a, a);
|
|
over = a[54] - m[54];
|
|
sp_3072_cond_sub_56(a, a, m, ~((over - 1) >> 31));
|
|
sp_3072_norm_56(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_mul_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_mul_56(r, a, b);
|
|
sp_3072_mont_reduce_56(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_sqr_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_sqr_56(r, a);
|
|
sp_3072_mont_reduce_56(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_d_56(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 56; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[56] = (sp_digit)(t & 0xfffffff);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_add_56(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 56; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_3072_rshift_56(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<48; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (28 - n)) & 0xfffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (28 - n)) & 0xfffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (28 - n)) & 0xfffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (28 - n)) & 0xfffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (28 - n)) & 0xfffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (28 - n)) & 0xfffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (28 - n)) & 0xfffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (28 - n)) & 0xfffffff);
|
|
}
|
|
r[48] = (a[48] >> n) | ((a[49] << (28 - n)) & 0xfffffff);
|
|
r[49] = (a[49] >> n) | ((a[50] << (28 - n)) & 0xfffffff);
|
|
r[50] = (a[50] >> n) | ((a[51] << (28 - n)) & 0xfffffff);
|
|
r[51] = (a[51] >> n) | ((a[52] << (28 - n)) & 0xfffffff);
|
|
r[52] = (a[52] >> n) | ((a[53] << (28 - n)) & 0xfffffff);
|
|
r[53] = (a[53] >> n) | ((a[54] << (28 - n)) & 0xfffffff);
|
|
r[54] = (a[54] >> n) | ((a[55] << (28 - n)) & 0xfffffff);
|
|
r[55] = a[55] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_3072_div_word_56(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 28);
|
|
sp_digit t0 = (sp_digit)(d & 0xfffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 26; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 27) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 28);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 56) - (sp_digit)(d >> 56);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 13) + 1;
|
|
|
|
t = (sp_digit)(d >> 26);
|
|
t = (t / dv) << 13;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 11);
|
|
t = t / (dv << 2);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_3072_word_div_word_56(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_div_56(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 56 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 56 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 112 + 1;
|
|
sd = t2 + 56 + 1;
|
|
|
|
sp_3072_mul_d_56(sd, d, (sp_digit)1 << 4);
|
|
sp_3072_mul_d_112(t1, a, (sp_digit)1 << 4);
|
|
dv = sd[54];
|
|
t1[55 + 55] += t1[55 + 55 - 1] >> 28;
|
|
t1[55 + 55 - 1] &= 0xfffffff;
|
|
for (i=55; i>=0; i--) {
|
|
r1 = sp_3072_div_word_56(t1[55 + i], t1[55 + i - 1], dv);
|
|
|
|
sp_3072_mul_d_56(t2, sd, r1);
|
|
(void)sp_3072_sub_56(&t1[i], &t1[i], t2);
|
|
sp_3072_norm_55(&t1[i]);
|
|
t1[55 + i] += t1[55 + i - 1] >> 28;
|
|
t1[55 + i - 1] &= 0xfffffff;
|
|
r1 = sp_3072_div_word_56(-t1[55 + i], -t1[55 + i - 1], dv);
|
|
r1 -= t1[55 + i];
|
|
sp_3072_mul_d_56(t2, sd, r1);
|
|
(void)sp_3072_add_56(&t1[i], &t1[i], t2);
|
|
t1[55 + i] += t1[55 + i - 1] >> 28;
|
|
t1[55 + i - 1] &= 0xfffffff;
|
|
}
|
|
t1[55 - 1] += t1[55 - 2] >> 28;
|
|
t1[55 - 2] &= 0xfffffff;
|
|
r1 = sp_3072_word_div_word_56(t1[55 - 1], dv);
|
|
|
|
sp_3072_mul_d_56(t2, sd, r1);
|
|
sp_3072_sub_56(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 112U);
|
|
for (i=0; i<54; i++) {
|
|
r[i+1] += r[i] >> 28;
|
|
r[i] &= 0xfffffff;
|
|
}
|
|
sp_3072_cond_add_56(r, r, sd, r[54] >> 31);
|
|
|
|
sp_3072_norm_55(r);
|
|
sp_3072_rshift_56(r, r, 4);
|
|
r[55] = 0;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_mod_56(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_3072_div_56(a, m, NULL, r);
|
|
}
|
|
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_3072_mod_exp_56(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 112];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 56 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 56 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 56U * 2U);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_56(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_56(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 56U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_56(t[1], t[1], norm);
|
|
err = sp_3072_mod_56(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 28;
|
|
c = bits % 28;
|
|
n = e[i--] << (28 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 28;
|
|
}
|
|
|
|
y = (int)((n >> 27) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_56(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 56 * 2);
|
|
sp_3072_mont_sqr_56(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 56 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_56(t[0], m, mp);
|
|
n = sp_3072_cmp_56(t[0], m);
|
|
sp_3072_cond_sub_56(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 56 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 112];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 56 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 56 * 2);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_56(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_56(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_56(t[1], t[1], norm);
|
|
err = sp_3072_mod_56(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_56(t[1], a, norm);
|
|
err = sp_3072_mod_56(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 28;
|
|
c = bits % 28;
|
|
n = e[i--] << (28 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 28;
|
|
}
|
|
|
|
y = (int)((n >> 27) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_56(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 56 * 2);
|
|
sp_3072_mont_sqr_56(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 56 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_56(t[0], m, mp);
|
|
n = sp_3072_cmp_56(t[0], m);
|
|
sp_3072_cond_sub_56(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 56 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(32 * 112) + 112];
|
|
#endif
|
|
sp_digit* t[32];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 112) + 112), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<32; i++)
|
|
t[i] = td + i * 112;
|
|
rt = td + 3584;
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_56(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_56(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_56(t[1], t[1], norm);
|
|
err = sp_3072_mod_56(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_56(t[1], a, norm);
|
|
err = sp_3072_mod_56(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mont_sqr_56(t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_mul_56(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_sqr_56(t[ 4], t[ 2], m, mp);
|
|
sp_3072_mont_mul_56(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_3072_mont_sqr_56(t[ 6], t[ 3], m, mp);
|
|
sp_3072_mont_mul_56(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_3072_mont_sqr_56(t[ 8], t[ 4], m, mp);
|
|
sp_3072_mont_mul_56(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_3072_mont_sqr_56(t[10], t[ 5], m, mp);
|
|
sp_3072_mont_mul_56(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_3072_mont_sqr_56(t[12], t[ 6], m, mp);
|
|
sp_3072_mont_mul_56(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_3072_mont_sqr_56(t[14], t[ 7], m, mp);
|
|
sp_3072_mont_mul_56(t[15], t[ 8], t[ 7], m, mp);
|
|
sp_3072_mont_sqr_56(t[16], t[ 8], m, mp);
|
|
sp_3072_mont_mul_56(t[17], t[ 9], t[ 8], m, mp);
|
|
sp_3072_mont_sqr_56(t[18], t[ 9], m, mp);
|
|
sp_3072_mont_mul_56(t[19], t[10], t[ 9], m, mp);
|
|
sp_3072_mont_sqr_56(t[20], t[10], m, mp);
|
|
sp_3072_mont_mul_56(t[21], t[11], t[10], m, mp);
|
|
sp_3072_mont_sqr_56(t[22], t[11], m, mp);
|
|
sp_3072_mont_mul_56(t[23], t[12], t[11], m, mp);
|
|
sp_3072_mont_sqr_56(t[24], t[12], m, mp);
|
|
sp_3072_mont_mul_56(t[25], t[13], t[12], m, mp);
|
|
sp_3072_mont_sqr_56(t[26], t[13], m, mp);
|
|
sp_3072_mont_mul_56(t[27], t[14], t[13], m, mp);
|
|
sp_3072_mont_sqr_56(t[28], t[14], m, mp);
|
|
sp_3072_mont_mul_56(t[29], t[15], t[14], m, mp);
|
|
sp_3072_mont_sqr_56(t[30], t[15], m, mp);
|
|
sp_3072_mont_mul_56(t[31], t[16], t[15], m, mp);
|
|
|
|
bits = ((bits + 4) / 5) * 5;
|
|
i = ((bits + 27) / 28) - 1;
|
|
c = bits % 28;
|
|
if (c == 0) {
|
|
c = 28;
|
|
}
|
|
if (i < 56) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 5) {
|
|
n |= e[i--] << (4 - c);
|
|
c += 28;
|
|
}
|
|
y = (int)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 112);
|
|
while ((i >= 0) || (c >= 5)) {
|
|
if (c >= 5) {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 4;
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c = 23;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n = e[i--] << 4;
|
|
c = 5 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 28 - c;
|
|
}
|
|
|
|
sp_3072_mont_sqr_56(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_56(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_56(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_56(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_56(rt, rt, m, mp);
|
|
|
|
sp_3072_mont_mul_56(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_3072_mont_reduce_56(rt, m, mp);
|
|
n = sp_3072_cmp_56(rt, m);
|
|
sp_3072_cond_sub_56(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 112);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) | WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 3072 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_3072_mont_norm_112(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i = 0; i < 104; i += 8) {
|
|
r[i + 0] = 0xfffffff;
|
|
r[i + 1] = 0xfffffff;
|
|
r[i + 2] = 0xfffffff;
|
|
r[i + 3] = 0xfffffff;
|
|
r[i + 4] = 0xfffffff;
|
|
r[i + 5] = 0xfffffff;
|
|
r[i + 6] = 0xfffffff;
|
|
r[i + 7] = 0xfffffff;
|
|
}
|
|
r[104] = 0xfffffff;
|
|
r[105] = 0xfffffff;
|
|
r[106] = 0xfffffff;
|
|
r[107] = 0xfffffff;
|
|
r[108] = 0xfffffff;
|
|
r[109] = 0xfffffL;
|
|
r[110] = 0;
|
|
r[111] = 0;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_3072_sub_112(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_3072_cmp_112(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
for (i = 104; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 27);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 27);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_sub_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 112; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_add_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 112; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0xfffffff;
|
|
t >>= 28;
|
|
}
|
|
r[112] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 104; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0xfffffff;
|
|
t[1] += t[0] >> 28;
|
|
r[i+1] = t[1] & 0xfffffff;
|
|
t[2] += t[1] >> 28;
|
|
r[i+2] = t[2] & 0xfffffff;
|
|
t[3] += t[2] >> 28;
|
|
r[i+3] = t[3] & 0xfffffff;
|
|
t[4] += t[3] >> 28;
|
|
r[i+4] = t[4] & 0xfffffff;
|
|
t[5] += t[4] >> 28;
|
|
r[i+5] = t[5] & 0xfffffff;
|
|
t[6] += t[5] >> 28;
|
|
r[i+6] = t[6] & 0xfffffff;
|
|
t[7] += t[6] >> 28;
|
|
r[i+7] = t[7] & 0xfffffff;
|
|
t[0] = t[7] >> 28;
|
|
}
|
|
t[0] += (tb * a[104]) + r[104];
|
|
t[1] = (tb * a[105]) + r[105];
|
|
t[2] = (tb * a[106]) + r[106];
|
|
t[3] = (tb * a[107]) + r[107];
|
|
t[4] = (tb * a[108]) + r[108];
|
|
t[5] = (tb * a[109]) + r[109];
|
|
t[6] = (tb * a[110]) + r[110];
|
|
t[7] = (tb * a[111]) + r[111];
|
|
r[104] = t[0] & 0xfffffff;
|
|
t[1] += t[0] >> 28;
|
|
r[105] = t[1] & 0xfffffff;
|
|
t[2] += t[1] >> 28;
|
|
r[106] = t[2] & 0xfffffff;
|
|
t[3] += t[2] >> 28;
|
|
r[107] = t[3] & 0xfffffff;
|
|
t[4] += t[3] >> 28;
|
|
r[108] = t[4] & 0xfffffff;
|
|
t[5] += t[4] >> 28;
|
|
r[109] = t[5] & 0xfffffff;
|
|
t[6] += t[5] >> 28;
|
|
r[110] = t[6] & 0xfffffff;
|
|
t[7] += t[6] >> 28;
|
|
r[111] = t[7] & 0xfffffff;
|
|
r[112] += (sp_digit)(t[7] >> 28);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 3072 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_3072_mont_shift_112(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[109] >> 20;
|
|
n += ((sp_int64)a[110]) << 8;
|
|
for (i = 0; i < 104; i += 8) {
|
|
r[i + 0] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 111]) << 8;
|
|
r[i + 1] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 112]) << 8;
|
|
r[i + 2] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 113]) << 8;
|
|
r[i + 3] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 114]) << 8;
|
|
r[i + 4] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 115]) << 8;
|
|
r[i + 5] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 116]) << 8;
|
|
r[i + 6] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 117]) << 8;
|
|
r[i + 7] = n & 0xfffffff;
|
|
n >>= 28; n += ((sp_int64)a[i + 118]) << 8;
|
|
}
|
|
r[104] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[215]) << 8;
|
|
r[105] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[216]) << 8;
|
|
r[106] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[217]) << 8;
|
|
r[107] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[218]) << 8;
|
|
r[108] = n & 0xfffffff; n >>= 28; n += ((sp_int64)a[219]) << 8;
|
|
r[109] = (sp_digit)n;
|
|
XMEMSET(&r[110], 0, sizeof(*r) * 110U);
|
|
}
|
|
|
|
/* Reduce the number back to 3072 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_3072_mont_reduce_112(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_3072_norm_112(a + 110);
|
|
|
|
#ifdef WOLFSSL_SP_DH
|
|
if (mp != 1) {
|
|
for (i=0; i<109; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff;
|
|
sp_3072_mul_add_112(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
|
|
sp_3072_mul_add_112(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
a[i] &= 0xfffffff;
|
|
}
|
|
else {
|
|
for (i=0; i<109; i++) {
|
|
mu = a[i] & 0xfffffff;
|
|
sp_3072_mul_add_112(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
}
|
|
mu = a[i] & 0xfffffL;
|
|
sp_3072_mul_add_112(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
a[i] &= 0xfffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<109; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffff;
|
|
sp_3072_mul_add_112(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
|
|
sp_3072_mul_add_112(a+i, m, mu);
|
|
a[i+1] += a[i] >> 28;
|
|
a[i] &= 0xfffffff;
|
|
#endif
|
|
sp_3072_mont_shift_112(a, a);
|
|
over = a[109] - m[109];
|
|
sp_3072_cond_sub_112(a, a, m, ~((over - 1) >> 31));
|
|
sp_3072_norm_112(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_mul_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_mul_112(r, a, b);
|
|
sp_3072_mont_reduce_112(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mont_sqr_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_3072_sqr_112(r, a);
|
|
sp_3072_mont_reduce_112(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_3072_mul_d_224(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 224; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0xfffffff);
|
|
t >>= 28;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[224] = (sp_digit)(t & 0xfffffff);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_3072_cond_add_112(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 112; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_3072_rshift_112(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<104; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (28 - n)) & 0xfffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (28 - n)) & 0xfffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (28 - n)) & 0xfffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (28 - n)) & 0xfffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (28 - n)) & 0xfffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (28 - n)) & 0xfffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (28 - n)) & 0xfffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (28 - n)) & 0xfffffff);
|
|
}
|
|
r[104] = (a[104] >> n) | ((a[105] << (28 - n)) & 0xfffffff);
|
|
r[105] = (a[105] >> n) | ((a[106] << (28 - n)) & 0xfffffff);
|
|
r[106] = (a[106] >> n) | ((a[107] << (28 - n)) & 0xfffffff);
|
|
r[107] = (a[107] >> n) | ((a[108] << (28 - n)) & 0xfffffff);
|
|
r[108] = (a[108] >> n) | ((a[109] << (28 - n)) & 0xfffffff);
|
|
r[109] = (a[109] >> n) | ((a[110] << (28 - n)) & 0xfffffff);
|
|
r[110] = (a[110] >> n) | ((a[111] << (28 - n)) & 0xfffffff);
|
|
r[111] = a[111] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_3072_div_word_112(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 28);
|
|
sp_digit t0 = (sp_digit)(d & 0xfffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 26; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 27) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 28);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 56) - (sp_digit)(d >> 56);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 28) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 13) + 1;
|
|
|
|
t = (sp_digit)(d >> 26);
|
|
t = (t / dv) << 13;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 11);
|
|
t = t / (dv << 2);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_3072_word_div_word_112(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_div_112(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 112 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 112 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 224 + 1;
|
|
sd = t2 + 112 + 1;
|
|
|
|
sp_3072_mul_d_112(sd, d, (sp_digit)1 << 8);
|
|
sp_3072_mul_d_224(t1, a, (sp_digit)1 << 8);
|
|
dv = sd[109];
|
|
t1[110 + 110] += t1[110 + 110 - 1] >> 28;
|
|
t1[110 + 110 - 1] &= 0xfffffff;
|
|
for (i=110; i>=0; i--) {
|
|
r1 = sp_3072_div_word_112(t1[110 + i], t1[110 + i - 1], dv);
|
|
|
|
sp_3072_mul_d_112(t2, sd, r1);
|
|
(void)sp_3072_sub_112(&t1[i], &t1[i], t2);
|
|
sp_3072_norm_110(&t1[i]);
|
|
t1[110 + i] += t1[110 + i - 1] >> 28;
|
|
t1[110 + i - 1] &= 0xfffffff;
|
|
r1 = sp_3072_div_word_112(-t1[110 + i], -t1[110 + i - 1], dv);
|
|
r1 -= t1[110 + i];
|
|
sp_3072_mul_d_112(t2, sd, r1);
|
|
(void)sp_3072_add_112(&t1[i], &t1[i], t2);
|
|
t1[110 + i] += t1[110 + i - 1] >> 28;
|
|
t1[110 + i - 1] &= 0xfffffff;
|
|
}
|
|
t1[110 - 1] += t1[110 - 2] >> 28;
|
|
t1[110 - 2] &= 0xfffffff;
|
|
r1 = sp_3072_word_div_word_112(t1[110 - 1], dv);
|
|
|
|
sp_3072_mul_d_112(t2, sd, r1);
|
|
sp_3072_sub_112(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 224U);
|
|
for (i=0; i<109; i++) {
|
|
r[i+1] += r[i] >> 28;
|
|
r[i] &= 0xfffffff;
|
|
}
|
|
sp_3072_cond_add_112(r, r, sd, r[109] >> 31);
|
|
|
|
sp_3072_norm_110(r);
|
|
sp_3072_rshift_112(r, r, 8);
|
|
r[110] = 0;
|
|
r[111] = 0;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_3072_mod_112(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_3072_div_112(a, m, NULL, r);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
|
|
defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_3072_mod_exp_112(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 224];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 112 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 112 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 112U * 2U);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_112(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_112(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 112U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_112(t[1], t[1], norm);
|
|
err = sp_3072_mod_112(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 28;
|
|
c = bits % 28;
|
|
n = e[i--] << (28 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 28;
|
|
}
|
|
|
|
y = (int)((n >> 27) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_112(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 112 * 2);
|
|
sp_3072_mont_sqr_112(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 112 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_112(t[0], m, mp);
|
|
n = sp_3072_cmp_112(t[0], m);
|
|
sp_3072_cond_sub_112(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 112 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 224];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 112 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 112 * 2);
|
|
}
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_112(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_112(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_112(t[1], t[1], norm);
|
|
err = sp_3072_mod_112(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_112(t[1], a, norm);
|
|
err = sp_3072_mod_112(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 28;
|
|
c = bits % 28;
|
|
n = e[i--] << (28 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 28;
|
|
}
|
|
|
|
y = (int)((n >> 27) & 1);
|
|
n <<= 1;
|
|
|
|
sp_3072_mont_mul_112(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 112 * 2);
|
|
sp_3072_mont_sqr_112(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 112 * 2);
|
|
}
|
|
|
|
sp_3072_mont_reduce_112(t[0], m, mp);
|
|
n = sp_3072_cmp_112(t[0], m);
|
|
sp_3072_cond_sub_112(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 112 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(16 * 224) + 224];
|
|
#endif
|
|
sp_digit* t[16];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 224) + 224), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<16; i++)
|
|
t[i] = td + i * 224;
|
|
rt = td + 3584;
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_112(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_3072_mod_112(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_112(t[1], t[1], norm);
|
|
err = sp_3072_mod_112(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_3072_mul_112(t[1], a, norm);
|
|
err = sp_3072_mod_112(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mont_sqr_112(t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_mul_112(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_3072_mont_sqr_112(t[ 4], t[ 2], m, mp);
|
|
sp_3072_mont_mul_112(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_3072_mont_sqr_112(t[ 6], t[ 3], m, mp);
|
|
sp_3072_mont_mul_112(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_3072_mont_sqr_112(t[ 8], t[ 4], m, mp);
|
|
sp_3072_mont_mul_112(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_3072_mont_sqr_112(t[10], t[ 5], m, mp);
|
|
sp_3072_mont_mul_112(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_3072_mont_sqr_112(t[12], t[ 6], m, mp);
|
|
sp_3072_mont_mul_112(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_3072_mont_sqr_112(t[14], t[ 7], m, mp);
|
|
sp_3072_mont_mul_112(t[15], t[ 8], t[ 7], m, mp);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 27) / 28) - 1;
|
|
c = bits % 28;
|
|
if (c == 0) {
|
|
c = 28;
|
|
}
|
|
if (i < 112) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (4 - c);
|
|
c += 28;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 224);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 4;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 24;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 4;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 28 - c;
|
|
}
|
|
|
|
sp_3072_mont_sqr_112(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_112(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_112(rt, rt, m, mp);
|
|
sp_3072_mont_sqr_112(rt, rt, m, mp);
|
|
|
|
sp_3072_mont_mul_112(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_3072_mont_reduce_112(rt, m, mp);
|
|
n = sp_3072_cmp_112(rt, m);
|
|
sp_3072_cond_sub_112(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 224);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
|
|
/* WOLFSSL_HAVE_SP_DH */
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
#ifdef WOLFSSL_HAVE_SP_RSA
|
|
/* RSA public key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* em Public exponent.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 384 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPublic_3072(const byte* in, word32 inLen, const mp_int* em,
|
|
const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[112 * 5];
|
|
#endif
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit e[1] = {0};
|
|
sp_digit mp = 0;
|
|
int i;
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 28) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
r = a + 112 * 2;
|
|
m = r + 112 * 2;
|
|
norm = r;
|
|
|
|
sp_3072_from_bin(a, 112, in, inLen);
|
|
#if DIGIT_BIT >= 28
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(m, 112, mm);
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_112(norm, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_112(a, a, norm);
|
|
err = sp_3072_mod_112(a, a, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
for (i=27; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 112 * 2);
|
|
for (i--; i>=0; i--) {
|
|
sp_3072_mont_sqr_112(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_3072_mont_mul_112(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_3072_mont_reduce_112(r, m, mp);
|
|
mp = sp_3072_cmp_112(r, m);
|
|
sp_3072_cond_sub_112(r, r, m, ~(mp >> 31));
|
|
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[112 * 5];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit e[1] = {0};
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 28) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d;
|
|
r = a + 112 * 2;
|
|
m = r + 112 * 2;
|
|
|
|
sp_3072_from_bin(a, 112, in, inLen);
|
|
#if DIGIT_BIT >= 28
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(m, 112, mm);
|
|
|
|
if (e[0] == 0x3) {
|
|
sp_3072_sqr_112(r, a);
|
|
err = sp_3072_mod_112(r, r, m);
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_112(r, a, r);
|
|
err = sp_3072_mod_112(r, r, m);
|
|
}
|
|
}
|
|
else {
|
|
sp_digit* norm = r;
|
|
int i;
|
|
sp_digit mp;
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_112(norm, m);
|
|
|
|
sp_3072_mul_112(a, a, norm);
|
|
err = sp_3072_mod_112(a, a, m);
|
|
|
|
if (err == MP_OKAY) {
|
|
for (i=27; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 224U);
|
|
for (i--; i>=0; i--) {
|
|
sp_3072_mont_sqr_112(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_3072_mont_mul_112(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_3072_mont_reduce_112(r, m, mp);
|
|
mp = sp_3072_cmp_112(r, m);
|
|
sp_3072_cond_sub_112(r, r, m, ~(mp >> 31));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
|
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
|
|
#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
|
|
/* RSA private key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* dm Private exponent.
|
|
* pm First prime.
|
|
* qm Second prime.
|
|
* dpm First prime's CRT exponent.
|
|
* dqm Second prime's CRT exponent.
|
|
* qim Inverse of second prime mod p.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 384 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPrivate_3072(const byte* in, word32 inLen, const mp_int* dm,
|
|
const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
|
|
const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[112 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 112;
|
|
m = a + 224;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 112, in, inLen);
|
|
sp_3072_from_mp(d, 112, dm);
|
|
sp_3072_from_mp(m, 112, mm);
|
|
err = sp_3072_mod_exp_112(r, a, d, 3072, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 112);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[112 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 112;
|
|
m = a + 224;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 112, in, inLen);
|
|
sp_3072_from_mp(d, 112, dm);
|
|
sp_3072_from_mp(m, 112, mm);
|
|
err = sp_3072_mod_exp_112(r, a, d, 3072, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 112);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#else
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[56 * 8];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 384) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 8, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
p = a + 112;
|
|
qi = dq = dp = p + 56;
|
|
tmpa = qi + 56;
|
|
tmpb = tmpa + 112;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 112, in, inLen);
|
|
sp_3072_from_mp(p, 56, pm);
|
|
sp_3072_from_mp(dp, 56, dpm);
|
|
err = sp_3072_mod_exp_56(tmpa, a, dp, 1536, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(p, 56, qm);
|
|
sp_3072_from_mp(dq, 56, dqm);
|
|
err = sp_3072_mod_exp_56(tmpb, a, dq, 1536, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(p, 56, pm);
|
|
(void)sp_3072_sub_56(tmpa, tmpa, tmpb);
|
|
sp_3072_norm_55(tmpa);
|
|
sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
|
|
sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
|
|
sp_3072_norm_56(tmpa);
|
|
|
|
sp_3072_from_mp(qi, 56, qim);
|
|
sp_3072_mul_56(tmpa, tmpa, qi);
|
|
err = sp_3072_mod_56(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_from_mp(p, 56, qm);
|
|
sp_3072_mul_56(tmpa, p, tmpa);
|
|
(void)sp_3072_add_112(r, tmpb, tmpa);
|
|
sp_3072_norm_112(r);
|
|
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 56 * 8);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[56 * 13];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* q = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 384U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 13, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = a + 112 * 2;
|
|
q = p + 56;
|
|
dp = q + 56;
|
|
dq = dp + 56;
|
|
qi = dq + 56;
|
|
tmpa = qi + 56;
|
|
tmpb = tmpa + 112;
|
|
r = a;
|
|
|
|
sp_3072_from_bin(a, 112, in, inLen);
|
|
sp_3072_from_mp(p, 56, pm);
|
|
sp_3072_from_mp(q, 56, qm);
|
|
sp_3072_from_mp(dp, 56, dpm);
|
|
sp_3072_from_mp(dq, 56, dqm);
|
|
sp_3072_from_mp(qi, 56, qim);
|
|
|
|
err = sp_3072_mod_exp_56(tmpa, a, dp, 1536, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_3072_mod_exp_56(tmpb, a, dq, 1536, q, 1);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
(void)sp_3072_sub_56(tmpa, tmpa, tmpb);
|
|
sp_3072_norm_55(tmpa);
|
|
sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
|
|
sp_3072_cond_add_56(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[54] >> 31));
|
|
sp_3072_norm_56(tmpa);
|
|
sp_3072_mul_56(tmpa, tmpa, qi);
|
|
err = sp_3072_mod_56(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_mul_56(tmpa, tmpa, q);
|
|
(void)sp_3072_add_112(r, tmpb, tmpa);
|
|
sp_3072_norm_112(r);
|
|
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 56 * 13);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
|
|
}
|
|
|
|
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
#endif /* WOLFSSL_HAVE_SP_RSA */
|
|
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
|
|
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_3072_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 28
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 110);
|
|
r->used = 110;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 28
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 110; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 28) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 28 - s;
|
|
}
|
|
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 110; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 28 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 28 - s;
|
|
}
|
|
else {
|
|
s += 28;
|
|
}
|
|
}
|
|
r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_3072(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[112 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 112 * 2;
|
|
m = e + 112;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 112, base);
|
|
sp_3072_from_mp(e, 112, exp);
|
|
sp_3072_from_mp(m, 112, mod);
|
|
|
|
err = sp_3072_mod_exp_112(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 112U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[112 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 112 * 2;
|
|
m = e + 112;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 112, base);
|
|
sp_3072_from_mp(e, 112, exp);
|
|
sp_3072_from_mp(m, 112, mod);
|
|
|
|
err = sp_3072_mod_exp_112(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 112U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#ifdef WOLFSSL_HAVE_SP_DH
|
|
|
|
#ifdef HAVE_FFDHE_3072
|
|
SP_NOINLINE static void sp_3072_lshift_112(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
sp_int_digit s;
|
|
sp_int_digit t;
|
|
|
|
s = (sp_int_digit)a[111];
|
|
r[112] = s >> (28U - n);
|
|
s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]);
|
|
r[111] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]);
|
|
r[110] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]);
|
|
r[109] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]);
|
|
r[108] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]);
|
|
r[107] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]);
|
|
r[106] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]);
|
|
r[105] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]);
|
|
r[104] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]);
|
|
r[103] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]);
|
|
r[102] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]);
|
|
r[101] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]);
|
|
r[100] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]);
|
|
r[99] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]);
|
|
r[98] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]);
|
|
r[97] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]);
|
|
r[96] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]);
|
|
r[95] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]);
|
|
r[94] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]);
|
|
r[93] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]);
|
|
r[92] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]);
|
|
r[91] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]);
|
|
r[90] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]);
|
|
r[89] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]);
|
|
r[88] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]);
|
|
r[87] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]);
|
|
r[86] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]);
|
|
r[85] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]);
|
|
r[84] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]);
|
|
r[83] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]);
|
|
r[82] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]);
|
|
r[81] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]);
|
|
r[80] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]);
|
|
r[79] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]);
|
|
r[78] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]);
|
|
r[77] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]);
|
|
r[76] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]);
|
|
r[75] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]);
|
|
r[74] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]);
|
|
r[73] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]);
|
|
r[72] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]);
|
|
r[71] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]);
|
|
r[70] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]);
|
|
r[69] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]);
|
|
r[68] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]);
|
|
r[67] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]);
|
|
r[66] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]);
|
|
r[65] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]);
|
|
r[64] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]);
|
|
r[63] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]);
|
|
r[62] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]);
|
|
r[61] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]);
|
|
r[60] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]);
|
|
r[59] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]);
|
|
r[58] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]);
|
|
r[57] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]);
|
|
r[56] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]);
|
|
r[55] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]);
|
|
r[54] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]);
|
|
r[53] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]);
|
|
r[52] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]);
|
|
r[51] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]);
|
|
r[50] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]);
|
|
r[49] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]);
|
|
r[48] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]);
|
|
r[47] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]);
|
|
r[46] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]);
|
|
r[45] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]);
|
|
r[44] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]);
|
|
r[43] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]);
|
|
r[42] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
|
|
r[41] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
|
|
r[40] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
|
|
r[39] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
|
|
r[38] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
|
|
r[37] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
|
|
r[36] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
|
|
r[35] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
|
|
r[34] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
|
|
r[33] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
|
|
r[32] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
|
|
r[31] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
|
|
r[30] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
|
|
r[29] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
|
|
r[28] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
|
|
r[27] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
|
|
r[26] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
|
|
r[25] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
|
|
r[24] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
|
|
r[23] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
|
|
r[22] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
|
|
r[21] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
|
|
r[20] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
|
|
r[19] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
|
|
r[18] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
|
|
r[17] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
|
|
r[16] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
|
|
r[15] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
|
|
r[14] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
|
|
r[13] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
|
|
r[12] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
|
|
r[11] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
|
|
r[10] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
|
|
r[9] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
|
|
r[8] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
|
|
r[7] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
|
|
r[6] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
|
|
r[5] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
|
|
r[4] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
|
|
r[3] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
|
|
r[2] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
|
|
r[1] = ((s << n) | (t >> (28U - n))) & 0xfffffff;
|
|
r[0] = (a[0] << n) & 0xfffffff;
|
|
}
|
|
|
|
/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even.
|
|
*/
|
|
static int sp_3072_mod_exp_2_112(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[337];
|
|
#endif
|
|
sp_digit* norm = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
sp_digit o;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 337, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
tmp = td + 224;
|
|
XMEMSET(td, 0, sizeof(sp_digit) * 337);
|
|
|
|
sp_3072_mont_setup(m, &mp);
|
|
sp_3072_mont_norm_112(norm, m);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 27) / 28) - 1;
|
|
c = bits % 28;
|
|
if (c == 0) {
|
|
c = 28;
|
|
}
|
|
if (i < 112) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (4 - c);
|
|
c += 28;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
sp_3072_lshift_112(r, norm, (byte)y);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 4;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 24;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 4;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 28 - c;
|
|
}
|
|
|
|
sp_3072_mont_sqr_112(r, r, m, mp);
|
|
sp_3072_mont_sqr_112(r, r, m, mp);
|
|
sp_3072_mont_sqr_112(r, r, m, mp);
|
|
sp_3072_mont_sqr_112(r, r, m, mp);
|
|
|
|
sp_3072_lshift_112(r, r, (byte)y);
|
|
sp_3072_mul_d_112(tmp, norm, (r[110] << 8) + (r[109] >> 20));
|
|
r[110] = 0;
|
|
r[109] &= 0xfffffL;
|
|
(void)sp_3072_add_112(r, r, tmp);
|
|
sp_3072_norm_112(r);
|
|
o = sp_3072_cmp_112(r, m);
|
|
sp_3072_cond_sub_112(r, r, m, ~(o >> 31));
|
|
}
|
|
|
|
sp_3072_mont_reduce_112(r, m, mp);
|
|
n = sp_3072_cmp_112(r, m);
|
|
sp_3072_cond_sub_112(r, r, m, ~(n >> 31));
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* HAVE_FFDHE_3072 */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base.
|
|
* exp Array of bytes that is the exponent.
|
|
* expLen Length of data, in bytes, in exponent.
|
|
* mod Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 384 bytes long.
|
|
* outLen Length, in bytes, of exponentiation result.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_DhExp_3072(const mp_int* base, const byte* exp, word32 expLen,
|
|
const mp_int* mod, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[112 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
word32 i;
|
|
int err = MP_OKAY;
|
|
|
|
if (mp_count_bits(base) > 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expLen > 384U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 3072) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 112 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 112 * 2;
|
|
m = e + 112;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 112, base);
|
|
sp_3072_from_bin(e, 112, exp, expLen);
|
|
sp_3072_from_mp(m, 112, mod);
|
|
|
|
#ifdef HAVE_FFDHE_3072
|
|
if (base->used == 1 && base->dp[0] == 2U &&
|
|
(m[109] >> 4) == 0xffffL) {
|
|
err = sp_3072_mod_exp_2_112(r, e, expLen * 8U, m);
|
|
}
|
|
else {
|
|
#endif
|
|
err = sp_3072_mod_exp_112(r, b, e, expLen * 8U, m, 0);
|
|
#ifdef HAVE_FFDHE_3072
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_3072_to_bin_112(r, out);
|
|
*outLen = 384;
|
|
for (i=0; i<384U && out[i] == 0U; i++) {
|
|
/* Search for first non-zero. */
|
|
}
|
|
*outLen -= i;
|
|
XMEMMOVE(out, out + i, *outLen);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 112U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_SP_DH */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_1536(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[56 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 56 * 2;
|
|
m = e + 56;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 56, base);
|
|
sp_3072_from_mp(e, 56, exp);
|
|
sp_3072_from_mp(m, 56, mod);
|
|
|
|
err = sp_3072_mod_exp_56(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(r + 56, 0, sizeof(*r) * 56U);
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 112U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[56 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 1536) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 56 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 56 * 2;
|
|
m = e + 56;
|
|
r = b;
|
|
|
|
sp_3072_from_mp(b, 56, base);
|
|
sp_3072_from_mp(e, 56, exp);
|
|
sp_3072_from_mp(m, 56, mod);
|
|
|
|
err = sp_3072_mod_exp_56(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(r + 56, 0, sizeof(*r) * 56U);
|
|
err = sp_3072_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 112U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* !WOLFSSL_SP_NO_3072 */
|
|
|
|
#ifdef WOLFSSL_SP_4096
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 21U) {
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 29
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 29
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 29U) <= (word32)DIGIT_BIT) {
|
|
s += 29U;
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 29) {
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 29 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 512
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_4096_to_bin_142(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<141; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
j = 4103 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<142 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 29) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 29);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_71(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 70; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_142(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 141; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[141]) * b[141];
|
|
r[283] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 281; k >= 0; k--) {
|
|
if (k >= 142) {
|
|
i = k - 141;
|
|
imax = 141;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
if (imax - i > 15) {
|
|
int imaxlo;
|
|
lo = 0;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
|
|
for (; i <= imax && i < imaxlo + 15; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
lo &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
else {
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_sqr_142(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[141]) * a[141];
|
|
r[283] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 281; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 141) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 141;
|
|
}
|
|
if (imax - i >= 14) {
|
|
int imaxlo;
|
|
sp_uint64 hi;
|
|
|
|
hi = c >> 29;
|
|
c &= 0x1fffffff;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
|
|
t = 0;
|
|
for (; i <= imax && i < imaxlo + 14; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
hi += c >> 29;
|
|
c &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(hi >> 29);
|
|
r[k + 1] = (sp_digit)(hi & 0x1fffffff);
|
|
c <<= 29;
|
|
}
|
|
else
|
|
{
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
/* Caclulate the bottom digit of -1/a mod 2^n.
|
|
*
|
|
* a A single precision number.
|
|
* rho Bottom word of inverse.
|
|
*/
|
|
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
|
|
{
|
|
sp_digit x;
|
|
sp_digit b;
|
|
|
|
b = a[0];
|
|
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**8 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**16 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
|
|
x &= 0x1fffffff;
|
|
|
|
/* rho = -1/m mod b */
|
|
*rho = ((sp_digit)1 << 29) - x;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_d_142(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 142; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[142] = (sp_digit)t;
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
|
|
#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_sub_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 71; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 4096 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_4096_mont_norm_71(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i=0; i<70; i++) {
|
|
r[i] = 0x1fffffff;
|
|
}
|
|
r[70] = 0x3ffffL;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_4096_sub_71(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_4096_cmp_71(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
for (i=70; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_sub_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 71; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_add_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 71; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[71] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 68; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[68]) + r[68];
|
|
t[1] = (tb * a[69]) + r[69];
|
|
t[2] = (tb * a[70]) + r[70];
|
|
r[68] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[69] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[70] = t[2] & 0x1fffffff;
|
|
r[71] += (sp_digit)(t[2] >> 29);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 2048 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_4096_mont_shift_71(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[70] >> 18;
|
|
n += ((sp_int64)a[71]) << 11;
|
|
|
|
for (i = 0; i < 70; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[72 + i]) << 11;
|
|
}
|
|
r[70] = (sp_digit)n;
|
|
XMEMSET(&r[71], 0, sizeof(*r) * 71U);
|
|
}
|
|
|
|
/* Reduce the number back to 4096 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_4096_mont_reduce_71(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_4096_norm_71(a + 71);
|
|
|
|
for (i=0; i<70; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_4096_mul_add_71(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffL;
|
|
sp_4096_mul_add_71(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
sp_4096_mont_shift_71(a, a);
|
|
over = a[70] - m[70];
|
|
sp_4096_cond_sub_71(a, a, m, ~((over - 1) >> 31));
|
|
sp_4096_norm_71(a);
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[70]) * b[70];
|
|
r[141] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 139; k >= 0; k--) {
|
|
if (k >= 71) {
|
|
i = k - 70;
|
|
imax = 70;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
if (imax - i > 15) {
|
|
int imaxlo;
|
|
lo = 0;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 15) {
|
|
for (; i <= imax && i < imaxlo + 15; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
lo &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
else {
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_mul_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_mul_71(r, a, b);
|
|
sp_4096_mont_reduce_71(r, m, mp);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_sqr_71(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[70]) * a[70];
|
|
r[141] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 139; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 70) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 70;
|
|
}
|
|
if (imax - i >= 14) {
|
|
int imaxlo;
|
|
sp_uint64 hi;
|
|
|
|
hi = c >> 29;
|
|
c &= 0x1fffffff;
|
|
for (imaxlo = i; imaxlo <= imax; imaxlo += 14) {
|
|
t = 0;
|
|
for (; i <= imax && i < imaxlo + 14; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
hi += c >> 29;
|
|
c &= 0x1fffffff;
|
|
}
|
|
r[k + 2] += (sp_digit)(hi >> 29);
|
|
r[k + 1] = (sp_digit)(hi & 0x1fffffff);
|
|
c <<= 29;
|
|
}
|
|
else
|
|
{
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_sqr_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_sqr_71(r, a);
|
|
sp_4096_mont_reduce_71(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_d_71(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 71; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[71] = (sp_digit)t;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_add_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 71; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_71(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 71; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SP_NOINLINE static void sp_4096_rshift_71(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<70; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
r[70] = a[70] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_4096_div_word_71(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 29);
|
|
sp_digit t0 = (sp_digit)(d & 0x1fffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 27; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 29);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 14) + 1;
|
|
|
|
t = (sp_digit)(d >> 28);
|
|
t = (t / dv) << 14;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 13);
|
|
t = t / (dv << 1);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_4096_word_div_word_71(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_div_71(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 71 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 71 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 142 + 1;
|
|
sd = t2 + 71 + 1;
|
|
|
|
sp_4096_mul_d_71(sd, d, (sp_digit)1 << 11);
|
|
sp_4096_mul_d_142(t1, a, (sp_digit)1 << 11);
|
|
dv = sd[70];
|
|
t1[71 + 71] += t1[71 + 71 - 1] >> 29;
|
|
t1[71 + 71 - 1] &= 0x1fffffff;
|
|
for (i=71; i>=0; i--) {
|
|
r1 = sp_4096_div_word_71(t1[71 + i], t1[71 + i - 1], dv);
|
|
|
|
sp_4096_mul_d_71(t2, sd, r1);
|
|
(void)sp_4096_sub_71(&t1[i], &t1[i], t2);
|
|
sp_4096_norm_71(&t1[i]);
|
|
t1[71 + i] -= t2[71];
|
|
t1[71 + i] += t1[71 + i - 1] >> 29;
|
|
t1[71 + i - 1] &= 0x1fffffff;
|
|
r1 = sp_4096_div_word_71(-t1[71 + i], -t1[71 + i - 1], dv);
|
|
r1 -= t1[71 + i];
|
|
sp_4096_mul_d_71(t2, sd, r1);
|
|
(void)sp_4096_add_71(&t1[i], &t1[i], t2);
|
|
t1[71 + i] += t1[71 + i - 1] >> 29;
|
|
t1[71 + i - 1] &= 0x1fffffff;
|
|
}
|
|
t1[71 - 1] += t1[71 - 2] >> 29;
|
|
t1[71 - 2] &= 0x1fffffff;
|
|
r1 = sp_4096_word_div_word_71(t1[71 - 1], dv);
|
|
|
|
sp_4096_mul_d_71(t2, sd, r1);
|
|
sp_4096_sub_71(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 142U);
|
|
for (i=0; i<70; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
sp_4096_cond_add_71(r, r, sd, r[70] >> 31);
|
|
|
|
sp_4096_norm_71(r);
|
|
sp_4096_rshift_71(r, r, 11);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_mod_71(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_4096_div_71(a, m, NULL, r);
|
|
}
|
|
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_4096_mod_exp_71(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 142];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 71 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 71 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 71U * 2U);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_71(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_71(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 71U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_71(t[1], t[1], norm);
|
|
err = sp_4096_mod_71(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_71(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 71 * 2);
|
|
sp_4096_mont_sqr_71(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 71 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_71(t[0], m, mp);
|
|
n = sp_4096_cmp_71(t[0], m);
|
|
sp_4096_cond_sub_71(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 71 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 142];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 71 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 71 * 2);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_71(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_71(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_71(t[1], t[1], norm);
|
|
err = sp_4096_mod_71(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_71(t[1], a, norm);
|
|
err = sp_4096_mod_71(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_71(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 71 * 2);
|
|
sp_4096_mont_sqr_71(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 71 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_71(t[0], m, mp);
|
|
n = sp_4096_cmp_71(t[0], m);
|
|
sp_4096_cond_sub_71(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 71 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(32 * 142) + 142];
|
|
#endif
|
|
sp_digit* t[32];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 142) + 142), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<32; i++)
|
|
t[i] = td + i * 142;
|
|
rt = td + 4544;
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_71(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_71(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_71(t[1], t[1], norm);
|
|
err = sp_4096_mod_71(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_71(t[1], a, norm);
|
|
err = sp_4096_mod_71(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mont_sqr_71(t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_mul_71(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_sqr_71(t[ 4], t[ 2], m, mp);
|
|
sp_4096_mont_mul_71(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_4096_mont_sqr_71(t[ 6], t[ 3], m, mp);
|
|
sp_4096_mont_mul_71(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_4096_mont_sqr_71(t[ 8], t[ 4], m, mp);
|
|
sp_4096_mont_mul_71(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_4096_mont_sqr_71(t[10], t[ 5], m, mp);
|
|
sp_4096_mont_mul_71(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_4096_mont_sqr_71(t[12], t[ 6], m, mp);
|
|
sp_4096_mont_mul_71(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_4096_mont_sqr_71(t[14], t[ 7], m, mp);
|
|
sp_4096_mont_mul_71(t[15], t[ 8], t[ 7], m, mp);
|
|
sp_4096_mont_sqr_71(t[16], t[ 8], m, mp);
|
|
sp_4096_mont_mul_71(t[17], t[ 9], t[ 8], m, mp);
|
|
sp_4096_mont_sqr_71(t[18], t[ 9], m, mp);
|
|
sp_4096_mont_mul_71(t[19], t[10], t[ 9], m, mp);
|
|
sp_4096_mont_sqr_71(t[20], t[10], m, mp);
|
|
sp_4096_mont_mul_71(t[21], t[11], t[10], m, mp);
|
|
sp_4096_mont_sqr_71(t[22], t[11], m, mp);
|
|
sp_4096_mont_mul_71(t[23], t[12], t[11], m, mp);
|
|
sp_4096_mont_sqr_71(t[24], t[12], m, mp);
|
|
sp_4096_mont_mul_71(t[25], t[13], t[12], m, mp);
|
|
sp_4096_mont_sqr_71(t[26], t[13], m, mp);
|
|
sp_4096_mont_mul_71(t[27], t[14], t[13], m, mp);
|
|
sp_4096_mont_sqr_71(t[28], t[14], m, mp);
|
|
sp_4096_mont_mul_71(t[29], t[15], t[14], m, mp);
|
|
sp_4096_mont_sqr_71(t[30], t[15], m, mp);
|
|
sp_4096_mont_mul_71(t[31], t[16], t[15], m, mp);
|
|
|
|
bits = ((bits + 4) / 5) * 5;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 71) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 5) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 142);
|
|
while ((i >= 0) || (c >= 5)) {
|
|
if (c >= 5) {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c = 24;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n = e[i--] << 3;
|
|
c = 5 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_4096_mont_sqr_71(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_71(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_71(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_71(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_71(rt, rt, m, mp);
|
|
|
|
sp_4096_mont_mul_71(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_4096_mont_reduce_71(rt, m, mp);
|
|
n = sp_4096_cmp_71(rt, m);
|
|
sp_4096_cond_sub_71(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 142);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_sub_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 142; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 4096 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_4096_mont_norm_142(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i=0; i<141; i++) {
|
|
r[i] = 0x1fffffff;
|
|
}
|
|
r[141] = 0x7fL;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_4096_sub_142(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_4096_cmp_142(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
for (i=141; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_sub_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 142; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_add_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 142; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[142] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 140; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[140]) + r[140];
|
|
t[1] = (tb * a[141]) + r[141];
|
|
r[140] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[141] = t[1] & 0x1fffffff;
|
|
r[142] += (sp_digit)(t[1] >> 29);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 4096 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_4096_mont_shift_142(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[141] >> 7;
|
|
n += ((sp_int64)a[142]) << 22;
|
|
|
|
for (i = 0; i < 141; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[143 + i]) << 22;
|
|
}
|
|
r[141] = (sp_digit)n;
|
|
XMEMSET(&r[142], 0, sizeof(*r) * 142U);
|
|
}
|
|
|
|
/* Reduce the number back to 4096 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_4096_mont_reduce_142(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_4096_norm_142(a + 142);
|
|
|
|
#ifdef WOLFSSL_SP_DH
|
|
if (mp != 1) {
|
|
for (i=0; i<141; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_4096_mul_add_142(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7fL;
|
|
sp_4096_mul_add_142(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
else {
|
|
for (i=0; i<141; i++) {
|
|
mu = a[i] & 0x1fffffff;
|
|
sp_4096_mul_add_142(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = a[i] & 0x7fL;
|
|
sp_4096_mul_add_142(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<141; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_4096_mul_add_142(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x7fL;
|
|
sp_4096_mul_add_142(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
#endif
|
|
sp_4096_mont_shift_142(a, a);
|
|
over = a[141] - m[141];
|
|
sp_4096_cond_sub_142(a, a, m, ~((over - 1) >> 31));
|
|
sp_4096_norm_142(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_mul_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_mul_142(r, a, b);
|
|
sp_4096_mont_reduce_142(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_sqr_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_sqr_142(r, a);
|
|
sp_4096_mont_reduce_142(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_d_284(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 284; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[284] = (sp_digit)t;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_add_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 142; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_142(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 142; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
SP_NOINLINE static void sp_4096_rshift_142(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<141; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
r[141] = a[141] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_4096_div_word_142(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 29);
|
|
sp_digit t0 = (sp_digit)(d & 0x1fffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 27; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 28) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 29);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 58) - (sp_digit)(d >> 58);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 29) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 14) + 1;
|
|
|
|
t = (sp_digit)(d >> 28);
|
|
t = (t / dv) << 14;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 13);
|
|
t = t / (dv << 1);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_4096_word_div_word_142(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_div_142(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 142 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 142 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 284 + 1;
|
|
sd = t2 + 142 + 1;
|
|
|
|
sp_4096_mul_d_142(sd, d, (sp_digit)1 << 22);
|
|
sp_4096_mul_d_284(t1, a, (sp_digit)1 << 22);
|
|
dv = sd[141];
|
|
t1[142 + 142] += t1[142 + 142 - 1] >> 29;
|
|
t1[142 + 142 - 1] &= 0x1fffffff;
|
|
for (i=142; i>=0; i--) {
|
|
r1 = sp_4096_div_word_142(t1[142 + i], t1[142 + i - 1], dv);
|
|
|
|
sp_4096_mul_d_142(t2, sd, r1);
|
|
(void)sp_4096_sub_142(&t1[i], &t1[i], t2);
|
|
sp_4096_norm_142(&t1[i]);
|
|
t1[142 + i] -= t2[142];
|
|
t1[142 + i] += t1[142 + i - 1] >> 29;
|
|
t1[142 + i - 1] &= 0x1fffffff;
|
|
r1 = sp_4096_div_word_142(-t1[142 + i], -t1[142 + i - 1], dv);
|
|
r1 -= t1[142 + i];
|
|
sp_4096_mul_d_142(t2, sd, r1);
|
|
(void)sp_4096_add_142(&t1[i], &t1[i], t2);
|
|
t1[142 + i] += t1[142 + i - 1] >> 29;
|
|
t1[142 + i - 1] &= 0x1fffffff;
|
|
}
|
|
t1[142 - 1] += t1[142 - 2] >> 29;
|
|
t1[142 - 2] &= 0x1fffffff;
|
|
r1 = sp_4096_word_div_word_142(t1[142 - 1], dv);
|
|
|
|
sp_4096_mul_d_142(t2, sd, r1);
|
|
sp_4096_sub_142(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 284U);
|
|
for (i=0; i<141; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
sp_4096_cond_add_142(r, r, sd, r[141] >> 31);
|
|
|
|
sp_4096_norm_142(r);
|
|
sp_4096_rshift_142(r, r, 22);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_mod_142(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_4096_div_142(a, m, NULL, r);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_4096_mod_exp_142(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 284];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 142 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 142 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 142U * 2U);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_142(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_142(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 142U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_142(t[1], t[1], norm);
|
|
err = sp_4096_mod_142(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_142(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 142 * 2);
|
|
sp_4096_mont_sqr_142(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 142 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_142(t[0], m, mp);
|
|
n = sp_4096_cmp_142(t[0], m);
|
|
sp_4096_cond_sub_142(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 142 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 284];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 142 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 142 * 2);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_142(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_142(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_142(t[1], t[1], norm);
|
|
err = sp_4096_mod_142(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_142(t[1], a, norm);
|
|
err = sp_4096_mod_142(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 29;
|
|
c = bits % 29;
|
|
n = e[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (int)((n >> 28) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_142(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 142 * 2);
|
|
sp_4096_mont_sqr_142(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 142 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_142(t[0], m, mp);
|
|
n = sp_4096_cmp_142(t[0], m);
|
|
sp_4096_cond_sub_142(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 142 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(16 * 284) + 284];
|
|
#endif
|
|
sp_digit* t[16];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 284) + 284), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<16; i++)
|
|
t[i] = td + i * 284;
|
|
rt = td + 4544;
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_142(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_142(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_142(t[1], t[1], norm);
|
|
err = sp_4096_mod_142(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_142(t[1], a, norm);
|
|
err = sp_4096_mod_142(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mont_sqr_142(t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_mul_142(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_sqr_142(t[ 4], t[ 2], m, mp);
|
|
sp_4096_mont_mul_142(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_4096_mont_sqr_142(t[ 6], t[ 3], m, mp);
|
|
sp_4096_mont_mul_142(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_4096_mont_sqr_142(t[ 8], t[ 4], m, mp);
|
|
sp_4096_mont_mul_142(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_4096_mont_sqr_142(t[10], t[ 5], m, mp);
|
|
sp_4096_mont_mul_142(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_4096_mont_sqr_142(t[12], t[ 6], m, mp);
|
|
sp_4096_mont_mul_142(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_4096_mont_sqr_142(t[14], t[ 7], m, mp);
|
|
sp_4096_mont_mul_142(t[15], t[ 8], t[ 7], m, mp);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 142) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 284);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 25;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 3;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_4096_mont_sqr_142(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_142(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_142(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_142(rt, rt, m, mp);
|
|
|
|
sp_4096_mont_mul_142(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_4096_mont_reduce_142(rt, m, mp);
|
|
n = sp_4096_cmp_142(rt, m);
|
|
sp_4096_cond_sub_142(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 284);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
#ifdef WOLFSSL_HAVE_SP_RSA
|
|
/* RSA public key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* em Public exponent.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 512 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
|
|
const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[142 * 5];
|
|
#endif
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit e[1] = {0};
|
|
sp_digit mp = 0;
|
|
int i;
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 29) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
r = a + 142 * 2;
|
|
m = r + 142 * 2;
|
|
norm = r;
|
|
|
|
sp_4096_from_bin(a, 142, in, inLen);
|
|
#if DIGIT_BIT >= 29
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(m, 142, mm);
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_142(norm, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_142(a, a, norm);
|
|
err = sp_4096_mod_142(a, a, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
for (i=28; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 142 * 2);
|
|
for (i--; i>=0; i--) {
|
|
sp_4096_mont_sqr_142(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_4096_mont_mul_142(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_4096_mont_reduce_142(r, m, mp);
|
|
mp = sp_4096_cmp_142(r, m);
|
|
sp_4096_cond_sub_142(r, r, m, ~(mp >> 31));
|
|
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[142 * 5];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit e[1] = {0};
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 29) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d;
|
|
r = a + 142 * 2;
|
|
m = r + 142 * 2;
|
|
|
|
sp_4096_from_bin(a, 142, in, inLen);
|
|
#if DIGIT_BIT >= 29
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(m, 142, mm);
|
|
|
|
if (e[0] == 0x3) {
|
|
sp_4096_sqr_142(r, a);
|
|
err = sp_4096_mod_142(r, r, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_142(r, a, r);
|
|
err = sp_4096_mod_142(r, r, m);
|
|
}
|
|
}
|
|
else {
|
|
sp_digit* norm = r;
|
|
int i;
|
|
sp_digit mp;
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_142(norm, m);
|
|
|
|
sp_4096_mul_142(a, a, norm);
|
|
err = sp_4096_mod_142(a, a, m);
|
|
|
|
if (err == MP_OKAY) {
|
|
for (i=28; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 284U);
|
|
for (i--; i>=0; i--) {
|
|
sp_4096_mont_sqr_142(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_4096_mont_mul_142(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_4096_mont_reduce_142(r, m, mp);
|
|
mp = sp_4096_cmp_142(r, m);
|
|
sp_4096_cond_sub_142(r, r, m, ~(mp >> 31));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
|
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
|
|
#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
|
|
/* RSA private key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* dm Private exponent.
|
|
* pm First prime.
|
|
* qm Second prime.
|
|
* dpm First prime's CRT exponent.
|
|
* dqm Second prime's CRT exponent.
|
|
* qim Inverse of second prime mod p.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 512 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
|
|
const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
|
|
const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[142 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 142;
|
|
m = a + 284;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 142, in, inLen);
|
|
sp_4096_from_mp(d, 142, dm);
|
|
sp_4096_from_mp(m, 142, mm);
|
|
err = sp_4096_mod_exp_142(r, a, d, 4096, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 142);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[142 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 142;
|
|
m = a + 284;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 142, in, inLen);
|
|
sp_4096_from_mp(d, 142, dm);
|
|
sp_4096_from_mp(m, 142, mm);
|
|
err = sp_4096_mod_exp_142(r, a, d, 4096, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 142);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#else
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[71 * 8];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 512) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 71 * 8, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
p = a + 142;
|
|
qi = dq = dp = p + 71;
|
|
tmpa = qi + 71;
|
|
tmpb = tmpa + 142;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 142, in, inLen);
|
|
sp_4096_from_mp(p, 71, pm);
|
|
sp_4096_from_mp(dp, 71, dpm);
|
|
err = sp_4096_mod_exp_71(tmpa, a, dp, 2048, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(p, 71, qm);
|
|
sp_4096_from_mp(dq, 71, dqm);
|
|
err = sp_4096_mod_exp_71(tmpb, a, dq, 2048, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(p, 71, pm);
|
|
(void)sp_4096_sub_71(tmpa, tmpa, tmpb);
|
|
sp_4096_norm_71(tmpa);
|
|
sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
|
|
sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
|
|
sp_4096_norm_71(tmpa);
|
|
|
|
sp_4096_from_mp(qi, 71, qim);
|
|
sp_4096_mul_71(tmpa, tmpa, qi);
|
|
err = sp_4096_mod_71(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(p, 71, qm);
|
|
sp_4096_mul_71(tmpa, p, tmpa);
|
|
(void)sp_4096_add_142(r, tmpb, tmpa);
|
|
sp_4096_norm_142(r);
|
|
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 71 * 8);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[71 * 13];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* q = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 71 * 13, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = a + 142 * 2;
|
|
q = p + 71;
|
|
dp = q + 71;
|
|
dq = dp + 71;
|
|
qi = dq + 71;
|
|
tmpa = qi + 71;
|
|
tmpb = tmpa + 142;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 142, in, inLen);
|
|
sp_4096_from_mp(p, 71, pm);
|
|
sp_4096_from_mp(q, 71, qm);
|
|
sp_4096_from_mp(dp, 71, dpm);
|
|
sp_4096_from_mp(dq, 71, dqm);
|
|
sp_4096_from_mp(qi, 71, qim);
|
|
|
|
err = sp_4096_mod_exp_71(tmpa, a, dp, 2048, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_4096_mod_exp_71(tmpb, a, dq, 2048, q, 1);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
(void)sp_4096_sub_71(tmpa, tmpa, tmpb);
|
|
sp_4096_norm_71(tmpa);
|
|
sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
|
|
sp_4096_cond_add_71(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[70] >> 31));
|
|
sp_4096_norm_71(tmpa);
|
|
sp_4096_mul_71(tmpa, tmpa, qi);
|
|
err = sp_4096_mod_71(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_71(tmpa, tmpa, q);
|
|
(void)sp_4096_add_142(r, tmpb, tmpa);
|
|
sp_4096_norm_142(r);
|
|
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 71 * 13);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
|
|
}
|
|
|
|
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
#endif /* WOLFSSL_HAVE_SP_RSA */
|
|
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
|
|
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 29
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 142);
|
|
r->used = 142;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 29
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 142; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 29) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 29 - s;
|
|
}
|
|
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 142; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 29 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 29 - s;
|
|
}
|
|
else {
|
|
s += 29;
|
|
}
|
|
}
|
|
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[142 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 142 * 2;
|
|
m = e + 142;
|
|
r = b;
|
|
|
|
sp_4096_from_mp(b, 142, base);
|
|
sp_4096_from_mp(e, 142, exp);
|
|
sp_4096_from_mp(m, 142, mod);
|
|
|
|
err = sp_4096_mod_exp_142(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_4096_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 142U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[142 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 142 * 2;
|
|
m = e + 142;
|
|
r = b;
|
|
|
|
sp_4096_from_mp(b, 142, base);
|
|
sp_4096_from_mp(e, 142, exp);
|
|
sp_4096_from_mp(m, 142, mod);
|
|
|
|
err = sp_4096_mod_exp_142(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_4096_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 142U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#ifdef WOLFSSL_HAVE_SP_DH
|
|
|
|
#ifdef HAVE_FFDHE_4096
|
|
SP_NOINLINE static void sp_4096_lshift_142(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
r[142] = a[141] >> (29 - n);
|
|
for (i=141; i>0; i--) {
|
|
r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
|
|
}
|
|
r[0] = (a[0] << n) & 0x1fffffff;
|
|
}
|
|
|
|
/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even.
|
|
*/
|
|
static int sp_4096_mod_exp_2_142(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[427];
|
|
#endif
|
|
sp_digit* norm = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
sp_digit o;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 427, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
tmp = td + 284;
|
|
XMEMSET(td, 0, sizeof(sp_digit) * 427);
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_142(norm, m);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 28) / 29) - 1;
|
|
c = bits % 29;
|
|
if (c == 0) {
|
|
c = 29;
|
|
}
|
|
if (i < 142) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (3 - c);
|
|
c += 29;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
sp_4096_lshift_142(r, norm, (byte)y);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 3;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 25;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 3;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 29 - c;
|
|
}
|
|
|
|
sp_4096_mont_sqr_142(r, r, m, mp);
|
|
sp_4096_mont_sqr_142(r, r, m, mp);
|
|
sp_4096_mont_sqr_142(r, r, m, mp);
|
|
sp_4096_mont_sqr_142(r, r, m, mp);
|
|
|
|
sp_4096_lshift_142(r, r, (byte)y);
|
|
sp_4096_mul_d_142(tmp, norm, (r[142] << 22) + (r[141] >> 7));
|
|
r[142] = 0;
|
|
r[141] &= 0x7fL;
|
|
(void)sp_4096_add_142(r, r, tmp);
|
|
sp_4096_norm_142(r);
|
|
o = sp_4096_cmp_142(r, m);
|
|
sp_4096_cond_sub_142(r, r, m, ~(o >> 31));
|
|
}
|
|
|
|
sp_4096_mont_reduce_142(r, m, mp);
|
|
n = sp_4096_cmp_142(r, m);
|
|
sp_4096_cond_sub_142(r, r, m, ~(n >> 31));
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* HAVE_FFDHE_4096 */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base.
|
|
* exp Array of bytes that is the exponent.
|
|
* expLen Length of data, in bytes, in exponent.
|
|
* mod Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 512 bytes long.
|
|
* outLen Length, in bytes, of exponentiation result.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
|
|
const mp_int* mod, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[142 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
word32 i;
|
|
int err = MP_OKAY;
|
|
|
|
if (mp_count_bits(base) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 142 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 142 * 2;
|
|
m = e + 142;
|
|
r = b;
|
|
|
|
sp_4096_from_mp(b, 142, base);
|
|
sp_4096_from_bin(e, 142, exp, expLen);
|
|
sp_4096_from_mp(m, 142, mod);
|
|
|
|
#ifdef HAVE_FFDHE_4096
|
|
if (base->used == 1 && base->dp[0] == 2U &&
|
|
((m[141] << 9) | (m[140] >> 20)) == 0xffffL) {
|
|
err = sp_4096_mod_exp_2_142(r, e, expLen * 8U, m);
|
|
}
|
|
else {
|
|
#endif
|
|
err = sp_4096_mod_exp_142(r, b, e, expLen * 8U, m, 0);
|
|
#ifdef HAVE_FFDHE_4096
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_142(r, out);
|
|
*outLen = 512;
|
|
for (i=0; i<512U && out[i] == 0U; i++) {
|
|
/* Search for first non-zero. */
|
|
}
|
|
*outLen -= i;
|
|
XMEMMOVE(out, out + i, *outLen);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 142U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_SP_DH */
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
|
|
|
|
#else
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_4096_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 18U) {
|
|
r[j] &= 0x3ffffff;
|
|
s = 26U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_4096_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 26
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 26
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x3ffffff;
|
|
s = 26U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 26U) <= (word32)DIGIT_BIT) {
|
|
s += 26U;
|
|
r[j] &= 0x3ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 26) {
|
|
r[j] &= 0x3ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 26 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 512
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_4096_to_bin_162(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<161; i++) {
|
|
r[i+1] += r[i] >> 26;
|
|
r[i] &= 0x3ffffff;
|
|
}
|
|
j = 4103 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<158 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 26) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 26);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_81(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 80; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_79(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 72; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[73] += a[72] >> 26; a[72] &= 0x3ffffff;
|
|
a[74] += a[73] >> 26; a[73] &= 0x3ffffff;
|
|
a[75] += a[74] >> 26; a[74] &= 0x3ffffff;
|
|
a[76] += a[75] >> 26; a[75] &= 0x3ffffff;
|
|
a[77] += a[76] >> 26; a[76] &= 0x3ffffff;
|
|
a[78] += a[77] >> 26; a[77] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_162(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 160; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[161] += a[160] >> 26; a[160] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_158(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 152; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[153] += a[152] >> 26; a[152] &= 0x3ffffff;
|
|
a[154] += a[153] >> 26; a[153] &= 0x3ffffff;
|
|
a[155] += a[154] >> 26; a[154] &= 0x3ffffff;
|
|
a[156] += a[155] >> 26; a[155] &= 0x3ffffff;
|
|
a[157] += a[156] >> 26; a[156] &= 0x3ffffff;
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_uint64 t0;
|
|
sp_uint64 t1;
|
|
sp_digit t[9];
|
|
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 0];
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 1]
|
|
+ ((sp_uint64)a[ 1]) * b[ 0];
|
|
t[ 0] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 2]
|
|
+ ((sp_uint64)a[ 1]) * b[ 1]
|
|
+ ((sp_uint64)a[ 2]) * b[ 0];
|
|
t[ 1] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 3]
|
|
+ ((sp_uint64)a[ 1]) * b[ 2]
|
|
+ ((sp_uint64)a[ 2]) * b[ 1]
|
|
+ ((sp_uint64)a[ 3]) * b[ 0];
|
|
t[ 2] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 4]
|
|
+ ((sp_uint64)a[ 1]) * b[ 3]
|
|
+ ((sp_uint64)a[ 2]) * b[ 2]
|
|
+ ((sp_uint64)a[ 3]) * b[ 1]
|
|
+ ((sp_uint64)a[ 4]) * b[ 0];
|
|
t[ 3] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 5]
|
|
+ ((sp_uint64)a[ 1]) * b[ 4]
|
|
+ ((sp_uint64)a[ 2]) * b[ 3]
|
|
+ ((sp_uint64)a[ 3]) * b[ 2]
|
|
+ ((sp_uint64)a[ 4]) * b[ 1]
|
|
+ ((sp_uint64)a[ 5]) * b[ 0];
|
|
t[ 4] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 6]
|
|
+ ((sp_uint64)a[ 1]) * b[ 5]
|
|
+ ((sp_uint64)a[ 2]) * b[ 4]
|
|
+ ((sp_uint64)a[ 3]) * b[ 3]
|
|
+ ((sp_uint64)a[ 4]) * b[ 2]
|
|
+ ((sp_uint64)a[ 5]) * b[ 1]
|
|
+ ((sp_uint64)a[ 6]) * b[ 0];
|
|
t[ 5] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 0]) * b[ 7]
|
|
+ ((sp_uint64)a[ 1]) * b[ 6]
|
|
+ ((sp_uint64)a[ 2]) * b[ 5]
|
|
+ ((sp_uint64)a[ 3]) * b[ 4]
|
|
+ ((sp_uint64)a[ 4]) * b[ 3]
|
|
+ ((sp_uint64)a[ 5]) * b[ 2]
|
|
+ ((sp_uint64)a[ 6]) * b[ 1]
|
|
+ ((sp_uint64)a[ 7]) * b[ 0];
|
|
t[ 6] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 0]) * b[ 8]
|
|
+ ((sp_uint64)a[ 1]) * b[ 7]
|
|
+ ((sp_uint64)a[ 2]) * b[ 6]
|
|
+ ((sp_uint64)a[ 3]) * b[ 5]
|
|
+ ((sp_uint64)a[ 4]) * b[ 4]
|
|
+ ((sp_uint64)a[ 5]) * b[ 3]
|
|
+ ((sp_uint64)a[ 6]) * b[ 2]
|
|
+ ((sp_uint64)a[ 7]) * b[ 1]
|
|
+ ((sp_uint64)a[ 8]) * b[ 0];
|
|
t[ 7] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 1]) * b[ 8]
|
|
+ ((sp_uint64)a[ 2]) * b[ 7]
|
|
+ ((sp_uint64)a[ 3]) * b[ 6]
|
|
+ ((sp_uint64)a[ 4]) * b[ 5]
|
|
+ ((sp_uint64)a[ 5]) * b[ 4]
|
|
+ ((sp_uint64)a[ 6]) * b[ 3]
|
|
+ ((sp_uint64)a[ 7]) * b[ 2]
|
|
+ ((sp_uint64)a[ 8]) * b[ 1];
|
|
t[ 8] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 2]) * b[ 8]
|
|
+ ((sp_uint64)a[ 3]) * b[ 7]
|
|
+ ((sp_uint64)a[ 4]) * b[ 6]
|
|
+ ((sp_uint64)a[ 5]) * b[ 5]
|
|
+ ((sp_uint64)a[ 6]) * b[ 4]
|
|
+ ((sp_uint64)a[ 7]) * b[ 3]
|
|
+ ((sp_uint64)a[ 8]) * b[ 2];
|
|
r[ 9] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 3]) * b[ 8]
|
|
+ ((sp_uint64)a[ 4]) * b[ 7]
|
|
+ ((sp_uint64)a[ 5]) * b[ 6]
|
|
+ ((sp_uint64)a[ 6]) * b[ 5]
|
|
+ ((sp_uint64)a[ 7]) * b[ 4]
|
|
+ ((sp_uint64)a[ 8]) * b[ 3];
|
|
r[10] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 4]) * b[ 8]
|
|
+ ((sp_uint64)a[ 5]) * b[ 7]
|
|
+ ((sp_uint64)a[ 6]) * b[ 6]
|
|
+ ((sp_uint64)a[ 7]) * b[ 5]
|
|
+ ((sp_uint64)a[ 8]) * b[ 4];
|
|
r[11] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 5]) * b[ 8]
|
|
+ ((sp_uint64)a[ 6]) * b[ 7]
|
|
+ ((sp_uint64)a[ 7]) * b[ 6]
|
|
+ ((sp_uint64)a[ 8]) * b[ 5];
|
|
r[12] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 6]) * b[ 8]
|
|
+ ((sp_uint64)a[ 7]) * b[ 7]
|
|
+ ((sp_uint64)a[ 8]) * b[ 6];
|
|
r[13] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_uint64)a[ 7]) * b[ 8]
|
|
+ ((sp_uint64)a[ 8]) * b[ 7];
|
|
r[14] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 8]) * b[ 8];
|
|
r[15] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
r[16] = t0 & 0x3ffffff;
|
|
r[17] = (sp_digit)(t0 >> 26);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
r[ 7] = a[ 7] + b[ 7];
|
|
r[ 8] = a[ 8] + b[ 8];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_sub_18(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[16] = a[16] - b[16];
|
|
r[17] = a[17] - b[17];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_18(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[16] = a[16] + b[16];
|
|
r[17] = a[17] + b[17];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_9(sp_digit* a)
|
|
{
|
|
a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
|
|
a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
|
|
a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
|
|
a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
|
|
a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
|
|
a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
|
|
a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
|
|
a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_18(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 16; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[17] += a[16] >> 26; a[16] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_54(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 48; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[49] += a[48] >> 26; a[48] &= 0x3ffffff;
|
|
a[50] += a[49] >> 26; a[49] &= 0x3ffffff;
|
|
a[51] += a[50] >> 26; a[50] &= 0x3ffffff;
|
|
a[52] += a[51] >> 26; a[51] &= 0x3ffffff;
|
|
a[53] += a[52] >> 26; a[52] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_27(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit p0[18];
|
|
sp_digit p1[18];
|
|
sp_digit p2[18];
|
|
sp_digit p3[18];
|
|
sp_digit p4[18];
|
|
sp_digit p5[18];
|
|
sp_digit t0[18];
|
|
sp_digit t1[18];
|
|
sp_digit t2[18];
|
|
sp_digit a0[9];
|
|
sp_digit a1[9];
|
|
sp_digit a2[9];
|
|
sp_digit b0[9];
|
|
sp_digit b1[9];
|
|
sp_digit b2[9];
|
|
(void)sp_4096_add_9(a0, a, &a[9]);
|
|
sp_4096_norm_9(a0);
|
|
(void)sp_4096_add_9(b0, b, &b[9]);
|
|
sp_4096_norm_9(b0);
|
|
(void)sp_4096_add_9(a1, &a[9], &a[18]);
|
|
sp_4096_norm_9(a1);
|
|
(void)sp_4096_add_9(b1, &b[9], &b[18]);
|
|
sp_4096_norm_9(b1);
|
|
(void)sp_4096_add_9(a2, a0, &a[18]);
|
|
sp_4096_norm_9(a1);
|
|
(void)sp_4096_add_9(b2, b0, &b[18]);
|
|
sp_4096_norm_9(b2);
|
|
sp_4096_mul_9(p0, a, b);
|
|
sp_4096_mul_9(p2, &a[9], &b[9]);
|
|
sp_4096_mul_9(p4, &a[18], &b[18]);
|
|
sp_4096_mul_9(p1, a0, b0);
|
|
sp_4096_mul_9(p3, a1, b1);
|
|
sp_4096_mul_9(p5, a2, b2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*27U);
|
|
(void)sp_4096_sub_18(t0, p3, p2);
|
|
(void)sp_4096_sub_18(t1, p1, p2);
|
|
(void)sp_4096_sub_18(t2, p5, t0);
|
|
(void)sp_4096_sub_18(t2, t2, t1);
|
|
sp_4096_norm_18(t2);
|
|
(void)sp_4096_sub_18(t0, t0, p4);
|
|
sp_4096_norm_18(t0);
|
|
(void)sp_4096_sub_18(t1, t1, p0);
|
|
sp_4096_norm_18(t1);
|
|
(void)sp_4096_add_18(r, r, p0);
|
|
(void)sp_4096_add_18(&r[9], &r[9], t1);
|
|
(void)sp_4096_add_18(&r[18], &r[18], t2);
|
|
(void)sp_4096_add_18(&r[27], &r[27], t0);
|
|
(void)sp_4096_add_18(&r[36], &r[36], p4);
|
|
sp_4096_norm_54(r);
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_27(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 24; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[24] = a[24] + b[24];
|
|
r[25] = a[25] + b[25];
|
|
r[26] = a[26] + b[26];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_sub_54(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 48; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[48] = a[48] - b[48];
|
|
r[49] = a[49] - b[49];
|
|
r[50] = a[50] - b[50];
|
|
r[51] = a[51] - b[51];
|
|
r[52] = a[52] - b[52];
|
|
r[53] = a[53] - b[53];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_54(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 48; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[48] = a[48] + b[48];
|
|
r[49] = a[49] + b[49];
|
|
r[50] = a[50] + b[50];
|
|
r[51] = a[51] + b[51];
|
|
r[52] = a[52] + b[52];
|
|
r[53] = a[53] + b[53];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_27(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 24; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[25] += a[24] >> 26; a[24] &= 0x3ffffff;
|
|
a[26] += a[25] >> 26; a[25] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit p0[54];
|
|
sp_digit p1[54];
|
|
sp_digit p2[54];
|
|
sp_digit p3[54];
|
|
sp_digit p4[54];
|
|
sp_digit p5[54];
|
|
sp_digit t0[54];
|
|
sp_digit t1[54];
|
|
sp_digit t2[54];
|
|
sp_digit a0[27];
|
|
sp_digit a1[27];
|
|
sp_digit a2[27];
|
|
sp_digit b0[27];
|
|
sp_digit b1[27];
|
|
sp_digit b2[27];
|
|
(void)sp_4096_add_27(a0, a, &a[27]);
|
|
sp_4096_norm_27(a0);
|
|
(void)sp_4096_add_27(b0, b, &b[27]);
|
|
sp_4096_norm_27(b0);
|
|
(void)sp_4096_add_27(a1, &a[27], &a[54]);
|
|
sp_4096_norm_27(a1);
|
|
(void)sp_4096_add_27(b1, &b[27], &b[54]);
|
|
sp_4096_norm_27(b1);
|
|
(void)sp_4096_add_27(a2, a0, &a[54]);
|
|
sp_4096_norm_27(a1);
|
|
(void)sp_4096_add_27(b2, b0, &b[54]);
|
|
sp_4096_norm_27(b2);
|
|
sp_4096_mul_27(p0, a, b);
|
|
sp_4096_mul_27(p2, &a[27], &b[27]);
|
|
sp_4096_mul_27(p4, &a[54], &b[54]);
|
|
sp_4096_mul_27(p1, a0, b0);
|
|
sp_4096_mul_27(p3, a1, b1);
|
|
sp_4096_mul_27(p5, a2, b2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*81U);
|
|
(void)sp_4096_sub_54(t0, p3, p2);
|
|
(void)sp_4096_sub_54(t1, p1, p2);
|
|
(void)sp_4096_sub_54(t2, p5, t0);
|
|
(void)sp_4096_sub_54(t2, t2, t1);
|
|
sp_4096_norm_54(t2);
|
|
(void)sp_4096_sub_54(t0, t0, p4);
|
|
sp_4096_norm_54(t0);
|
|
(void)sp_4096_sub_54(t1, t1, p0);
|
|
sp_4096_norm_54(t1);
|
|
(void)sp_4096_add_54(r, r, p0);
|
|
(void)sp_4096_add_54(&r[27], &r[27], t1);
|
|
(void)sp_4096_add_54(&r[54], &r[54], t2);
|
|
(void)sp_4096_add_54(&r[81], &r[81], t0);
|
|
(void)sp_4096_add_54(&r[108], &r[108], p4);
|
|
sp_4096_norm_162(r);
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[80] = a[80] + b[80];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_add_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 160; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[160] = a[160] + b[160];
|
|
r[161] = a[161] + b[161];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_sub_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 160; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[160] = a[160] - b[160];
|
|
r[161] = a[161] - b[161];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_4096_norm_324(sp_digit* a)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 320; i += 8) {
|
|
a[i+1] += a[i+0] >> 26; a[i+0] &= 0x3ffffff;
|
|
a[i+2] += a[i+1] >> 26; a[i+1] &= 0x3ffffff;
|
|
a[i+3] += a[i+2] >> 26; a[i+2] &= 0x3ffffff;
|
|
a[i+4] += a[i+3] >> 26; a[i+3] &= 0x3ffffff;
|
|
a[i+5] += a[i+4] >> 26; a[i+4] &= 0x3ffffff;
|
|
a[i+6] += a[i+5] >> 26; a[i+5] &= 0x3ffffff;
|
|
a[i+7] += a[i+6] >> 26; a[i+6] &= 0x3ffffff;
|
|
a[i+8] += a[i+7] >> 26; a[i+7] &= 0x3ffffff;
|
|
}
|
|
a[321] += a[320] >> 26; a[320] &= 0x3ffffff;
|
|
a[322] += a[321] >> 26; a[321] &= 0x3ffffff;
|
|
a[323] += a[322] >> 26; a[322] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[162];
|
|
sp_digit* a1 = z1;
|
|
sp_digit b1[81];
|
|
sp_digit* z2 = r + 162;
|
|
(void)sp_4096_add_81(a1, a, &a[81]);
|
|
sp_4096_norm_81(a1);
|
|
(void)sp_4096_add_81(b1, b, &b[81]);
|
|
sp_4096_norm_81(b1);
|
|
sp_4096_mul_81(z2, &a[81], &b[81]);
|
|
sp_4096_mul_81(z0, a, b);
|
|
sp_4096_mul_81(z1, a1, b1);
|
|
(void)sp_4096_sub_162(z1, z1, z2);
|
|
(void)sp_4096_sub_162(z1, z1, z0);
|
|
(void)sp_4096_add_162(r + 81, r + 81, z1);
|
|
sp_4096_norm_324(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_sqr_9(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_uint64 t0;
|
|
sp_uint64 t1;
|
|
sp_digit t[9];
|
|
|
|
t0 = ((sp_uint64)a[ 0]) * a[ 0];
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 1]) * 2;
|
|
t[ 0] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 2]) * 2
|
|
+ ((sp_uint64)a[ 1]) * a[ 1];
|
|
t[ 1] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 3]
|
|
+ ((sp_uint64)a[ 1]) * a[ 2]) * 2;
|
|
t[ 2] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 4]
|
|
+ ((sp_uint64)a[ 1]) * a[ 3]) * 2
|
|
+ ((sp_uint64)a[ 2]) * a[ 2];
|
|
t[ 3] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 5]
|
|
+ ((sp_uint64)a[ 1]) * a[ 4]
|
|
+ ((sp_uint64)a[ 2]) * a[ 3]) * 2;
|
|
t[ 4] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 6]
|
|
+ ((sp_uint64)a[ 1]) * a[ 5]
|
|
+ ((sp_uint64)a[ 2]) * a[ 4]) * 2
|
|
+ ((sp_uint64)a[ 3]) * a[ 3];
|
|
t[ 5] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 0]) * a[ 7]
|
|
+ ((sp_uint64)a[ 1]) * a[ 6]
|
|
+ ((sp_uint64)a[ 2]) * a[ 5]
|
|
+ ((sp_uint64)a[ 3]) * a[ 4]) * 2;
|
|
t[ 6] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 0]) * a[ 8]
|
|
+ ((sp_uint64)a[ 1]) * a[ 7]
|
|
+ ((sp_uint64)a[ 2]) * a[ 6]
|
|
+ ((sp_uint64)a[ 3]) * a[ 5]) * 2
|
|
+ ((sp_uint64)a[ 4]) * a[ 4];
|
|
t[ 7] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 1]) * a[ 8]
|
|
+ ((sp_uint64)a[ 2]) * a[ 7]
|
|
+ ((sp_uint64)a[ 3]) * a[ 6]
|
|
+ ((sp_uint64)a[ 4]) * a[ 5]) * 2;
|
|
t[ 8] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 2]) * a[ 8]
|
|
+ ((sp_uint64)a[ 3]) * a[ 7]
|
|
+ ((sp_uint64)a[ 4]) * a[ 6]) * 2
|
|
+ ((sp_uint64)a[ 5]) * a[ 5];
|
|
r[ 9] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 3]) * a[ 8]
|
|
+ ((sp_uint64)a[ 4]) * a[ 7]
|
|
+ ((sp_uint64)a[ 5]) * a[ 6]) * 2;
|
|
r[10] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 4]) * a[ 8]
|
|
+ ((sp_uint64)a[ 5]) * a[ 7]) * 2
|
|
+ ((sp_uint64)a[ 6]) * a[ 6];
|
|
r[11] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 5]) * a[ 8]
|
|
+ ((sp_uint64)a[ 6]) * a[ 7]) * 2;
|
|
r[12] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_uint64)a[ 6]) * a[ 8]) * 2
|
|
+ ((sp_uint64)a[ 7]) * a[ 7];
|
|
r[13] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_uint64)a[ 7]) * a[ 8]) * 2;
|
|
r[14] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_uint64)a[ 8]) * a[ 8];
|
|
r[15] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
r[16] = t0 & 0x3ffffff;
|
|
r[17] = (sp_digit)(t0 >> 26);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
/* Square a into r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_sqr_27(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit p0[18];
|
|
sp_digit p1[18];
|
|
sp_digit p2[18];
|
|
sp_digit p3[18];
|
|
sp_digit p4[18];
|
|
sp_digit p5[18];
|
|
sp_digit t0[18];
|
|
sp_digit t1[18];
|
|
sp_digit t2[18];
|
|
sp_digit a0[9];
|
|
sp_digit a1[9];
|
|
sp_digit a2[9];
|
|
(void)sp_4096_add_9(a0, a, &a[9]);
|
|
sp_4096_norm_9(a0);
|
|
(void)sp_4096_add_9(a1, &a[9], &a[18]);
|
|
sp_4096_norm_9(a1);
|
|
(void)sp_4096_add_9(a2, a0, &a[18]);
|
|
sp_4096_norm_9(a2);
|
|
sp_4096_sqr_9(p0, a);
|
|
sp_4096_sqr_9(p2, &a[9]);
|
|
sp_4096_sqr_9(p4, &a[18]);
|
|
sp_4096_sqr_9(p1, a0);
|
|
sp_4096_sqr_9(p3, a1);
|
|
sp_4096_sqr_9(p5, a2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*27U);
|
|
(void)sp_4096_sub_18(t0, p3, p2);
|
|
(void)sp_4096_sub_18(t1, p1, p2);
|
|
(void)sp_4096_sub_18(t2, p5, t0);
|
|
(void)sp_4096_sub_18(t2, t2, t1);
|
|
sp_4096_norm_18(t2);
|
|
(void)sp_4096_sub_18(t0, t0, p4);
|
|
sp_4096_norm_18(t0);
|
|
(void)sp_4096_sub_18(t1, t1, p0);
|
|
sp_4096_norm_18(t1);
|
|
(void)sp_4096_add_18(r, r, p0);
|
|
(void)sp_4096_add_18(&r[9], &r[9], t1);
|
|
(void)sp_4096_add_18(&r[18], &r[18], t2);
|
|
(void)sp_4096_add_18(&r[27], &r[27], t0);
|
|
(void)sp_4096_add_18(&r[36], &r[36], p4);
|
|
sp_4096_norm_54(r);
|
|
}
|
|
|
|
/* Square a into r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_sqr_81(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit p0[54];
|
|
sp_digit p1[54];
|
|
sp_digit p2[54];
|
|
sp_digit p3[54];
|
|
sp_digit p4[54];
|
|
sp_digit p5[54];
|
|
sp_digit t0[54];
|
|
sp_digit t1[54];
|
|
sp_digit t2[54];
|
|
sp_digit a0[27];
|
|
sp_digit a1[27];
|
|
sp_digit a2[27];
|
|
(void)sp_4096_add_27(a0, a, &a[27]);
|
|
sp_4096_norm_27(a0);
|
|
(void)sp_4096_add_27(a1, &a[27], &a[54]);
|
|
sp_4096_norm_27(a1);
|
|
(void)sp_4096_add_27(a2, a0, &a[54]);
|
|
sp_4096_norm_27(a2);
|
|
sp_4096_sqr_27(p0, a);
|
|
sp_4096_sqr_27(p2, &a[27]);
|
|
sp_4096_sqr_27(p4, &a[54]);
|
|
sp_4096_sqr_27(p1, a0);
|
|
sp_4096_sqr_27(p3, a1);
|
|
sp_4096_sqr_27(p5, a2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*81U);
|
|
(void)sp_4096_sub_54(t0, p3, p2);
|
|
(void)sp_4096_sub_54(t1, p1, p2);
|
|
(void)sp_4096_sub_54(t2, p5, t0);
|
|
(void)sp_4096_sub_54(t2, t2, t1);
|
|
sp_4096_norm_54(t2);
|
|
(void)sp_4096_sub_54(t0, t0, p4);
|
|
sp_4096_norm_54(t0);
|
|
(void)sp_4096_sub_54(t1, t1, p0);
|
|
sp_4096_norm_54(t1);
|
|
(void)sp_4096_add_54(r, r, p0);
|
|
(void)sp_4096_add_54(&r[27], &r[27], t1);
|
|
(void)sp_4096_add_54(&r[54], &r[54], t2);
|
|
(void)sp_4096_add_54(&r[81], &r[81], t0);
|
|
(void)sp_4096_add_54(&r[108], &r[108], p4);
|
|
sp_4096_norm_162(r);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_sqr_162(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[162];
|
|
sp_digit* a1 = z1;
|
|
sp_digit* z2 = r + 162;
|
|
(void)sp_4096_add_81(a1, a, &a[81]);
|
|
sp_4096_norm_81(a1);
|
|
sp_4096_sqr_81(z2, &a[81]);
|
|
sp_4096_sqr_81(z0, a);
|
|
sp_4096_sqr_81(z1, a1);
|
|
(void)sp_4096_sub_162(z1, z1, z2);
|
|
(void)sp_4096_sub_162(z1, z1, z0);
|
|
(void)sp_4096_add_162(r + 81, r + 81, z1);
|
|
sp_4096_norm_324(r);
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
/* Caclulate the bottom digit of -1/a mod 2^n.
|
|
*
|
|
* a A single precision number.
|
|
* rho Bottom word of inverse.
|
|
*/
|
|
static void sp_4096_mont_setup(const sp_digit* a, sp_digit* rho)
|
|
{
|
|
sp_digit x;
|
|
sp_digit b;
|
|
|
|
b = a[0];
|
|
x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**8 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**16 */
|
|
x *= 2 - b * x; /* here x*a==1 mod 2**32 */
|
|
x &= 0x3ffffff;
|
|
|
|
/* rho = -1/m mod b */
|
|
*rho = ((sp_digit)1 << 26) - x;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_d_162(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 160; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
t += tb * a[160];
|
|
r[160] = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
t += tb * a[161];
|
|
r[161] = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[162] = (sp_digit)(t & 0x3ffffff);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)
|
|
#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D)
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_4096_sub_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[80] = a[80] - b[80];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 4096 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_4096_mont_norm_81(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i = 0; i < 72; i += 8) {
|
|
r[i + 0] = 0x3ffffff;
|
|
r[i + 1] = 0x3ffffff;
|
|
r[i + 2] = 0x3ffffff;
|
|
r[i + 3] = 0x3ffffff;
|
|
r[i + 4] = 0x3ffffff;
|
|
r[i + 5] = 0x3ffffff;
|
|
r[i + 6] = 0x3ffffff;
|
|
r[i + 7] = 0x3ffffff;
|
|
}
|
|
r[72] = 0x3ffffff;
|
|
r[73] = 0x3ffffff;
|
|
r[74] = 0x3ffffff;
|
|
r[75] = 0x3ffffff;
|
|
r[76] = 0x3ffffff;
|
|
r[77] = 0x3ffffff;
|
|
r[78] = 0xfffffL;
|
|
r[79] = 0;
|
|
r[80] = 0;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_4096_sub_81(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_4096_cmp_81(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
r |= (a[80] - b[80]) & (0 - (sp_digit)1);
|
|
for (i = 72; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 25);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_sub_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
r[80] = a[80] - (b[80] & m);
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_add_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 81; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x3ffffff;
|
|
t >>= 26;
|
|
}
|
|
r[81] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 80; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0x3ffffff;
|
|
t[1] += t[0] >> 26;
|
|
r[i+1] = t[1] & 0x3ffffff;
|
|
t[2] += t[1] >> 26;
|
|
r[i+2] = t[2] & 0x3ffffff;
|
|
t[3] += t[2] >> 26;
|
|
r[i+3] = t[3] & 0x3ffffff;
|
|
t[4] += t[3] >> 26;
|
|
r[i+4] = t[4] & 0x3ffffff;
|
|
t[5] += t[4] >> 26;
|
|
r[i+5] = t[5] & 0x3ffffff;
|
|
t[6] += t[5] >> 26;
|
|
r[i+6] = t[6] & 0x3ffffff;
|
|
t[7] += t[6] >> 26;
|
|
r[i+7] = t[7] & 0x3ffffff;
|
|
t[0] = t[7] >> 26;
|
|
}
|
|
t[0] += (tb * a[80]) + r[80];
|
|
r[80] = t[0] & 0x3ffffff;
|
|
r[81] += (sp_digit)(t[0] >> 26);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 2048 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_4096_mont_shift_81(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[78] >> 20;
|
|
n += ((sp_int64)a[79]) << 6;
|
|
for (i = 0; i < 72; i += 8) {
|
|
r[i + 0] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 80]) << 6;
|
|
r[i + 1] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 81]) << 6;
|
|
r[i + 2] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 82]) << 6;
|
|
r[i + 3] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 83]) << 6;
|
|
r[i + 4] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 84]) << 6;
|
|
r[i + 5] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 85]) << 6;
|
|
r[i + 6] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 86]) << 6;
|
|
r[i + 7] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 87]) << 6;
|
|
}
|
|
r[72] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[152]) << 6;
|
|
r[73] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[153]) << 6;
|
|
r[74] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[154]) << 6;
|
|
r[75] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[155]) << 6;
|
|
r[76] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[156]) << 6;
|
|
r[77] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[157]) << 6;
|
|
r[78] = (sp_digit)n;
|
|
XMEMSET(&r[79], 0, sizeof(*r) * 79U);
|
|
}
|
|
|
|
/* Reduce the number back to 4096 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_4096_mont_reduce_81(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_4096_norm_81(a + 79);
|
|
|
|
for (i=0; i<78; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
|
|
sp_4096_mul_add_81(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
|
|
sp_4096_mul_add_81(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
a[i] &= 0x3ffffff;
|
|
sp_4096_mont_shift_81(a, a);
|
|
over = a[78] - m[78];
|
|
sp_4096_cond_sub_81(a, a, m, ~((over - 1) >> 31));
|
|
sp_4096_norm_81(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_mul_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_mul_81(r, a, b);
|
|
sp_4096_mont_reduce_81(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_sqr_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_sqr_81(r, a);
|
|
sp_4096_mont_reduce_81(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_d_81(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
t += tb * a[80];
|
|
r[80] = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[81] = (sp_digit)(t & 0x3ffffff);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_add_81(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 80; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
r[80] = a[80] + (b[80] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_4096_rshift_81(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<80; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (26 - n)) & 0x3ffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (26 - n)) & 0x3ffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (26 - n)) & 0x3ffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (26 - n)) & 0x3ffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (26 - n)) & 0x3ffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (26 - n)) & 0x3ffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (26 - n)) & 0x3ffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (26 - n)) & 0x3ffffff);
|
|
}
|
|
r[80] = a[80] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_4096_div_word_81(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 26);
|
|
sp_digit t0 = (sp_digit)(d & 0x3ffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 24; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 25) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 26);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 52) - (sp_digit)(d >> 52);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 11) + 1;
|
|
|
|
t = (sp_digit)(d >> 22);
|
|
t = (t / dv) << 11;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 7);
|
|
t = t / (dv << 4);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_4096_word_div_word_81(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_div_81(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 81 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 81 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 162 + 1;
|
|
sd = t2 + 81 + 1;
|
|
|
|
sp_4096_mul_d_81(sd, d, (sp_digit)1 << 6);
|
|
sp_4096_mul_d_162(t1, a, (sp_digit)1 << 6);
|
|
dv = sd[78];
|
|
t1[79 + 79] += t1[79 + 79 - 1] >> 26;
|
|
t1[79 + 79 - 1] &= 0x3ffffff;
|
|
for (i=79; i>=0; i--) {
|
|
r1 = sp_4096_div_word_81(t1[79 + i], t1[79 + i - 1], dv);
|
|
|
|
sp_4096_mul_d_81(t2, sd, r1);
|
|
(void)sp_4096_sub_81(&t1[i], &t1[i], t2);
|
|
sp_4096_norm_79(&t1[i]);
|
|
t1[79 + i] += t1[79 + i - 1] >> 26;
|
|
t1[79 + i - 1] &= 0x3ffffff;
|
|
r1 = sp_4096_div_word_81(-t1[79 + i], -t1[79 + i - 1], dv);
|
|
r1 -= t1[79 + i];
|
|
sp_4096_mul_d_81(t2, sd, r1);
|
|
(void)sp_4096_add_81(&t1[i], &t1[i], t2);
|
|
t1[79 + i] += t1[79 + i - 1] >> 26;
|
|
t1[79 + i - 1] &= 0x3ffffff;
|
|
}
|
|
t1[79 - 1] += t1[79 - 2] >> 26;
|
|
t1[79 - 2] &= 0x3ffffff;
|
|
r1 = sp_4096_word_div_word_81(t1[79 - 1], dv);
|
|
|
|
sp_4096_mul_d_81(t2, sd, r1);
|
|
sp_4096_sub_81(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 162U);
|
|
for (i=0; i<78; i++) {
|
|
r[i+1] += r[i] >> 26;
|
|
r[i] &= 0x3ffffff;
|
|
}
|
|
sp_4096_cond_add_81(r, r, sd, r[78] >> 31);
|
|
|
|
sp_4096_norm_79(r);
|
|
sp_4096_rshift_81(r, r, 6);
|
|
r[79] = 0;
|
|
r[80] = 0;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_mod_81(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_4096_div_81(a, m, NULL, r);
|
|
}
|
|
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_4096_mod_exp_81(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 162];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 81 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 81 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 81U * 2U);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_81(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_81(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 81U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_81(t[1], t[1], norm);
|
|
err = sp_4096_mod_81(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 26;
|
|
c = bits % 26;
|
|
n = e[i--] << (26 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 26;
|
|
}
|
|
|
|
y = (int)((n >> 25) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_81(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 81 * 2);
|
|
sp_4096_mont_sqr_81(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 81 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_81(t[0], m, mp);
|
|
n = sp_4096_cmp_81(t[0], m);
|
|
sp_4096_cond_sub_81(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 81 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 162];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 81 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 81 * 2);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_81(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_81(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_81(t[1], t[1], norm);
|
|
err = sp_4096_mod_81(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_81(t[1], a, norm);
|
|
err = sp_4096_mod_81(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 26;
|
|
c = bits % 26;
|
|
n = e[i--] << (26 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 26;
|
|
}
|
|
|
|
y = (int)((n >> 25) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_81(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 81 * 2);
|
|
sp_4096_mont_sqr_81(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 81 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_81(t[0], m, mp);
|
|
n = sp_4096_cmp_81(t[0], m);
|
|
sp_4096_cond_sub_81(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 81 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(32 * 162) + 162];
|
|
#endif
|
|
sp_digit* t[32];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((32 * 162) + 162), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<32; i++)
|
|
t[i] = td + i * 162;
|
|
rt = td + 5184;
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_81(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_81(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_81(t[1], t[1], norm);
|
|
err = sp_4096_mod_81(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_81(t[1], a, norm);
|
|
err = sp_4096_mod_81(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mont_sqr_81(t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_mul_81(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_sqr_81(t[ 4], t[ 2], m, mp);
|
|
sp_4096_mont_mul_81(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_4096_mont_sqr_81(t[ 6], t[ 3], m, mp);
|
|
sp_4096_mont_mul_81(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_4096_mont_sqr_81(t[ 8], t[ 4], m, mp);
|
|
sp_4096_mont_mul_81(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_4096_mont_sqr_81(t[10], t[ 5], m, mp);
|
|
sp_4096_mont_mul_81(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_4096_mont_sqr_81(t[12], t[ 6], m, mp);
|
|
sp_4096_mont_mul_81(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_4096_mont_sqr_81(t[14], t[ 7], m, mp);
|
|
sp_4096_mont_mul_81(t[15], t[ 8], t[ 7], m, mp);
|
|
sp_4096_mont_sqr_81(t[16], t[ 8], m, mp);
|
|
sp_4096_mont_mul_81(t[17], t[ 9], t[ 8], m, mp);
|
|
sp_4096_mont_sqr_81(t[18], t[ 9], m, mp);
|
|
sp_4096_mont_mul_81(t[19], t[10], t[ 9], m, mp);
|
|
sp_4096_mont_sqr_81(t[20], t[10], m, mp);
|
|
sp_4096_mont_mul_81(t[21], t[11], t[10], m, mp);
|
|
sp_4096_mont_sqr_81(t[22], t[11], m, mp);
|
|
sp_4096_mont_mul_81(t[23], t[12], t[11], m, mp);
|
|
sp_4096_mont_sqr_81(t[24], t[12], m, mp);
|
|
sp_4096_mont_mul_81(t[25], t[13], t[12], m, mp);
|
|
sp_4096_mont_sqr_81(t[26], t[13], m, mp);
|
|
sp_4096_mont_mul_81(t[27], t[14], t[13], m, mp);
|
|
sp_4096_mont_sqr_81(t[28], t[14], m, mp);
|
|
sp_4096_mont_mul_81(t[29], t[15], t[14], m, mp);
|
|
sp_4096_mont_sqr_81(t[30], t[15], m, mp);
|
|
sp_4096_mont_mul_81(t[31], t[16], t[15], m, mp);
|
|
|
|
bits = ((bits + 4) / 5) * 5;
|
|
i = ((bits + 25) / 26) - 1;
|
|
c = bits % 26;
|
|
if (c == 0) {
|
|
c = 26;
|
|
}
|
|
if (i < 81) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 5) {
|
|
n |= e[i--] << (6 - c);
|
|
c += 26;
|
|
}
|
|
y = (int)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 162);
|
|
while ((i >= 0) || (c >= 5)) {
|
|
if (c >= 5) {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c -= 5;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 6;
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n <<= 5;
|
|
c = 21;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 27) & 0x1f);
|
|
n = e[i--] << 6;
|
|
c = 5 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 26 - c;
|
|
}
|
|
|
|
sp_4096_mont_sqr_81(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_81(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_81(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_81(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_81(rt, rt, m, mp);
|
|
|
|
sp_4096_mont_mul_81(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_4096_mont_reduce_81(rt, m, mp);
|
|
n = sp_4096_cmp_81(rt, m);
|
|
sp_4096_cond_sub_81(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 162);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_RSA & !SP_RSA_PRIVATE_EXP_D */
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH) & !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
|
|
/* r = 2^n mod m where n is the number of bits to reduce by.
|
|
* Given m must be 4096 bits, just need to subtract.
|
|
*
|
|
* r A single precision number.
|
|
* m A single precision number.
|
|
*/
|
|
static void sp_4096_mont_norm_162(sp_digit* r, const sp_digit* m)
|
|
{
|
|
/* Set r = 2^n - 1. */
|
|
int i;
|
|
|
|
for (i = 0; i < 152; i += 8) {
|
|
r[i + 0] = 0x3ffffff;
|
|
r[i + 1] = 0x3ffffff;
|
|
r[i + 2] = 0x3ffffff;
|
|
r[i + 3] = 0x3ffffff;
|
|
r[i + 4] = 0x3ffffff;
|
|
r[i + 5] = 0x3ffffff;
|
|
r[i + 6] = 0x3ffffff;
|
|
r[i + 7] = 0x3ffffff;
|
|
}
|
|
r[152] = 0x3ffffff;
|
|
r[153] = 0x3ffffff;
|
|
r[154] = 0x3ffffff;
|
|
r[155] = 0x3ffffff;
|
|
r[156] = 0x3ffffff;
|
|
r[157] = 0x3fffL;
|
|
r[158] = 0;
|
|
r[159] = 0;
|
|
r[160] = 0;
|
|
r[161] = 0;
|
|
|
|
/* r = (2^n - 1) mod n */
|
|
(void)sp_4096_sub_162(r, r, m);
|
|
|
|
/* Add one so r = 2^n mod m */
|
|
r[0] += 1;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_4096_cmp_162(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
int i;
|
|
|
|
r |= (a[161] - b[161]) & (0 - (sp_digit)1);
|
|
r |= (a[160] - b[160]) & ~(((sp_digit)0 - r) >> 25);
|
|
for (i = 152; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 25);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_sub_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 160; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
r[160] = a[160] - (b[160] & m);
|
|
r[161] = a[161] - (b[161] & m);
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_add_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 162; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x3ffffff;
|
|
t >>= 26;
|
|
}
|
|
r[162] += (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 160; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0x3ffffff;
|
|
t[1] += t[0] >> 26;
|
|
r[i+1] = t[1] & 0x3ffffff;
|
|
t[2] += t[1] >> 26;
|
|
r[i+2] = t[2] & 0x3ffffff;
|
|
t[3] += t[2] >> 26;
|
|
r[i+3] = t[3] & 0x3ffffff;
|
|
t[4] += t[3] >> 26;
|
|
r[i+4] = t[4] & 0x3ffffff;
|
|
t[5] += t[4] >> 26;
|
|
r[i+5] = t[5] & 0x3ffffff;
|
|
t[6] += t[5] >> 26;
|
|
r[i+6] = t[6] & 0x3ffffff;
|
|
t[7] += t[6] >> 26;
|
|
r[i+7] = t[7] & 0x3ffffff;
|
|
t[0] = t[7] >> 26;
|
|
}
|
|
t[0] += (tb * a[160]) + r[160];
|
|
t[1] = (tb * a[161]) + r[161];
|
|
r[160] = t[0] & 0x3ffffff;
|
|
t[1] += t[0] >> 26;
|
|
r[161] = t[1] & 0x3ffffff;
|
|
r[162] += (sp_digit)(t[1] >> 26);
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Shift the result in the high 4096 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_4096_mont_shift_162(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
sp_int64 n = a[157] >> 14;
|
|
n += ((sp_int64)a[158]) << 12;
|
|
for (i = 0; i < 152; i += 8) {
|
|
r[i + 0] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 159]) << 12;
|
|
r[i + 1] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 160]) << 12;
|
|
r[i + 2] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 161]) << 12;
|
|
r[i + 3] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 162]) << 12;
|
|
r[i + 4] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 163]) << 12;
|
|
r[i + 5] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 164]) << 12;
|
|
r[i + 6] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 165]) << 12;
|
|
r[i + 7] = n & 0x3ffffff;
|
|
n >>= 26; n += ((sp_int64)a[i + 166]) << 12;
|
|
}
|
|
r[152] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[311]) << 12;
|
|
r[153] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[312]) << 12;
|
|
r[154] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[313]) << 12;
|
|
r[155] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[314]) << 12;
|
|
r[156] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[315]) << 12;
|
|
r[157] = (sp_digit)n;
|
|
XMEMSET(&r[158], 0, sizeof(*r) * 158U);
|
|
}
|
|
|
|
/* Reduce the number back to 4096 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_4096_mont_reduce_162(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_4096_norm_162(a + 158);
|
|
|
|
#ifdef WOLFSSL_SP_DH
|
|
if (mp != 1) {
|
|
for (i=0; i<157; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
|
|
sp_4096_mul_add_162(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3fffL;
|
|
sp_4096_mul_add_162(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
a[i] &= 0x3ffffff;
|
|
}
|
|
else {
|
|
for (i=0; i<157; i++) {
|
|
mu = a[i] & 0x3ffffff;
|
|
sp_4096_mul_add_162(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
}
|
|
mu = a[i] & 0x3fffL;
|
|
sp_4096_mul_add_162(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
a[i] &= 0x3ffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<157; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
|
|
sp_4096_mul_add_162(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3fffL;
|
|
sp_4096_mul_add_162(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
a[i] &= 0x3ffffff;
|
|
#endif
|
|
sp_4096_mont_shift_162(a, a);
|
|
over = a[157] - m[157];
|
|
sp_4096_cond_sub_162(a, a, m, ~((over - 1) >> 31));
|
|
sp_4096_norm_162(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_mul_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_mul_162(r, a, b);
|
|
sp_4096_mont_reduce_162(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mont_sqr_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_4096_sqr_162(r, a);
|
|
sp_4096_mont_reduce_162(r, m, mp);
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_4096_mul_d_324(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 324; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[324] = (sp_digit)(t & 0x3ffffff);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_4096_cond_add_162(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 160; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
r[160] = a[160] + (b[160] & m);
|
|
r[161] = a[161] + (b[161] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_4096_rshift_162(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<160; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (26 - n)) & 0x3ffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (26 - n)) & 0x3ffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (26 - n)) & 0x3ffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (26 - n)) & 0x3ffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (26 - n)) & 0x3ffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (26 - n)) & 0x3ffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (26 - n)) & 0x3ffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (26 - n)) & 0x3ffffff);
|
|
}
|
|
r[160] = (a[160] >> n) | ((a[161] << (26 - n)) & 0x3ffffff);
|
|
r[161] = a[161] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_4096_div_word_162(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 26);
|
|
sp_digit t0 = (sp_digit)(d & 0x3ffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 24; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 25) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 26);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 52) - (sp_digit)(d >> 52);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 26) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 11) + 1;
|
|
|
|
t = (sp_digit)(d >> 22);
|
|
t = (t / dv) << 11;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 7);
|
|
t = t / (dv << 4);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_4096_word_div_word_162(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_div_162(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 162 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 162 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 324 + 1;
|
|
sd = t2 + 162 + 1;
|
|
|
|
sp_4096_mul_d_162(sd, d, (sp_digit)1 << 12);
|
|
sp_4096_mul_d_324(t1, a, (sp_digit)1 << 12);
|
|
dv = sd[157];
|
|
t1[158 + 158] += t1[158 + 158 - 1] >> 26;
|
|
t1[158 + 158 - 1] &= 0x3ffffff;
|
|
for (i=158; i>=0; i--) {
|
|
r1 = sp_4096_div_word_162(t1[158 + i], t1[158 + i - 1], dv);
|
|
|
|
sp_4096_mul_d_162(t2, sd, r1);
|
|
(void)sp_4096_sub_162(&t1[i], &t1[i], t2);
|
|
sp_4096_norm_158(&t1[i]);
|
|
t1[158 + i] += t1[158 + i - 1] >> 26;
|
|
t1[158 + i - 1] &= 0x3ffffff;
|
|
r1 = sp_4096_div_word_162(-t1[158 + i], -t1[158 + i - 1], dv);
|
|
r1 -= t1[158 + i];
|
|
sp_4096_mul_d_162(t2, sd, r1);
|
|
(void)sp_4096_add_162(&t1[i], &t1[i], t2);
|
|
t1[158 + i] += t1[158 + i - 1] >> 26;
|
|
t1[158 + i - 1] &= 0x3ffffff;
|
|
}
|
|
t1[158 - 1] += t1[158 - 2] >> 26;
|
|
t1[158 - 2] &= 0x3ffffff;
|
|
r1 = sp_4096_word_div_word_162(t1[158 - 1], dv);
|
|
|
|
sp_4096_mul_d_162(t2, sd, r1);
|
|
sp_4096_sub_162(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 324U);
|
|
for (i=0; i<157; i++) {
|
|
r[i+1] += r[i] >> 26;
|
|
r[i] &= 0x3ffffff;
|
|
}
|
|
sp_4096_cond_add_162(r, r, sd, r[157] >> 31);
|
|
|
|
sp_4096_norm_158(r);
|
|
sp_4096_rshift_162(r, r, 12);
|
|
r[158] = 0;
|
|
r[159] = 0;
|
|
r[160] = 0;
|
|
r[161] = 0;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_4096_mod_162(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_4096_div_162(a, m, NULL, r);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH)
|
|
#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \
|
|
defined(WOLFSSL_HAVE_SP_DH)
|
|
/* Modular exponentiate a to the e mod m. (r = a^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* a A single precision number being exponentiated.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even or exponent is 0.
|
|
*/
|
|
static int sp_4096_mod_exp_162(sp_digit* r, const sp_digit* a, const sp_digit* e,
|
|
int bits, const sp_digit* m, int reduceA)
|
|
{
|
|
#if defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_FAST_MODEXP)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 324];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 162 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 162 * 2);
|
|
XMEMSET(t[i], 0, sizeof(sp_digit) * 162U * 2U);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_162(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_162(t[1], a, m);
|
|
}
|
|
else {
|
|
XMEMCPY(t[1], a, sizeof(sp_digit) * 162U);
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_162(t[1], t[1], norm);
|
|
err = sp_4096_mod_162(t[1], t[1], m);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 26;
|
|
c = bits % 26;
|
|
n = e[i--] << (26 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 26;
|
|
}
|
|
|
|
y = (int)((n >> 25) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_162(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 162 * 2);
|
|
sp_4096_mont_sqr_162(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 162 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_162(t[0], m, mp);
|
|
n = sp_4096_cmp_162(t[0], m);
|
|
sp_4096_cond_sub_162(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 162 * 2);
|
|
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#elif !defined(WC_NO_CACHE_RESISTANT)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[3 * 324];
|
|
#endif
|
|
sp_digit* t[3] = {0, 0, 0};
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 3 * 162 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<3; i++) {
|
|
t[i] = td + (i * 162 * 2);
|
|
}
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_162(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_162(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_162(t[1], t[1], norm);
|
|
err = sp_4096_mod_162(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_162(t[1], a, norm);
|
|
err = sp_4096_mod_162(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
i = bits / 26;
|
|
c = bits % 26;
|
|
n = e[i--] << (26 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1) {
|
|
break;
|
|
}
|
|
|
|
n = e[i--];
|
|
c = 26;
|
|
}
|
|
|
|
y = (int)((n >> 25) & 1);
|
|
n <<= 1;
|
|
|
|
sp_4096_mont_mul_162(t[y^1], t[0], t[1], m, mp);
|
|
|
|
XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])),
|
|
sizeof(*t[2]) * 162 * 2);
|
|
sp_4096_mont_sqr_162(t[2], t[2], m, mp);
|
|
XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) +
|
|
((size_t)t[1] & addr_mask[y])), t[2],
|
|
sizeof(*t[2]) * 162 * 2);
|
|
}
|
|
|
|
sp_4096_mont_reduce_162(t[0], m, mp);
|
|
n = sp_4096_cmp_162(t[0], m);
|
|
sp_4096_cond_sub_162(t[0], t[0], m, ~(n >> 31));
|
|
XMEMCPY(r, t[0], sizeof(*r) * 162 * 2);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[(16 * 324) + 324];
|
|
#endif
|
|
sp_digit* t[16];
|
|
sp_digit* rt = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * ((16 * 324) + 324), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
for (i=0; i<16; i++)
|
|
t[i] = td + i * 324;
|
|
rt = td + 5184;
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_162(norm, m);
|
|
|
|
if (reduceA != 0) {
|
|
err = sp_4096_mod_162(t[1], a, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_162(t[1], t[1], norm);
|
|
err = sp_4096_mod_162(t[1], t[1], m);
|
|
}
|
|
}
|
|
else {
|
|
sp_4096_mul_162(t[1], a, norm);
|
|
err = sp_4096_mod_162(t[1], t[1], m);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mont_sqr_162(t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_mul_162(t[ 3], t[ 2], t[ 1], m, mp);
|
|
sp_4096_mont_sqr_162(t[ 4], t[ 2], m, mp);
|
|
sp_4096_mont_mul_162(t[ 5], t[ 3], t[ 2], m, mp);
|
|
sp_4096_mont_sqr_162(t[ 6], t[ 3], m, mp);
|
|
sp_4096_mont_mul_162(t[ 7], t[ 4], t[ 3], m, mp);
|
|
sp_4096_mont_sqr_162(t[ 8], t[ 4], m, mp);
|
|
sp_4096_mont_mul_162(t[ 9], t[ 5], t[ 4], m, mp);
|
|
sp_4096_mont_sqr_162(t[10], t[ 5], m, mp);
|
|
sp_4096_mont_mul_162(t[11], t[ 6], t[ 5], m, mp);
|
|
sp_4096_mont_sqr_162(t[12], t[ 6], m, mp);
|
|
sp_4096_mont_mul_162(t[13], t[ 7], t[ 6], m, mp);
|
|
sp_4096_mont_sqr_162(t[14], t[ 7], m, mp);
|
|
sp_4096_mont_mul_162(t[15], t[ 8], t[ 7], m, mp);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 25) / 26) - 1;
|
|
c = bits % 26;
|
|
if (c == 0) {
|
|
c = 26;
|
|
}
|
|
if (i < 162) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (6 - c);
|
|
c += 26;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
XMEMCPY(rt, t[y], sizeof(sp_digit) * 324);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 6;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 22;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 6;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 26 - c;
|
|
}
|
|
|
|
sp_4096_mont_sqr_162(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_162(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_162(rt, rt, m, mp);
|
|
sp_4096_mont_sqr_162(rt, rt, m, mp);
|
|
|
|
sp_4096_mont_mul_162(rt, rt, t[y], m, mp);
|
|
}
|
|
|
|
sp_4096_mont_reduce_162(rt, m, mp);
|
|
n = sp_4096_cmp_162(rt, m);
|
|
sp_4096_cond_sub_162(rt, rt, m, ~(n >> 31));
|
|
XMEMCPY(r, rt, sizeof(sp_digit) * 324);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) || */
|
|
/* WOLFSSL_HAVE_SP_DH */
|
|
|
|
#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */
|
|
#ifdef WOLFSSL_HAVE_SP_RSA
|
|
/* RSA public key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* em Public exponent.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 512 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPublic_4096(const byte* in, word32 inLen, const mp_int* em,
|
|
const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[162 * 5];
|
|
#endif
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* norm = NULL;
|
|
sp_digit e[1] = {0};
|
|
sp_digit mp = 0;
|
|
int i;
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 26) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
r = a + 162 * 2;
|
|
m = r + 162 * 2;
|
|
norm = r;
|
|
|
|
sp_4096_from_bin(a, 162, in, inLen);
|
|
#if DIGIT_BIT >= 26
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(m, 162, mm);
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_162(norm, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_162(a, a, norm);
|
|
err = sp_4096_mod_162(a, a, m);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
for (i=25; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 162 * 2);
|
|
for (i--; i>=0; i--) {
|
|
sp_4096_mont_sqr_162(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_4096_mont_mul_162(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_4096_mont_reduce_162(r, m, mp);
|
|
mp = sp_4096_cmp_162(r, m);
|
|
sp_4096_cond_sub_162(r, r, m, ~(mp >> 31));
|
|
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[162 * 5];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit e[1] = {0};
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(em) > 26) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 5, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d;
|
|
r = a + 162 * 2;
|
|
m = r + 162 * 2;
|
|
|
|
sp_4096_from_bin(a, 162, in, inLen);
|
|
#if DIGIT_BIT >= 26
|
|
e[0] = (sp_digit)em->dp[0];
|
|
#else
|
|
e[0] = (sp_digit)em->dp[0];
|
|
if (em->used > 1) {
|
|
e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT;
|
|
}
|
|
#endif
|
|
if (e[0] == 0) {
|
|
err = MP_EXPTMOD_E;
|
|
}
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(m, 162, mm);
|
|
|
|
if (e[0] == 0x3) {
|
|
sp_4096_sqr_162(r, a);
|
|
err = sp_4096_mod_162(r, r, m);
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_162(r, a, r);
|
|
err = sp_4096_mod_162(r, r, m);
|
|
}
|
|
}
|
|
else {
|
|
sp_digit* norm = r;
|
|
int i;
|
|
sp_digit mp;
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_162(norm, m);
|
|
|
|
sp_4096_mul_162(a, a, norm);
|
|
err = sp_4096_mod_162(a, a, m);
|
|
|
|
if (err == MP_OKAY) {
|
|
for (i=25; i>=0; i--) {
|
|
if ((e[0] >> i) != 0) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
XMEMCPY(r, a, sizeof(sp_digit) * 324U);
|
|
for (i--; i>=0; i--) {
|
|
sp_4096_mont_sqr_162(r, r, m, mp);
|
|
|
|
if (((e[0] >> i) & 1) == 1) {
|
|
sp_4096_mont_mul_162(r, r, a, m, mp);
|
|
}
|
|
}
|
|
sp_4096_mont_reduce_162(r, m, mp);
|
|
mp = sp_4096_cmp_162(r, m);
|
|
sp_4096_cond_sub_162(r, r, m, ~(mp >> 31));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifndef WOLFSSL_RSA_PUBLIC_ONLY
|
|
#if !defined(SP_RSA_PRIVATE_EXP_D) && !defined(RSA_LOW_MEM)
|
|
#endif /* !SP_RSA_PRIVATE_EXP_D & !RSA_LOW_MEM */
|
|
/* RSA private key operation.
|
|
*
|
|
* in Array of bytes representing the number to exponentiate, base.
|
|
* inLen Number of bytes in base.
|
|
* dm Private exponent.
|
|
* pm First prime.
|
|
* qm Second prime.
|
|
* dpm First prime's CRT exponent.
|
|
* dqm Second prime's CRT exponent.
|
|
* qim Inverse of second prime mod p.
|
|
* mm Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 512 bytes long.
|
|
* outLen Number of bytes in result.
|
|
* returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when
|
|
* an array is too long and MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_RsaPrivate_4096(const byte* in, word32 inLen, const mp_int* dm,
|
|
const mp_int* pm, const mp_int* qm, const mp_int* dpm, const mp_int* dqm,
|
|
const mp_int* qim, const mp_int* mm, byte* out, word32* outLen)
|
|
{
|
|
#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM)
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[162 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 162;
|
|
m = a + 324;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 162, in, inLen);
|
|
sp_4096_from_mp(d, 162, dm);
|
|
sp_4096_from_mp(m, 162, mm);
|
|
err = sp_4096_mod_exp_162(r, a, d, 4096, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 162);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* d = NULL;
|
|
#else
|
|
sp_digit d[162 * 4];
|
|
#endif
|
|
sp_digit* a = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)pm;
|
|
(void)qm;
|
|
(void)dpm;
|
|
(void)dqm;
|
|
(void)qim;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (mp_count_bits(dm) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (d == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a = d + 162;
|
|
m = a + 324;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 162, in, inLen);
|
|
sp_4096_from_mp(d, 162, dm);
|
|
sp_4096_from_mp(m, 162, mm);
|
|
err = sp_4096_mod_exp_162(r, a, d, 4096, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (d != NULL)
|
|
#endif
|
|
{
|
|
/* only "a" and "r" are sensitive and need zeroized (same pointer) */
|
|
if (a != NULL)
|
|
ForceZero(a, sizeof(sp_digit) * 162);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(d, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#else
|
|
#if defined(WOLFSSL_SP_SMALL)
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[81 * 8];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 512) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 81 * 8, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
p = a + 162;
|
|
qi = dq = dp = p + 81;
|
|
tmpa = qi + 81;
|
|
tmpb = tmpa + 162;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 162, in, inLen);
|
|
sp_4096_from_mp(p, 81, pm);
|
|
sp_4096_from_mp(dp, 81, dpm);
|
|
err = sp_4096_mod_exp_81(tmpa, a, dp, 2048, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(p, 81, qm);
|
|
sp_4096_from_mp(dq, 81, dqm);
|
|
err = sp_4096_mod_exp_81(tmpb, a, dq, 2048, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(p, 81, pm);
|
|
(void)sp_4096_sub_81(tmpa, tmpa, tmpb);
|
|
sp_4096_norm_79(tmpa);
|
|
sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
|
|
sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
|
|
sp_4096_norm_81(tmpa);
|
|
|
|
sp_4096_from_mp(qi, 81, qim);
|
|
sp_4096_mul_81(tmpa, tmpa, qi);
|
|
err = sp_4096_mod_81(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_from_mp(p, 81, qm);
|
|
sp_4096_mul_81(tmpa, p, tmpa);
|
|
(void)sp_4096_add_162(r, tmpb, tmpa);
|
|
sp_4096_norm_162(r);
|
|
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 81 * 8);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* a = NULL;
|
|
#else
|
|
sp_digit a[81 * 13];
|
|
#endif
|
|
sp_digit* p = NULL;
|
|
sp_digit* q = NULL;
|
|
sp_digit* dp = NULL;
|
|
sp_digit* dq = NULL;
|
|
sp_digit* qi = NULL;
|
|
sp_digit* tmpa = NULL;
|
|
sp_digit* tmpb = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)dm;
|
|
(void)mm;
|
|
|
|
if (*outLen < 512U) {
|
|
err = MP_TO_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (inLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mm) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(pm)) {
|
|
err = MP_VAL;
|
|
}
|
|
else if (mp_iseven(qm)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
a = (sp_digit*)XMALLOC(sizeof(sp_digit) * 81 * 13, NULL,
|
|
DYNAMIC_TYPE_RSA);
|
|
if (a == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = a + 162 * 2;
|
|
q = p + 81;
|
|
dp = q + 81;
|
|
dq = dp + 81;
|
|
qi = dq + 81;
|
|
tmpa = qi + 81;
|
|
tmpb = tmpa + 162;
|
|
r = a;
|
|
|
|
sp_4096_from_bin(a, 162, in, inLen);
|
|
sp_4096_from_mp(p, 81, pm);
|
|
sp_4096_from_mp(q, 81, qm);
|
|
sp_4096_from_mp(dp, 81, dpm);
|
|
sp_4096_from_mp(dq, 81, dqm);
|
|
sp_4096_from_mp(qi, 81, qim);
|
|
|
|
err = sp_4096_mod_exp_81(tmpa, a, dp, 2048, p, 1);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_4096_mod_exp_81(tmpb, a, dq, 2048, q, 1);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
(void)sp_4096_sub_81(tmpa, tmpa, tmpb);
|
|
sp_4096_norm_79(tmpa);
|
|
sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
|
|
sp_4096_cond_add_81(tmpa, tmpa, p, 0 - ((sp_int_digit)tmpa[78] >> 31));
|
|
sp_4096_norm_81(tmpa);
|
|
sp_4096_mul_81(tmpa, tmpa, qi);
|
|
err = sp_4096_mod_81(tmpa, tmpa, p);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_mul_81(tmpa, tmpa, q);
|
|
(void)sp_4096_add_162(r, tmpb, tmpa);
|
|
sp_4096_norm_162(r);
|
|
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (a != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(a, sizeof(sp_digit) * 81 * 13);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(a, NULL, DYNAMIC_TYPE_RSA);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */
|
|
}
|
|
|
|
#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */
|
|
#endif /* WOLFSSL_HAVE_SP_RSA */
|
|
#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \
|
|
!defined(WOLFSSL_RSA_PUBLIC_ONLY))
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_4096_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (4096 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 26
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 158);
|
|
r->used = 158;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 26
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 158; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 26) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 26 - s;
|
|
}
|
|
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 158; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 26 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 26 - s;
|
|
}
|
|
else {
|
|
s += 26;
|
|
}
|
|
}
|
|
r->used = (4096 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base. MP integer.
|
|
* exp Exponent. MP integer.
|
|
* mod Modulus. MP integer.
|
|
* res Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_4096(const mp_int* base, const mp_int* exp, const mp_int* mod,
|
|
mp_int* res)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[162 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 162 * 2;
|
|
m = e + 162;
|
|
r = b;
|
|
|
|
sp_4096_from_mp(b, 162, base);
|
|
sp_4096_from_mp(e, 162, exp);
|
|
sp_4096_from_mp(m, 162, mod);
|
|
|
|
err = sp_4096_mod_exp_162(r, b, e, mp_count_bits(exp), m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_4096_to_mp(r, res);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 162U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
return err;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[162 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
int err = MP_OKAY;
|
|
int expBits = mp_count_bits(exp);
|
|
|
|
if (mp_count_bits(base) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expBits > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL, DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 162 * 2;
|
|
m = e + 162;
|
|
r = b;
|
|
|
|
sp_4096_from_mp(b, 162, base);
|
|
sp_4096_from_mp(e, 162, exp);
|
|
sp_4096_from_mp(m, 162, mod);
|
|
|
|
err = sp_4096_mod_exp_162(r, b, e, expBits, m, 0);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_4096_to_mp(r, res);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 162U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#ifdef WOLFSSL_HAVE_SP_DH
|
|
|
|
#ifdef HAVE_FFDHE_4096
|
|
SP_NOINLINE static void sp_4096_lshift_162(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
sp_int_digit s;
|
|
sp_int_digit t;
|
|
|
|
s = (sp_int_digit)a[161];
|
|
r[162] = s >> (26U - n);
|
|
s = (sp_int_digit)(a[161]); t = (sp_int_digit)(a[160]);
|
|
r[161] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[160]); t = (sp_int_digit)(a[159]);
|
|
r[160] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[159]); t = (sp_int_digit)(a[158]);
|
|
r[159] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[158]); t = (sp_int_digit)(a[157]);
|
|
r[158] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[157]); t = (sp_int_digit)(a[156]);
|
|
r[157] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[156]); t = (sp_int_digit)(a[155]);
|
|
r[156] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[155]); t = (sp_int_digit)(a[154]);
|
|
r[155] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[154]); t = (sp_int_digit)(a[153]);
|
|
r[154] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[153]); t = (sp_int_digit)(a[152]);
|
|
r[153] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[152]); t = (sp_int_digit)(a[151]);
|
|
r[152] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[151]); t = (sp_int_digit)(a[150]);
|
|
r[151] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[150]); t = (sp_int_digit)(a[149]);
|
|
r[150] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[149]); t = (sp_int_digit)(a[148]);
|
|
r[149] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[148]); t = (sp_int_digit)(a[147]);
|
|
r[148] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[147]); t = (sp_int_digit)(a[146]);
|
|
r[147] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[146]); t = (sp_int_digit)(a[145]);
|
|
r[146] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[145]); t = (sp_int_digit)(a[144]);
|
|
r[145] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[144]); t = (sp_int_digit)(a[143]);
|
|
r[144] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[143]); t = (sp_int_digit)(a[142]);
|
|
r[143] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[142]); t = (sp_int_digit)(a[141]);
|
|
r[142] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[141]); t = (sp_int_digit)(a[140]);
|
|
r[141] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[140]); t = (sp_int_digit)(a[139]);
|
|
r[140] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[139]); t = (sp_int_digit)(a[138]);
|
|
r[139] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[138]); t = (sp_int_digit)(a[137]);
|
|
r[138] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[137]); t = (sp_int_digit)(a[136]);
|
|
r[137] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[136]); t = (sp_int_digit)(a[135]);
|
|
r[136] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[135]); t = (sp_int_digit)(a[134]);
|
|
r[135] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[134]); t = (sp_int_digit)(a[133]);
|
|
r[134] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[133]); t = (sp_int_digit)(a[132]);
|
|
r[133] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[132]); t = (sp_int_digit)(a[131]);
|
|
r[132] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[131]); t = (sp_int_digit)(a[130]);
|
|
r[131] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[130]); t = (sp_int_digit)(a[129]);
|
|
r[130] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[129]); t = (sp_int_digit)(a[128]);
|
|
r[129] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[128]); t = (sp_int_digit)(a[127]);
|
|
r[128] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[127]); t = (sp_int_digit)(a[126]);
|
|
r[127] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[126]); t = (sp_int_digit)(a[125]);
|
|
r[126] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[125]); t = (sp_int_digit)(a[124]);
|
|
r[125] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[124]); t = (sp_int_digit)(a[123]);
|
|
r[124] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[123]); t = (sp_int_digit)(a[122]);
|
|
r[123] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[122]); t = (sp_int_digit)(a[121]);
|
|
r[122] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[121]); t = (sp_int_digit)(a[120]);
|
|
r[121] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[120]); t = (sp_int_digit)(a[119]);
|
|
r[120] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[119]); t = (sp_int_digit)(a[118]);
|
|
r[119] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[118]); t = (sp_int_digit)(a[117]);
|
|
r[118] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[117]); t = (sp_int_digit)(a[116]);
|
|
r[117] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[116]); t = (sp_int_digit)(a[115]);
|
|
r[116] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[115]); t = (sp_int_digit)(a[114]);
|
|
r[115] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[114]); t = (sp_int_digit)(a[113]);
|
|
r[114] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[113]); t = (sp_int_digit)(a[112]);
|
|
r[113] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[112]); t = (sp_int_digit)(a[111]);
|
|
r[112] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[111]); t = (sp_int_digit)(a[110]);
|
|
r[111] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[110]); t = (sp_int_digit)(a[109]);
|
|
r[110] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[109]); t = (sp_int_digit)(a[108]);
|
|
r[109] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[108]); t = (sp_int_digit)(a[107]);
|
|
r[108] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[107]); t = (sp_int_digit)(a[106]);
|
|
r[107] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[106]); t = (sp_int_digit)(a[105]);
|
|
r[106] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[105]); t = (sp_int_digit)(a[104]);
|
|
r[105] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[104]); t = (sp_int_digit)(a[103]);
|
|
r[104] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[103]); t = (sp_int_digit)(a[102]);
|
|
r[103] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[102]); t = (sp_int_digit)(a[101]);
|
|
r[102] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[101]); t = (sp_int_digit)(a[100]);
|
|
r[101] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[100]); t = (sp_int_digit)(a[99]);
|
|
r[100] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[99]); t = (sp_int_digit)(a[98]);
|
|
r[99] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[98]); t = (sp_int_digit)(a[97]);
|
|
r[98] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[97]); t = (sp_int_digit)(a[96]);
|
|
r[97] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[96]); t = (sp_int_digit)(a[95]);
|
|
r[96] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[95]); t = (sp_int_digit)(a[94]);
|
|
r[95] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[94]); t = (sp_int_digit)(a[93]);
|
|
r[94] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[93]); t = (sp_int_digit)(a[92]);
|
|
r[93] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[92]); t = (sp_int_digit)(a[91]);
|
|
r[92] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[91]); t = (sp_int_digit)(a[90]);
|
|
r[91] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[90]); t = (sp_int_digit)(a[89]);
|
|
r[90] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[89]); t = (sp_int_digit)(a[88]);
|
|
r[89] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[88]); t = (sp_int_digit)(a[87]);
|
|
r[88] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[87]); t = (sp_int_digit)(a[86]);
|
|
r[87] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[86]); t = (sp_int_digit)(a[85]);
|
|
r[86] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[85]); t = (sp_int_digit)(a[84]);
|
|
r[85] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[84]); t = (sp_int_digit)(a[83]);
|
|
r[84] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[83]); t = (sp_int_digit)(a[82]);
|
|
r[83] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[82]); t = (sp_int_digit)(a[81]);
|
|
r[82] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[81]); t = (sp_int_digit)(a[80]);
|
|
r[81] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[80]); t = (sp_int_digit)(a[79]);
|
|
r[80] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[79]); t = (sp_int_digit)(a[78]);
|
|
r[79] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[78]); t = (sp_int_digit)(a[77]);
|
|
r[78] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[77]); t = (sp_int_digit)(a[76]);
|
|
r[77] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[76]); t = (sp_int_digit)(a[75]);
|
|
r[76] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[75]); t = (sp_int_digit)(a[74]);
|
|
r[75] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[74]); t = (sp_int_digit)(a[73]);
|
|
r[74] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[73]); t = (sp_int_digit)(a[72]);
|
|
r[73] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[72]); t = (sp_int_digit)(a[71]);
|
|
r[72] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[71]); t = (sp_int_digit)(a[70]);
|
|
r[71] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[70]); t = (sp_int_digit)(a[69]);
|
|
r[70] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[69]); t = (sp_int_digit)(a[68]);
|
|
r[69] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[68]); t = (sp_int_digit)(a[67]);
|
|
r[68] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[67]); t = (sp_int_digit)(a[66]);
|
|
r[67] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[66]); t = (sp_int_digit)(a[65]);
|
|
r[66] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[65]); t = (sp_int_digit)(a[64]);
|
|
r[65] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[64]); t = (sp_int_digit)(a[63]);
|
|
r[64] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[63]); t = (sp_int_digit)(a[62]);
|
|
r[63] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[62]); t = (sp_int_digit)(a[61]);
|
|
r[62] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[61]); t = (sp_int_digit)(a[60]);
|
|
r[61] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[60]); t = (sp_int_digit)(a[59]);
|
|
r[60] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[59]); t = (sp_int_digit)(a[58]);
|
|
r[59] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[58]); t = (sp_int_digit)(a[57]);
|
|
r[58] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[57]); t = (sp_int_digit)(a[56]);
|
|
r[57] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[56]); t = (sp_int_digit)(a[55]);
|
|
r[56] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[55]); t = (sp_int_digit)(a[54]);
|
|
r[55] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[54]); t = (sp_int_digit)(a[53]);
|
|
r[54] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[53]); t = (sp_int_digit)(a[52]);
|
|
r[53] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[52]); t = (sp_int_digit)(a[51]);
|
|
r[52] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[51]); t = (sp_int_digit)(a[50]);
|
|
r[51] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[50]); t = (sp_int_digit)(a[49]);
|
|
r[50] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[49]); t = (sp_int_digit)(a[48]);
|
|
r[49] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[48]); t = (sp_int_digit)(a[47]);
|
|
r[48] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[47]); t = (sp_int_digit)(a[46]);
|
|
r[47] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[46]); t = (sp_int_digit)(a[45]);
|
|
r[46] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[45]); t = (sp_int_digit)(a[44]);
|
|
r[45] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[44]); t = (sp_int_digit)(a[43]);
|
|
r[44] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[43]); t = (sp_int_digit)(a[42]);
|
|
r[43] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[42]); t = (sp_int_digit)(a[41]);
|
|
r[42] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
|
|
r[41] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
|
|
r[40] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
|
|
r[39] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
|
|
r[38] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
|
|
r[37] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
|
|
r[36] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
|
|
r[35] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
|
|
r[34] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
|
|
r[33] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
|
|
r[32] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
|
|
r[31] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
|
|
r[30] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
|
|
r[29] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
|
|
r[28] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
|
|
r[27] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
|
|
r[26] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
|
|
r[25] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
|
|
r[24] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
|
|
r[23] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
|
|
r[22] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
|
|
r[21] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
|
|
r[20] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
|
|
r[19] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
|
|
r[18] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
|
|
r[17] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
|
|
r[16] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
|
|
r[15] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
|
|
r[14] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
|
|
r[13] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
|
|
r[12] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
|
|
r[11] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
|
|
r[10] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
|
|
r[9] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
|
|
r[8] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
|
|
r[7] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
|
|
r[6] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
|
|
r[5] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
|
|
r[4] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
|
|
r[3] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
|
|
r[2] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
|
|
r[1] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
r[0] = (a[0] << n) & 0x3ffffff;
|
|
}
|
|
|
|
/* Modular exponentiate 2 to the e mod m. (r = 2^e mod m)
|
|
*
|
|
* r A single precision number that is the result of the operation.
|
|
* e A single precision number that is the exponent.
|
|
* bits The number of bits in the exponent.
|
|
* m A single precision number that is the modulus.
|
|
* returns 0 on success.
|
|
* returns MEMORY_E on dynamic memory allocation failure.
|
|
* returns MP_VAL when base is even.
|
|
*/
|
|
static int sp_4096_mod_exp_2_162(sp_digit* r, const sp_digit* e, int bits, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* td = NULL;
|
|
#else
|
|
sp_digit td[487];
|
|
#endif
|
|
sp_digit* norm = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit mp = 1;
|
|
sp_digit n;
|
|
sp_digit o;
|
|
int i;
|
|
int c;
|
|
byte y;
|
|
int err = MP_OKAY;
|
|
|
|
if (bits == 0) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 487, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
norm = td;
|
|
tmp = td + 324;
|
|
XMEMSET(td, 0, sizeof(sp_digit) * 487);
|
|
|
|
sp_4096_mont_setup(m, &mp);
|
|
sp_4096_mont_norm_162(norm, m);
|
|
|
|
bits = ((bits + 3) / 4) * 4;
|
|
i = ((bits + 25) / 26) - 1;
|
|
c = bits % 26;
|
|
if (c == 0) {
|
|
c = 26;
|
|
}
|
|
if (i < 162) {
|
|
n = e[i--] << (32 - c);
|
|
}
|
|
else {
|
|
n = 0;
|
|
i--;
|
|
}
|
|
if (c < 4) {
|
|
n |= e[i--] << (6 - c);
|
|
c += 26;
|
|
}
|
|
y = (int)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
sp_4096_lshift_162(r, norm, (byte)y);
|
|
while ((i >= 0) || (c >= 4)) {
|
|
if (c >= 4) {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c -= 4;
|
|
}
|
|
else if (c == 0) {
|
|
n = e[i--] << 6;
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n <<= 4;
|
|
c = 22;
|
|
}
|
|
else {
|
|
y = (byte)((n >> 28) & 0xf);
|
|
n = e[i--] << 6;
|
|
c = 4 - c;
|
|
y |= (byte)((n >> (32 - c)) & ((1 << c) - 1));
|
|
n <<= c;
|
|
c = 26 - c;
|
|
}
|
|
|
|
sp_4096_mont_sqr_162(r, r, m, mp);
|
|
sp_4096_mont_sqr_162(r, r, m, mp);
|
|
sp_4096_mont_sqr_162(r, r, m, mp);
|
|
sp_4096_mont_sqr_162(r, r, m, mp);
|
|
|
|
sp_4096_lshift_162(r, r, (byte)y);
|
|
sp_4096_mul_d_162(tmp, norm, (r[158] << 12) + (r[157] >> 14));
|
|
r[158] = 0;
|
|
r[157] &= 0x3fffL;
|
|
(void)sp_4096_add_162(r, r, tmp);
|
|
sp_4096_norm_162(r);
|
|
o = sp_4096_cmp_162(r, m);
|
|
sp_4096_cond_sub_162(r, r, m, ~(o >> 31));
|
|
}
|
|
|
|
sp_4096_mont_reduce_162(r, m, mp);
|
|
n = sp_4096_cmp_162(r, m);
|
|
sp_4096_cond_sub_162(r, r, m, ~(n >> 31));
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (td != NULL)
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* HAVE_FFDHE_4096 */
|
|
|
|
/* Perform the modular exponentiation for Diffie-Hellman.
|
|
*
|
|
* base Base.
|
|
* exp Array of bytes that is the exponent.
|
|
* expLen Length of data, in bytes, in exponent.
|
|
* mod Modulus.
|
|
* out Buffer to hold big-endian bytes of exponentiation result.
|
|
* Must be at least 512 bytes long.
|
|
* outLen Length, in bytes, of exponentiation result.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_DhExp_4096(const mp_int* base, const byte* exp, word32 expLen,
|
|
const mp_int* mod, byte* out, word32* outLen)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* b = NULL;
|
|
#else
|
|
sp_digit b[162 * 4];
|
|
#endif
|
|
sp_digit* e = NULL;
|
|
sp_digit* m = NULL;
|
|
sp_digit* r = NULL;
|
|
word32 i;
|
|
int err = MP_OKAY;
|
|
|
|
if (mp_count_bits(base) > 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (expLen > 512U) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_count_bits(mod) != 4096) {
|
|
err = MP_READ_E;
|
|
}
|
|
else if (mp_iseven(mod)) {
|
|
err = MP_VAL;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
b = (sp_digit*)XMALLOC(sizeof(sp_digit) * 162 * 4, NULL,
|
|
DYNAMIC_TYPE_DH);
|
|
if (b == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
e = b + 162 * 2;
|
|
m = e + 162;
|
|
r = b;
|
|
|
|
sp_4096_from_mp(b, 162, base);
|
|
sp_4096_from_bin(e, 162, exp, expLen);
|
|
sp_4096_from_mp(m, 162, mod);
|
|
|
|
#ifdef HAVE_FFDHE_4096
|
|
if (base->used == 1 && base->dp[0] == 2U &&
|
|
((m[157] << 2) | (m[156] >> 24)) == 0xffffL) {
|
|
err = sp_4096_mod_exp_2_162(r, e, expLen * 8U, m);
|
|
}
|
|
else {
|
|
#endif
|
|
err = sp_4096_mod_exp_162(r, b, e, expLen * 8U, m, 0);
|
|
#ifdef HAVE_FFDHE_4096
|
|
}
|
|
#endif
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_4096_to_bin_162(r, out);
|
|
*outLen = 512;
|
|
for (i=0; i<512U && out[i] == 0U; i++) {
|
|
/* Search for first non-zero. */
|
|
}
|
|
*outLen -= i;
|
|
XMEMMOVE(out, out + i, *outLen);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (b != NULL)
|
|
#endif
|
|
{
|
|
/* only "e" is sensitive and needs zeroized */
|
|
if (e != NULL)
|
|
ForceZero(e, sizeof(sp_digit) * 162U);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(b, NULL, DYNAMIC_TYPE_DH);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_SP_DH */
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_DH | (WOLFSSL_HAVE_SP_RSA & !WOLFSSL_RSA_PUBLIC_ONLY) */
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* WOLFSSL_SP_4096 */
|
|
|
|
#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH */
|
|
#ifdef WOLFSSL_HAVE_SP_ECC
|
|
#ifndef WOLFSSL_SP_NO_256
|
|
|
|
/* Point structure to use. */
|
|
typedef struct sp_point_256 {
|
|
/* X ordinate of point. */
|
|
sp_digit x[2 * 9];
|
|
/* Y ordinate of point. */
|
|
sp_digit y[2 * 9];
|
|
/* Z ordinate of point. */
|
|
sp_digit z[2 * 9];
|
|
/* Indicates point is at infinity. */
|
|
int infinity;
|
|
} sp_point_256;
|
|
|
|
/* The modulus (prime) of the curve P256. */
|
|
static const sp_digit p256_mod[9] = {
|
|
0x1fffffff,0x1fffffff,0x1fffffff,0x000001ff,0x00000000,0x00000000,
|
|
0x00040000,0x1fe00000,0x00ffffff
|
|
};
|
|
/* The Montgomery normalizer for modulus of the curve P256. */
|
|
static const sp_digit p256_norm_mod[9] = {
|
|
0x00000001,0x00000000,0x00000000,0x1ffffe00,0x1fffffff,0x1fffffff,
|
|
0x1ffbffff,0x001fffff,0x00000000
|
|
};
|
|
/* The Montgomery multiplier for modulus of the curve P256. */
|
|
static const sp_digit p256_mp_mod = 0x0000001;
|
|
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
|
|
defined(HAVE_ECC_VERIFY)
|
|
/* The order of the curve P256. */
|
|
static const sp_digit p256_order[9] = {
|
|
0x1c632551,0x1dce5617,0x05e7a13c,0x0df55b4e,0x1ffffbce,0x1fffffff,
|
|
0x0003ffff,0x1fe00000,0x00ffffff
|
|
};
|
|
#endif
|
|
/* The order of the curve P256 minus 2. */
|
|
static const sp_digit p256_order2[9] = {
|
|
0x1c63254f,0x1dce5617,0x05e7a13c,0x0df55b4e,0x1ffffbce,0x1fffffff,
|
|
0x0003ffff,0x1fe00000,0x00ffffff
|
|
};
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* The Montgomery normalizer for order of the curve P256. */
|
|
static const sp_digit p256_norm_order[9] = {
|
|
0x039cdaaf,0x0231a9e8,0x1a185ec3,0x120aa4b1,0x00000431,0x00000000,
|
|
0x1ffc0000,0x001fffff,0x00000000
|
|
};
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* The Montgomery multiplier for order of the curve P256. */
|
|
static const sp_digit p256_mp_order = 0xe00bc4f;
|
|
#endif
|
|
/* The base point of curve P256. */
|
|
static const sp_point_256 p256_base = {
|
|
/* X ordinate */
|
|
{
|
|
0x1898c296,0x0509ca2e,0x1acce83d,0x06fb025b,0x040f2770,0x1372b1d2,
|
|
0x091fe2f3,0x1e5c2588,0x006b17d1,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
|
|
},
|
|
/* Y ordinate */
|
|
{
|
|
0x17bf51f5,0x1db20341,0x0c57b3b2,0x1c66aed6,0x19e162bc,0x15a53e07,
|
|
0x1e6e3b9f,0x1c5fc34f,0x004fe342,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
|
|
},
|
|
/* Z ordinate */
|
|
{
|
|
0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
|
|
0x00000000,0x00000000,0x00000000,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
|
|
},
|
|
/* infinity */
|
|
0
|
|
};
|
|
#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
|
|
static const sp_digit p256_b[9] = {
|
|
0x07d2604b,0x1e71e1f1,0x14ec3d8e,0x1a0d6198,0x086bc651,0x1eaabb4c,
|
|
0x0f9ecfae,0x1b154752,0x005ac635
|
|
};
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_256_mul_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[8]) * b[8];
|
|
r[17] = (sp_digit)(c >> 29);
|
|
c &= 0x1fffffff;
|
|
for (k = 15; k >= 0; k--) {
|
|
if (k >= 9) {
|
|
i = k - 8;
|
|
imax = 8;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 29;
|
|
r[k + 2] += (sp_digit)(c >> 29);
|
|
r[k + 1] = (sp_digit)(c & 0x1fffffff);
|
|
c = lo & 0x1fffffff;
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
#else
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_256_mul_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_int64 t0;
|
|
sp_int64 t1;
|
|
sp_digit t[9];
|
|
|
|
t0 = ((sp_int64)a[ 0]) * b[ 0];
|
|
t1 = ((sp_int64)a[ 0]) * b[ 1]
|
|
+ ((sp_int64)a[ 1]) * b[ 0];
|
|
t[ 0] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 2]
|
|
+ ((sp_int64)a[ 1]) * b[ 1]
|
|
+ ((sp_int64)a[ 2]) * b[ 0];
|
|
t[ 1] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 3]
|
|
+ ((sp_int64)a[ 1]) * b[ 2]
|
|
+ ((sp_int64)a[ 2]) * b[ 1]
|
|
+ ((sp_int64)a[ 3]) * b[ 0];
|
|
t[ 2] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 4]
|
|
+ ((sp_int64)a[ 1]) * b[ 3]
|
|
+ ((sp_int64)a[ 2]) * b[ 2]
|
|
+ ((sp_int64)a[ 3]) * b[ 1]
|
|
+ ((sp_int64)a[ 4]) * b[ 0];
|
|
t[ 3] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 5]
|
|
+ ((sp_int64)a[ 1]) * b[ 4]
|
|
+ ((sp_int64)a[ 2]) * b[ 3]
|
|
+ ((sp_int64)a[ 3]) * b[ 2]
|
|
+ ((sp_int64)a[ 4]) * b[ 1]
|
|
+ ((sp_int64)a[ 5]) * b[ 0];
|
|
t[ 4] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 6]
|
|
+ ((sp_int64)a[ 1]) * b[ 5]
|
|
+ ((sp_int64)a[ 2]) * b[ 4]
|
|
+ ((sp_int64)a[ 3]) * b[ 3]
|
|
+ ((sp_int64)a[ 4]) * b[ 2]
|
|
+ ((sp_int64)a[ 5]) * b[ 1]
|
|
+ ((sp_int64)a[ 6]) * b[ 0];
|
|
t[ 5] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 7]
|
|
+ ((sp_int64)a[ 1]) * b[ 6]
|
|
+ ((sp_int64)a[ 2]) * b[ 5]
|
|
+ ((sp_int64)a[ 3]) * b[ 4]
|
|
+ ((sp_int64)a[ 4]) * b[ 3]
|
|
+ ((sp_int64)a[ 5]) * b[ 2]
|
|
+ ((sp_int64)a[ 6]) * b[ 1]
|
|
+ ((sp_int64)a[ 7]) * b[ 0];
|
|
t[ 6] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 8]
|
|
+ ((sp_int64)a[ 1]) * b[ 7]
|
|
+ ((sp_int64)a[ 2]) * b[ 6]
|
|
+ ((sp_int64)a[ 3]) * b[ 5]
|
|
+ ((sp_int64)a[ 4]) * b[ 4]
|
|
+ ((sp_int64)a[ 5]) * b[ 3]
|
|
+ ((sp_int64)a[ 6]) * b[ 2]
|
|
+ ((sp_int64)a[ 7]) * b[ 1]
|
|
+ ((sp_int64)a[ 8]) * b[ 0];
|
|
t[ 7] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 1]) * b[ 8]
|
|
+ ((sp_int64)a[ 2]) * b[ 7]
|
|
+ ((sp_int64)a[ 3]) * b[ 6]
|
|
+ ((sp_int64)a[ 4]) * b[ 5]
|
|
+ ((sp_int64)a[ 5]) * b[ 4]
|
|
+ ((sp_int64)a[ 6]) * b[ 3]
|
|
+ ((sp_int64)a[ 7]) * b[ 2]
|
|
+ ((sp_int64)a[ 8]) * b[ 1];
|
|
t[ 8] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 2]) * b[ 8]
|
|
+ ((sp_int64)a[ 3]) * b[ 7]
|
|
+ ((sp_int64)a[ 4]) * b[ 6]
|
|
+ ((sp_int64)a[ 5]) * b[ 5]
|
|
+ ((sp_int64)a[ 6]) * b[ 4]
|
|
+ ((sp_int64)a[ 7]) * b[ 3]
|
|
+ ((sp_int64)a[ 8]) * b[ 2];
|
|
r[ 9] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 3]) * b[ 8]
|
|
+ ((sp_int64)a[ 4]) * b[ 7]
|
|
+ ((sp_int64)a[ 5]) * b[ 6]
|
|
+ ((sp_int64)a[ 6]) * b[ 5]
|
|
+ ((sp_int64)a[ 7]) * b[ 4]
|
|
+ ((sp_int64)a[ 8]) * b[ 3];
|
|
r[10] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 4]) * b[ 8]
|
|
+ ((sp_int64)a[ 5]) * b[ 7]
|
|
+ ((sp_int64)a[ 6]) * b[ 6]
|
|
+ ((sp_int64)a[ 7]) * b[ 5]
|
|
+ ((sp_int64)a[ 8]) * b[ 4];
|
|
r[11] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 5]) * b[ 8]
|
|
+ ((sp_int64)a[ 6]) * b[ 7]
|
|
+ ((sp_int64)a[ 7]) * b[ 6]
|
|
+ ((sp_int64)a[ 8]) * b[ 5];
|
|
r[12] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 6]) * b[ 8]
|
|
+ ((sp_int64)a[ 7]) * b[ 7]
|
|
+ ((sp_int64)a[ 8]) * b[ 6];
|
|
r[13] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = ((sp_int64)a[ 7]) * b[ 8]
|
|
+ ((sp_int64)a[ 8]) * b[ 7];
|
|
r[14] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 8]) * b[ 8];
|
|
r[15] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
r[16] = t0 & 0x1fffffff;
|
|
r[17] = (sp_digit)(t0 >> 29);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_256_sqr_9(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[8]) * a[8];
|
|
r[17] = (sp_digit)(c >> 29);
|
|
c = (c & 0x1fffffff) << 29;
|
|
for (k = 15; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 8) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 8;
|
|
}
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 58);
|
|
r[k + 1] = (sp_digit)((c >> 29) & 0x1fffffff);
|
|
c = (c & 0x1fffffff) << 29;
|
|
}
|
|
r[0] = (sp_digit)(c >> 29);
|
|
}
|
|
|
|
#else
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_256_sqr_9(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_int64 t0;
|
|
sp_int64 t1;
|
|
sp_digit t[9];
|
|
|
|
t0 = ((sp_int64)a[ 0]) * a[ 0];
|
|
t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2;
|
|
t[ 0] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 2]) * 2
|
|
+ ((sp_int64)a[ 1]) * a[ 1];
|
|
t[ 1] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 3]
|
|
+ ((sp_int64)a[ 1]) * a[ 2]) * 2;
|
|
t[ 2] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 4]
|
|
+ ((sp_int64)a[ 1]) * a[ 3]) * 2
|
|
+ ((sp_int64)a[ 2]) * a[ 2];
|
|
t[ 3] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 5]
|
|
+ ((sp_int64)a[ 1]) * a[ 4]
|
|
+ ((sp_int64)a[ 2]) * a[ 3]) * 2;
|
|
t[ 4] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 6]
|
|
+ ((sp_int64)a[ 1]) * a[ 5]
|
|
+ ((sp_int64)a[ 2]) * a[ 4]) * 2
|
|
+ ((sp_int64)a[ 3]) * a[ 3];
|
|
t[ 5] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 7]
|
|
+ ((sp_int64)a[ 1]) * a[ 6]
|
|
+ ((sp_int64)a[ 2]) * a[ 5]
|
|
+ ((sp_int64)a[ 3]) * a[ 4]) * 2;
|
|
t[ 6] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 8]
|
|
+ ((sp_int64)a[ 1]) * a[ 7]
|
|
+ ((sp_int64)a[ 2]) * a[ 6]
|
|
+ ((sp_int64)a[ 3]) * a[ 5]) * 2
|
|
+ ((sp_int64)a[ 4]) * a[ 4];
|
|
t[ 7] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 1]) * a[ 8]
|
|
+ ((sp_int64)a[ 2]) * a[ 7]
|
|
+ ((sp_int64)a[ 3]) * a[ 6]
|
|
+ ((sp_int64)a[ 4]) * a[ 5]) * 2;
|
|
t[ 8] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 2]) * a[ 8]
|
|
+ ((sp_int64)a[ 3]) * a[ 7]
|
|
+ ((sp_int64)a[ 4]) * a[ 6]) * 2
|
|
+ ((sp_int64)a[ 5]) * a[ 5];
|
|
r[ 9] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 3]) * a[ 8]
|
|
+ ((sp_int64)a[ 4]) * a[ 7]
|
|
+ ((sp_int64)a[ 5]) * a[ 6]) * 2;
|
|
r[10] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 4]) * a[ 8]
|
|
+ ((sp_int64)a[ 5]) * a[ 7]) * 2
|
|
+ ((sp_int64)a[ 6]) * a[ 6];
|
|
r[11] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 5]) * a[ 8]
|
|
+ ((sp_int64)a[ 6]) * a[ 7]) * 2;
|
|
r[12] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = (((sp_int64)a[ 6]) * a[ 8]) * 2
|
|
+ ((sp_int64)a[ 7]) * a[ 7];
|
|
r[13] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
t1 = (((sp_int64)a[ 7]) * a[ 8]) * 2;
|
|
r[14] = t0 & 0x1fffffff; t1 += t0 >> 29;
|
|
t0 = ((sp_int64)a[ 8]) * a[ 8];
|
|
r[15] = t1 & 0x1fffffff; t0 += t1 >> 29;
|
|
r[16] = t0 & 0x1fffffff;
|
|
r[17] = (sp_digit)(t0 >> 29);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_256_add_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_256_add_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
r[ 7] = a[ 7] + b[ 7];
|
|
r[ 8] = a[ 8] + b[ 8];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_256_sub_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_256_sub_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] - b[ 0];
|
|
r[ 1] = a[ 1] - b[ 1];
|
|
r[ 2] = a[ 2] - b[ 2];
|
|
r[ 3] = a[ 3] - b[ 3];
|
|
r[ 4] = a[ 4] - b[ 4];
|
|
r[ 5] = a[ 5] - b[ 5];
|
|
r[ 6] = a[ 6] - b[ 6];
|
|
r[ 7] = a[ 7] - b[ 7];
|
|
r[ 8] = a[ 8] - b[ 8];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_256_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 29
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 29
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 29U) <= (word32)DIGIT_BIT) {
|
|
s += 29U;
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 29) {
|
|
r[j] &= 0x1fffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 29 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Convert a point of type ecc_point to type sp_point_256.
|
|
*
|
|
* p Point of type sp_point_256 (result).
|
|
* pm Point of type ecc_point.
|
|
*/
|
|
static void sp_256_point_from_ecc_point_9(sp_point_256* p,
|
|
const ecc_point* pm)
|
|
{
|
|
XMEMSET(p->x, 0, sizeof(p->x));
|
|
XMEMSET(p->y, 0, sizeof(p->y));
|
|
XMEMSET(p->z, 0, sizeof(p->z));
|
|
sp_256_from_mp(p->x, 9, pm->x);
|
|
sp_256_from_mp(p->y, 9, pm->y);
|
|
sp_256_from_mp(p->z, 9, pm->z);
|
|
p->infinity = 0;
|
|
}
|
|
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_256_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 29
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 9);
|
|
r->used = 9;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 29
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 9; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 29) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 29 - s;
|
|
}
|
|
r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 9; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 29 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 29 - s;
|
|
}
|
|
else {
|
|
s += 29;
|
|
}
|
|
}
|
|
r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Convert a point of type sp_point_256 to type ecc_point.
|
|
*
|
|
* p Point of type sp_point_256.
|
|
* pm Point of type ecc_point (result).
|
|
* returns MEMORY_E when allocation of memory in ecc_point fails otherwise
|
|
* MP_OKAY.
|
|
*/
|
|
static int sp_256_point_to_ecc_point_9(const sp_point_256* p, ecc_point* pm)
|
|
{
|
|
int err;
|
|
|
|
err = sp_256_to_mp(p->x, pm->x);
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->y, pm->y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->z, pm->z);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_256_cmp_9(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=8; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 28);
|
|
}
|
|
#else
|
|
r |= (a[ 8] - b[ 8]) & (0 - (sp_digit)1);
|
|
r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 28);
|
|
r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 28);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_256_cond_sub_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
#else
|
|
r[ 0] = a[ 0] - (b[ 0] & m);
|
|
r[ 1] = a[ 1] - (b[ 1] & m);
|
|
r[ 2] = a[ 2] - (b[ 2] & m);
|
|
r[ 3] = a[ 3] - (b[ 3] & m);
|
|
r[ 4] = a[ 4] - (b[ 4] & m);
|
|
r[ 5] = a[ 5] - (b[ 5] & m);
|
|
r[ 6] = a[ 6] - (b[ 6] & m);
|
|
r[ 7] = a[ 7] - (b[ 7] & m);
|
|
r[ 8] = a[ 8] - (b[ 8] & m);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_256_mul_add_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifndef WOLFSSL_SP_LARGE_CODE
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
t += r[i];
|
|
t += tb * a[i];
|
|
r[i] = ((sp_digit)t) & 0x1fffffff;
|
|
t >>= 29;
|
|
}
|
|
r[9] += (sp_digit)t;
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 8; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[0] = t[3] >> 29;
|
|
}
|
|
t[0] += (tb * a[8]) + r[8];
|
|
r[8] = t[0] & 0x1fffffff;
|
|
r[9] += (sp_digit)(t[0] >> 29);
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 8; i += 8) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
t[4] = (tb * a[i+4]) + r[i+4];
|
|
t[5] = (tb * a[i+5]) + r[i+5];
|
|
t[6] = (tb * a[i+6]) + r[i+6];
|
|
t[7] = (tb * a[i+7]) + r[i+7];
|
|
r[i+0] = t[0] & 0x1fffffff;
|
|
t[1] += t[0] >> 29;
|
|
r[i+1] = t[1] & 0x1fffffff;
|
|
t[2] += t[1] >> 29;
|
|
r[i+2] = t[2] & 0x1fffffff;
|
|
t[3] += t[2] >> 29;
|
|
r[i+3] = t[3] & 0x1fffffff;
|
|
t[4] += t[3] >> 29;
|
|
r[i+4] = t[4] & 0x1fffffff;
|
|
t[5] += t[4] >> 29;
|
|
r[i+5] = t[5] & 0x1fffffff;
|
|
t[6] += t[5] >> 29;
|
|
r[i+6] = t[6] & 0x1fffffff;
|
|
t[7] += t[6] >> 29;
|
|
r[i+7] = t[7] & 0x1fffffff;
|
|
t[0] = t[7] >> 29;
|
|
}
|
|
t[0] += (tb * a[8]) + r[8];
|
|
r[8] = t[0] & 0x1fffffff;
|
|
r[9] += (sp_digit)(t[0] >> 29);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#endif /* !WOLFSSL_SP_LARGE_CODE */
|
|
}
|
|
|
|
/* Normalize the values in each word to 29 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_256_norm_9(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 8; i++) {
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
}
|
|
#else
|
|
a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
|
|
a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
|
|
a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
|
|
a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
|
|
a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
|
|
a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
|
|
a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
|
|
a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Shift the result in the high 256 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_256_mont_shift_9(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
sp_int64 n = a[8] >> 24;
|
|
n += ((sp_int64)a[9]) << 5;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
r[i] = n & 0x1fffffff;
|
|
n >>= 29;
|
|
n += ((sp_int64)a[10 + i]) << 5;
|
|
}
|
|
r[8] = (sp_digit)n;
|
|
#else
|
|
sp_int64 n = a[8] >> 24;
|
|
n += ((sp_int64)a[9]) << 5;
|
|
r[ 0] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[10]) << 5;
|
|
r[ 1] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[11]) << 5;
|
|
r[ 2] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[12]) << 5;
|
|
r[ 3] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[13]) << 5;
|
|
r[ 4] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[14]) << 5;
|
|
r[ 5] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[15]) << 5;
|
|
r[ 6] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[16]) << 5;
|
|
r[ 7] = n & 0x1fffffff; n >>= 29; n += ((sp_int64)a[17]) << 5;
|
|
r[8] = (sp_digit)n;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
XMEMSET(&r[9], 0, sizeof(*r) * 9U);
|
|
}
|
|
|
|
/* Reduce the number back to 256 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_256_mont_reduce_order_9(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_256_norm_9(a + 9);
|
|
|
|
for (i=0; i<8; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffff;
|
|
sp_256_mul_add_9(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xffffffL;
|
|
sp_256_mul_add_9(a+i, m, mu);
|
|
a[i+1] += a[i] >> 29;
|
|
a[i] &= 0x1fffffff;
|
|
sp_256_mont_shift_9(a, a);
|
|
over = a[8] >> 24;
|
|
sp_256_cond_sub_9(a, a, m, ~((over - 1) >> 31));
|
|
sp_256_norm_9(a);
|
|
}
|
|
|
|
/* Reduce the number back to 256 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_256_mont_reduce_9(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit am;
|
|
|
|
(void)m;
|
|
(void)mp;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
am = a[i] & 0x1fffffff;
|
|
a[i + 3] += (am << 9) & 0x1fffffff;
|
|
a[i + 4] += am >> 20;
|
|
a[i + 6] += (am << 18) & 0x1fffffff;
|
|
a[i + 7] += (am >> 11) - ((am << 21) & 0x1fffffff);
|
|
a[i + 8] += -(am >> 8) + ((am << 24) & 0x1fffffff);
|
|
a[i + 9] += am >> 5;
|
|
|
|
a[i + 1] += a[i] >> 29;
|
|
}
|
|
am = a[8] & 0xffffff;
|
|
a[8 + 3] += (am << 9) & 0x1fffffff;
|
|
a[8 + 4] += am >> 20;
|
|
a[8 + 6] += (am << 18) & 0x1fffffff;
|
|
a[8 + 7] += (am >> 11) - ((am << 21) & 0x1fffffff);
|
|
a[8 + 8] += -(am >> 8) + ((am << 24) & 0x1fffffff);
|
|
a[8 + 9] += am >> 5;
|
|
|
|
a[0] = (a[ 8] >> 24) + ((a[ 9] << 5) & 0x1fffffff);
|
|
a[1] = (a[ 9] >> 24) + ((a[10] << 5) & 0x1fffffff);
|
|
a[2] = (a[10] >> 24) + ((a[11] << 5) & 0x1fffffff);
|
|
a[3] = (a[11] >> 24) + ((a[12] << 5) & 0x1fffffff);
|
|
a[4] = (a[12] >> 24) + ((a[13] << 5) & 0x1fffffff);
|
|
a[5] = (a[13] >> 24) + ((a[14] << 5) & 0x1fffffff);
|
|
a[6] = (a[14] >> 24) + ((a[15] << 5) & 0x1fffffff);
|
|
a[7] = (a[15] >> 24) + ((a[16] << 5) & 0x1fffffff);
|
|
a[8] = (a[16] >> 24) + (a[17] << 5);
|
|
|
|
a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
|
|
a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
|
|
a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
|
|
a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
|
|
a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
|
|
a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
|
|
a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
|
|
a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
|
|
|
|
/* Get the bit over, if any. */
|
|
am = a[8] >> 24;
|
|
/* Create mask. */
|
|
am = 0 - am;
|
|
|
|
a[0] -= 0x1fffffff & am;
|
|
a[1] -= 0x1fffffff & am;
|
|
a[2] -= 0x1fffffff & am;
|
|
a[3] -= 0x000001ff & am;
|
|
/* p256_mod[4] is zero */
|
|
/* p256_mod[5] is zero */
|
|
a[6] -= 0x00040000 & am;
|
|
a[7] -= 0x1fe00000 & am;
|
|
a[8] -= 0x00ffffff & am;
|
|
|
|
a[1] += a[0] >> 29; a[0] &= 0x1fffffff;
|
|
a[2] += a[1] >> 29; a[1] &= 0x1fffffff;
|
|
a[3] += a[2] >> 29; a[2] &= 0x1fffffff;
|
|
a[4] += a[3] >> 29; a[3] &= 0x1fffffff;
|
|
a[5] += a[4] >> 29; a[4] &= 0x1fffffff;
|
|
a[6] += a[5] >> 29; a[5] &= 0x1fffffff;
|
|
a[7] += a[6] >> 29; a[6] &= 0x1fffffff;
|
|
a[8] += a[7] >> 29; a[7] &= 0x1fffffff;
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_256_mont_mul_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_256_mul_9(r, a, b);
|
|
sp_256_mont_reduce_9(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_256_mont_sqr_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_256_sqr_9(r, a);
|
|
sp_256_mont_reduce_9(r, m, mp);
|
|
}
|
|
|
|
#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
|
|
/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* n Number of times to square.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
static void sp_256_mont_sqr_n_9(sp_digit* r, const sp_digit* a, int n,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_256_mont_sqr_9(r, a, m, mp);
|
|
for (; n > 1; n--) {
|
|
sp_256_mont_sqr_9(r, r, m, mp);
|
|
}
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Mod-2 for the P256 curve. */
|
|
static const uint32_t p256_mod_minus_2[8] = {
|
|
0xfffffffdU,0xffffffffU,0xffffffffU,0x00000000U,0x00000000U,0x00000000U,
|
|
0x00000001U,0xffffffffU
|
|
};
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
|
|
* P256 curve. (r = 1 / a mod m)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
static void sp_256_mont_inv_9(sp_digit* r, const sp_digit* a, sp_digit* td)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_digit* t = td;
|
|
int i;
|
|
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 9);
|
|
for (i=254; i>=0; i--) {
|
|
sp_256_mont_sqr_9(t, t, p256_mod, p256_mp_mod);
|
|
if (p256_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
|
|
sp_256_mont_mul_9(t, t, a, p256_mod, p256_mp_mod);
|
|
}
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 9);
|
|
#else
|
|
sp_digit* t1 = td;
|
|
sp_digit* t2 = td + 2 * 9;
|
|
sp_digit* t3 = td + 4 * 9;
|
|
/* 0x2 */
|
|
sp_256_mont_sqr_9(t1, a, p256_mod, p256_mp_mod);
|
|
/* 0x3 */
|
|
sp_256_mont_mul_9(t2, t1, a, p256_mod, p256_mp_mod);
|
|
/* 0xc */
|
|
sp_256_mont_sqr_n_9(t1, t2, 2, p256_mod, p256_mp_mod);
|
|
/* 0xd */
|
|
sp_256_mont_mul_9(t3, t1, a, p256_mod, p256_mp_mod);
|
|
/* 0xf */
|
|
sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
|
|
/* 0xf0 */
|
|
sp_256_mont_sqr_n_9(t1, t2, 4, p256_mod, p256_mp_mod);
|
|
/* 0xfd */
|
|
sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod);
|
|
/* 0xff */
|
|
sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
|
|
/* 0xff00 */
|
|
sp_256_mont_sqr_n_9(t1, t2, 8, p256_mod, p256_mp_mod);
|
|
/* 0xfffd */
|
|
sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod);
|
|
/* 0xffff */
|
|
sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
|
|
/* 0xffff0000 */
|
|
sp_256_mont_sqr_n_9(t1, t2, 16, p256_mod, p256_mp_mod);
|
|
/* 0xfffffffd */
|
|
sp_256_mont_mul_9(t3, t3, t1, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff */
|
|
sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff00000000 */
|
|
sp_256_mont_sqr_n_9(t1, t2, 32, p256_mod, p256_mp_mod);
|
|
/* 0xffffffffffffffff */
|
|
sp_256_mont_mul_9(t2, t2, t1, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff00000001 */
|
|
sp_256_mont_mul_9(r, t1, a, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff000000010000000000000000000000000000000000000000 */
|
|
sp_256_mont_sqr_n_9(r, r, 160, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff00000001000000000000000000000000ffffffffffffffff */
|
|
sp_256_mont_mul_9(r, r, t2, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff00000001000000000000000000000000ffffffffffffffff00000000 */
|
|
sp_256_mont_sqr_n_9(r, r, 32, p256_mod, p256_mp_mod);
|
|
/* 0xffffffff00000001000000000000000000000000fffffffffffffffffffffffd */
|
|
sp_256_mont_mul_9(r, r, t3, p256_mod, p256_mp_mod);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Map the Montgomery form projective coordinate point to an affine point.
|
|
*
|
|
* r Resulting affine coordinate point.
|
|
* p Montgomery form projective coordinate point.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_map_9(sp_point_256* r, const sp_point_256* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*9;
|
|
sp_int32 n;
|
|
|
|
sp_256_mont_inv_9(t1, p->z, t + 2*9);
|
|
|
|
sp_256_mont_sqr_9(t2, t1, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t1, t2, t1, p256_mod, p256_mp_mod);
|
|
|
|
/* x /= z^2 */
|
|
sp_256_mont_mul_9(r->x, p->x, t2, p256_mod, p256_mp_mod);
|
|
XMEMSET(r->x + 9, 0, sizeof(sp_digit) * 9U);
|
|
sp_256_mont_reduce_9(r->x, p256_mod, p256_mp_mod);
|
|
/* Reduce x to less than modulus */
|
|
n = sp_256_cmp_9(r->x, p256_mod);
|
|
sp_256_cond_sub_9(r->x, r->x, p256_mod, ~(n >> 28));
|
|
sp_256_norm_9(r->x);
|
|
|
|
/* y /= z^3 */
|
|
sp_256_mont_mul_9(r->y, p->y, t1, p256_mod, p256_mp_mod);
|
|
XMEMSET(r->y + 9, 0, sizeof(sp_digit) * 9U);
|
|
sp_256_mont_reduce_9(r->y, p256_mod, p256_mp_mod);
|
|
/* Reduce y to less than modulus */
|
|
n = sp_256_cmp_9(r->y, p256_mod);
|
|
sp_256_cond_sub_9(r->y, r->y, p256_mod, ~(n >> 28));
|
|
sp_256_norm_9(r->y);
|
|
|
|
XMEMSET(r->z, 0, sizeof(r->z) / 2);
|
|
r->z[0] = 1;
|
|
}
|
|
|
|
/* Add two Montgomery form numbers (r = a + b % m).
|
|
*
|
|
* r Result of addition.
|
|
* a First number to add in Montgomery form.
|
|
* b Second number to add in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_256_mont_add_9(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_256_add_9(r, a, b);
|
|
sp_256_norm_9(r);
|
|
over = r[8] >> 24;
|
|
sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
|
|
sp_256_norm_9(r);
|
|
}
|
|
|
|
/* Double a Montgomery form number (r = a + a % m).
|
|
*
|
|
* r Result of doubling.
|
|
* a Number to double in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_256_mont_dbl_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_256_add_9(r, a, a);
|
|
sp_256_norm_9(r);
|
|
over = r[8] >> 24;
|
|
sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
|
|
sp_256_norm_9(r);
|
|
}
|
|
|
|
/* Triple a Montgomery form number (r = a + a + a % m).
|
|
*
|
|
* r Result of Tripling.
|
|
* a Number to triple in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_256_mont_tpl_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_256_add_9(r, a, a);
|
|
sp_256_norm_9(r);
|
|
over = r[8] >> 24;
|
|
sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
|
|
sp_256_norm_9(r);
|
|
(void)sp_256_add_9(r, r, a);
|
|
sp_256_norm_9(r);
|
|
over = r[8] >> 24;
|
|
sp_256_cond_sub_9(r, r, m, ~((over - 1) >> 31));
|
|
sp_256_norm_9(r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_256_cond_add_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_256_cond_add_9(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
r[ 0] = a[ 0] + (b[ 0] & m);
|
|
r[ 1] = a[ 1] + (b[ 1] & m);
|
|
r[ 2] = a[ 2] + (b[ 2] & m);
|
|
r[ 3] = a[ 3] + (b[ 3] & m);
|
|
r[ 4] = a[ 4] + (b[ 4] & m);
|
|
r[ 5] = a[ 5] + (b[ 5] & m);
|
|
r[ 6] = a[ 6] + (b[ 6] & m);
|
|
r[ 7] = a[ 7] + (b[ 7] & m);
|
|
r[ 8] = a[ 8] + (b[ 8] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Subtract two Montgomery form numbers (r = a - b % m).
|
|
*
|
|
* r Result of subtration.
|
|
* a Number to subtract from in Montgomery form.
|
|
* b Number to subtract with in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_256_mont_sub_9(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
(void)sp_256_sub_9(r, a, b);
|
|
sp_256_norm_9(r);
|
|
sp_256_cond_add_9(r, r, m, r[8] >> 24);
|
|
sp_256_norm_9(r);
|
|
}
|
|
|
|
#define sp_256_mont_sub_lower_9 sp_256_mont_sub_9
|
|
/* Shift number left one bit.
|
|
* Bottom bit is lost.
|
|
*
|
|
* r Result of shift.
|
|
* a Number to shift.
|
|
*/
|
|
SP_NOINLINE static void sp_256_rshift1_9(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=0; i<8; i++) {
|
|
r[i] = (a[i] >> 1) + ((a[i + 1] << 28) & 0x1fffffff);
|
|
}
|
|
#else
|
|
r[0] = (a[0] >> 1) + ((a[1] << 28) & 0x1fffffff);
|
|
r[1] = (a[1] >> 1) + ((a[2] << 28) & 0x1fffffff);
|
|
r[2] = (a[2] >> 1) + ((a[3] << 28) & 0x1fffffff);
|
|
r[3] = (a[3] >> 1) + ((a[4] << 28) & 0x1fffffff);
|
|
r[4] = (a[4] >> 1) + ((a[5] << 28) & 0x1fffffff);
|
|
r[5] = (a[5] >> 1) + ((a[6] << 28) & 0x1fffffff);
|
|
r[6] = (a[6] >> 1) + ((a[7] << 28) & 0x1fffffff);
|
|
r[7] = (a[7] >> 1) + ((a[8] << 28) & 0x1fffffff);
|
|
#endif
|
|
r[8] = a[8] >> 1;
|
|
}
|
|
|
|
/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
|
|
*
|
|
* r Result of division by 2.
|
|
* a Number to divide.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_256_div2_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_256_cond_add_9(r, a, m, 0 - (a[0] & 1));
|
|
sp_256_norm_9(r);
|
|
sp_256_rshift1_9(r, r);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_proj_point_dbl_9(sp_point_256* r, const sp_point_256* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*9;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
|
|
x = r->x;
|
|
y = r->y;
|
|
z = r->z;
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
|
|
/* T1 = Z * Z */
|
|
sp_256_mont_sqr_9(t1, p->z, p256_mod, p256_mp_mod);
|
|
/* Z = Y * Z */
|
|
sp_256_mont_mul_9(z, p->y, p->z, p256_mod, p256_mp_mod);
|
|
/* Z = 2Z */
|
|
sp_256_mont_dbl_9(z, z, p256_mod);
|
|
/* T2 = X - T1 */
|
|
sp_256_mont_sub_9(t2, p->x, t1, p256_mod);
|
|
/* T1 = X + T1 */
|
|
sp_256_mont_add_9(t1, p->x, t1, p256_mod);
|
|
/* T2 = T1 * T2 */
|
|
sp_256_mont_mul_9(t2, t1, t2, p256_mod, p256_mp_mod);
|
|
/* T1 = 3T2 */
|
|
sp_256_mont_tpl_9(t1, t2, p256_mod);
|
|
/* Y = 2Y */
|
|
sp_256_mont_dbl_9(y, p->y, p256_mod);
|
|
/* Y = Y * Y */
|
|
sp_256_mont_sqr_9(y, y, p256_mod, p256_mp_mod);
|
|
/* T2 = Y * Y */
|
|
sp_256_mont_sqr_9(t2, y, p256_mod, p256_mp_mod);
|
|
/* T2 = T2/2 */
|
|
sp_256_div2_9(t2, t2, p256_mod);
|
|
/* Y = Y * X */
|
|
sp_256_mont_mul_9(y, y, p->x, p256_mod, p256_mp_mod);
|
|
/* X = T1 * T1 */
|
|
sp_256_mont_sqr_9(x, t1, p256_mod, p256_mp_mod);
|
|
/* X = X - Y */
|
|
sp_256_mont_sub_9(x, x, y, p256_mod);
|
|
/* X = X - Y */
|
|
sp_256_mont_sub_9(x, x, y, p256_mod);
|
|
/* Y = Y - X */
|
|
sp_256_mont_sub_lower_9(y, y, x, p256_mod);
|
|
/* Y = Y * T1 */
|
|
sp_256_mont_mul_9(y, y, t1, p256_mod, p256_mp_mod);
|
|
/* Y = Y - T2 */
|
|
sp_256_mont_sub_9(y, y, t2, p256_mod);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_256_proj_point_dbl_9_ctx {
|
|
int state;
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_256_proj_point_dbl_9_ctx;
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_256_proj_point_dbl_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r, const sp_point_256* p, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_256_proj_point_dbl_9_ctx* ctx = (sp_256_proj_point_dbl_9_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_256_proj_point_dbl_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*9;
|
|
ctx->x = r->x;
|
|
ctx->y = r->y;
|
|
ctx->z = r->z;
|
|
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* T1 = Z * Z */
|
|
sp_256_mont_sqr_9(ctx->t1, p->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
/* Z = Y * Z */
|
|
sp_256_mont_mul_9(ctx->z, p->y, p->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
/* Z = 2Z */
|
|
sp_256_mont_dbl_9(ctx->z, ctx->z, p256_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* T2 = X - T1 */
|
|
sp_256_mont_sub_9(ctx->t2, p->x, ctx->t1, p256_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
/* T1 = X + T1 */
|
|
sp_256_mont_add_9(ctx->t1, p->x, ctx->t1, p256_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
/* T2 = T1 * T2 */
|
|
sp_256_mont_mul_9(ctx->t2, ctx->t1, ctx->t2, p256_mod, p256_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* T1 = 3T2 */
|
|
sp_256_mont_tpl_9(ctx->t1, ctx->t2, p256_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* Y = 2Y */
|
|
sp_256_mont_dbl_9(ctx->y, p->y, p256_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Y = Y * Y */
|
|
sp_256_mont_sqr_9(ctx->y, ctx->y, p256_mod, p256_mp_mod);
|
|
ctx->state = 10;
|
|
break;
|
|
case 10:
|
|
/* T2 = Y * Y */
|
|
sp_256_mont_sqr_9(ctx->t2, ctx->y, p256_mod, p256_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* T2 = T2/2 */
|
|
sp_256_div2_9(ctx->t2, ctx->t2, p256_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* Y = Y * X */
|
|
sp_256_mont_mul_9(ctx->y, ctx->y, p->x, p256_mod, p256_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
/* X = T1 * T1 */
|
|
sp_256_mont_sqr_9(ctx->x, ctx->t1, p256_mod, p256_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
/* X = X - Y */
|
|
sp_256_mont_sub_9(ctx->x, ctx->x, ctx->y, p256_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* X = X - Y */
|
|
sp_256_mont_sub_9(ctx->x, ctx->x, ctx->y, p256_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
/* Y = Y - X */
|
|
sp_256_mont_sub_lower_9(ctx->y, ctx->y, ctx->x, p256_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
/* Y = Y * T1 */
|
|
sp_256_mont_mul_9(ctx->y, ctx->y, ctx->t1, p256_mod, p256_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
/* Y = Y - T2 */
|
|
sp_256_mont_sub_9(ctx->y, ctx->y, ctx->t2, p256_mod);
|
|
ctx->state = 19;
|
|
/* fall-through */
|
|
case 19:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 19) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
/* Compare two numbers to determine if they are equal.
|
|
* Constant time implementation.
|
|
*
|
|
* a First number to compare.
|
|
* b Second number to compare.
|
|
* returns 1 when equal and 0 otherwise.
|
|
*/
|
|
static int sp_256_cmp_equal_9(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
|
|
(a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
|
|
(a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8])) == 0;
|
|
}
|
|
|
|
/* Returns 1 if the number of zero.
|
|
* Implementation is constant time.
|
|
*
|
|
* a Number to check.
|
|
* returns 1 if the number is zero and 0 otherwise.
|
|
*/
|
|
static int sp_256_iszero_9(const sp_digit* a)
|
|
{
|
|
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
|
|
a[8]) == 0;
|
|
}
|
|
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_proj_point_add_9(sp_point_256* r,
|
|
const sp_point_256* p, const sp_point_256* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*9;
|
|
sp_digit* t3 = t + 4*9;
|
|
sp_digit* t4 = t + 6*9;
|
|
sp_digit* t5 = t + 8*9;
|
|
sp_digit* t6 = t + 10*9;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_256_mont_sqr_9(t1, q->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t3, t1, q->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t1, t1, p->x, p256_mod, p256_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_256_mont_sqr_9(t2, p->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t4, t2, p->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_256_mont_mul_9(t3, t3, p->y, p256_mod, p256_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod);
|
|
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_256_cmp_equal_9(t2, t1) &
|
|
sp_256_cmp_equal_9(t4, t3)) {
|
|
sp_256_proj_point_dbl_9(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t6;
|
|
sp_digit* y = t1;
|
|
sp_digit* z = t2;
|
|
int i;
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
|
|
/* H = U2 - U1 */
|
|
sp_256_mont_sub_9(t2, t2, t1, p256_mod);
|
|
/* R = S2 - S1 */
|
|
sp_256_mont_sub_9(t4, t4, t3, p256_mod);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(y, t1, t5, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_256_mont_mul_9(z, p->z, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(z, z, q->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_9(x, t4, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(x, x, t5, p256_mod);
|
|
sp_256_mont_mul_9(t5, t5, t3, p256_mod, p256_mp_mod);
|
|
sp_256_mont_dbl_9(t3, y, p256_mod);
|
|
sp_256_mont_sub_9(x, x, t3, p256_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_256_mont_sub_lower_9(y, y, x, p256_mod);
|
|
sp_256_mont_mul_9(y, y, t4, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(y, y, t5, p256_mod);
|
|
for (i = 0; i < 9; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_256_proj_point_add_9_ctx {
|
|
int state;
|
|
sp_256_proj_point_dbl_9_ctx dbl_ctx;
|
|
const sp_point_256* ap[2];
|
|
sp_point_256* rp[2];
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* t3;
|
|
sp_digit* t4;
|
|
sp_digit* t5;
|
|
sp_digit* t6;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_256_proj_point_add_9_ctx;
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_256_proj_point_add_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
|
|
const sp_point_256* p, const sp_point_256* q, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_256_proj_point_add_9_ctx* ctx = (sp_256_proj_point_add_9_ctx*)sp_ctx->data;
|
|
|
|
/* Ensure only the first point is the same as the result. */
|
|
if (q == r) {
|
|
const sp_point_256* a = p;
|
|
p = q;
|
|
q = a;
|
|
}
|
|
|
|
typedef char ctx_size_test[sizeof(sp_256_proj_point_add_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*9;
|
|
ctx->t3 = t + 4*9;
|
|
ctx->t4 = t + 6*9;
|
|
ctx->t5 = t + 8*9;
|
|
ctx->t6 = t + 10*9;
|
|
ctx->x = ctx->t6;
|
|
ctx->y = ctx->t1;
|
|
ctx->z = ctx->t2;
|
|
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* U1 = X1*Z2^2 */
|
|
sp_256_mont_sqr_9(ctx->t1, q->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
sp_256_mont_mul_9(ctx->t3, ctx->t1, q->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
sp_256_mont_mul_9(ctx->t1, ctx->t1, p->x, p256_mod, p256_mp_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* U2 = X2*Z1^2 */
|
|
sp_256_mont_sqr_9(ctx->t2, p->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
sp_256_mont_mul_9(ctx->t4, ctx->t2, p->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
sp_256_mont_mul_9(ctx->t2, ctx->t2, q->x, p256_mod, p256_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_256_mont_mul_9(ctx->t3, ctx->t3, p->y, p256_mod, p256_mp_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_256_mont_mul_9(ctx->t4, ctx->t4, q->y, p256_mod, p256_mp_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_256_cmp_equal_9(ctx->t2, ctx->t1) &
|
|
sp_256_cmp_equal_9(ctx->t4, ctx->t3)) {
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
sp_256_proj_point_dbl_9(r, p, t);
|
|
ctx->state = 25;
|
|
}
|
|
else {
|
|
ctx->state = 10;
|
|
}
|
|
break;
|
|
case 10:
|
|
/* H = U2 - U1 */
|
|
sp_256_mont_sub_9(ctx->t2, ctx->t2, ctx->t1, p256_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* R = S2 - S1 */
|
|
sp_256_mont_sub_9(ctx->t4, ctx->t4, ctx->t3, p256_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_256_mont_sqr_9(ctx->t5, ctx->t2, p256_mod, p256_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
sp_256_mont_mul_9(ctx->y, ctx->t1, ctx->t5, p256_mod, p256_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
sp_256_mont_mul_9(ctx->t5, ctx->t5, ctx->t2, p256_mod, p256_mp_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_256_mont_mul_9(ctx->z, p->z, ctx->t2, p256_mod, p256_mp_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
sp_256_mont_mul_9(ctx->z, ctx->z, q->z, p256_mod, p256_mp_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
sp_256_mont_sqr_9(ctx->x, ctx->t4, p256_mod, p256_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
sp_256_mont_sub_9(ctx->x, ctx->x, ctx->t5, p256_mod);
|
|
ctx->state = 19;
|
|
break;
|
|
case 19:
|
|
sp_256_mont_mul_9(ctx->t5, ctx->t5, ctx->t3, p256_mod, p256_mp_mod);
|
|
ctx->state = 20;
|
|
break;
|
|
case 20:
|
|
sp_256_mont_dbl_9(ctx->t3, ctx->y, p256_mod);
|
|
sp_256_mont_sub_9(ctx->x, ctx->x, ctx->t3, p256_mod);
|
|
ctx->state = 21;
|
|
break;
|
|
case 21:
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_256_mont_sub_lower_9(ctx->y, ctx->y, ctx->x, p256_mod);
|
|
ctx->state = 22;
|
|
break;
|
|
case 22:
|
|
sp_256_mont_mul_9(ctx->y, ctx->y, ctx->t4, p256_mod, p256_mp_mod);
|
|
ctx->state = 23;
|
|
break;
|
|
case 23:
|
|
sp_256_mont_sub_9(ctx->y, ctx->y, ctx->t5, p256_mod);
|
|
ctx->state = 24;
|
|
break;
|
|
case 24:
|
|
{
|
|
int i;
|
|
sp_digit maskp = 0 - (q->infinity & (!p->infinity));
|
|
sp_digit maskq = 0 - (p->infinity & (!q->infinity));
|
|
sp_digit maskt = ~(maskp | maskq);
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (ctx->x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (ctx->y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (ctx->z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
ctx->state = 25;
|
|
break;
|
|
}
|
|
case 25:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 25) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
/* Multiply a number by Montgomery normalizer mod modulus (prime).
|
|
*
|
|
* r The resulting Montgomery form number.
|
|
* a The number to convert.
|
|
* m The modulus (prime).
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_256_mod_mul_norm_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
int64_t* t = NULL;
|
|
#else
|
|
int64_t t[2 * 8];
|
|
#endif
|
|
int64_t* a32 = NULL;
|
|
int64_t o;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
return MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a32 = t + 8;
|
|
|
|
a32[0] = a[0];
|
|
a32[0] |= a[1] << 29U;
|
|
a32[0] &= 0xffffffffL;
|
|
a32[1] = (a[1] >> 3);
|
|
a32[1] |= a[2] << 26U;
|
|
a32[1] &= 0xffffffffL;
|
|
a32[2] = (a[2] >> 6);
|
|
a32[2] |= a[3] << 23U;
|
|
a32[2] &= 0xffffffffL;
|
|
a32[3] = (a[3] >> 9);
|
|
a32[3] |= a[4] << 20U;
|
|
a32[3] &= 0xffffffffL;
|
|
a32[4] = (a[4] >> 12);
|
|
a32[4] |= a[5] << 17U;
|
|
a32[4] &= 0xffffffffL;
|
|
a32[5] = (a[5] >> 15);
|
|
a32[5] |= a[6] << 14U;
|
|
a32[5] &= 0xffffffffL;
|
|
a32[6] = (a[6] >> 18);
|
|
a32[6] |= a[7] << 11U;
|
|
a32[6] &= 0xffffffffL;
|
|
a32[7] = (a[7] >> 21);
|
|
a32[7] |= a[8] << 8U;
|
|
a32[7] &= 0xffffffffL;
|
|
|
|
/* 1 1 0 -1 -1 -1 -1 0 */
|
|
t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6];
|
|
/* 0 1 1 0 -1 -1 -1 -1 */
|
|
t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7];
|
|
/* 0 0 1 1 0 -1 -1 -1 */
|
|
t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7];
|
|
/* -1 -1 0 2 2 1 0 -1 */
|
|
t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7];
|
|
/* 0 -1 -1 0 2 2 1 0 */
|
|
t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6];
|
|
/* 0 0 -1 -1 0 2 2 1 */
|
|
t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7];
|
|
/* -1 -1 0 0 0 1 3 2 */
|
|
t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7];
|
|
/* 1 0 -1 -1 -1 -1 0 3 */
|
|
t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7];
|
|
|
|
t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
|
|
t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
|
|
t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
|
|
t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
|
|
t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
|
|
t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
|
|
t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
|
|
o = t[7] >> 32U; t[7] &= 0xffffffffL;
|
|
t[0] += o;
|
|
t[3] -= o;
|
|
t[6] -= o;
|
|
t[7] += o;
|
|
t[1] += t[0] >> 32U; t[0] &= 0xffffffffL;
|
|
t[2] += t[1] >> 32U; t[1] &= 0xffffffffL;
|
|
t[3] += t[2] >> 32U; t[2] &= 0xffffffffL;
|
|
t[4] += t[3] >> 32U; t[3] &= 0xffffffffL;
|
|
t[5] += t[4] >> 32U; t[4] &= 0xffffffffL;
|
|
t[6] += t[5] >> 32U; t[5] &= 0xffffffffL;
|
|
t[7] += t[6] >> 32U; t[6] &= 0xffffffffL;
|
|
|
|
r[0] = (sp_digit)(t[0]) & 0x1fffffffL;
|
|
r[1] = (sp_digit)(t[0] >> 29U);
|
|
r[1] |= (sp_digit)(t[1] << 3U);
|
|
r[1] &= 0x1fffffffL;
|
|
r[2] = (sp_digit)(t[1] >> 26U);
|
|
r[2] |= (sp_digit)(t[2] << 6U);
|
|
r[2] &= 0x1fffffffL;
|
|
r[3] = (sp_digit)(t[2] >> 23U);
|
|
r[3] |= (sp_digit)(t[3] << 9U);
|
|
r[3] &= 0x1fffffffL;
|
|
r[4] = (sp_digit)(t[3] >> 20U);
|
|
r[4] |= (sp_digit)(t[4] << 12U);
|
|
r[4] &= 0x1fffffffL;
|
|
r[5] = (sp_digit)(t[4] >> 17U);
|
|
r[5] |= (sp_digit)(t[5] << 15U);
|
|
r[5] &= 0x1fffffffL;
|
|
r[6] = (sp_digit)(t[5] >> 14U);
|
|
r[6] |= (sp_digit)(t[6] << 18U);
|
|
r[6] &= 0x1fffffffL;
|
|
r[7] = (sp_digit)(t[6] >> 11U);
|
|
r[7] |= (sp_digit)(t[7] << 21U);
|
|
r[7] &= 0x1fffffffL;
|
|
r[8] = (sp_digit)(t[7] >> 8U);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Small implementation using add and double that is cache attack resistant but
|
|
* allocates memory rather than use large stacks.
|
|
* 256 adds and doubles.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_256 t[3];
|
|
sp_digit tmp[2 * 9 * 6];
|
|
#endif
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
int err = MP_OKAY;
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(t, 0, sizeof(sp_point_256) * 3);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod);
|
|
}
|
|
if (err == MP_OKAY)
|
|
err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod);
|
|
if (err == MP_OKAY)
|
|
err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod);
|
|
|
|
if (err == MP_OKAY) {
|
|
i = 8;
|
|
c = 24;
|
|
n = k[i--] << (29 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1)
|
|
break;
|
|
|
|
n = k[i--];
|
|
c = 29;
|
|
}
|
|
|
|
y = (n >> 28) & 1;
|
|
n <<= 1;
|
|
|
|
sp_256_proj_point_add_9(&t[y^1], &t[0], &t[1], tmp);
|
|
|
|
XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])),
|
|
sizeof(sp_point_256));
|
|
sp_256_proj_point_dbl_9(&t[2], &t[2], tmp);
|
|
XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])), &t[2],
|
|
sizeof(sp_point_256));
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_256_map_9(r, &t[0], tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &t[0], sizeof(sp_point_256));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(tmp, sizeof(sp_digit) * 2 * 9 * 6);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(t, sizeof(sp_point_256) * 3);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_256_ecc_mulmod_9_ctx {
|
|
int state;
|
|
union {
|
|
sp_256_proj_point_dbl_9_ctx dbl_ctx;
|
|
sp_256_proj_point_add_9_ctx add_ctx;
|
|
};
|
|
sp_point_256 t[3];
|
|
sp_digit tmp[2 * 9 * 6];
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
} sp_256_ecc_mulmod_9_ctx;
|
|
|
|
static int sp_256_ecc_mulmod_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
|
|
const sp_point_256* g, const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_256_ecc_mulmod_9_ctx* ctx = (sp_256_ecc_mulmod_9_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_256_ecc_mulmod_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
XMEMSET(ctx->t, 0, sizeof(sp_point_256) * 3);
|
|
ctx->i = 8;
|
|
ctx->c = 24;
|
|
ctx->n = k[ctx->i--] << (29 - ctx->c);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
ctx->t[0].infinity = 1;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* T1X */
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_256_mod_mul_norm_9(ctx->t[1].x, g->x, p256_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* T1Y */
|
|
err = sp_256_mod_mul_norm_9(ctx->t[1].y, g->y, p256_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* T1Z */
|
|
err = sp_256_mod_mul_norm_9(ctx->t[1].z, g->z, p256_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4: /* ADDPREP */
|
|
if (ctx->c == 0) {
|
|
if (ctx->i == -1) {
|
|
ctx->state = 7;
|
|
break;
|
|
}
|
|
|
|
ctx->n = k[ctx->i--];
|
|
ctx->c = 29;
|
|
}
|
|
ctx->y = (ctx->n >> 28) & 1;
|
|
ctx->n <<= 1;
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* ADD */
|
|
err = sp_256_proj_point_add_9_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
|
|
&ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])),
|
|
sizeof(sp_point_256));
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* DBL */
|
|
err = sp_256_proj_point_dbl_9_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
|
|
&ctx->t[2], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
|
|
sizeof(sp_point_256));
|
|
ctx->state = 4;
|
|
ctx->c--;
|
|
}
|
|
break;
|
|
case 7: /* MAP */
|
|
if (map != 0) {
|
|
sp_256_map_9(r, &ctx->t[0], ctx->tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &ctx->t[0], sizeof(sp_point_256));
|
|
}
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 7) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
ForceZero(ctx->tmp, sizeof(ctx->tmp));
|
|
ForceZero(ctx->t, sizeof(ctx->t));
|
|
}
|
|
|
|
(void)heap;
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#else
|
|
/* A table entry for pre-computed points. */
|
|
typedef struct sp_table_entry_256 {
|
|
sp_digit x[9];
|
|
sp_digit y[9];
|
|
} sp_table_entry_256;
|
|
|
|
/* Conditionally copy a into r using the mask m.
|
|
* m is -1 to copy and 0 when not.
|
|
*
|
|
* r A single precision number to copy over.
|
|
* a A single precision number to copy.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_256_cond_copy_9(sp_digit* r, const sp_digit* a, const sp_digit m)
|
|
{
|
|
sp_digit t[9];
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
t[i] = r[i] ^ a[i];
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r[i] ^= t[i] & m;
|
|
}
|
|
#else
|
|
t[ 0] = r[ 0] ^ a[ 0];
|
|
t[ 1] = r[ 1] ^ a[ 1];
|
|
t[ 2] = r[ 2] ^ a[ 2];
|
|
t[ 3] = r[ 3] ^ a[ 3];
|
|
t[ 4] = r[ 4] ^ a[ 4];
|
|
t[ 5] = r[ 5] ^ a[ 5];
|
|
t[ 6] = r[ 6] ^ a[ 6];
|
|
t[ 7] = r[ 7] ^ a[ 7];
|
|
t[ 8] = r[ 8] ^ a[ 8];
|
|
r[ 0] ^= t[ 0] & m;
|
|
r[ 1] ^= t[ 1] & m;
|
|
r[ 2] ^= t[ 2] & m;
|
|
r[ 3] ^= t[ 3] & m;
|
|
r[ 4] ^= t[ 4] & m;
|
|
r[ 5] ^= t[ 5] & m;
|
|
r[ 6] ^= t[ 6] & m;
|
|
r[ 7] ^= t[ 7] & m;
|
|
r[ 8] ^= t[ 8] & m;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#define sp_256_mont_dbl_lower_9 sp_256_mont_dbl_9
|
|
#define sp_256_mont_tpl_lower_9 sp_256_mont_tpl_9
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_proj_point_dbl_n_9(sp_point_256* p, int i,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*9;
|
|
sp_digit* b = t + 4*9;
|
|
sp_digit* t1 = t + 6*9;
|
|
sp_digit* t2 = t + 8*9;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
volatile int n = i;
|
|
|
|
x = p->x;
|
|
y = p->y;
|
|
z = p->z;
|
|
|
|
/* Y = 2*Y */
|
|
sp_256_mont_dbl_9(y, y, p256_mod);
|
|
/* W = Z^4 */
|
|
sp_256_mont_sqr_9(w, z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_9(w, w, p256_mod, p256_mp_mod);
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
while (--n > 0)
|
|
#else
|
|
while (--n >= 0)
|
|
#endif
|
|
{
|
|
/* A = 3*(X^2 - W) */
|
|
sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(t1, t1, w, p256_mod);
|
|
sp_256_mont_tpl_lower_9(a, t1, p256_mod);
|
|
/* B = X*Y^2 */
|
|
sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod);
|
|
sp_256_mont_dbl_9(t2, b, p256_mod);
|
|
sp_256_mont_sub_9(x, x, t2, p256_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_256_mont_sub_lower_9(t2, b, x, p256_mod);
|
|
sp_256_mont_dbl_lower_9(b, t2, p256_mod);
|
|
/* Z = Z*Y */
|
|
sp_256_mont_mul_9(z, z, y, p256_mod, p256_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
if (n != 0)
|
|
#endif
|
|
{
|
|
/* W = W*Y^4 */
|
|
sp_256_mont_mul_9(w, w, t1, p256_mod, p256_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(y, y, t1, p256_mod);
|
|
}
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* A = 3*(X^2 - W) */
|
|
sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(t1, t1, w, p256_mod);
|
|
sp_256_mont_tpl_lower_9(a, t1, p256_mod);
|
|
/* B = X*Y^2 */
|
|
sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod);
|
|
sp_256_mont_dbl_9(t2, b, p256_mod);
|
|
sp_256_mont_sub_9(x, x, t2, p256_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_256_mont_sub_lower_9(t2, b, x, p256_mod);
|
|
sp_256_mont_dbl_lower_9(b, t2, p256_mod);
|
|
/* Z = Z*Y */
|
|
sp_256_mont_mul_9(z, z, y, p256_mod, p256_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod);
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(y, y, t1, p256_mod);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Y = Y/2 */
|
|
sp_256_div2_9(y, y, p256_mod);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_proj_point_dbl_n_store_9(sp_point_256* r,
|
|
const sp_point_256* p, int n, int m, sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*9;
|
|
sp_digit* b = t + 4*9;
|
|
sp_digit* t1 = t + 6*9;
|
|
sp_digit* t2 = t + 8*9;
|
|
sp_digit* x = r[2*m].x;
|
|
sp_digit* y = r[(1<<n)*m].y;
|
|
sp_digit* z = r[2*m].z;
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0; i<9; i++) {
|
|
x[i] = p->x[i];
|
|
}
|
|
for (i=0; i<9; i++) {
|
|
y[i] = p->y[i];
|
|
}
|
|
for (i=0; i<9; i++) {
|
|
z[i] = p->z[i];
|
|
}
|
|
|
|
/* Y = 2*Y */
|
|
sp_256_mont_dbl_9(y, y, p256_mod);
|
|
/* W = Z^4 */
|
|
sp_256_mont_sqr_9(w, z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_9(w, w, p256_mod, p256_mp_mod);
|
|
j = m;
|
|
for (i=1; i<=n; i++) {
|
|
j *= 2;
|
|
|
|
/* A = 3*(X^2 - W) */
|
|
sp_256_mont_sqr_9(t1, x, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(t1, t1, w, p256_mod);
|
|
sp_256_mont_tpl_lower_9(a, t1, p256_mod);
|
|
/* B = X*Y^2 */
|
|
sp_256_mont_sqr_9(t1, y, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(b, t1, x, p256_mod, p256_mp_mod);
|
|
x = r[j].x;
|
|
/* X = A^2 - 2B */
|
|
sp_256_mont_sqr_9(x, a, p256_mod, p256_mp_mod);
|
|
sp_256_mont_dbl_9(t2, b, p256_mod);
|
|
sp_256_mont_sub_9(x, x, t2, p256_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_256_mont_sub_lower_9(t2, b, x, p256_mod);
|
|
sp_256_mont_dbl_lower_9(b, t2, p256_mod);
|
|
/* Z = Z*Y */
|
|
sp_256_mont_mul_9(r[j].z, z, y, p256_mod, p256_mp_mod);
|
|
z = r[j].z;
|
|
/* t1 = Y^4 */
|
|
sp_256_mont_sqr_9(t1, t1, p256_mod, p256_mp_mod);
|
|
if (i != n) {
|
|
/* W = W*Y^4 */
|
|
sp_256_mont_mul_9(w, w, t1, p256_mod, p256_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_256_mont_mul_9(y, b, a, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(y, y, t1, p256_mod);
|
|
/* Y = Y/2 */
|
|
sp_256_div2_9(r[j].y, y, p256_mod);
|
|
r[j].infinity = 0;
|
|
}
|
|
}
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* ra Result of addition.
|
|
* rs Result of subtraction.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_proj_point_add_sub_9(sp_point_256* ra,
|
|
sp_point_256* rs, const sp_point_256* p, const sp_point_256* q,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*9;
|
|
sp_digit* t3 = t + 4*9;
|
|
sp_digit* t4 = t + 6*9;
|
|
sp_digit* t5 = t + 8*9;
|
|
sp_digit* t6 = t + 10*9;
|
|
sp_digit* xa = ra->x;
|
|
sp_digit* ya = ra->y;
|
|
sp_digit* za = ra->z;
|
|
sp_digit* xs = rs->x;
|
|
sp_digit* ys = rs->y;
|
|
sp_digit* zs = rs->z;
|
|
|
|
|
|
XMEMCPY(xa, p->x, sizeof(p->x) / 2);
|
|
XMEMCPY(ya, p->y, sizeof(p->y) / 2);
|
|
XMEMCPY(za, p->z, sizeof(p->z) / 2);
|
|
ra->infinity = 0;
|
|
rs->infinity = 0;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_256_mont_sqr_9(t1, q->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t3, t1, q->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t1, t1, xa, p256_mod, p256_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_256_mont_sqr_9(t2, za, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t4, t2, za, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_256_mont_mul_9(t3, t3, ya, p256_mod, p256_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod);
|
|
/* H = U2 - U1 */
|
|
sp_256_mont_sub_9(t2, t2, t1, p256_mod);
|
|
/* RS = S2 + S1 */
|
|
sp_256_mont_add_9(t6, t4, t3, p256_mod);
|
|
/* R = S2 - S1 */
|
|
sp_256_mont_sub_9(t4, t4, t3, p256_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
/* ZS = H*Z1*Z2 */
|
|
sp_256_mont_mul_9(za, za, q->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(za, za, t2, p256_mod, p256_mp_mod);
|
|
XMEMCPY(zs, za, sizeof(p->z)/2);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
/* XS = RS^2 - H^3 - 2*U1*H^2 */
|
|
sp_256_mont_sqr_9(xa, t4, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_9(xs, t6, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(ya, t1, t5, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(xa, xa, t5, p256_mod);
|
|
sp_256_mont_sub_9(xs, xs, t5, p256_mod);
|
|
sp_256_mont_dbl_9(t1, ya, p256_mod);
|
|
sp_256_mont_sub_9(xa, xa, t1, p256_mod);
|
|
sp_256_mont_sub_9(xs, xs, t1, p256_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
/* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
|
|
sp_256_mont_sub_lower_9(ys, ya, xs, p256_mod);
|
|
sp_256_mont_sub_lower_9(ya, ya, xa, p256_mod);
|
|
sp_256_mont_mul_9(ya, ya, t4, p256_mod, p256_mp_mod);
|
|
sp_256_sub_9(t6, p256_mod, t6);
|
|
sp_256_mont_mul_9(ys, ys, t6, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t5, t5, t3, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(ya, ya, t5, p256_mod);
|
|
sp_256_mont_sub_9(ys, ys, t5, p256_mod);
|
|
}
|
|
|
|
/* Structure used to describe recoding of scalar multiplication. */
|
|
typedef struct ecc_recode_256 {
|
|
/* Index into pre-computation table. */
|
|
uint8_t i;
|
|
/* Use the negative of the point. */
|
|
uint8_t neg;
|
|
} ecc_recode_256;
|
|
|
|
/* The index into pre-computation table to use. */
|
|
static const uint8_t recode_index_9_6[66] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
|
|
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
|
0, 1,
|
|
};
|
|
|
|
/* Whether to negate y-ordinate. */
|
|
static const uint8_t recode_neg_9_6[66] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 0,
|
|
};
|
|
|
|
/* Recode the scalar for multiplication using pre-computed values and
|
|
* subtraction.
|
|
*
|
|
* k Scalar to multiply by.
|
|
* v Vector of operations to perform.
|
|
*/
|
|
static void sp_256_ecc_recode_6_9(const sp_digit* k, ecc_recode_256* v)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint8_t y;
|
|
int carry = 0;
|
|
int o;
|
|
sp_digit n;
|
|
|
|
j = 0;
|
|
n = k[j];
|
|
o = 0;
|
|
for (i=0; i<43; i++) {
|
|
y = (int8_t)n;
|
|
if (o + 6 < 29) {
|
|
y &= 0x3f;
|
|
n >>= 6;
|
|
o += 6;
|
|
}
|
|
else if (o + 6 == 29) {
|
|
n >>= 6;
|
|
if (++j < 9)
|
|
n = k[j];
|
|
o = 0;
|
|
}
|
|
else if (++j < 9) {
|
|
n = k[j];
|
|
y |= (uint8_t)((n << (29 - o)) & 0x3f);
|
|
o -= 23;
|
|
n >>= o;
|
|
}
|
|
|
|
y += (uint8_t)carry;
|
|
v[i].i = recode_index_9_6[y];
|
|
v[i].neg = recode_neg_9_6[y];
|
|
carry = (y >> 6) + v[i].neg;
|
|
}
|
|
}
|
|
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
/* Touch each possible point that could be being copied.
|
|
*
|
|
* r Point to copy into.
|
|
* table Table - start of the entires to access
|
|
* idx Index of entry to retrieve.
|
|
*/
|
|
static void sp_256_get_point_33_9(sp_point_256* r, const sp_point_256* table,
|
|
int idx)
|
|
{
|
|
int i;
|
|
sp_digit mask;
|
|
|
|
r->x[0] = 0;
|
|
r->x[1] = 0;
|
|
r->x[2] = 0;
|
|
r->x[3] = 0;
|
|
r->x[4] = 0;
|
|
r->x[5] = 0;
|
|
r->x[6] = 0;
|
|
r->x[7] = 0;
|
|
r->x[8] = 0;
|
|
r->y[0] = 0;
|
|
r->y[1] = 0;
|
|
r->y[2] = 0;
|
|
r->y[3] = 0;
|
|
r->y[4] = 0;
|
|
r->y[5] = 0;
|
|
r->y[6] = 0;
|
|
r->y[7] = 0;
|
|
r->y[8] = 0;
|
|
r->z[0] = 0;
|
|
r->z[1] = 0;
|
|
r->z[2] = 0;
|
|
r->z[3] = 0;
|
|
r->z[4] = 0;
|
|
r->z[5] = 0;
|
|
r->z[6] = 0;
|
|
r->z[7] = 0;
|
|
r->z[8] = 0;
|
|
for (i = 1; i < 33; i++) {
|
|
mask = 0 - (i == idx);
|
|
r->x[0] |= mask & table[i].x[0];
|
|
r->x[1] |= mask & table[i].x[1];
|
|
r->x[2] |= mask & table[i].x[2];
|
|
r->x[3] |= mask & table[i].x[3];
|
|
r->x[4] |= mask & table[i].x[4];
|
|
r->x[5] |= mask & table[i].x[5];
|
|
r->x[6] |= mask & table[i].x[6];
|
|
r->x[7] |= mask & table[i].x[7];
|
|
r->x[8] |= mask & table[i].x[8];
|
|
r->y[0] |= mask & table[i].y[0];
|
|
r->y[1] |= mask & table[i].y[1];
|
|
r->y[2] |= mask & table[i].y[2];
|
|
r->y[3] |= mask & table[i].y[3];
|
|
r->y[4] |= mask & table[i].y[4];
|
|
r->y[5] |= mask & table[i].y[5];
|
|
r->y[6] |= mask & table[i].y[6];
|
|
r->y[7] |= mask & table[i].y[7];
|
|
r->y[8] |= mask & table[i].y[8];
|
|
r->z[0] |= mask & table[i].z[0];
|
|
r->z[1] |= mask & table[i].z[1];
|
|
r->z[2] |= mask & table[i].z[2];
|
|
r->z[3] |= mask & table[i].z[3];
|
|
r->z[4] |= mask & table[i].z[4];
|
|
r->z[5] |= mask & table[i].z[5];
|
|
r->z[6] |= mask & table[i].z[6];
|
|
r->z[7] |= mask & table[i].z[7];
|
|
r->z[8] |= mask & table[i].z[8];
|
|
}
|
|
}
|
|
#endif /* !WC_NO_CACHE_RESISTANT */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Window technique of 6 bits. (Add-Sub variation.)
|
|
* Calculate 0..32 times the point. Use function that adds and
|
|
* subtracts the same two points.
|
|
* Recode to add or subtract one of the computed points.
|
|
* Double to push up.
|
|
* NOT a sliding window.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_mulmod_win_add_sub_9(sp_point_256* r, const sp_point_256* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_256 t[33+2];
|
|
sp_digit tmp[2 * 9 * 6];
|
|
#endif
|
|
sp_point_256* rt = NULL;
|
|
sp_point_256* p = NULL;
|
|
sp_digit* negy;
|
|
int i;
|
|
ecc_recode_256 v[43];
|
|
int err = MP_OKAY;
|
|
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) *
|
|
(33+2), heap, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6,
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
rt = t + 33;
|
|
p = t + 33+1;
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
XMEMSET(&t[0], 0, sizeof(t[0]));
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_256_mod_mul_norm_9(t[1].x, g->x, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_mod_mul_norm_9(t[1].y, g->y, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_mod_mul_norm_9(t[1].z, g->z, p256_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
t[1].infinity = 0;
|
|
/* t[2] ... t[32] */
|
|
sp_256_proj_point_dbl_n_store_9(t, &t[ 1], 5, 1, tmp);
|
|
sp_256_proj_point_add_9(&t[ 3], &t[ 2], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[ 6], &t[ 3], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[10], &t[ 5], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[12], &t[ 6], tmp);
|
|
sp_256_proj_point_dbl_9(&t[14], &t[ 7], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[15], &t[13], &t[14], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[18], &t[ 9], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[19], &t[17], &t[18], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[20], &t[10], tmp);
|
|
sp_256_proj_point_dbl_9(&t[22], &t[11], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[23], &t[21], &t[22], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[24], &t[12], tmp);
|
|
sp_256_proj_point_dbl_9(&t[26], &t[13], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[27], &t[25], &t[26], &t[ 1], tmp);
|
|
sp_256_proj_point_dbl_9(&t[28], &t[14], tmp);
|
|
sp_256_proj_point_dbl_9(&t[30], &t[15], tmp);
|
|
sp_256_proj_point_add_sub_9(&t[31], &t[29], &t[30], &t[ 1], tmp);
|
|
|
|
negy = t[0].y;
|
|
|
|
sp_256_ecc_recode_6_9(k, v);
|
|
|
|
i = 42;
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_256_get_point_33_9(rt, t, v[i].i);
|
|
rt->infinity = !v[i].i;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_256));
|
|
}
|
|
for (--i; i>=0; i--) {
|
|
sp_256_proj_point_dbl_n_9(rt, 6, tmp);
|
|
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_256_get_point_33_9(p, t, v[i].i);
|
|
p->infinity = !v[i].i;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(p, &t[v[i].i], sizeof(sp_point_256));
|
|
}
|
|
sp_256_sub_9(negy, p256_mod, p->y);
|
|
sp_256_norm_9(negy);
|
|
sp_256_cond_copy_9(p->y, negy, (sp_digit)0 - v[i].neg);
|
|
sp_256_proj_point_add_9(rt, rt, p, tmp);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_256_map_9(r, rt, tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_256));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp != NULL)
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#endif /* FP_ECC */
|
|
/* Add two Montgomery form projective points. The second point has a q value of
|
|
* one.
|
|
* Only the first point can be the same pointer as the result point.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_256_proj_point_add_qz1_9(sp_point_256* r,
|
|
const sp_point_256* p, const sp_point_256* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*9;
|
|
sp_digit* t3 = t + 4*9;
|
|
sp_digit* t4 = t + 6*9;
|
|
sp_digit* t5 = t + 8*9;
|
|
sp_digit* t6 = t + 10*9;
|
|
|
|
/* Calculate values to subtract from P->x and P->y. */
|
|
/* U2 = X2*Z1^2 */
|
|
sp_256_mont_sqr_9(t2, p->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t4, t2, p->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t2, t2, q->x, p256_mod, p256_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_256_mont_mul_9(t4, t4, q->y, p256_mod, p256_mp_mod);
|
|
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_256_cmp_equal_9(p->x, t2) &
|
|
sp_256_cmp_equal_9(p->y, t4)) {
|
|
sp_256_proj_point_dbl_9(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t2;
|
|
sp_digit* y = t5;
|
|
sp_digit* z = t6;
|
|
int i;
|
|
|
|
/* H = U2 - X1 */
|
|
sp_256_mont_sub_9(t2, t2, p->x, p256_mod);
|
|
/* R = S2 - Y1 */
|
|
sp_256_mont_sub_9(t4, t4, p->y, p256_mod);
|
|
/* Z3 = H*Z1 */
|
|
sp_256_mont_mul_9(z, p->z, t2, p256_mod, p256_mp_mod);
|
|
/* X3 = R^2 - H^3 - 2*X1*H^2 */
|
|
sp_256_mont_sqr_9(t1, t4, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_9(t5, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t3, p->x, t5, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t5, t5, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(x, t1, t5, p256_mod);
|
|
sp_256_mont_dbl_9(t1, t3, p256_mod);
|
|
sp_256_mont_sub_9(x, x, t1, p256_mod);
|
|
/* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
|
|
sp_256_mont_sub_lower_9(t3, t3, x, p256_mod);
|
|
sp_256_mont_mul_9(t3, t3, t4, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t5, t5, p->y, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sub_9(y, t3, t5, p256_mod);
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
for (i = 0; i < 9; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 9; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
/* Convert the projective point to affine.
|
|
* Ordinates are in Montgomery form.
|
|
*
|
|
* a Point to convert.
|
|
* t Temporary data.
|
|
*/
|
|
static void sp_256_proj_to_affine_9(sp_point_256* a, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 9;
|
|
sp_digit* tmp = t + 4 * 9;
|
|
|
|
sp_256_mont_inv_9(t1, a->z, tmp);
|
|
|
|
sp_256_mont_sqr_9(t2, t1, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(t1, t2, t1, p256_mod, p256_mp_mod);
|
|
|
|
sp_256_mont_mul_9(a->x, a->x, t2, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(a->y, a->y, t1, p256_mod, p256_mp_mod);
|
|
XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod));
|
|
}
|
|
|
|
/* Generate the pre-computed table of points for the base point.
|
|
*
|
|
* width = 8
|
|
* 256 entries
|
|
* 32 bits between
|
|
*
|
|
* a The base point.
|
|
* table Place to store generated point data.
|
|
* tmp Temporary data.
|
|
* heap Heap to use for allocation.
|
|
*/
|
|
static int sp_256_gen_stripe_table_9(const sp_point_256* a,
|
|
sp_table_entry_256* table, sp_digit* tmp, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* t = NULL;
|
|
#else
|
|
sp_point_256 t[3];
|
|
#endif
|
|
sp_point_256* s1 = NULL;
|
|
sp_point_256* s2 = NULL;
|
|
int i;
|
|
int j;
|
|
int err = MP_OKAY;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
s1 = t + 1;
|
|
s2 = t + 2;
|
|
|
|
err = sp_256_mod_mul_norm_9(t->x, a->x, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_mod_mul_norm_9(t->y, a->y, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_mod_mul_norm_9(t->z, a->z, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
t->infinity = 0;
|
|
sp_256_proj_to_affine_9(t, tmp);
|
|
|
|
XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod));
|
|
s1->infinity = 0;
|
|
XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod));
|
|
s2->infinity = 0;
|
|
|
|
/* table[0] = {0, 0, infinity} */
|
|
XMEMSET(&table[0], 0, sizeof(sp_table_entry_256));
|
|
/* table[1] = Affine version of 'a' in Montgomery form */
|
|
XMEMCPY(table[1].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1].y, t->y, sizeof(table->y));
|
|
|
|
for (i=1; i<8; i++) {
|
|
sp_256_proj_point_dbl_n_9(t, 32, tmp);
|
|
sp_256_proj_to_affine_9(t, tmp);
|
|
XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
|
|
}
|
|
|
|
for (i=1; i<8; i++) {
|
|
XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
|
|
XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
|
|
for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
|
|
XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
|
|
XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
|
|
sp_256_proj_point_add_qz1_9(t, s1, s2, tmp);
|
|
sp_256_proj_to_affine_9(t, tmp);
|
|
XMEMCPY(table[j].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[j].y, t->y, sizeof(table->y));
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* FP_ECC */
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
/* Touch each possible entry that could be being copied.
|
|
*
|
|
* r Point to copy into.
|
|
* table Table - start of the entires to access
|
|
* idx Index of entry to retrieve.
|
|
*/
|
|
static void sp_256_get_entry_256_9(sp_point_256* r,
|
|
const sp_table_entry_256* table, int idx)
|
|
{
|
|
int i;
|
|
sp_digit mask;
|
|
|
|
r->x[0] = 0;
|
|
r->x[1] = 0;
|
|
r->x[2] = 0;
|
|
r->x[3] = 0;
|
|
r->x[4] = 0;
|
|
r->x[5] = 0;
|
|
r->x[6] = 0;
|
|
r->x[7] = 0;
|
|
r->x[8] = 0;
|
|
r->y[0] = 0;
|
|
r->y[1] = 0;
|
|
r->y[2] = 0;
|
|
r->y[3] = 0;
|
|
r->y[4] = 0;
|
|
r->y[5] = 0;
|
|
r->y[6] = 0;
|
|
r->y[7] = 0;
|
|
r->y[8] = 0;
|
|
for (i = 1; i < 256; i++) {
|
|
mask = 0 - (i == idx);
|
|
r->x[0] |= mask & table[i].x[0];
|
|
r->x[1] |= mask & table[i].x[1];
|
|
r->x[2] |= mask & table[i].x[2];
|
|
r->x[3] |= mask & table[i].x[3];
|
|
r->x[4] |= mask & table[i].x[4];
|
|
r->x[5] |= mask & table[i].x[5];
|
|
r->x[6] |= mask & table[i].x[6];
|
|
r->x[7] |= mask & table[i].x[7];
|
|
r->x[8] |= mask & table[i].x[8];
|
|
r->y[0] |= mask & table[i].y[0];
|
|
r->y[1] |= mask & table[i].y[1];
|
|
r->y[2] |= mask & table[i].y[2];
|
|
r->y[3] |= mask & table[i].y[3];
|
|
r->y[4] |= mask & table[i].y[4];
|
|
r->y[5] |= mask & table[i].y[5];
|
|
r->y[6] |= mask & table[i].y[6];
|
|
r->y[7] |= mask & table[i].y[7];
|
|
r->y[8] |= mask & table[i].y[8];
|
|
}
|
|
}
|
|
#endif /* !WC_NO_CACHE_RESISTANT */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^32, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* table Pre-computed table.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_mulmod_stripe_9(sp_point_256* r, const sp_point_256* g,
|
|
const sp_table_entry_256* table, const sp_digit* k, int map,
|
|
int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* rt = NULL;
|
|
sp_digit* t = NULL;
|
|
#else
|
|
sp_point_256 rt[2];
|
|
sp_digit t[2 * 9 * 6];
|
|
#endif
|
|
sp_point_256* p = NULL;
|
|
int i;
|
|
int j;
|
|
int y;
|
|
int x;
|
|
int err = MP_OKAY;
|
|
|
|
(void)g;
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
rt = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (rt == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = rt + 1;
|
|
|
|
XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod));
|
|
XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod));
|
|
|
|
y = 0;
|
|
x = 31;
|
|
for (j=0; j<8; j++) {
|
|
y |= (int)(((k[x / 29] >> (x % 29)) & 1) << j);
|
|
x += 32;
|
|
}
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_256_get_entry_256_9(rt, table, y);
|
|
} else
|
|
#endif
|
|
{
|
|
XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
|
|
}
|
|
rt->infinity = !y;
|
|
for (i=30; i>=0; i--) {
|
|
y = 0;
|
|
x = i;
|
|
for (j=0; j<8; j++) {
|
|
y |= (int)(((k[x / 29] >> (x % 29)) & 1) << j);
|
|
x += 32;
|
|
}
|
|
|
|
sp_256_proj_point_dbl_9(rt, rt, t);
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_256_get_entry_256_9(p, table, y);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
|
|
}
|
|
p->infinity = !y;
|
|
sp_256_proj_point_add_qz1_9(rt, rt, p, t);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_256_map_9(r, rt, t);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_256));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (rt != NULL)
|
|
XFREE(rt, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#ifndef FP_ENTRIES
|
|
#define FP_ENTRIES 16
|
|
#endif
|
|
|
|
/* Cache entry - holds precomputation tables for a point. */
|
|
typedef struct sp_cache_256_t {
|
|
/* X ordinate of point that table was generated from. */
|
|
sp_digit x[9];
|
|
/* Y ordinate of point that table was generated from. */
|
|
sp_digit y[9];
|
|
/* Precomputation table for point. */
|
|
sp_table_entry_256 table[256];
|
|
/* Count of entries in table. */
|
|
uint32_t cnt;
|
|
/* Point and table set in entry. */
|
|
int set;
|
|
} sp_cache_256_t;
|
|
|
|
/* Cache of tables. */
|
|
static THREAD_LS_T sp_cache_256_t sp_cache_256[FP_ENTRIES];
|
|
/* Index of last entry in cache. */
|
|
static THREAD_LS_T int sp_cache_256_last = -1;
|
|
/* Cache has been initialized. */
|
|
static THREAD_LS_T int sp_cache_256_inited = 0;
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
static volatile int initCacheMutex_256 = 0;
|
|
static wolfSSL_Mutex sp_cache_256_lock;
|
|
#endif
|
|
|
|
/* Get the cache entry for the point.
|
|
*
|
|
* g [in] Point scalar multipling.
|
|
* cache [out] Cache table to use.
|
|
*/
|
|
static void sp_ecc_get_cache_256(const sp_point_256* g, sp_cache_256_t** cache)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint32_t least;
|
|
|
|
if (sp_cache_256_inited == 0) {
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
sp_cache_256[i].set = 0;
|
|
}
|
|
sp_cache_256_inited = 1;
|
|
}
|
|
|
|
/* Compare point with those in cache. */
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
if (!sp_cache_256[i].set)
|
|
continue;
|
|
|
|
if (sp_256_cmp_equal_9(g->x, sp_cache_256[i].x) &
|
|
sp_256_cmp_equal_9(g->y, sp_cache_256[i].y)) {
|
|
sp_cache_256[i].cnt++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* No match. */
|
|
if (i == FP_ENTRIES) {
|
|
/* Find empty entry. */
|
|
i = (sp_cache_256_last + 1) % FP_ENTRIES;
|
|
for (; i != sp_cache_256_last; i=(i+1)%FP_ENTRIES) {
|
|
if (!sp_cache_256[i].set) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Evict least used. */
|
|
if (i == sp_cache_256_last) {
|
|
least = sp_cache_256[0].cnt;
|
|
for (j=1; j<FP_ENTRIES; j++) {
|
|
if (sp_cache_256[j].cnt < least) {
|
|
i = j;
|
|
least = sp_cache_256[i].cnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
XMEMCPY(sp_cache_256[i].x, g->x, sizeof(sp_cache_256[i].x));
|
|
XMEMCPY(sp_cache_256[i].y, g->y, sizeof(sp_cache_256[i].y));
|
|
sp_cache_256[i].set = 1;
|
|
sp_cache_256[i].cnt = 1;
|
|
}
|
|
|
|
*cache = &sp_cache_256[i];
|
|
sp_cache_256_last = i;
|
|
}
|
|
#endif /* FP_ECC */
|
|
|
|
/* Multiply the base point of P256 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_mulmod_9(sp_point_256* r, const sp_point_256* g, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
#ifndef FP_ECC
|
|
return sp_256_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap);
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp;
|
|
#else
|
|
sp_digit tmp[2 * 9 * 6];
|
|
#endif
|
|
sp_cache_256_t* cache;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
#ifndef HAVE_THREAD_LS
|
|
if (err == MP_OKAY) {
|
|
if (initCacheMutex_256 == 0) {
|
|
wc_InitMutex(&sp_cache_256_lock);
|
|
initCacheMutex_256 = 1;
|
|
}
|
|
if (wc_LockMutex(&sp_cache_256_lock) != 0) {
|
|
err = BAD_MUTEX_E;
|
|
}
|
|
}
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_ecc_get_cache_256(g, &cache);
|
|
if (cache->cnt == 2)
|
|
sp_256_gen_stripe_table_9(g, cache->table, tmp, heap);
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
wc_UnLockMutex(&sp_cache_256_lock);
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (cache->cnt < 2) {
|
|
err = sp_256_ecc_mulmod_win_add_sub_9(r, g, k, map, ct, heap);
|
|
}
|
|
else {
|
|
err = sp_256_ecc_mulmod_stripe_9(r, g, cache->table, k,
|
|
map, ct, heap);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_256(const mp_int* km, const ecc_point* gm, ecc_point* r,
|
|
int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_256 point[1];
|
|
sp_digit k[9];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_256_from_mp(k, 9, km);
|
|
sp_256_point_from_ecc_point_9(point, gm);
|
|
|
|
err = sp_256_ecc_mulmod_9(point, point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_point_to_ecc_point_9(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the point by the scalar, add point a and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_add_256(const mp_int* km, const ecc_point* gm,
|
|
const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_256 point[2];
|
|
sp_digit k[9 + 9 * 2 * 6];
|
|
#endif
|
|
sp_point_256* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (9 + 9 * 2 * 6), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 9;
|
|
|
|
sp_256_from_mp(k, 9, km);
|
|
sp_256_point_from_ecc_point_9(point, gm);
|
|
sp_256_point_from_ecc_point_9(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_256_mod_mul_norm_9(addP->x, addP->x, p256_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_256_mod_mul_norm_9(addP->y, addP->y, p256_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_256_mod_mul_norm_9(addP->z, addP->z, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_ecc_mulmod_9(point, point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_256_proj_point_add_9(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_256_map_9(point, point, tmp);
|
|
}
|
|
|
|
err = sp_256_point_to_ecc_point_9(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the base point of P256 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_256_ecc_mulmod_9(r, &p256_base, k, map, ct, heap);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
static int sp_256_ecc_mulmod_base_9_nb(sp_ecc_ctx_t* sp_ctx, sp_point_256* r,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_256_ecc_mulmod_9_nb(sp_ctx, r, &p256_base, k, map, ct, heap);
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
|
|
#else
|
|
/* Striping precomputation table.
|
|
* 8 points combined into a table of 256 points.
|
|
* Distance of 32 between points.
|
|
*/
|
|
static const sp_table_entry_256 p256_table[256] = {
|
|
/* 0 */
|
|
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
|
/* 1 */
|
|
{ { 0x18a9143c,0x0f3986a0,0x1b6d805e,0x152bf8bf,0x0251075b,0x1995bbb1,
|
|
0x1719e7ed,0x0ed4a6ea,0x0018905f },
|
|
{ 0x0e95560a,0x0f929abe,0x06791737,0x1571c974,0x1f3258b4,0x03446e90,
|
|
0x16174ba2,0x0304b10b,0x008571ff } },
|
|
/* 2 */
|
|
{ { 0x0147519a,0x01443012,0x0cdcbc08,0x103d584d,0x1ebc8d09,0x13e553c2,
|
|
0x03a6a752,0x01bb7beb,0x00d953c5 },
|
|
{ 0x1d590f8f,0x0b1b0e67,0x19b245e7,0x12c4d689,0x164cf72e,0x10881175,
|
|
0x03cdff65,0x0fd3d651,0x00863ebb } },
|
|
/* 3 */
|
|
{ { 0x1cdb6485,0x02b5b11a,0x028be5de,0x1e1d445e,0x0300b808,0x0caa27bf,
|
|
0x0280f9a3,0x0ab6bff0,0x00000760 },
|
|
{ 0x038d2010,0x11a75cdc,0x10dc229d,0x029f7664,0x06606540,0x1e9cc215,
|
|
0x1b838391,0x0c2686e7,0x00830877 } },
|
|
/* 4 */
|
|
{ { 0x16a0d2bb,0x1c917e28,0x188d2653,0x1982d834,0x02c8b0d5,0x079d2be3,
|
|
0x19fe4907,0x0c3fa36c,0x002f5e69 },
|
|
{ 0x15a01797,0x00ae385f,0x05586497,0x01689ac1,0x1db523d2,0x0d9b838f,
|
|
0x1dec1244,0x02d1ade1,0x00f648f9 } },
|
|
/* 5 */
|
|
{ { 0x0137bbbc,0x12b3423f,0x1a82fb27,0x088d3d14,0x13463e43,0x13b0bceb,
|
|
0x0056c710,0x10a267a0,0x005abe02 },
|
|
{ 0x004c7dab,0x15541be6,0x098301e4,0x1b3e9886,0x0cc37573,0x0ab13c73,
|
|
0x0e0c324c,0x0b6d6dee,0x0094bb72 } },
|
|
/* 6 */
|
|
{ { 0x120f141c,0x1fcda47b,0x1d6f1d2e,0x13679a5b,0x045c4619,0x1094a088,
|
|
0x13bf70fd,0x1965efb8,0x00cdd6bb },
|
|
{ 0x0af436fd,0x0533805f,0x04c9afb3,0x08fedb73,0x125226f6,0x13c900a7,
|
|
0x17d8303e,0x17a97b5c,0x00a361be } },
|
|
/* 7 */
|
|
{ { 0x197c13c7,0x05512ac2,0x0df0f84a,0x1ac6bea1,0x09d1dc38,0x0d7679e0,
|
|
0x04b01c0e,0x013896a5,0x00ba12ca },
|
|
{ 0x19f91dfd,0x12047d22,0x1a81fee7,0x0876cd9d,0x00b293af,0x1844cebc,
|
|
0x1d2c7b3a,0x13ae03fd,0x0053ebb9 } },
|
|
/* 8 */
|
|
{ { 0x10e63d34,0x1f3f718d,0x1953ead3,0x000ae553,0x1b5a4f46,0x199a6af3,
|
|
0x00c70124,0x1240daa9,0x008589fb },
|
|
{ 0x0583553a,0x1387ae63,0x1592796a,0x121295c4,0x04652087,0x02838802,
|
|
0x113f3241,0x0da04a83,0x00ebb069 } },
|
|
/* 9 */
|
|
{ { 0x0c1647c5,0x10b650ad,0x13d5e651,0x04fa8f89,0x1fbacb81,0x1551bb26,
|
|
0x168f7199,0x197a364f,0x00eb2820 },
|
|
{ 0x0a87e008,0x0037c6c3,0x08de3ce5,0x1bf53b24,0x0ecb2d87,0x17214066,
|
|
0x08755bb4,0x136ab4fb,0x001f2828 } },
|
|
/* 10 */
|
|
{ { 0x1b89da99,0x1dd50601,0x0a1008aa,0x05af3d70,0x005e8a6f,0x1c315c0e,
|
|
0x158c9e11,0x0b20bca9,0x00337a4b },
|
|
{ 0x01f7794a,0x033a8069,0x1b5fd84f,0x000b6efa,0x1d6e8207,0x1bc08267,
|
|
0x0f582968,0x1abe985f,0x000d65e0 } },
|
|
/* 11 */
|
|
{ { 0x15275d38,0x0e84ddf5,0x1828d636,0x114e8a17,0x0b265426,0x17fa4b9f,
|
|
0x08cbc1d8,0x084a5e94,0x00c23da2 },
|
|
{ 0x0b94520c,0x0d0dc278,0x16f5e397,0x0ccec760,0x09ea1096,0x05c34a69,
|
|
0x1fc4e937,0x1198f219,0x0019de3b } },
|
|
/* 12 */
|
|
{ { 0x06c5fe04,0x01d38b61,0x0e86f6c6,0x11bc1677,0x1712c3b2,0x02c35265,
|
|
0x0ff5d0cb,0x1a923f99,0x00e34dcb },
|
|
{ 0x0aa58403,0x0046a35d,0x1a5e94ed,0x12e90d05,0x0a8af9a6,0x00939b55,
|
|
0x1dfe78e4,0x088f69c1,0x00e7641f } },
|
|
/* 13 */
|
|
{ { 0x1f64ba59,0x0ba9ca0e,0x0090bf1f,0x1e21d816,0x01859d33,0x0fe350ac,
|
|
0x1efd3c1b,0x0ae0a54a,0x004a12df },
|
|
{ 0x1439dbd0,0x1d319c7c,0x194f87ef,0x0497a97b,0x1b314d3c,0x07fd10f8,
|
|
0x091bf579,0x12776b7d,0x006af5aa } },
|
|
/* 14 */
|
|
{ { 0x10c91999,0x1085b4c8,0x16012476,0x09688054,0x020900a2,0x0a5a5c66,
|
|
0x004cf802,0x0b4cd488,0x005fe347 },
|
|
{ 0x193e7b4b,0x07c655ef,0x08fe46ac,0x16a034f8,0x06263292,0x04d7668f,
|
|
0x04590ba2,0x011d9fd5,0x00b544e3 } },
|
|
/* 15 */
|
|
{ { 0x16ddfdce,0x03c63748,0x045e7999,0x0522cdf1,0x067e12c3,0x173b26a7,
|
|
0x082d3a35,0x17b4d618,0x00e0b6b2 },
|
|
{ 0x1b7efb57,0x09896f95,0x031001c3,0x181bbcf2,0x1c9441aa,0x1b56b3cd,
|
|
0x1dd3e40c,0x1bc4b4c6,0x0071c023 } },
|
|
/* 16 */
|
|
{ { 0x1fe20925,0x15461225,0x173a19d8,0x0335871f,0x0706391c,0x12eaee9c,
|
|
0x13d96a5a,0x1a843a64,0x0061d587 },
|
|
{ 0x037173ea,0x03b39d15,0x1de2d97a,0x090010a6,0x0b43e238,0x020f02dd,
|
|
0x1ef843e1,0x0248c43d,0x00fa11fe } },
|
|
/* 17 */
|
|
{ { 0x0cb19ffd,0x0448f959,0x048f08c7,0x151ab763,0x1ca8e01b,0x1eb3c562,
|
|
0x1b72db40,0x0983e277,0x00586eb0 },
|
|
{ 0x07e8ed09,0x01ae3729,0x067b7883,0x03467830,0x052fa1e8,0x0b602b63,
|
|
0x1c449e3f,0x010e10c9,0x0019d5ac } },
|
|
/* 18 */
|
|
{ { 0x109a4e1f,0x14cfac09,0x09c01d07,0x1bce37d2,0x08d20ab7,0x1785f7e9,
|
|
0x18fc9a97,0x07eff38a,0x00e7c007 },
|
|
{ 0x0ef59f76,0x1b6b31d0,0x1f2c1407,0x1676a841,0x002d4669,0x0fbd3d33,
|
|
0x102b0230,0x1fd8cb67,0x00e08504 } },
|
|
/* 19 */
|
|
{ { 0x0031b3ca,0x04c7b46d,0x169b59bc,0x19573dcd,0x046e86d1,0x00fd4a79,
|
|
0x1ad16ff6,0x104b6132,0x0078f018 },
|
|
{ 0x1a25787f,0x1f77ef21,0x132b26ed,0x0df01a3b,0x1fc36801,0x043bd9ad,
|
|
0x11e833a9,0x170fd28e,0x0043a773 } },
|
|
/* 20 */
|
|
{ { 0x12b533d5,0x12bbb9a6,0x0f777018,0x1715ed43,0x0c293673,0x1e4d53cf,
|
|
0x1ac55df9,0x0a38764c,0x00bb6de6 },
|
|
{ 0x165259b3,0x1f4981d5,0x0e9d2039,0x015fa7a0,0x0fc27d6a,0x01e8cd9e,
|
|
0x066f16b2,0x134ba317,0x0060b461 } },
|
|
/* 21 */
|
|
{ { 0x1ae5aa1c,0x0b51c708,0x19cd962f,0x0eca5693,0x187edb8b,0x000a772f,
|
|
0x1f342c4c,0x1655dd7f,0x009d0f27 },
|
|
{ 0x1a730a55,0x1492318b,0x0ef20eb2,0x0ab65fbb,0x19a719c9,0x0ff05600,
|
|
0x12341f07,0x0da6add8,0x00244a56 } },
|
|
/* 22 */
|
|
{ { 0x0acf1f96,0x0d81ca57,0x1309c71b,0x02455204,0x1d3b99f2,0x160dc165,
|
|
0x1da4989a,0x10e6b03d,0x0045e58c },
|
|
{ 0x038f9dbc,0x1ffa3ced,0x02281034,0x15e28dd1,0x0bed7a8a,0x0fd92370,
|
|
0x1e92516b,0x03983c96,0x00c040e2 } },
|
|
/* 23 */
|
|
{ { 0x0f8117b6,0x03d78003,0x08d50ce1,0x12d3fee7,0x075eb651,0x1abb0eca,
|
|
0x1b1d20ac,0x12ed058d,0x001cdf5c },
|
|
{ 0x11f04839,0x0dbbada0,0x1785a61f,0x1d59e891,0x132197db,0x0ee8db85,
|
|
0x1cf6ca48,0x1f1525bf,0x00046755 } },
|
|
/* 24 */
|
|
{ { 0x1ce8ffcd,0x04562e95,0x1986a0b3,0x0789165f,0x0d6c70d5,0x10b93901,
|
|
0x17cfdbc5,0x02277074,0x00046e5e },
|
|
{ 0x18007f01,0x1dc7fb26,0x1d0c60f9,0x03de24b5,0x1a03c7fb,0x0f531af0,
|
|
0x016c1171,0x186607a0,0x006e0106 } },
|
|
/* 25 */
|
|
{ { 0x08dd73b1,0x0639ac24,0x17b43652,0x00e11f32,0x02ab7767,0x0f5462b5,
|
|
0x1c7ce0e1,0x1dbd2039,0x00442594 },
|
|
{ 0x12d4b65b,0x07d51648,0x12430dfe,0x0468772d,0x18d1f94c,0x1250af4b,
|
|
0x1a3b4c9b,0x0a2985dc,0x00a796fa } },
|
|
/* 26 */
|
|
{ { 0x023addd7,0x0cfdb024,0x19a4eccd,0x14c307ca,0x13c809e2,0x1bc71e5f,
|
|
0x1ba7e216,0x1538d2ec,0x00e4ad2d },
|
|
{ 0x0e048a61,0x0bfbfa14,0x04b6680d,0x1a331981,0x0d8ef082,0x0d7a601f,
|
|
0x050ff0e8,0x08d86f6a,0x00c5e940 } },
|
|
/* 27 */
|
|
{ { 0x0be75f9e,0x1b529c61,0x048e9e11,0x0353d196,0x1c04b6fd,0x06f85884,
|
|
0x1d1f6179,0x15fb68c8,0x0063283d },
|
|
{ 0x1af2df15,0x139467bd,0x1669fd33,0x0588aa15,0x0bcc3e59,0x1356f41a,
|
|
0x04e3eac8,0x15633035,0x0068bd19 } },
|
|
/* 28 */
|
|
{ { 0x1887d659,0x04756a88,0x164c16b0,0x09abe966,0x14fe3337,0x14c0e7f3,
|
|
0x1f5a5a61,0x1ea78dfb,0x00495292 },
|
|
{ 0x1acec896,0x143c64f0,0x16d12112,0x096421d8,0x160a7d96,0x1bf13326,
|
|
0x00dd9a5b,0x01a4c06d,0x000ec753 } },
|
|
/* 29 */
|
|
{ { 0x0d2687bb,0x0d09d02d,0x0b887e8b,0x1076d5e6,0x0607ba1f,0x0f7a8eea,
|
|
0x1c2ce43d,0x14cc90c7,0x000f6207 },
|
|
{ 0x0f138233,0x0b3f1dd8,0x0aa9c62f,0x0d72d84e,0x088aedd6,0x02039376,
|
|
0x173e3b40,0x0e411dad,0x00ff0db0 } },
|
|
/* 30 */
|
|
{ { 0x0c95d553,0x04fd080a,0x1a02a29d,0x00a5faba,0x1566fa44,0x018bff9d,
|
|
0x1a8c60ed,0x07910e81,0x00313b51 },
|
|
{ 0x08d11549,0x00171560,0x17b8872d,0x1dc21769,0x0320e071,0x03eea3f9,
|
|
0x1e049ae6,0x1f30de33,0x002d3abc } },
|
|
/* 31 */
|
|
{ { 0x015581a2,0x0144280c,0x08846bd3,0x14daacc6,0x12e999a0,0x1d078655,
|
|
0x137c66e9,0x021bdb31,0x00c036fa },
|
|
{ 0x01fbd009,0x0d7045d6,0x1456058a,0x1163200d,0x00d8f0b6,0x193bcdcf,
|
|
0x06530bac,0x1896da80,0x00a6b2a2 } },
|
|
/* 32 */
|
|
{ { 0x0d3549cf,0x019f287b,0x135997b5,0x06d2dff5,0x1fcb46f3,0x1ed66708,
|
|
0x0181a56f,0x0a55ef93,0x00810ee2 },
|
|
{ 0x1159bb2c,0x0a287f0b,0x02cd5ed9,0x1f7d7ceb,0x1ea72f7d,0x1f3a6b4f,
|
|
0x1d14ac15,0x0f524e62,0x00d48571 } },
|
|
/* 33 */
|
|
{ { 0x10cb5a98,0x0ba0d457,0x0c442fc4,0x151f263e,0x02adfd3d,0x1165d59c,
|
|
0x01386653,0x14e5f34c,0x006a6045 },
|
|
{ 0x02b2411d,0x186069fd,0x03a5b805,0x1d707ca2,0x1b3ccbe0,0x0fb9c432,
|
|
0x1e40ef32,0x1f5f3c2a,0x00d3e45c } },
|
|
/* 34 */
|
|
{ { 0x083f7669,0x10fb4ddf,0x01df5af3,0x115d04e5,0x0278d09f,0x172a1922,
|
|
0x06725522,0x1bdc7858,0x00207755 },
|
|
{ 0x0fef1945,0x1deb0ecb,0x0b4a30e1,0x0279df62,0x164aa188,0x08eb396f,
|
|
0x00367ef3,0x1cae2a96,0x0048dc5e } },
|
|
/* 35 */
|
|
{ { 0x17e5a199,0x11bc85ff,0x0732edc4,0x1f719f31,0x19c79e0e,0x15ff0528,
|
|
0x111709e8,0x1dbbfede,0x00f2fb0a },
|
|
{ 0x10b5025f,0x0e04abaf,0x1ea7c890,0x0a87ae81,0x1fbd0550,0x04569c05,
|
|
0x14963e8f,0x02bb651a,0x00a13e90 } },
|
|
/* 36 */
|
|
{ { 0x02b65cbc,0x0fbd1a85,0x119089be,0x0972e454,0x107a10b0,0x1120f11f,
|
|
0x09bc9973,0x160292ea,0x002bf0d6 },
|
|
{ 0x0b216fb7,0x1ea6e9fa,0x17689ab4,0x0f70cff7,0x0505cf7d,0x1c1fb384,
|
|
0x027ebade,0x0b42c5fd,0x0042a94a } },
|
|
/* 37 */
|
|
{ { 0x0aadf191,0x0235685f,0x089a35d6,0x1491204b,0x1c1f60f8,0x182824a6,
|
|
0x18f7a180,0x0d38cbdb,0x002c2dd9 },
|
|
{ 0x13849c17,0x0810b8ec,0x0894375b,0x0911743b,0x05485460,0x03831e1d,
|
|
0x16f12043,0x03e858ad,0x00f437fa } },
|
|
/* 38 */
|
|
{ { 0x0a0f7dab,0x1506b8a2,0x1dba6b1a,0x092f262e,0x197860f0,0x10287af9,
|
|
0x0aa14b02,0x066a8e0f,0x00aaf45b },
|
|
{ 0x018d364a,0x0f1be19e,0x125c5961,0x17360c7c,0x05444d40,0x0b408af6,
|
|
0x0af3d05c,0x01be9e4e,0x00cdf631 } },
|
|
/* 39 */
|
|
{ { 0x0ea8b7ef,0x039e311c,0x0f08a1dd,0x126a310b,0x08e3408e,0x13b915ed,
|
|
0x1fc90655,0x175b53c5,0x00f0d008 },
|
|
{ 0x0414d3b1,0x089338e9,0x067a9d8a,0x0a930b60,0x1cbdbb37,0x1cb6a29d,
|
|
0x0e2d7186,0x1eb9510f,0x005bd5c2 } },
|
|
/* 40 */
|
|
{ { 0x149a3154,0x187a34f7,0x0acba6bb,0x0b4b2adc,0x04a9c3e8,0x160f5549,
|
|
0x1c6516ab,0x191413c8,0x00aa12df },
|
|
{ 0x0df69f1d,0x1793913a,0x1fd79cc9,0x09905945,0x1dd44e0e,0x0739dbd4,
|
|
0x0406e763,0x0e7c9195,0x006c036e } },
|
|
/* 41 */
|
|
{ { 0x0f6e3138,0x07d70950,0x0b4d1697,0x0dde004b,0x12bc5696,0x0325a2b3,
|
|
0x1892264f,0x0b12d5f7,0x00292ff6 },
|
|
{ 0x1e213402,0x09286a22,0x04b27fb5,0x101c4e87,0x072e8f65,0x1cbfed0e,
|
|
0x09d825ec,0x1206236e,0x00644e0c } },
|
|
/* 42 */
|
|
{ { 0x047153f0,0x0f210f0d,0x01063278,0x1876f324,0x17672b86,0x0743b82e,
|
|
0x09de4ef7,0x127956f3,0x00f25ae7 },
|
|
{ 0x0d869d0c,0x198ca51b,0x01b09907,0x0b910493,0x0945e9d5,0x0f5184b7,
|
|
0x08f927ed,0x0a627b61,0x0039b8e6 } },
|
|
/* 43 */
|
|
{ { 0x16fd2e59,0x1baa1005,0x157263cd,0x0580cd24,0x0573935e,0x190d0715,
|
|
0x0c1b676a,0x05e1e33b,0x0039122f },
|
|
{ 0x03cad53c,0x1de70f00,0x1705f8f3,0x16581fcc,0x13877225,0x18e94d50,
|
|
0x1e35caeb,0x1f19d01f,0x008de80a } },
|
|
/* 44 */
|
|
{ { 0x007bbb76,0x1df546c9,0x1e09d62b,0x18fcf842,0x036b1921,0x1ba58e02,
|
|
0x10137e8a,0x00c5c6d1,0x00871949 },
|
|
{ 0x03993df5,0x0fc945dd,0x0cf49aad,0x1aeb6be7,0x15050639,0x13c542da,
|
|
0x1784046a,0x0d4b6e9f,0x00fc315e } },
|
|
/* 45 */
|
|
{ { 0x08d6ecfa,0x10fea0d7,0x1b1fe195,0x1889ec35,0x0741d5f8,0x153da492,
|
|
0x02226114,0x15bdc712,0x00e6d4a7 },
|
|
{ 0x0593c75d,0x02a9768a,0x09c45898,0x0e1b49ba,0x0c7db70a,0x0f49bdd1,
|
|
0x195f4abb,0x13537c55,0x0035dfaf } },
|
|
/* 46 */
|
|
{ { 0x0a736636,0x1cab7e6d,0x0b2adf9a,0x0a3b2f5c,0x0996609f,0x1fa0879a,
|
|
0x14afec42,0x1ae39061,0x001da5c7 },
|
|
{ 0x1cce6825,0x020f2419,0x15cf0ed7,0x1a231ff2,0x036b815a,0x0963f918,
|
|
0x075a8a15,0x1fbb7e97,0x007077c0 } },
|
|
/* 47 */
|
|
{ { 0x06b9661c,0x1b1ffc6a,0x0b3f5c6f,0x1fa6d61a,0x1f8f7a1d,0x10a05423,
|
|
0x19100dcf,0x05dca1df,0x0053a863 },
|
|
{ 0x096d8051,0x0bb7fb43,0x13d1a282,0x18192b8e,0x026bddae,0x06e1af27,
|
|
0x13058a65,0x0da69c3f,0x00028ca7 } },
|
|
/* 48 */
|
|
{ { 0x1c9877ee,0x08ea3ee7,0x074000b4,0x06c42100,0x060b6c8b,0x008baa61,
|
|
0x011b400b,0x1b0d2c5e,0x0004c17c },
|
|
{ 0x10daddf5,0x0cde84a5,0x1395701b,0x046aea49,0x003b5bea,0x0b73396d,
|
|
0x11d198cd,0x1d3fdb2e,0x00f7ba4d } },
|
|
/* 49 */
|
|
{ { 0x0be1263f,0x06dfd1a7,0x0b9f39b4,0x0c6e6ae3,0x0f523557,0x02a9c153,
|
|
0x11074910,0x000a4263,0x00e31f96 },
|
|
{ 0x0a6b6ec6,0x0ddc90b7,0x10bf1134,0x03a25ce7,0x0a29437a,0x1f5644e8,
|
|
0x11ef0439,0x0b39c69a,0x00aa3a62 } },
|
|
/* 50 */
|
|
{ { 0x16f3dcd3,0x1e7cefa9,0x0fdcd83e,0x1bdaa1a5,0x04f5b6ce,0x087d6fa8,
|
|
0x0bb9245c,0x0c4fcf3b,0x002398dd },
|
|
{ 0x0d09569e,0x1a382d1b,0x127dda73,0x0c3376a2,0x0034cea0,0x01bb9afb,
|
|
0x0843fe70,0x1643808c,0x005717f5 } },
|
|
/* 51 */
|
|
{ { 0x01dd895e,0x1f114e49,0x10a11467,0x030a0081,0x17ecd8e5,0x091c8eb1,
|
|
0x037be84f,0x0ac1c785,0x00660a2c },
|
|
{ 0x167fcbd0,0x06544576,0x0a7c25a7,0x0e48f01d,0x12b4dc84,0x1a40b974,
|
|
0x114ccacb,0x0989ea44,0x00624ee5 } },
|
|
/* 52 */
|
|
{ { 0x1897eccc,0x0aa4e726,0x06202a82,0x13a3b27f,0x07c204d4,0x1211821d,
|
|
0x0f01c8f0,0x1f7257bf,0x004f392a },
|
|
{ 0x1de44fd9,0x0b4fc7d3,0x0cc8559a,0x19f7c8af,0x0bc3cb66,0x14019b47,
|
|
0x06736cbe,0x0ef99b67,0x008a3e79 } },
|
|
/* 53 */
|
|
{ { 0x06c4b125,0x0f0c40f8,0x18f2a337,0x09c601ed,0x013e9ae3,0x0cef2e3d,
|
|
0x1013bda6,0x046e1848,0x003888d0 },
|
|
{ 0x04f91081,0x11401ab2,0x0055411d,0x1f9ec2be,0x0d36e3d9,0x16e43196,
|
|
0x0cd8609f,0x08e30204,0x00a5e62e } },
|
|
/* 54 */
|
|
{ { 0x0facd6c8,0x1412f719,0x0f2f1986,0x18c6a8a9,0x19931699,0x16fbcc6f,
|
|
0x0b70338f,0x1cc8cd4b,0x002c4768 },
|
|
{ 0x10a64bc9,0x1a37fc64,0x1de7d72c,0x14c041c8,0x1e884630,0x08325e02,
|
|
0x0a836527,0x083f3cca,0x007b5e64 } },
|
|
/* 55 */
|
|
{ { 0x1d28444a,0x0b4a1160,0x04da8e48,0x0d8bb17c,0x07fcee99,0x17f2fd86,
|
|
0x11288e1e,0x196191ae,0x00b8af73 },
|
|
{ 0x138b86fd,0x1ef41d51,0x02973fd7,0x07e2b14b,0x09433fee,0x07b79056,
|
|
0x025727ba,0x0befe7e1,0x00a03639 } },
|
|
/* 56 */
|
|
{ { 0x010f7770,0x039e35dd,0x0a838923,0x02db0342,0x02b9fa6f,0x1b4128de,
|
|
0x14cc4037,0x0030ebf6,0x004be36b },
|
|
{ 0x1fb56dbb,0x11304374,0x19e93e24,0x1fdf160f,0x12f20306,0x0602b36a,
|
|
0x0303bab3,0x10e37b80,0x008cbc9a } },
|
|
/* 57 */
|
|
{ { 0x00dac4ab,0x098c4ae6,0x0bfc44b8,0x094880e2,0x0ee57a87,0x173e350e,
|
|
0x17e18cca,0x07c18106,0x0044e755 },
|
|
{ 0x1734002d,0x0a81fffb,0x0d10971b,0x0b971616,0x138b59d3,0x013b0743,
|
|
0x106257dc,0x074bd71f,0x00470a68 } },
|
|
/* 58 */
|
|
{ { 0x10513482,0x0dbb0ee4,0x1a49daa0,0x0e405403,0x13083028,0x00f70673,
|
|
0x1bbf3691,0x1218c7b8,0x00164106 },
|
|
{ 0x0d06a2ed,0x081a5033,0x06c402fd,0x1aee8a31,0x018c9dd4,0x173955c1,
|
|
0x0d3f6452,0x1faf5797,0x00d73479 } },
|
|
/* 59 */
|
|
{ { 0x1ad4c6e5,0x16f7d8b2,0x01b4135f,0x19e11eb6,0x1cb14262,0x0dd8c2ba,
|
|
0x19ac4bb5,0x1c60ee2c,0x00816469 },
|
|
{ 0x161e291e,0x1d5cebca,0x17859875,0x1b5e4583,0x00513eb9,0x13f589af,
|
|
0x1e73d260,0x047e1ba7,0x000a36dd } },
|
|
/* 60 */
|
|
{ { 0x01d5533c,0x0c69963a,0x0118a3c2,0x1eb53d0d,0x1bd117c5,0x1456f1a4,
|
|
0x0460e688,0x1adfb756,0x00e331df },
|
|
{ 0x0bcc6ed8,0x08055b43,0x1e898394,0x01877bde,0x050d7716,0x0cd3de74,
|
|
0x0e26418f,0x054925c6,0x00d3b478 } },
|
|
/* 61 */
|
|
{ { 0x13821f90,0x0a4db747,0x1adeab68,0x1bb3dacd,0x1311692e,0x14a98d00,
|
|
0x16f42ed9,0x0b4990d4,0x00728127 },
|
|
{ 0x13ff47e5,0x01c2c7be,0x00591054,0x0c2d78c2,0x19bb15e1,0x188d3efe,
|
|
0x01658ac3,0x0fd9c28a,0x002c062e } },
|
|
/* 62 */
|
|
{ { 0x0159ac2e,0x1b7ccb78,0x16c9c4e9,0x1cee6d97,0x06047281,0x09440472,
|
|
0x1bc4ab5b,0x1f2589cf,0x00282a35 },
|
|
{ 0x00ce5cd2,0x01aa58f6,0x1e708a67,0x13df9226,0x0c11ecf9,0x179c1f41,
|
|
0x0af664b2,0x026aa9a5,0x00c71cd5 } },
|
|
/* 63 */
|
|
{ { 0x09b578f4,0x042ef4e0,0x0bfe9e92,0x09c4b1c7,0x02f1f188,0x18dbac8c,
|
|
0x0e8e3dda,0x0819e8fe,0x00c50f67 },
|
|
{ 0x174b68ea,0x0e256f99,0x0597f8aa,0x0de646d3,0x13050a40,0x111142d2,
|
|
0x0370be1a,0x14e4252b,0x00b9ecb3 } },
|
|
/* 64 */
|
|
{ { 0x14f8b16a,0x17c20877,0x1ec99a95,0x0835fd88,0x087c1972,0x15c736ce,
|
|
0x0c6c2901,0x0059a855,0x00803f3e },
|
|
{ 0x04dbec69,0x18184d40,0x0eb417df,0x170bee77,0x0197fa83,0x1939d6c7,
|
|
0x17071825,0x01ca0cf5,0x00c09744 } },
|
|
/* 65 */
|
|
{ { 0x0379ab34,0x0352b796,0x077e3461,0x1c0d1708,0x068efa8e,0x022c8bb6,
|
|
0x1cc080c5,0x1ab22be3,0x00f1af32 },
|
|
{ 0x1d75bd50,0x0e1ba98a,0x0bd9ef26,0x19ff75ee,0x1723f837,0x120c246b,
|
|
0x122c184e,0x061c5a83,0x0023d0f1 } },
|
|
/* 66 */
|
|
{ { 0x141500d9,0x0bd5b76f,0x0fab6a21,0x1215cbf9,0x059510d8,0x032444b9,
|
|
0x0b754bfa,0x1ad8147f,0x00b0288d },
|
|
{ 0x050bcb08,0x09907983,0x175b85a1,0x1ec626d2,0x1aa7671a,0x1053dcc4,
|
|
0x0348c7d4,0x09fe8119,0x00ffd372 } },
|
|
/* 67 */
|
|
{ { 0x1458e6cb,0x1cb47325,0x1e974a14,0x1b5a4062,0x15f56992,0x1705bd53,
|
|
0x1b7ce052,0x095af184,0x00f5590f },
|
|
{ 0x0f0ba55a,0x1e125e9e,0x1de2eb83,0x08e49418,0x1674a0fc,0x0327b41d,
|
|
0x088073a6,0x0a9edee9,0x0018d6da } },
|
|
/* 68 */
|
|
{ { 0x15be5a2b,0x0c9f112e,0x0d3cf1bb,0x0f3306b2,0x06ffc6fe,0x04931131,
|
|
0x05a90c50,0x1b2f3204,0x0050bbb4 },
|
|
{ 0x057ec63e,0x1c0c8e37,0x07736c8d,0x04588030,0x0e0f6654,0x04cd811b,
|
|
0x070d06a0,0x03003fc9,0x002b1001 } },
|
|
/* 69 */
|
|
{ { 0x1b391593,0x0345ae2c,0x009c3f3f,0x0beb44b3,0x0dcbbc38,0x19d568cd,
|
|
0x1831c513,0x13307f75,0x00dd5589 },
|
|
{ 0x14b82ff4,0x1dc45c73,0x19cd3264,0x007880e3,0x0322ad2e,0x0f57a1e0,
|
|
0x010669ea,0x0a2293ac,0x00e6e4c5 } },
|
|
/* 70 */
|
|
{ { 0x1e9af288,0x0fb2add8,0x0b6a4c55,0x1c34c9ef,0x020e5647,0x1f25e594,
|
|
0x1bfd0da5,0x1620fdaa,0x0051e00d },
|
|
{ 0x171c327e,0x1e8b4dc3,0x05b0ab50,0x1b641695,0x1477929c,0x08fa9ef5,
|
|
0x05df01f5,0x08293052,0x00e22f42 } },
|
|
/* 71 */
|
|
{ { 0x035f1abb,0x0a2f47a3,0x14e21d33,0x18196ad0,0x0034d7ed,0x160fdad4,
|
|
0x0327251c,0x07aa5b89,0x00f70937 },
|
|
{ 0x08af30d6,0x00cb35dd,0x0deda710,0x1ebe95e2,0x1c47e95b,0x0b1549b0,
|
|
0x0c44e598,0x111ce4eb,0x00bd52d2 } },
|
|
/* 72 */
|
|
{ { 0x1c5fa877,0x18aae3d4,0x0e8f522a,0x15ace4fa,0x189d817d,0x1fcf39e8,
|
|
0x1e990fd0,0x1c99154e,0x00a0d0f8 },
|
|
{ 0x0c94f92d,0x1df57ec6,0x1376ce82,0x11917c18,0x0ba14d81,0x12fc5c17,
|
|
0x08008b31,0x18f28dad,0x00a56c78 } },
|
|
/* 73 */
|
|
{ { 0x0dd09529,0x0b11c8d8,0x0b77f3ca,0x1c1d4c7b,0x1f481803,0x1a8fadad,
|
|
0x19e8b1dc,0x1f0e6346,0x00d8befd },
|
|
{ 0x1c0157f4,0x1c8cea17,0x1239942a,0x195daffd,0x08b0af51,0x05a0016a,
|
|
0x11e337e7,0x14b9d3ec,0x00854a68 } },
|
|
/* 74 */
|
|
{ { 0x03506ea5,0x01afb3db,0x1f8359b7,0x0d891349,0x1cd4d928,0x0e9dff4a,
|
|
0x0a54fc40,0x0173108d,0x005cacea },
|
|
{ 0x1ceac44d,0x086fb064,0x13470eaa,0x0535e86a,0x1babe3db,0x1ef456ae,
|
|
0x1ea42374,0x0246bc9d,0x00e4982d } },
|
|
/* 75 */
|
|
{ { 0x034cd55e,0x18825116,0x00344c88,0x12b7664d,0x1d943586,0x0d7d0fd0,
|
|
0x1267ecd1,0x1ec2d640,0x008046b7 },
|
|
{ 0x18e7d098,0x099ac0f1,0x1bc2dc2d,0x0c3d1be8,0x178c4d7f,0x14f52265,
|
|
0x1d54c37a,0x0f721055,0x00eb17ca } },
|
|
/* 76 */
|
|
{ { 0x16a145b9,0x1a8dacc3,0x0f1c7b05,0x1ed61f83,0x115bba5c,0x1ab29c93,
|
|
0x04c74f80,0x175f56bc,0x00097b00 },
|
|
{ 0x165f69e1,0x1336474a,0x0f94666a,0x11eeb56b,0x1d98477e,0x1d08ed27,
|
|
0x127980ce,0x0f75fb79,0x00f95c74 } },
|
|
/* 77 */
|
|
{ { 0x1ebae45e,0x0c780e9d,0x0f1a5555,0x17d3e189,0x04fc6a8e,0x02d8ede3,
|
|
0x00debadc,0x03cacddb,0x00351260 },
|
|
{ 0x1a1161cd,0x19b78f0f,0x197be1e4,0x1571aa98,0x121e5328,0x17713927,
|
|
0x0dad1d5f,0x046c0d15,0x000ef971 } },
|
|
/* 78 */
|
|
{ { 0x14ca4226,0x12cc67ba,0x190b2380,0x1bc271f0,0x017905ee,0x1fba2347,
|
|
0x12552258,0x066769f7,0x00fc16d9 },
|
|
{ 0x07c800ca,0x14b7d98f,0x1e2b6aaf,0x00c6624c,0x1e8b5138,0x024bb7f9,
|
|
0x085cf589,0x1e372baf,0x0014ca4a } },
|
|
/* 79 */
|
|
{ { 0x1d2f81d5,0x123b8dd5,0x1df4659e,0x1f3ad203,0x1c9071a5,0x1f7be56c,
|
|
0x0c776262,0x0c7eb384,0x004057b0 },
|
|
{ 0x09c05c0a,0x1fec17f4,0x1037e16f,0x0238de3b,0x016dbe49,0x065751ad,
|
|
0x0c4cefbf,0x0c9e2661,0x001c3b5d } },
|
|
/* 80 */
|
|
{ { 0x00ec21fe,0x1f0a5ff4,0x156fa097,0x1c22d584,0x05d67f6c,0x0d0397a5,
|
|
0x0ebe62f1,0x091b6fcc,0x00fad271 },
|
|
{ 0x09ab05b3,0x0605b561,0x0946b9a4,0x1350789c,0x0de7d37a,0x043ae155,
|
|
0x0a1029f7,0x1c73e1c3,0x0077387d } },
|
|
/* 81 */
|
|
{ { 0x056c0dd7,0x14f6624d,0x021b1d07,0x1ff9b08c,0x1aecea5c,0x0a047a82,
|
|
0x11fa3de8,0x1817de18,0x00b37b85 },
|
|
{ 0x0c0e6a8f,0x0cb5b726,0x0e23c8cd,0x1a977ed6,0x0ef4efd6,0x09fd61ce,
|
|
0x0356ae91,0x191f3ec5,0x009c135a } },
|
|
/* 82 */
|
|
{ { 0x04e35743,0x15519014,0x08f37bcc,0x1ad5630b,0x19819320,0x18bb0ef8,
|
|
0x147ee086,0x03f88670,0x00572136 },
|
|
{ 0x11fc9168,0x186d9b53,0x17100f07,0x1174e6bc,0x0d8f55f9,0x143f1bde,
|
|
0x06f7d932,0x193cd762,0x00dcbac3 } },
|
|
/* 83 */
|
|
{ { 0x0518cbe2,0x00eccb42,0x07ac13bc,0x05f83139,0x1eebfd24,0x11e3f23f,
|
|
0x0189c9d9,0x13c5ac4d,0x00b8c1c8 },
|
|
{ 0x08e1d569,0x0d2c5eee,0x16233414,0x1013916f,0x131eb563,0x1fecf88f,
|
|
0x0b509b09,0x1b45f284,0x005d23bb } },
|
|
/* 84 */
|
|
{ { 0x15c8f8be,0x10e394a4,0x1cd8afc2,0x03890077,0x1d4ac296,0x0201efb1,
|
|
0x04027906,0x19723d9d,0x00c109f9 },
|
|
{ 0x18945705,0x1684ae82,0x1ae17030,0x107b2dbb,0x0449bb90,0x15c6bd20,
|
|
0x1b8611a4,0x09e5ddc3,0x009bc334 } },
|
|
/* 85 */
|
|
{ { 0x02913074,0x0ad71ab2,0x0950ac43,0x12364e91,0x0732a554,0x1332d988,
|
|
0x13051a72,0x0a4be349,0x0029591d },
|
|
{ 0x184f983f,0x1b7adb5d,0x17e13879,0x1dde833e,0x0a189be7,0x0a4b405d,
|
|
0x0cb04803,0x03e31de6,0x00637655 } },
|
|
/* 86 */
|
|
{ { 0x162976cc,0x0d2f8a72,0x1c4b0e2f,0x1947cc1d,0x0985222b,0x18323665,
|
|
0x01eaefe8,0x19011c53,0x00bdb79d },
|
|
{ 0x0b06a772,0x0965ae4e,0x14db73bf,0x08eb55fc,0x15db838f,0x10113e15,
|
|
0x052b0a8f,0x0035ba78,0x008ee860 } },
|
|
/* 87 */
|
|
{ { 0x04ade873,0x1f4b4c0d,0x1ee92332,0x13549b89,0x14ba57ee,0x144cad02,
|
|
0x092cb3b8,0x0f4deef5,0x0092e51d },
|
|
{ 0x1190a34d,0x045d7d43,0x0f47b465,0x11eeb7ed,0x11144d69,0x13718657,
|
|
0x0aab403b,0x0de14ad5,0x005182f8 } },
|
|
/* 88 */
|
|
{ { 0x1a4cc99c,0x1d310963,0x1b67287e,0x0136d07c,0x18c5aff6,0x13e5ad64,
|
|
0x1bc976ec,0x0ba80e74,0x0091dcab },
|
|
{ 0x1f575a70,0x0db661ea,0x0361fe80,0x06c272df,0x017360cb,0x074644cc,
|
|
0x1cac5975,0x1b72f2e9,0x0017a0ce } },
|
|
/* 89 */
|
|
{ { 0x076c8d3a,0x0430f150,0x03e492ce,0x155a7242,0x035d9701,0x157209d4,
|
|
0x1d065343,0x0d8fe99b,0x002e8ce3 },
|
|
{ 0x037a862b,0x0939ed58,0x19323ea4,0x15376ec1,0x0f2dd01b,0x09c419dd,
|
|
0x03cfe591,0x19669ecd,0x00f4ccc6 } },
|
|
/* 90 */
|
|
{ { 0x11f79687,0x077a92e7,0x1bea0551,0x12a92b25,0x18d297c5,0x0ba0d2e3,
|
|
0x0f27848c,0x111341be,0x00ac0db4 },
|
|
{ 0x1f01747f,0x15fe388e,0x05f7c4e1,0x1726b1de,0x16bb5592,0x0727ae65,
|
|
0x128b9620,0x0c32992e,0x0095a64a } },
|
|
/* 91 */
|
|
{ { 0x015a4c93,0x160f7ed6,0x1614505c,0x0d36e704,0x10bad402,0x1d8e0b65,
|
|
0x19ddaa37,0x17452420,0x00231e54 },
|
|
{ 0x0ae6d2dc,0x186fc8bc,0x044a4629,0x154c7e72,0x172234d6,0x1935af2d,
|
|
0x0787d89d,0x065b14e6,0x00ab0be0 } },
|
|
/* 92 */
|
|
{ { 0x0d131f2d,0x0bd6874c,0x013c4042,0x1e13c676,0x1a748637,0x10cb6af4,
|
|
0x19e46b21,0x10059ed4,0x00f1bcc8 },
|
|
{ 0x08daacb4,0x0e348a07,0x1d940249,0x1c80aac1,0x137a63c4,0x047e23bc,
|
|
0x09c56473,0x0d2b5d76,0x00851694 } },
|
|
/* 93 */
|
|
{ { 0x11dcf593,0x11ae0a1f,0x062f8ef7,0x00565360,0x19d3d782,0x16e14dee,
|
|
0x1763a736,0x1a5b55aa,0x008f67d9 },
|
|
{ 0x1481ea5f,0x0088b2b3,0x13164321,0x05bbd3c6,0x13fa8e7d,0x01fa0282,
|
|
0x0d77ff75,0x17380e51,0x00f84572 } },
|
|
/* 94 */
|
|
{ { 0x17af71c9,0x10d3d38c,0x1cd95957,0x092888f4,0x15063a14,0x1703870e,
|
|
0x106686d2,0x020c2d65,0x00edee27 },
|
|
{ 0x11734121,0x1781a7a8,0x097a7c2c,0x18dcaa94,0x02ecf1ca,0x0479d206,
|
|
0x1fd23705,0x13689d7a,0x009fd27e } },
|
|
/* 95 */
|
|
{ { 0x16e2cb16,0x063b2c57,0x16466d8f,0x16fa59fc,0x15583e3e,0x0c0b0b46,
|
|
0x0e1d6a31,0x16d2b1fe,0x00a40c2f },
|
|
{ 0x1edcc158,0x04f62b07,0x1c8c15a3,0x10098cab,0x07e127ad,0x13824d18,
|
|
0x1b3f64e5,0x170fb8db,0x0099bc9b } },
|
|
/* 96 */
|
|
{ { 0x127dafc6,0x054a90ec,0x02734661,0x03f6d2b8,0x06dde52c,0x00d07c9b,
|
|
0x19927656,0x01742daf,0x009abe21 },
|
|
{ 0x08915220,0x0057c252,0x1605b192,0x062ed49b,0x1ca5afa7,0x1cc38b40,
|
|
0x12c31f54,0x0af0fe68,0x007881c2 } },
|
|
/* 97 */
|
|
{ { 0x00bcf3ff,0x19ccda8f,0x1fdd3da4,0x05978a24,0x1d9680d0,0x12d16e80,
|
|
0x05023ed1,0x033461d1,0x0015e6e3 },
|
|
{ 0x1e0e05f4,0x036b7069,0x16210119,0x0f7bb886,0x050d3fad,0x03e8e27c,
|
|
0x0b3af987,0x19e3222e,0x000e55fa } },
|
|
/* 98 */
|
|
{ { 0x18787564,0x14ecc037,0x1a17399f,0x062e4263,0x1e8d61a3,0x0c655c0c,
|
|
0x15ddac05,0x0ecdfd2c,0x00d73d09 },
|
|
{ 0x1eb7206e,0x1241a128,0x062ed090,0x12521f8c,0x0a520a51,0x1c2caf18,
|
|
0x142d772e,0x0e91e2b4,0x009250a3 } },
|
|
/* 99 */
|
|
{ { 0x1e577410,0x17f847c5,0x1dea31b2,0x011406a0,0x063a4fd4,0x1944f605,
|
|
0x102fc7d8,0x10583991,0x00774140 },
|
|
{ 0x0b0991cd,0x0d207d37,0x1f70a581,0x1410cc93,0x0fd40c1c,0x11e3d992,
|
|
0x02e4e9a2,0x09a25d64,0x008cb04f } },
|
|
/* 100 */
|
|
{ { 0x0906171c,0x0e1682ab,0x09030fec,0x07d39b60,0x06841907,0x15a7ec48,
|
|
0x0d476e39,0x1de8e247,0x00e4e429 },
|
|
{ 0x18ec36f4,0x1c6ea9e1,0x12da89c2,0x05b803fe,0x09a48f9d,0x1703c3cd,
|
|
0x15497419,0x1fe78dcc,0x0037bca2 } },
|
|
/* 101 */
|
|
{ { 0x1f562470,0x06971e3e,0x0592b253,0x04e54581,0x193be44f,0x0efcc063,
|
|
0x08a9f1b5,0x1b860056,0x0059913e },
|
|
{ 0x1750592a,0x109cd41a,0x00f7809e,0x003b01cf,0x1d64f99e,0x01baf502,
|
|
0x089b3e30,0x0956027c,0x0043786e } },
|
|
/* 102 */
|
|
{ { 0x1e56b5a6,0x1995876c,0x1f1a3e7f,0x01b34db3,0x046a7075,0x1422acbc,
|
|
0x19ebb057,0x1316fcf3,0x008638ca },
|
|
{ 0x0afc24b2,0x1ad704b0,0x0b3a3c8b,0x131d5e9b,0x1a78f053,0x0ee85765,
|
|
0x1bc0edd9,0x0d4f6754,0x001ecdd3 } },
|
|
/* 103 */
|
|
{ { 0x0c5ff2f3,0x09d66b13,0x1cea5e17,0x0a2d8050,0x10d54a2d,0x04fd6908,
|
|
0x0cb6b653,0x10ba8b3e,0x00d85d0f },
|
|
{ 0x10b11da3,0x1b805c68,0x00c63127,0x0458614f,0x0decdd2c,0x047a4904,
|
|
0x118955a6,0x18769da7,0x00a04f19 } },
|
|
/* 104 */
|
|
{ { 0x0d7f93bd,0x03c92647,0x0bd47d82,0x0958ba72,0x171afcb6,0x1985410d,
|
|
0x02c1f2b8,0x1d4b812a,0x0092b2ee },
|
|
{ 0x05b6e235,0x0d6264a4,0x0db03c21,0x19495252,0x08891ab2,0x1359f028,
|
|
0x1db203ea,0x042b0684,0x001ee782 } },
|
|
/* 105 */
|
|
{ { 0x063e79f7,0x10517007,0x067641a9,0x01cf65e7,0x1c09df59,0x02a53303,
|
|
0x05424084,0x1b0af4dc,0x00f3f2ce },
|
|
{ 0x110d9b55,0x0028879f,0x19099208,0x1f9f59b0,0x10e7c9d2,0x0d53f45e,
|
|
0x0843958c,0x0a87b47c,0x000f56a4 } },
|
|
/* 106 */
|
|
{ { 0x1043e0df,0x190dffd0,0x001f9b56,0x096d9938,0x0517a6c7,0x17606a54,
|
|
0x098c6995,0x08232d3c,0x00bd8f17 },
|
|
{ 0x1eb7494a,0x14dddc35,0x1cee0e22,0x0fa8de8b,0x1a79a156,0x0953d272,
|
|
0x08277de8,0x06a6199f,0x002d1a1c } },
|
|
/* 107 */
|
|
{ { 0x106508da,0x0971c09a,0x15e569c6,0x03018943,0x144b3336,0x0ca4bd4c,
|
|
0x091b376d,0x0bd723f7,0x00a107a6 },
|
|
{ 0x0f94d639,0x168e8e28,0x162df5f9,0x15e6eb14,0x1ca1c8b4,0x0ac25e9b,
|
|
0x0bc869f1,0x015f0f53,0x00183d76 } },
|
|
/* 108 */
|
|
{ { 0x0dde59a4,0x0eb4b888,0x02fbe1ca,0x1b1a0e1d,0x0be78f1a,0x04b1a797,
|
|
0x1d508a6d,0x13b84d3a,0x001d4417 },
|
|
{ 0x0390d30e,0x196e067c,0x1a04432c,0x164ea61b,0x0339a0a3,0x0ee295e0,
|
|
0x0988c6bc,0x1852c0da,0x00771f9c } },
|
|
/* 109 */
|
|
{ { 0x05040739,0x0cc9f3bc,0x09aa4e66,0x073b7300,0x0fc26445,0x1b797afc,
|
|
0x063b3d03,0x06206c4e,0x0064427a },
|
|
{ 0x05428aa8,0x1a796c3c,0x1ed26a13,0x15b87fd7,0x101ac7b7,0x1636f91e,
|
|
0x15b4806c,0x092d5d21,0x0049d9b7 } },
|
|
/* 110 */
|
|
{ { 0x035d1099,0x03c6c5e2,0x03468233,0x179a9d1d,0x08a412ad,0x1150165b,
|
|
0x11140b0b,0x0367ec0a,0x009037d8 },
|
|
{ 0x074c7b61,0x06dd6138,0x0ff5cb9f,0x006356af,0x15352fe2,0x164b2cb6,
|
|
0x0e718733,0x0d4f980c,0x0008c3de } },
|
|
/* 111 */
|
|
{ { 0x16d552ab,0x07ee8107,0x13607c48,0x15ff300b,0x1129156b,0x1e1f489a,
|
|
0x0cbc1bed,0x0848af2d,0x00c69094 },
|
|
{ 0x01231bd1,0x1d9d74e2,0x11608145,0x18dd0eb9,0x0a1221ea,0x1bd5fceb,
|
|
0x0b008220,0x00595fc7,0x003fa3db } },
|
|
/* 112 */
|
|
{ { 0x05058880,0x1ad1f328,0x0e50fcb5,0x06cbdec8,0x049257da,0x030e7d59,
|
|
0x03fd051e,0x161fb701,0x00c5c4bd },
|
|
{ 0x1272b56b,0x1a89f1a5,0x0e410e9c,0x04fd2a23,0x04969c83,0x11befc42,
|
|
0x1ad7f633,0x1288d856,0x002d56db } },
|
|
/* 113 */
|
|
{ { 0x1f46ac6b,0x030bc17f,0x08b90949,0x1ef24c0f,0x08de1d19,0x11e204d2,
|
|
0x090bebfa,0x13bca077,0x000f56bd },
|
|
{ 0x145cda49,0x1bea7689,0x1bca6744,0x02b1f902,0x03402821,0x12a5575a,
|
|
0x17c79f1a,0x13a22e76,0x004003bb } },
|
|
/* 114 */
|
|
{ { 0x00803387,0x1c740c4d,0x12f5010e,0x022bea73,0x17f21ece,0x1046e943,
|
|
0x1e790a5c,0x04540fe5,0x00537655 },
|
|
{ 0x08a4182d,0x04c0510d,0x0677de69,0x17a0f464,0x1a2d4a2b,0x05170d0c,
|
|
0x15259d34,0x0b0d8ba8,0x007a056f } },
|
|
/* 115 */
|
|
{ { 0x1d8a2a47,0x03592ac4,0x17c9dcd9,0x10529187,0x0d5395b5,0x000755f8,
|
|
0x19d547b0,0x1e2f4344,0x0077d482 },
|
|
{ 0x07853948,0x050decac,0x1efffbae,0x102f7ad9,0x01e47a6f,0x002bc034,
|
|
0x0392adbb,0x05656716,0x00411501 } },
|
|
/* 116 */
|
|
{ { 0x0de28ced,0x039f87a3,0x04fb11cf,0x1b4ec136,0x063921d5,0x074f372e,
|
|
0x051986e3,0x0e5f7d41,0x00cdf045 },
|
|
{ 0x0c53c3b0,0x059e2c5b,0x1ee10f07,0x1c782088,0x1780e97f,0x0570965c,
|
|
0x0427ecae,0x1b52e706,0x00ee703d } },
|
|
/* 117 */
|
|
{ { 0x1f57e43a,0x028a8a07,0x0e046e0d,0x0cc1a763,0x0b986d44,0x0effc7a1,
|
|
0x1884aced,0x13b42c59,0x002a0ad8 },
|
|
{ 0x0bc277ba,0x072534a3,0x10709d99,0x1192a982,0x16274c78,0x1326655f,
|
|
0x1964506a,0x0cf58568,0x00d62d0b } },
|
|
/* 118 */
|
|
{ { 0x0c054ac4,0x0e2ec3d9,0x1f7de20e,0x00b0b3e4,0x128d6570,0x05f9d8c0,
|
|
0x109bb7df,0x1e532384,0x00b39a23 },
|
|
{ 0x10b16ae5,0x094250af,0x0dbd46e5,0x140b6342,0x007830c6,0x009bf938,
|
|
0x1314758f,0x12580ce9,0x0004ed00 } },
|
|
/* 119 */
|
|
{ { 0x1ae90393,0x1a0c2e8c,0x0f593987,0x0f685294,0x0fc14304,0x00d34c2a,
|
|
0x0e1eb800,0x18202ef8,0x00a0a91f },
|
|
{ 0x0e2c831e,0x1851f80d,0x1c9f85bf,0x0d5d0456,0x075b4bb7,0x0450ad18,
|
|
0x11063c4b,0x1113da41,0x00084cf9 } },
|
|
/* 120 */
|
|
{ { 0x1ca6becf,0x0c284ef7,0x1fecca36,0x1d5d00fb,0x0e8b92fc,0x0ae223bc,
|
|
0x1df97628,0x164e757e,0x00d57955 },
|
|
{ 0x11b5d4f1,0x086d3cf1,0x1e9e8708,0x05e09679,0x1c20baa5,0x1044ee13,
|
|
0x07c75344,0x08405a28,0x008e14ea } },
|
|
/* 121 */
|
|
{ { 0x12897042,0x16a81a2f,0x100b12bb,0x0a663e86,0x1fb218d0,0x00ca645e,
|
|
0x05632367,0x06e5549a,0x00597e1a },
|
|
{ 0x0f0bd68c,0x193f60d6,0x00925140,0x17c1b956,0x03e846d4,0x06bd64ff,
|
|
0x17a96e72,0x06c33369,0x00ca3f02 } },
|
|
/* 122 */
|
|
{ { 0x0170bd20,0x095085ab,0x0fd779d6,0x112fe2da,0x0ade20ea,0x1ff8a259,
|
|
0x1f928cd8,0x0fc61380,0x00bde7fd },
|
|
{ 0x18f5432c,0x0b5db695,0x10d112d4,0x1b8397c0,0x15b5a210,0x0f37fc7c,
|
|
0x0660f6c0,0x01c14fba,0x00b623ad } },
|
|
/* 123 */
|
|
{ { 0x00c7b65b,0x1adeb3ab,0x0928a269,0x18ab2047,0x06795ab8,0x07e86bd9,
|
|
0x0defe088,0x08cb1d82,0x00d6aa2e },
|
|
{ 0x1138bb85,0x055e005a,0x0cea5704,0x03a243b0,0x0a32e8c3,0x18058b81,
|
|
0x04eac93f,0x1c05b98a,0x00111662 } },
|
|
/* 124 */
|
|
{ { 0x0fb42b87,0x008a00af,0x1b137fde,0x1ebae036,0x1c129bd9,0x066bd3eb,
|
|
0x03e19bb3,0x197296ea,0x00db3ee1 },
|
|
{ 0x134837cf,0x1379ed87,0x15e353ec,0x1da31772,0x0657de7e,0x0fc9be2b,
|
|
0x096574b3,0x084a440d,0x00886a64 } },
|
|
/* 125 */
|
|
{ { 0x05b569ea,0x011a67db,0x0846704f,0x022283ee,0x0619e200,0x042ed0ad,
|
|
0x1ef22eb7,0x1d603142,0x00a70cf4 },
|
|
{ 0x0c4a6a65,0x127cbd74,0x0d0de3c8,0x0b9e4e02,0x0096036e,0x104f27bf,
|
|
0x0ddef8e9,0x157a2e8f,0x00aa4772 } },
|
|
/* 126 */
|
|
{ { 0x1aa60cc0,0x1b3b098b,0x1a0457d9,0x02c6c206,0x1bb5ac79,0x05da5de0,
|
|
0x05d37b66,0x1b861f5f,0x00611a6d },
|
|
{ 0x015ee47a,0x073c65e6,0x0365a94c,0x12c5049c,0x1ed882e8,0x0d6f9eec,
|
|
0x1220dbcd,0x1f02c853,0x005cfffa } },
|
|
/* 127 */
|
|
{ { 0x1b7a99cd,0x06aa67fc,0x0f116870,0x07733b08,0x139e17bf,0x0847b163,
|
|
0x05300e2a,0x046fb833,0x006e5a6b },
|
|
{ 0x0ba5db77,0x1c5a2a70,0x1d8358fb,0x1100ff59,0x08378b7b,0x00633b30,
|
|
0x0f339647,0x11a485b5,0x00481a23 } },
|
|
/* 128 */
|
|
{ { 0x15d0b34a,0x1a0bde01,0x09f029f8,0x1670d706,0x162d1440,0x1316d601,
|
|
0x050e3edc,0x099c19bf,0x002c4111 },
|
|
{ 0x0d95a0b1,0x1d2e778d,0x1550d88a,0x166f50cf,0x086c9c09,0x06e900f2,
|
|
0x0a5c9b5b,0x17e85ff2,0x0020477a } },
|
|
/* 129 */
|
|
{ { 0x18d65dbf,0x1ba8b9e0,0x07b6b60b,0x1f281c67,0x1001c77b,0x0935ee78,
|
|
0x1ad9c08b,0x1358ee72,0x00ac6640 },
|
|
{ 0x06261cc3,0x185d9b7e,0x039fa422,0x1ef79232,0x06c10213,0x075d522f,
|
|
0x1e159507,0x0eb98245,0x00ce8e69 } },
|
|
/* 130 */
|
|
{ { 0x1c0a67d2,0x1890da0d,0x13492283,0x08ec1488,0x1473762d,0x078eb2cd,
|
|
0x12a03811,0x0ca4a176,0x0008fde3 },
|
|
{ 0x048bf287,0x07761ed4,0x0da75bab,0x0c4305a6,0x09482c2a,0x0fee4922,
|
|
0x135cd60b,0x1a4acbad,0x002f7e2f } },
|
|
/* 131 */
|
|
{ { 0x03770fa7,0x125c96de,0x0410fe6b,0x1d1ab86f,0x01171095,0x074e8bbb,
|
|
0x0ab953cd,0x05d20ee0,0x00c65be9 },
|
|
{ 0x16fd0a40,0x1ac5181f,0x139e12c9,0x1045c779,0x167bfe7d,0x1ac2a7cb,
|
|
0x0ce9eb93,0x08fa2327,0x004bff8e } },
|
|
/* 132 */
|
|
{ { 0x00ff1480,0x0a0e90f8,0x1536c5b3,0x11f6fa0e,0x0f3ea2ab,0x0977ddf0,
|
|
0x19f6b207,0x1ccaee52,0x003e4e4a },
|
|
{ 0x1c5303e6,0x10c79b69,0x0988e5df,0x13329724,0x0c3c03bd,0x07130992,
|
|
0x00a27b5c,0x1fab1d8c,0x005388ae } },
|
|
/* 133 */
|
|
{ { 0x1e5d7713,0x0898bf5a,0x179276ab,0x130bdceb,0x1b26109b,0x1e27e3a7,
|
|
0x1838cbd6,0x1a29eeb7,0x005cf908 },
|
|
{ 0x0e657b12,0x1021a884,0x1bb6799d,0x08434b72,0x0ccc2bfd,0x1a8fc4b8,
|
|
0x138838a7,0x080c1e01,0x00a698ba } },
|
|
/* 134 */
|
|
{ { 0x0f748fec,0x1ed8b437,0x074b3e5c,0x0eab44fd,0x05effe6e,0x12a26713,
|
|
0x16358c2d,0x114f5d75,0x00b142ef },
|
|
{ 0x17d5770a,0x098d7cf8,0x0cd04beb,0x1e76ce59,0x159de66a,0x068def99,
|
|
0x01d5af58,0x12cb0a2a,0x00d1896a } },
|
|
/* 135 */
|
|
{ { 0x13c41c08,0x02cabd59,0x1a38b87b,0x1d2958a8,0x12f6c87d,0x15b9d623,
|
|
0x08e46205,0x016f303b,0x00267b0e },
|
|
{ 0x0e62b988,0x12aa72ec,0x1b4879db,0x1b8eaa22,0x06f99d8d,0x1d781e95,
|
|
0x0e4d1843,0x0f542232,0x00b54e28 } },
|
|
/* 136 */
|
|
{ { 0x178a876b,0x100915a8,0x14412d02,0x1f2dfe10,0x09f7651f,0x18d58a79,
|
|
0x1398142c,0x116bf0fa,0x0084abb2 },
|
|
{ 0x0270790a,0x0f6a1cfc,0x18fd1af5,0x196b3b0b,0x022122d6,0x0e0db60f,
|
|
0x1901d7d5,0x0ce2ecaa,0x00e5436f } },
|
|
/* 137 */
|
|
{ { 0x0286e8d5,0x1fc812f1,0x1114ef94,0x192b690c,0x0e3a0353,0x1adef204,
|
|
0x067b60cb,0x116b739d,0x000404f6 },
|
|
{ 0x0781e8e5,0x1699def5,0x0f0bd6f2,0x1ea0302c,0x1caa33cd,0x14b0008c,
|
|
0x1c055d5d,0x1be15838,0x003a4263 } },
|
|
/* 138 */
|
|
{ { 0x1aeb596d,0x14b2f664,0x0f24ad30,0x1407ce04,0x1396101e,0x1a5b1700,
|
|
0x0d9d1c12,0x07f20bd4,0x000ca8fd },
|
|
{ 0x151b2b61,0x1291d212,0x03f341a4,0x0f513872,0x0a63e1eb,0x095f01c9,
|
|
0x10cf9fc7,0x0c89bb61,0x0096dca2 } },
|
|
/* 139 */
|
|
{ { 0x187510af,0x01dda1d1,0x08da8048,0x1fd55153,0x10378846,0x0bb817ca,
|
|
0x077348e9,0x024755ab,0x004363e2 },
|
|
{ 0x00246a47,0x121d0e3a,0x17749372,0x0571a5ca,0x1af96b36,0x03022ec7,
|
|
0x0313e6c2,0x0b9b1773,0x00840e11 } },
|
|
/* 140 */
|
|
{ { 0x1023e8a7,0x09102f10,0x171e82fc,0x11519bb1,0x05ddfc80,0x11390b1d,
|
|
0x1b538a4a,0x17a61bda,0x005e0d6a },
|
|
{ 0x1cfc0f64,0x1d390e13,0x157b6201,0x1d803a1c,0x19db242e,0x1f7c8e8f,
|
|
0x09689a9e,0x1e8528b4,0x007dea48 } },
|
|
/* 141 */
|
|
{ { 0x05060a81,0x1efb78e7,0x1e55856a,0x1f38e5f1,0x0268be79,0x162a0356,
|
|
0x1b473f4d,0x17dd7fa2,0x00abc2a2 },
|
|
{ 0x13e2eac7,0x16337c8e,0x174119a2,0x0174c7a5,0x0d31b6f1,0x11bb8141,
|
|
0x1f059e43,0x128d8fdd,0x004ea353 } },
|
|
/* 142 */
|
|
{ { 0x1266309d,0x0c517c6a,0x05168fbb,0x038d8103,0x05dc10a5,0x1a2d2bc6,
|
|
0x1f0f3b2b,0x1123929f,0x003a76e6 },
|
|
{ 0x1d7b0d0f,0x15674523,0x161297e6,0x159d2d1e,0x17fbe963,0x06392734,
|
|
0x1191468c,0x0148cbcc,0x008212a1 } },
|
|
/* 143 */
|
|
{ { 0x0fab8caa,0x1be30e1e,0x0508e43b,0x171d081c,0x133ca18e,0x1fb3bf4b,
|
|
0x05933477,0x0e2b3396,0x00aa7cab },
|
|
{ 0x1c837bd1,0x17e4939d,0x1abd75c0,0x080fa186,0x1da49c06,0x09497a11,
|
|
0x1f0c5d88,0x0e7fc0c2,0x0040e380 } },
|
|
/* 144 */
|
|
{ { 0x07bf9b7c,0x07c04125,0x0f8c343d,0x1a46407f,0x19ce3365,0x09904be7,
|
|
0x149afef9,0x001660aa,0x00e36047 },
|
|
{ 0x0cc6c2c7,0x0e5cc88b,0x132fb993,0x106e1174,0x0d9ec726,0x0a1a31bd,
|
|
0x057f737b,0x0ef47bdc,0x006542d6 } },
|
|
/* 145 */
|
|
{ { 0x1b6c377a,0x1995b683,0x0d122f8f,0x00708f20,0x08af76cb,0x09d4106d,
|
|
0x1c875bf7,0x1dc1376d,0x00a6534a },
|
|
{ 0x1035facf,0x050bc068,0x12d1f98c,0x0ab4673b,0x1f39335e,0x07f0e223,
|
|
0x1c89ba94,0x05fb935d,0x00f3cb67 } },
|
|
/* 146 */
|
|
{ { 0x1b55fd83,0x19b8cff1,0x1777443a,0x0f48d90e,0x0a784e0d,0x0fd482e7,
|
|
0x039cceb2,0x05d55d0e,0x007cafaa },
|
|
{ 0x1d53b338,0x1c0a6820,0x01f9b1a6,0x198141df,0x12b0fe0a,0x088408b3,
|
|
0x08bbee4f,0x183737aa,0x000aab13 } },
|
|
/* 147 */
|
|
{ { 0x12681297,0x0e6713c6,0x02551ab7,0x0a1d636a,0x1aaf2cb3,0x18b9bb30,
|
|
0x0ba4b710,0x00508e02,0x004b91a6 },
|
|
{ 0x12f8ddcf,0x07f884ab,0x0446bd37,0x17ec3d35,0x0430e08e,0x1b0561b9,
|
|
0x12ad23d0,0x0a6e4643,0x0049534c } },
|
|
/* 148 */
|
|
{ { 0x107b7e9d,0x1efbeb8f,0x13545be0,0x11df4627,0x07ee3a47,0x1325b602,
|
|
0x17b9e3bc,0x09facb58,0x00caf46c },
|
|
{ 0x12aa8266,0x026863bc,0x0da12ee8,0x08a8cd22,0x116b0edf,0x08b45725,
|
|
0x1c3d5b99,0x0ae098ce,0x0014ce9e } },
|
|
/* 149 */
|
|
{ { 0x165e8f91,0x0a22f1f4,0x03c924a6,0x19437596,0x0a0a0d3a,0x0387c864,
|
|
0x09c74c73,0x14a7c993,0x001bb708 },
|
|
{ 0x158bdd7a,0x0e54f34a,0x0289ac75,0x140a1003,0x0f1ec734,0x1538a64e,
|
|
0x040ac24e,0x1e5b4600,0x00f9d126 } },
|
|
/* 150 */
|
|
{ { 0x0ff9563e,0x04de53d5,0x0645281d,0x0ef5fd69,0x11671dd0,0x0188dfaf,
|
|
0x11a789e8,0x172e53d9,0x00807afc },
|
|
{ 0x09b08b77,0x1c5499be,0x0f1f8e1f,0x074f0a88,0x1d8ba86c,0x1d2ca3b7,
|
|
0x163217eb,0x1a2cad19,0x00751adc } },
|
|
/* 151 */
|
|
{ { 0x10715c0d,0x1751c5a0,0x1da5fde2,0x07d4e31e,0x1f06dd11,0x158a49fd,
|
|
0x10fd997a,0x0d04a6ee,0x0029ec44 },
|
|
{ 0x150bebbc,0x0ca38ce5,0x1415088f,0x1dcb7fc8,0x1edb1399,0x0d9d4696,
|
|
0x1df64335,0x1c725480,0x00ff9370 } },
|
|
/* 152 */
|
|
{ { 0x06b75b65,0x0d16b4de,0x19947156,0x11f1aa4c,0x1d7d2418,0x199f1ef4,
|
|
0x0068a2a7,0x1174553a,0x00977647 },
|
|
{ 0x129af2c7,0x0293116c,0x1a4248e2,0x1ebada9c,0x051e9334,0x03f2d44d,
|
|
0x0beb39b3,0x07f585f0,0x0074a631 } },
|
|
/* 153 */
|
|
{ { 0x175f079c,0x17a6feed,0x18dbeeec,0x00f92a31,0x136dd85b,0x1e7873e6,
|
|
0x18f46db3,0x02a1fe90,0x00ab75be },
|
|
{ 0x173fc9b7,0x0d9b3e00,0x1653f420,0x14e841a4,0x11236b90,0x1f81e204,
|
|
0x07d857f6,0x05c1688b,0x004ebeac } },
|
|
/* 154 */
|
|
{ { 0x1c9f2c53,0x1b62ff3a,0x0ba5047a,0x0440231d,0x0c5d8d25,0x1b19fcad,
|
|
0x1ff32221,0x0f658375,0x00df9988 },
|
|
{ 0x050aaecb,0x1bc77694,0x15a89cae,0x12303603,0x1bcac9d4,0x0a88d8e6,
|
|
0x01625e37,0x14eef3e8,0x0027b040 } },
|
|
/* 155 */
|
|
{ { 0x173b2eb2,0x0202edbf,0x06c84624,0x1f0a111c,0x0327ee0d,0x18a92cb1,
|
|
0x0fd5406d,0x06fc99f4,0x00b393dd },
|
|
{ 0x1fd75165,0x091873d9,0x14cd5528,0x06898579,0x15022d66,0x18df07bd,
|
|
0x1065b0db,0x025a08c6,0x0009588c } },
|
|
/* 156 */
|
|
{ { 0x02601c3b,0x043049f8,0x170cd7f8,0x04a5f19e,0x0ff28fb0,0x194044a5,
|
|
0x122e5573,0x153b73ec,0x0081c879 },
|
|
{ 0x06f56c51,0x007343e6,0x05d86301,0x08e2d27e,0x1353bfed,0x0520c82c,
|
|
0x0f1113e2,0x1eabf823,0x00fa0d48 } },
|
|
/* 157 */
|
|
{ { 0x01608e4d,0x0370e4ef,0x00a08b2f,0x1bb4226b,0x0c2d7010,0x0ee08abf,
|
|
0x1f5bdadf,0x0ad6d46c,0x008ea0e1 },
|
|
{ 0x0383b3b4,0x1aa70179,0x007d4f28,0x0cd7287e,0x03ca5699,0x119596f0,
|
|
0x16b13fd9,0x049f4016,0x003f5ab9 } },
|
|
/* 158 */
|
|
{ { 0x19739efb,0x1bdd86ca,0x1afb034c,0x0361e9cf,0x067d1c75,0x16eb208d,
|
|
0x15b8b694,0x10e56e84,0x008bc768 },
|
|
{ 0x02d3d253,0x0df1db94,0x035de7e9,0x0cf343eb,0x167bba9f,0x00b470b3,
|
|
0x0d3e872b,0x120c1f9e,0x00b386f1 } },
|
|
/* 159 */
|
|
{ { 0x0fedcfc2,0x0f9e09a9,0x1e2bc34c,0x0d7ec4c5,0x088c2539,0x1a7572b9,
|
|
0x1136680a,0x1ee360d3,0x004cb460 },
|
|
{ 0x1b8095ea,0x133da69a,0x101d80eb,0x17f0b2df,0x0a16592b,0x0fb35b0a,
|
|
0x088f851d,0x0112bdea,0x0052c0d5 } },
|
|
/* 160 */
|
|
{ { 0x15339848,0x18e10870,0x1de32348,0x1451d0e0,0x0e170e87,0x1330b4ab,
|
|
0x102e7477,0x07057613,0x004ac3c9 },
|
|
{ 0x0998987d,0x0df02a8b,0x027d3586,0x06ed895c,0x1933d8b2,0x1bb28d1f,
|
|
0x17d07782,0x18fc72e0,0x00380d94 } },
|
|
/* 161 */
|
|
{ { 0x01542e75,0x0d1aad54,0x006e6dc0,0x0e4943dc,0x1708796c,0x14bbb126,
|
|
0x1ebdace8,0x0e3bc4c6,0x002ce3e1 },
|
|
{ 0x15d5bc1a,0x1f7f5a4f,0x1df8ad73,0x0ac0fc4e,0x1756ca65,0x1617ca89,
|
|
0x19353faa,0x0a416c49,0x002e6cd8 } },
|
|
/* 162 */
|
|
{ { 0x0c31c31d,0x142caa5c,0x1c86830d,0x067a00b7,0x19ec9685,0x11373ae3,
|
|
0x15502f5d,0x08e858d3,0x00ca1775 },
|
|
{ 0x16d2dbb2,0x0376d7ff,0x12a74633,0x1b197a2e,0x178e8fd0,0x03c9d522,
|
|
0x139a1d7a,0x02739565,0x00a976a7 } },
|
|
/* 163 */
|
|
{ { 0x13fb353d,0x1328f8dc,0x1f3e9c82,0x195716af,0x15281d75,0x07d398d8,
|
|
0x0666aa23,0x02e143e9,0x008720a7 },
|
|
{ 0x093e1b90,0x01f469bb,0x1db7f0e3,0x0bb8162d,0x08742d34,0x08055a95,
|
|
0x04f23aa3,0x0538ed31,0x009719ef } },
|
|
/* 164 */
|
|
{ { 0x18e35909,0x10776c6a,0x177045a0,0x0db1b867,0x05026936,0x0ce83710,
|
|
0x13075fe6,0x0edc2ae0,0x00a50729 },
|
|
{ 0x04e70b2e,0x0151bf56,0x042aa280,0x19ecaed1,0x12a5c84d,0x1f8c322d,
|
|
0x1c9735c6,0x13bef6ee,0x0099389c } },
|
|
/* 165 */
|
|
{ { 0x1ada7a4b,0x1c604793,0x0e24d988,0x1d3a07fa,0x1512c3ab,0x1744bb37,
|
|
0x0b91ad9c,0x15440590,0x00a88806 },
|
|
{ 0x1380184e,0x10102256,0x1aa2e159,0x16f18824,0x04f17a8c,0x186056c2,
|
|
0x13f9e759,0x1f68e71b,0x000043bf } },
|
|
/* 166 */
|
|
{ { 0x16d5192e,0x0acdaee1,0x042cabe3,0x110ba68b,0x01781acf,0x168508b0,
|
|
0x019a0d59,0x00374d89,0x0052f3ef },
|
|
{ 0x0edcb64d,0x0c339950,0x1a0de7ce,0x10584700,0x0f3090a4,0x12fd3820,
|
|
0x19d45b2f,0x1133de4f,0x003296bd } },
|
|
/* 167 */
|
|
{ { 0x054d81d7,0x1b55d44a,0x1ae6cf11,0x1bcfdea3,0x179869ea,0x10e6c0e2,
|
|
0x07a58668,0x17f5dcae,0x003b90fe },
|
|
{ 0x1496f7cb,0x1c9811f2,0x0d46f124,0x1c83b0ff,0x0b5ce55b,0x0ea44cdf,
|
|
0x0c600fc7,0x13b3f021,0x006e8806 } },
|
|
/* 168 */
|
|
{ { 0x143ea1db,0x11bd588d,0x1674a4b3,0x1fe352a4,0x0f1860a7,0x0110c7c2,
|
|
0x144e146c,0x1d5bdf55,0x00a7222b },
|
|
{ 0x0b0a9144,0x1563c761,0x1e967168,0x0480a3e5,0x1ce385a0,0x1652b0a3,
|
|
0x1a424747,0x04778558,0x00be94d5 } },
|
|
/* 169 */
|
|
{ { 0x0b226ce7,0x17a4a2f0,0x1fa2dc1c,0x1fae8f2c,0x0c63eb8a,0x0378c2d3,
|
|
0x1d9bb7a9,0x1fd37d18,0x007782de },
|
|
{ 0x1db38626,0x10695521,0x1d9eb45d,0x15cf0eed,0x19cdb460,0x037e2a24,
|
|
0x192cd06e,0x0cf45125,0x00038385 } },
|
|
/* 170 */
|
|
{ { 0x19ec1a0f,0x0c6d77eb,0x0ce725cb,0x19adfb9d,0x01a953bb,0x0ffe2c7b,
|
|
0x1083d55d,0x1895bef6,0x00dbd986 },
|
|
{ 0x15f39eb7,0x0d5440a0,0x0365db20,0x05f9eb73,0x1717d6ee,0x03aee797,
|
|
0x0f415195,0x188d0c17,0x008e24d3 } },
|
|
/* 171 */
|
|
{ { 0x1a587390,0x04ec72a4,0x0fb1621d,0x16329e19,0x183c612b,0x1ed2592c,
|
|
0x1f211b81,0x18880f75,0x00541a99 },
|
|
{ 0x024c8842,0x1920b493,0x1b017ff6,0x098255b0,0x1cf62604,0x0a5a27bf,
|
|
0x17471674,0x093eafa6,0x00c0092c } },
|
|
/* 172 */
|
|
{ { 0x1f2e61ef,0x1e63ae1e,0x06cd72b4,0x1083905c,0x129f47e8,0x1868c84f,
|
|
0x113718b4,0x068e50d2,0x0075e406 },
|
|
{ 0x1bc237d0,0x1ea0fe2d,0x13c07279,0x06f7e1d8,0x1d534c95,0x0d0b1415,
|
|
0x161a4714,0x0b18f090,0x005b7cb6 } },
|
|
/* 173 */
|
|
{ { 0x0a28ead1,0x12538424,0x0ed1fda5,0x1b8a11fa,0x05b39802,0x1fe8bb3f,
|
|
0x1e866b92,0x1751be12,0x007ae13e },
|
|
{ 0x0add384e,0x090b77c7,0x0cbfc1bf,0x0345b36d,0x1b5f3036,0x0c3c25e6,
|
|
0x0ff4812e,0x0e9c551c,0x00787d80 } },
|
|
/* 174 */
|
|
{ { 0x157fbb1c,0x0f12eb5b,0x08077af1,0x17bb6594,0x033ffe47,0x14d1b691,
|
|
0x12112957,0x0333de50,0x005c2228 },
|
|
{ 0x08315250,0x19ea542c,0x1c25f05d,0x04345704,0x1d33f21b,0x0750ef7a,
|
|
0x0ac2adf1,0x15775e1e,0x00e45d37 } },
|
|
/* 175 */
|
|
{ { 0x08511c8a,0x16f8f1a1,0x129b34f4,0x0453917b,0x039a7ebb,0x18d3b13e,
|
|
0x074d5e29,0x04509bf7,0x00ed7bc1 },
|
|
{ 0x13dea561,0x191536fc,0x03c3b473,0x07e31ba9,0x123e8544,0x10a02dd6,
|
|
0x149f62e1,0x1928b94d,0x00aac97c } },
|
|
/* 176 */
|
|
{ { 0x016bd00a,0x1aa753a5,0x102f307a,0x13d35beb,0x1fc06d83,0x1bf88fcd,
|
|
0x113824ae,0x16622c7b,0x00318f97 },
|
|
{ 0x030d7138,0x06062df6,0x10c0883b,0x11be4757,0x0360644e,0x0b97d811,
|
|
0x1d34aede,0x1433509f,0x00fa41fa } },
|
|
/* 177 */
|
|
{ { 0x06642269,0x0016cba5,0x0de0ef51,0x10299d37,0x1e60bc81,0x1c723ca0,
|
|
0x0788e634,0x0583a4dd,0x0038bb6b },
|
|
{ 0x0a577f87,0x1272512b,0x047f8731,0x05a4a7b8,0x007288b5,0x155fb114,
|
|
0x0697fccd,0x00b9cec0,0x0094dd09 } },
|
|
/* 178 */
|
|
{ { 0x1e93f92a,0x0b67bee6,0x0d7cc545,0x06679713,0x1e750a01,0x06fce4ca,
|
|
0x0ba40901,0x0cfa4b85,0x00920778 },
|
|
{ 0x0bf39d44,0x1238f008,0x0ed4f5f8,0x1920412d,0x03d8f5f2,0x1bd9ae4e,
|
|
0x0d453112,0x117a537d,0x0081e842 } },
|
|
/* 179 */
|
|
{ { 0x0477199f,0x0ece15d6,0x17b3765b,0x11dddcd6,0x0fd0e8cb,0x0d9ff720,
|
|
0x12c62bdf,0x0c5b77f4,0x001b94ab },
|
|
{ 0x0e47f143,0x0786c59e,0x1d1858d1,0x0c47f8c7,0x1938351e,0x1387e62c,
|
|
0x03bbc63c,0x0500aab2,0x0006a38e } },
|
|
/* 180 */
|
|
{ { 0x13355b49,0x12d809cd,0x1afe66cb,0x04cac169,0x1f3dc20e,0x1d35e934,
|
|
0x13e3023f,0x04107b3a,0x00a7b36c },
|
|
{ 0x1b3e8830,0x068ae1d0,0x07e702d9,0x19d5c351,0x16930d5f,0x12517168,
|
|
0x08833fbb,0x16945045,0x00be54c6 } },
|
|
/* 181 */
|
|
{ { 0x0d91167c,0x166d9efc,0x099897b5,0x187ef3cf,0x0c7f4517,0x12479a35,
|
|
0x0aedc415,0x157d5c04,0x00bf30a5 },
|
|
{ 0x13828a68,0x13bc2df4,0x0fbc0da3,0x038664fe,0x146b2516,0x0ff5ac90,
|
|
0x04eb846d,0x1bc4e65a,0x00d1c820 } },
|
|
/* 182 */
|
|
{ { 0x1038b363,0x01f09a3c,0x01794641,0x023ea8d6,0x0cad158c,0x1d5f3013,
|
|
0x168d3f95,0x1dad1431,0x00b7d17b },
|
|
{ 0x029c2559,0x0652c48f,0x1fff6111,0x1406ecb7,0x069484f7,0x1257ba72,
|
|
0x11912637,0x0bcc8259,0x003997fd } },
|
|
/* 183 */
|
|
{ { 0x0bd61507,0x103a3414,0x09934abc,0x0265aa69,0x015e329e,0x0fd84545,
|
|
0x0fa3ffb7,0x05278d82,0x000eeb89 },
|
|
{ 0x07e259f8,0x0db4d1f5,0x0f9f99fa,0x1b6fcda2,0x1a685ce1,0x0c7b568f,
|
|
0x1bbc9dcc,0x1f192456,0x00228916 } },
|
|
/* 184 */
|
|
{ { 0x0a12ab5b,0x0cd712d8,0x1ef04da5,0x022e3f2a,0x02b0ccc1,0x014f68b7,
|
|
0x05fa0161,0x03add261,0x00ec05ad },
|
|
{ 0x0c3f3708,0x0bdd2df5,0x0d675dc5,0x15f26a61,0x034e531b,0x091b88c1,
|
|
0x0cdd1ed5,0x0acffe23,0x007d3141 } },
|
|
/* 185 */
|
|
{ { 0x16dfefab,0x1ece02e7,0x0cddc1de,0x1e44d1b9,0x0bb95be2,0x16cb9d1c,
|
|
0x1e8f94fa,0x1f93783a,0x00e9ce66 },
|
|
{ 0x0f6a02a1,0x0d50abb3,0x19803b5d,0x010fbec1,0x1c1b938c,0x1f9a3466,
|
|
0x1947e251,0x002e4500,0x00d9650b } },
|
|
/* 186 */
|
|
{ { 0x1a057e60,0x025a6252,0x1bc97914,0x19877d1b,0x1ccbdcbc,0x19040be0,
|
|
0x1e8a98d4,0x135009d6,0x0014d669 },
|
|
{ 0x1b1f411a,0x045420ae,0x035da70b,0x175e17f0,0x177ad09f,0x17c80e17,
|
|
0x062ad37b,0x0821a86b,0x006f4c68 } },
|
|
/* 187 */
|
|
{ { 0x16c24a96,0x1936fa74,0x0f6668e1,0x1b790bf9,0x0e30a534,0x17794595,
|
|
0x0aecf119,0x1fac2313,0x004c4350 },
|
|
{ 0x1855b8da,0x0b3fb8b7,0x0f0e284a,0x0847288c,0x1334341a,0x0a09f574,
|
|
0x02d70df8,0x084b4623,0x00a726d2 } },
|
|
/* 188 */
|
|
{ { 0x148c1086,0x17359f74,0x14e8b876,0x1ca07b97,0x022f3f1d,0x169f81e8,
|
|
0x0e48fcd7,0x10598d9e,0x0013639e },
|
|
{ 0x0dafaa86,0x1649c7de,0x15289626,0x178bf64c,0x11329f45,0x19372282,
|
|
0x168c658e,0x1c383466,0x00ca9365 } },
|
|
/* 189 */
|
|
{ { 0x0c3b2d20,0x10ad63aa,0x138906cd,0x14a82f20,0x1071d742,0x10e2664e,
|
|
0x0a96c214,0x0692e16e,0x009ce29c },
|
|
{ 0x0d3e0ad6,0x0640fb9b,0x1e10d323,0x01b53de5,0x062d9806,0x0e8d3674,
|
|
0x1e60d7b4,0x1af56855,0x0048c4ab } },
|
|
/* 190 */
|
|
{ { 0x00c7485a,0x110d8662,0x09d36ff4,0x08ab77ca,0x1d2e8ead,0x1b4c4931,
|
|
0x0f2d24f1,0x065ecf66,0x0078017c },
|
|
{ 0x130cb5ee,0x0e9abb4c,0x1023b4ae,0x029d2818,0x11a4dc0d,0x1faa9397,
|
|
0x1013e2de,0x0a9bcb83,0x0053cd04 } },
|
|
/* 191 */
|
|
{ { 0x1d28ccac,0x06ac2fd2,0x16dd1baf,0x047cac00,0x123aa5f8,0x1850e680,
|
|
0x0a3df1e7,0x183a7aff,0x00eea465 },
|
|
{ 0x0551803b,0x00832cf8,0x19abdc1e,0x16b33ef9,0x08e706c0,0x13b81494,
|
|
0x064d0656,0x148f5cd2,0x001b6e42 } },
|
|
/* 192 */
|
|
{ { 0x167d04c3,0x14049be7,0x1bae044b,0x0257c513,0x14d601e3,0x0c43c92c,
|
|
0x14f55ad7,0x02830ff7,0x000224da },
|
|
{ 0x0c5fe36f,0x1d5dc318,0x1d47d7e1,0x1e78c09d,0x029ec580,0x18dfd9da,
|
|
0x1cce593e,0x1e0857ff,0x0060838e } },
|
|
/* 193 */
|
|
{ { 0x1e0bbe99,0x19659793,0x0a8e7b90,0x1489e609,0x139037bd,0x1e3d4fd4,
|
|
0x190d7d25,0x0045a662,0x00636eb2 },
|
|
{ 0x13ae00aa,0x07e8730c,0x0b9b4bff,0x1401fc63,0x1901c875,0x0c514fc9,
|
|
0x0eb3d0d9,0x16c72431,0x008844ee } },
|
|
/* 194 */
|
|
{ { 0x0b3bae58,0x0a0b8e93,0x18e7cf84,0x07bee22f,0x0eada7db,0x1e3fc0d4,
|
|
0x027b34de,0x1b8a3f6f,0x0027ba83 },
|
|
{ 0x1bf54de5,0x1efa1cff,0x1f869c69,0x0e06176b,0x17a48727,0x071aed94,
|
|
0x12ad0bba,0x0690fe74,0x00adb62d } },
|
|
/* 195 */
|
|
{ { 0x0175df2a,0x188b4515,0x030cba66,0x15409ec3,0x10916082,0x19738a35,
|
|
0x02cb2793,0x0ecebcf9,0x00b990fd },
|
|
{ 0x0df37313,0x014ecb5a,0x0d01e242,0x00aaf3a1,0x077111c2,0x17253c04,
|
|
0x06359b26,0x1f29a21a,0x0081707e } },
|
|
/* 196 */
|
|
{ { 0x03d6ff96,0x1ebe5590,0x010cd825,0x0a37f81b,0x0db4b5b8,0x11e26821,
|
|
0x09709a20,0x1d5ab515,0x003792da },
|
|
{ 0x141afa0b,0x140c432c,0x160d9c54,0x13ce8285,0x0e0a7f3e,0x1293adf2,
|
|
0x06e85f20,0x0bd29600,0x005abd63 } },
|
|
/* 197 */
|
|
{ { 0x0ac4927c,0x13fd4270,0x1233c8dc,0x10c06b4f,0x0a0dfe38,0x0af5256e,
|
|
0x184292f3,0x04308d56,0x005995bf },
|
|
{ 0x029dfa33,0x087c305c,0x03f062fa,0x1fc55d2b,0x10366caa,0x17a23c31,
|
|
0x047a6cee,0x145a9068,0x0044c32c } },
|
|
/* 198 */
|
|
{ { 0x040ed80c,0x1a54bf8f,0x14b2a0a9,0x07196263,0x16ad95f9,0x0925be16,
|
|
0x15314fc8,0x1f701054,0x001f2162 },
|
|
{ 0x120b173e,0x1233e62b,0x17c4be5f,0x114ccc10,0x165dc40e,0x0107264e,
|
|
0x1f2633af,0x05787d20,0x008f1d40 } },
|
|
/* 199 */
|
|
{ { 0x1bc4058a,0x1ac97ce7,0x0bd59c13,0x1c296c52,0x18c57b15,0x1f1bde0e,
|
|
0x0fe71573,0x08724ddb,0x00b1980f },
|
|
{ 0x12c76b09,0x0619f049,0x0c1fde26,0x0a4f3a67,0x1b4611df,0x156a431d,
|
|
0x1915bc23,0x1366e891,0x002828ad } },
|
|
/* 200 */
|
|
{ { 0x04cf4ac5,0x0b391626,0x1992beda,0x18347fbb,0x10832f5a,0x1d517044,
|
|
0x0e401546,0x04eb4296,0x004973f1 },
|
|
{ 0x122eac5d,0x0cec19a9,0x166d5a39,0x0fddea17,0x083935e0,0x1907d12c,
|
|
0x0b1eacd9,0x1a1b62d1,0x006dac8e } },
|
|
/* 201 */
|
|
{ { 0x0da835ef,0x1daa2d77,0x043b547d,0x0227a43a,0x01b094aa,0x12f009ba,
|
|
0x19300d69,0x0b24173b,0x004b23ef },
|
|
{ 0x1c4c7341,0x015db401,0x162f0dfa,0x0ee0da7e,0x03ee8d45,0x1c31d28f,
|
|
0x0939cd49,0x069bbe93,0x004dd715 } },
|
|
/* 202 */
|
|
{ { 0x15476cd9,0x1ca23394,0x069c96ef,0x1a0e5fc6,0x167e0648,0x045c7e25,
|
|
0x16ec5107,0x0005e949,0x00fd3170 },
|
|
{ 0x0995d0e1,0x05a1ffa4,0x1dca6a87,0x0d2ba21d,0x1898276e,0x1cbb20bc,
|
|
0x0d978357,0x1192ad3e,0x0014fac5 } },
|
|
/* 203 */
|
|
{ { 0x1312ae18,0x0cd0032f,0x124ff26b,0x0b1b81f9,0x12846519,0x0120453e,
|
|
0x09436685,0x0a26d57b,0x00ed7c76 },
|
|
{ 0x05d4abbc,0x113878d1,0x0844fa91,0x1bb1e7e3,0x1952f9b5,0x183aada8,
|
|
0x1d4f1826,0x1ee9a5d3,0x00fefcb7 } },
|
|
/* 204 */
|
|
{ { 0x1a119185,0x084a4bd5,0x1116e92f,0x1d186155,0x01179d54,0x1cef5529,
|
|
0x002d2491,0x0fd0fc1b,0x001801a5 },
|
|
{ 0x1cafffb0,0x19e9fc6f,0x09549001,0x0678175c,0x1dfbc6cf,0x1b1dadaf,
|
|
0x0191e075,0x03c3d5a2,0x009f8fc1 } },
|
|
/* 205 */
|
|
{ { 0x1e69544c,0x0c1d0b8a,0x12de04c5,0x1f0acfe0,0x04c320ea,0x147e93c5,
|
|
0x06a4788a,0x13a7a74d,0x00a9d380 },
|
|
{ 0x19a2da3b,0x1b616162,0x057211e4,0x1979ec31,0x1086938c,0x122731ea,
|
|
0x1bdd7994,0x15dc22f1,0x003006b9 } },
|
|
/* 206 */
|
|
{ { 0x09eead28,0x1d8f9586,0x1d37ef02,0x1ec6bb13,0x089397ee,0x0bfed967,
|
|
0x1d841d1d,0x1ae8bf1e,0x000ab85f },
|
|
{ 0x1e5b4549,0x06d3e499,0x048bc87b,0x0576b92f,0x180404be,0x093a5a1d,
|
|
0x0b089868,0x0ea23d28,0x00b122d6 } },
|
|
/* 207 */
|
|
{ { 0x06a5ae7a,0x1f303df3,0x0b72f8ce,0x0e07f4ed,0x0e5c501e,0x0180a75b,
|
|
0x0bb2be41,0x18212fb7,0x009f599d },
|
|
{ 0x0ff250ed,0x0badb8c0,0x0688371b,0x122ae869,0x027a38eb,0x02d20859,
|
|
0x0de10958,0x1c114529,0x007d5528 } },
|
|
/* 208 */
|
|
{ { 0x00c26def,0x07ac7b31,0x0acb47bc,0x0b0bd4b0,0x03881025,0x0bcd80e7,
|
|
0x1cc3ef9f,0x002607e2,0x0028ccea },
|
|
{ 0x19644ba5,0x0ed5e68b,0x1ffc2e34,0x0c87d00d,0x1e17b1fc,0x1b7e3359,
|
|
0x0efe9829,0x09143a02,0x00c18baf } },
|
|
/* 209 */
|
|
{ { 0x1dc4216d,0x0731c642,0x1850ab0d,0x0020ce40,0x1064a00c,0x10b8cafa,
|
|
0x05af514e,0x13b6f52b,0x009def80 },
|
|
{ 0x07ab8d2c,0x0f432173,0x0de8ad90,0x080866c4,0x0218bb42,0x1536b262,
|
|
0x1395f541,0x160d1011,0x000357f8 } },
|
|
/* 210 */
|
|
{ { 0x0cd2cc88,0x14edf322,0x0e3ce763,0x03851be1,0x0a0c8cc6,0x0c3a6698,
|
|
0x021d28c2,0x1ba36913,0x00e4a01a },
|
|
{ 0x157cd8f9,0x168f7567,0x1653120b,0x0cfa7d7a,0x0f7871b7,0x0e38bde9,
|
|
0x10c29ca5,0x0f39c219,0x00466d7d } },
|
|
/* 211 */
|
|
{ { 0x1dada2c7,0x1e98c494,0x06a89f51,0x014d871f,0x059e14fa,0x1e944105,
|
|
0x146a4393,0x0448a3d5,0x00c672a5 },
|
|
{ 0x1d86b655,0x0303e642,0x0b52bc4c,0x06ba77f3,0x172a6f02,0x03402b88,
|
|
0x144e6682,0x1f5e54ce,0x005e3d64 } },
|
|
/* 212 */
|
|
{ { 0x1b3b4416,0x1320863c,0x0c9b666a,0x1f9f0bd5,0x16a74cd8,0x1ba56db2,
|
|
0x0bf17aff,0x12bd71c8,0x006c8a7a },
|
|
{ 0x102a63bd,0x06305d3d,0x03c011c4,0x1e460717,0x190b06b2,0x1b9c1896,
|
|
0x0a4631b0,0x0455b059,0x00348ae4 } },
|
|
/* 213 */
|
|
{ { 0x1ccda2fb,0x1a3a331a,0x01c9b49f,0x1995431c,0x11f2022a,0x1bc12495,
|
|
0x14ba16b7,0x1c1b3de5,0x00c1074d },
|
|
{ 0x0e9a65b3,0x079e7225,0x15c546ff,0x03c9580b,0x09788fd7,0x0fa86735,
|
|
0x1ff351c4,0x1b793ca9,0x00fbadfb } },
|
|
/* 214 */
|
|
{ { 0x00a99363,0x189f8e69,0x1c89dd45,0x0acb1ed9,0x159b2b91,0x1ae69269,
|
|
0x1f365a05,0x16906e2d,0x00b7f976 },
|
|
{ 0x1d6dbf74,0x1ac7126a,0x10ebcd95,0x0775fae3,0x1dfe38d2,0x1bb00121,
|
|
0x001523d1,0x05d95f99,0x00f4d41b } },
|
|
/* 215 */
|
|
{ { 0x1dabd48d,0x0f8e7947,0x101e2914,0x037c6c65,0x146e9ce8,0x14ba08b8,
|
|
0x1c41ab38,0x1d5c02c1,0x00180824 },
|
|
{ 0x06e58358,0x1c3b4c5b,0x1b28d600,0x0d0ea59c,0x1e6c5635,0x071a2f20,
|
|
0x149608e0,0x073079ed,0x0067e5f6 } },
|
|
/* 216 */
|
|
{ { 0x0f4899ef,0x04e65c6e,0x0ed1303e,0x002be13d,0x18ec9949,0x093b592c,
|
|
0x1f1951be,0x13409823,0x009fef78 },
|
|
{ 0x13d2a071,0x09b3f67a,0x1466c25b,0x1c34ff48,0x02eefb10,0x1fd8308f,
|
|
0x188329ac,0x10353389,0x00bc80c1 } },
|
|
/* 217 */
|
|
{ { 0x05eb82e6,0x1929b7c7,0x1b2e4825,0x109f8fea,0x1da5e1a4,0x10b8a85a,
|
|
0x1c431e38,0x0c53f19b,0x0049270e },
|
|
{ 0x0a6b50ad,0x11cdbddf,0x0e23ff06,0x05098344,0x1197b9a0,0x158bc083,
|
|
0x1dfd500f,0x1f2c26e5,0x00d2ee52 } },
|
|
/* 218 */
|
|
{ { 0x08e0362a,0x1be6942c,0x09765374,0x1f514f1f,0x0a526442,0x1b72d21a,
|
|
0x1ccebfe0,0x17dcb576,0x00dfb478 },
|
|
{ 0x073eede6,0x08f8e73b,0x16cbc12a,0x1215a856,0x0da2fa53,0x1bdfaa98,
|
|
0x1ce9799b,0x16811be8,0x00d9a140 } },
|
|
/* 219 */
|
|
{ { 0x0e8ea498,0x10110dab,0x18fb8243,0x08f0526a,0x12ade623,0x01c899ae,
|
|
0x0c6b81ae,0x11ac47e9,0x00760c05 },
|
|
{ 0x0198aa79,0x1c4dac66,0x1eae9fc2,0x1121a5e0,0x0556af74,0x00887ef1,
|
|
0x10253881,0x05b1e320,0x00714198 } },
|
|
/* 220 */
|
|
{ { 0x0d4b0f45,0x1850719a,0x0aa5385b,0x10167072,0x01d5ed92,0x126359e3,
|
|
0x191cebcc,0x19d13aa9,0x003af9d1 },
|
|
{ 0x00930371,0x0c7bcc09,0x105c25ff,0x04cc9843,0x0309beda,0x02ee6e21,
|
|
0x17583a55,0x186e72af,0x00b1f815 } },
|
|
/* 221 */
|
|
{ { 0x09fec44a,0x07d53c74,0x0a932be1,0x055c8e79,0x0a624c8c,0x003ee0db,
|
|
0x0149a472,0x0282a87e,0x00a41aed },
|
|
{ 0x1d5ffe04,0x121a9ccb,0x16db8810,0x1965bec4,0x177758ba,0x105f43c0,
|
|
0x03be1759,0x1bb0df6c,0x00d6e9c1 } },
|
|
/* 222 */
|
|
{ { 0x06853264,0x15174bf6,0x0c1282ce,0x0a676fc4,0x0e9be771,0x15dbdc75,
|
|
0x03086e44,0x0215d37f,0x009c9c6e },
|
|
{ 0x0030b74c,0x1184d2cf,0x18c7a428,0x0e929ad4,0x179f24ed,0x0591d24d,
|
|
0x06da27d1,0x12c81f4c,0x00566bd5 } },
|
|
/* 223 */
|
|
{ { 0x018061f3,0x136008c6,0x00ff1c01,0x164ba6f9,0x13245190,0x04701393,
|
|
0x117bc17f,0x121ea4a6,0x00cf2c73 },
|
|
{ 0x10eb30cf,0x04de75a0,0x1ddc0ea8,0x05d7741a,0x1f255cfd,0x021d0a87,
|
|
0x05e7a10b,0x0ab15441,0x0002f517 } },
|
|
/* 224 */
|
|
{ { 0x0ddb7d07,0x0b77bca5,0x1155400e,0x1f8e8448,0x0a3ce0b4,0x075663c5,
|
|
0x05f7ebfe,0x14bd1a9b,0x0014e9ad },
|
|
{ 0x0f7079e2,0x15240509,0x0c2003b6,0x15479bc9,0x0157d45b,0x0f16bc1c,
|
|
0x0ba005d9,0x1571d3b3,0x00a0ad4f } },
|
|
/* 225 */
|
|
{ { 0x0a653618,0x1fdbb10a,0x1aaa97c2,0x05027863,0x09d5e187,0x139ba24a,
|
|
0x1478554f,0x170dcadd,0x00bcd530 },
|
|
{ 0x12e9c47b,0x14df4299,0x00166ac5,0x0eedfd6a,0x1fbb4dc2,0x0bb08c95,
|
|
0x107736ea,0x19ed2f26,0x00909283 } },
|
|
/* 226 */
|
|
{ { 0x16e81a13,0x1d801923,0x05c48e59,0x1c3532c4,0x019d69be,0x1b0de997,
|
|
0x126823b4,0x19359c2a,0x0035eeb7 },
|
|
{ 0x1e4e5bdc,0x140572d3,0x13bb1b84,0x1a59a76d,0x06bc12dc,0x11263713,
|
|
0x01914b90,0x1e88915d,0x009a8b2c } },
|
|
/* 227 */
|
|
{ { 0x09d03b59,0x1238df90,0x16bcaafd,0x1cc5476c,0x1eec9c90,0x18b475ea,
|
|
0x0de7fdff,0x1e9a8922,0x006bdb60 },
|
|
{ 0x0a55bc30,0x16d7f5e4,0x025ff836,0x1d5a2c20,0x03bddc79,0x0ba0a60f,
|
|
0x02a50b86,0x1fb29741,0x0001ec3c } },
|
|
/* 228 */
|
|
{ { 0x1c9485c2,0x1313bf5e,0x1ec431ee,0x1934f245,0x08d8a48c,0x0b07b851,
|
|
0x13d93d87,0x1808ea8c,0x00d1acb1 },
|
|
{ 0x06f36612,0x13481589,0x186362f4,0x07489dc0,0x157ee59c,0x14099841,
|
|
0x1b0937e2,0x13a80ac4,0x007dcd07 } },
|
|
/* 229 */
|
|
{ { 0x105a4b48,0x073ea69f,0x08c1dc97,0x1a52a46e,0x0915aadc,0x1cb8c095,
|
|
0x06e3463d,0x1126efa3,0x000bf535 },
|
|
{ 0x0c68ea73,0x0f66cad3,0x0e96134d,0x07779504,0x1a723c7f,0x1a637a39,
|
|
0x1bf27ed9,0x1b3c2cd0,0x00d28be4 } },
|
|
/* 230 */
|
|
{ { 0x18fa8e4b,0x095cc831,0x0ff63f17,0x1e30dd12,0x1b6fc559,0x115521b7,
|
|
0x0338e9b7,0x154a21f1,0x00d76007 },
|
|
{ 0x123a4988,0x088555b2,0x17409ccb,0x0b9e88e9,0x07278b45,0x184151a0,
|
|
0x0c05fd19,0x0d166077,0x00f2b52f } },
|
|
/* 231 */
|
|
{ { 0x1835b4ca,0x0abf57d4,0x19a72f03,0x0465f976,0x031982d2,0x1b406332,
|
|
0x14ea3bba,0x11d98b5d,0x00d8dbe9 },
|
|
{ 0x05a02709,0x1d4df1fe,0x0e87ea32,0x1cd1cbeb,0x0a85230b,0x01e6f887,
|
|
0x1c17faf5,0x147dcab2,0x00e01593 } },
|
|
/* 232 */
|
|
{ { 0x0a75a0a6,0x1f2d7a87,0x01600cf4,0x044d58af,0x16406512,0x0a87e80b,
|
|
0x1c19bf9b,0x1635d71d,0x00afec07 },
|
|
{ 0x00bb0a31,0x1dccab3c,0x0c26ab9f,0x15e7986e,0x1f3896f1,0x10ad00d5,
|
|
0x1f76454e,0x0a8dc5b7,0x00a71b93 } },
|
|
/* 233 */
|
|
{ { 0x18f593d2,0x1c709700,0x1e048aef,0x12085140,0x0f2add1a,0x02ed85d2,
|
|
0x0f645414,0x0b8c50a4,0x0053a200 },
|
|
{ 0x07f2b935,0x1e45b1cf,0x00a58681,0x1f2eb583,0x0ca2c2bf,0x1753ba8c,
|
|
0x18f61af3,0x1367ab11,0x00bf47d1 } },
|
|
/* 234 */
|
|
{ { 0x1d7665d5,0x194b3d3e,0x0bd37959,0x0060ae5e,0x0903f4e3,0x02d7406a,
|
|
0x06d85100,0x0fe73934,0x00001c2c },
|
|
{ 0x09efc6d6,0x01d400a3,0x11e9c905,0x017b54f7,0x150a4c81,0x1385d3c0,
|
|
0x066d7d95,0x1cf0dff7,0x00fdadf8 } },
|
|
/* 235 */
|
|
{ { 0x1fc00785,0x09c65c47,0x123ad9ff,0x14eb2276,0x08fbc77f,0x082adf9b,
|
|
0x12501153,0x09ab5487,0x003a838e },
|
|
{ 0x1e97bb9a,0x10b31949,0x07653655,0x1266c688,0x12a839eb,0x08d3056d,
|
|
0x168d4556,0x0af0e7c3,0x003cdb82 } },
|
|
/* 236 */
|
|
{ { 0x1de77eab,0x1b8a054b,0x19204244,0x038a1a82,0x1d0dff7e,0x05696758,
|
|
0x1ee9d8b7,0x113e3eaf,0x005a60cc },
|
|
{ 0x00d45673,0x059b1c12,0x04f19560,0x057c32b2,0x0b7411b8,0x025c6eb2,
|
|
0x1f0015ca,0x0dfb7fb1,0x00922ff5 } },
|
|
/* 237 */
|
|
{ { 0x09a129a1,0x1932ef76,0x0a138106,0x039caf98,0x1be3ca5b,0x0623675f,
|
|
0x158810e0,0x0fbed8b9,0x0072919a },
|
|
{ 0x0fb90f9a,0x0c7a29d4,0x1900c6ca,0x13801711,0x11856d71,0x073bbcb7,
|
|
0x026b8cb0,0x1006c481,0x005e7917 } },
|
|
/* 238 */
|
|
{ { 0x1f63cdfb,0x00b762ab,0x12b93f57,0x146ae3e3,0x197ca8e6,0x15f52b02,
|
|
0x1eaff389,0x0e3c4985,0x004e0a53 },
|
|
{ 0x05765357,0x1b52069d,0x1ce8ad09,0x135e881a,0x11a323c8,0x185720e8,
|
|
0x13bae3cd,0x031aacc0,0x00f5ff78 } },
|
|
/* 239 */
|
|
{ { 0x1a09df21,0x1f9f1ff0,0x1ba391fe,0x0ba51dcc,0x0901526d,0x1e8514e4,
|
|
0x1990825a,0x1d2a67eb,0x00e41df0 },
|
|
{ 0x13ba9e3f,0x02fed205,0x0136254c,0x0819d64c,0x167c7f23,0x10c93f81,
|
|
0x157c219b,0x0dd589e2,0x008edd7d } },
|
|
/* 240 */
|
|
{ { 0x0bfc8ff3,0x0d0ee070,0x0dbd0bf2,0x1fb057d2,0x181ef14e,0x17be6651,
|
|
0x1a599c05,0x195db15d,0x001432c1 },
|
|
{ 0x10b23c26,0x0342414b,0x0d6c9cfb,0x1fd0e60e,0x10f5aa64,0x1b72f577,
|
|
0x0b1b8e27,0x016b591a,0x00caef48 } },
|
|
/* 241 */
|
|
{ { 0x15315922,0x122e4bc3,0x18f32954,0x12a2e260,0x0f2cbd82,0x10685b27,
|
|
0x08dbcf39,0x0fd1df5c,0x00d0ba17 },
|
|
{ 0x11b3af60,0x1d4d747d,0x0b688394,0x12d5ca7a,0x0ef281a7,0x1b02efcf,
|
|
0x18580758,0x0f838a95,0x00f31c95 } },
|
|
/* 242 */
|
|
{ { 0x09cc4597,0x07ac6a92,0x18280a30,0x002b6175,0x0814adc5,0x1e2ab9a5,
|
|
0x10ebbf17,0x1972dc2f,0x00013404 },
|
|
{ 0x09a824bf,0x14f12c2e,0x07abb5ec,0x0630bc00,0x168acd59,0x134130f7,
|
|
0x19b235bb,0x09723267,0x006f377c } },
|
|
/* 243 */
|
|
{ { 0x08333fd2,0x1c9dd68d,0x0aa56e27,0x060404b4,0x15acea89,0x081bf57b,
|
|
0x14188479,0x09da5a12,0x006dba3e },
|
|
{ 0x104399cd,0x0477cc66,0x0dceb7a9,0x038cddcd,0x0caf3181,0x03a960bf,
|
|
0x129dcbd8,0x08477d9e,0x00f13cf3 } },
|
|
/* 244 */
|
|
{ { 0x0919e2eb,0x175cf605,0x0b03da33,0x13432bec,0x0229983a,0x1ddb3d5d,
|
|
0x0b4f3ee8,0x1524e977,0x00c83fa9 },
|
|
{ 0x02fa1ce0,0x0be8d85b,0x063befc3,0x16c1ea68,0x06f04e58,0x17cf2938,
|
|
0x1a0efea3,0x1e8bae04,0x00b49d70 } },
|
|
/* 245 */
|
|
{ { 0x1ad5513b,0x0a63a887,0x1d478b64,0x065dd962,0x19d5905f,0x020c6cfd,
|
|
0x073db614,0x1761861e,0x0059cfad },
|
|
{ 0x15cb7fd6,0x0b3d611a,0x0109a8f8,0x06cf7104,0x18864249,0x02c64853,
|
|
0x0d9fabbb,0x0c46a949,0x005babf3 } },
|
|
/* 246 */
|
|
{ { 0x0e424865,0x1e4c0e8f,0x1955dfcd,0x0050f1e5,0x0c0588b0,0x1878dcf0,
|
|
0x03c1c0a5,0x14f204d9,0x006188c6 },
|
|
{ 0x10f244da,0x17cd0cde,0x02021cc1,0x19dab9f6,0x136371ec,0x07cdcf90,
|
|
0x0764d51c,0x0ebbea17,0x00993fe4 } },
|
|
/* 247 */
|
|
{ { 0x1b2c3609,0x0718e6fc,0x11b53a9a,0x16338058,0x1510184e,0x160d4d3b,
|
|
0x05adeb27,0x0cc9900c,0x0081f764 },
|
|
{ 0x15fbe978,0x0be152d3,0x00ecd587,0x07fda7e3,0x1d2bf674,0x0f82280e,
|
|
0x18360e34,0x054bfd20,0x00564a81 } },
|
|
/* 248 */
|
|
{ { 0x1a817d1d,0x12d327a7,0x0a0b83de,0x12d0897d,0x1f9aa55f,0x0d07e6ab,
|
|
0x15b2d7fd,0x19e01ca3,0x00226bf3 },
|
|
{ 0x0f2833cf,0x168d4fc9,0x13e26a35,0x0146b49e,0x17f7720a,0x1624c79f,
|
|
0x00d8454d,0x08ffe4af,0x0068779f } },
|
|
/* 249 */
|
|
{ { 0x13043d08,0x0d860e0b,0x10083e9e,0x08cee83f,0x126d0a54,0x1f144d36,
|
|
0x182f4dd9,0x1a3d6125,0x0097bcb0 },
|
|
{ 0x132ed3c3,0x15b75547,0x006f120a,0x09e2a365,0x178f3c8a,0x1a79dfd0,
|
|
0x1955346f,0x1d014f08,0x00a872ff } },
|
|
/* 250 */
|
|
{ { 0x032b2086,0x0d5bc9ad,0x183d21ac,0x16e21d02,0x0e6bee1e,0x06c89db5,
|
|
0x0daa6f43,0x1f96e654,0x0002812b },
|
|
{ 0x0f605318,0x11febe56,0x1f5b4769,0x1cbaa1fb,0x0d619646,0x01cc1081,
|
|
0x1abe875a,0x193fca72,0x0007391c } },
|
|
/* 251 */
|
|
{ { 0x0b80d02b,0x080abf84,0x01dfdff1,0x0667a2c5,0x142ae6b8,0x0d7c3c6a,
|
|
0x0821eb28,0x1b8fcda5,0x00355d2a },
|
|
{ 0x087386e1,0x00f99ad1,0x190c9d6d,0x0e5529f1,0x189eafd2,0x1166f3cc,
|
|
0x09e4a1b2,0x1c6f8547,0x003dc2b1 } },
|
|
/* 252 */
|
|
{ { 0x04581352,0x144e90e0,0x19e0afb5,0x01904a6e,0x1701f0a0,0x0ac84ff6,
|
|
0x11ac80ef,0x020799b0,0x00c47869 },
|
|
{ 0x04c768ed,0x0dd3b841,0x107d95d7,0x1dd404d0,0x0ce0e72f,0x1f6ab566,
|
|
0x14c9ccc4,0x0d1ab769,0x00ccc429 } },
|
|
/* 253 */
|
|
{ { 0x1d7620b9,0x07286f09,0x04a95aa5,0x14b914b3,0x087c9d89,0x1b2033aa,
|
|
0x073f7001,0x0855490e,0x00e147eb },
|
|
{ 0x0cf3ae46,0x1a55a775,0x0d43ef89,0x126df6a0,0x040eafd4,0x1f23a464,
|
|
0x1b8f7cab,0x08e101d2,0x00239ac0 } },
|
|
/* 254 */
|
|
{ { 0x0bfee8d4,0x00e8f9a9,0x1ec3fb12,0x016b9ff4,0x1af3cce8,0x064f1674,
|
|
0x16744171,0x147ebefc,0x00c55fa1 },
|
|
{ 0x0257c227,0x0c378a74,0x0af802cc,0x02ca7e68,0x04fb2c5b,0x04cc5548,
|
|
0x1a6426bf,0x139a9e96,0x00094cd9 } },
|
|
/* 255 */
|
|
{ { 0x1703beba,0x14c0e426,0x13aca462,0x03a2a065,0x149ec863,0x1964f1de,
|
|
0x14ce9117,0x16c85575,0x00b90a30 },
|
|
{ 0x14a5abf9,0x032a027d,0x16dd80ed,0x0ea186eb,0x1d89f004,0x0166651a,
|
|
0x13ddbe69,0x13436f24,0x00019f8b } },
|
|
};
|
|
|
|
/* Multiply the base point of P256 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^32, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_mulmod_base_9(sp_point_256* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
return sp_256_ecc_mulmod_stripe_9(r, &p256_base, p256_table,
|
|
k, map, ct, heap);
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Multiply the base point of P256 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_256(const mp_int* km, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_256 point[1];
|
|
sp_digit k[9];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_256_from_mp(k, 9, km);
|
|
|
|
err = sp_256_ecc_mulmod_base_9(point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_point_to_ecc_point_9(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the base point of P256 by the scalar, add point a and return
|
|
* the result. If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_add_256(const mp_int* km, const ecc_point* am,
|
|
int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_256 point[2];
|
|
sp_digit k[9 + 9 * 2 * 6];
|
|
#endif
|
|
sp_point_256* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (9 + 9 * 2 * 6),
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 9;
|
|
|
|
sp_256_from_mp(k, 9, km);
|
|
sp_256_point_from_ecc_point_9(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_256_mod_mul_norm_9(addP->x, addP->x, p256_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_256_mod_mul_norm_9(addP->y, addP->y, p256_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_256_mod_mul_norm_9(addP->z, addP->z, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_ecc_mulmod_base_9(point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_256_proj_point_add_9(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_256_map_9(point, point, tmp);
|
|
}
|
|
|
|
err = sp_256_point_to_ecc_point_9(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
|
|
defined(HAVE_ECC_VERIFY)
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
|
|
/* Add 1 to a. (a = a + 1)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_256_add_one_9(sp_digit* a)
|
|
{
|
|
a[0]++;
|
|
sp_256_norm_9(a);
|
|
}
|
|
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_256_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 21U) {
|
|
r[j] &= 0x1fffffff;
|
|
s = 29U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Generates a scalar that is in the range 1..order-1.
|
|
*
|
|
* rng Random number generator.
|
|
* k Scalar value.
|
|
* returns RNG failures, MEMORY_E when memory allocation fails and
|
|
* MP_OKAY on success.
|
|
*/
|
|
static int sp_256_ecc_gen_k_9(WC_RNG* rng, sp_digit* k)
|
|
{
|
|
int err;
|
|
byte buf[32];
|
|
|
|
do {
|
|
err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
|
|
if (err == 0) {
|
|
sp_256_from_bin(k, 9, buf, (int)sizeof(buf));
|
|
if (sp_256_cmp_9(k, p256_order2) <= 0) {
|
|
sp_256_add_one_9(k);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while (err == 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Makes a random EC key pair.
|
|
*
|
|
* rng Random number generator.
|
|
* priv Generated private value.
|
|
* pub Generated public point.
|
|
* heap Heap to use for allocation.
|
|
* returns ECC_INF_E when the point does not have the correct order, RNG
|
|
* failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_256 point[2];
|
|
#else
|
|
sp_point_256 point[1];
|
|
#endif
|
|
sp_digit k[9];
|
|
#endif
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_256* infinity = NULL;
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap, DYNAMIC_TYPE_ECC);
|
|
#else
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
infinity = point + 1;
|
|
#endif
|
|
|
|
err = sp_256_ecc_gen_k_9(rng, k);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_ecc_mulmod_9(infinity, point, p256_order, 1, 1, NULL);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (sp_256_iszero_9(point->x) || sp_256_iszero_9(point->y)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(k, priv);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_point_to_ecc_point_9(point, pub);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL) {
|
|
/* point is not sensitive, so no need to zeroize */
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
}
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_key_gen_256_ctx {
|
|
int state;
|
|
sp_256_ecc_mulmod_9_ctx mulmod_ctx;
|
|
sp_digit k[9];
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_256 point[2];
|
|
#else
|
|
sp_point_256 point[1];
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
} sp_ecc_key_gen_256_ctx;
|
|
|
|
int sp_ecc_make_key_256_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv,
|
|
ecc_point* pub, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_key_gen_256_ctx* ctx = (sp_ecc_key_gen_256_ctx*)sp_ctx->data;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_256* infinity = ctx->point + 1;
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_key_gen_256_ctx)
|
|
>= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
err = sp_256_ecc_gen_k_9(rng, ctx->k);
|
|
if (err == MP_OKAY) {
|
|
err = FP_WOULDBLOCK;
|
|
ctx->state = 1;
|
|
}
|
|
break;
|
|
case 1:
|
|
err = sp_256_ecc_mulmod_base_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
ctx->point, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
err = FP_WOULDBLOCK;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 2;
|
|
#else
|
|
ctx->state = 3;
|
|
#endif
|
|
}
|
|
break;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
case 2:
|
|
err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
infinity, ctx->point, p256_order, 1, 1);
|
|
if (err == MP_OKAY) {
|
|
if (sp_256_iszero_9(ctx->point->x) ||
|
|
sp_256_iszero_9(ctx->point->y)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
else {
|
|
err = FP_WOULDBLOCK;
|
|
ctx->state = 3;
|
|
}
|
|
}
|
|
break;
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
case 3:
|
|
err = sp_256_to_mp(ctx->k, priv);
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_point_to_ecc_point_9(ctx->point, pub);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_256_ctx));
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#ifdef HAVE_ECC_DHE
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 32
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_256_to_bin_9(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<8; i++) {
|
|
r[i+1] += r[i] >> 29;
|
|
r[i] &= 0x1fffffff;
|
|
}
|
|
j = 263 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<9 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 29) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 29);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Multiply the point by the scalar and serialize the X ordinate.
|
|
* The number is 0 padded to maximum size on output.
|
|
*
|
|
* priv Scalar to multiply the point by.
|
|
* pub Point to multiply.
|
|
* out Buffer to hold X ordinate.
|
|
* outLen On entry, size of the buffer in bytes.
|
|
* On exit, length of data in buffer in bytes.
|
|
* heap Heap to use for allocation.
|
|
* returns BUFFER_E if the buffer is to small for output size,
|
|
* MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_secret_gen_256(const mp_int* priv, const ecc_point* pub, byte* out,
|
|
word32* outLen, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_256 point[1];
|
|
sp_digit k[9];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 32U) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_256_from_mp(k, 9, priv);
|
|
sp_256_point_from_ecc_point_9(point, pub);
|
|
err = sp_256_ecc_mulmod_9(point, point, k, 1, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_256_to_bin_9(point->x, out);
|
|
*outLen = 32;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_sec_gen_256_ctx {
|
|
int state;
|
|
union {
|
|
sp_256_ecc_mulmod_9_ctx mulmod_ctx;
|
|
};
|
|
sp_digit k[9];
|
|
sp_point_256 point;
|
|
} sp_ecc_sec_gen_256_ctx;
|
|
|
|
int sp_ecc_secret_gen_256_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
|
const ecc_point* pub, byte* out, word32* outLen, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_sec_gen_256_ctx* ctx = (sp_ecc_sec_gen_256_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
if (*outLen < 32U) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
sp_256_from_mp(ctx->k, 9, priv);
|
|
sp_256_point_from_ecc_point_9(&ctx->point, pub);
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
&ctx->point, &ctx->point, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
sp_256_to_bin_9(ctx->point.x, out);
|
|
*outLen = 32;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 1) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_256_ctx));
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_DHE */
|
|
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
SP_NOINLINE static void sp_256_rshift_9(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
for (i=0; i<8; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (29 - n))) & 0x1fffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<8; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (29 - n)) & 0x1fffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (29 - n)) & 0x1fffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (29 - n)) & 0x1fffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (29 - n)) & 0x1fffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (29 - n)) & 0x1fffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (29 - n)) & 0x1fffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (29 - n)) & 0x1fffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (29 - n)) & 0x1fffffff);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[8] = a[8] >> n;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_256_mul_d_9(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 9; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1fffffff);
|
|
t >>= 29;
|
|
}
|
|
r[9] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[9];
|
|
|
|
t[ 0] = tb * a[ 0];
|
|
t[ 1] = tb * a[ 1];
|
|
t[ 2] = tb * a[ 2];
|
|
t[ 3] = tb * a[ 3];
|
|
t[ 4] = tb * a[ 4];
|
|
t[ 5] = tb * a[ 5];
|
|
t[ 6] = tb * a[ 6];
|
|
t[ 7] = tb * a[ 7];
|
|
t[ 8] = tb * a[ 8];
|
|
r[ 0] = (sp_digit) (t[ 0] & 0x1fffffff);
|
|
r[ 1] = (sp_digit)((t[ 0] >> 29) + (t[ 1] & 0x1fffffff));
|
|
r[ 2] = (sp_digit)((t[ 1] >> 29) + (t[ 2] & 0x1fffffff));
|
|
r[ 3] = (sp_digit)((t[ 2] >> 29) + (t[ 3] & 0x1fffffff));
|
|
r[ 4] = (sp_digit)((t[ 3] >> 29) + (t[ 4] & 0x1fffffff));
|
|
r[ 5] = (sp_digit)((t[ 4] >> 29) + (t[ 5] & 0x1fffffff));
|
|
r[ 6] = (sp_digit)((t[ 5] >> 29) + (t[ 6] & 0x1fffffff));
|
|
r[ 7] = (sp_digit)((t[ 6] >> 29) + (t[ 7] & 0x1fffffff));
|
|
r[ 8] = (sp_digit)((t[ 7] >> 29) + (t[ 8] & 0x1fffffff));
|
|
r[ 9] = (sp_digit) (t[ 8] >> 29);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
SP_NOINLINE static void sp_256_lshift_18(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
r[18] = a[17] >> (29 - n);
|
|
for (i=17; i>0; i--) {
|
|
r[i] = ((a[i] << n) | (a[i-1] >> (29 - n))) & 0x1fffffff;
|
|
}
|
|
#else
|
|
sp_int_digit s;
|
|
sp_int_digit t;
|
|
|
|
s = (sp_int_digit)a[17];
|
|
r[18] = s >> (29U - n);
|
|
s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
|
|
r[17] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
|
|
r[16] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
|
|
r[15] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
|
|
r[14] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
|
|
r[13] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
|
|
r[12] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
|
|
r[11] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
|
|
r[10] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
|
|
r[9] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
|
|
r[8] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
|
|
r[7] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
|
|
r[6] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
|
|
r[5] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
|
|
r[4] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
|
|
r[3] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
|
|
r[2] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
|
|
r[1] = ((s << n) | (t >> (29U - n))) & 0x1fffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[0] = (a[0] << n) & 0x1fffffff;
|
|
}
|
|
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Simplified based on top word of divisor being (1 << 29) - 1
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_256_div_9(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
sp_digit r1;
|
|
sp_digit mask;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 9 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 9 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 18 + 1;
|
|
sd = t2 + 9 + 1;
|
|
|
|
sp_256_mul_d_9(sd, d, (sp_digit)1 << 5);
|
|
sp_256_lshift_18(t1, a, 5);
|
|
t1[9 + 9] += t1[9 + 9 - 1] >> 29;
|
|
t1[9 + 9 - 1] &= 0x1fffffff;
|
|
for (i=8; i>=0; i--) {
|
|
r1 = t1[9 + i];
|
|
sp_256_mul_d_9(t2, sd, r1);
|
|
(void)sp_256_sub_9(&t1[i], &t1[i], t2);
|
|
t1[9 + i] -= t2[9];
|
|
sp_256_norm_9(&t1[i + 1]);
|
|
|
|
mask = ~((t1[9 + i] - 1) >> 31);
|
|
sp_256_cond_sub_9(t1 + i, t1 + i, sd, mask);
|
|
sp_256_norm_9(&t1[i + 1]);
|
|
}
|
|
sp_256_norm_9(t1);
|
|
sp_256_rshift_9(r, t1, 5);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_256_mod_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_256_div_9(a, m, NULL, r);
|
|
}
|
|
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* Multiply two number mod the order of P256 curve. (r = a * b mod order)
|
|
*
|
|
* r Result of the multiplication.
|
|
* a First operand of the multiplication.
|
|
* b Second operand of the multiplication.
|
|
*/
|
|
static void sp_256_mont_mul_order_9(sp_digit* r, const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_256_mul_9(r, a, b);
|
|
sp_256_mont_reduce_order_9(r, p256_order, p256_mp_order);
|
|
}
|
|
|
|
#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Order-2 for the P256 curve. */
|
|
static const uint32_t p256_order_minus_2[8] = {
|
|
0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU,0xffffffffU,0xffffffffU,
|
|
0x00000000U,0xffffffffU
|
|
};
|
|
#else
|
|
/* The low half of the order-2 of the P256 curve. */
|
|
static const sp_int_digit p256_order_low[4] = {
|
|
0xfc63254fU,0xf3b9cac2U,0xa7179e84U,0xbce6faadU
|
|
};
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Square number mod the order of P256 curve. (r = a * a mod order)
|
|
*
|
|
* r Result of the squaring.
|
|
* a Number to square.
|
|
*/
|
|
static void sp_256_mont_sqr_order_9(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_256_sqr_9(r, a);
|
|
sp_256_mont_reduce_order_9(r, p256_order, p256_mp_order);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Square number mod the order of P256 curve a number of times.
|
|
* (r = a ^ n mod order)
|
|
*
|
|
* r Result of the squaring.
|
|
* a Number to square.
|
|
*/
|
|
static void sp_256_mont_sqr_n_order_9(sp_digit* r, const sp_digit* a, int n)
|
|
{
|
|
int i;
|
|
|
|
sp_256_mont_sqr_order_9(r, a);
|
|
for (i=1; i<n; i++) {
|
|
sp_256_mont_sqr_order_9(r, r);
|
|
}
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Invert the number, in Montgomery form, modulo the order of the P256 curve.
|
|
* (r = 1 / a mod order)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_256_mont_inv_order_9_ctx {
|
|
int state;
|
|
int i;
|
|
} sp_256_mont_inv_order_9_ctx;
|
|
static int sp_256_mont_inv_order_9_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
|
|
sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_256_mont_inv_order_9_ctx* ctx = (sp_256_mont_inv_order_9_ctx*)sp_ctx;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_256_mont_inv_order_9_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 9);
|
|
ctx->i = 254;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
sp_256_mont_sqr_order_9(t, t);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
if ((p256_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
|
|
sp_256_mont_mul_order_9(t, t, a);
|
|
}
|
|
ctx->i--;
|
|
ctx->state = (ctx->i == 0) ? 3 : 1;
|
|
break;
|
|
case 3:
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 9U);
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
static void sp_256_mont_inv_order_9(sp_digit* r, const sp_digit* a,
|
|
sp_digit* td)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_digit* t = td;
|
|
int i;
|
|
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 9);
|
|
for (i=254; i>=0; i--) {
|
|
sp_256_mont_sqr_order_9(t, t);
|
|
if ((p256_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_256_mont_mul_order_9(t, t, a);
|
|
}
|
|
}
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 9U);
|
|
#else
|
|
sp_digit* t = td;
|
|
sp_digit* t2 = td + 2 * 9;
|
|
sp_digit* t3 = td + 4 * 9;
|
|
int i;
|
|
|
|
/* t = a^2 */
|
|
sp_256_mont_sqr_order_9(t, a);
|
|
/* t = a^3 = t * a */
|
|
sp_256_mont_mul_order_9(t, t, a);
|
|
/* t2= a^c = t ^ 2 ^ 2 */
|
|
sp_256_mont_sqr_n_order_9(t2, t, 2);
|
|
/* t3= a^f = t2 * t */
|
|
sp_256_mont_mul_order_9(t3, t2, t);
|
|
/* t2= a^f0 = t3 ^ 2 ^ 4 */
|
|
sp_256_mont_sqr_n_order_9(t2, t3, 4);
|
|
/* t = a^ff = t2 * t3 */
|
|
sp_256_mont_mul_order_9(t, t2, t3);
|
|
/* t3= a^ff00 = t ^ 2 ^ 8 */
|
|
sp_256_mont_sqr_n_order_9(t2, t, 8);
|
|
/* t = a^ffff = t2 * t */
|
|
sp_256_mont_mul_order_9(t, t2, t);
|
|
/* t2= a^ffff0000 = t ^ 2 ^ 16 */
|
|
sp_256_mont_sqr_n_order_9(t2, t, 16);
|
|
/* t = a^ffffffff = t2 * t */
|
|
sp_256_mont_mul_order_9(t, t2, t);
|
|
/* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */
|
|
sp_256_mont_sqr_n_order_9(t2, t, 64);
|
|
/* t2= a^ffffffff00000000ffffffff = t2 * t */
|
|
sp_256_mont_mul_order_9(t2, t2, t);
|
|
/* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */
|
|
sp_256_mont_sqr_n_order_9(t2, t2, 32);
|
|
/* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */
|
|
sp_256_mont_mul_order_9(t2, t2, t);
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6 */
|
|
for (i=127; i>=112; i--) {
|
|
sp_256_mont_sqr_order_9(t2, t2);
|
|
if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_256_mont_mul_order_9(t2, t2, a);
|
|
}
|
|
}
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6f */
|
|
sp_256_mont_sqr_n_order_9(t2, t2, 4);
|
|
sp_256_mont_mul_order_9(t2, t2, t3);
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */
|
|
for (i=107; i>=64; i--) {
|
|
sp_256_mont_sqr_order_9(t2, t2);
|
|
if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_256_mont_mul_order_9(t2, t2, a);
|
|
}
|
|
}
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */
|
|
sp_256_mont_sqr_n_order_9(t2, t2, 4);
|
|
sp_256_mont_mul_order_9(t2, t2, t3);
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */
|
|
for (i=59; i>=32; i--) {
|
|
sp_256_mont_sqr_order_9(t2, t2);
|
|
if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_256_mont_mul_order_9(t2, t2, a);
|
|
}
|
|
}
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */
|
|
sp_256_mont_sqr_n_order_9(t2, t2, 4);
|
|
sp_256_mont_mul_order_9(t2, t2, t3);
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */
|
|
for (i=27; i>=0; i--) {
|
|
sp_256_mont_sqr_order_9(t2, t2);
|
|
if ((p256_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_256_mont_mul_order_9(t2, t2, a);
|
|
}
|
|
}
|
|
/* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */
|
|
sp_256_mont_sqr_n_order_9(t2, t2, 4);
|
|
/* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */
|
|
sp_256_mont_mul_order_9(r, t2, t3);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
|
|
#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
|
|
#ifdef HAVE_ECC_SIGN
|
|
#ifndef SP_ECC_MAX_SIG_GEN
|
|
#define SP_ECC_MAX_SIG_GEN 64
|
|
#endif
|
|
|
|
/* Calculate second signature value S from R, k and private value.
|
|
*
|
|
* s = (r * x + e) / k
|
|
*
|
|
* s Signature value.
|
|
* r First signature value.
|
|
* k Ephemeral private key.
|
|
* x Private key as a number.
|
|
* e Hash of message as a number.
|
|
* tmp Temporary storage for intermediate numbers.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_calc_s_9(sp_digit* s, const sp_digit* r, sp_digit* k,
|
|
sp_digit* x, const sp_digit* e, sp_digit* tmp)
|
|
{
|
|
int err;
|
|
sp_digit carry;
|
|
sp_int32 c;
|
|
sp_digit* kInv = k;
|
|
|
|
/* Conv k to Montgomery form (mod order) */
|
|
sp_256_mul_9(k, k, p256_norm_order);
|
|
err = sp_256_mod_9(k, k, p256_order);
|
|
if (err == MP_OKAY) {
|
|
sp_256_norm_9(k);
|
|
|
|
/* kInv = 1/k mod order */
|
|
sp_256_mont_inv_order_9(kInv, k, tmp);
|
|
sp_256_norm_9(kInv);
|
|
|
|
/* s = r * x + e */
|
|
sp_256_mul_9(x, x, r);
|
|
err = sp_256_mod_9(x, x, p256_order);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_256_norm_9(x);
|
|
carry = sp_256_add_9(s, e, x);
|
|
sp_256_cond_sub_9(s, s, p256_order, 0 - carry);
|
|
sp_256_norm_9(s);
|
|
c = sp_256_cmp_9(s, p256_order);
|
|
sp_256_cond_sub_9(s, s, p256_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_256_norm_9(s);
|
|
|
|
/* s = s * k^-1 mod order */
|
|
sp_256_mont_mul_order_9(s, s, kInv);
|
|
sp_256_norm_9(s);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Sign the hash using the private key.
|
|
* e = [hash, 256 bits] from binary
|
|
* r = (k.G)->x mod order
|
|
* s = (r * x + e) / k mod order
|
|
* The hash is truncated to the first 256 bits.
|
|
*
|
|
* hash Hash to sign.
|
|
* hashLen Length of the hash data.
|
|
* rng Random number generator.
|
|
* priv Private part of key - scalar.
|
|
* rm First part of result as an mp_int.
|
|
* sm Sirst part of result as an mp_int.
|
|
* heap Heap to use for allocation.
|
|
* returns RNG failures, MEMORY_E when memory allocation fails and
|
|
* MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng,
|
|
const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* e = NULL;
|
|
sp_point_256* point = NULL;
|
|
#else
|
|
sp_digit e[7 * 2 * 9];
|
|
sp_point_256 point[1];
|
|
#endif
|
|
sp_digit* x = NULL;
|
|
sp_digit* k = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit* s = NULL;
|
|
sp_int32 c;
|
|
int err = MP_OKAY;
|
|
int i;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_256*)XMALLOC(sizeof(sp_point_256), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (e == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
x = e + 2 * 9;
|
|
k = e + 4 * 9;
|
|
r = e + 6 * 9;
|
|
tmp = e + 8 * 9;
|
|
s = e;
|
|
|
|
if (hashLen > 32U) {
|
|
hashLen = 32U;
|
|
}
|
|
}
|
|
|
|
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
|
|
/* New random point. */
|
|
if (km == NULL || mp_iszero(km)) {
|
|
err = sp_256_ecc_gen_k_9(rng, k);
|
|
}
|
|
else {
|
|
sp_256_from_mp(k, 9, km);
|
|
mp_zero(km);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_ecc_mulmod_base_9(point, k, 1, 1, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* r = point->x mod order */
|
|
XMEMCPY(r, point->x, sizeof(sp_digit) * 9U);
|
|
sp_256_norm_9(r);
|
|
c = sp_256_cmp_9(r, p256_order);
|
|
sp_256_cond_sub_9(r, r, p256_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_256_norm_9(r);
|
|
|
|
if (!sp_256_iszero_9(r)) {
|
|
/* x is modified in calculation of s. */
|
|
sp_256_from_mp(x, 9, priv);
|
|
/* s ptr == e ptr, e is modified in calculation of s. */
|
|
sp_256_from_bin(e, 9, hash, (int)hashLen);
|
|
|
|
err = sp_256_calc_s_9(s, r, k, x, e, tmp);
|
|
|
|
/* Check that signature is usable. */
|
|
if ((err == MP_OKAY) && (!sp_256_iszero_9(s))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
|
|
i = 1;
|
|
#endif
|
|
}
|
|
|
|
if (i == 0) {
|
|
err = RNG_FAILURE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(r, rm);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(s, sm);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (e != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(e, sizeof(sp_digit) * 7 * 2 * 9);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(e, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (point != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(point, sizeof(sp_point_256));
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_sign_256_ctx {
|
|
int state;
|
|
union {
|
|
sp_256_ecc_mulmod_9_ctx mulmod_ctx;
|
|
sp_256_mont_inv_order_9_ctx mont_inv_order_ctx;
|
|
};
|
|
sp_digit e[2*9];
|
|
sp_digit x[2*9];
|
|
sp_digit k[2*9];
|
|
sp_digit r[2*9];
|
|
sp_digit tmp[3 * 2*9];
|
|
sp_point_256 point;
|
|
sp_digit* s;
|
|
sp_digit* kInv;
|
|
int i;
|
|
} sp_ecc_sign_256_ctx;
|
|
|
|
int sp_ecc_sign_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
|
|
mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_sign_256_ctx* ctx = (sp_ecc_sign_256_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_sign_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->s = ctx->e;
|
|
ctx->kInv = ctx->k;
|
|
|
|
ctx->i = SP_ECC_MAX_SIG_GEN;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* GEN */
|
|
/* New random point. */
|
|
if (km == NULL || mp_iszero(km)) {
|
|
err = sp_256_ecc_gen_k_9(rng, ctx->k);
|
|
}
|
|
else {
|
|
sp_256_from_mp(ctx->k, 9, km);
|
|
mp_zero(km);
|
|
}
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* MULMOD */
|
|
err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
&ctx->point, &p256_base, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
ctx->state = 3;
|
|
}
|
|
break;
|
|
case 3: /* MODORDER */
|
|
{
|
|
sp_int32 c;
|
|
/* r = point->x mod order */
|
|
XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 9U);
|
|
sp_256_norm_9(ctx->r);
|
|
c = sp_256_cmp_9(ctx->r, p256_order);
|
|
sp_256_cond_sub_9(ctx->r, ctx->r, p256_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_256_norm_9(ctx->r);
|
|
|
|
if (hashLen > 32U) {
|
|
hashLen = 32U;
|
|
}
|
|
sp_256_from_mp(ctx->x, 9, priv);
|
|
sp_256_from_bin(ctx->e, 9, hash, (int)hashLen);
|
|
ctx->state = 4;
|
|
break;
|
|
}
|
|
case 4: /* KMODORDER */
|
|
/* Conv k to Montgomery form (mod order) */
|
|
sp_256_mul_9(ctx->k, ctx->k, p256_norm_order);
|
|
err = sp_256_mod_9(ctx->k, ctx->k, p256_order);
|
|
if (err == MP_OKAY) {
|
|
sp_256_norm_9(ctx->k);
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 5;
|
|
}
|
|
break;
|
|
case 5: /* KINV */
|
|
/* kInv = 1/k mod order */
|
|
err = sp_256_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* KINVNORM */
|
|
sp_256_norm_9(ctx->kInv);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7: /* R */
|
|
/* s = r * x + e */
|
|
sp_256_mul_9(ctx->x, ctx->x, ctx->r);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8: /* S1 */
|
|
err = sp_256_mod_9(ctx->x, ctx->x, p256_order);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 9;
|
|
break;
|
|
case 9: /* S2 */
|
|
{
|
|
sp_digit carry;
|
|
sp_int32 c;
|
|
sp_256_norm_9(ctx->x);
|
|
carry = sp_256_add_9(ctx->s, ctx->e, ctx->x);
|
|
sp_256_cond_sub_9(ctx->s, ctx->s,
|
|
p256_order, 0 - carry);
|
|
sp_256_norm_9(ctx->s);
|
|
c = sp_256_cmp_9(ctx->s, p256_order);
|
|
sp_256_cond_sub_9(ctx->s, ctx->s, p256_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_256_norm_9(ctx->s);
|
|
|
|
/* s = s * k^-1 mod order */
|
|
sp_256_mont_mul_order_9(ctx->s, ctx->s, ctx->kInv);
|
|
sp_256_norm_9(ctx->s);
|
|
|
|
/* Check that signature is usable. */
|
|
if (sp_256_iszero_9(ctx->s) == 0) {
|
|
ctx->state = 10;
|
|
break;
|
|
}
|
|
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
|
|
ctx->i = 1;
|
|
#endif
|
|
|
|
/* not usable gen, try again */
|
|
ctx->i--;
|
|
if (ctx->i == 0) {
|
|
err = RNG_FAILURE_E;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
}
|
|
case 10: /* RES */
|
|
err = sp_256_to_mp(ctx->r, rm);
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(ctx->s, sm);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 10) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 9U);
|
|
XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 9U);
|
|
XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 9U);
|
|
XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 9U);
|
|
XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 9U);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_SIGN */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
static const char sp_256_tab32_9[32] = {
|
|
1, 10, 2, 11, 14, 22, 3, 30,
|
|
12, 15, 17, 19, 23, 26, 4, 31,
|
|
9, 13, 21, 29, 16, 18, 25, 8,
|
|
20, 28, 24, 7, 27, 6, 5, 32};
|
|
|
|
static int sp_256_num_bits_29_9(sp_digit v)
|
|
{
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
return sp_256_tab32_9[(uint32_t)(v*0x07C4ACDD) >> 27];
|
|
}
|
|
|
|
static int sp_256_num_bits_9(const sp_digit* a)
|
|
{
|
|
int i;
|
|
int r = 0;
|
|
|
|
for (i = 8; i >= 0; i--) {
|
|
if (a[i] != 0) {
|
|
r = sp_256_num_bits_29_9(a[i]);
|
|
r += i * 29;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Non-constant time modular inversion.
|
|
*
|
|
* @param [out] r Resulting number.
|
|
* @param [in] a Number to invert.
|
|
* @param [in] m Modulus.
|
|
* @return MP_OKAY on success.
|
|
* @return MEMEORY_E when dynamic memory allocation fails.
|
|
*/
|
|
static int sp_256_mod_inv_9(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* u = NULL;
|
|
#else
|
|
sp_digit u[9 * 4];
|
|
#endif
|
|
sp_digit* v = NULL;
|
|
sp_digit* b = NULL;
|
|
sp_digit* d = NULL;
|
|
int ut;
|
|
int vt;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 4, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (u == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
v = u + 9;
|
|
b = u + 2 * 9;
|
|
d = u + 3 * 9;
|
|
|
|
XMEMCPY(u, m, sizeof(sp_digit) * 9);
|
|
XMEMCPY(v, a, sizeof(sp_digit) * 9);
|
|
|
|
ut = sp_256_num_bits_9(u);
|
|
vt = sp_256_num_bits_9(v);
|
|
|
|
XMEMSET(b, 0, sizeof(sp_digit) * 9);
|
|
if ((v[0] & 1) == 0) {
|
|
sp_256_rshift1_9(v, v);
|
|
XMEMCPY(d, m, sizeof(sp_digit) * 9);
|
|
d[0]++;
|
|
sp_256_rshift1_9(d, d);
|
|
vt--;
|
|
|
|
while ((v[0] & 1) == 0) {
|
|
sp_256_rshift1_9(v, v);
|
|
if (d[0] & 1)
|
|
sp_256_add_9(d, d, m);
|
|
sp_256_rshift1_9(d, d);
|
|
vt--;
|
|
}
|
|
}
|
|
else {
|
|
XMEMSET(d+1, 0, sizeof(sp_digit) * (9 - 1));
|
|
d[0] = 1;
|
|
}
|
|
|
|
while (ut > 1 && vt > 1) {
|
|
if (ut > vt || (ut == vt &&
|
|
sp_256_cmp_9(u, v) >= 0)) {
|
|
sp_256_sub_9(u, u, v);
|
|
sp_256_norm_9(u);
|
|
|
|
sp_256_sub_9(b, b, d);
|
|
sp_256_norm_9(b);
|
|
if (b[8] < 0)
|
|
sp_256_add_9(b, b, m);
|
|
sp_256_norm_9(b);
|
|
ut = sp_256_num_bits_9(u);
|
|
|
|
do {
|
|
sp_256_rshift1_9(u, u);
|
|
if (b[0] & 1)
|
|
sp_256_add_9(b, b, m);
|
|
sp_256_rshift1_9(b, b);
|
|
ut--;
|
|
}
|
|
while (ut > 0 && (u[0] & 1) == 0);
|
|
}
|
|
else {
|
|
sp_256_sub_9(v, v, u);
|
|
sp_256_norm_9(v);
|
|
|
|
sp_256_sub_9(d, d, b);
|
|
sp_256_norm_9(d);
|
|
if (d[8] < 0)
|
|
sp_256_add_9(d, d, m);
|
|
sp_256_norm_9(d);
|
|
vt = sp_256_num_bits_9(v);
|
|
|
|
do {
|
|
sp_256_rshift1_9(v, v);
|
|
if (d[0] & 1)
|
|
sp_256_add_9(d, d, m);
|
|
sp_256_rshift1_9(d, d);
|
|
vt--;
|
|
}
|
|
while (vt > 0 && (v[0] & 1) == 0);
|
|
}
|
|
}
|
|
|
|
if (ut == 1)
|
|
XMEMCPY(r, b, sizeof(sp_digit) * 9);
|
|
else
|
|
XMEMCPY(r, d, sizeof(sp_digit) * 9);
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (u != NULL)
|
|
XFREE(u, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
|
|
*
|
|
* p1 First point to add and holds result.
|
|
* p2 Second point to add.
|
|
* tmp Temporary storage for intermediate numbers.
|
|
*/
|
|
static void sp_256_add_points_9(sp_point_256* p1, const sp_point_256* p2,
|
|
sp_digit* tmp)
|
|
{
|
|
|
|
sp_256_proj_point_add_9(p1, p1, p2, tmp);
|
|
if (sp_256_iszero_9(p1->z)) {
|
|
if (sp_256_iszero_9(p1->x) && sp_256_iszero_9(p1->y)) {
|
|
sp_256_proj_point_dbl_9(p1, p2, tmp);
|
|
}
|
|
else {
|
|
/* Y ordinate is not used from here - don't set. */
|
|
p1->x[0] = 0;
|
|
p1->x[1] = 0;
|
|
p1->x[2] = 0;
|
|
p1->x[3] = 0;
|
|
p1->x[4] = 0;
|
|
p1->x[5] = 0;
|
|
p1->x[6] = 0;
|
|
p1->x[7] = 0;
|
|
p1->x[8] = 0;
|
|
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Calculate the verification point: [e/s]G + [r/s]Q
|
|
*
|
|
* p1 Calculated point.
|
|
* p2 Public point and temporary.
|
|
* s Second part of signature as a number.
|
|
* u1 Temporary number.
|
|
* u2 Temproray number.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_256_calc_vfy_point_9(sp_point_256* p1, sp_point_256* p2,
|
|
sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
|
|
{
|
|
int err;
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
err = sp_256_mod_inv_9(s, s, p256_order);
|
|
if (err == MP_OKAY)
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
{
|
|
sp_256_mul_9(s, s, p256_norm_order);
|
|
err = sp_256_mod_9(s, s, p256_order);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_256_norm_9(s);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
{
|
|
sp_256_mont_inv_order_9(s, s, tmp);
|
|
sp_256_mont_mul_order_9(u1, u1, s);
|
|
sp_256_mont_mul_order_9(u2, u2, s);
|
|
}
|
|
#else
|
|
{
|
|
sp_256_mont_mul_order_9(u1, u1, s);
|
|
sp_256_mont_mul_order_9(u2, u2, s);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
{
|
|
err = sp_256_ecc_mulmod_base_9(p1, u1, 0, 0, heap);
|
|
}
|
|
}
|
|
if ((err == MP_OKAY) && sp_256_iszero_9(p1->z)) {
|
|
p1->infinity = 1;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_ecc_mulmod_9(p2, p2, u2, 0, 0, heap);
|
|
}
|
|
if ((err == MP_OKAY) && sp_256_iszero_9(p2->z)) {
|
|
p2->infinity = 1;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_256_add_points_9(p1, p2, tmp);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef HAVE_ECC_VERIFY
|
|
/* Verify the signature values with the hash and public key.
|
|
* e = Truncate(hash, 256)
|
|
* u1 = e/s mod order
|
|
* u2 = r/s mod order
|
|
* r == (u1.G + u2.Q)->x mod order
|
|
* Optimization: Leave point in projective form.
|
|
* (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
|
|
* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
|
|
* The hash is truncated to the first 256 bits.
|
|
*
|
|
* hash Hash to sign.
|
|
* hashLen Length of the hash data.
|
|
* rng Random number generator.
|
|
* priv Private part of key - scalar.
|
|
* rm First part of result as an mp_int.
|
|
* sm Sirst part of result as an mp_int.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_verify_256(const byte* hash, word32 hashLen, const mp_int* pX,
|
|
const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
|
|
int* res, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* u1 = NULL;
|
|
sp_point_256* p1 = NULL;
|
|
#else
|
|
sp_digit u1[18 * 9];
|
|
sp_point_256 p1[2];
|
|
#endif
|
|
sp_digit* u2 = NULL;
|
|
sp_digit* s = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_point_256* p2 = NULL;
|
|
sp_digit carry;
|
|
sp_int32 c = 0;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p1 = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p1 == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (u1 == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
u2 = u1 + 2 * 9;
|
|
s = u1 + 4 * 9;
|
|
tmp = u1 + 6 * 9;
|
|
p2 = p1 + 1;
|
|
|
|
if (hashLen > 32U) {
|
|
hashLen = 32U;
|
|
}
|
|
|
|
sp_256_from_bin(u1, 9, hash, (int)hashLen);
|
|
sp_256_from_mp(u2, 9, rm);
|
|
sp_256_from_mp(s, 9, sm);
|
|
sp_256_from_mp(p2->x, 9, pX);
|
|
sp_256_from_mp(p2->y, 9, pY);
|
|
sp_256_from_mp(p2->z, 9, pZ);
|
|
|
|
err = sp_256_calc_vfy_point_9(p1, p2, s, u1, u2, tmp, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
|
|
/* Reload r and convert to Montgomery form. */
|
|
sp_256_from_mp(u2, 9, rm);
|
|
err = sp_256_mod_mul_norm_9(u2, u2, p256_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* u1 = r.z'.z' mod prime */
|
|
sp_256_mont_sqr_9(p1->z, p1->z, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod);
|
|
*res = (int)(sp_256_cmp_9(p1->x, u1) == 0);
|
|
if (*res == 0) {
|
|
/* Reload r and add order. */
|
|
sp_256_from_mp(u2, 9, rm);
|
|
carry = sp_256_add_9(u2, u2, p256_order);
|
|
/* Carry means result is greater than mod and is not valid. */
|
|
if (carry == 0) {
|
|
sp_256_norm_9(u2);
|
|
|
|
/* Compare with mod and if greater or equal then not valid. */
|
|
c = sp_256_cmp_9(u2, p256_mod);
|
|
}
|
|
}
|
|
if ((*res == 0) && (c < 0)) {
|
|
/* Convert to Montogomery form */
|
|
err = sp_256_mod_mul_norm_9(u2, u2, p256_mod);
|
|
if (err == MP_OKAY) {
|
|
/* u1 = (r + 1*order).z'.z' mod prime */
|
|
{
|
|
sp_256_mont_mul_9(u1, u2, p1->z, p256_mod, p256_mp_mod);
|
|
}
|
|
*res = (sp_256_cmp_9(p1->x, u1) == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (u1 != NULL)
|
|
XFREE(u1, heap, DYNAMIC_TYPE_ECC);
|
|
if (p1 != NULL)
|
|
XFREE(p1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_verify_256_ctx {
|
|
int state;
|
|
union {
|
|
sp_256_ecc_mulmod_9_ctx mulmod_ctx;
|
|
sp_256_mont_inv_order_9_ctx mont_inv_order_ctx;
|
|
sp_256_proj_point_dbl_9_ctx dbl_ctx;
|
|
sp_256_proj_point_add_9_ctx add_ctx;
|
|
};
|
|
sp_digit u1[2*9];
|
|
sp_digit u2[2*9];
|
|
sp_digit s[2*9];
|
|
sp_digit tmp[2*9 * 6];
|
|
sp_point_256 p1;
|
|
sp_point_256 p2;
|
|
} sp_ecc_verify_256_ctx;
|
|
|
|
int sp_ecc_verify_256_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
|
|
word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
|
|
const mp_int* rm, const mp_int* sm, int* res, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_verify_256_ctx* ctx = (sp_ecc_verify_256_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_verify_256_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
if (hashLen > 32U) {
|
|
hashLen = 32U;
|
|
}
|
|
|
|
sp_256_from_bin(ctx->u1, 9, hash, (int)hashLen);
|
|
sp_256_from_mp(ctx->u2, 9, rm);
|
|
sp_256_from_mp(ctx->s, 9, sm);
|
|
sp_256_from_mp(ctx->p2.x, 9, pX);
|
|
sp_256_from_mp(ctx->p2.y, 9, pY);
|
|
sp_256_from_mp(ctx->p2.z, 9, pZ);
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* NORMS0 */
|
|
sp_256_mul_9(ctx->s, ctx->s, p256_norm_order);
|
|
err = sp_256_mod_9(ctx->s, ctx->s, p256_order);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* NORMS1 */
|
|
sp_256_norm_9(ctx->s);
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* NORMS2 */
|
|
err = sp_256_mont_inv_order_9_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
ctx->state = 4;
|
|
}
|
|
break;
|
|
case 4: /* NORMS3 */
|
|
sp_256_mont_mul_order_9(ctx->u1, ctx->u1, ctx->s);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* NORMS4 */
|
|
sp_256_mont_mul_order_9(ctx->u2, ctx->u2, ctx->s);
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 6;
|
|
break;
|
|
case 6: /* MULBASE */
|
|
err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p256_base, ctx->u1, 0, 0, heap);
|
|
if (err == MP_OKAY) {
|
|
if (sp_256_iszero_9(ctx->p1.z)) {
|
|
ctx->p1.infinity = 1;
|
|
}
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 7;
|
|
}
|
|
break;
|
|
case 7: /* MULMOD */
|
|
err = sp_256_ecc_mulmod_9_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
|
|
if (err == MP_OKAY) {
|
|
if (sp_256_iszero_9(ctx->p2.z)) {
|
|
ctx->p2.infinity = 1;
|
|
}
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 8;
|
|
}
|
|
break;
|
|
case 8: /* ADD */
|
|
err = sp_256_proj_point_add_9_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 9;
|
|
break;
|
|
case 9: /* MONT */
|
|
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
|
|
/* Reload r and convert to Montgomery form. */
|
|
sp_256_from_mp(ctx->u2, 9, rm);
|
|
err = sp_256_mod_mul_norm_9(ctx->u2, ctx->u2, p256_mod);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 10;
|
|
break;
|
|
case 10: /* SQR */
|
|
/* u1 = r.z'.z' mod prime */
|
|
sp_256_mont_sqr_9(ctx->p1.z, ctx->p1.z, p256_mod, p256_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11: /* MUL */
|
|
sp_256_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p256_mod, p256_mp_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12: /* RES */
|
|
{
|
|
sp_int32 c = 0;
|
|
err = MP_OKAY; /* math okay, now check result */
|
|
*res = (int)(sp_256_cmp_9(ctx->p1.x, ctx->u1) == 0);
|
|
if (*res == 0) {
|
|
sp_digit carry;
|
|
|
|
/* Reload r and add order. */
|
|
sp_256_from_mp(ctx->u2, 9, rm);
|
|
carry = sp_256_add_9(ctx->u2, ctx->u2, p256_order);
|
|
/* Carry means result is greater than mod and is not valid. */
|
|
if (carry == 0) {
|
|
sp_256_norm_9(ctx->u2);
|
|
|
|
/* Compare with mod and if greater or equal then not valid. */
|
|
c = sp_256_cmp_9(ctx->u2, p256_mod);
|
|
}
|
|
}
|
|
if ((*res == 0) && (c < 0)) {
|
|
/* Convert to Montogomery form */
|
|
err = sp_256_mod_mul_norm_9(ctx->u2, ctx->u2, p256_mod);
|
|
if (err == MP_OKAY) {
|
|
/* u1 = (r + 1*order).z'.z' mod prime */
|
|
sp_256_mont_mul_9(ctx->u1, ctx->u2, ctx->p1.z, p256_mod,
|
|
p256_mp_mod);
|
|
*res = (int)(sp_256_cmp_9(ctx->p1.x, ctx->u1) == 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
} /* switch */
|
|
|
|
if (err == MP_OKAY && ctx->state != 12) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_VERIFY */
|
|
|
|
#ifdef HAVE_ECC_CHECK_KEY
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* point EC point.
|
|
* heap Heap to use if dynamically allocating.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_256_ecc_is_point_9(const sp_point_256* point,
|
|
void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[9 * 4];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9 * 4, heap, DYNAMIC_TYPE_ECC);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
(void)heap;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 2 * 9;
|
|
|
|
sp_256_sqr_9(t1, point->y);
|
|
(void)sp_256_mod_9(t1, t1, p256_mod);
|
|
sp_256_sqr_9(t2, point->x);
|
|
(void)sp_256_mod_9(t2, t2, p256_mod);
|
|
sp_256_mul_9(t2, t2, point->x);
|
|
(void)sp_256_mod_9(t2, t2, p256_mod);
|
|
(void)sp_256_sub_9(t2, p256_mod, t2);
|
|
sp_256_mont_add_9(t1, t1, t2, p256_mod);
|
|
|
|
sp_256_mont_add_9(t1, t1, point->x, p256_mod);
|
|
sp_256_mont_add_9(t1, t1, point->x, p256_mod);
|
|
sp_256_mont_add_9(t1, t1, point->x, p256_mod);
|
|
|
|
if (sp_256_cmp_9(t1, p256_b) != 0) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_is_point_256(const mp_int* pX, const mp_int* pY)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_256* pub = NULL;
|
|
#else
|
|
sp_point_256 pub[1];
|
|
#endif
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_256_from_mp(pub->x, 9, pX);
|
|
sp_256_from_mp(pub->y, 9, pY);
|
|
sp_256_from_bin(pub->z, 9, one, (int)sizeof(one));
|
|
|
|
err = sp_256_ecc_is_point_9(pub, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the private scalar generates the EC point (px, py), the point is
|
|
* on the curve and the point has the correct order.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* privm Private scalar that generates EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve, ECC_INF_E if the point does not have the correct order,
|
|
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
|
|
* MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_check_key_256(const mp_int* pX, const mp_int* pY,
|
|
const mp_int* privm, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* priv = NULL;
|
|
sp_point_256* pub = NULL;
|
|
#else
|
|
sp_digit priv[9];
|
|
sp_point_256 pub[2];
|
|
#endif
|
|
sp_point_256* p = NULL;
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
|
|
/* Quick check the lengs of public key ordinates and private key are in
|
|
* range. Proper check later.
|
|
*/
|
|
if (((mp_count_bits(pX) > 256) ||
|
|
(mp_count_bits(pY) > 256) ||
|
|
((privm != NULL) && (mp_count_bits(privm) > 256)))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
pub = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY && privm) {
|
|
priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 9, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (priv == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = pub + 1;
|
|
|
|
sp_256_from_mp(pub->x, 9, pX);
|
|
sp_256_from_mp(pub->y, 9, pY);
|
|
sp_256_from_bin(pub->z, 9, one, (int)sizeof(one));
|
|
if (privm)
|
|
sp_256_from_mp(priv, 9, privm);
|
|
|
|
/* Check point at infinitiy. */
|
|
if ((sp_256_iszero_9(pub->x) != 0) &&
|
|
(sp_256_iszero_9(pub->y) != 0)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
|
|
/* Check range of X and Y */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_256_cmp_9(pub->x, p256_mod) >= 0) ||
|
|
(sp_256_cmp_9(pub->y, p256_mod) >= 0))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Check point is on curve */
|
|
err = sp_256_ecc_is_point_9(pub, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Point * order = infinity */
|
|
err = sp_256_ecc_mulmod_9(p, pub, p256_order, 1, 1, heap);
|
|
}
|
|
/* Check result is infinity */
|
|
if ((err == MP_OKAY) && ((sp_256_iszero_9(p->x) == 0) ||
|
|
(sp_256_iszero_9(p->y) == 0))) {
|
|
err = ECC_INF_E;
|
|
}
|
|
|
|
if (privm) {
|
|
if (err == MP_OKAY) {
|
|
/* Base * private = point */
|
|
err = sp_256_ecc_mulmod_base_9(p, priv, 1, 1, heap);
|
|
}
|
|
/* Check result is public key */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_256_cmp_9(p->x, pub->x) != 0) ||
|
|
(sp_256_cmp_9(p->y, pub->y) != 0))) {
|
|
err = ECC_PRIV_KEY_E;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, heap, DYNAMIC_TYPE_ECC);
|
|
if (priv != NULL)
|
|
XFREE(priv, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
|
|
/* Add two projective EC points together.
|
|
* (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
|
|
*
|
|
* pX First EC point's X ordinate.
|
|
* pY First EC point's Y ordinate.
|
|
* pZ First EC point's Z ordinate.
|
|
* qX Second EC point's X ordinate.
|
|
* qY Second EC point's Y ordinate.
|
|
* qZ Second EC point's Z ordinate.
|
|
* rX Resultant EC point's X ordinate.
|
|
* rY Resultant EC point's Y ordinate.
|
|
* rZ Resultant EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
|
|
mp_int* qX, mp_int* qY, mp_int* qZ,
|
|
mp_int* rX, mp_int* rY, mp_int* rZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_256* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 9 * 6];
|
|
sp_point_256 p[2];
|
|
#endif
|
|
sp_point_256* q = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_256*)XMALLOC(sizeof(sp_point_256) * 2, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 6, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
q = p + 1;
|
|
|
|
sp_256_from_mp(p->x, 9, pX);
|
|
sp_256_from_mp(p->y, 9, pY);
|
|
sp_256_from_mp(p->z, 9, pZ);
|
|
sp_256_from_mp(q->x, 9, qX);
|
|
sp_256_from_mp(q->y, 9, qY);
|
|
sp_256_from_mp(q->z, 9, qZ);
|
|
p->infinity = sp_256_iszero_9(p->x) &
|
|
sp_256_iszero_9(p->y);
|
|
q->infinity = sp_256_iszero_9(q->x) &
|
|
sp_256_iszero_9(q->y);
|
|
|
|
sp_256_proj_point_add_9(p, p, q, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->x, rX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->y, rY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->z, rZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Double a projective EC point.
|
|
* (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
|
|
*
|
|
* pX EC point's X ordinate.
|
|
* pY EC point's Y ordinate.
|
|
* pZ EC point's Z ordinate.
|
|
* rX Resultant EC point's X ordinate.
|
|
* rY Resultant EC point's Y ordinate.
|
|
* rZ Resultant EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ,
|
|
mp_int* rX, mp_int* rY, mp_int* rZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_256* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 9 * 2];
|
|
sp_point_256 p[1];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 2, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_256_from_mp(p->x, 9, pX);
|
|
sp_256_from_mp(p->y, 9, pY);
|
|
sp_256_from_mp(p->z, 9, pZ);
|
|
p->infinity = sp_256_iszero_9(p->x) &
|
|
sp_256_iszero_9(p->y);
|
|
|
|
sp_256_proj_point_dbl_9(p, p, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->x, rX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->y, rY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->z, rZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Map a projective EC point to affine in place.
|
|
* pZ will be one.
|
|
*
|
|
* pX EC point's X ordinate.
|
|
* pY EC point's Y ordinate.
|
|
* pZ EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_256* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 9 * 4];
|
|
sp_point_256 p[1];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_256*)XMALLOC(sizeof(sp_point_256), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 9 * 4, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
sp_256_from_mp(p->x, 9, pX);
|
|
sp_256_from_mp(p->y, 9, pY);
|
|
sp_256_from_mp(p->z, 9, pZ);
|
|
p->infinity = sp_256_iszero_9(p->x) &
|
|
sp_256_iszero_9(p->y);
|
|
|
|
sp_256_map_9(p, p, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->x, pX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->y, pY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_256_to_mp(p->z, pZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
|
|
#ifdef HAVE_COMP_KEY
|
|
/* Find the square root of a number mod the prime of the curve.
|
|
*
|
|
* y The number to operate on and the result.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_256_mont_sqrt_9(sp_digit* y)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 9];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 9, NULL, DYNAMIC_TYPE_ECC);
|
|
if (t1 == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 2 * 9;
|
|
|
|
{
|
|
/* t2 = y ^ 0x2 */
|
|
sp_256_mont_sqr_9(t2, y, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0x3 */
|
|
sp_256_mont_mul_9(t1, t2, y, p256_mod, p256_mp_mod);
|
|
/* t2 = y ^ 0xc */
|
|
sp_256_mont_sqr_n_9(t2, t1, 2, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xf */
|
|
sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
|
|
/* t2 = y ^ 0xf0 */
|
|
sp_256_mont_sqr_n_9(t2, t1, 4, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xff */
|
|
sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
|
|
/* t2 = y ^ 0xff00 */
|
|
sp_256_mont_sqr_n_9(t2, t1, 8, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xffff */
|
|
sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
|
|
/* t2 = y ^ 0xffff0000 */
|
|
sp_256_mont_sqr_n_9(t2, t1, 16, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xffffffff */
|
|
sp_256_mont_mul_9(t1, t1, t2, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xffffffff00000000 */
|
|
sp_256_mont_sqr_n_9(t1, t1, 32, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xffffffff00000001 */
|
|
sp_256_mont_mul_9(t1, t1, y, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xffffffff00000001000000000000000000000000 */
|
|
sp_256_mont_sqr_n_9(t1, t1, 96, p256_mod, p256_mp_mod);
|
|
/* t1 = y ^ 0xffffffff00000001000000000000000000000001 */
|
|
sp_256_mont_mul_9(t1, t1, y, p256_mod, p256_mp_mod);
|
|
sp_256_mont_sqr_n_9(y, t1, 94, p256_mod, p256_mp_mod);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/* Uncompress the point given the X ordinate.
|
|
*
|
|
* xm X ordinate.
|
|
* odd Whether the Y ordinate is odd.
|
|
* ym Calculated Y ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* x = NULL;
|
|
#else
|
|
sp_digit x[4 * 9];
|
|
#endif
|
|
sp_digit* y = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 9, NULL, DYNAMIC_TYPE_ECC);
|
|
if (x == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
y = x + 2 * 9;
|
|
|
|
sp_256_from_mp(x, 9, xm);
|
|
err = sp_256_mod_mul_norm_9(x, x, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* y = x^3 */
|
|
{
|
|
sp_256_mont_sqr_9(y, x, p256_mod, p256_mp_mod);
|
|
sp_256_mont_mul_9(y, y, x, p256_mod, p256_mp_mod);
|
|
}
|
|
/* y = x^3 - 3x */
|
|
sp_256_mont_sub_9(y, y, x, p256_mod);
|
|
sp_256_mont_sub_9(y, y, x, p256_mod);
|
|
sp_256_mont_sub_9(y, y, x, p256_mod);
|
|
/* y = x^3 - 3x + b */
|
|
err = sp_256_mod_mul_norm_9(x, p256_b, p256_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_256_mont_add_9(y, y, x, p256_mod);
|
|
/* y = sqrt(x^3 - 3x + b) */
|
|
err = sp_256_mont_sqrt_9(y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(y + 9, 0, 9U * sizeof(sp_digit));
|
|
sp_256_mont_reduce_9(y, p256_mod, p256_mp_mod);
|
|
if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
|
|
sp_256_mont_sub_9(y, p256_mod, y, p256_mod);
|
|
}
|
|
|
|
err = sp_256_to_mp(y, ym);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (x != NULL)
|
|
XFREE(x, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#endif /* !WOLFSSL_SP_NO_256 */
|
|
#ifdef WOLFSSL_SP_384
|
|
|
|
/* Point structure to use. */
|
|
typedef struct sp_point_384 {
|
|
/* X ordinate of point. */
|
|
sp_digit x[2 * 15];
|
|
/* Y ordinate of point. */
|
|
sp_digit y[2 * 15];
|
|
/* Z ordinate of point. */
|
|
sp_digit z[2 * 15];
|
|
/* Indicates point is at infinity. */
|
|
int infinity;
|
|
} sp_point_384;
|
|
|
|
/* The modulus (prime) of the curve P384. */
|
|
static const sp_digit p384_mod[15] = {
|
|
0x3ffffff,0x000003f,0x0000000,0x3fc0000,0x2ffffff,0x3ffffff,0x3ffffff,
|
|
0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,
|
|
0x00fffff
|
|
};
|
|
/* The Montgomery normalizer for modulus of the curve P384. */
|
|
static const sp_digit p384_norm_mod[15] = {
|
|
0x0000001,0x3ffffc0,0x3ffffff,0x003ffff,0x1000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000
|
|
};
|
|
/* The Montgomery multiplier for modulus of the curve P384. */
|
|
static sp_digit p384_mp_mod = 0x000001;
|
|
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
|
|
defined(HAVE_ECC_VERIFY)
|
|
/* The order of the curve P384. */
|
|
static const sp_digit p384_order[15] = {
|
|
0x0c52973,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f,
|
|
0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,
|
|
0x00fffff
|
|
};
|
|
#endif
|
|
/* The order of the curve P384 minus 2. */
|
|
static const sp_digit p384_order2[15] = {
|
|
0x0c52971,0x3065ab3,0x277aece,0x2c922c2,0x3581a0d,0x10dcb77,0x234d81f,
|
|
0x3ffff1d,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,0x3ffffff,
|
|
0x00fffff
|
|
};
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* The Montgomery normalizer for order of the curve P384. */
|
|
static const sp_digit p384_norm_order[15] = {
|
|
0x33ad68d,0x0f9a54c,0x1885131,0x136dd3d,0x0a7e5f2,0x2f23488,0x1cb27e0,
|
|
0x00000e2,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000
|
|
};
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* The Montgomery multiplier for order of the curve P384. */
|
|
static sp_digit p384_mp_order = 0x8fdc45;
|
|
#endif
|
|
/* The base point of curve P384. */
|
|
static const sp_point_384 p384_base = {
|
|
/* X ordinate */
|
|
{
|
|
0x2760ab7,0x1178e1c,0x296c3a5,0x176fd54,0x05502f2,0x0950a8e,0x3741e08,
|
|
0x26e6167,0x3628ba7,0x11b874e,0x3320ad7,0x2c71c7b,0x305378e,0x288afa2,
|
|
0x00aa87c,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
|
|
},
|
|
/* Y ordinate */
|
|
{
|
|
0x0ea0e5f,0x0c75f24,0x019d7a4,0x33875fa,0x00a60b1,0x17c2e30,0x1a3113b,
|
|
0x051f3a7,0x1bd289a,0x27e3d07,0x1292dc2,0x27a62fe,0x22c6f5d,0x392a589,
|
|
0x003617d,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
|
|
},
|
|
/* Z ordinate */
|
|
{
|
|
0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0
|
|
},
|
|
/* infinity */
|
|
0
|
|
};
|
|
#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
|
|
static const sp_digit p384_b[15] = {
|
|
0x3ec2aef,0x1723b74,0x119d2a8,0x23628bb,0x2c65639,0x004e1d6,0x14088f5,
|
|
0x104480c,0x06efe81,0x2460767,0x23f82d1,0x23815af,0x2e7e498,0x3e9f88f,
|
|
0x00b3312
|
|
};
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[14]) * b[14];
|
|
r[29] = (sp_digit)(c >> 26);
|
|
c &= 0x3ffffff;
|
|
for (k = 27; k >= 0; k--) {
|
|
if (k >= 15) {
|
|
i = k - 14;
|
|
imax = 14;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 26;
|
|
r[k + 2] += (sp_digit)(c >> 26);
|
|
r[k + 1] = (sp_digit)(c & 0x3ffffff);
|
|
c = lo & 0x3ffffff;
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
#else
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_384_mul_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_int64 t0;
|
|
sp_int64 t1;
|
|
sp_digit t[15];
|
|
|
|
t0 = ((sp_int64)a[ 0]) * b[ 0];
|
|
t1 = ((sp_int64)a[ 0]) * b[ 1]
|
|
+ ((sp_int64)a[ 1]) * b[ 0];
|
|
t[ 0] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 2]
|
|
+ ((sp_int64)a[ 1]) * b[ 1]
|
|
+ ((sp_int64)a[ 2]) * b[ 0];
|
|
t[ 1] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 3]
|
|
+ ((sp_int64)a[ 1]) * b[ 2]
|
|
+ ((sp_int64)a[ 2]) * b[ 1]
|
|
+ ((sp_int64)a[ 3]) * b[ 0];
|
|
t[ 2] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 4]
|
|
+ ((sp_int64)a[ 1]) * b[ 3]
|
|
+ ((sp_int64)a[ 2]) * b[ 2]
|
|
+ ((sp_int64)a[ 3]) * b[ 1]
|
|
+ ((sp_int64)a[ 4]) * b[ 0];
|
|
t[ 3] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 5]
|
|
+ ((sp_int64)a[ 1]) * b[ 4]
|
|
+ ((sp_int64)a[ 2]) * b[ 3]
|
|
+ ((sp_int64)a[ 3]) * b[ 2]
|
|
+ ((sp_int64)a[ 4]) * b[ 1]
|
|
+ ((sp_int64)a[ 5]) * b[ 0];
|
|
t[ 4] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 6]
|
|
+ ((sp_int64)a[ 1]) * b[ 5]
|
|
+ ((sp_int64)a[ 2]) * b[ 4]
|
|
+ ((sp_int64)a[ 3]) * b[ 3]
|
|
+ ((sp_int64)a[ 4]) * b[ 2]
|
|
+ ((sp_int64)a[ 5]) * b[ 1]
|
|
+ ((sp_int64)a[ 6]) * b[ 0];
|
|
t[ 5] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 7]
|
|
+ ((sp_int64)a[ 1]) * b[ 6]
|
|
+ ((sp_int64)a[ 2]) * b[ 5]
|
|
+ ((sp_int64)a[ 3]) * b[ 4]
|
|
+ ((sp_int64)a[ 4]) * b[ 3]
|
|
+ ((sp_int64)a[ 5]) * b[ 2]
|
|
+ ((sp_int64)a[ 6]) * b[ 1]
|
|
+ ((sp_int64)a[ 7]) * b[ 0];
|
|
t[ 6] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[ 8]
|
|
+ ((sp_int64)a[ 1]) * b[ 7]
|
|
+ ((sp_int64)a[ 2]) * b[ 6]
|
|
+ ((sp_int64)a[ 3]) * b[ 5]
|
|
+ ((sp_int64)a[ 4]) * b[ 4]
|
|
+ ((sp_int64)a[ 5]) * b[ 3]
|
|
+ ((sp_int64)a[ 6]) * b[ 2]
|
|
+ ((sp_int64)a[ 7]) * b[ 1]
|
|
+ ((sp_int64)a[ 8]) * b[ 0];
|
|
t[ 7] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 0]) * b[ 9]
|
|
+ ((sp_int64)a[ 1]) * b[ 8]
|
|
+ ((sp_int64)a[ 2]) * b[ 7]
|
|
+ ((sp_int64)a[ 3]) * b[ 6]
|
|
+ ((sp_int64)a[ 4]) * b[ 5]
|
|
+ ((sp_int64)a[ 5]) * b[ 4]
|
|
+ ((sp_int64)a[ 6]) * b[ 3]
|
|
+ ((sp_int64)a[ 7]) * b[ 2]
|
|
+ ((sp_int64)a[ 8]) * b[ 1]
|
|
+ ((sp_int64)a[ 9]) * b[ 0];
|
|
t[ 8] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[10]
|
|
+ ((sp_int64)a[ 1]) * b[ 9]
|
|
+ ((sp_int64)a[ 2]) * b[ 8]
|
|
+ ((sp_int64)a[ 3]) * b[ 7]
|
|
+ ((sp_int64)a[ 4]) * b[ 6]
|
|
+ ((sp_int64)a[ 5]) * b[ 5]
|
|
+ ((sp_int64)a[ 6]) * b[ 4]
|
|
+ ((sp_int64)a[ 7]) * b[ 3]
|
|
+ ((sp_int64)a[ 8]) * b[ 2]
|
|
+ ((sp_int64)a[ 9]) * b[ 1]
|
|
+ ((sp_int64)a[10]) * b[ 0];
|
|
t[ 9] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 0]) * b[11]
|
|
+ ((sp_int64)a[ 1]) * b[10]
|
|
+ ((sp_int64)a[ 2]) * b[ 9]
|
|
+ ((sp_int64)a[ 3]) * b[ 8]
|
|
+ ((sp_int64)a[ 4]) * b[ 7]
|
|
+ ((sp_int64)a[ 5]) * b[ 6]
|
|
+ ((sp_int64)a[ 6]) * b[ 5]
|
|
+ ((sp_int64)a[ 7]) * b[ 4]
|
|
+ ((sp_int64)a[ 8]) * b[ 3]
|
|
+ ((sp_int64)a[ 9]) * b[ 2]
|
|
+ ((sp_int64)a[10]) * b[ 1]
|
|
+ ((sp_int64)a[11]) * b[ 0];
|
|
t[10] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[12]
|
|
+ ((sp_int64)a[ 1]) * b[11]
|
|
+ ((sp_int64)a[ 2]) * b[10]
|
|
+ ((sp_int64)a[ 3]) * b[ 9]
|
|
+ ((sp_int64)a[ 4]) * b[ 8]
|
|
+ ((sp_int64)a[ 5]) * b[ 7]
|
|
+ ((sp_int64)a[ 6]) * b[ 6]
|
|
+ ((sp_int64)a[ 7]) * b[ 5]
|
|
+ ((sp_int64)a[ 8]) * b[ 4]
|
|
+ ((sp_int64)a[ 9]) * b[ 3]
|
|
+ ((sp_int64)a[10]) * b[ 2]
|
|
+ ((sp_int64)a[11]) * b[ 1]
|
|
+ ((sp_int64)a[12]) * b[ 0];
|
|
t[11] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 0]) * b[13]
|
|
+ ((sp_int64)a[ 1]) * b[12]
|
|
+ ((sp_int64)a[ 2]) * b[11]
|
|
+ ((sp_int64)a[ 3]) * b[10]
|
|
+ ((sp_int64)a[ 4]) * b[ 9]
|
|
+ ((sp_int64)a[ 5]) * b[ 8]
|
|
+ ((sp_int64)a[ 6]) * b[ 7]
|
|
+ ((sp_int64)a[ 7]) * b[ 6]
|
|
+ ((sp_int64)a[ 8]) * b[ 5]
|
|
+ ((sp_int64)a[ 9]) * b[ 4]
|
|
+ ((sp_int64)a[10]) * b[ 3]
|
|
+ ((sp_int64)a[11]) * b[ 2]
|
|
+ ((sp_int64)a[12]) * b[ 1]
|
|
+ ((sp_int64)a[13]) * b[ 0];
|
|
t[12] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 0]) * b[14]
|
|
+ ((sp_int64)a[ 1]) * b[13]
|
|
+ ((sp_int64)a[ 2]) * b[12]
|
|
+ ((sp_int64)a[ 3]) * b[11]
|
|
+ ((sp_int64)a[ 4]) * b[10]
|
|
+ ((sp_int64)a[ 5]) * b[ 9]
|
|
+ ((sp_int64)a[ 6]) * b[ 8]
|
|
+ ((sp_int64)a[ 7]) * b[ 7]
|
|
+ ((sp_int64)a[ 8]) * b[ 6]
|
|
+ ((sp_int64)a[ 9]) * b[ 5]
|
|
+ ((sp_int64)a[10]) * b[ 4]
|
|
+ ((sp_int64)a[11]) * b[ 3]
|
|
+ ((sp_int64)a[12]) * b[ 2]
|
|
+ ((sp_int64)a[13]) * b[ 1]
|
|
+ ((sp_int64)a[14]) * b[ 0];
|
|
t[13] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 1]) * b[14]
|
|
+ ((sp_int64)a[ 2]) * b[13]
|
|
+ ((sp_int64)a[ 3]) * b[12]
|
|
+ ((sp_int64)a[ 4]) * b[11]
|
|
+ ((sp_int64)a[ 5]) * b[10]
|
|
+ ((sp_int64)a[ 6]) * b[ 9]
|
|
+ ((sp_int64)a[ 7]) * b[ 8]
|
|
+ ((sp_int64)a[ 8]) * b[ 7]
|
|
+ ((sp_int64)a[ 9]) * b[ 6]
|
|
+ ((sp_int64)a[10]) * b[ 5]
|
|
+ ((sp_int64)a[11]) * b[ 4]
|
|
+ ((sp_int64)a[12]) * b[ 3]
|
|
+ ((sp_int64)a[13]) * b[ 2]
|
|
+ ((sp_int64)a[14]) * b[ 1];
|
|
t[14] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 2]) * b[14]
|
|
+ ((sp_int64)a[ 3]) * b[13]
|
|
+ ((sp_int64)a[ 4]) * b[12]
|
|
+ ((sp_int64)a[ 5]) * b[11]
|
|
+ ((sp_int64)a[ 6]) * b[10]
|
|
+ ((sp_int64)a[ 7]) * b[ 9]
|
|
+ ((sp_int64)a[ 8]) * b[ 8]
|
|
+ ((sp_int64)a[ 9]) * b[ 7]
|
|
+ ((sp_int64)a[10]) * b[ 6]
|
|
+ ((sp_int64)a[11]) * b[ 5]
|
|
+ ((sp_int64)a[12]) * b[ 4]
|
|
+ ((sp_int64)a[13]) * b[ 3]
|
|
+ ((sp_int64)a[14]) * b[ 2];
|
|
r[15] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 3]) * b[14]
|
|
+ ((sp_int64)a[ 4]) * b[13]
|
|
+ ((sp_int64)a[ 5]) * b[12]
|
|
+ ((sp_int64)a[ 6]) * b[11]
|
|
+ ((sp_int64)a[ 7]) * b[10]
|
|
+ ((sp_int64)a[ 8]) * b[ 9]
|
|
+ ((sp_int64)a[ 9]) * b[ 8]
|
|
+ ((sp_int64)a[10]) * b[ 7]
|
|
+ ((sp_int64)a[11]) * b[ 6]
|
|
+ ((sp_int64)a[12]) * b[ 5]
|
|
+ ((sp_int64)a[13]) * b[ 4]
|
|
+ ((sp_int64)a[14]) * b[ 3];
|
|
r[16] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 4]) * b[14]
|
|
+ ((sp_int64)a[ 5]) * b[13]
|
|
+ ((sp_int64)a[ 6]) * b[12]
|
|
+ ((sp_int64)a[ 7]) * b[11]
|
|
+ ((sp_int64)a[ 8]) * b[10]
|
|
+ ((sp_int64)a[ 9]) * b[ 9]
|
|
+ ((sp_int64)a[10]) * b[ 8]
|
|
+ ((sp_int64)a[11]) * b[ 7]
|
|
+ ((sp_int64)a[12]) * b[ 6]
|
|
+ ((sp_int64)a[13]) * b[ 5]
|
|
+ ((sp_int64)a[14]) * b[ 4];
|
|
r[17] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 5]) * b[14]
|
|
+ ((sp_int64)a[ 6]) * b[13]
|
|
+ ((sp_int64)a[ 7]) * b[12]
|
|
+ ((sp_int64)a[ 8]) * b[11]
|
|
+ ((sp_int64)a[ 9]) * b[10]
|
|
+ ((sp_int64)a[10]) * b[ 9]
|
|
+ ((sp_int64)a[11]) * b[ 8]
|
|
+ ((sp_int64)a[12]) * b[ 7]
|
|
+ ((sp_int64)a[13]) * b[ 6]
|
|
+ ((sp_int64)a[14]) * b[ 5];
|
|
r[18] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 6]) * b[14]
|
|
+ ((sp_int64)a[ 7]) * b[13]
|
|
+ ((sp_int64)a[ 8]) * b[12]
|
|
+ ((sp_int64)a[ 9]) * b[11]
|
|
+ ((sp_int64)a[10]) * b[10]
|
|
+ ((sp_int64)a[11]) * b[ 9]
|
|
+ ((sp_int64)a[12]) * b[ 8]
|
|
+ ((sp_int64)a[13]) * b[ 7]
|
|
+ ((sp_int64)a[14]) * b[ 6];
|
|
r[19] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 7]) * b[14]
|
|
+ ((sp_int64)a[ 8]) * b[13]
|
|
+ ((sp_int64)a[ 9]) * b[12]
|
|
+ ((sp_int64)a[10]) * b[11]
|
|
+ ((sp_int64)a[11]) * b[10]
|
|
+ ((sp_int64)a[12]) * b[ 9]
|
|
+ ((sp_int64)a[13]) * b[ 8]
|
|
+ ((sp_int64)a[14]) * b[ 7];
|
|
r[20] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[ 8]) * b[14]
|
|
+ ((sp_int64)a[ 9]) * b[13]
|
|
+ ((sp_int64)a[10]) * b[12]
|
|
+ ((sp_int64)a[11]) * b[11]
|
|
+ ((sp_int64)a[12]) * b[10]
|
|
+ ((sp_int64)a[13]) * b[ 9]
|
|
+ ((sp_int64)a[14]) * b[ 8];
|
|
r[21] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[ 9]) * b[14]
|
|
+ ((sp_int64)a[10]) * b[13]
|
|
+ ((sp_int64)a[11]) * b[12]
|
|
+ ((sp_int64)a[12]) * b[11]
|
|
+ ((sp_int64)a[13]) * b[10]
|
|
+ ((sp_int64)a[14]) * b[ 9];
|
|
r[22] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[10]) * b[14]
|
|
+ ((sp_int64)a[11]) * b[13]
|
|
+ ((sp_int64)a[12]) * b[12]
|
|
+ ((sp_int64)a[13]) * b[11]
|
|
+ ((sp_int64)a[14]) * b[10];
|
|
r[23] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[11]) * b[14]
|
|
+ ((sp_int64)a[12]) * b[13]
|
|
+ ((sp_int64)a[13]) * b[12]
|
|
+ ((sp_int64)a[14]) * b[11];
|
|
r[24] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[12]) * b[14]
|
|
+ ((sp_int64)a[13]) * b[13]
|
|
+ ((sp_int64)a[14]) * b[12];
|
|
r[25] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = ((sp_int64)a[13]) * b[14]
|
|
+ ((sp_int64)a[14]) * b[13];
|
|
r[26] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[14]) * b[14];
|
|
r[27] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
r[28] = t0 & 0x3ffffff;
|
|
r[29] = (sp_digit)(t0 >> 26);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[14]) * a[14];
|
|
r[29] = (sp_digit)(c >> 26);
|
|
c = (c & 0x3ffffff) << 26;
|
|
for (k = 27; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 14) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 14;
|
|
}
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 52);
|
|
r[k + 1] = (sp_digit)((c >> 26) & 0x3ffffff);
|
|
c = (c & 0x3ffffff) << 26;
|
|
}
|
|
r[0] = (sp_digit)(c >> 26);
|
|
}
|
|
|
|
#else
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_384_sqr_15(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_int64 t0;
|
|
sp_int64 t1;
|
|
sp_digit t[15];
|
|
|
|
t0 = ((sp_int64)a[ 0]) * a[ 0];
|
|
t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2;
|
|
t[ 0] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 2]) * 2
|
|
+ ((sp_int64)a[ 1]) * a[ 1];
|
|
t[ 1] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 3]
|
|
+ ((sp_int64)a[ 1]) * a[ 2]) * 2;
|
|
t[ 2] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 4]
|
|
+ ((sp_int64)a[ 1]) * a[ 3]) * 2
|
|
+ ((sp_int64)a[ 2]) * a[ 2];
|
|
t[ 3] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 5]
|
|
+ ((sp_int64)a[ 1]) * a[ 4]
|
|
+ ((sp_int64)a[ 2]) * a[ 3]) * 2;
|
|
t[ 4] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 6]
|
|
+ ((sp_int64)a[ 1]) * a[ 5]
|
|
+ ((sp_int64)a[ 2]) * a[ 4]) * 2
|
|
+ ((sp_int64)a[ 3]) * a[ 3];
|
|
t[ 5] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 7]
|
|
+ ((sp_int64)a[ 1]) * a[ 6]
|
|
+ ((sp_int64)a[ 2]) * a[ 5]
|
|
+ ((sp_int64)a[ 3]) * a[ 4]) * 2;
|
|
t[ 6] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[ 8]
|
|
+ ((sp_int64)a[ 1]) * a[ 7]
|
|
+ ((sp_int64)a[ 2]) * a[ 6]
|
|
+ ((sp_int64)a[ 3]) * a[ 5]) * 2
|
|
+ ((sp_int64)a[ 4]) * a[ 4];
|
|
t[ 7] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 0]) * a[ 9]
|
|
+ ((sp_int64)a[ 1]) * a[ 8]
|
|
+ ((sp_int64)a[ 2]) * a[ 7]
|
|
+ ((sp_int64)a[ 3]) * a[ 6]
|
|
+ ((sp_int64)a[ 4]) * a[ 5]) * 2;
|
|
t[ 8] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[10]
|
|
+ ((sp_int64)a[ 1]) * a[ 9]
|
|
+ ((sp_int64)a[ 2]) * a[ 8]
|
|
+ ((sp_int64)a[ 3]) * a[ 7]
|
|
+ ((sp_int64)a[ 4]) * a[ 6]) * 2
|
|
+ ((sp_int64)a[ 5]) * a[ 5];
|
|
t[ 9] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 0]) * a[11]
|
|
+ ((sp_int64)a[ 1]) * a[10]
|
|
+ ((sp_int64)a[ 2]) * a[ 9]
|
|
+ ((sp_int64)a[ 3]) * a[ 8]
|
|
+ ((sp_int64)a[ 4]) * a[ 7]
|
|
+ ((sp_int64)a[ 5]) * a[ 6]) * 2;
|
|
t[10] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[12]
|
|
+ ((sp_int64)a[ 1]) * a[11]
|
|
+ ((sp_int64)a[ 2]) * a[10]
|
|
+ ((sp_int64)a[ 3]) * a[ 9]
|
|
+ ((sp_int64)a[ 4]) * a[ 8]
|
|
+ ((sp_int64)a[ 5]) * a[ 7]) * 2
|
|
+ ((sp_int64)a[ 6]) * a[ 6];
|
|
t[11] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 0]) * a[13]
|
|
+ ((sp_int64)a[ 1]) * a[12]
|
|
+ ((sp_int64)a[ 2]) * a[11]
|
|
+ ((sp_int64)a[ 3]) * a[10]
|
|
+ ((sp_int64)a[ 4]) * a[ 9]
|
|
+ ((sp_int64)a[ 5]) * a[ 8]
|
|
+ ((sp_int64)a[ 6]) * a[ 7]) * 2;
|
|
t[12] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 0]) * a[14]
|
|
+ ((sp_int64)a[ 1]) * a[13]
|
|
+ ((sp_int64)a[ 2]) * a[12]
|
|
+ ((sp_int64)a[ 3]) * a[11]
|
|
+ ((sp_int64)a[ 4]) * a[10]
|
|
+ ((sp_int64)a[ 5]) * a[ 9]
|
|
+ ((sp_int64)a[ 6]) * a[ 8]) * 2
|
|
+ ((sp_int64)a[ 7]) * a[ 7];
|
|
t[13] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 1]) * a[14]
|
|
+ ((sp_int64)a[ 2]) * a[13]
|
|
+ ((sp_int64)a[ 3]) * a[12]
|
|
+ ((sp_int64)a[ 4]) * a[11]
|
|
+ ((sp_int64)a[ 5]) * a[10]
|
|
+ ((sp_int64)a[ 6]) * a[ 9]
|
|
+ ((sp_int64)a[ 7]) * a[ 8]) * 2;
|
|
t[14] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 2]) * a[14]
|
|
+ ((sp_int64)a[ 3]) * a[13]
|
|
+ ((sp_int64)a[ 4]) * a[12]
|
|
+ ((sp_int64)a[ 5]) * a[11]
|
|
+ ((sp_int64)a[ 6]) * a[10]
|
|
+ ((sp_int64)a[ 7]) * a[ 9]) * 2
|
|
+ ((sp_int64)a[ 8]) * a[ 8];
|
|
r[15] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 3]) * a[14]
|
|
+ ((sp_int64)a[ 4]) * a[13]
|
|
+ ((sp_int64)a[ 5]) * a[12]
|
|
+ ((sp_int64)a[ 6]) * a[11]
|
|
+ ((sp_int64)a[ 7]) * a[10]
|
|
+ ((sp_int64)a[ 8]) * a[ 9]) * 2;
|
|
r[16] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 4]) * a[14]
|
|
+ ((sp_int64)a[ 5]) * a[13]
|
|
+ ((sp_int64)a[ 6]) * a[12]
|
|
+ ((sp_int64)a[ 7]) * a[11]
|
|
+ ((sp_int64)a[ 8]) * a[10]) * 2
|
|
+ ((sp_int64)a[ 9]) * a[ 9];
|
|
r[17] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 5]) * a[14]
|
|
+ ((sp_int64)a[ 6]) * a[13]
|
|
+ ((sp_int64)a[ 7]) * a[12]
|
|
+ ((sp_int64)a[ 8]) * a[11]
|
|
+ ((sp_int64)a[ 9]) * a[10]) * 2;
|
|
r[18] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 6]) * a[14]
|
|
+ ((sp_int64)a[ 7]) * a[13]
|
|
+ ((sp_int64)a[ 8]) * a[12]
|
|
+ ((sp_int64)a[ 9]) * a[11]) * 2
|
|
+ ((sp_int64)a[10]) * a[10];
|
|
r[19] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 7]) * a[14]
|
|
+ ((sp_int64)a[ 8]) * a[13]
|
|
+ ((sp_int64)a[ 9]) * a[12]
|
|
+ ((sp_int64)a[10]) * a[11]) * 2;
|
|
r[20] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[ 8]) * a[14]
|
|
+ ((sp_int64)a[ 9]) * a[13]
|
|
+ ((sp_int64)a[10]) * a[12]) * 2
|
|
+ ((sp_int64)a[11]) * a[11];
|
|
r[21] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[ 9]) * a[14]
|
|
+ ((sp_int64)a[10]) * a[13]
|
|
+ ((sp_int64)a[11]) * a[12]) * 2;
|
|
r[22] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[10]) * a[14]
|
|
+ ((sp_int64)a[11]) * a[13]) * 2
|
|
+ ((sp_int64)a[12]) * a[12];
|
|
r[23] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[11]) * a[14]
|
|
+ ((sp_int64)a[12]) * a[13]) * 2;
|
|
r[24] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = (((sp_int64)a[12]) * a[14]) * 2
|
|
+ ((sp_int64)a[13]) * a[13];
|
|
r[25] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
t1 = (((sp_int64)a[13]) * a[14]) * 2;
|
|
r[26] = t0 & 0x3ffffff; t1 += t0 >> 26;
|
|
t0 = ((sp_int64)a[14]) * a[14];
|
|
r[27] = t1 & 0x3ffffff; t0 += t1 >> 26;
|
|
r[28] = t0 & 0x3ffffff;
|
|
r[29] = (sp_digit)(t0 >> 26);
|
|
XMEMCPY(r, t, sizeof(t));
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_384_add_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
r[ 7] = a[ 7] + b[ 7];
|
|
r[ 8] = a[ 8] + b[ 8];
|
|
r[ 9] = a[ 9] + b[ 9];
|
|
r[10] = a[10] + b[10];
|
|
r[11] = a[11] + b[11];
|
|
r[12] = a[12] + b[12];
|
|
r[13] = a[13] + b[13];
|
|
r[14] = a[14] + b[14];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_384_sub_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] - b[ 0];
|
|
r[ 1] = a[ 1] - b[ 1];
|
|
r[ 2] = a[ 2] - b[ 2];
|
|
r[ 3] = a[ 3] - b[ 3];
|
|
r[ 4] = a[ 4] - b[ 4];
|
|
r[ 5] = a[ 5] - b[ 5];
|
|
r[ 6] = a[ 6] - b[ 6];
|
|
r[ 7] = a[ 7] - b[ 7];
|
|
r[ 8] = a[ 8] - b[ 8];
|
|
r[ 9] = a[ 9] - b[ 9];
|
|
r[10] = a[10] - b[10];
|
|
r[11] = a[11] - b[11];
|
|
r[12] = a[12] - b[12];
|
|
r[13] = a[13] - b[13];
|
|
r[14] = a[14] - b[14];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_384_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 26
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 26
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x3ffffff;
|
|
s = 26U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 26U) <= (word32)DIGIT_BIT) {
|
|
s += 26U;
|
|
r[j] &= 0x3ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 26) {
|
|
r[j] &= 0x3ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 26 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Convert a point of type ecc_point to type sp_point_384.
|
|
*
|
|
* p Point of type sp_point_384 (result).
|
|
* pm Point of type ecc_point.
|
|
*/
|
|
static void sp_384_point_from_ecc_point_15(sp_point_384* p,
|
|
const ecc_point* pm)
|
|
{
|
|
XMEMSET(p->x, 0, sizeof(p->x));
|
|
XMEMSET(p->y, 0, sizeof(p->y));
|
|
XMEMSET(p->z, 0, sizeof(p->z));
|
|
sp_384_from_mp(p->x, 15, pm->x);
|
|
sp_384_from_mp(p->y, 15, pm->y);
|
|
sp_384_from_mp(p->z, 15, pm->z);
|
|
p->infinity = 0;
|
|
}
|
|
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_384_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (384 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 26
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 15);
|
|
r->used = 15;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 26
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 15; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 26) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 26 - s;
|
|
}
|
|
r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 15; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 26 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 26 - s;
|
|
}
|
|
else {
|
|
s += 26;
|
|
}
|
|
}
|
|
r->used = (384 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Convert a point of type sp_point_384 to type ecc_point.
|
|
*
|
|
* p Point of type sp_point_384.
|
|
* pm Point of type ecc_point (result).
|
|
* returns MEMORY_E when allocation of memory in ecc_point fails otherwise
|
|
* MP_OKAY.
|
|
*/
|
|
static int sp_384_point_to_ecc_point_15(const sp_point_384* p, ecc_point* pm)
|
|
{
|
|
int err;
|
|
|
|
err = sp_384_to_mp(p->x, pm->x);
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->y, pm->y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->z, pm->z);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_384_cmp_15(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=14; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 25);
|
|
}
|
|
#else
|
|
r |= (a[14] - b[14]) & (0 - (sp_digit)1);
|
|
r |= (a[13] - b[13]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[12] - b[12]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[11] - b[11]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[10] - b[10]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 9] - b[ 9]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 8] - b[ 8]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 7] - b[ 7]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 6] - b[ 6]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 5] - b[ 5]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 4] - b[ 4]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 3] - b[ 3]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 2] - b[ 2]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 1] - b[ 1]) & ~(((sp_digit)0 - r) >> 25);
|
|
r |= (a[ 0] - b[ 0]) & ~(((sp_digit)0 - r) >> 25);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_384_cond_sub_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
#else
|
|
r[ 0] = a[ 0] - (b[ 0] & m);
|
|
r[ 1] = a[ 1] - (b[ 1] & m);
|
|
r[ 2] = a[ 2] - (b[ 2] & m);
|
|
r[ 3] = a[ 3] - (b[ 3] & m);
|
|
r[ 4] = a[ 4] - (b[ 4] & m);
|
|
r[ 5] = a[ 5] - (b[ 5] & m);
|
|
r[ 6] = a[ 6] - (b[ 6] & m);
|
|
r[ 7] = a[ 7] - (b[ 7] & m);
|
|
r[ 8] = a[ 8] - (b[ 8] & m);
|
|
r[ 9] = a[ 9] - (b[ 9] & m);
|
|
r[10] = a[10] - (b[10] & m);
|
|
r[11] = a[11] - (b[11] & m);
|
|
r[12] = a[12] - (b[12] & m);
|
|
r[13] = a[13] - (b[13] & m);
|
|
r[14] = a[14] - (b[14] & m);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_384_mul_add_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 12; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x3ffffff;
|
|
t[1] += t[0] >> 26;
|
|
r[i+1] = t[1] & 0x3ffffff;
|
|
t[2] += t[1] >> 26;
|
|
r[i+2] = t[2] & 0x3ffffff;
|
|
t[3] += t[2] >> 26;
|
|
r[i+3] = t[3] & 0x3ffffff;
|
|
t[0] = t[3] >> 26;
|
|
}
|
|
t[0] += (tb * a[12]) + r[12];
|
|
t[1] = (tb * a[13]) + r[13];
|
|
t[2] = (tb * a[14]) + r[14];
|
|
r[12] = t[0] & 0x3ffffff;
|
|
t[1] += t[0] >> 26;
|
|
r[13] = t[1] & 0x3ffffff;
|
|
t[2] += t[1] >> 26;
|
|
r[14] = t[2] & 0x3ffffff;
|
|
r[15] += (sp_digit)(t[2] >> 26);
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[15];
|
|
|
|
t[ 0] = tb * a[ 0];
|
|
t[ 1] = tb * a[ 1];
|
|
t[ 2] = tb * a[ 2];
|
|
t[ 3] = tb * a[ 3];
|
|
t[ 4] = tb * a[ 4];
|
|
t[ 5] = tb * a[ 5];
|
|
t[ 6] = tb * a[ 6];
|
|
t[ 7] = tb * a[ 7];
|
|
t[ 8] = tb * a[ 8];
|
|
t[ 9] = tb * a[ 9];
|
|
t[10] = tb * a[10];
|
|
t[11] = tb * a[11];
|
|
t[12] = tb * a[12];
|
|
t[13] = tb * a[13];
|
|
t[14] = tb * a[14];
|
|
r[ 0] += (sp_digit) (t[ 0] & 0x3ffffff);
|
|
r[ 1] += (sp_digit)((t[ 0] >> 26) + (t[ 1] & 0x3ffffff));
|
|
r[ 2] += (sp_digit)((t[ 1] >> 26) + (t[ 2] & 0x3ffffff));
|
|
r[ 3] += (sp_digit)((t[ 2] >> 26) + (t[ 3] & 0x3ffffff));
|
|
r[ 4] += (sp_digit)((t[ 3] >> 26) + (t[ 4] & 0x3ffffff));
|
|
r[ 5] += (sp_digit)((t[ 4] >> 26) + (t[ 5] & 0x3ffffff));
|
|
r[ 6] += (sp_digit)((t[ 5] >> 26) + (t[ 6] & 0x3ffffff));
|
|
r[ 7] += (sp_digit)((t[ 6] >> 26) + (t[ 7] & 0x3ffffff));
|
|
r[ 8] += (sp_digit)((t[ 7] >> 26) + (t[ 8] & 0x3ffffff));
|
|
r[ 9] += (sp_digit)((t[ 8] >> 26) + (t[ 9] & 0x3ffffff));
|
|
r[10] += (sp_digit)((t[ 9] >> 26) + (t[10] & 0x3ffffff));
|
|
r[11] += (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff));
|
|
r[12] += (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff));
|
|
r[13] += (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff));
|
|
r[14] += (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff));
|
|
r[15] += (sp_digit) (t[14] >> 26);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Normalize the values in each word to 26 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_384_norm_15(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 14; i++) {
|
|
a[i+1] += a[i] >> 26;
|
|
a[i] &= 0x3ffffff;
|
|
}
|
|
#else
|
|
a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
|
|
a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
|
|
a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
|
|
a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
|
|
a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
|
|
a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
|
|
a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
|
|
a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
|
|
a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
|
|
a[10] += a[9] >> 26; a[9] &= 0x3ffffff;
|
|
a[11] += a[10] >> 26; a[10] &= 0x3ffffff;
|
|
a[12] += a[11] >> 26; a[11] &= 0x3ffffff;
|
|
a[13] += a[12] >> 26; a[12] &= 0x3ffffff;
|
|
a[14] += a[13] >> 26; a[13] &= 0x3ffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Shift the result in the high 384 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_384_mont_shift_15(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
sp_int64 n = a[14] >> 20;
|
|
n += ((sp_int64)a[15]) << 6;
|
|
|
|
for (i = 0; i < 14; i++) {
|
|
r[i] = n & 0x3ffffff;
|
|
n >>= 26;
|
|
n += ((sp_int64)a[16 + i]) << 6;
|
|
}
|
|
r[14] = (sp_digit)n;
|
|
#else
|
|
sp_int64 n = a[14] >> 20;
|
|
n += ((sp_int64)a[15]) << 6;
|
|
r[ 0] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[16]) << 6;
|
|
r[ 1] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[17]) << 6;
|
|
r[ 2] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[18]) << 6;
|
|
r[ 3] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[19]) << 6;
|
|
r[ 4] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[20]) << 6;
|
|
r[ 5] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[21]) << 6;
|
|
r[ 6] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[22]) << 6;
|
|
r[ 7] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[23]) << 6;
|
|
r[ 8] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[24]) << 6;
|
|
r[ 9] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[25]) << 6;
|
|
r[10] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[26]) << 6;
|
|
r[11] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[27]) << 6;
|
|
r[12] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[28]) << 6;
|
|
r[13] = n & 0x3ffffff; n >>= 26; n += ((sp_int64)a[29]) << 6;
|
|
r[14] = (sp_digit)n;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
XMEMSET(&r[15], 0, sizeof(*r) * 15U);
|
|
}
|
|
|
|
/* Reduce the number back to 384 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_384_mont_reduce_order_15(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_384_norm_15(a + 15);
|
|
|
|
for (i=0; i<14; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x3ffffff;
|
|
sp_384_mul_add_15(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0xfffffL;
|
|
sp_384_mul_add_15(a+i, m, mu);
|
|
a[i+1] += a[i] >> 26;
|
|
a[i] &= 0x3ffffff;
|
|
sp_384_mont_shift_15(a, a);
|
|
over = a[14] >> 20;
|
|
sp_384_cond_sub_15(a, a, m, ~((over - 1) >> 31));
|
|
sp_384_norm_15(a);
|
|
}
|
|
|
|
/* Reduce the number back to 384 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_384_mont_reduce_15(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit am;
|
|
|
|
(void)m;
|
|
(void)mp;
|
|
|
|
for (i = 0; i < 14; i++) {
|
|
am = (a[i] * 0x1) & 0x3ffffff;
|
|
a[i + 1] += (am << 6) & 0x3ffffff;
|
|
a[i + 2] += am >> 20;
|
|
a[i + 3] -= (am << 18) & 0x3ffffff;
|
|
a[i + 4] -= am >> 8;
|
|
a[i + 4] -= (am << 24) & 0x3ffffff;
|
|
a[i + 5] -= am >> 2;
|
|
a[i + 14] += (am << 20) & 0x3ffffff;
|
|
a[i + 15] += am >> 6;
|
|
|
|
a[i + 1] += a[i] >> 26;
|
|
}
|
|
am = (a[14] * 0x1) & 0xfffff;
|
|
a[14 + 1] += (am << 6) & 0x3ffffff;
|
|
a[14 + 2] += am >> 20;
|
|
a[14 + 3] -= (am << 18) & 0x3ffffff;
|
|
a[14 + 4] -= am >> 8;
|
|
a[14 + 4] -= (am << 24) & 0x3ffffff;
|
|
a[14 + 5] -= am >> 2;
|
|
a[14 + 14] += (am << 20) & 0x3ffffff;
|
|
a[14 + 15] += am >> 6;
|
|
|
|
a[0] = (a[14] >> 20) + ((a[15] << 6) & 0x3ffffff);
|
|
a[1] = (a[15] >> 20) + ((a[16] << 6) & 0x3ffffff);
|
|
a[2] = (a[16] >> 20) + ((a[17] << 6) & 0x3ffffff);
|
|
a[3] = (a[17] >> 20) + ((a[18] << 6) & 0x3ffffff);
|
|
a[4] = (a[18] >> 20) + ((a[19] << 6) & 0x3ffffff);
|
|
a[5] = (a[19] >> 20) + ((a[20] << 6) & 0x3ffffff);
|
|
a[6] = (a[20] >> 20) + ((a[21] << 6) & 0x3ffffff);
|
|
a[7] = (a[21] >> 20) + ((a[22] << 6) & 0x3ffffff);
|
|
a[8] = (a[22] >> 20) + ((a[23] << 6) & 0x3ffffff);
|
|
a[9] = (a[23] >> 20) + ((a[24] << 6) & 0x3ffffff);
|
|
a[10] = (a[24] >> 20) + ((a[25] << 6) & 0x3ffffff);
|
|
a[11] = (a[25] >> 20) + ((a[26] << 6) & 0x3ffffff);
|
|
a[12] = (a[26] >> 20) + ((a[27] << 6) & 0x3ffffff);
|
|
a[13] = (a[27] >> 20) + ((a[28] << 6) & 0x3ffffff);
|
|
a[14] = (a[14 + 14] >> 20) + (a[29] << 6);
|
|
|
|
a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
|
|
a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
|
|
a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
|
|
a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
|
|
a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
|
|
a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
|
|
a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
|
|
a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
|
|
a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
|
|
a[10] += a[9] >> 26; a[9] &= 0x3ffffff;
|
|
a[11] += a[10] >> 26; a[10] &= 0x3ffffff;
|
|
a[12] += a[11] >> 26; a[11] &= 0x3ffffff;
|
|
a[13] += a[12] >> 26; a[12] &= 0x3ffffff;
|
|
a[14] += a[13] >> 26; a[13] &= 0x3ffffff;
|
|
|
|
/* Get the bit over, if any. */
|
|
am = a[14] >> 20;
|
|
/* Create mask. */
|
|
am = 0 - am;
|
|
|
|
a[0] -= 0x03ffffff & am;
|
|
a[1] -= 0x0000003f & am;
|
|
/* p384_mod[2] is zero */
|
|
a[3] -= 0x03fc0000 & am;
|
|
a[4] -= 0x02ffffff & am;
|
|
a[5] -= 0x03ffffff & am;
|
|
a[6] -= 0x03ffffff & am;
|
|
a[7] -= 0x03ffffff & am;
|
|
a[8] -= 0x03ffffff & am;
|
|
a[9] -= 0x03ffffff & am;
|
|
a[10] -= 0x03ffffff & am;
|
|
a[11] -= 0x03ffffff & am;
|
|
a[12] -= 0x03ffffff & am;
|
|
a[13] -= 0x03ffffff & am;
|
|
a[14] -= 0x000fffff & am;
|
|
|
|
a[1] += a[0] >> 26; a[0] &= 0x3ffffff;
|
|
a[2] += a[1] >> 26; a[1] &= 0x3ffffff;
|
|
a[3] += a[2] >> 26; a[2] &= 0x3ffffff;
|
|
a[4] += a[3] >> 26; a[3] &= 0x3ffffff;
|
|
a[5] += a[4] >> 26; a[4] &= 0x3ffffff;
|
|
a[6] += a[5] >> 26; a[5] &= 0x3ffffff;
|
|
a[7] += a[6] >> 26; a[6] &= 0x3ffffff;
|
|
a[8] += a[7] >> 26; a[7] &= 0x3ffffff;
|
|
a[9] += a[8] >> 26; a[8] &= 0x3ffffff;
|
|
a[10] += a[9] >> 26; a[9] &= 0x3ffffff;
|
|
a[11] += a[10] >> 26; a[10] &= 0x3ffffff;
|
|
a[12] += a[11] >> 26; a[11] &= 0x3ffffff;
|
|
a[13] += a[12] >> 26; a[12] &= 0x3ffffff;
|
|
a[14] += a[13] >> 26; a[13] &= 0x3ffffff;
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_384_mont_mul_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_384_mul_15(r, a, b);
|
|
sp_384_mont_reduce_15(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_384_mont_sqr_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_384_sqr_15(r, a);
|
|
sp_384_mont_reduce_15(r, m, mp);
|
|
}
|
|
|
|
#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY)
|
|
/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* n Number of times to square.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
static void sp_384_mont_sqr_n_15(sp_digit* r, const sp_digit* a, int n,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_384_mont_sqr_15(r, a, m, mp);
|
|
for (; n > 1; n--) {
|
|
sp_384_mont_sqr_15(r, r, m, mp);
|
|
}
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Mod-2 for the P384 curve. */
|
|
static const uint32_t p384_mod_minus_2[12] = {
|
|
0xfffffffdU,0x00000000U,0x00000000U,0xffffffffU,0xfffffffeU,0xffffffffU,
|
|
0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU
|
|
};
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
|
|
* P384 curve. (r = 1 / a mod m)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
static void sp_384_mont_inv_15(sp_digit* r, const sp_digit* a, sp_digit* td)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_digit* t = td;
|
|
int i;
|
|
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 15);
|
|
for (i=382; i>=0; i--) {
|
|
sp_384_mont_sqr_15(t, t, p384_mod, p384_mp_mod);
|
|
if (p384_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
|
|
sp_384_mont_mul_15(t, t, a, p384_mod, p384_mp_mod);
|
|
}
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 15);
|
|
#else
|
|
sp_digit* t1 = td;
|
|
sp_digit* t2 = td + 2 * 15;
|
|
sp_digit* t3 = td + 4 * 15;
|
|
sp_digit* t4 = td + 6 * 15;
|
|
sp_digit* t5 = td + 8 * 15;
|
|
|
|
/* 0x2 */
|
|
sp_384_mont_sqr_15(t1, a, p384_mod, p384_mp_mod);
|
|
/* 0x3 */
|
|
sp_384_mont_mul_15(t5, t1, a, p384_mod, p384_mp_mod);
|
|
/* 0xc */
|
|
sp_384_mont_sqr_n_15(t1, t5, 2, p384_mod, p384_mp_mod);
|
|
/* 0xf */
|
|
sp_384_mont_mul_15(t2, t5, t1, p384_mod, p384_mp_mod);
|
|
/* 0x1e */
|
|
sp_384_mont_sqr_15(t1, t2, p384_mod, p384_mp_mod);
|
|
/* 0x1f */
|
|
sp_384_mont_mul_15(t4, t1, a, p384_mod, p384_mp_mod);
|
|
/* 0x3e0 */
|
|
sp_384_mont_sqr_n_15(t1, t4, 5, p384_mod, p384_mp_mod);
|
|
/* 0x3ff */
|
|
sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod);
|
|
/* 0x7fe0 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 5, p384_mod, p384_mp_mod);
|
|
/* 0x7fff */
|
|
sp_384_mont_mul_15(t4, t4, t1, p384_mod, p384_mp_mod);
|
|
/* 0x3fff8000 */
|
|
sp_384_mont_sqr_n_15(t1, t4, 15, p384_mod, p384_mp_mod);
|
|
/* 0x3fffffff */
|
|
sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffc */
|
|
sp_384_mont_sqr_n_15(t3, t2, 2, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffd */
|
|
sp_384_mont_mul_15(r, t3, a, p384_mod, p384_mp_mod);
|
|
/* 0xffffffff */
|
|
sp_384_mont_mul_15(t3, t5, t3, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffc0000000 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 30, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffffffffff */
|
|
sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffffffffff000000000000000 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 60, p384_mod, p384_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffff */
|
|
sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 120, p384_mod, p384_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_384_mont_mul_15(t2, t2, t1, p384_mod, p384_mp_mod);
|
|
/* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 15, p384_mod, p384_mp_mod);
|
|
/* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_384_mont_mul_15(t2, t4, t1, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00000000 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 33, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff */
|
|
sp_384_mont_mul_15(t2, t3, t1, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff000000000000000000000000 */
|
|
sp_384_mont_sqr_n_15(t1, t2, 96, p384_mod, p384_mp_mod);
|
|
/* 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000fffffffd */
|
|
sp_384_mont_mul_15(r, r, t1, p384_mod, p384_mp_mod);
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Map the Montgomery form projective coordinate point to an affine point.
|
|
*
|
|
* r Resulting affine coordinate point.
|
|
* p Montgomery form projective coordinate point.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_map_15(sp_point_384* r, const sp_point_384* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*15;
|
|
sp_int32 n;
|
|
|
|
sp_384_mont_inv_15(t1, p->z, t + 2*15);
|
|
|
|
sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod);
|
|
|
|
/* x /= z^2 */
|
|
sp_384_mont_mul_15(r->x, p->x, t2, p384_mod, p384_mp_mod);
|
|
XMEMSET(r->x + 15, 0, sizeof(sp_digit) * 15U);
|
|
sp_384_mont_reduce_15(r->x, p384_mod, p384_mp_mod);
|
|
/* Reduce x to less than modulus */
|
|
n = sp_384_cmp_15(r->x, p384_mod);
|
|
sp_384_cond_sub_15(r->x, r->x, p384_mod, ~(n >> 25));
|
|
sp_384_norm_15(r->x);
|
|
|
|
/* y /= z^3 */
|
|
sp_384_mont_mul_15(r->y, p->y, t1, p384_mod, p384_mp_mod);
|
|
XMEMSET(r->y + 15, 0, sizeof(sp_digit) * 15U);
|
|
sp_384_mont_reduce_15(r->y, p384_mod, p384_mp_mod);
|
|
/* Reduce y to less than modulus */
|
|
n = sp_384_cmp_15(r->y, p384_mod);
|
|
sp_384_cond_sub_15(r->y, r->y, p384_mod, ~(n >> 25));
|
|
sp_384_norm_15(r->y);
|
|
|
|
XMEMSET(r->z, 0, sizeof(r->z) / 2);
|
|
r->z[0] = 1;
|
|
}
|
|
|
|
/* Add two Montgomery form numbers (r = a + b % m).
|
|
*
|
|
* r Result of addition.
|
|
* a First number to add in Montgomery form.
|
|
* b Second number to add in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_384_mont_add_15(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_384_add_15(r, a, b);
|
|
sp_384_norm_15(r);
|
|
over = r[14] >> 20;
|
|
sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
|
|
sp_384_norm_15(r);
|
|
}
|
|
|
|
/* Double a Montgomery form number (r = a + a % m).
|
|
*
|
|
* r Result of doubling.
|
|
* a Number to double in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_384_mont_dbl_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_384_add_15(r, a, a);
|
|
sp_384_norm_15(r);
|
|
over = r[14] >> 20;
|
|
sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
|
|
sp_384_norm_15(r);
|
|
}
|
|
|
|
/* Triple a Montgomery form number (r = a + a + a % m).
|
|
*
|
|
* r Result of Tripling.
|
|
* a Number to triple in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_384_mont_tpl_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_384_add_15(r, a, a);
|
|
sp_384_norm_15(r);
|
|
over = r[14] >> 20;
|
|
sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
|
|
sp_384_norm_15(r);
|
|
(void)sp_384_add_15(r, r, a);
|
|
sp_384_norm_15(r);
|
|
over = r[14] >> 20;
|
|
sp_384_cond_sub_15(r, r, m, ~((over - 1) >> 31));
|
|
sp_384_norm_15(r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_384_cond_add_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_384_cond_add_15(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
r[ 0] = a[ 0] + (b[ 0] & m);
|
|
r[ 1] = a[ 1] + (b[ 1] & m);
|
|
r[ 2] = a[ 2] + (b[ 2] & m);
|
|
r[ 3] = a[ 3] + (b[ 3] & m);
|
|
r[ 4] = a[ 4] + (b[ 4] & m);
|
|
r[ 5] = a[ 5] + (b[ 5] & m);
|
|
r[ 6] = a[ 6] + (b[ 6] & m);
|
|
r[ 7] = a[ 7] + (b[ 7] & m);
|
|
r[ 8] = a[ 8] + (b[ 8] & m);
|
|
r[ 9] = a[ 9] + (b[ 9] & m);
|
|
r[10] = a[10] + (b[10] & m);
|
|
r[11] = a[11] + (b[11] & m);
|
|
r[12] = a[12] + (b[12] & m);
|
|
r[13] = a[13] + (b[13] & m);
|
|
r[14] = a[14] + (b[14] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Subtract two Montgomery form numbers (r = a - b % m).
|
|
*
|
|
* r Result of subtration.
|
|
* a Number to subtract from in Montgomery form.
|
|
* b Number to subtract with in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_384_mont_sub_15(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
(void)sp_384_sub_15(r, a, b);
|
|
sp_384_norm_15(r);
|
|
sp_384_cond_add_15(r, r, m, r[14] >> 20);
|
|
sp_384_norm_15(r);
|
|
}
|
|
|
|
#define sp_384_mont_sub_lower_15 sp_384_mont_sub_15
|
|
/* Shift number left one bit.
|
|
* Bottom bit is lost.
|
|
*
|
|
* r Result of shift.
|
|
* a Number to shift.
|
|
*/
|
|
SP_NOINLINE static void sp_384_rshift1_15(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=0; i<14; i++) {
|
|
r[i] = (a[i] >> 1) + ((a[i + 1] << 25) & 0x3ffffff);
|
|
}
|
|
#else
|
|
r[0] = (a[0] >> 1) + ((a[1] << 25) & 0x3ffffff);
|
|
r[1] = (a[1] >> 1) + ((a[2] << 25) & 0x3ffffff);
|
|
r[2] = (a[2] >> 1) + ((a[3] << 25) & 0x3ffffff);
|
|
r[3] = (a[3] >> 1) + ((a[4] << 25) & 0x3ffffff);
|
|
r[4] = (a[4] >> 1) + ((a[5] << 25) & 0x3ffffff);
|
|
r[5] = (a[5] >> 1) + ((a[6] << 25) & 0x3ffffff);
|
|
r[6] = (a[6] >> 1) + ((a[7] << 25) & 0x3ffffff);
|
|
r[7] = (a[7] >> 1) + ((a[8] << 25) & 0x3ffffff);
|
|
r[8] = (a[8] >> 1) + ((a[9] << 25) & 0x3ffffff);
|
|
r[9] = (a[9] >> 1) + ((a[10] << 25) & 0x3ffffff);
|
|
r[10] = (a[10] >> 1) + ((a[11] << 25) & 0x3ffffff);
|
|
r[11] = (a[11] >> 1) + ((a[12] << 25) & 0x3ffffff);
|
|
r[12] = (a[12] >> 1) + ((a[13] << 25) & 0x3ffffff);
|
|
r[13] = (a[13] >> 1) + ((a[14] << 25) & 0x3ffffff);
|
|
#endif
|
|
r[14] = a[14] >> 1;
|
|
}
|
|
|
|
/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
|
|
*
|
|
* r Result of division by 2.
|
|
* a Number to divide.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_384_div2_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_384_cond_add_15(r, a, m, 0 - (a[0] & 1));
|
|
sp_384_norm_15(r);
|
|
sp_384_rshift1_15(r, r);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_proj_point_dbl_15(sp_point_384* r, const sp_point_384* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*15;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
|
|
x = r->x;
|
|
y = r->y;
|
|
z = r->z;
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
|
|
/* T1 = Z * Z */
|
|
sp_384_mont_sqr_15(t1, p->z, p384_mod, p384_mp_mod);
|
|
/* Z = Y * Z */
|
|
sp_384_mont_mul_15(z, p->y, p->z, p384_mod, p384_mp_mod);
|
|
/* Z = 2Z */
|
|
sp_384_mont_dbl_15(z, z, p384_mod);
|
|
/* T2 = X - T1 */
|
|
sp_384_mont_sub_15(t2, p->x, t1, p384_mod);
|
|
/* T1 = X + T1 */
|
|
sp_384_mont_add_15(t1, p->x, t1, p384_mod);
|
|
/* T2 = T1 * T2 */
|
|
sp_384_mont_mul_15(t2, t1, t2, p384_mod, p384_mp_mod);
|
|
/* T1 = 3T2 */
|
|
sp_384_mont_tpl_15(t1, t2, p384_mod);
|
|
/* Y = 2Y */
|
|
sp_384_mont_dbl_15(y, p->y, p384_mod);
|
|
/* Y = Y * Y */
|
|
sp_384_mont_sqr_15(y, y, p384_mod, p384_mp_mod);
|
|
/* T2 = Y * Y */
|
|
sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod);
|
|
/* T2 = T2/2 */
|
|
sp_384_div2_15(t2, t2, p384_mod);
|
|
/* Y = Y * X */
|
|
sp_384_mont_mul_15(y, y, p->x, p384_mod, p384_mp_mod);
|
|
/* X = T1 * T1 */
|
|
sp_384_mont_sqr_15(x, t1, p384_mod, p384_mp_mod);
|
|
/* X = X - Y */
|
|
sp_384_mont_sub_15(x, x, y, p384_mod);
|
|
/* X = X - Y */
|
|
sp_384_mont_sub_15(x, x, y, p384_mod);
|
|
/* Y = Y - X */
|
|
sp_384_mont_sub_lower_15(y, y, x, p384_mod);
|
|
/* Y = Y * T1 */
|
|
sp_384_mont_mul_15(y, y, t1, p384_mod, p384_mp_mod);
|
|
/* Y = Y - T2 */
|
|
sp_384_mont_sub_15(y, y, t2, p384_mod);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_384_proj_point_dbl_15_ctx {
|
|
int state;
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_384_proj_point_dbl_15_ctx;
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_384_proj_point_dbl_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r, const sp_point_384* p, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_384_proj_point_dbl_15_ctx* ctx = (sp_384_proj_point_dbl_15_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_384_proj_point_dbl_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*15;
|
|
ctx->x = r->x;
|
|
ctx->y = r->y;
|
|
ctx->z = r->z;
|
|
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* T1 = Z * Z */
|
|
sp_384_mont_sqr_15(ctx->t1, p->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
/* Z = Y * Z */
|
|
sp_384_mont_mul_15(ctx->z, p->y, p->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
/* Z = 2Z */
|
|
sp_384_mont_dbl_15(ctx->z, ctx->z, p384_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* T2 = X - T1 */
|
|
sp_384_mont_sub_15(ctx->t2, p->x, ctx->t1, p384_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
/* T1 = X + T1 */
|
|
sp_384_mont_add_15(ctx->t1, p->x, ctx->t1, p384_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
/* T2 = T1 * T2 */
|
|
sp_384_mont_mul_15(ctx->t2, ctx->t1, ctx->t2, p384_mod, p384_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* T1 = 3T2 */
|
|
sp_384_mont_tpl_15(ctx->t1, ctx->t2, p384_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* Y = 2Y */
|
|
sp_384_mont_dbl_15(ctx->y, p->y, p384_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Y = Y * Y */
|
|
sp_384_mont_sqr_15(ctx->y, ctx->y, p384_mod, p384_mp_mod);
|
|
ctx->state = 10;
|
|
break;
|
|
case 10:
|
|
/* T2 = Y * Y */
|
|
sp_384_mont_sqr_15(ctx->t2, ctx->y, p384_mod, p384_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* T2 = T2/2 */
|
|
sp_384_div2_15(ctx->t2, ctx->t2, p384_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* Y = Y * X */
|
|
sp_384_mont_mul_15(ctx->y, ctx->y, p->x, p384_mod, p384_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
/* X = T1 * T1 */
|
|
sp_384_mont_sqr_15(ctx->x, ctx->t1, p384_mod, p384_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
/* X = X - Y */
|
|
sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* X = X - Y */
|
|
sp_384_mont_sub_15(ctx->x, ctx->x, ctx->y, p384_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
/* Y = Y - X */
|
|
sp_384_mont_sub_lower_15(ctx->y, ctx->y, ctx->x, p384_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
/* Y = Y * T1 */
|
|
sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t1, p384_mod, p384_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
/* Y = Y - T2 */
|
|
sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t2, p384_mod);
|
|
ctx->state = 19;
|
|
/* fall-through */
|
|
case 19:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 19) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
/* Compare two numbers to determine if they are equal.
|
|
* Constant time implementation.
|
|
*
|
|
* a First number to compare.
|
|
* b Second number to compare.
|
|
* returns 1 when equal and 0 otherwise.
|
|
*/
|
|
static int sp_384_cmp_equal_15(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
|
|
(a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
|
|
(a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
|
|
(a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
|
|
(a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14])) == 0;
|
|
}
|
|
|
|
/* Returns 1 if the number of zero.
|
|
* Implementation is constant time.
|
|
*
|
|
* a Number to check.
|
|
* returns 1 if the number is zero and 0 otherwise.
|
|
*/
|
|
static int sp_384_iszero_15(const sp_digit* a)
|
|
{
|
|
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
|
|
a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14]) == 0;
|
|
}
|
|
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_proj_point_add_15(sp_point_384* r,
|
|
const sp_point_384* p, const sp_point_384* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*15;
|
|
sp_digit* t3 = t + 4*15;
|
|
sp_digit* t4 = t + 6*15;
|
|
sp_digit* t5 = t + 8*15;
|
|
sp_digit* t6 = t + 10*15;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t1, t1, p->x, p384_mod, p384_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_384_mont_sqr_15(t2, p->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t4, t2, p->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_384_mont_mul_15(t3, t3, p->y, p384_mod, p384_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod);
|
|
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_384_cmp_equal_15(t2, t1) &
|
|
sp_384_cmp_equal_15(t4, t3)) {
|
|
sp_384_proj_point_dbl_15(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t6;
|
|
sp_digit* y = t1;
|
|
sp_digit* z = t2;
|
|
int i;
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
|
|
/* H = U2 - U1 */
|
|
sp_384_mont_sub_15(t2, t2, t1, p384_mod);
|
|
/* R = S2 - S1 */
|
|
sp_384_mont_sub_15(t4, t4, t3, p384_mod);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(y, t1, t5, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_384_mont_mul_15(z, p->z, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(z, z, q->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sqr_15(x, t4, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(x, x, t5, p384_mod);
|
|
sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod);
|
|
sp_384_mont_dbl_15(t3, y, p384_mod);
|
|
sp_384_mont_sub_15(x, x, t3, p384_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_384_mont_sub_lower_15(y, y, x, p384_mod);
|
|
sp_384_mont_mul_15(y, y, t4, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(y, y, t5, p384_mod);
|
|
for (i = 0; i < 15; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_384_proj_point_add_15_ctx {
|
|
int state;
|
|
sp_384_proj_point_dbl_15_ctx dbl_ctx;
|
|
const sp_point_384* ap[2];
|
|
sp_point_384* rp[2];
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* t3;
|
|
sp_digit* t4;
|
|
sp_digit* t5;
|
|
sp_digit* t6;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_384_proj_point_add_15_ctx;
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_384_proj_point_add_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
|
|
const sp_point_384* p, const sp_point_384* q, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_384_proj_point_add_15_ctx* ctx = (sp_384_proj_point_add_15_ctx*)sp_ctx->data;
|
|
|
|
/* Ensure only the first point is the same as the result. */
|
|
if (q == r) {
|
|
const sp_point_384* a = p;
|
|
p = q;
|
|
q = a;
|
|
}
|
|
|
|
typedef char ctx_size_test[sizeof(sp_384_proj_point_add_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*15;
|
|
ctx->t3 = t + 4*15;
|
|
ctx->t4 = t + 6*15;
|
|
ctx->t5 = t + 8*15;
|
|
ctx->t6 = t + 10*15;
|
|
ctx->x = ctx->t6;
|
|
ctx->y = ctx->t1;
|
|
ctx->z = ctx->t2;
|
|
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* U1 = X1*Z2^2 */
|
|
sp_384_mont_sqr_15(ctx->t1, q->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
sp_384_mont_mul_15(ctx->t3, ctx->t1, q->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
sp_384_mont_mul_15(ctx->t1, ctx->t1, p->x, p384_mod, p384_mp_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* U2 = X2*Z1^2 */
|
|
sp_384_mont_sqr_15(ctx->t2, p->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
sp_384_mont_mul_15(ctx->t4, ctx->t2, p->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
sp_384_mont_mul_15(ctx->t2, ctx->t2, q->x, p384_mod, p384_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_384_mont_mul_15(ctx->t3, ctx->t3, p->y, p384_mod, p384_mp_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_384_mont_mul_15(ctx->t4, ctx->t4, q->y, p384_mod, p384_mp_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_384_cmp_equal_15(ctx->t2, ctx->t1) &
|
|
sp_384_cmp_equal_15(ctx->t4, ctx->t3)) {
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
sp_384_proj_point_dbl_15(r, p, t);
|
|
ctx->state = 25;
|
|
}
|
|
else {
|
|
ctx->state = 10;
|
|
}
|
|
break;
|
|
case 10:
|
|
/* H = U2 - U1 */
|
|
sp_384_mont_sub_15(ctx->t2, ctx->t2, ctx->t1, p384_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* R = S2 - S1 */
|
|
sp_384_mont_sub_15(ctx->t4, ctx->t4, ctx->t3, p384_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_384_mont_sqr_15(ctx->t5, ctx->t2, p384_mod, p384_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
sp_384_mont_mul_15(ctx->y, ctx->t1, ctx->t5, p384_mod, p384_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t2, p384_mod, p384_mp_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_384_mont_mul_15(ctx->z, p->z, ctx->t2, p384_mod, p384_mp_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
sp_384_mont_mul_15(ctx->z, ctx->z, q->z, p384_mod, p384_mp_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
sp_384_mont_sqr_15(ctx->x, ctx->t4, p384_mod, p384_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t5, p384_mod);
|
|
ctx->state = 19;
|
|
break;
|
|
case 19:
|
|
sp_384_mont_mul_15(ctx->t5, ctx->t5, ctx->t3, p384_mod, p384_mp_mod);
|
|
ctx->state = 20;
|
|
break;
|
|
case 20:
|
|
sp_384_mont_dbl_15(ctx->t3, ctx->y, p384_mod);
|
|
sp_384_mont_sub_15(ctx->x, ctx->x, ctx->t3, p384_mod);
|
|
ctx->state = 21;
|
|
break;
|
|
case 21:
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_384_mont_sub_lower_15(ctx->y, ctx->y, ctx->x, p384_mod);
|
|
ctx->state = 22;
|
|
break;
|
|
case 22:
|
|
sp_384_mont_mul_15(ctx->y, ctx->y, ctx->t4, p384_mod, p384_mp_mod);
|
|
ctx->state = 23;
|
|
break;
|
|
case 23:
|
|
sp_384_mont_sub_15(ctx->y, ctx->y, ctx->t5, p384_mod);
|
|
ctx->state = 24;
|
|
break;
|
|
case 24:
|
|
{
|
|
int i;
|
|
sp_digit maskp = 0 - (q->infinity & (!p->infinity));
|
|
sp_digit maskq = 0 - (p->infinity & (!q->infinity));
|
|
sp_digit maskt = ~(maskp | maskq);
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (ctx->x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (ctx->y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (ctx->z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
ctx->state = 25;
|
|
break;
|
|
}
|
|
case 25:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 25) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
/* Multiply a number by Montgomery normalizer mod modulus (prime).
|
|
*
|
|
* r The resulting Montgomery form number.
|
|
* a The number to convert.
|
|
* m The modulus (prime).
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_384_mod_mul_norm_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
int64_t* t = NULL;
|
|
#else
|
|
int64_t t[2 * 12];
|
|
#endif
|
|
int64_t* a32 = NULL;
|
|
int64_t o;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 12, NULL, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
a32 = t + 12;
|
|
|
|
a32[0] = a[0];
|
|
a32[0] |= a[1] << 26U;
|
|
a32[0] &= 0xffffffffL;
|
|
a32[1] = (a[1] >> 6);
|
|
a32[1] |= a[2] << 20U;
|
|
a32[1] &= 0xffffffffL;
|
|
a32[2] = (a[2] >> 12);
|
|
a32[2] |= a[3] << 14U;
|
|
a32[2] &= 0xffffffffL;
|
|
a32[3] = (a[3] >> 18);
|
|
a32[3] |= a[4] << 8U;
|
|
a32[3] &= 0xffffffffL;
|
|
a32[4] = (a[4] >> 24);
|
|
a32[4] |= a[5] << 2U;
|
|
a32[4] |= a[6] << 28U;
|
|
a32[4] &= 0xffffffffL;
|
|
a32[5] = (a[6] >> 4);
|
|
a32[5] |= a[7] << 22U;
|
|
a32[5] &= 0xffffffffL;
|
|
a32[6] = (a[7] >> 10);
|
|
a32[6] |= a[8] << 16U;
|
|
a32[6] &= 0xffffffffL;
|
|
a32[7] = (a[8] >> 16);
|
|
a32[7] |= a[9] << 10U;
|
|
a32[7] &= 0xffffffffL;
|
|
a32[8] = (a[9] >> 22);
|
|
a32[8] |= a[10] << 4U;
|
|
a32[8] |= a[11] << 30U;
|
|
a32[8] &= 0xffffffffL;
|
|
a32[9] = (a[11] >> 2);
|
|
a32[9] |= a[12] << 24U;
|
|
a32[9] &= 0xffffffffL;
|
|
a32[10] = (a[12] >> 8);
|
|
a32[10] |= a[13] << 18U;
|
|
a32[10] &= 0xffffffffL;
|
|
a32[11] = (a[13] >> 14);
|
|
a32[11] |= a[14] << 12U;
|
|
a32[11] &= 0xffffffffL;
|
|
|
|
/* 1 0 0 0 0 0 0 0 1 1 0 -1 */
|
|
t[0] = 0 + a32[0] + a32[8] + a32[9] - a32[11];
|
|
/* -1 1 0 0 0 0 0 0 -1 0 1 1 */
|
|
t[1] = 0 - a32[0] + a32[1] - a32[8] + a32[10] + a32[11];
|
|
/* 0 -1 1 0 0 0 0 0 0 -1 0 1 */
|
|
t[2] = 0 - a32[1] + a32[2] - a32[9] + a32[11];
|
|
/* 1 0 -1 1 0 0 0 0 1 1 -1 -1 */
|
|
t[3] = 0 + a32[0] - a32[2] + a32[3] + a32[8] + a32[9] - a32[10] - a32[11];
|
|
/* 1 1 0 -1 1 0 0 0 1 2 1 -2 */
|
|
t[4] = 0 + a32[0] + a32[1] - a32[3] + a32[4] + a32[8] + 2 * a32[9] + a32[10] - 2 * a32[11];
|
|
/* 0 1 1 0 -1 1 0 0 0 1 2 1 */
|
|
t[5] = 0 + a32[1] + a32[2] - a32[4] + a32[5] + a32[9] + 2 * a32[10] + a32[11];
|
|
/* 0 0 1 1 0 -1 1 0 0 0 1 2 */
|
|
t[6] = 0 + a32[2] + a32[3] - a32[5] + a32[6] + a32[10] + 2 * a32[11];
|
|
/* 0 0 0 1 1 0 -1 1 0 0 0 1 */
|
|
t[7] = 0 + a32[3] + a32[4] - a32[6] + a32[7] + a32[11];
|
|
/* 0 0 0 0 1 1 0 -1 1 0 0 0 */
|
|
t[8] = 0 + a32[4] + a32[5] - a32[7] + a32[8];
|
|
/* 0 0 0 0 0 1 1 0 -1 1 0 0 */
|
|
t[9] = 0 + a32[5] + a32[6] - a32[8] + a32[9];
|
|
/* 0 0 0 0 0 0 1 1 0 -1 1 0 */
|
|
t[10] = 0 + a32[6] + a32[7] - a32[9] + a32[10];
|
|
/* 0 0 0 0 0 0 0 1 1 0 -1 1 */
|
|
t[11] = 0 + a32[7] + a32[8] - a32[10] + a32[11];
|
|
|
|
t[1] += t[0] >> 32; t[0] &= 0xffffffff;
|
|
t[2] += t[1] >> 32; t[1] &= 0xffffffff;
|
|
t[3] += t[2] >> 32; t[2] &= 0xffffffff;
|
|
t[4] += t[3] >> 32; t[3] &= 0xffffffff;
|
|
t[5] += t[4] >> 32; t[4] &= 0xffffffff;
|
|
t[6] += t[5] >> 32; t[5] &= 0xffffffff;
|
|
t[7] += t[6] >> 32; t[6] &= 0xffffffff;
|
|
t[8] += t[7] >> 32; t[7] &= 0xffffffff;
|
|
t[9] += t[8] >> 32; t[8] &= 0xffffffff;
|
|
t[10] += t[9] >> 32; t[9] &= 0xffffffff;
|
|
t[11] += t[10] >> 32; t[10] &= 0xffffffff;
|
|
o = t[11] >> 32; t[11] &= 0xffffffff;
|
|
t[0] += o;
|
|
t[1] -= o;
|
|
t[3] += o;
|
|
t[4] += o;
|
|
t[1] += t[0] >> 32; t[0] &= 0xffffffff;
|
|
t[2] += t[1] >> 32; t[1] &= 0xffffffff;
|
|
t[3] += t[2] >> 32; t[2] &= 0xffffffff;
|
|
t[4] += t[3] >> 32; t[3] &= 0xffffffff;
|
|
t[5] += t[4] >> 32; t[4] &= 0xffffffff;
|
|
t[6] += t[5] >> 32; t[5] &= 0xffffffff;
|
|
t[7] += t[6] >> 32; t[6] &= 0xffffffff;
|
|
t[8] += t[7] >> 32; t[7] &= 0xffffffff;
|
|
t[9] += t[8] >> 32; t[8] &= 0xffffffff;
|
|
t[10] += t[9] >> 32; t[9] &= 0xffffffff;
|
|
t[11] += t[10] >> 32; t[10] &= 0xffffffff;
|
|
|
|
r[0] = (sp_digit)(t[0]) & 0x3ffffffL;
|
|
r[1] = (sp_digit)(t[0] >> 26U);
|
|
r[1] |= (sp_digit)(t[1] << 6U);
|
|
r[1] &= 0x3ffffffL;
|
|
r[2] = (sp_digit)(t[1] >> 20U);
|
|
r[2] |= (sp_digit)(t[2] << 12U);
|
|
r[2] &= 0x3ffffffL;
|
|
r[3] = (sp_digit)(t[2] >> 14U);
|
|
r[3] |= (sp_digit)(t[3] << 18U);
|
|
r[3] &= 0x3ffffffL;
|
|
r[4] = (sp_digit)(t[3] >> 8U);
|
|
r[4] |= (sp_digit)(t[4] << 24U);
|
|
r[4] &= 0x3ffffffL;
|
|
r[5] = (sp_digit)(t[4] >> 2U) & 0x3ffffffL;
|
|
r[6] = (sp_digit)(t[4] >> 28U);
|
|
r[6] |= (sp_digit)(t[5] << 4U);
|
|
r[6] &= 0x3ffffffL;
|
|
r[7] = (sp_digit)(t[5] >> 22U);
|
|
r[7] |= (sp_digit)(t[6] << 10U);
|
|
r[7] &= 0x3ffffffL;
|
|
r[8] = (sp_digit)(t[6] >> 16U);
|
|
r[8] |= (sp_digit)(t[7] << 16U);
|
|
r[8] &= 0x3ffffffL;
|
|
r[9] = (sp_digit)(t[7] >> 10U);
|
|
r[9] |= (sp_digit)(t[8] << 22U);
|
|
r[9] &= 0x3ffffffL;
|
|
r[10] = (sp_digit)(t[8] >> 4U) & 0x3ffffffL;
|
|
r[11] = (sp_digit)(t[8] >> 30U);
|
|
r[11] |= (sp_digit)(t[9] << 2U);
|
|
r[11] &= 0x3ffffffL;
|
|
r[12] = (sp_digit)(t[9] >> 24U);
|
|
r[12] |= (sp_digit)(t[10] << 8U);
|
|
r[12] &= 0x3ffffffL;
|
|
r[13] = (sp_digit)(t[10] >> 18U);
|
|
r[13] |= (sp_digit)(t[11] << 14U);
|
|
r[13] &= 0x3ffffffL;
|
|
r[14] = (sp_digit)(t[11] >> 12U);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Small implementation using add and double that is cache attack resistant but
|
|
* allocates memory rather than use large stacks.
|
|
* 384 adds and doubles.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_384 t[3];
|
|
sp_digit tmp[2 * 15 * 6];
|
|
#endif
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
int err = MP_OKAY;
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(t, 0, sizeof(sp_point_384) * 3);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod);
|
|
}
|
|
if (err == MP_OKAY)
|
|
err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod);
|
|
if (err == MP_OKAY)
|
|
err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod);
|
|
|
|
if (err == MP_OKAY) {
|
|
i = 14;
|
|
c = 20;
|
|
n = k[i--] << (26 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1)
|
|
break;
|
|
|
|
n = k[i--];
|
|
c = 26;
|
|
}
|
|
|
|
y = (n >> 25) & 1;
|
|
n <<= 1;
|
|
|
|
sp_384_proj_point_add_15(&t[y^1], &t[0], &t[1], tmp);
|
|
|
|
XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])),
|
|
sizeof(sp_point_384));
|
|
sp_384_proj_point_dbl_15(&t[2], &t[2], tmp);
|
|
XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])), &t[2],
|
|
sizeof(sp_point_384));
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_384_map_15(r, &t[0], tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &t[0], sizeof(sp_point_384));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(tmp, sizeof(sp_digit) * 2 * 15 * 6);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(t, sizeof(sp_point_384) * 3);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_384_ecc_mulmod_15_ctx {
|
|
int state;
|
|
union {
|
|
sp_384_proj_point_dbl_15_ctx dbl_ctx;
|
|
sp_384_proj_point_add_15_ctx add_ctx;
|
|
};
|
|
sp_point_384 t[3];
|
|
sp_digit tmp[2 * 15 * 6];
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
} sp_384_ecc_mulmod_15_ctx;
|
|
|
|
static int sp_384_ecc_mulmod_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
|
|
const sp_point_384* g, const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_384_ecc_mulmod_15_ctx* ctx = (sp_384_ecc_mulmod_15_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_384_ecc_mulmod_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
XMEMSET(ctx->t, 0, sizeof(sp_point_384) * 3);
|
|
ctx->i = 14;
|
|
ctx->c = 20;
|
|
ctx->n = k[ctx->i--] << (26 - ctx->c);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
ctx->t[0].infinity = 1;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* T1X */
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_384_mod_mul_norm_15(ctx->t[1].x, g->x, p384_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* T1Y */
|
|
err = sp_384_mod_mul_norm_15(ctx->t[1].y, g->y, p384_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* T1Z */
|
|
err = sp_384_mod_mul_norm_15(ctx->t[1].z, g->z, p384_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4: /* ADDPREP */
|
|
if (ctx->c == 0) {
|
|
if (ctx->i == -1) {
|
|
ctx->state = 7;
|
|
break;
|
|
}
|
|
|
|
ctx->n = k[ctx->i--];
|
|
ctx->c = 26;
|
|
}
|
|
ctx->y = (ctx->n >> 25) & 1;
|
|
ctx->n <<= 1;
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* ADD */
|
|
err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
|
|
&ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])),
|
|
sizeof(sp_point_384));
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* DBL */
|
|
err = sp_384_proj_point_dbl_15_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
|
|
&ctx->t[2], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
|
|
sizeof(sp_point_384));
|
|
ctx->state = 4;
|
|
ctx->c--;
|
|
}
|
|
break;
|
|
case 7: /* MAP */
|
|
if (map != 0) {
|
|
sp_384_map_15(r, &ctx->t[0], ctx->tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &ctx->t[0], sizeof(sp_point_384));
|
|
}
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 7) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
ForceZero(ctx->tmp, sizeof(ctx->tmp));
|
|
ForceZero(ctx->t, sizeof(ctx->t));
|
|
}
|
|
|
|
(void)heap;
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#else
|
|
/* A table entry for pre-computed points. */
|
|
typedef struct sp_table_entry_384 {
|
|
sp_digit x[15];
|
|
sp_digit y[15];
|
|
} sp_table_entry_384;
|
|
|
|
/* Conditionally copy a into r using the mask m.
|
|
* m is -1 to copy and 0 when not.
|
|
*
|
|
* r A single precision number to copy over.
|
|
* a A single precision number to copy.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_384_cond_copy_15(sp_digit* r, const sp_digit* a, const sp_digit m)
|
|
{
|
|
sp_digit t[15];
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
t[i] = r[i] ^ a[i];
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r[i] ^= t[i] & m;
|
|
}
|
|
#else
|
|
t[ 0] = r[ 0] ^ a[ 0];
|
|
t[ 1] = r[ 1] ^ a[ 1];
|
|
t[ 2] = r[ 2] ^ a[ 2];
|
|
t[ 3] = r[ 3] ^ a[ 3];
|
|
t[ 4] = r[ 4] ^ a[ 4];
|
|
t[ 5] = r[ 5] ^ a[ 5];
|
|
t[ 6] = r[ 6] ^ a[ 6];
|
|
t[ 7] = r[ 7] ^ a[ 7];
|
|
t[ 8] = r[ 8] ^ a[ 8];
|
|
t[ 9] = r[ 9] ^ a[ 9];
|
|
t[10] = r[10] ^ a[10];
|
|
t[11] = r[11] ^ a[11];
|
|
t[12] = r[12] ^ a[12];
|
|
t[13] = r[13] ^ a[13];
|
|
t[14] = r[14] ^ a[14];
|
|
r[ 0] ^= t[ 0] & m;
|
|
r[ 1] ^= t[ 1] & m;
|
|
r[ 2] ^= t[ 2] & m;
|
|
r[ 3] ^= t[ 3] & m;
|
|
r[ 4] ^= t[ 4] & m;
|
|
r[ 5] ^= t[ 5] & m;
|
|
r[ 6] ^= t[ 6] & m;
|
|
r[ 7] ^= t[ 7] & m;
|
|
r[ 8] ^= t[ 8] & m;
|
|
r[ 9] ^= t[ 9] & m;
|
|
r[10] ^= t[10] & m;
|
|
r[11] ^= t[11] & m;
|
|
r[12] ^= t[12] & m;
|
|
r[13] ^= t[13] & m;
|
|
r[14] ^= t[14] & m;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#define sp_384_mont_dbl_lower_15 sp_384_mont_dbl_15
|
|
#define sp_384_mont_tpl_lower_15 sp_384_mont_tpl_15
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_proj_point_dbl_n_15(sp_point_384* p, int i,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*15;
|
|
sp_digit* b = t + 4*15;
|
|
sp_digit* t1 = t + 6*15;
|
|
sp_digit* t2 = t + 8*15;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
volatile int n = i;
|
|
|
|
x = p->x;
|
|
y = p->y;
|
|
z = p->z;
|
|
|
|
/* Y = 2*Y */
|
|
sp_384_mont_dbl_15(y, y, p384_mod);
|
|
/* W = Z^4 */
|
|
sp_384_mont_sqr_15(w, z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sqr_15(w, w, p384_mod, p384_mp_mod);
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
while (--n > 0)
|
|
#else
|
|
while (--n >= 0)
|
|
#endif
|
|
{
|
|
/* A = 3*(X^2 - W) */
|
|
sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(t1, t1, w, p384_mod);
|
|
sp_384_mont_tpl_lower_15(a, t1, p384_mod);
|
|
/* B = X*Y^2 */
|
|
sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod);
|
|
sp_384_mont_dbl_15(t2, b, p384_mod);
|
|
sp_384_mont_sub_15(x, x, t2, p384_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_384_mont_sub_lower_15(t2, b, x, p384_mod);
|
|
sp_384_mont_dbl_lower_15(b, t2, p384_mod);
|
|
/* Z = Z*Y */
|
|
sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
if (n != 0)
|
|
#endif
|
|
{
|
|
/* W = W*Y^4 */
|
|
sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(y, y, t1, p384_mod);
|
|
}
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* A = 3*(X^2 - W) */
|
|
sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(t1, t1, w, p384_mod);
|
|
sp_384_mont_tpl_lower_15(a, t1, p384_mod);
|
|
/* B = X*Y^2 */
|
|
sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod);
|
|
sp_384_mont_dbl_15(t2, b, p384_mod);
|
|
sp_384_mont_sub_15(x, x, t2, p384_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_384_mont_sub_lower_15(t2, b, x, p384_mod);
|
|
sp_384_mont_dbl_lower_15(b, t2, p384_mod);
|
|
/* Z = Z*Y */
|
|
sp_384_mont_mul_15(z, z, y, p384_mod, p384_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod);
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(y, y, t1, p384_mod);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Y = Y/2 */
|
|
sp_384_div2_15(y, y, p384_mod);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_proj_point_dbl_n_store_15(sp_point_384* r,
|
|
const sp_point_384* p, int n, int m, sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*15;
|
|
sp_digit* b = t + 4*15;
|
|
sp_digit* t1 = t + 6*15;
|
|
sp_digit* t2 = t + 8*15;
|
|
sp_digit* x = r[2*m].x;
|
|
sp_digit* y = r[(1<<n)*m].y;
|
|
sp_digit* z = r[2*m].z;
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0; i<15; i++) {
|
|
x[i] = p->x[i];
|
|
}
|
|
for (i=0; i<15; i++) {
|
|
y[i] = p->y[i];
|
|
}
|
|
for (i=0; i<15; i++) {
|
|
z[i] = p->z[i];
|
|
}
|
|
|
|
/* Y = 2*Y */
|
|
sp_384_mont_dbl_15(y, y, p384_mod);
|
|
/* W = Z^4 */
|
|
sp_384_mont_sqr_15(w, z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sqr_15(w, w, p384_mod, p384_mp_mod);
|
|
j = m;
|
|
for (i=1; i<=n; i++) {
|
|
j *= 2;
|
|
|
|
/* A = 3*(X^2 - W) */
|
|
sp_384_mont_sqr_15(t1, x, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(t1, t1, w, p384_mod);
|
|
sp_384_mont_tpl_lower_15(a, t1, p384_mod);
|
|
/* B = X*Y^2 */
|
|
sp_384_mont_sqr_15(t1, y, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(b, t1, x, p384_mod, p384_mp_mod);
|
|
x = r[j].x;
|
|
/* X = A^2 - 2B */
|
|
sp_384_mont_sqr_15(x, a, p384_mod, p384_mp_mod);
|
|
sp_384_mont_dbl_15(t2, b, p384_mod);
|
|
sp_384_mont_sub_15(x, x, t2, p384_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_384_mont_sub_lower_15(t2, b, x, p384_mod);
|
|
sp_384_mont_dbl_lower_15(b, t2, p384_mod);
|
|
/* Z = Z*Y */
|
|
sp_384_mont_mul_15(r[j].z, z, y, p384_mod, p384_mp_mod);
|
|
z = r[j].z;
|
|
/* t1 = Y^4 */
|
|
sp_384_mont_sqr_15(t1, t1, p384_mod, p384_mp_mod);
|
|
if (i != n) {
|
|
/* W = W*Y^4 */
|
|
sp_384_mont_mul_15(w, w, t1, p384_mod, p384_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_384_mont_mul_15(y, b, a, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(y, y, t1, p384_mod);
|
|
/* Y = Y/2 */
|
|
sp_384_div2_15(r[j].y, y, p384_mod);
|
|
r[j].infinity = 0;
|
|
}
|
|
}
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* ra Result of addition.
|
|
* rs Result of subtraction.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_proj_point_add_sub_15(sp_point_384* ra,
|
|
sp_point_384* rs, const sp_point_384* p, const sp_point_384* q,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*15;
|
|
sp_digit* t3 = t + 4*15;
|
|
sp_digit* t4 = t + 6*15;
|
|
sp_digit* t5 = t + 8*15;
|
|
sp_digit* t6 = t + 10*15;
|
|
sp_digit* xa = ra->x;
|
|
sp_digit* ya = ra->y;
|
|
sp_digit* za = ra->z;
|
|
sp_digit* xs = rs->x;
|
|
sp_digit* ys = rs->y;
|
|
sp_digit* zs = rs->z;
|
|
|
|
|
|
XMEMCPY(xa, p->x, sizeof(p->x) / 2);
|
|
XMEMCPY(ya, p->y, sizeof(p->y) / 2);
|
|
XMEMCPY(za, p->z, sizeof(p->z) / 2);
|
|
ra->infinity = 0;
|
|
rs->infinity = 0;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_384_mont_sqr_15(t1, q->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t3, t1, q->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t1, t1, xa, p384_mod, p384_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_384_mont_sqr_15(t2, za, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t4, t2, za, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_384_mont_mul_15(t3, t3, ya, p384_mod, p384_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod);
|
|
/* H = U2 - U1 */
|
|
sp_384_mont_sub_15(t2, t2, t1, p384_mod);
|
|
/* RS = S2 + S1 */
|
|
sp_384_mont_add_15(t6, t4, t3, p384_mod);
|
|
/* R = S2 - S1 */
|
|
sp_384_mont_sub_15(t4, t4, t3, p384_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
/* ZS = H*Z1*Z2 */
|
|
sp_384_mont_mul_15(za, za, q->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(za, za, t2, p384_mod, p384_mp_mod);
|
|
XMEMCPY(zs, za, sizeof(p->z)/2);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
/* XS = RS^2 - H^3 - 2*U1*H^2 */
|
|
sp_384_mont_sqr_15(xa, t4, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sqr_15(xs, t6, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(ya, t1, t5, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(xa, xa, t5, p384_mod);
|
|
sp_384_mont_sub_15(xs, xs, t5, p384_mod);
|
|
sp_384_mont_dbl_15(t1, ya, p384_mod);
|
|
sp_384_mont_sub_15(xa, xa, t1, p384_mod);
|
|
sp_384_mont_sub_15(xs, xs, t1, p384_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
/* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
|
|
sp_384_mont_sub_lower_15(ys, ya, xs, p384_mod);
|
|
sp_384_mont_sub_lower_15(ya, ya, xa, p384_mod);
|
|
sp_384_mont_mul_15(ya, ya, t4, p384_mod, p384_mp_mod);
|
|
sp_384_sub_15(t6, p384_mod, t6);
|
|
sp_384_mont_mul_15(ys, ys, t6, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t5, t5, t3, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(ya, ya, t5, p384_mod);
|
|
sp_384_mont_sub_15(ys, ys, t5, p384_mod);
|
|
}
|
|
|
|
/* Structure used to describe recoding of scalar multiplication. */
|
|
typedef struct ecc_recode_384 {
|
|
/* Index into pre-computation table. */
|
|
uint8_t i;
|
|
/* Use the negative of the point. */
|
|
uint8_t neg;
|
|
} ecc_recode_384;
|
|
|
|
/* The index into pre-computation table to use. */
|
|
static const uint8_t recode_index_15_6[66] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
|
|
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
|
0, 1,
|
|
};
|
|
|
|
/* Whether to negate y-ordinate. */
|
|
static const uint8_t recode_neg_15_6[66] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 0,
|
|
};
|
|
|
|
/* Recode the scalar for multiplication using pre-computed values and
|
|
* subtraction.
|
|
*
|
|
* k Scalar to multiply by.
|
|
* v Vector of operations to perform.
|
|
*/
|
|
static void sp_384_ecc_recode_6_15(const sp_digit* k, ecc_recode_384* v)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint8_t y;
|
|
int carry = 0;
|
|
int o;
|
|
sp_digit n;
|
|
|
|
j = 0;
|
|
n = k[j];
|
|
o = 0;
|
|
for (i=0; i<65; i++) {
|
|
y = (int8_t)n;
|
|
if (o + 6 < 26) {
|
|
y &= 0x3f;
|
|
n >>= 6;
|
|
o += 6;
|
|
}
|
|
else if (o + 6 == 26) {
|
|
n >>= 6;
|
|
if (++j < 15)
|
|
n = k[j];
|
|
o = 0;
|
|
}
|
|
else if (++j < 15) {
|
|
n = k[j];
|
|
y |= (uint8_t)((n << (26 - o)) & 0x3f);
|
|
o -= 20;
|
|
n >>= o;
|
|
}
|
|
|
|
y += (uint8_t)carry;
|
|
v[i].i = recode_index_15_6[y];
|
|
v[i].neg = recode_neg_15_6[y];
|
|
carry = (y >> 6) + v[i].neg;
|
|
}
|
|
}
|
|
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
/* Touch each possible point that could be being copied.
|
|
*
|
|
* r Point to copy into.
|
|
* table Table - start of the entires to access
|
|
* idx Index of entry to retrieve.
|
|
*/
|
|
static void sp_384_get_point_33_15(sp_point_384* r, const sp_point_384* table,
|
|
int idx)
|
|
{
|
|
int i;
|
|
sp_digit mask;
|
|
|
|
r->x[0] = 0;
|
|
r->x[1] = 0;
|
|
r->x[2] = 0;
|
|
r->x[3] = 0;
|
|
r->x[4] = 0;
|
|
r->x[5] = 0;
|
|
r->x[6] = 0;
|
|
r->x[7] = 0;
|
|
r->x[8] = 0;
|
|
r->x[9] = 0;
|
|
r->x[10] = 0;
|
|
r->x[11] = 0;
|
|
r->x[12] = 0;
|
|
r->x[13] = 0;
|
|
r->x[14] = 0;
|
|
r->y[0] = 0;
|
|
r->y[1] = 0;
|
|
r->y[2] = 0;
|
|
r->y[3] = 0;
|
|
r->y[4] = 0;
|
|
r->y[5] = 0;
|
|
r->y[6] = 0;
|
|
r->y[7] = 0;
|
|
r->y[8] = 0;
|
|
r->y[9] = 0;
|
|
r->y[10] = 0;
|
|
r->y[11] = 0;
|
|
r->y[12] = 0;
|
|
r->y[13] = 0;
|
|
r->y[14] = 0;
|
|
r->z[0] = 0;
|
|
r->z[1] = 0;
|
|
r->z[2] = 0;
|
|
r->z[3] = 0;
|
|
r->z[4] = 0;
|
|
r->z[5] = 0;
|
|
r->z[6] = 0;
|
|
r->z[7] = 0;
|
|
r->z[8] = 0;
|
|
r->z[9] = 0;
|
|
r->z[10] = 0;
|
|
r->z[11] = 0;
|
|
r->z[12] = 0;
|
|
r->z[13] = 0;
|
|
r->z[14] = 0;
|
|
for (i = 1; i < 33; i++) {
|
|
mask = 0 - (i == idx);
|
|
r->x[0] |= mask & table[i].x[0];
|
|
r->x[1] |= mask & table[i].x[1];
|
|
r->x[2] |= mask & table[i].x[2];
|
|
r->x[3] |= mask & table[i].x[3];
|
|
r->x[4] |= mask & table[i].x[4];
|
|
r->x[5] |= mask & table[i].x[5];
|
|
r->x[6] |= mask & table[i].x[6];
|
|
r->x[7] |= mask & table[i].x[7];
|
|
r->x[8] |= mask & table[i].x[8];
|
|
r->x[9] |= mask & table[i].x[9];
|
|
r->x[10] |= mask & table[i].x[10];
|
|
r->x[11] |= mask & table[i].x[11];
|
|
r->x[12] |= mask & table[i].x[12];
|
|
r->x[13] |= mask & table[i].x[13];
|
|
r->x[14] |= mask & table[i].x[14];
|
|
r->y[0] |= mask & table[i].y[0];
|
|
r->y[1] |= mask & table[i].y[1];
|
|
r->y[2] |= mask & table[i].y[2];
|
|
r->y[3] |= mask & table[i].y[3];
|
|
r->y[4] |= mask & table[i].y[4];
|
|
r->y[5] |= mask & table[i].y[5];
|
|
r->y[6] |= mask & table[i].y[6];
|
|
r->y[7] |= mask & table[i].y[7];
|
|
r->y[8] |= mask & table[i].y[8];
|
|
r->y[9] |= mask & table[i].y[9];
|
|
r->y[10] |= mask & table[i].y[10];
|
|
r->y[11] |= mask & table[i].y[11];
|
|
r->y[12] |= mask & table[i].y[12];
|
|
r->y[13] |= mask & table[i].y[13];
|
|
r->y[14] |= mask & table[i].y[14];
|
|
r->z[0] |= mask & table[i].z[0];
|
|
r->z[1] |= mask & table[i].z[1];
|
|
r->z[2] |= mask & table[i].z[2];
|
|
r->z[3] |= mask & table[i].z[3];
|
|
r->z[4] |= mask & table[i].z[4];
|
|
r->z[5] |= mask & table[i].z[5];
|
|
r->z[6] |= mask & table[i].z[6];
|
|
r->z[7] |= mask & table[i].z[7];
|
|
r->z[8] |= mask & table[i].z[8];
|
|
r->z[9] |= mask & table[i].z[9];
|
|
r->z[10] |= mask & table[i].z[10];
|
|
r->z[11] |= mask & table[i].z[11];
|
|
r->z[12] |= mask & table[i].z[12];
|
|
r->z[13] |= mask & table[i].z[13];
|
|
r->z[14] |= mask & table[i].z[14];
|
|
}
|
|
}
|
|
#endif /* !WC_NO_CACHE_RESISTANT */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Window technique of 6 bits. (Add-Sub variation.)
|
|
* Calculate 0..32 times the point. Use function that adds and
|
|
* subtracts the same two points.
|
|
* Recode to add or subtract one of the computed points.
|
|
* Double to push up.
|
|
* NOT a sliding window.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_mulmod_win_add_sub_15(sp_point_384* r, const sp_point_384* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_384 t[33+2];
|
|
sp_digit tmp[2 * 15 * 6];
|
|
#endif
|
|
sp_point_384* rt = NULL;
|
|
sp_point_384* p = NULL;
|
|
sp_digit* negy;
|
|
int i;
|
|
ecc_recode_384 v[65];
|
|
int err = MP_OKAY;
|
|
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) *
|
|
(33+2), heap, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6,
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
rt = t + 33;
|
|
p = t + 33+1;
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
XMEMSET(&t[0], 0, sizeof(t[0]));
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_384_mod_mul_norm_15(t[1].x, g->x, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_mod_mul_norm_15(t[1].y, g->y, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_mod_mul_norm_15(t[1].z, g->z, p384_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
t[1].infinity = 0;
|
|
/* t[2] ... t[32] */
|
|
sp_384_proj_point_dbl_n_store_15(t, &t[ 1], 5, 1, tmp);
|
|
sp_384_proj_point_add_15(&t[ 3], &t[ 2], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[ 6], &t[ 3], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[10], &t[ 5], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[12], &t[ 6], tmp);
|
|
sp_384_proj_point_dbl_15(&t[14], &t[ 7], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[15], &t[13], &t[14], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[18], &t[ 9], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[19], &t[17], &t[18], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[20], &t[10], tmp);
|
|
sp_384_proj_point_dbl_15(&t[22], &t[11], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[23], &t[21], &t[22], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[24], &t[12], tmp);
|
|
sp_384_proj_point_dbl_15(&t[26], &t[13], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[27], &t[25], &t[26], &t[ 1], tmp);
|
|
sp_384_proj_point_dbl_15(&t[28], &t[14], tmp);
|
|
sp_384_proj_point_dbl_15(&t[30], &t[15], tmp);
|
|
sp_384_proj_point_add_sub_15(&t[31], &t[29], &t[30], &t[ 1], tmp);
|
|
|
|
negy = t[0].y;
|
|
|
|
sp_384_ecc_recode_6_15(k, v);
|
|
|
|
i = 64;
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_384_get_point_33_15(rt, t, v[i].i);
|
|
rt->infinity = !v[i].i;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_384));
|
|
}
|
|
for (--i; i>=0; i--) {
|
|
sp_384_proj_point_dbl_n_15(rt, 6, tmp);
|
|
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_384_get_point_33_15(p, t, v[i].i);
|
|
p->infinity = !v[i].i;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(p, &t[v[i].i], sizeof(sp_point_384));
|
|
}
|
|
sp_384_sub_15(negy, p384_mod, p->y);
|
|
sp_384_norm_15(negy);
|
|
sp_384_cond_copy_15(p->y, negy, (sp_digit)0 - v[i].neg);
|
|
sp_384_proj_point_add_15(rt, rt, p, tmp);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_384_map_15(r, rt, tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_384));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp != NULL)
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#endif /* FP_ECC */
|
|
/* Add two Montgomery form projective points. The second point has a q value of
|
|
* one.
|
|
* Only the first point can be the same pointer as the result point.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_384_proj_point_add_qz1_15(sp_point_384* r,
|
|
const sp_point_384* p, const sp_point_384* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*15;
|
|
sp_digit* t3 = t + 4*15;
|
|
sp_digit* t4 = t + 6*15;
|
|
sp_digit* t5 = t + 8*15;
|
|
sp_digit* t6 = t + 10*15;
|
|
|
|
/* Calculate values to subtract from P->x and P->y. */
|
|
/* U2 = X2*Z1^2 */
|
|
sp_384_mont_sqr_15(t2, p->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t4, t2, p->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t2, t2, q->x, p384_mod, p384_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_384_mont_mul_15(t4, t4, q->y, p384_mod, p384_mp_mod);
|
|
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_384_cmp_equal_15(p->x, t2) &
|
|
sp_384_cmp_equal_15(p->y, t4)) {
|
|
sp_384_proj_point_dbl_15(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t2;
|
|
sp_digit* y = t5;
|
|
sp_digit* z = t6;
|
|
int i;
|
|
|
|
/* H = U2 - X1 */
|
|
sp_384_mont_sub_15(t2, t2, p->x, p384_mod);
|
|
/* R = S2 - Y1 */
|
|
sp_384_mont_sub_15(t4, t4, p->y, p384_mod);
|
|
/* Z3 = H*Z1 */
|
|
sp_384_mont_mul_15(z, p->z, t2, p384_mod, p384_mp_mod);
|
|
/* X3 = R^2 - H^3 - 2*X1*H^2 */
|
|
sp_384_mont_sqr_15(t1, t4, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sqr_15(t5, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t3, p->x, t5, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t5, t5, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(x, t1, t5, p384_mod);
|
|
sp_384_mont_dbl_15(t1, t3, p384_mod);
|
|
sp_384_mont_sub_15(x, x, t1, p384_mod);
|
|
/* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
|
|
sp_384_mont_sub_lower_15(t3, t3, x, p384_mod);
|
|
sp_384_mont_mul_15(t3, t3, t4, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t5, t5, p->y, p384_mod, p384_mp_mod);
|
|
sp_384_mont_sub_15(y, t3, t5, p384_mod);
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
for (i = 0; i < 15; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
/* Convert the projective point to affine.
|
|
* Ordinates are in Montgomery form.
|
|
*
|
|
* a Point to convert.
|
|
* t Temporary data.
|
|
*/
|
|
static void sp_384_proj_to_affine_15(sp_point_384* a, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 15;
|
|
sp_digit* tmp = t + 4 * 15;
|
|
|
|
sp_384_mont_inv_15(t1, a->z, tmp);
|
|
|
|
sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(t1, t2, t1, p384_mod, p384_mp_mod);
|
|
|
|
sp_384_mont_mul_15(a->x, a->x, t2, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(a->y, a->y, t1, p384_mod, p384_mp_mod);
|
|
XMEMCPY(a->z, p384_norm_mod, sizeof(p384_norm_mod));
|
|
}
|
|
|
|
/* Generate the pre-computed table of points for the base point.
|
|
*
|
|
* width = 8
|
|
* 256 entries
|
|
* 48 bits between
|
|
*
|
|
* a The base point.
|
|
* table Place to store generated point data.
|
|
* tmp Temporary data.
|
|
* heap Heap to use for allocation.
|
|
*/
|
|
static int sp_384_gen_stripe_table_15(const sp_point_384* a,
|
|
sp_table_entry_384* table, sp_digit* tmp, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* t = NULL;
|
|
#else
|
|
sp_point_384 t[3];
|
|
#endif
|
|
sp_point_384* s1 = NULL;
|
|
sp_point_384* s2 = NULL;
|
|
int i;
|
|
int j;
|
|
int err = MP_OKAY;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
s1 = t + 1;
|
|
s2 = t + 2;
|
|
|
|
err = sp_384_mod_mul_norm_15(t->x, a->x, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_mod_mul_norm_15(t->y, a->y, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_mod_mul_norm_15(t->z, a->z, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
t->infinity = 0;
|
|
sp_384_proj_to_affine_15(t, tmp);
|
|
|
|
XMEMCPY(s1->z, p384_norm_mod, sizeof(p384_norm_mod));
|
|
s1->infinity = 0;
|
|
XMEMCPY(s2->z, p384_norm_mod, sizeof(p384_norm_mod));
|
|
s2->infinity = 0;
|
|
|
|
/* table[0] = {0, 0, infinity} */
|
|
XMEMSET(&table[0], 0, sizeof(sp_table_entry_384));
|
|
/* table[1] = Affine version of 'a' in Montgomery form */
|
|
XMEMCPY(table[1].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1].y, t->y, sizeof(table->y));
|
|
|
|
for (i=1; i<8; i++) {
|
|
sp_384_proj_point_dbl_n_15(t, 48, tmp);
|
|
sp_384_proj_to_affine_15(t, tmp);
|
|
XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
|
|
}
|
|
|
|
for (i=1; i<8; i++) {
|
|
XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
|
|
XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
|
|
for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
|
|
XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
|
|
XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
|
|
sp_384_proj_point_add_qz1_15(t, s1, s2, tmp);
|
|
sp_384_proj_to_affine_15(t, tmp);
|
|
XMEMCPY(table[j].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[j].y, t->y, sizeof(table->y));
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* FP_ECC */
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
/* Touch each possible entry that could be being copied.
|
|
*
|
|
* r Point to copy into.
|
|
* table Table - start of the entires to access
|
|
* idx Index of entry to retrieve.
|
|
*/
|
|
static void sp_384_get_entry_256_15(sp_point_384* r,
|
|
const sp_table_entry_384* table, int idx)
|
|
{
|
|
int i;
|
|
sp_digit mask;
|
|
|
|
r->x[0] = 0;
|
|
r->x[1] = 0;
|
|
r->x[2] = 0;
|
|
r->x[3] = 0;
|
|
r->x[4] = 0;
|
|
r->x[5] = 0;
|
|
r->x[6] = 0;
|
|
r->x[7] = 0;
|
|
r->x[8] = 0;
|
|
r->x[9] = 0;
|
|
r->x[10] = 0;
|
|
r->x[11] = 0;
|
|
r->x[12] = 0;
|
|
r->x[13] = 0;
|
|
r->x[14] = 0;
|
|
r->y[0] = 0;
|
|
r->y[1] = 0;
|
|
r->y[2] = 0;
|
|
r->y[3] = 0;
|
|
r->y[4] = 0;
|
|
r->y[5] = 0;
|
|
r->y[6] = 0;
|
|
r->y[7] = 0;
|
|
r->y[8] = 0;
|
|
r->y[9] = 0;
|
|
r->y[10] = 0;
|
|
r->y[11] = 0;
|
|
r->y[12] = 0;
|
|
r->y[13] = 0;
|
|
r->y[14] = 0;
|
|
for (i = 1; i < 256; i++) {
|
|
mask = 0 - (i == idx);
|
|
r->x[0] |= mask & table[i].x[0];
|
|
r->x[1] |= mask & table[i].x[1];
|
|
r->x[2] |= mask & table[i].x[2];
|
|
r->x[3] |= mask & table[i].x[3];
|
|
r->x[4] |= mask & table[i].x[4];
|
|
r->x[5] |= mask & table[i].x[5];
|
|
r->x[6] |= mask & table[i].x[6];
|
|
r->x[7] |= mask & table[i].x[7];
|
|
r->x[8] |= mask & table[i].x[8];
|
|
r->x[9] |= mask & table[i].x[9];
|
|
r->x[10] |= mask & table[i].x[10];
|
|
r->x[11] |= mask & table[i].x[11];
|
|
r->x[12] |= mask & table[i].x[12];
|
|
r->x[13] |= mask & table[i].x[13];
|
|
r->x[14] |= mask & table[i].x[14];
|
|
r->y[0] |= mask & table[i].y[0];
|
|
r->y[1] |= mask & table[i].y[1];
|
|
r->y[2] |= mask & table[i].y[2];
|
|
r->y[3] |= mask & table[i].y[3];
|
|
r->y[4] |= mask & table[i].y[4];
|
|
r->y[5] |= mask & table[i].y[5];
|
|
r->y[6] |= mask & table[i].y[6];
|
|
r->y[7] |= mask & table[i].y[7];
|
|
r->y[8] |= mask & table[i].y[8];
|
|
r->y[9] |= mask & table[i].y[9];
|
|
r->y[10] |= mask & table[i].y[10];
|
|
r->y[11] |= mask & table[i].y[11];
|
|
r->y[12] |= mask & table[i].y[12];
|
|
r->y[13] |= mask & table[i].y[13];
|
|
r->y[14] |= mask & table[i].y[14];
|
|
}
|
|
}
|
|
#endif /* !WC_NO_CACHE_RESISTANT */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^48, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* table Pre-computed table.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_mulmod_stripe_15(sp_point_384* r, const sp_point_384* g,
|
|
const sp_table_entry_384* table, const sp_digit* k, int map,
|
|
int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* rt = NULL;
|
|
sp_digit* t = NULL;
|
|
#else
|
|
sp_point_384 rt[2];
|
|
sp_digit t[2 * 15 * 6];
|
|
#endif
|
|
sp_point_384* p = NULL;
|
|
int i;
|
|
int j;
|
|
int y;
|
|
int x;
|
|
int err = MP_OKAY;
|
|
|
|
(void)g;
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
rt = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (rt == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = rt + 1;
|
|
|
|
XMEMCPY(p->z, p384_norm_mod, sizeof(p384_norm_mod));
|
|
XMEMCPY(rt->z, p384_norm_mod, sizeof(p384_norm_mod));
|
|
|
|
y = 0;
|
|
x = 47;
|
|
for (j=0; j<8; j++) {
|
|
y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j);
|
|
x += 48;
|
|
}
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_384_get_entry_256_15(rt, table, y);
|
|
} else
|
|
#endif
|
|
{
|
|
XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
|
|
}
|
|
rt->infinity = !y;
|
|
for (i=46; i>=0; i--) {
|
|
y = 0;
|
|
x = i;
|
|
for (j=0; j<8; j++) {
|
|
y |= (int)(((k[x / 26] >> (x % 26)) & 1) << j);
|
|
x += 48;
|
|
}
|
|
|
|
sp_384_proj_point_dbl_15(rt, rt, t);
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_384_get_entry_256_15(p, table, y);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
|
|
}
|
|
p->infinity = !y;
|
|
sp_384_proj_point_add_qz1_15(rt, rt, p, t);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_384_map_15(r, rt, t);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_384));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (rt != NULL)
|
|
XFREE(rt, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#ifndef FP_ENTRIES
|
|
#define FP_ENTRIES 16
|
|
#endif
|
|
|
|
/* Cache entry - holds precomputation tables for a point. */
|
|
typedef struct sp_cache_384_t {
|
|
/* X ordinate of point that table was generated from. */
|
|
sp_digit x[15];
|
|
/* Y ordinate of point that table was generated from. */
|
|
sp_digit y[15];
|
|
/* Precomputation table for point. */
|
|
sp_table_entry_384 table[256];
|
|
/* Count of entries in table. */
|
|
uint32_t cnt;
|
|
/* Point and table set in entry. */
|
|
int set;
|
|
} sp_cache_384_t;
|
|
|
|
/* Cache of tables. */
|
|
static THREAD_LS_T sp_cache_384_t sp_cache_384[FP_ENTRIES];
|
|
/* Index of last entry in cache. */
|
|
static THREAD_LS_T int sp_cache_384_last = -1;
|
|
/* Cache has been initialized. */
|
|
static THREAD_LS_T int sp_cache_384_inited = 0;
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
static volatile int initCacheMutex_384 = 0;
|
|
static wolfSSL_Mutex sp_cache_384_lock;
|
|
#endif
|
|
|
|
/* Get the cache entry for the point.
|
|
*
|
|
* g [in] Point scalar multipling.
|
|
* cache [out] Cache table to use.
|
|
*/
|
|
static void sp_ecc_get_cache_384(const sp_point_384* g, sp_cache_384_t** cache)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint32_t least;
|
|
|
|
if (sp_cache_384_inited == 0) {
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
sp_cache_384[i].set = 0;
|
|
}
|
|
sp_cache_384_inited = 1;
|
|
}
|
|
|
|
/* Compare point with those in cache. */
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
if (!sp_cache_384[i].set)
|
|
continue;
|
|
|
|
if (sp_384_cmp_equal_15(g->x, sp_cache_384[i].x) &
|
|
sp_384_cmp_equal_15(g->y, sp_cache_384[i].y)) {
|
|
sp_cache_384[i].cnt++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* No match. */
|
|
if (i == FP_ENTRIES) {
|
|
/* Find empty entry. */
|
|
i = (sp_cache_384_last + 1) % FP_ENTRIES;
|
|
for (; i != sp_cache_384_last; i=(i+1)%FP_ENTRIES) {
|
|
if (!sp_cache_384[i].set) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Evict least used. */
|
|
if (i == sp_cache_384_last) {
|
|
least = sp_cache_384[0].cnt;
|
|
for (j=1; j<FP_ENTRIES; j++) {
|
|
if (sp_cache_384[j].cnt < least) {
|
|
i = j;
|
|
least = sp_cache_384[i].cnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
XMEMCPY(sp_cache_384[i].x, g->x, sizeof(sp_cache_384[i].x));
|
|
XMEMCPY(sp_cache_384[i].y, g->y, sizeof(sp_cache_384[i].y));
|
|
sp_cache_384[i].set = 1;
|
|
sp_cache_384[i].cnt = 1;
|
|
}
|
|
|
|
*cache = &sp_cache_384[i];
|
|
sp_cache_384_last = i;
|
|
}
|
|
#endif /* FP_ECC */
|
|
|
|
/* Multiply the base point of P384 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_mulmod_15(sp_point_384* r, const sp_point_384* g, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
#ifndef FP_ECC
|
|
return sp_384_ecc_mulmod_win_add_sub_15(r, g, k, map, ct, heap);
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp;
|
|
#else
|
|
sp_digit tmp[2 * 15 * 7];
|
|
#endif
|
|
sp_cache_384_t* cache;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 7, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
#ifndef HAVE_THREAD_LS
|
|
if (err == MP_OKAY) {
|
|
if (initCacheMutex_384 == 0) {
|
|
wc_InitMutex(&sp_cache_384_lock);
|
|
initCacheMutex_384 = 1;
|
|
}
|
|
if (wc_LockMutex(&sp_cache_384_lock) != 0) {
|
|
err = BAD_MUTEX_E;
|
|
}
|
|
}
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_ecc_get_cache_384(g, &cache);
|
|
if (cache->cnt == 2)
|
|
sp_384_gen_stripe_table_15(g, cache->table, tmp, heap);
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
wc_UnLockMutex(&sp_cache_384_lock);
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (cache->cnt < 2) {
|
|
err = sp_384_ecc_mulmod_win_add_sub_15(r, g, k, map, ct, heap);
|
|
}
|
|
else {
|
|
err = sp_384_ecc_mulmod_stripe_15(r, g, cache->table, k,
|
|
map, ct, heap);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_384(const mp_int* km, const ecc_point* gm, ecc_point* r,
|
|
int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_384 point[1];
|
|
sp_digit k[15];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_384_from_mp(k, 15, km);
|
|
sp_384_point_from_ecc_point_15(point, gm);
|
|
|
|
err = sp_384_ecc_mulmod_15(point, point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_point_to_ecc_point_15(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the point by the scalar, add point a and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_add_384(const mp_int* km, const ecc_point* gm,
|
|
const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_384 point[2];
|
|
sp_digit k[15 + 15 * 2 * 6];
|
|
#endif
|
|
sp_point_384* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (15 + 15 * 2 * 6), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 15;
|
|
|
|
sp_384_from_mp(k, 15, km);
|
|
sp_384_point_from_ecc_point_15(point, gm);
|
|
sp_384_point_from_ecc_point_15(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_384_mod_mul_norm_15(addP->x, addP->x, p384_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_384_mod_mul_norm_15(addP->y, addP->y, p384_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_384_mod_mul_norm_15(addP->z, addP->z, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_ecc_mulmod_15(point, point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_384_proj_point_add_15(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_384_map_15(point, point, tmp);
|
|
}
|
|
|
|
err = sp_384_point_to_ecc_point_15(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the base point of P384 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_384_ecc_mulmod_15(r, &p384_base, k, map, ct, heap);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
static int sp_384_ecc_mulmod_base_15_nb(sp_ecc_ctx_t* sp_ctx, sp_point_384* r,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_384_ecc_mulmod_15_nb(sp_ctx, r, &p384_base, k, map, ct, heap);
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
|
|
#else
|
|
/* Striping precomputation table.
|
|
* 8 points combined into a table of 256 points.
|
|
* Distance of 48 between points.
|
|
*/
|
|
static const sp_table_entry_384 p384_table[256] = {
|
|
/* 0 */
|
|
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00 },
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00 } },
|
|
/* 1 */
|
|
{ { 0x1c0b528,0x01d5992,0x0e383dd,0x38a835b,0x220e378,0x106d35b,
|
|
0x1c3afc5,0x03bfe1e,0x28459a3,0x2d91521,0x214ede2,0x0bfdc8d,
|
|
0x2151381,0x3708a67,0x004d3aa },
|
|
{ 0x303a4fe,0x10f6b52,0x29ac230,0x2fdeed2,0x0a1bfa8,0x3a0ec14,
|
|
0x2de7562,0x3ff662e,0x21968f4,0x031b0d4,0x3969a84,0x2000898,
|
|
0x1c5e9dd,0x2f09685,0x002b78a } },
|
|
/* 2 */
|
|
{ { 0x30c535b,0x191d4ca,0x2296298,0x14dc141,0x090dd69,0x05aae6b,
|
|
0x0cd6b42,0x35da80e,0x3b7be12,0x2cf7e6d,0x1f347bd,0x3d365e1,
|
|
0x1448913,0x32704fa,0x00222c5 },
|
|
{ 0x280dc64,0x39e5bc9,0x24175f8,0x2dd60d4,0x0120e7c,0x041d02e,
|
|
0x0b5d8ad,0x37b9895,0x2fb5337,0x1f0e2e3,0x14f0224,0x2230b86,
|
|
0x1bc4cf6,0x17cdb09,0x007b5c7 } },
|
|
/* 3 */
|
|
{ { 0x2dffea5,0x28f30e7,0x29fce26,0x070df5f,0x235bbfd,0x2f78fbd,
|
|
0x27700d9,0x23d6bc3,0x3471a53,0x0c0e03a,0x05bf9eb,0x276a2ec,
|
|
0x20c3e2e,0x31cc691,0x00dbb93 },
|
|
{ 0x126b605,0x2e8983d,0x153737d,0x23bf5e1,0x295d497,0x35ca812,
|
|
0x2d793ae,0x16c6893,0x3777600,0x089a520,0x1e681f8,0x3d55ee6,
|
|
0x154ef99,0x155f592,0x00ae5f9 } },
|
|
/* 4 */
|
|
{ { 0x26feef9,0x20315fc,0x1240244,0x250e838,0x3c31a26,0x1cf8af1,
|
|
0x1002c32,0x3b531cd,0x1c53ef1,0x22310ba,0x3f4948e,0x22eafd9,
|
|
0x3863202,0x3d0e2a5,0x006a502 },
|
|
{ 0x34536fe,0x04e91ad,0x30ebf5f,0x2af62a7,0x01d218b,0x1c8c9da,
|
|
0x336bcc3,0x23060c3,0x331576e,0x1b14c5e,0x1bbcb76,0x0755e9a,
|
|
0x3d4dcef,0x24c2cf8,0x00917c4 } },
|
|
/* 5 */
|
|
{ { 0x349ddd0,0x09b8bb8,0x0250114,0x3e66cbf,0x29f117e,0x3005d29,
|
|
0x36b480e,0x2119bfc,0x2761845,0x253d2f7,0x0580604,0x0bb6db4,
|
|
0x3ca922f,0x1744677,0x008adc7 },
|
|
{ 0x3d5a7ce,0x27425ed,0x11e9a61,0x3968d10,0x3874275,0x3692d3b,
|
|
0x03e0470,0x0763d50,0x3d97790,0x3cbaeab,0x2747170,0x18faf3a,
|
|
0x180365e,0x2511fe7,0x0012a36 } },
|
|
/* 6 */
|
|
{ { 0x3c52870,0x2701e93,0x296128f,0x120694e,0x1ce0b37,0x3860a36,
|
|
0x10fa180,0x0896b55,0x2f76adb,0x22892ae,0x2e58a34,0x07b4295,
|
|
0x2cb62d1,0x079a522,0x00f3d81 },
|
|
{ 0x061ed22,0x2375dd3,0x3c9d861,0x3e602d1,0x10bb747,0x39ae156,
|
|
0x3f796fd,0x087a48a,0x06d680a,0x37f7f47,0x2af2c9d,0x36c55dc,
|
|
0x10f3dc0,0x279b07a,0x00a0937 } },
|
|
/* 7 */
|
|
{ { 0x085c629,0x319bbf8,0x089a386,0x184256f,0x15fc2a4,0x00fd2d0,
|
|
0x13d6312,0x363d44d,0x32b7e4b,0x25f2865,0x27df8ce,0x1dce02a,
|
|
0x24ea3b0,0x0e27b9f,0x00d8a90 },
|
|
{ 0x3b14461,0x1d371f9,0x0f781bc,0x0503271,0x0dc2cb0,0x13bc284,
|
|
0x34b3a68,0x1ff894a,0x25d2032,0x16f79ba,0x260f961,0x07b10d5,
|
|
0x18173b7,0x2812e2b,0x00eede5 } },
|
|
/* 8 */
|
|
{ { 0x13b9a2d,0x132ece2,0x0c5d558,0x02c0214,0x1820c66,0x37cb50f,
|
|
0x26d8267,0x3a00504,0x3f00109,0x33756ee,0x38172f1,0x2e4bb8c,
|
|
0x030d985,0x3e4fcc5,0x00609d4 },
|
|
{ 0x2daf9d6,0x16681fa,0x1fb01e0,0x1b03c49,0x370e653,0x183c839,
|
|
0x2207515,0x0ea6b58,0x1ae7aaf,0x3a96522,0x24bae14,0x1c38bd9,
|
|
0x082497b,0x1c05db4,0x000dd03 } },
|
|
/* 9 */
|
|
{ { 0x110521f,0x04efa21,0x0c174cc,0x2a7dc93,0x387315b,0x14f7098,
|
|
0x1d83bb3,0x2495ed2,0x2fe0c27,0x1e2d9df,0x093c953,0x0287073,
|
|
0x02c9951,0x336291c,0x0033e30 },
|
|
{ 0x208353f,0x3f22748,0x2b2bf0f,0x2373b50,0x10170fa,0x1b8a97d,
|
|
0x0851ed2,0x0b25824,0x055ecb5,0x12049d9,0x3fe1adf,0x11b1385,
|
|
0x28eab06,0x11fac21,0x00513f0 } },
|
|
/* 10 */
|
|
{ { 0x35bdf53,0x1847d37,0x1a6dc07,0x29d62c4,0x045d331,0x313b8e5,
|
|
0x165daf1,0x1e34562,0x3e75a58,0x16ea2fa,0x02dd302,0x3302862,
|
|
0x3eb8bae,0x2266a48,0x00cf2a3 },
|
|
{ 0x24fd048,0x324a074,0x025df98,0x1662eec,0x3841bfb,0x26ae754,
|
|
0x1df8cec,0x0113ae3,0x0b67fef,0x094e293,0x2323666,0x0ab087c,
|
|
0x2f06509,0x0e142d9,0x00a919d } },
|
|
/* 11 */
|
|
{ { 0x1d480d8,0x00ed021,0x3a7d3db,0x1e46ca1,0x28cd9f4,0x2a3ceeb,
|
|
0x24dc754,0x0624a3c,0x0003db4,0x1520bae,0x1c56e0f,0x2fe7ace,
|
|
0x1dc6f38,0x0c826a4,0x008b977 },
|
|
{ 0x209cfc2,0x2c16c9c,0x1b70a31,0x21416cb,0x34c49bf,0x186549e,
|
|
0x062498d,0x146e959,0x0391fac,0x08ff944,0x2b4b834,0x013d57a,
|
|
0x2eabffb,0x0370131,0x00c07c1 } },
|
|
/* 12 */
|
|
{ { 0x332f048,0x0bf9336,0x16dfad2,0x2451d7b,0x35f23bf,0x299adb2,
|
|
0x0ce0c0a,0x0170294,0x289f034,0x2b7d89e,0x395e2d6,0x1d20df7,
|
|
0x2e64e36,0x16dae90,0x00081c9 },
|
|
{ 0x31d6ceb,0x0f80db9,0x0271eba,0x33db1ac,0x1b45bcc,0x1a11c07,
|
|
0x347e630,0x148fd9e,0x142e712,0x3183e3e,0x1cd47ad,0x108d1c9,
|
|
0x09cbb82,0x35e61d9,0x0083027 } },
|
|
/* 13 */
|
|
{ { 0x215b0b8,0x0a7a98d,0x2c41b39,0x3f69536,0x0b41441,0x16da8da,
|
|
0x15d556b,0x3c17a26,0x129167e,0x3ea0351,0x2d25a27,0x2f2d285,
|
|
0x15b68f6,0x2931ef5,0x00210d6 },
|
|
{ 0x1351130,0x012aec9,0x37ebf38,0x26640f8,0x01d2df6,0x2130972,
|
|
0x201efc0,0x23a457c,0x087a1c6,0x14c68a3,0x163f62a,0x36b494d,
|
|
0x015d481,0x39c35b1,0x005dd6d } },
|
|
/* 14 */
|
|
{ { 0x06612ce,0x11c3f61,0x199729f,0x3b36863,0x2986f3e,0x3cd2be1,
|
|
0x04c1612,0x2be2dae,0x00846dd,0x3d7bc29,0x249e795,0x1016803,
|
|
0x37a3714,0x2c5aa8b,0x005f491 },
|
|
{ 0x341b38d,0x01eb936,0x3caac7f,0x27863ef,0x1ef7d11,0x1110ec6,
|
|
0x18e0761,0x26498e8,0x01a79a1,0x390d5a1,0x22226fb,0x3d2a473,
|
|
0x0872191,0x1230f32,0x00dc772 } },
|
|
/* 15 */
|
|
{ { 0x0b1ec9d,0x03fc6b9,0x3706d57,0x03b9fbb,0x221d23e,0x2867821,
|
|
0x1e40f4c,0x2c9c0f3,0x3c4cd4b,0x31f5948,0x3f13aa6,0x307c1b2,
|
|
0x04b6016,0x116b453,0x005aa72 },
|
|
{ 0x0b74de8,0x20519d1,0x134e37f,0x05d882a,0x1839e7a,0x3a2c6a8,
|
|
0x0d14e8d,0x1d78bdd,0x251f30d,0x3a1e27e,0x081c261,0x2c9014b,
|
|
0x165ee09,0x19e0cf1,0x00654e2 } },
|
|
/* 16 */
|
|
{ { 0x39fbe67,0x081778b,0x0e44378,0x20dfdca,0x1c4afcb,0x20b803c,
|
|
0x0ec06c6,0x1508f6f,0x1c3114d,0x3bca851,0x3a52463,0x07661d1,
|
|
0x17b0aa0,0x16c5f5c,0x00fc093 },
|
|
{ 0x0d01f95,0x0ef13f5,0x2d34965,0x2a25582,0x39aa83e,0x3e38fcf,
|
|
0x3943dca,0x385bbdd,0x210e86f,0x3dc1dd2,0x3f9ffdc,0x18b9bc6,
|
|
0x345c96b,0x0e79621,0x008a72f } },
|
|
/* 17 */
|
|
{ { 0x341c342,0x3793688,0x042273a,0x153a9c1,0x3dd326e,0x1d073bc,
|
|
0x2c7d983,0x05524cd,0x00d59e6,0x347abe8,0x3d9a3ef,0x0fb624a,
|
|
0x2c7e4cd,0x09b3171,0x0003faf },
|
|
{ 0x045f8ac,0x38bf3cc,0x1e73087,0x0c85d3c,0x314a655,0x382be69,
|
|
0x384f28f,0x24d6cb3,0x2842cdc,0x1777f5e,0x2929c89,0x03c45ed,
|
|
0x3cfcc4c,0x0b59322,0x0035657 } },
|
|
/* 18 */
|
|
{ { 0x18c1bba,0x2eb005f,0x33d57ec,0x30e42c3,0x36058f9,0x1865f43,
|
|
0x2116e3f,0x2c4a2bb,0x0684033,0x0f1375c,0x0209b98,0x2136e9b,
|
|
0x1bc4af0,0x0b3e0c7,0x0097c7c },
|
|
{ 0x16010e8,0x398777e,0x2a172f4,0x0814a7e,0x0d97e4e,0x274dfc8,
|
|
0x2666606,0x1b5c93b,0x1ed3d36,0x3f3304e,0x13488e0,0x02dbb88,
|
|
0x2d53369,0x3717ce9,0x007cad1 } },
|
|
/* 19 */
|
|
{ { 0x257a41f,0x2a6a076,0x39b6660,0x04bb000,0x1e74a04,0x3876b45,
|
|
0x343c6b5,0x0753108,0x3f54668,0x24a13cf,0x23749e8,0x0421fc5,
|
|
0x32f13b5,0x0f31be7,0x00070f2 },
|
|
{ 0x1186e14,0x0847697,0x0dff542,0x0dff76c,0x084748f,0x2c7d060,
|
|
0x23aab4d,0x0b43906,0x27ba640,0x1497b59,0x02f5835,0x0a492a4,
|
|
0x0a6892f,0x39f3e91,0x005844e } },
|
|
/* 20 */
|
|
{ { 0x33b236f,0x02181cf,0x21dafab,0x0760788,0x019e9d4,0x249ed0a,
|
|
0x36571e3,0x3c7dbcf,0x1337550,0x010d22a,0x285e62f,0x19ee65a,
|
|
0x052bf71,0x1d65fd5,0x0062d43 },
|
|
{ 0x2955926,0x3fae7bc,0x0353d85,0x07db7de,0x1440a56,0x328dad6,
|
|
0x1668ec9,0x28058e2,0x1a1a22d,0x1014afc,0x3609325,0x3effdcb,
|
|
0x209f3bd,0x3ca3888,0x0094e50 } },
|
|
/* 21 */
|
|
{ { 0x062e8af,0x0b96ccc,0x136990b,0x1d7a28f,0x1a85723,0x0076dec,
|
|
0x21b00b2,0x06a88ff,0x2f0ee65,0x1fa49b7,0x39b10ad,0x10b26fa,
|
|
0x0be7465,0x026e8bf,0x00098e3 },
|
|
{ 0x3f1d63f,0x37bacff,0x1374779,0x02882ff,0x323d0e8,0x1da3de5,
|
|
0x12bb3b8,0x0a15a11,0x34d1f95,0x2b3dd6e,0x29ea3fa,0x39ad000,
|
|
0x33a538f,0x390204d,0x0012bd3 } },
|
|
/* 22 */
|
|
{ { 0x04cbba5,0x0de0344,0x1d4cc02,0x11fe8d7,0x36207e7,0x32a6da8,
|
|
0x0239281,0x1ec40d7,0x3e89798,0x213fc66,0x0022eee,0x11daefe,
|
|
0x3e74db8,0x28534ee,0x00aa0a4 },
|
|
{ 0x07d4543,0x250cc46,0x206620f,0x1c1e7db,0x1321538,0x31fa0b8,
|
|
0x30f74ea,0x01aae0e,0x3a2828f,0x3e9dd22,0x026ef35,0x3c0a62b,
|
|
0x27dbdc5,0x01c23a6,0x000f0c5 } },
|
|
/* 23 */
|
|
{ { 0x2f029dd,0x3091337,0x21b80c5,0x21e1419,0x13dabc6,0x3847660,
|
|
0x12b865f,0x36eb666,0x38f6274,0x0ba6006,0x098da24,0x1398c64,
|
|
0x13d08e5,0x246a469,0x009929a },
|
|
{ 0x1285887,0x3ff5c8d,0x010237b,0x097c506,0x0bc7594,0x34b9b88,
|
|
0x00cc35f,0x0bb964a,0x00cfbc4,0x29cd718,0x0837619,0x2b4a192,
|
|
0x0c57bb7,0x08c69de,0x00a3627 } },
|
|
/* 24 */
|
|
{ { 0x1361ed8,0x266d724,0x366cae7,0x1d5b18c,0x247d71b,0x2c9969a,
|
|
0x0dd5211,0x1edd153,0x25998d7,0x0380856,0x3ab29db,0x09366de,
|
|
0x1e53644,0x2b31ff6,0x008b0ff },
|
|
{ 0x3b5d9ef,0x217448d,0x174746d,0x18afea4,0x15b106d,0x3e66e8b,
|
|
0x0479f85,0x13793b4,0x1231d10,0x3c39bce,0x25e8983,0x2a13210,
|
|
0x05a7083,0x382be04,0x00a9507 } },
|
|
/* 25 */
|
|
{ { 0x0cf381c,0x1a29b85,0x31ccf6c,0x2f708b8,0x3af9d27,0x2a29732,
|
|
0x168d4da,0x393488d,0x2c0e338,0x3f90c7b,0x0f52ad1,0x2a0a3fa,
|
|
0x2cd80f1,0x15e7a1a,0x00db6a0 },
|
|
{ 0x107832a,0x159cb91,0x1289288,0x17e21f9,0x073fc27,0x1584342,
|
|
0x3802780,0x3d6c197,0x154075f,0x16366d1,0x09f712b,0x23a3ec4,
|
|
0x29cf23a,0x3218baf,0x0039f0a } },
|
|
/* 26 */
|
|
{ { 0x052edf5,0x2afde13,0x2e53d8f,0x3969626,0x3dcd737,0x1e46ac5,
|
|
0x118bf0d,0x01b2652,0x156bcff,0x16d7ef6,0x1ca46d4,0x34c0cbb,
|
|
0x3e486f6,0x1f85068,0x002cdff },
|
|
{ 0x1f47ec8,0x12cee98,0x0608667,0x18fbbe1,0x08a8821,0x31a1fe4,
|
|
0x17c7054,0x3c89e89,0x2edf6cd,0x1b8c32c,0x3f6ea84,0x1319329,
|
|
0x3cd3c2c,0x05f331a,0x00186fa } },
|
|
/* 27 */
|
|
{ { 0x1fcb91e,0x0fd4d87,0x358a48a,0x04d91b4,0x083595e,0x044a1e6,
|
|
0x15827b9,0x1d5eaf4,0x2b82187,0x08f3984,0x21bd737,0x0c54285,
|
|
0x2f56887,0x14c2d98,0x00f4684 },
|
|
{ 0x01896f6,0x0e542d0,0x2090883,0x269dfcf,0x1e11cb8,0x239fd29,
|
|
0x312cac4,0x19dfacb,0x369f606,0x0cc4f75,0x16579f9,0x33c22cc,
|
|
0x0f22bfd,0x3b251ae,0x006429c } },
|
|
/* 28 */
|
|
{ { 0x375f9a4,0x137552e,0x3570498,0x2e4a74e,0x24aef06,0x35b9307,
|
|
0x384ca23,0x3bcd6d7,0x011b083,0x3c93187,0x392ca9f,0x129ce48,
|
|
0x0a800ce,0x145d9cc,0x00865d6 },
|
|
{ 0x22b4a2b,0x37f9d9c,0x3e0eca3,0x3e5ec20,0x112c04b,0x2e1ae29,
|
|
0x3ce5b51,0x0f83200,0x32d6a7e,0x10ff1d8,0x081adbe,0x265c30b,
|
|
0x216b1c8,0x0eb4483,0x003cbcd } },
|
|
/* 29 */
|
|
{ { 0x030ce93,0x2d331fb,0x20a2fbf,0x1f6dc9c,0x010ed6c,0x1ed5540,
|
|
0x275bf74,0x3df0fb1,0x103333f,0x0241c96,0x1075bfc,0x30e5cf9,
|
|
0x0f31bc7,0x32c01eb,0x00b049e },
|
|
{ 0x358839c,0x1dbabd3,0x1e4fb40,0x36a8ac1,0x2101896,0x2d0319b,
|
|
0x2033b0a,0x192e8fd,0x2ebc8d8,0x2867ba7,0x07bf6d2,0x1b3c555,
|
|
0x2477deb,0x198fe09,0x008e5a9 } },
|
|
/* 30 */
|
|
{ { 0x3fbd5e1,0x18bf77d,0x2b1d69e,0x151da44,0x338ecfe,0x0768efe,
|
|
0x1a3d56d,0x3c35211,0x10e1c86,0x2012525,0x3bc36ce,0x32b6fe4,
|
|
0x0c8d183,0x15c93f3,0x0041fce },
|
|
{ 0x332c144,0x24e70a0,0x246e05f,0x22c21c7,0x2b17f24,0x1ba2bfd,
|
|
0x0534e26,0x318a4f6,0x1dc3b85,0x0c741bc,0x23131b7,0x01a8cba,
|
|
0x364e5db,0x21362cf,0x00f2951 } },
|
|
/* 31 */
|
|
{ { 0x2ddc103,0x14ffdcd,0x206fd96,0x0de57bd,0x025f43e,0x381b73a,
|
|
0x2301fcf,0x3bafc27,0x34130b6,0x0216bc8,0x0ff56b2,0x2c4ad4c,
|
|
0x23c6b79,0x1267fa6,0x009b4fb },
|
|
{ 0x1d27ac2,0x13e2494,0x1389015,0x38d5b29,0x2d33167,0x3f01969,
|
|
0x28ec1fa,0x1b26de0,0x2587f74,0x1c25668,0x0c44f83,0x23c6f8c,
|
|
0x32fdbb1,0x045f104,0x00a7946 } },
|
|
/* 32 */
|
|
{ { 0x23c647b,0x09addd7,0x1348c04,0x0e633c1,0x1bfcbd9,0x1cb034f,
|
|
0x1312e31,0x11cdcc7,0x1e6ee75,0x057d27f,0x2da7ee6,0x154c3c1,
|
|
0x3a5fb89,0x2c2ba2c,0x00cf281 },
|
|
{ 0x1b8a543,0x125cd50,0x1d30fd1,0x29cc203,0x341a625,0x14e4233,
|
|
0x3aae076,0x289e38a,0x036ba02,0x230f405,0x3b21b8f,0x34088b9,
|
|
0x01297a0,0x03a75fb,0x00fdc27 } },
|
|
/* 33 */
|
|
{ { 0x07f41d6,0x1cf032f,0x1641008,0x0f86deb,0x3d97611,0x0e110fe,
|
|
0x136ff42,0x0b914a9,0x0e241e6,0x180c340,0x1f545fc,0x0ba619d,
|
|
0x1208c53,0x04223a4,0x00cd033 },
|
|
{ 0x397612c,0x0132665,0x34e2d1a,0x00bba99,0x1d4393e,0x065d0a8,
|
|
0x2fa69ee,0x1643b55,0x08085f0,0x3774aad,0x08a2243,0x33bf149,
|
|
0x03f41a5,0x1ed950e,0x0048cc6 } },
|
|
/* 34 */
|
|
{ { 0x014ab48,0x010c3bf,0x2a744e5,0x13c99c1,0x2195b7f,0x32207fd,
|
|
0x28a228c,0x004f4bf,0x0e2d945,0x2ec6e5a,0x0b92162,0x1aa95e5,
|
|
0x2754a93,0x1adcd93,0x004fb76 },
|
|
{ 0x1e1ff7f,0x24ef28c,0x269113f,0x32b393c,0x2696eb5,0x0ac2780,
|
|
0x354bf8a,0x0ffe3fd,0x09ce58e,0x0163c4f,0x1678c0b,0x15cd1bc,
|
|
0x292b3b7,0x036ea19,0x00d5420 } },
|
|
/* 35 */
|
|
{ { 0x1da1265,0x0c2ef5b,0x18dd9a0,0x3f3a25c,0x0f7b4f3,0x0d8196e,
|
|
0x24931f9,0x090729a,0x1875f72,0x1ef39cb,0x2577585,0x2ed472d,
|
|
0x136756c,0x20553a6,0x00c7161 },
|
|
{ 0x2e32189,0x283de4b,0x00b2e81,0x0989df7,0x3ef2fab,0x1c7d1a7,
|
|
0x24f6feb,0x3e16679,0x233dfda,0x06d1233,0x3e6b5df,0x1707132,
|
|
0x05f7b3f,0x2c00779,0x00fb8df } },
|
|
/* 36 */
|
|
{ { 0x15bb921,0x117e9d3,0x267ec73,0x2f934ad,0x25c7e04,0x20b5e8f,
|
|
0x2d3a802,0x2ca911f,0x3f87e47,0x39709dd,0x08488e2,0x2cec400,
|
|
0x35b4589,0x1f0acba,0x009aad7 },
|
|
{ 0x2ac34ae,0x06f29f6,0x3326d68,0x3949abe,0x02452e4,0x0687b85,
|
|
0x0879244,0x1eb7832,0x0d4c240,0x31d0ec1,0x3c17a2a,0x17a666f,
|
|
0x01a06cb,0x3e0929c,0x004dca2 } },
|
|
/* 37 */
|
|
{ { 0x127bc1a,0x0c72984,0x13be68e,0x26c5fab,0x1a3edd5,0x097d685,
|
|
0x36b645e,0x385799e,0x394a420,0x39d8885,0x0b1e872,0x13f60ed,
|
|
0x2ce1b79,0x3c0ecb7,0x007cab3 },
|
|
{ 0x29b3586,0x26fc572,0x0bd7711,0x0913494,0x0a55459,0x31af3c9,
|
|
0x3633eac,0x3e2105c,0x0c2b1b6,0x0e6f4c2,0x047d38c,0x2b81bd5,
|
|
0x1fe1c3b,0x04d7cd0,0x0054dcc } },
|
|
/* 38 */
|
|
{ { 0x03caf0d,0x0d66365,0x313356d,0x2a4897f,0x2ce044e,0x18feb7a,
|
|
0x1f6a7c5,0x3709e7b,0x14473e8,0x2d8cbae,0x3190dca,0x12d19f8,
|
|
0x31e3181,0x3cc5b6e,0x002d4f4 },
|
|
{ 0x143b7ca,0x2604728,0x39508d6,0x0cb79f3,0x24ec1ac,0x1ed7fa0,
|
|
0x3ab5fd3,0x3c76488,0x2e49390,0x03a0985,0x3580461,0x3fd2c81,
|
|
0x308f0ab,0x38561d6,0x0011b9b } },
|
|
/* 39 */
|
|
{ { 0x3be682c,0x0c68f4e,0x32dd4ae,0x099d3bb,0x0bc7c5d,0x311f750,
|
|
0x2fd10a3,0x2e7864a,0x23bc14a,0x13b1f82,0x32e495e,0x1b0f746,
|
|
0x3cd856a,0x17a4c26,0x00085ee },
|
|
{ 0x02e67fd,0x06a4223,0x2af2f38,0x2038987,0x132083a,0x1b7bb85,
|
|
0x0d6a499,0x131e43f,0x3035e52,0x278ee3e,0x1d5b08b,0x30d8364,
|
|
0x2719f8d,0x0b21fc9,0x003a06e } },
|
|
/* 40 */
|
|
{ { 0x237cac0,0x27d6a1c,0x27945cd,0x2750d61,0x293f0b5,0x253db13,
|
|
0x04a764e,0x20b4d0e,0x12bb627,0x160c13b,0x0de0601,0x236e2cf,
|
|
0x2190f0b,0x354d76f,0x004336d },
|
|
{ 0x2ab473a,0x10d54e4,0x1046574,0x1d6f97b,0x0031c72,0x06426a9,
|
|
0x38678c2,0x0b76cf9,0x04f9920,0x152adf8,0x2977e63,0x1234819,
|
|
0x198be26,0x061024c,0x00d427d } },
|
|
/* 41 */
|
|
{ { 0x39b5a31,0x2123d43,0x362a822,0x1a2eab6,0x0bb0034,0x0d5d567,
|
|
0x3a04723,0x3a10c8c,0x08079ae,0x0d27bda,0x2eb9e1e,0x2619e82,
|
|
0x39a55a8,0x0c6c7db,0x00c1519 },
|
|
{ 0x174251e,0x13ac2eb,0x295ed26,0x18d2afc,0x037b9b2,0x1258344,
|
|
0x00921b0,0x1f702d8,0x1bc4da7,0x1c3794f,0x12b1869,0x366eacf,
|
|
0x16ddf01,0x31ebdc5,0x00ad54e } },
|
|
/* 42 */
|
|
{ { 0x1efdc58,0x1370d5e,0x0ddb8e7,0x1a53fda,0x1456bd3,0x0c825a9,
|
|
0x0e74ccd,0x20f41c9,0x3423867,0x139073f,0x3c70d8a,0x131fc85,
|
|
0x219a2a0,0x34bf986,0x0041199 },
|
|
{ 0x1c05dd2,0x268f80a,0x3da9d38,0x1af9f8f,0x0535f2a,0x30ad37e,
|
|
0x2cf72d7,0x14a509b,0x1f4fe74,0x259e09d,0x1d23f51,0x0672732,
|
|
0x08fc463,0x00b6201,0x001e05a } },
|
|
/* 43 */
|
|
{ { 0x0d5ffe8,0x3238bb5,0x17f275c,0x25b6fa8,0x2f8bb48,0x3b8f2d2,
|
|
0x059790c,0x18594d4,0x285a47c,0x3d301bb,0x12935d2,0x23ffc96,
|
|
0x3d7c7f9,0x15c8cbf,0x0034c4a },
|
|
{ 0x20376a2,0x05201ba,0x1e02c4b,0x1413c45,0x02ea5e7,0x39575f0,
|
|
0x2d76e21,0x113694c,0x011f310,0x0da3725,0x31b7799,0x1cb9195,
|
|
0x0cfd592,0x22ee4ea,0x00adaa3 } },
|
|
/* 44 */
|
|
{ { 0x14ed72a,0x031c49f,0x39a34bf,0x192e87d,0x0da0e92,0x130e7a9,
|
|
0x00258bf,0x144e123,0x2d82a71,0x0294e53,0x3f06c66,0x3d4473a,
|
|
0x037cd4a,0x3bbfb17,0x00fcebc },
|
|
{ 0x39ae8c1,0x2dd6a9d,0x206ef23,0x332b479,0x2deff59,0x09d5720,
|
|
0x3526fd2,0x33bf7cf,0x344bb32,0x359316a,0x115bdef,0x1b8468a,
|
|
0x3813ea9,0x11a8450,0x00ab197 } },
|
|
/* 45 */
|
|
{ { 0x0837d7d,0x1e1617b,0x0ba443c,0x2f2e3b8,0x2ca5b6f,0x176ed7b,
|
|
0x2924d9d,0x07294d3,0x104bb4f,0x1cfd3e8,0x398640f,0x1162dc8,
|
|
0x007ea15,0x2aa75fd,0x004231f },
|
|
{ 0x16e6896,0x01987be,0x0f9d53e,0x1a740ec,0x1554e4c,0x31e1634,
|
|
0x3cb07b9,0x013eb53,0x39352cb,0x1dfa549,0x0974e7f,0x17c55d2,
|
|
0x157c85f,0x1561adb,0x002e3fa } },
|
|
/* 46 */
|
|
{ { 0x29951a8,0x35200da,0x2ad042c,0x22109e4,0x3a8b15b,0x2eca69c,
|
|
0x28bcf9a,0x0cfa063,0x0924099,0x12ff668,0x2fb88dc,0x028d653,
|
|
0x2445876,0x218d01c,0x0014418 },
|
|
{ 0x1caedc7,0x295bba6,0x01c9162,0x3364744,0x28fb12e,0x24c80b6,
|
|
0x2719673,0x35e5ba9,0x04aa4cc,0x206ab23,0x1cf185a,0x2c140d8,
|
|
0x1095a7d,0x1b3633f,0x000c9f8 } },
|
|
/* 47 */
|
|
{ { 0x0b2a556,0x0a051c4,0x30b29a7,0x190c9ed,0x3767ca9,0x38de66d,
|
|
0x2d9e125,0x3aca813,0x2dc22a3,0x319e074,0x0d9450a,0x3445bac,
|
|
0x3e08a5b,0x07f29fa,0x00eccac },
|
|
{ 0x02d6e94,0x21113f7,0x321bde6,0x0a4d7b3,0x03621f4,0x2780e8b,
|
|
0x22d5432,0x1fc2853,0x0d57d3e,0x254f90b,0x33ed00b,0x289b025,
|
|
0x12272bb,0x30e715f,0x0000297 } },
|
|
/* 48 */
|
|
{ { 0x0243a7d,0x2aac42e,0x0c5b3aa,0x0fa3e96,0x06eeef9,0x2b9fdd9,
|
|
0x26fca39,0x0134fe1,0x22661ab,0x1990416,0x03945d6,0x15e3628,
|
|
0x3848ca3,0x0f91e46,0x00b08cd },
|
|
{ 0x16d2411,0x3717e1d,0x128c45e,0x3669d54,0x0d4a790,0x2797da8,
|
|
0x0f09634,0x2faab0b,0x27df649,0x3b19b49,0x0467039,0x39b65a2,
|
|
0x3816f3c,0x31ad0bd,0x0050046 } },
|
|
/* 49 */
|
|
{ { 0x2425043,0x3858099,0x389092a,0x3f7c236,0x11ff66a,0x3c58b39,
|
|
0x2f5a7f8,0x1663ce1,0x2a0fcf5,0x38634b7,0x1a8ca18,0x0dcace8,
|
|
0x0e6f778,0x03ae334,0x00df0d2 },
|
|
{ 0x1bb4045,0x357875d,0x14b77ed,0x33ae5b6,0x2252a47,0x31899dd,
|
|
0x3293582,0x040c6f6,0x14340dd,0x3614f0e,0x3d5f47f,0x326fb3d,
|
|
0x0044a9d,0x00beeb9,0x0027c23 } },
|
|
/* 50 */
|
|
{ { 0x32d49ce,0x34822a3,0x30a22d1,0x00858b7,0x10d91aa,0x2681fd9,
|
|
0x1cce870,0x2404a71,0x38b8433,0x377c1c8,0x019442c,0x0a38b21,
|
|
0x22aba50,0x0d61c81,0x002dcbd },
|
|
{ 0x0680967,0x2f0f2f9,0x172cb5f,0x1167e4b,0x12a7bc6,0x05b0da7,
|
|
0x2c76e11,0x3a36201,0x37a3177,0x1d71419,0x0569df5,0x0dce7ad,
|
|
0x3f40b75,0x3bd8db0,0x002d481 } },
|
|
/* 51 */
|
|
{ { 0x2a1103e,0x34e7f7f,0x1b171a2,0x24a57e0,0x2eaae55,0x166c992,
|
|
0x10aa18f,0x0bb836f,0x01acb59,0x0e430e7,0x1750cca,0x18be036,
|
|
0x3cc6cdf,0x0a0f7e5,0x00da4d8 },
|
|
{ 0x2201067,0x374d187,0x1f6b0a6,0x165a7ec,0x31531f8,0x3580487,
|
|
0x15e5521,0x0724522,0x2b04c04,0x202c86a,0x3cc1ccf,0x225b11a,
|
|
0x1bde79d,0x0eccc50,0x00d24da } },
|
|
/* 52 */
|
|
{ { 0x3b0a354,0x2814dd4,0x1cd8575,0x3d031b7,0x0392ff2,0x1855ee5,
|
|
0x0e8cff5,0x203442e,0x3bd3b1b,0x141cf95,0x3fedee1,0x1d783c0,
|
|
0x26f192a,0x0392aa3,0x0075238 },
|
|
{ 0x158ffe9,0x3889f19,0x14151f4,0x06067b1,0x13a3486,0x1e65c21,
|
|
0x382d5ef,0x1ab0aac,0x2ffddc4,0x3179b7a,0x3c8d094,0x05101e3,
|
|
0x237c6e5,0x3947d83,0x00f674f } },
|
|
/* 53 */
|
|
{ { 0x363408f,0x21eb96b,0x27376fb,0x2a735d6,0x1a39c36,0x3d31863,
|
|
0x33313fc,0x32235e0,0x082f034,0x23ef351,0x39b3528,0x1a69d84,
|
|
0x1d9c944,0x07159ad,0x0077a71 },
|
|
{ 0x04f8d65,0x25771e5,0x2ba84a6,0x194586a,0x1e6da5f,0x118059a,
|
|
0x14e9c32,0x1d24619,0x3f528ae,0x22f22e4,0x0f5580d,0x0747a0e,
|
|
0x32cc85f,0x286b3a8,0x008ccf9 } },
|
|
/* 54 */
|
|
{ { 0x196fee2,0x2c4431c,0x094528a,0x18e1d32,0x175799d,0x26bb6b7,
|
|
0x2293482,0x23fd289,0x07b2be8,0x1a5c533,0x158d60d,0x04a4f3f,
|
|
0x164e9f7,0x32ccca9,0x00da6b6 },
|
|
{ 0x1d821c2,0x3f76c4f,0x323df43,0x17e4374,0x0f2f278,0x121227e,
|
|
0x2464190,0x19d2644,0x326d24c,0x3185983,0x0803c15,0x0767a33,
|
|
0x1c4c996,0x0563eab,0x00631c6 } },
|
|
/* 55 */
|
|
{ { 0x1752366,0x0baf83f,0x288bacf,0x0384e6f,0x2b93c34,0x3c805e7,
|
|
0x3664850,0x29e1663,0x254ff1d,0x3852080,0x0f85c16,0x1e389d9,
|
|
0x3191352,0x3915eaa,0x00a246e },
|
|
{ 0x3763b33,0x187ad14,0x3c0d438,0x3f11702,0x1c49f03,0x35ac7a8,
|
|
0x3f16bca,0x27266bf,0x08b6fd4,0x0f38ce4,0x37fde8c,0x147a6ff,
|
|
0x02c5e5c,0x28e7fc5,0x00076a7 } },
|
|
/* 56 */
|
|
{ { 0x2338d10,0x0e77fa7,0x011b046,0x1bfd0ad,0x28ee699,0x21d73bc,
|
|
0x0461d1a,0x342ea58,0x2d695b4,0x30415ed,0x2906e0b,0x18e494a,
|
|
0x20f8a27,0x026b870,0x002c19f },
|
|
{ 0x2f4c43d,0x3f0fc3b,0x0aa95b8,0x2a01ea1,0x3e2e1b1,0x0d74af6,
|
|
0x0555288,0x0cb757d,0x24d2071,0x143d2bb,0x3907f67,0x3e0ce30,
|
|
0x131f0e9,0x3724381,0x007a874 } },
|
|
/* 57 */
|
|
{ { 0x3c27050,0x08b5165,0x0bf884b,0x3dd679c,0x3bd0b8d,0x25ce2e6,
|
|
0x1674057,0x1f13ed3,0x1f5cd91,0x0d1fd35,0x13ce6e3,0x2671338,
|
|
0x10f8b90,0x34e5487,0x00942bf },
|
|
{ 0x03b566d,0x23c3da9,0x37de502,0x1a486ff,0x1af6e86,0x1108cb3,
|
|
0x36f856c,0x01a6a0f,0x179f915,0x1595a01,0x2cfecb8,0x082568b,
|
|
0x1ba16d1,0x1abb6c0,0x00cf7f0 } },
|
|
/* 58 */
|
|
{ { 0x2f96c80,0x1b8f123,0x209c0f5,0x2ccf76d,0x1d521f2,0x3705143,
|
|
0x2941027,0x07f88af,0x07102a9,0x38b4868,0x1efa37d,0x1bdd3e8,
|
|
0x028a12e,0x02e055b,0x009a9a9 },
|
|
{ 0x1c7dfcb,0x3aa7aa7,0x1d62c54,0x3f0b0b0,0x3c74e66,0x274f819,
|
|
0x23f9674,0x0e2b67c,0x24654dd,0x0c71f0e,0x1946cee,0x0016211,
|
|
0x0045dc7,0x0da1173,0x0089856 } },
|
|
/* 59 */
|
|
{ { 0x0e73946,0x29f353f,0x056329d,0x2d48c5a,0x28f697d,0x2ea4bb1,
|
|
0x235e9cc,0x34faa38,0x15f9f91,0x3557519,0x2a50a6c,0x1a27c8e,
|
|
0x2a1a0f3,0x3098879,0x00dcf21 },
|
|
{ 0x1b818bf,0x2f20b98,0x2243cff,0x25b691e,0x3c74a2f,0x2f06833,
|
|
0x0e980a8,0x32db48d,0x2b57929,0x33cd7f5,0x2fe17d6,0x11a384b,
|
|
0x2dafb81,0x2b9562c,0x00ddea6 } },
|
|
/* 60 */
|
|
{ { 0x2787b2e,0x37a21df,0x310d294,0x07ce6a4,0x1258acc,0x3050997,
|
|
0x19714aa,0x122824b,0x11c708b,0x0462d56,0x21abbf7,0x331aec3,
|
|
0x307b927,0x3e8d5a0,0x00c0581 },
|
|
{ 0x24d4d58,0x3d628fc,0x23279e0,0x2e38338,0x2febe9b,0x346f9c0,
|
|
0x3d6a419,0x3264e47,0x245faca,0x3669f62,0x1e50d66,0x3028232,
|
|
0x18201ab,0x0bdc192,0x0002c34 } },
|
|
/* 61 */
|
|
{ { 0x17bdbc2,0x1c501c5,0x1605ccd,0x31ab438,0x372fa89,0x24a8057,
|
|
0x13da2bb,0x3f95ac7,0x3cda0a3,0x1e2b679,0x24f0673,0x03b72f4,
|
|
0x35be616,0x2ccd849,0x0079d4d },
|
|
{ 0x33497c4,0x0c7f657,0x2fb0d3d,0x3b81064,0x38cafea,0x0e942bc,
|
|
0x3ca7451,0x2ab9784,0x1678c85,0x3c62098,0x1eb556f,0x01b3aa2,
|
|
0x149f3ce,0x2656f6d,0x002eef1 } },
|
|
/* 62 */
|
|
{ { 0x0596edc,0x1f4fad4,0x03a28ed,0x18a4149,0x3aa3593,0x12db40a,
|
|
0x12c2c2a,0x3b1a288,0x327c4fb,0x35847f5,0x384f733,0x02e3fde,
|
|
0x1af0e8a,0x2e417c3,0x00d85a6 },
|
|
{ 0x0091cf7,0x2267d75,0x276860e,0x19cbbfc,0x04fef2b,0x030ce59,
|
|
0x3195cb1,0x1aa3f07,0x3699362,0x2a09d74,0x0d6c840,0x1e413d0,
|
|
0x28acdc7,0x1ff5ea1,0x0088d8b } },
|
|
/* 63 */
|
|
{ { 0x3d98425,0x08dc8de,0x154e85f,0x24b1c2c,0x2d44639,0x19a1e8b,
|
|
0x300ee29,0x053f72e,0x3f7c832,0x12417f6,0x1359368,0x0674a4c,
|
|
0x1218e20,0x0e4fbd4,0x000428c },
|
|
{ 0x01e909a,0x1d88fe6,0x12da40c,0x215ef86,0x2925133,0x004241f,
|
|
0x3e480f4,0x2d16523,0x07c3120,0x3375e86,0x21fd8f3,0x35dc0b6,
|
|
0x0efc5c9,0x14ef8d6,0x0066e47 } },
|
|
/* 64 */
|
|
{ { 0x2973cf4,0x34d3845,0x34f7070,0x22df93c,0x120aee0,0x3ae2b4a,
|
|
0x1af9b95,0x177689a,0x036a6a4,0x0377828,0x23df41e,0x22d4a39,
|
|
0x0df2aa1,0x06ca898,0x0003cc7 },
|
|
{ 0x06b1dd7,0x19dc2a8,0x35d324a,0x0467499,0x25bfa9c,0x1a1110c,
|
|
0x01e2a19,0x1b3c1cf,0x18d131a,0x10d9815,0x2ee7945,0x0a2720c,
|
|
0x0ddcdb0,0x2c071b6,0x00a6aef } },
|
|
/* 65 */
|
|
{ { 0x1ab5245,0x1192d00,0x13ffba1,0x1b71236,0x09b8d0b,0x0eb49cb,
|
|
0x1867dc9,0x371de4e,0x05eae9f,0x36faf82,0x094ea8b,0x2b9440e,
|
|
0x022e173,0x2268e6b,0x00740fc },
|
|
{ 0x0e23b23,0x22c28ca,0x04d05e2,0x0bb84c4,0x1235272,0x0289903,
|
|
0x267a18b,0x0df0fd1,0x32e49bb,0x2ab1d29,0x281e183,0x3dcd3c3,
|
|
0x1c0eb79,0x2db0ff6,0x00bffe5 } },
|
|
/* 66 */
|
|
{ { 0x2a2123f,0x0d63d71,0x1f6db1a,0x257f8a3,0x1927b2d,0x06674be,
|
|
0x302753f,0x20b7225,0x14c1a3f,0x0429cdd,0x377affe,0x0f40a75,
|
|
0x2d34d06,0x05fb6b9,0x0054398 },
|
|
{ 0x38b83c4,0x1e7bbda,0x1682f79,0x0527651,0x2615cb2,0x1795fab,
|
|
0x0e4facc,0x11f763c,0x1b81130,0x2010ae2,0x13f3650,0x20d5b72,
|
|
0x1f32f88,0x34617f4,0x00bf008 } },
|
|
/* 67 */
|
|
{ { 0x28068db,0x0aa8913,0x1a47801,0x10695ca,0x1c72cc6,0x0fc1a47,
|
|
0x33df2c4,0x0517cf0,0x3471d92,0x1be815c,0x397f794,0x3f03cbe,
|
|
0x121bfae,0x172cbe0,0x00813d7 },
|
|
{ 0x383bba6,0x04f1c90,0x0b3f056,0x1c29089,0x2a924ce,0x3c85e69,
|
|
0x1cecbe5,0x0ad8796,0x0aa79f6,0x25e38ba,0x13ad807,0x30b30ed,
|
|
0x0fa963a,0x35c763d,0x0055518 } },
|
|
/* 68 */
|
|
{ { 0x0623f3b,0x3ca4880,0x2bff03c,0x0457ca7,0x3095c71,0x02a9a08,
|
|
0x1722478,0x302c10b,0x3a17458,0x001131e,0x0959ec2,0x18bdfbc,
|
|
0x2929fca,0x2adfe32,0x0040ae2 },
|
|
{ 0x127b102,0x14ddeaa,0x1771b8c,0x283700c,0x2398a86,0x085a901,
|
|
0x108f9dc,0x0cc0012,0x33a918d,0x26d08e9,0x20b9473,0x12c3fc7,
|
|
0x1f69763,0x1c94b5a,0x00e29de } },
|
|
/* 69 */
|
|
{ { 0x035af04,0x3450021,0x12da744,0x077fb06,0x25f255b,0x0db7150,
|
|
0x17dc123,0x1a2a07c,0x2a7636a,0x3972430,0x3704ca1,0x0327add,
|
|
0x3d65a96,0x3c79bec,0x009de8c },
|
|
{ 0x11d3d06,0x3fb8354,0x12c7c60,0x04fe7ad,0x0466e23,0x01ac245,
|
|
0x3c0f5f2,0x2a935d0,0x3ac2191,0x090bd56,0x3febdbc,0x3f1f23f,
|
|
0x0ed1cce,0x02079ba,0x00d4fa6 } },
|
|
/* 70 */
|
|
{ { 0x0ab9645,0x10174ec,0x3711b5e,0x26357c7,0x2aeec7f,0x2170a9b,
|
|
0x1423115,0x1a5122b,0x39e512c,0x18116b2,0x290db1c,0x041b13a,
|
|
0x26563ae,0x0f56263,0x00b89f3 },
|
|
{ 0x3ed2ce4,0x01f365f,0x1b2043b,0x05f7605,0x1f9934e,0x2a068d2,
|
|
0x38d4d50,0x201859d,0x2de5291,0x0a7985a,0x17e6711,0x01b6c1b,
|
|
0x08091fa,0x33c6212,0x001da23 } },
|
|
/* 71 */
|
|
{ { 0x2f2c4b5,0x311acd0,0x1e47821,0x3bd9816,0x1931513,0x1bd4334,
|
|
0x30ae436,0x2c49dc0,0x2c943e7,0x010ed4d,0x1fca536,0x189633d,
|
|
0x17abf00,0x39e5ad5,0x00e4e3e },
|
|
{ 0x0c8b22f,0x2ce4009,0x1054bb6,0x307f2fc,0x32eb5e2,0x19d24ab,
|
|
0x3b18c95,0x0e55e4d,0x2e4acf5,0x1bc250c,0x1dbf3a5,0x17d6a74,
|
|
0x087cf58,0x07f6f82,0x00f8675 } },
|
|
/* 72 */
|
|
{ { 0x110e0b2,0x0e672e7,0x11b7157,0x1598371,0x01c0d59,0x3d60c24,
|
|
0x096b8a1,0x0121075,0x0268859,0x219962f,0x03213f2,0x3022adc,
|
|
0x18de488,0x3dcdeb9,0x008d2e0 },
|
|
{ 0x06cfee6,0x26f2552,0x3c579b7,0x31fa796,0x2036a26,0x362ba5e,
|
|
0x103601c,0x012506b,0x387ff3a,0x101a41f,0x2c7eb58,0x23d2efc,
|
|
0x10a5a07,0x2fd5fa3,0x00e3731 } },
|
|
/* 73 */
|
|
{ { 0x1cd0abe,0x08a0af8,0x2fa272f,0x17a1fbf,0x1d4f901,0x30e0d2f,
|
|
0x1898066,0x273b674,0x0c1b8a2,0x3272337,0x3ee82eb,0x006e7d3,
|
|
0x2a75606,0x0af1c81,0x0037105 },
|
|
{ 0x2f32562,0x2842491,0x1bb476f,0x1305cd4,0x1daad53,0x0d8daed,
|
|
0x164c37b,0x138030f,0x05145d5,0x300e2a3,0x32c09e7,0x0798600,
|
|
0x3515130,0x2b9e55c,0x009764e } },
|
|
/* 74 */
|
|
{ { 0x3d5256a,0x06c67f2,0x3a3b879,0x3c9b284,0x04007e0,0x33c1a41,
|
|
0x3794604,0x1d6240e,0x022b6c1,0x22c62a7,0x01d4590,0x32df5f6,
|
|
0x368f1a1,0x2a7486e,0x006e13f },
|
|
{ 0x31e6e16,0x20f18a9,0x09ed471,0x23b861d,0x15cf0ef,0x397b502,
|
|
0x1c7f9b2,0x05f84b2,0x2cce6e1,0x3c10bba,0x13fb5a7,0x1b52058,
|
|
0x1feb1b8,0x03b7279,0x00ea1cf } },
|
|
/* 75 */
|
|
{ { 0x2a4cc9b,0x15cf273,0x08f36e6,0x076bf3b,0x2541796,0x10e2dbd,
|
|
0x0bf02aa,0x3aa2201,0x03cdcd4,0x3ee252c,0x3799571,0x3e01fa4,
|
|
0x156e8d0,0x1fd6188,0x003466a },
|
|
{ 0x2515664,0x166b355,0x2b0b51e,0x0f28f17,0x355b0f9,0x2909e76,
|
|
0x206b026,0x3823a12,0x179c5fa,0x0972141,0x2663a1a,0x01ee36e,
|
|
0x3fc8dcf,0x2ef3d1b,0x0049a36 } },
|
|
/* 76 */
|
|
{ { 0x2d93106,0x3d6b311,0x3c9ce47,0x382aa25,0x265b7ad,0x0b5f92f,
|
|
0x0f4c941,0x32aa4df,0x380d4b2,0x0e8aba6,0x260357a,0x1f38273,
|
|
0x0d5f95e,0x199f23b,0x0029f77 },
|
|
{ 0x0a0b1c5,0x21a3d6a,0x0ad8df6,0x33d8a5e,0x1240858,0x30000a8,
|
|
0x3ac101d,0x2a8143d,0x1d7ffe9,0x1c74a2a,0x1b962c9,0x1261359,
|
|
0x0c8b274,0x002cf4a,0x00a8a7c } },
|
|
/* 77 */
|
|
{ { 0x211a338,0x22a14ab,0x16e77c5,0x3c746be,0x3a78613,0x0d5731c,
|
|
0x1767d25,0x0b799fa,0x009792a,0x09ae8dc,0x124386b,0x183d860,
|
|
0x176747d,0x14c4445,0x00ab09b },
|
|
{ 0x0eb9dd0,0x0121066,0x032895a,0x330541c,0x1e6c17a,0x2271b92,
|
|
0x06da454,0x054c2bf,0x20abb21,0x0ead169,0x3d7ea93,0x2359649,
|
|
0x242c6c5,0x3194255,0x00a3ef3 } },
|
|
/* 78 */
|
|
{ { 0x3010879,0x1083a77,0x217989d,0x174e55d,0x29d2525,0x0e544ed,
|
|
0x1efd50e,0x30c4e73,0x05bd5d1,0x0793bf9,0x3f7af77,0x052779c,
|
|
0x2b06bc0,0x13d0d02,0x0055a6b },
|
|
{ 0x3eaf771,0x094947a,0x0288f13,0x0a21e35,0x22ab441,0x23816bf,
|
|
0x15832e1,0x2d8aff3,0x348cc1f,0x2bbd4a8,0x01c4792,0x34209d3,
|
|
0x06dc72b,0x211a1df,0x00345c5 } },
|
|
/* 79 */
|
|
{ { 0x2a65e90,0x173ac2f,0x199cde1,0x0ac905b,0x00987f7,0x3618f7b,
|
|
0x1b578df,0x0d5e113,0x34bac6a,0x27d85ed,0x1b48e99,0x18af5eb,
|
|
0x1a1be9e,0x3987aac,0x00877ca },
|
|
{ 0x2358610,0x3776a8e,0x2b0723a,0x344c978,0x22fc4d6,0x1615d53,
|
|
0x3198f51,0x2d61225,0x12cb392,0x07dd061,0x355f7de,0x09e0132,
|
|
0x0efae99,0x13b46aa,0x00e9e6c } },
|
|
/* 80 */
|
|
{ { 0x0683186,0x36d8e66,0x0ea9867,0x0937731,0x1fb5cf4,0x13c39ef,
|
|
0x1a7ffed,0x27dfb32,0x31c7a77,0x09f15fd,0x16b25ef,0x1dd01e7,
|
|
0x0168090,0x240ed02,0x0090eae },
|
|
{ 0x2e1fceb,0x2ab9783,0x1a1fdf2,0x093a1b0,0x33ff1da,0x2864fb7,
|
|
0x3587d6c,0x275aa03,0x123dc9b,0x0e95a55,0x0592030,0x2102402,
|
|
0x1bdef7b,0x37f2e9b,0x001efa4 } },
|
|
/* 81 */
|
|
{ { 0x0540015,0x20e3e78,0x37dcfbd,0x11b0e41,0x02c3239,0x3586449,
|
|
0x1fb9e6a,0x0baa22c,0x00c0ca6,0x3e58491,0x2dbe00f,0x366d4b0,
|
|
0x176439a,0x2a86b86,0x00f52ab },
|
|
{ 0x0ac32ad,0x226250b,0x0f91d0e,0x1098aa6,0x3dfb79e,0x1dbd572,
|
|
0x052ecf2,0x0f84995,0x0d27ad2,0x036c6b0,0x1e4986f,0x2317dab,
|
|
0x2327df6,0x0dee0b3,0x00389ac } },
|
|
/* 82 */
|
|
{ { 0x0e60f5b,0x0622d3e,0x2ada511,0x05522a8,0x27fe670,0x206af28,
|
|
0x333cb83,0x3f25f6c,0x19ddaf3,0x0ec579b,0x36aabc0,0x093dbac,
|
|
0x348b44b,0x277dca9,0x00c5978 },
|
|
{ 0x1cf5279,0x32e294a,0x1a6c26f,0x3f006b6,0x37a3c6b,0x2e2eb26,
|
|
0x2cf88d4,0x3410619,0x1899c80,0x23d3226,0x30add14,0x2810905,
|
|
0x01a41f0,0x11e5176,0x005a02f } },
|
|
/* 83 */
|
|
{ { 0x1c90202,0x321df30,0x3570fa5,0x103e2b1,0x3d099d4,0x05e207d,
|
|
0x0a5b1bd,0x0075d0a,0x3db5b25,0x2d87899,0x32e4465,0x226fc13,
|
|
0x24cb8f8,0x3821daa,0x004da3a },
|
|
{ 0x3e66861,0x03f89b8,0x386d3ef,0x14ccc62,0x35e7729,0x11ce5b7,
|
|
0x035fbc7,0x3f4df0f,0x29c439f,0x1144568,0x32d7037,0x312f65e,
|
|
0x06b9dbf,0x03a9589,0x0008863 } },
|
|
/* 84 */
|
|
{ { 0x0a9e8c9,0x1a19b6e,0x091ecd9,0x2e16ee0,0x2a11963,0x116cf34,
|
|
0x390d530,0x194131f,0x2b580f3,0x31d569c,0x21d3751,0x3e2ce64,
|
|
0x193de46,0x32454f0,0x004bffd },
|
|
{ 0x09554e7,0x170126e,0x2be6cd1,0x153de89,0x0353c67,0x350765c,
|
|
0x202370b,0x1db01e5,0x30b12b1,0x3778591,0x00c8809,0x2e845d5,
|
|
0x1fb1e56,0x170f90d,0x00e2db3 } },
|
|
/* 85 */
|
|
{ { 0x328e33f,0x392aad8,0x36d1d71,0x0aebe04,0x1548678,0x1b55c8c,
|
|
0x24995f8,0x2a5a01e,0x1bd1651,0x37c7c29,0x36803b6,0x3716c91,
|
|
0x1a935a5,0x32f10b7,0x005c587 },
|
|
{ 0x2e8b4c0,0x336ccae,0x11382b6,0x22ec4cc,0x066d159,0x35fa585,
|
|
0x23b2d25,0x3017528,0x2a674a8,0x3a4f900,0x1a7ce82,0x2b2539b,
|
|
0x3d46545,0x0a07918,0x00eb9f8 } },
|
|
/* 86 */
|
|
{ { 0x2cf5b9b,0x03e747f,0x166a34e,0x0afc81a,0x0a115b1,0x3aa814d,
|
|
0x11cf3b1,0x163e556,0x3cbfb15,0x157c0a4,0x1bc703a,0x2141e90,
|
|
0x01f811c,0x207218b,0x0092e6b },
|
|
{ 0x1af24e3,0x3af19b3,0x3c70cc9,0x335cbf3,0x068917e,0x055ee92,
|
|
0x09a9308,0x2cac9b7,0x008b06a,0x1175097,0x36e929c,0x0be339c,
|
|
0x0932436,0x15f18ba,0x0009f6f } },
|
|
/* 87 */
|
|
{ { 0x29375fb,0x35ade34,0x11571c7,0x07b8d74,0x3fabd85,0x090fa91,
|
|
0x362dcd4,0x02c3fdb,0x0608fe3,0x2477649,0x3fc6e70,0x059b7eb,
|
|
0x1e6a708,0x1a4c220,0x00c6c4c },
|
|
{ 0x2a53fb0,0x1a3e1f5,0x11f9203,0x27e7ad3,0x038718e,0x3f5f9e4,
|
|
0x308acda,0x0a8700f,0x34472fe,0x3420d7a,0x08076e5,0x014240e,
|
|
0x0e7317e,0x197a98e,0x00538f7 } },
|
|
/* 88 */
|
|
{ { 0x2663b4b,0x0927670,0x38dd0e0,0x16d1f34,0x3e700ab,0x3119567,
|
|
0x12559d2,0x399b6c6,0x0a84bcd,0x163e7dd,0x3e2aced,0x058548c,
|
|
0x03a5bad,0x011cf74,0x00c155c },
|
|
{ 0x3e454eb,0x2a1e64e,0x1ccd346,0x36e0edf,0x266ee94,0x2e74aaf,
|
|
0x2d8378a,0x3cd547d,0x1d27733,0x0928e5b,0x353553c,0x26f502b,
|
|
0x1d94341,0x2635cc7,0x00d0ead } },
|
|
/* 89 */
|
|
{ { 0x0142408,0x382c3bb,0x3310908,0x2e50452,0x398943c,0x1d0ac75,
|
|
0x1bf7d81,0x04bd00f,0x36b6934,0x3349c37,0x0f69e20,0x0195252,
|
|
0x243a1c5,0x030da5f,0x00a76a9 },
|
|
{ 0x224825a,0x28ce111,0x34c2e0f,0x02e2b30,0x382e48c,0x26853ca,
|
|
0x24bd14e,0x0200dec,0x1e24db3,0x0d3d775,0x132da0a,0x1dea79e,
|
|
0x253dc0c,0x03c9d31,0x0020db9 } },
|
|
/* 90 */
|
|
{ { 0x26c5fd9,0x05e6dc3,0x2eea261,0x08db260,0x2f8bec1,0x1255edf,
|
|
0x283338d,0x3d9a91d,0x2640a72,0x03311f9,0x1bad935,0x152fda8,
|
|
0x0e95abd,0x31abd15,0x00dfbf4 },
|
|
{ 0x107f4fa,0x29ebe9a,0x27353f7,0x3821972,0x27311fa,0x2925ab6,
|
|
0x337ab82,0x2de6c91,0x1f115fe,0x044f909,0x21b93c2,0x3a5f142,
|
|
0x13eb5e9,0x3ab1377,0x00b26b6 } },
|
|
/* 91 */
|
|
{ { 0x22e5f2b,0x2ae7d4a,0x1ac481c,0x0a6fce1,0x2f93caf,0x242658e,
|
|
0x3f35c3c,0x050f3d2,0x30074c9,0x142079c,0x0281b4c,0x295fea3,
|
|
0x007413e,0x01726cd,0x00e4979 },
|
|
{ 0x1ab3cfb,0x1b76295,0x36adf55,0x1ad4636,0x1d444b9,0x3bd2e55,
|
|
0x35425a5,0x1aa8cd3,0x3acecd2,0x1f769e8,0x1a655e9,0x1f6846f,
|
|
0x24c70b5,0x3bff080,0x0002da3 } },
|
|
/* 92 */
|
|
{ { 0x081d0d9,0x2c00d99,0x1fe2e24,0x396063f,0x03740db,0x243f680,
|
|
0x3c1f451,0x1ff7b07,0x2803cf2,0x38ca724,0x2934f43,0x0d72d4d,
|
|
0x0e8fe74,0x2975e21,0x002b505 },
|
|
{ 0x11adcc9,0x331a99c,0x21e16cf,0x1714c78,0x1f03432,0x2caa2a6,
|
|
0x34a9679,0x2f7fe8b,0x0423c21,0x1a757ce,0x31b57d6,0x171e044,
|
|
0x093b9b2,0x13602e0,0x00db534 } },
|
|
/* 93 */
|
|
{ { 0x250a2f5,0x0b999eb,0x21d10d7,0x22b92a1,0x39b7f8d,0x0c37c72,
|
|
0x29f70f3,0x3bf0e84,0x1d7e04f,0x07a42a9,0x272c3ae,0x1587b2f,
|
|
0x155faff,0x10a336e,0x000d8fb },
|
|
{ 0x3663784,0x0d7dcf5,0x056ad22,0x319f8b1,0x0c05bae,0x2b6ff33,
|
|
0x0292e42,0x0435797,0x188efb1,0x0d3f45e,0x119d49f,0x395dcd3,
|
|
0x279fe27,0x133a13d,0x00188ac } },
|
|
/* 94 */
|
|
{ { 0x396c53e,0x0d133e9,0x009b7ee,0x13421a0,0x1bbf607,0x1d284a5,
|
|
0x1594f74,0x18cb47c,0x2dcac11,0x2999ddb,0x04e2fa5,0x1889e2c,
|
|
0x0a89a18,0x33cb215,0x0052665 },
|
|
{ 0x104ab58,0x1d91920,0x3d6d7e3,0x04dc813,0x1167759,0x13a8466,
|
|
0x0a06a54,0x103761b,0x25b1c92,0x26a8fdd,0x2474614,0x21406a4,
|
|
0x251d75f,0x38c3734,0x007b982 } },
|
|
/* 95 */
|
|
{ { 0x15f3060,0x3a7bf30,0x3be6e44,0x0baa1fa,0x05ad62f,0x1e54035,
|
|
0x099d41c,0x2a744d9,0x1c0336f,0x3e99b5b,0x1afd3b1,0x2bf1255,
|
|
0x1822bf8,0x2c93972,0x001d8cc },
|
|
{ 0x1d7584b,0x0508ade,0x20dd403,0x203a8fc,0x1c54a05,0x1611a31,
|
|
0x037c8f9,0x1dcd4fe,0x110fbea,0x30f60bc,0x3dffe2f,0x26a1de1,
|
|
0x0480367,0x18ec81c,0x0048eba } },
|
|
/* 96 */
|
|
{ { 0x346e2f6,0x0435077,0x036789b,0x3e06545,0x313ab57,0x351a721,
|
|
0x3372b91,0x15e6019,0x2fa4f6c,0x3c30656,0x272c9ac,0x10e84a8,
|
|
0x2bdacea,0x232d9e2,0x009dadd },
|
|
{ 0x182579a,0x15b1af8,0x02d8cce,0x36cb49b,0x086feba,0x2911d17,
|
|
0x268ee12,0x011e871,0x18698dc,0x35602b3,0x11b9ec2,0x0ade731,
|
|
0x0f6a05a,0x1821015,0x00007da } },
|
|
/* 97 */
|
|
{ { 0x3b00dd0,0x328d485,0x27a69e3,0x32c3a06,0x1046779,0x120b61c,
|
|
0x19fef3d,0x0fef2e6,0x134d923,0x039bce0,0x348cd0e,0x0b0c007,
|
|
0x066ae11,0x15d8f1b,0x00934e7 },
|
|
{ 0x33234dc,0x353f0f5,0x2fc1b44,0x18a193a,0x2fcae20,0x1afbc86,
|
|
0x3afe252,0x17f7e10,0x107f3b7,0x2d84d54,0x394c2e6,0x19e96a9,
|
|
0x0a37283,0x26c6152,0x003d262 } },
|
|
/* 98 */
|
|
{ { 0x37cfaf8,0x01863d0,0x0299623,0x32c80cb,0x25b8742,0x0a4d90e,
|
|
0x1f72472,0x13de652,0x31a0946,0x0ee0103,0x0f25414,0x2518b49,
|
|
0x07e7604,0x1488d9b,0x00abd6b },
|
|
{ 0x1338f55,0x2ce4af5,0x1a0c119,0x3380525,0x21a80a9,0x235d4df,
|
|
0x118ca7f,0x2dd8bcc,0x1c26bf4,0x32dc56b,0x28482b6,0x1418596,
|
|
0x3c84d24,0x1f1a5a9,0x00d958d } },
|
|
/* 99 */
|
|
{ { 0x1c21f31,0x22aa1ef,0x258c9ad,0x2d2018f,0x0adb3ca,0x01f75ee,
|
|
0x186283b,0x31ad3bf,0x3621be7,0x3b1ee6d,0x015582d,0x3d61d04,
|
|
0x2ddf32e,0x14b8a66,0x00c970c },
|
|
{ 0x2f24d66,0x00b8a88,0x100a78f,0x041d330,0x2efec1d,0x24c5b86,
|
|
0x2a6a390,0x37526bc,0x2055849,0x3339f08,0x16bffc4,0x07f9d72,
|
|
0x06ec09c,0x3f49ee8,0x00cad98 } },
|
|
/* 100 */
|
|
{ { 0x248b73e,0x1b8b42d,0x285eed7,0x39473f4,0x1a9f92c,0x3b44f78,
|
|
0x086c062,0x06a4ea3,0x34ea519,0x3c74e95,0x1ad1b8b,0x1737e2c,
|
|
0x2cfe338,0x0a291f4,0x00bbecc },
|
|
{ 0x1cec548,0x0c9b01a,0x20b298d,0x377c902,0x24f5bc1,0x2415c8d,
|
|
0x1a70622,0x2529090,0x1c5c682,0x283f1ba,0x2319f17,0x0120e2e,
|
|
0x01c6f4d,0x33c67ff,0x008b612 } },
|
|
/* 101 */
|
|
{ { 0x03830eb,0x02d4053,0x10c59bb,0x0f23b83,0x13d08f8,0x26ea4e2,
|
|
0x2626427,0x0a45292,0x0449cbc,0x0175750,0x074c46f,0x27ae0f8,
|
|
0x2d7d6ae,0x163dd3a,0x0063bb7 },
|
|
{ 0x2bb29e0,0x034bab1,0x341e1c4,0x21d2c0b,0x295aa2d,0x0f2c666,
|
|
0x1891755,0x13db64a,0x2fe5158,0x337646e,0x31a1aae,0x057bee4,
|
|
0x00f9e37,0x396d19e,0x00c1b6a } },
|
|
/* 102 */
|
|
{ { 0x2772f41,0x34f92d0,0x39d1cde,0x174ef2d,0x03a700d,0x03fbb98,
|
|
0x30d50e8,0x352ed10,0x1fcf5e5,0x3d113bc,0x26e358f,0x180653f,
|
|
0x1b43cc6,0x3cc9aa4,0x00e68a2 },
|
|
{ 0x37fe4d2,0x09dd725,0x01eb584,0x171f8a9,0x278fdef,0x3e37c03,
|
|
0x3bec02f,0x149757c,0x0cd5852,0x37d2e10,0x0e6988b,0x1c120e9,
|
|
0x0b83708,0x38e7319,0x0039499 } },
|
|
/* 103 */
|
|
{ { 0x08df5fe,0x177a02c,0x0362fc0,0x1f18ee8,0x00c1295,0x173c50a,
|
|
0x379414d,0x1885ba8,0x32a54ef,0x2315644,0x39e65cf,0x357c4be,
|
|
0x1d66333,0x09e05a5,0x0009c60 },
|
|
{ 0x1f7a2fb,0x073b518,0x2eb83ac,0x11353d7,0x1dd8384,0x0c63f2b,
|
|
0x238c6c8,0x2a1920a,0x2e5e9f1,0x1cc56f8,0x042daf4,0x1ed5dc5,
|
|
0x25f9e31,0x012a56a,0x0081b59 } },
|
|
/* 104 */
|
|
{ { 0x321d232,0x2c71422,0x3a756b6,0x30230b2,0x387f3db,0x3a7c3eb,
|
|
0x274b46a,0x201e69f,0x185bb7b,0x140da82,0x0d974a2,0x0616e42,
|
|
0x35ec94f,0x3bc366b,0x005aa7c },
|
|
{ 0x3dcfffc,0x19a9c15,0x3225e05,0x36ae114,0x16ea311,0x0cda2aa,
|
|
0x2a1a8d2,0x154b5cb,0x08348cd,0x17b66c8,0x080ea43,0x21e59f3,
|
|
0x04173b9,0x31d5b04,0x00ad735 } },
|
|
/* 105 */
|
|
{ { 0x2e76ef4,0x216acf3,0x2b93aea,0x112bc74,0x3449974,0x2b2e48f,
|
|
0x11929be,0x2f03021,0x19051e3,0x0ac202d,0x19be68a,0x3b87619,
|
|
0x26cdac4,0x086592c,0x00f00de },
|
|
{ 0x2e90d4d,0x3ed703c,0x2c648d7,0x29ddf67,0x000e219,0x3471247,
|
|
0x26febd5,0x1161713,0x3541a8f,0x302038d,0x08d2af9,0x26e1b21,
|
|
0x398514a,0x36dad99,0x002ed70 } },
|
|
/* 106 */
|
|
{ { 0x06f25cb,0x1104596,0x370faee,0x07e83f3,0x0f7b686,0x228d43a,
|
|
0x12cd201,0x0a1bd57,0x3e592dc,0x1e186fc,0x2226aba,0x2c63fe9,
|
|
0x17b039a,0x1efaa61,0x00d1582 },
|
|
{ 0x2e6acef,0x07d51e4,0x3ac326c,0x322b07e,0x1422c63,0x32ff5c7,
|
|
0x18760df,0x048928b,0x139b251,0x04d7da9,0x048d1a2,0x2a23e84,
|
|
0x199dbba,0x2fa7afe,0x0049f1a } },
|
|
/* 107 */
|
|
{ { 0x3492b73,0x27d3d3d,0x2b1a16f,0x07b2ce4,0x0cf28ec,0x2729bff,
|
|
0x3130d46,0x3e96116,0x140b72e,0x14a2ea3,0x1ca066f,0x3a61f1d,
|
|
0x022ebac,0x09192b4,0x003e399 },
|
|
{ 0x12555bb,0x0b6139d,0x239463a,0x12a70ab,0x2aaa93b,0x2254e72,
|
|
0x00424ec,0x26a6736,0x26daa11,0x25b5ad6,0x379f262,0x140cd30,
|
|
0x0c7d3bd,0x097bbcf,0x00899e9 } },
|
|
/* 108 */
|
|
{ { 0x3825dc4,0x3cd946f,0x0462b7f,0x31102e7,0x30f741c,0x3313ed6,
|
|
0x1ff5a95,0x15bf9dc,0x09b47fd,0x0f2e7a7,0x1626c0d,0x3c14f6d,
|
|
0x14098bd,0x19d7df8,0x00a97ce },
|
|
{ 0x0934f5e,0x3f968db,0x046f68a,0x12333bf,0x26cd5e1,0x1ea2161,
|
|
0x358570d,0x235031d,0x35edd55,0x05265e3,0x24ae00c,0x3542229,
|
|
0x25bb2a1,0x1c83c75,0x0058f2a } },
|
|
/* 109 */
|
|
{ { 0x24daedb,0x376928f,0x305266f,0x0499746,0x038318c,0x312efd7,
|
|
0x1910a24,0x33450a3,0x1c478a9,0x39d8bf9,0x12cc0ae,0x397aeab,
|
|
0x0654c08,0x095f283,0x00d2cdf },
|
|
{ 0x0b717d2,0x1f162c2,0x107a48f,0x128e1b3,0x2380718,0x39f4044,
|
|
0x00f626a,0x05ec0c9,0x21bc439,0x200fa4d,0x20aea01,0x186a1d8,
|
|
0x26372f2,0x1a91f87,0x0053f55 } },
|
|
/* 110 */
|
|
{ { 0x3512a90,0x33b958b,0x29f1c84,0x0106c3a,0x224b3c0,0x09b307a,
|
|
0x215d2de,0x3bdf43b,0x22cf0c9,0x176121d,0x1534143,0x09ba717,
|
|
0x16b3110,0x0f73f6c,0x008f5b7 },
|
|
{ 0x2c75d95,0x26fbcb4,0x0dda1f6,0x206f819,0x28d33d5,0x1fb4d79,
|
|
0x024c125,0x30a0630,0x1f9c309,0x0fe350d,0x1696019,0x0a54187,
|
|
0x09541fd,0x35e3a79,0x0066618 } },
|
|
/* 111 */
|
|
{ { 0x0e382de,0x33f5163,0x0dde571,0x3bb7a40,0x1175806,0x12ae8ed,
|
|
0x0499653,0x3b25586,0x38ade7a,0x3fa265d,0x3f4aa97,0x3c03dbb,
|
|
0x30c6de8,0x32d4042,0x00ae971 },
|
|
{ 0x2f788f1,0x1fbaf0e,0x3e2d182,0x3ff904f,0x0d46229,0x1d0726d,
|
|
0x15455b4,0x093ae28,0x290f8e4,0x097c0b9,0x1ae8771,0x28480bb,
|
|
0x04f6d40,0x3689925,0x0049b3b } },
|
|
/* 112 */
|
|
{ { 0x35b2d69,0x31819c0,0x11b0d63,0x035afb6,0x2b50715,0x2bece6c,
|
|
0x35f82f7,0x0ad987c,0x0011601,0x02e6f67,0x2d0a5f5,0x365e583,
|
|
0x2f7c900,0x11449c5,0x00ed705 },
|
|
{ 0x27abdb4,0x1bbfd04,0x301c157,0x263c079,0x36850d6,0x3f21f8b,
|
|
0x27d7493,0x0f9227e,0x06fb0ce,0x002daf3,0x37d8c1c,0x3ef87d7,
|
|
0x19cc6f4,0x0c3809c,0x00cf752 } },
|
|
/* 113 */
|
|
{ { 0x22d94ed,0x075b09c,0x020e676,0x084dc62,0x2d1ec3f,0x17439f1,
|
|
0x240b702,0x33cc596,0x30ebaf3,0x0359fe0,0x393ea43,0x0ece01e,
|
|
0x16c6963,0x03a82f2,0x0017faa },
|
|
{ 0x3866b98,0x3cd20b7,0x12d4e6b,0x3a6a76d,0x1205c1e,0x3e6ae1a,
|
|
0x2f9bbdf,0x2e61547,0x2d175ee,0x28e18f6,0x13cf442,0x085b0ef,
|
|
0x0e321ef,0x238fe72,0x003fb22 } },
|
|
/* 114 */
|
|
{ { 0x360ac07,0x26dc301,0x3f4d94f,0x2ba75e6,0x1f3c9cc,0x17ff20f,
|
|
0x0ea084c,0x30e39cf,0x143dc49,0x03bd43e,0x3c9e733,0x19e8aba,
|
|
0x27fbaf4,0x12d913a,0x005ee53 },
|
|
{ 0x3609e7f,0x2d89c80,0x09f020c,0x1558bf7,0x3098443,0x3c515fd,
|
|
0x1c8e580,0x16506bd,0x26cb4b2,0x1747d42,0x2ec8239,0x32c91f0,
|
|
0x1ca3377,0x079768f,0x00a5f3e } },
|
|
/* 115 */
|
|
{ { 0x185fa94,0x122759f,0x0e47023,0x0dcb6e7,0x10ba405,0x3b5eab4,
|
|
0x1f7a1fa,0x32d003f,0x1739a4c,0x3295ec3,0x1b18967,0x3f3b265,
|
|
0x34d2448,0x2dbadc9,0x00f30b5 },
|
|
{ 0x01c5338,0x2d1dcf2,0x2bd07cc,0x39a8fb5,0x2b85639,0x355bab6,
|
|
0x1df95f1,0x01eb5f6,0x17f0a16,0x1b895b5,0x157574d,0x29fff72,
|
|
0x3a8c46d,0x0118071,0x0065f84 } },
|
|
/* 116 */
|
|
{ { 0x3a1e7f1,0x17432f2,0x1f648d4,0x3000ad5,0x2ef0a08,0x1f86624,
|
|
0x1ca31b1,0x241f9dc,0x2cb4885,0x2b8610f,0x364ce16,0x1e5faf0,
|
|
0x0b33867,0x2cb637d,0x00816d2 },
|
|
{ 0x1aa8671,0x02c394e,0x35f5e87,0x393040a,0x39f0db3,0x1c831a5,
|
|
0x2966591,0x034a8d0,0x09e613c,0x042b532,0x018ddd6,0x3e402c9,
|
|
0x2e20e1a,0x29cb4cd,0x00e087c } },
|
|
/* 117 */
|
|
{ { 0x3a10079,0x20c7fea,0x3ff2222,0x1edb593,0x00dc5f8,0x3a32ccc,
|
|
0x1479073,0x0cfed11,0x2a2702a,0x17a056a,0x1fba321,0x235acb9,
|
|
0x149c833,0x172de7d,0x000f753 },
|
|
{ 0x2e95923,0x3b365cb,0x009f471,0x0df1b47,0x21e868b,0x199bbd3,
|
|
0x07b8ecc,0x12ff0af,0x189808a,0x3bd5059,0x3fbc4d2,0x0fa7b88,
|
|
0x1125bf2,0x0db0b5d,0x0043572 } },
|
|
/* 118 */
|
|
{ { 0x29cdb1b,0x1db656e,0x391efe1,0x004be09,0x245a1ca,0x3793328,
|
|
0x254af24,0x2f2e65d,0x10e5cc4,0x2af6fe7,0x2d97ac0,0x29f7d42,
|
|
0x19fd6f6,0x0ac184d,0x00c5211 },
|
|
{ 0x305eae3,0x36738d3,0x2c2b696,0x00ba50e,0x3903adc,0x2122f85,
|
|
0x0753470,0x1cf96a4,0x1702a39,0x247883c,0x2feb67e,0x2ab3071,
|
|
0x3c6b9e1,0x30cb85a,0x002ca0a } },
|
|
/* 119 */
|
|
{ { 0x3871eb5,0x284b93b,0x0a7affe,0x176a2fc,0x294c2f2,0x204d3aa,
|
|
0x1e4c2a7,0x3ec4134,0x2fb0360,0x3847b45,0x05fc11b,0x0a6db6e,
|
|
0x390fa40,0x2adfd34,0x005e9f7 },
|
|
{ 0x0646612,0x1b5cbcc,0x10d8507,0x0777687,0x3a0afed,0x1687440,
|
|
0x0222578,0x1af34a4,0x2174e27,0x372d267,0x11246c3,0x34769c5,
|
|
0x2044316,0x1b4d626,0x00c72d5 } },
|
|
/* 120 */
|
|
{ { 0x2e5bb45,0x3ff1d36,0x16dcdf5,0x128986f,0x399068c,0x2a63b1e,
|
|
0x0afa7aa,0x3a5b770,0x200f121,0x33b74bb,0x1414045,0x0f31ef8,
|
|
0x2f50e16,0x2f38cd6,0x00b0b1b },
|
|
{ 0x1a06293,0x035e140,0x2644d44,0x1f1954b,0x2cdebab,0x31d5f91,
|
|
0x0b8dbc8,0x38f2d23,0x3783cab,0x2a07e73,0x3123f59,0x3409846,
|
|
0x3784ddd,0x223bbac,0x003dc7b } },
|
|
/* 121 */
|
|
{ { 0x0741456,0x234e631,0x2121e1b,0x00980ca,0x3a9dfa9,0x098c916,
|
|
0x3fc86d1,0x1c63072,0x3625244,0x13d0471,0x05b0fc5,0x1487550,
|
|
0x2498596,0x11bb6ea,0x001afab },
|
|
{ 0x274b4ad,0x240aea1,0x3d12a75,0x2b56b61,0x1486b43,0x1b83426,
|
|
0x31c7363,0x35b59ca,0x207bb6c,0x38e6243,0x19bace4,0x0a26671,
|
|
0x35e3381,0x0c2ded4,0x00d8da4 } },
|
|
/* 122 */
|
|
{ { 0x2b75791,0x19590b1,0x2bfb39f,0x2988601,0x0050947,0x0d8bbe1,
|
|
0x23e3701,0x08e4432,0x2ed8c3d,0x326f182,0x332e1dd,0x12219c5,
|
|
0x2e0779b,0x367aa63,0x0012d10 },
|
|
{ 0x251b7dc,0x0a08b4d,0x1138b6f,0x2ea02af,0x06345a5,0x1cb4f21,
|
|
0x0332624,0x1d49d88,0x140acc5,0x2f55287,0x024447c,0x291ace9,
|
|
0x1a4966e,0x015cbec,0x005bc41 } },
|
|
/* 123 */
|
|
{ { 0x351cd0e,0x315e8e9,0x07d6e70,0x067ae8f,0x2190d84,0x351f556,
|
|
0x03bee79,0x31b62c7,0x266f912,0x1b6a504,0x007a6ad,0x3a6ab31,
|
|
0x3891112,0x3c45ba0,0x00d6ce5 },
|
|
{ 0x0e1f2ce,0x32a5edc,0x1434063,0x1ca084f,0x2a3e47c,0x137e042,
|
|
0x16e2418,0x2069280,0x3b0dfd8,0x35a22b5,0x289bf0a,0x1f667f2,
|
|
0x02d23a3,0x0ce688f,0x00d8e3f } },
|
|
/* 124 */
|
|
{ { 0x10bed6f,0x14c58dd,0x0b0abdf,0x0ca0f9a,0x3808abc,0x2ec228c,
|
|
0x2366275,0x12afa16,0x20f6b0e,0x37dca8e,0x3af0c6a,0x1c5b467,
|
|
0x1b25ff7,0x00814de,0x0022dcc },
|
|
{ 0x1a56e11,0x02fe37e,0x3f21740,0x35d5a91,0x06cb8ba,0x29bad91,
|
|
0x17176f7,0x2d919f2,0x0f7d1f5,0x13a3f61,0x04ddb05,0x0c82a51,
|
|
0x286f598,0x2e8c777,0x0007071 } },
|
|
/* 125 */
|
|
{ { 0x0f8fcb9,0x3e83966,0x170c6fd,0x3825343,0x089cec8,0x01b482a,
|
|
0x0993971,0x3327282,0x39aba8a,0x32456fe,0x1507e01,0x1c3252d,
|
|
0x21ffb13,0x29822a0,0x0083246 },
|
|
{ 0x23c378f,0x1cea7ef,0x1be9a82,0x224d689,0x37e5447,0x3764a75,
|
|
0x3a49724,0x361e1b3,0x19d365b,0x3a61ffb,0x1c29a7a,0x20ab251,
|
|
0x17ec549,0x175d777,0x004589a } },
|
|
/* 126 */
|
|
{ { 0x15540a9,0x2ec5d2a,0x05b09fa,0x1bc058b,0x07cfb88,0x28f7b86,
|
|
0x3e766be,0x189305e,0x01fe88e,0x23fdf69,0x0b919c3,0x02dc7ae,
|
|
0x3f9a9ad,0x0b83cc7,0x0086a52 },
|
|
{ 0x28bc259,0x39bdca1,0x39e4bc8,0x0e0f33b,0x16130c6,0x2919955,
|
|
0x31f4549,0x2fed027,0x30919b2,0x0a39b03,0x0ca7bb2,0x1711b24,
|
|
0x3b67b94,0x05a136b,0x00acd87 } },
|
|
/* 127 */
|
|
{ { 0x0c53841,0x31cb284,0x3ced090,0x06d5693,0x1c20ae0,0x0408d2b,
|
|
0x37ebd5e,0x081900f,0x26a8589,0x0acfd0a,0x34a1472,0x2f0c302,
|
|
0x124ccbd,0x10de328,0x00971bc },
|
|
{ 0x17ff2ff,0x27d1b54,0x147b6f7,0x38bb2ea,0x26a9c96,0x0a49448,
|
|
0x39f2f46,0x247c579,0x3b16a4e,0x28c2a5a,0x2d4c72d,0x11f248c,
|
|
0x1e4df11,0x047d604,0x0065bc3 } },
|
|
/* 128 */
|
|
{ { 0x39b3239,0x1f75f44,0x3bae87c,0x139360c,0x18b5782,0x3ffc005,
|
|
0x3c48789,0x2bc6af2,0x38b909e,0x223ff3b,0x31443a7,0x017d3bb,
|
|
0x0bfed99,0x128b857,0x00020dd },
|
|
{ 0x306d695,0x25a7b28,0x2f60ca2,0x2b6e4f2,0x1df940c,0x1fa9b8e,
|
|
0x37fab78,0x13f959f,0x10ff98c,0x38343b8,0x019cb91,0x11a1e6b,
|
|
0x17ab4c6,0x1431f47,0x004b4ea } },
|
|
/* 129 */
|
|
{ { 0x20db57e,0x102515e,0x170219e,0x2b66a32,0x1e6017c,0x2f973fe,
|
|
0x3739e51,0x0e28b6f,0x3cda7a9,0x30d91ac,0x28350df,0x1444215,
|
|
0x098b504,0x1bcd5b8,0x00ad3bd },
|
|
{ 0x22e3e3e,0x3aeaffb,0x26cb935,0x0091ce4,0x2fbd017,0x3a7ed6a,
|
|
0x335b029,0x3bfc1f1,0x3852e3f,0x2b14a86,0x046b405,0x266af4c,
|
|
0x3997191,0x33b0e40,0x00e306f } },
|
|
/* 130 */
|
|
{ { 0x3e4712c,0x26bb208,0x18eed6d,0x1b30f06,0x27ca837,0x06faf62,
|
|
0x1831873,0x3fbcf9b,0x3f3d88b,0x1fb55eb,0x0f44edc,0x29917bb,
|
|
0x3151772,0x342d72e,0x00d4e63 },
|
|
{ 0x2ee0ecf,0x39e8733,0x2e8e98c,0x0cd4e0f,0x08f0126,0x1ad157a,
|
|
0x079078a,0x23018ee,0x196c765,0x2b2f34f,0x0783336,0x075bf9c,
|
|
0x3713672,0x098d699,0x00f21a7 } },
|
|
/* 131 */
|
|
{ { 0x186ba11,0x22cf365,0x048019d,0x2ca2970,0x0d9e0ae,0x08c3bd7,
|
|
0x261dbf2,0x2fc2790,0x1ee02e6,0x10256a7,0x00dc778,0x18dc8f2,
|
|
0x157b189,0x2ebc514,0x005c97d },
|
|
{ 0x3c4503e,0x1d10d12,0x337097e,0x0c6169a,0x30fb1cb,0x3481752,
|
|
0x0df2bec,0x19768fa,0x1bcf8f7,0x2925f74,0x2c988a1,0x3be571d,
|
|
0x04cfa92,0x2ea9937,0x003f924 } },
|
|
/* 132 */
|
|
{ { 0x268b448,0x06e375c,0x1b946bf,0x287bf5e,0x3d4c28b,0x138d547,
|
|
0x21f8c8e,0x21ea4be,0x2d45c91,0x35da78e,0x00326c0,0x210ed35,
|
|
0x1d66928,0x0251435,0x00fefc8 },
|
|
{ 0x0339366,0x216ff64,0x2c3a30c,0x3c5733d,0x04eeb56,0x2333477,
|
|
0x32b1492,0x25e3839,0x1b5f2ce,0x0dcfba1,0x3165bb2,0x3acafcc,
|
|
0x10abfcd,0x248d390,0x008106c } },
|
|
/* 133 */
|
|
{ { 0x102f4ee,0x3c0585f,0x1225c8d,0x11c6388,0x08a7815,0x2b3e790,
|
|
0x2895eb6,0x18cf53a,0x0b56e5a,0x2e2c003,0x3e981ff,0x0761b55,
|
|
0x1bc32f3,0x0a7111d,0x00f5c80 },
|
|
{ 0x3568973,0x1587386,0x16ec764,0x20698a6,0x02f809b,0x2821502,
|
|
0x113d64d,0x38c2679,0x15de61c,0x0309f60,0x272999e,0x29bfe64,
|
|
0x173f70d,0x1de7fab,0x00bd284 } },
|
|
/* 134 */
|
|
{ { 0x31cdf2b,0x0f0be66,0x2151603,0x01af17e,0x32a99cf,0x085dece,
|
|
0x27d2591,0x1520df4,0x273c448,0x1ec7c54,0x102e229,0x355f604,
|
|
0x2acb75f,0x005f1fd,0x003d43e },
|
|
{ 0x270eb28,0x22ec2ce,0x306b41a,0x238fa02,0x167de2d,0x030a379,
|
|
0x245a417,0x1808c24,0x0b1a7b2,0x3ab5f6f,0x2cbc6c1,0x2c228d4,
|
|
0x3041f70,0x2d9a6cc,0x00b504f } },
|
|
/* 135 */
|
|
{ { 0x17a27c2,0x216ad7e,0x011ba8e,0x22f0428,0x16ac5ec,0x3ef3c58,
|
|
0x345533f,0x0298155,0x2856579,0x0005e03,0x19ee75b,0x146fe16,
|
|
0x29881e4,0x18ece70,0x008907a },
|
|
{ 0x20189ed,0x119ce09,0x35cb76d,0x0d91ef4,0x2284a44,0x032ad87,
|
|
0x0e8c402,0x3c82b5d,0x38c416c,0x398992f,0x1fd820c,0x169b255,
|
|
0x3b5fcfa,0x1343c92,0x00fa715 } },
|
|
/* 136 */
|
|
{ { 0x33f5034,0x20b3b26,0x28fd184,0x16b3679,0x3962d44,0x15d1bc8,
|
|
0x2fb1d69,0x1292c99,0x25a58c9,0x1b19ab7,0x2d68a5b,0x2f6a09b,
|
|
0x0d6aedb,0x2935eac,0x0005664 },
|
|
{ 0x25e32fc,0x13f9440,0x3252bcd,0x2fea5b7,0x161a5ae,0x0564a8c,
|
|
0x0a07e23,0x1545f62,0x0de9890,0x1d76765,0x1fd440e,0x2ed0041,
|
|
0x3db4c96,0x1e8ba01,0x001b0c4 } },
|
|
/* 137 */
|
|
{ { 0x0223878,0x29ab202,0x15585c2,0x1a79969,0x1ba08c2,0x2ef09ff,
|
|
0x2b1b9b9,0x181f748,0x1bf72b9,0x224645c,0x2588dc5,0x2d157e7,
|
|
0x22d939a,0x05b88d9,0x006d549 },
|
|
{ 0x31de0c1,0x23a4e0e,0x278f8da,0x1aa013c,0x1a84d18,0x0d185a5,
|
|
0x0988ccd,0x2c32efd,0x3bee10e,0x37d7ab8,0x3f2a66e,0x3e2da3e,
|
|
0x1b5701f,0x3d9f0c1,0x00a68da } },
|
|
/* 138 */
|
|
{ { 0x0b2e045,0x0133fd1,0x05d4c10,0x0d92c70,0x391b5e1,0x2292281,
|
|
0x2e40908,0x2ec694e,0x195ea11,0x29cfeca,0x3d93a4e,0x01215c0,
|
|
0x08a5f32,0x37a0eff,0x00cce45 },
|
|
{ 0x2b3106e,0x12a5fb0,0x0b4faff,0x0c2da12,0x09069c6,0x35d8907,
|
|
0x2837a6e,0x3db3fb6,0x3136cc3,0x222836b,0x3da018a,0x2741274,
|
|
0x13ba319,0x1ac7642,0x00f867c } },
|
|
/* 139 */
|
|
{ { 0x2527296,0x10a9595,0x178de4d,0x0f739c4,0x0ae26c7,0x3094599,
|
|
0x20adac6,0x2b875c2,0x3ae5dc0,0x3e04d20,0x1aab2da,0x1d3ab37,
|
|
0x15f4f75,0x0b730b5,0x00c56b5 },
|
|
{ 0x1f32923,0x2f059e5,0x2a89872,0x2056f74,0x04be175,0x1da67c0,
|
|
0x17f1e7a,0x3780a6d,0x0723ac2,0x257f367,0x1237773,0x2bcee86,
|
|
0x0b97f83,0x38aff14,0x00a64d4 } },
|
|
/* 140 */
|
|
{ { 0x2552b40,0x0b6b883,0x12e8217,0x0974d35,0x062f497,0x1e563e6,
|
|
0x30ee400,0x375d1e4,0x290751f,0x0d5b68a,0x353e48c,0x064a0d3,
|
|
0x3c343f1,0x309a394,0x0034d2a },
|
|
{ 0x3111286,0x0f08604,0x1827107,0x0536a76,0x0201dac,0x3a574de,
|
|
0x2c29dbe,0x382c7b0,0x1191f3e,0x324c5bc,0x144ce71,0x24327c1,
|
|
0x1212778,0x22bc9d8,0x00d7713 } },
|
|
/* 141 */
|
|
{ { 0x34ad1cd,0x1179b4e,0x1bc1780,0x1392a92,0x2cd86b9,0x359de85,
|
|
0x251f1df,0x0da5d5f,0x135fa61,0x0f64a42,0x34f4d89,0x0fe564c,
|
|
0x3cf9b7a,0x122d757,0x008c9c2 },
|
|
{ 0x370d4e9,0x0e9209b,0x0ae99f2,0x1518c64,0x0172734,0x2c20692,
|
|
0x1d7c135,0x149c52f,0x38928d6,0x3c78b78,0x25841d1,0x2eaa897,
|
|
0x372e50b,0x29e5d19,0x00c4c18 } },
|
|
/* 142 */
|
|
{ { 0x13375ac,0x389a056,0x211310e,0x2f9f757,0x04f3288,0x103cd4e,
|
|
0x17b2fb2,0x2c78a6a,0x09f1de6,0x23e8442,0x1351bc5,0x1b69588,
|
|
0x285b551,0x0464b7e,0x00573b6 },
|
|
{ 0x0ba7df5,0x259a0db,0x2b4089e,0x05630a2,0x3f299be,0x350ff2f,
|
|
0x1c9348a,0x3becfa4,0x3cc9a1c,0x17a6ef1,0x338b277,0x2b761d9,
|
|
0x2aa01c8,0x3cb9dd7,0x006e3b1 } },
|
|
/* 143 */
|
|
{ { 0x277788b,0x16a222d,0x173c036,0x310ff58,0x2634ae8,0x392636f,
|
|
0x0987619,0x1e6acc1,0x26dc8f7,0x242310f,0x0c09aca,0x22b8e11,
|
|
0x0d17006,0x1c2c806,0x002380c },
|
|
{ 0x297c5ec,0x1fef0e8,0x3948cf7,0x14f2915,0x2dacbc8,0x0dafb1f,
|
|
0x10de043,0x31184da,0x06414ee,0x3c9aeeb,0x1f713ab,0x308f1f8,
|
|
0x1569ed1,0x3f379bf,0x00f08bb } },
|
|
/* 144 */
|
|
{ { 0x0770ee3,0x058fd21,0x17065f8,0x251d128,0x10e0c7f,0x06cb51b,
|
|
0x0f05f7e,0x3666a72,0x3e7d01f,0x2d05fab,0x11440e5,0x28577d4,
|
|
0x2fbcf2b,0x14aa469,0x00dc5c5 },
|
|
{ 0x270f721,0x1c75d28,0x085b862,0x1d68011,0x132c0a0,0x37be81d,
|
|
0x1a87e38,0x083fa74,0x3acbf0d,0x16d6429,0x0feda1f,0x031070a,
|
|
0x2ec2443,0x21e563d,0x00454d2 } },
|
|
/* 145 */
|
|
{ { 0x0525435,0x1e98d5f,0x3dbc52b,0x1fcdf12,0x13d9ef5,0x3ff311d,
|
|
0x393e9ed,0x3cef8ae,0x2987710,0x3bdee2e,0x21b727d,0x3ba1b68,
|
|
0x10d0142,0x3c64b92,0x0055ac3 },
|
|
{ 0x0c1c390,0x38e9bb0,0x1e7b487,0x11511b3,0x1036fb3,0x25aba54,
|
|
0x1eb2764,0x048d022,0x0d971ed,0x1bb7fb5,0x100f0b4,0x06c3756,
|
|
0x2f0d366,0x3c6e160,0x0011bd6 } },
|
|
/* 146 */
|
|
{ { 0x36bc9d1,0x24d43c1,0x12c35cf,0x2fb3cf3,0x015d903,0x16bc0c7,
|
|
0x0fc8c22,0x3195c87,0x2488b1c,0x1f82b4c,0x30014e8,0x27ee58d,
|
|
0x31658dd,0x1684a5f,0x00f0f3a },
|
|
{ 0x1f703aa,0x023eebc,0x20babb9,0x080bd9d,0x12f9cc4,0x1a8e2d4,
|
|
0x0eec666,0x1176803,0x33005d6,0x1137b68,0x37de339,0x33d71cb,
|
|
0x0c906b9,0x14086b5,0x00aeef6 } },
|
|
/* 147 */
|
|
{ { 0x219045d,0x0f22c5e,0x024c058,0x00b414a,0x0ae7c31,0x3db3e96,
|
|
0x234979f,0x0cf00a8,0x3c962c7,0x27fa77f,0x1c0c4b0,0x1fe8942,
|
|
0x218053a,0x1eed3f8,0x0051643 },
|
|
{ 0x2a23ddb,0x138f570,0x104e945,0x21ca270,0x30726d8,0x3f45490,
|
|
0x37d9184,0x242ea25,0x33f6d77,0x3f15679,0x065af85,0x34fa1f5,
|
|
0x2e46b8f,0x31d17fb,0x00a2615 } },
|
|
/* 148 */
|
|
{ { 0x335167d,0x181ea10,0x0887c8d,0x01383d7,0x18b42d8,0x263447e,
|
|
0x1f13df3,0x0319d7e,0x0872074,0x2d6aa94,0x23d9234,0x36a69aa,
|
|
0x0bad183,0x3138a95,0x00bd3a5 },
|
|
{ 0x1b0f658,0x0e4530b,0x373add1,0x1b968fc,0x329dcb6,0x09169ca,
|
|
0x162df55,0x0211eff,0x02391e4,0x3867460,0x3136b1a,0x37dd36e,
|
|
0x3bc5bd9,0x2dacfe4,0x0072a06 } },
|
|
/* 149 */
|
|
{ { 0x119d96f,0x067b0eb,0x00996da,0x293eca9,0x2b342da,0x1889c7a,
|
|
0x21633a6,0x0152c39,0x281ce8c,0x18ef3b3,0x0bd62dc,0x3238186,
|
|
0x38d8b7c,0x3867b95,0x00ae189 },
|
|
{ 0x0ed1eed,0x1e89777,0x13ab73e,0x029e1d7,0x2c1257f,0x33fbc09,
|
|
0x32d5a21,0x3d870b2,0x39bb1fd,0x33663bc,0x24e83e6,0x239bda4,
|
|
0x3088bcd,0x01db1ed,0x00d71e7 } },
|
|
/* 150 */
|
|
{ { 0x14245bf,0x0da0c27,0x153b339,0x05cab0a,0x122d962,0x1b0f0f3,
|
|
0x3f5a825,0x267a2ce,0x2910d06,0x254326f,0x0f36645,0x025118e,
|
|
0x37c35ec,0x36e944e,0x006c056 },
|
|
{ 0x05ab0e3,0x29aa0c1,0x1295687,0x1fd1172,0x08d40b5,0x05bd655,
|
|
0x345048a,0x02a1c3c,0x2393d8f,0x0992d71,0x1f71c5e,0x18d4e8a,
|
|
0x30dd410,0x11d61d3,0x00dd58b } },
|
|
/* 151 */
|
|
{ { 0x2230c72,0x30213d8,0x05e367e,0x329204e,0x0f14f6c,0x3369ddd,
|
|
0x0bb4074,0x2edafd6,0x1b1aa2d,0x0785404,0x0c035ab,0x220da74,
|
|
0x1f2fdd4,0x092a091,0x00ef83c },
|
|
{ 0x3dc2538,0x1cca3e7,0x246afb5,0x24c647f,0x0798082,0x0bb7952,
|
|
0x0f5c443,0x008b38a,0x299ea1a,0x3c6cf36,0x3df2ec7,0x398e6dc,
|
|
0x29a1839,0x1cadd83,0x0077b62 } },
|
|
/* 152 */
|
|
{ { 0x25d56d5,0x3546f69,0x16e02b1,0x3e5fa9a,0x03a9b71,0x2413d31,
|
|
0x250ecc9,0x1d2de54,0x2ebe757,0x2a2f135,0x2aeeb9a,0x0d0fe2b,
|
|
0x204cb0e,0x07464c3,0x00c473c },
|
|
{ 0x24cd8ae,0x0c86c41,0x221c282,0x0795588,0x1f4b437,0x06fc488,
|
|
0x0c81ecd,0x020bf07,0x3a9e2c8,0x2294a81,0x3a64a95,0x0363966,
|
|
0x32c9a35,0x0f79bec,0x0029e4f } },
|
|
/* 153 */
|
|
{ { 0x289aaa5,0x2755b2e,0x059e0aa,0x3031318,0x0f0208a,0x35b7729,
|
|
0x00d9c6b,0x3dd29d0,0x075f2c2,0x0ece139,0x31562dd,0x04187f2,
|
|
0x13b8d4c,0x0920b85,0x003924e },
|
|
{ 0x09808ab,0x2e36621,0x2a36f38,0x1829246,0x229bf32,0x20883b7,
|
|
0x159ada8,0x3108a14,0x15bbe5b,0x1e2d1e4,0x1730096,0x0d35cbb,
|
|
0x15d0da9,0x0e60b94,0x00c4f30 } },
|
|
/* 154 */
|
|
{ { 0x31de38b,0x27b9086,0x2760e3e,0x169098d,0x2a124e2,0x00596c6,
|
|
0x3f73c09,0x0d31642,0x2341464,0x248600a,0x2e1fa10,0x2aa0fc8,
|
|
0x051e954,0x00f3b67,0x001d4bd },
|
|
{ 0x18751e6,0x25a8e1e,0x07f5c2d,0x17e30d4,0x0ed2723,0x23093e2,
|
|
0x3b80e2c,0x13de2d7,0x2fad37f,0x1be1cfb,0x3224ba9,0x0a7f5d3,
|
|
0x1714972,0x06667b7,0x009dcd9 } },
|
|
/* 155 */
|
|
{ { 0x294f22a,0x3e06993,0x0341ee9,0x24bdc7b,0x2e56098,0x2660a13,
|
|
0x018ddda,0x2c261b2,0x2953b54,0x267f51c,0x0e8a7cc,0x29ab00c,
|
|
0x3a38247,0x397ac81,0x00de684 },
|
|
{ 0x36b956b,0x347b34a,0x35834bd,0x053c06c,0x0090844,0x148cec5,
|
|
0x380b325,0x2f17b8b,0x054ef5e,0x09683fb,0x3f8b29a,0x33c979a,
|
|
0x1e01474,0x3e81fca,0x001c757 } },
|
|
/* 156 */
|
|
{ { 0x30fdfe4,0x2d712ba,0x13671bc,0x2cfc226,0x3d7c649,0x16f020e,
|
|
0x368e3f0,0x2981ebb,0x246a78a,0x115e81b,0x21223a4,0x04dbb30,
|
|
0x1a50ba2,0x12114bd,0x0089bd6 },
|
|
{ 0x055f15a,0x1046e51,0x00fd724,0x1c022a7,0x323dfa9,0x36d8efb,
|
|
0x0da4d16,0x0910dec,0x2c1fb16,0x2dbe29f,0x298284f,0x2b273bb,
|
|
0x26022c1,0x20accd5,0x00085a5 } },
|
|
/* 157 */
|
|
{ { 0x01f138a,0x2d87e7b,0x0c2815c,0x0c19a3c,0x311c9a2,0x3e4fce3,
|
|
0x029729d,0x21236b2,0x2984048,0x3f3bc95,0x2bba8fb,0x1a1b680,
|
|
0x0619a3f,0x29e0447,0x00ed5fe },
|
|
{ 0x2d1c833,0x3dcef35,0x3f809b4,0x01a1b9e,0x1509516,0x10ac754,
|
|
0x2735080,0x27b0a8a,0x2495fb8,0x0a7bdba,0x1ef8b89,0x00233a5,
|
|
0x0568bf1,0x1a126ba,0x0078a7e } },
|
|
/* 158 */
|
|
{ { 0x0470cd8,0x20e9f04,0x30003fe,0x20be1b7,0x1927346,0x2a5026d,
|
|
0x1ac06bd,0x2717ed7,0x2609493,0x3079ea5,0x1cc116d,0x31b0541,
|
|
0x2c8ccde,0x10219ae,0x001a52b },
|
|
{ 0x2864045,0x0e8d95b,0x2fc1530,0x0aa44e7,0x345eae7,0x3cc7553,
|
|
0x3ec6466,0x229b60e,0x06f6e95,0x00bed2a,0x0ff4403,0x181c639,
|
|
0x2e0df67,0x1f8fa46,0x0000811 } },
|
|
/* 159 */
|
|
{ { 0x04310a2,0x20cee8e,0x09fc5d5,0x3707f5b,0x0bdfb4e,0x12713ee,
|
|
0x24f1028,0x0787ee6,0x39a581c,0x3797ec8,0x10a9746,0x112cb9f,
|
|
0x142b9ba,0x1da0ef6,0x0078f7b },
|
|
{ 0x07607ae,0x3232872,0x2a7e076,0x0bb572a,0x182b23c,0x1d8f918,
|
|
0x181f392,0x37c45a9,0x24a3886,0x0b2a297,0x264e7f2,0x1fa433c,
|
|
0x0fcfcc8,0x21c0857,0x0004f74 } },
|
|
/* 160 */
|
|
{ { 0x01d161c,0x1744585,0x2d17528,0x03a4f13,0x267cd2e,0x30d861f,
|
|
0x062a647,0x213284b,0x139ed25,0x27d4ca5,0x02fbbd6,0x31ddf11,
|
|
0x3c50ac4,0x1dd86f7,0x00107de },
|
|
{ 0x16beebd,0x1b7317a,0x2151997,0x256a196,0x3be2aff,0x3621cab,
|
|
0x0a9da19,0x05f3038,0x23da63c,0x3178d5e,0x215cc67,0x07f7f63,
|
|
0x0c6d8d3,0x3bf5e5c,0x00c44bb } },
|
|
/* 161 */
|
|
{ { 0x00c62f1,0x3e0f893,0x1572703,0x3b93865,0x19b1e28,0x389b33b,
|
|
0x02858bf,0x0e3e9aa,0x04bc436,0x234e072,0x25ba43d,0x3dca19e,
|
|
0x0274394,0x20f442e,0x003b4a7 },
|
|
{ 0x176451e,0x2b5ed5d,0x35c8ee1,0x25c52da,0x0c3d0b5,0x32b306e,
|
|
0x030954f,0x275ecf7,0x10e472c,0x21577c4,0x02f8a32,0x321bb5c,
|
|
0x0098f97,0x104e237,0x00d0433 } },
|
|
/* 162 */
|
|
{ { 0x0a8f2fe,0x034548b,0x141f1a6,0x121246f,0x1616409,0x237f80d,
|
|
0x2e29a55,0x1218db6,0x3ea278e,0x1669856,0x1ad7c8e,0x36d11de,
|
|
0x2c2fcbb,0x18c0b3a,0x001c706 },
|
|
{ 0x1699b4b,0x2d531a6,0x17e85e2,0x1b48e78,0x2b509ca,0x2818ea0,
|
|
0x0165fee,0x0b809ca,0x09db6a2,0x3dad798,0x326ee1d,0x204e416,
|
|
0x091fa12,0x1c890e5,0x0007b9f } },
|
|
/* 163 */
|
|
{ { 0x0ff4e49,0x0bb0512,0x0129159,0x05db591,0x03e4e9f,0x055ab30,
|
|
0x0f82881,0x0ac2deb,0x3a8bb09,0x356a8d2,0x3d38393,0x03e4089,
|
|
0x38187cd,0x1377a93,0x0041672 },
|
|
{ 0x0139e73,0x3990730,0x187d3c4,0x33e4793,0x2e0fe46,0x2ad87e2,
|
|
0x33c792c,0x21d4fb6,0x1e4d386,0x2932d1b,0x20f1098,0x1270874,
|
|
0x0ea6ee4,0x0167d6e,0x005e5fd } },
|
|
/* 164 */
|
|
{ { 0x1856031,0x2b7519d,0x3bd07fc,0x337abcb,0x089c7a4,0x2a1f120,
|
|
0x3523ce7,0x2ba406b,0x09561d9,0x1797f04,0x3cdb95f,0x2d6193e,
|
|
0x32c7d3f,0x223aed6,0x00beb51 },
|
|
{ 0x2e65825,0x158f0ce,0x16413d1,0x310395f,0x3116854,0x250baf4,
|
|
0x373d341,0x156cc47,0x104c069,0x0893716,0x195a0a6,0x035320e,
|
|
0x37b7d8a,0x21b5755,0x00fb26b } },
|
|
/* 165 */
|
|
{ { 0x286ae17,0x04239f1,0x1a56c53,0x0e74707,0x29090d7,0x2bb142b,
|
|
0x03b0139,0x1aac916,0x08ba49a,0x0376682,0x3382f85,0x064bbab,
|
|
0x2910e28,0x1d5bd7f,0x00cc8df },
|
|
{ 0x0ab7630,0x208e8e7,0x3fc1877,0x26bee39,0x264984a,0x192ff05,
|
|
0x08ef9c3,0x0aa6951,0x071c44e,0x26eed3e,0x035c95e,0x06906ad,
|
|
0x10a0690,0x397eaa9,0x00c6c23 } },
|
|
/* 166 */
|
|
{ { 0x034d8dd,0x005b064,0x279bb78,0x12c2c4f,0x1856bb4,0x0c90681,
|
|
0x06409ab,0x3b48617,0x19a2d78,0x0a34bf8,0x326eddf,0x31f09b5,
|
|
0x04f04dc,0x3d7c944,0x003ccaf },
|
|
{ 0x321f843,0x35fb71a,0x1e4c397,0x377a5d7,0x2da88e4,0x3d6ada7,
|
|
0x33d3964,0x1b30149,0x0e39aae,0x054dda0,0x3e6f946,0x1273394,
|
|
0x3ffd3f7,0x2f6655e,0x00021dd } },
|
|
/* 167 */
|
|
{ { 0x37233cf,0x11617dd,0x26f07b6,0x3d8250a,0x0fe6771,0x3f9bbbc,
|
|
0x2aba7ad,0x200a58d,0x3568603,0x198eefa,0x1e8fcf3,0x3b9610b,
|
|
0x20524ac,0x2a67528,0x0048d9a },
|
|
{ 0x1a5e57a,0x1e9d303,0x16c9cff,0x0f39527,0x3c23259,0x03c8a1e,
|
|
0x104bccf,0x182d5a1,0x18dbc83,0x05b5f42,0x1b402f4,0x317c525,
|
|
0x11bf1ea,0x3c46e1f,0x0061936 } },
|
|
/* 168 */
|
|
{ { 0x0153a9d,0x36859ee,0x2cf0aa9,0x2b27a0f,0x0a49fe3,0x2d984e1,
|
|
0x018f8e1,0x1378453,0x1ab3843,0x1987093,0x283dae9,0x25cf0e8,
|
|
0x14fc93d,0x280609d,0x00c99ba },
|
|
{ 0x026b1e3,0x34663d3,0x2202477,0x21a9d45,0x212e8e1,0x18ab77e,
|
|
0x2e52f63,0x0a14ce1,0x295c396,0x00c7a3d,0x2aaedb6,0x30abc4d,
|
|
0x374acde,0x1318a73,0x00fcfdb } },
|
|
/* 169 */
|
|
{ { 0x0a40298,0x3ba5633,0x11956b3,0x14fcbd7,0x3c38781,0x34bab96,
|
|
0x165630e,0x1f3c831,0x37e3a69,0x2b4226c,0x2d5029e,0x3b4ab1e,
|
|
0x1da6ac2,0x3eb43c3,0x007e5cd },
|
|
{ 0x1b86202,0x109b7f6,0x2054f98,0x2c50cd7,0x2ed1960,0x3c518e7,
|
|
0x1b02463,0x319c07f,0x1c30db6,0x045fdc2,0x373421e,0x31a1eb9,
|
|
0x1a8acbf,0x31289b0,0x0013fef } },
|
|
/* 170 */
|
|
{ { 0x3fa0a5f,0x068661f,0x2109e36,0x00b18ff,0x1f4b261,0x31d3844,
|
|
0x0acbc56,0x3aebc99,0x1fa77ab,0x152bd11,0x24cddb7,0x2313f74,
|
|
0x06eea44,0x15f5114,0x000b131 },
|
|
{ 0x2e9993d,0x1ac565c,0x2cbe22a,0x3921797,0x12c3c57,0x360f868,
|
|
0x33560bf,0x320ee99,0x382c3b8,0x39af88f,0x00bbe38,0x2c4ea59,
|
|
0x3399b40,0x00ceb45,0x0066eea } },
|
|
/* 171 */
|
|
{ { 0x0c6c693,0x31ba56d,0x3d3849f,0x378dabd,0x0efc735,0x17f90bf,
|
|
0x13343d3,0x2df0f81,0x27c6a9a,0x13c2a90,0x0a0fcb2,0x27c10d9,
|
|
0x3bc50c7,0x090e4fa,0x0016287 },
|
|
{ 0x2927e1e,0x35af405,0x184c5c3,0x3499cee,0x240158e,0x33522e6,
|
|
0x386fc84,0x0a0b69f,0x1a660ea,0x34590fb,0x22a1bee,0x2ce4fab,
|
|
0x31a9445,0x0e78655,0x00664c8 } },
|
|
/* 172 */
|
|
{ { 0x3eeaf94,0x115d409,0x21e7577,0x097aa67,0x22875c9,0x021ab7a,
|
|
0x27e7ba5,0x1093f04,0x2a086fe,0x05d9494,0x2b6c028,0x10f31b0,
|
|
0x1312d11,0x262759c,0x00c9bb2 },
|
|
{ 0x1acb0a5,0x30cdf14,0x0f78880,0x0574f18,0x1a37109,0x098adbb,
|
|
0x2113c09,0x2060925,0x1f89ce4,0x1974976,0x3381358,0x2dab5ca,
|
|
0x2159c53,0x3af1303,0x000ea3b } },
|
|
/* 173 */
|
|
{ { 0x1e49bea,0x29142b1,0x1a59cab,0x055f017,0x0684e54,0x39eb0db,
|
|
0x29cab9d,0x255ee8b,0x35f2e6f,0x05329e6,0x09b817b,0x1ec091c,
|
|
0x1df0fef,0x2641f62,0x00eb304 },
|
|
{ 0x2fe5096,0x3dcc1d1,0x2aaf508,0x3a0b813,0x0695810,0x144bddb,
|
|
0x2f1bd93,0x281ae23,0x3513ebc,0x1ddd984,0x0cf158b,0x35218eb,
|
|
0x257daf7,0x391253b,0x00b2a81 } },
|
|
/* 174 */
|
|
{ { 0x153e6ba,0x22396db,0x0ea2ff2,0x2a45121,0x0a90de1,0x34cf23b,
|
|
0x2db60ce,0x1a900be,0x2f328b6,0x355e75b,0x2c24372,0x0b75b77,
|
|
0x2ec7d4f,0x3f24759,0x00e9e33 },
|
|
{ 0x39eab6e,0x2267480,0x3b5e110,0x1e8fa5e,0x2a31a66,0x3f739a3,
|
|
0x00166dc,0x3552d88,0x3ae5137,0x3efa0fa,0x0800acd,0x17df61d,
|
|
0x38c8608,0x04cc31b,0x00cf4ab } },
|
|
/* 175 */
|
|
{ { 0x31e08fb,0x1961164,0x22c003f,0x078541b,0x3643855,0x30da587,
|
|
0x11f0dc9,0x324595e,0x329e3dc,0x29a041e,0x3495d2c,0x0908dd3,
|
|
0x1895b83,0x198dbb9,0x00d8cfb },
|
|
{ 0x0349b1b,0x383c5a8,0x2b86525,0x1b1283e,0x133cd2c,0x2be376a,
|
|
0x012ee82,0x1eb4d1b,0x0ba71e9,0x01f3109,0x37621eb,0x1d9b77c,
|
|
0x0d39069,0x3d5a97c,0x0095565 } },
|
|
/* 176 */
|
|
{ { 0x20f5e94,0x1eefc86,0x1327e0e,0x054760b,0x2f771e1,0x3ac447e,
|
|
0x033e3dc,0x198e040,0x04dd342,0x1b49a5d,0x00d01ef,0x3cb6768,
|
|
0x1ceafbd,0x31c6812,0x001cb80 },
|
|
{ 0x221c677,0x060ca27,0x398b17f,0x0146723,0x36452af,0x02d9e65,
|
|
0x39c5f78,0x3cf50d6,0x0be40f8,0x2970b87,0x26d667c,0x3e45959,
|
|
0x16e7943,0x01673e7,0x009faaa } },
|
|
/* 177 */
|
|
{ { 0x2078fe6,0x0918602,0x11dd8ad,0x399193f,0x0f6cc73,0x0f8dd12,
|
|
0x2ce34dc,0x06d7d34,0x0c5e327,0x0989254,0x2fc5af7,0x2443d7b,
|
|
0x32bc662,0x2fe2a84,0x008b585 },
|
|
{ 0x039327f,0x08e616a,0x252f117,0x1f52ab0,0x234e2d2,0x0a5b313,
|
|
0x2f59ef6,0x0f7a500,0x15c4705,0x2c02b81,0x28b4f09,0x08aa5c8,
|
|
0x0180efc,0x0993e83,0x00a9e86 } },
|
|
/* 178 */
|
|
{ { 0x0310ecc,0x2d8892f,0x14ed0b7,0x3c59fe8,0x08a1a74,0x0850e57,
|
|
0x1d09607,0x044a21f,0x109f5c9,0x237c6cf,0x06b264a,0x3fc8f1a,
|
|
0x0d4c539,0x2740f96,0x00dc2d4 },
|
|
{ 0x1d6f501,0x0adf4ea,0x14f7215,0x0930102,0x3f4c32e,0x24e2643,
|
|
0x366596d,0x081ff18,0x38f94fb,0x2c21341,0x328594c,0x267c75c,
|
|
0x196b3fd,0x29932cb,0x0036def } },
|
|
/* 179 */
|
|
{ { 0x3ed7cbe,0x26de044,0x3d0e461,0x0565e12,0x295e500,0x31dc17f,
|
|
0x32251c2,0x3420ca8,0x3995f0d,0x2e8ddab,0x0361a45,0x10971b0,
|
|
0x11e7b55,0x33bc7ca,0x00812d2 },
|
|
{ 0x3d94972,0x1606817,0x0383ccf,0x0e795b7,0x026e20e,0x0f6fefc,
|
|
0x13685d6,0x315d402,0x0cc36b8,0x1c7f059,0x390ef5e,0x316ae04,
|
|
0x08c66b9,0x2fac9a4,0x0040086 } },
|
|
/* 180 */
|
|
{ { 0x3e3c115,0x153de4d,0x1a8ae5e,0x2330511,0x169b8ee,0x1d965c2,
|
|
0x2edff2b,0x3ef99e6,0x1631b46,0x1f8a238,0x118d7bb,0x12113c3,
|
|
0x26424db,0x0f4122a,0x00e0ea2 },
|
|
{ 0x3d80a73,0x30393bc,0x0f98714,0x278ef59,0x087a0aa,0x3b18c20,
|
|
0x04b8a82,0x2068e21,0x030255d,0x3382b27,0x055397f,0x05448dd,
|
|
0x2015586,0x1190be0,0x000b979 } },
|
|
/* 181 */
|
|
{ { 0x2e03080,0x2895692,0x09fb127,0x2d1602a,0x1232306,0x105bd4e,
|
|
0x28cd6a6,0x0a83813,0x1ee13b0,0x2abadc3,0x0c09684,0x00e33e1,
|
|
0x033eea3,0x30f0a39,0x00a710e },
|
|
{ 0x01b1f7d,0x1c959da,0x017077a,0x254bf0a,0x086fbce,0x15cd6b2,
|
|
0x008683f,0x23a4f4d,0x22a6bd6,0x14e8c93,0x0027d15,0x31d0d4f,
|
|
0x271777e,0x1533510,0x00ab603 } },
|
|
/* 182 */
|
|
{ { 0x34c209d,0x14d0abb,0x270432a,0x1d02358,0x22ba752,0x209757f,
|
|
0x34af6fc,0x1ffc52e,0x1ced28e,0x1870e46,0x1e0340f,0x3f0bf73,
|
|
0x33ba91d,0x2ebca7c,0x00c6580 },
|
|
{ 0x1d442cb,0x0879d50,0x24e4ae1,0x3f4e91c,0x04c7727,0x093cd1d,
|
|
0x16d6a45,0x10a8b95,0x0c77856,0x361f84f,0x217845f,0x0bbeec6,
|
|
0x0485718,0x33c5385,0x00dcec0 } },
|
|
/* 183 */
|
|
{ { 0x1539819,0x225507a,0x1bf11cb,0x13e7653,0x0c8cb3b,0x05f695e,
|
|
0x353f634,0x2827874,0x3fb8053,0x22de9a5,0x035d8b7,0x2105cc7,
|
|
0x2a7a98d,0x35bed95,0x0085748 },
|
|
{ 0x1859c5d,0x00e51f0,0x22a21fd,0x3054d74,0x06ce965,0x328eab7,
|
|
0x26a13e0,0x13bfc65,0x01d4fb1,0x36600b9,0x36dd3fc,0x01232ed,
|
|
0x15bbaa9,0x0ad7a51,0x0089b18 } },
|
|
/* 184 */
|
|
{ { 0x3360710,0x1eb5a90,0x136bd77,0x3bd57a6,0x0841287,0x12886c9,
|
|
0x35c6700,0x21bc6eb,0x25f35ad,0x3bcb01c,0x0707e72,0x23e9943,
|
|
0x03e5233,0x34bb622,0x002bf8e },
|
|
{ 0x16e0d6a,0x04b3d2d,0x290cb02,0x049a10c,0x350537e,0x22cf71b,
|
|
0x3184a19,0x2dc8b62,0x2350210,0x3b4afa6,0x159781e,0x1d01b6d,
|
|
0x1853440,0x16442f0,0x005a78d } },
|
|
/* 185 */
|
|
{ { 0x348b02c,0x1ea8ab5,0x3b954d5,0x14684ac,0x0be5b34,0x11c4496,
|
|
0x0a7a456,0x14f6eb7,0x11a3221,0x2d65f82,0x32eb1ea,0x09c4018,
|
|
0x3f301f3,0x32e8a1c,0x00bd9ad },
|
|
{ 0x0543f7f,0x31e744e,0x1fefd1d,0x24a486c,0x1000220,0x3977e3b,
|
|
0x1b3ef51,0x2512a1b,0x2049e6b,0x122232b,0x391a32b,0x2f4a7b1,
|
|
0x1c13e71,0x081a9b4,0x00d3516 } },
|
|
/* 186 */
|
|
{ { 0x1924f43,0x1ae5495,0x28d52ef,0x2b93e77,0x2d2f401,0x371a010,
|
|
0x33e8d7a,0x06ed3f1,0x30c0d9d,0x2589fa9,0x3bf3567,0x2ecf8fa,
|
|
0x2dee4c3,0x152b620,0x007e8a2 },
|
|
{ 0x1924407,0x01bd42d,0x044a089,0x18686b5,0x2f14a0e,0x17cdce3,
|
|
0x0efa216,0x3c586a8,0x1d6ae71,0x375831f,0x3175894,0x20e43eb,
|
|
0x34c009e,0x3480527,0x00d115c } },
|
|
/* 187 */
|
|
{ { 0x12abf77,0x38b0769,0x25682f2,0x295508c,0x0c2a0dc,0x1259b73,
|
|
0x023ea25,0x340e7b5,0x3c7cd0d,0x1f92324,0x176405c,0x1528894,
|
|
0x18f2e1e,0x2c59c35,0x001efb5 },
|
|
{ 0x0fb1471,0x07e7665,0x141da75,0x07d9f4a,0x0fdb31e,0x0dccda6,
|
|
0x074eb25,0x3d92a9b,0x11189a0,0x1b4c557,0x24b8d2b,0x0533f92,
|
|
0x0e9e344,0x2fa3dea,0x008d5a4 } },
|
|
/* 188 */
|
|
{ { 0x2669e98,0x1ad3514,0x2a035c9,0x08a3f50,0x24547f9,0x0a145d3,
|
|
0x1c1319d,0x3fe833d,0x1ae064b,0x1e01734,0x246d27e,0x3a2f13c,
|
|
0x01e1150,0x263f55e,0x00f89ef },
|
|
{ 0x2e0b63f,0x3e57db7,0x23a4b4f,0x11c8899,0x0ad8500,0x348f3a7,
|
|
0x2918604,0x27d6409,0x1ce5001,0x38f94c2,0x29a508a,0x39bdc89,
|
|
0x3a52c27,0x194899e,0x00e9376 } },
|
|
/* 189 */
|
|
{ { 0x0368708,0x34a2730,0x2e1da04,0x0bd78c1,0x2c45887,0x0c44bfa,
|
|
0x3a23de3,0x390b9db,0x1746efd,0x05c638e,0x1d20609,0x3263370,
|
|
0x31987f0,0x2988529,0x005fa3c },
|
|
{ 0x0aa9f2a,0x20622f7,0x060deee,0x0c9626a,0x3312cc7,0x18ebac7,
|
|
0x008dd6c,0x0ad4fe6,0x3db4ea6,0x1dc3f50,0x090b6e9,0x0aff8d2,
|
|
0x26aa62c,0x18f3e90,0x00105f8 } },
|
|
/* 190 */
|
|
{ { 0x38059ad,0x25e576c,0x3ea00b2,0x1fa4191,0x25686b7,0x2d1ce8f,
|
|
0x30470ed,0x3478bbf,0x340f9b6,0x1c9e348,0x3d594ec,0x2ffe56e,
|
|
0x3f23deb,0x0cd34e9,0x00f4b72 },
|
|
{ 0x1a83f0b,0x2166029,0x28b32a2,0x06a5c5a,0x20786c4,0x0944604,
|
|
0x0901bd2,0x379b84e,0x221e2fe,0x0346d54,0x1f4eb59,0x01b8993,
|
|
0x2462e08,0x25f9d8b,0x006c4c8 } },
|
|
/* 191 */
|
|
{ { 0x0b41d9d,0x2e417ed,0x265bd10,0x199148e,0x3826ca4,0x1a67e8d,
|
|
0x1bbd13b,0x23e414d,0x3d773bc,0x356e64c,0x0d2118a,0x0cb587f,
|
|
0x25fd093,0x24fb529,0x00158c6 },
|
|
{ 0x2806e63,0x3ecaa39,0x251b4dd,0x3b2d779,0x2e31ed3,0x066f1a6,
|
|
0x060e518,0x2c7e3e5,0x0d62c76,0x0d88a70,0x101970a,0x1e3c8c6,
|
|
0x272b8bb,0x083e73b,0x0031f38 } },
|
|
/* 192 */
|
|
{ { 0x09e1c72,0x072bcb0,0x0cf4e93,0x2604a64,0x00715f2,0x10c98b6,
|
|
0x2ad81d9,0x234fcce,0x37a7304,0x1974a4a,0x1c7415f,0x14aaa93,
|
|
0x19587b1,0x3f643f4,0x00c3d10 },
|
|
{ 0x1ddadd0,0x2cd715d,0x294cf76,0x14479ed,0x19f5f4a,0x0198c09,
|
|
0x1ab7ebc,0x182c0bc,0x0879202,0x1807273,0x05d39da,0x2c7d868,
|
|
0x29c4ec4,0x1b13ad2,0x006dcd7 } },
|
|
/* 193 */
|
|
{ { 0x1c83f01,0x0245bff,0x24f90ba,0x112554f,0x2354c8b,0x3f17988,
|
|
0x0c511af,0x39e1e9b,0x26ae95b,0x0ae551c,0x35b41a6,0x0120455,
|
|
0x1e989cb,0x1b37aff,0x00fa2ae },
|
|
{ 0x324659a,0x1aef1c3,0x1c43637,0x3f530a2,0x313a999,0x326af62,
|
|
0x134184e,0x2ac131c,0x3f6a789,0x30a300a,0x13e526e,0x2107af3,
|
|
0x093a8ff,0x2479902,0x00442b1 } },
|
|
/* 194 */
|
|
{ { 0x22b6e20,0x31b18be,0x18614ca,0x26fdb5a,0x197f29e,0x325b44b,
|
|
0x0ab1dbb,0x042348a,0x3275e8e,0x15bae44,0x0077124,0x2cf5345,
|
|
0x2803ad4,0x188f2a2,0x0061b20 },
|
|
{ 0x2a560b1,0x3ced069,0x3cf42c2,0x100e167,0x3879e1d,0x0936ff0,
|
|
0x1b51450,0x14c55f3,0x3153bfa,0x2957423,0x2a93823,0x15f5dce,
|
|
0x2c9a22f,0x16731a8,0x00a97f2 } },
|
|
/* 195 */
|
|
{ { 0x18edbbb,0x18c5ef9,0x1f13c30,0x071e77f,0x225ade5,0x1b60f75,
|
|
0x1beaf11,0x3e495ad,0x2441dd8,0x2fa00e2,0x32a87b6,0x00050f2,
|
|
0x038de7f,0x0037d6d,0x00a885d },
|
|
{ 0x39e48bd,0x1d9e433,0x2768e9f,0x3c29458,0x3f0bdf9,0x35ed5f2,
|
|
0x36709fa,0x176dc10,0x012f7c1,0x2df8547,0x1d90ee3,0x053c089,
|
|
0x21a8d35,0x200cb0d,0x002e84e } },
|
|
/* 196 */
|
|
{ { 0x23ec8d8,0x1d81f55,0x0cb7227,0x07f8e4d,0x2a66181,0x163f577,
|
|
0x272e7af,0x131a8f2,0x2046229,0x25e6276,0x36bbefe,0x2cdc22f,
|
|
0x17c8288,0x33dd4fb,0x000d524 },
|
|
{ 0x330c073,0x1a6728b,0x1cf369f,0x12e7707,0x2f0fa26,0x17c2abd,
|
|
0x0a45680,0x26ebd13,0x3c7d19b,0x1c3d6c8,0x2abd110,0x064fd07,
|
|
0x09b8339,0x02b4a9f,0x009e3e1 } },
|
|
/* 197 */
|
|
{ { 0x0ae972f,0x2093c35,0x06e7a90,0x0af1ba1,0x243eef0,0x2748582,
|
|
0x0606122,0x13a45f9,0x0acfe60,0x08a685e,0x0eb184b,0x015bc11,
|
|
0x0cdf423,0x157fad5,0x004fcad },
|
|
{ 0x2728d15,0x3e5bceb,0x0331a0f,0x31b1a80,0x28a2680,0x3b94955,
|
|
0x04cae07,0x176b57e,0x03ac5a6,0x3d7918b,0x22d23f4,0x0ae077f,
|
|
0x1eb075d,0x006f16c,0x006e473 } },
|
|
/* 198 */
|
|
{ { 0x38219b9,0x0475a2b,0x107a774,0x39946c6,0x1cb883c,0x004e0ed,
|
|
0x087e571,0x25c3497,0x059982f,0x0a71f66,0x118305d,0x1aaf294,
|
|
0x3a5dbaa,0x34be404,0x00725fe },
|
|
{ 0x3abd109,0x336ebea,0x2528487,0x15a1d61,0x0c0f8cf,0x2b56095,
|
|
0x2591e68,0x3549a80,0x1d1debb,0x0701c6c,0x161e7e3,0x1f7fa2e,
|
|
0x3dfe192,0x17e6498,0x0055f89 } },
|
|
/* 199 */
|
|
{ { 0x175645b,0x26c036c,0x0b92f89,0x09ed96d,0x351f3a6,0x19ce67b,
|
|
0x33ac8db,0x2f0828b,0x27fe400,0x0b9c5e1,0x1967b95,0x3324080,
|
|
0x11de142,0x1d44fb3,0x003d596 },
|
|
{ 0x3979775,0x3af37b6,0x3e88d41,0x2f1a8b9,0x299ba61,0x085413c,
|
|
0x1149a53,0x0beb40e,0x31427ba,0x239f708,0x357d836,0x1558c22,
|
|
0x280a79f,0x1b255f6,0x002b6d1 } },
|
|
/* 200 */
|
|
{ { 0x39ad982,0x3d79d89,0x01a684a,0x0b6722e,0x39bb4c9,0x39a6399,
|
|
0x1ad44e0,0x3059f5e,0x048265f,0x33a2fa4,0x0c3a4cc,0x0d7df98,
|
|
0x23a33f1,0x34e2e21,0x00a0a10 },
|
|
{ 0x386efd9,0x1c91f34,0x06c2e19,0x3e6d48d,0x00eefd3,0x2181ef2,
|
|
0x2415f97,0x1d33b08,0x0625086,0x1e8aa3e,0x08c9d60,0x0ab427b,
|
|
0x2764fa7,0x3b7943e,0x00cd9f0 } },
|
|
/* 201 */
|
|
{ { 0x1a46d4d,0x0e471f4,0x1693063,0x0467ac0,0x22df51c,0x127a0f7,
|
|
0x0498008,0x20e0b16,0x1aa8ad0,0x1923f42,0x2a74273,0x01761ce,
|
|
0x1600ca4,0x187b87e,0x00ee49e },
|
|
{ 0x0c76f73,0x19daf92,0x0b2ad76,0x3d8049d,0x1d9c100,0x0fe1c63,
|
|
0x0bb67c8,0x035cc44,0x02002fc,0x37b2169,0x344656a,0x1127879,
|
|
0x1939bc0,0x0dd8df6,0x0028ce7 } },
|
|
/* 202 */
|
|
{ { 0x0544ac7,0x26bdc91,0x042697e,0x356e804,0x1f2c658,0x2ceb7ef,
|
|
0x2dec39f,0x02c1dcc,0x391a2df,0x2344beb,0x2171e20,0x3099c94,
|
|
0x0fa548a,0x37216c9,0x00f820c },
|
|
{ 0x0f4cf77,0x29bbaa5,0x33c6307,0x34a5128,0x118c783,0x2dd06b1,
|
|
0x139d4c0,0x2db912e,0x1153ffb,0x1075eb3,0x3a255e4,0x2892161,
|
|
0x36d5006,0x125338c,0x0014fbc } },
|
|
/* 203 */
|
|
{ { 0x1584e3c,0x0830314,0x00279b9,0x167df95,0x2c7733c,0x2108aef,
|
|
0x0ce1398,0x35aaf89,0x012523b,0x3c46b6a,0x388e6de,0x01a2002,
|
|
0x0582dde,0x19c7fa3,0x007b872 },
|
|
{ 0x1e53510,0x11bca1f,0x19684e7,0x267de5c,0x2492f8b,0x364a2b0,
|
|
0x080bc77,0x2c6d47b,0x248432e,0x3ace44f,0x32028f6,0x0212198,
|
|
0x2f38bad,0x20d63f0,0x00122bb } },
|
|
/* 204 */
|
|
{ { 0x30b29c3,0x3cec78e,0x01510a9,0x0c93e91,0x3837b64,0x1eca3a9,
|
|
0x105c921,0x05d42e6,0x1379845,0x07ce6f2,0x0e8b6da,0x0e0f093,
|
|
0x220b2cd,0x1f6c041,0x00299f5 },
|
|
{ 0x0afdce3,0x2b0e596,0x2f477b6,0x2ccf417,0x3a15206,0x26ec0bf,
|
|
0x2e37e2b,0x2593282,0x0ab9db3,0x2841dd8,0x27954be,0x277a681,
|
|
0x03f82e2,0x2b610c7,0x00446a1 } },
|
|
/* 205 */
|
|
{ { 0x06b8195,0x3b3a817,0x31b9c6f,0x317d279,0x3d744a7,0x1de9eb9,
|
|
0x296acc1,0x1ce9ea3,0x06c3587,0x246815d,0x3756736,0x0588518,
|
|
0x1c971a4,0x1fde1f4,0x00aa021 },
|
|
{ 0x3fd3226,0x274561d,0x00be61e,0x01393d8,0x30f6f23,0x29b7fc1,
|
|
0x04cebc7,0x0a892a7,0x20109f1,0x27456be,0x0c863ee,0x2eb6c8a,
|
|
0x38c782b,0x039397a,0x00a2829 } },
|
|
/* 206 */
|
|
{ { 0x29de330,0x21fe80f,0x145b55b,0x1986570,0x012b260,0x2482fbc,
|
|
0x0536e0a,0x16b7382,0x32c4d19,0x1deffdb,0x145f418,0x0c67a76,
|
|
0x2ce477f,0x218fe24,0x00f9848 },
|
|
{ 0x3e37657,0x3f074d3,0x245ad0e,0x20973c3,0x23c58de,0x2c332ef,
|
|
0x2ad21a8,0x0bf1589,0x208af95,0x1f4a8c4,0x2b43735,0x1e46657,
|
|
0x15d4f81,0x0c3e63a,0x005f19d } },
|
|
/* 207 */
|
|
{ { 0x26865bb,0x20f6683,0x16a672e,0x0efd8d1,0x222f5af,0x18f2367,
|
|
0x1e9c734,0x25c3902,0x178dfe6,0x2903a79,0x311b91c,0x1adbbe9,
|
|
0x225a387,0x0b3e509,0x0089551 },
|
|
{ 0x34e462b,0x23b6a32,0x27c884c,0x129104b,0x384c015,0x3adedc7,
|
|
0x325db1c,0x021dc10,0x1e366f7,0x3054df7,0x1992b9a,0x2824e64,
|
|
0x0ae77f3,0x181b526,0x00a7316 } },
|
|
/* 208 */
|
|
{ { 0x2d260f5,0x2434bf2,0x28c0139,0x0a7bb03,0x176c3be,0x3def5f5,
|
|
0x05bee00,0x3692df7,0x3d2efeb,0x3a6f859,0x1122b87,0x38f779a,
|
|
0x1415ccc,0x2c260ad,0x0075a28 },
|
|
{ 0x04607a6,0x042f37a,0x3f0df68,0x0a1bd36,0x3c6d581,0x2d36bfa,
|
|
0x2d577d1,0x0a3affa,0x0b2066b,0x2e6f110,0x0b17e84,0x3c76a5e,
|
|
0x1a57553,0x012f36a,0x0004595 } },
|
|
/* 209 */
|
|
{ { 0x29e5836,0x0e6808c,0x269d13e,0x147dc5c,0x32c9e7d,0x09b258e,
|
|
0x2c58d6f,0x1efd716,0x0437996,0x34ec31b,0x15908d9,0x2efa8fd,
|
|
0x09ad160,0x079fc1f,0x00d8481 },
|
|
{ 0x3d20e4a,0x18269d6,0x3aa8fe7,0x34829c2,0x2e4325d,0x0d800e1,
|
|
0x11f370b,0x10c08dc,0x22fd092,0x1a5fe55,0x0acc443,0x037030d,
|
|
0x1cdd404,0x097379e,0x00fd6d7 } },
|
|
/* 210 */
|
|
{ { 0x313eafb,0x3f438f3,0x2e5fb3e,0x2ed6a82,0x121009c,0x240889e,
|
|
0x00c5537,0x269b792,0x334b2fc,0x1dd573c,0x07096ae,0x19296fc,
|
|
0x3813985,0x2742f48,0x00ddd64 },
|
|
{ 0x2045041,0x3842c62,0x1572d0d,0x04f255f,0x06e05b4,0x383ec97,
|
|
0x1ff8064,0x18bed71,0x39b6411,0x2764cc5,0x257439f,0x3521217,
|
|
0x172aa42,0x342a2a3,0x0070c5b } },
|
|
/* 211 */
|
|
{ { 0x3bdf646,0x1c5ce25,0x1f7ca76,0x2d2acca,0x3aa1485,0x23c97f7,
|
|
0x3e11d6f,0x0609338,0x07ec622,0x01da8ff,0x3392474,0x17ca07f,
|
|
0x13a9a04,0x353a5b4,0x0024557 },
|
|
{ 0x14c27cd,0x32012f7,0x3fea875,0x3d03d71,0x211c5f0,0x3157fdf,
|
|
0x0c880bd,0x3c406b2,0x2c51103,0x24ab377,0x399faa8,0x0d06887,
|
|
0x16b5738,0x28b33a7,0x00c7b67 } },
|
|
/* 212 */
|
|
{ { 0x2357586,0x35c93e3,0x0da09a0,0x3d77d92,0x11d7f4f,0x37b98a9,
|
|
0x3e6c9bf,0x2cdca70,0x2f00389,0x2412673,0x18eab87,0x0101436,
|
|
0x11617e9,0x06d9b01,0x00e8eef },
|
|
{ 0x37e3ca9,0x16ffaf0,0x391debf,0x1b69382,0x07c5e94,0x312fa8a,
|
|
0x0973142,0x2cadde4,0x109ee67,0x3a07db0,0x1afc5ed,0x08df66f,
|
|
0x304c7af,0x0804aae,0x00d2e60 } },
|
|
/* 213 */
|
|
{ { 0x24f57bf,0x1818322,0x182a615,0x25bfc44,0x0f97586,0x0a5bbc0,
|
|
0x36773c6,0x1a2660c,0x3ceff66,0x3270152,0x319cd11,0x2845845,
|
|
0x1acfad6,0x19076f8,0x009824a },
|
|
{ 0x289fd01,0x2de97ee,0x39d80b7,0x026227d,0x0f8d3b8,0x15e0a17,
|
|
0x21ea08f,0x20a2317,0x136ae6d,0x3deb1d1,0x3521ef5,0x0de8801,
|
|
0x0a25d5d,0x0612c98,0x005ecc4 } },
|
|
/* 214 */
|
|
{ { 0x308c8d3,0x3aec669,0x01ecddc,0x13f18fe,0x1e63ed0,0x061cfe5,
|
|
0x05f5a01,0x1db5741,0x14479f2,0x0ced6b5,0x025ae5b,0x09ca8f5,
|
|
0x2160581,0x1404433,0x008bfeb },
|
|
{ 0x08228bf,0x0e02722,0x37df423,0x33ecabf,0x34bd82a,0x32f529f,
|
|
0x28f1800,0x0c8f671,0x1246b44,0x1ff35dc,0x091db95,0x303f3da,
|
|
0x28f7f60,0x3624136,0x00cfbb4 } },
|
|
/* 215 */
|
|
{ { 0x326139a,0x2977e4e,0x3eb89a6,0x20ecb31,0x13e076a,0x2a592f3,
|
|
0x28e82d5,0x235ad1e,0x239b927,0x262938a,0x2444354,0x141b263,
|
|
0x0d56693,0x2a3fc78,0x0006497 },
|
|
{ 0x31efa05,0x3a3664a,0x3e333de,0x2a114e4,0x12da63c,0x3c15e6b,
|
|
0x2f7277c,0x363aa92,0x2393236,0x16bd2d1,0x32b617f,0x32b656c,
|
|
0x3b1246c,0x22e2e22,0x00ce76d } },
|
|
/* 216 */
|
|
{ { 0x03843dc,0x094de82,0x13b463d,0x0507905,0x089eb35,0x2a6bf25,
|
|
0x35ebc4e,0x2bb5d45,0x1808ed1,0x1de9949,0x185e829,0x0a55847,
|
|
0x0b73d67,0x1a2ed61,0x008dd2d },
|
|
{ 0x133c3a4,0x04e7980,0x38ea237,0x2ad2f49,0x19de838,0x018bf36,
|
|
0x29b072c,0x21c1ba0,0x14f63ba,0x31c1cc3,0x13cd05e,0x20120ff,
|
|
0x1f84d60,0x16e0321,0x00872ab } },
|
|
/* 217 */
|
|
{ { 0x19d4d49,0x1ddb4e6,0x05e7fc0,0x37bb0fd,0x1a3eb59,0x36b87f0,
|
|
0x190e440,0x1c7fef2,0x31ea153,0x14cd65a,0x1bc7ab2,0x11f72ca,
|
|
0x39582d4,0x0fa4d65,0x00cd5b6 },
|
|
{ 0x3d1ff11,0x0d9be9d,0x2903ae3,0x017b7b9,0x259f28f,0x110cefc,
|
|
0x03fed1a,0x38039bd,0x09bdf9c,0x3055027,0x2ca9c5d,0x2d737b6,
|
|
0x3bdb421,0x16560b5,0x00f9f33 } },
|
|
/* 218 */
|
|
{ { 0x022c792,0x110de25,0x38bf959,0x08f2562,0x1239ea9,0x3c1d950,
|
|
0x21a247d,0x315112d,0x285bb9f,0x2534a73,0x0b42455,0x1a4a99c,
|
|
0x069009a,0x1680392,0x006e0ca },
|
|
{ 0x1b3bece,0x269e0a1,0x18926b7,0x0e7187e,0x241f35e,0x39d1fe0,
|
|
0x02099aa,0x1675bfe,0x23fd0ca,0x3d6322b,0x19406b5,0x324c38a,
|
|
0x242434a,0x3ae677c,0x002ce04 } },
|
|
/* 219 */
|
|
{ { 0x2c37b82,0x1ae6506,0x0d83436,0x23496c1,0x0ff0c72,0x2711edf,
|
|
0x1513611,0x04f9c7d,0x1edbeff,0x376fcb5,0x212a683,0x23bf547,
|
|
0x0f9c4f7,0x16e6627,0x0082cd8 },
|
|
{ 0x0cb5d37,0x31b6db8,0x1a15e23,0x2f5cbb8,0x0818aee,0x21dc6c5,
|
|
0x12aafd2,0x205f608,0x1d91def,0x3def088,0x1445c51,0x3100e8a,
|
|
0x3746bda,0x145c4b0,0x00711b0 } },
|
|
/* 220 */
|
|
{ { 0x2a99ecc,0x27b5217,0x35e10ed,0x036e32a,0x0f79950,0x15c32f7,
|
|
0x2c87dcb,0x3ebb2a3,0x2c2d35d,0x114b3ec,0x2e4d80a,0x0c7eb89,
|
|
0x2abe58d,0x3727737,0x00e6a37 },
|
|
{ 0x1eca452,0x1968d07,0x344e5d3,0x29435a2,0x109a5f8,0x181d12c,
|
|
0x238ea5a,0x127a564,0x00dbb42,0x0fcbfb7,0x2909b2e,0x2571d3a,
|
|
0x08250e3,0x0694e4e,0x00e156d } },
|
|
/* 221 */
|
|
{ { 0x3181ae9,0x1acf411,0x3808d79,0x2a11065,0x0baf44b,0x133cfeb,
|
|
0x1330943,0x1711b9a,0x2dec3bd,0x1906a9a,0x2ed947c,0x369d763,
|
|
0x1a5254f,0x104a7a9,0x00acd9d },
|
|
{ 0x030301b,0x31568f5,0x2a4965c,0x33ded4b,0x03c9a5b,0x16541fc,
|
|
0x1319cf1,0x2a3748b,0x1b5de74,0x18bb82e,0x077ac2b,0x309a87a,
|
|
0x3c31420,0x0f6a4b9,0x00387d7 } },
|
|
/* 222 */
|
|
{ { 0x0d3fdac,0x120cfa3,0x1b8e13c,0x1ccccb9,0x376fcd4,0x0bf87f4,
|
|
0x271b4be,0x363b3fd,0x28b5d98,0x0535cd3,0x114bbc1,0x3ab4f19,
|
|
0x10494b1,0x2161ece,0x00d14ca },
|
|
{ 0x12d37e9,0x110ebd7,0x062295a,0x1cc0119,0x073c6ea,0x15d5411,
|
|
0x0aeb4b1,0x23fba91,0x175fab5,0x3ee8fe1,0x1c680a6,0x1e76f27,
|
|
0x3ddfc97,0x3d69ecd,0x00e1ee5 } },
|
|
/* 223 */
|
|
{ { 0x2d29f46,0x2d19204,0x3137cd0,0x02c3b54,0x193295b,0x02fbdb2,
|
|
0x2260948,0x22c02ff,0x3885424,0x1299595,0x00e7f9c,0x310ff2a,
|
|
0x01ea169,0x0deef85,0x0021908 },
|
|
{ 0x1b26cfb,0x38566a8,0x2852875,0x21debff,0x290ca9f,0x0b29663,
|
|
0x26550d9,0x2b44457,0x05d1938,0x1f8f825,0x366ef93,0x1d8daec,
|
|
0x069e5ef,0x342ece6,0x00b6034 } },
|
|
/* 224 */
|
|
{ { 0x2d8356e,0x1578c09,0x226f4d2,0x3b74c51,0x0f83666,0x0323b59,
|
|
0x1ddf61d,0x1ed8508,0x3c52667,0x0e5b91c,0x1e9b18b,0x352bdfa,
|
|
0x13f75da,0x352aa4e,0x00fceff },
|
|
{ 0x1c731d5,0x04e2844,0x01d9843,0x286cbc5,0x105bcb3,0x05edd9c,
|
|
0x21fa956,0x3b1ec83,0x01288cc,0x22fbf3a,0x10f1b56,0x081cf72,
|
|
0x15cb758,0x18687c1,0x00f5722 } },
|
|
/* 225 */
|
|
{ { 0x2973088,0x1209dcd,0x3980f31,0x0221aa7,0x1c008e7,0x011b098,
|
|
0x395947e,0x2f2806d,0x27dca76,0x037c79a,0x31acddf,0x2bf6219,
|
|
0x0d8f4ab,0x13644d9,0x00ff705 },
|
|
{ 0x2260594,0x18d51f8,0x277e2cf,0x1cb5cec,0x2468a53,0x3e6f4d7,
|
|
0x019e24e,0x0f30f1d,0x0202404,0x34ad287,0x090b39c,0x23c11ea,
|
|
0x1a2e3a2,0x3a851be,0x00dca2c } },
|
|
/* 226 */
|
|
{ { 0x3277538,0x221cd94,0x3738ab7,0x0973da5,0x1a734e2,0x2c8b8b0,
|
|
0x2e1d1e6,0x348499b,0x389ebe1,0x18b1854,0x02bb076,0x1b2b500,
|
|
0x0f207f3,0x170cf99,0x0012088 },
|
|
{ 0x0fbfec2,0x1df55a4,0x34ae59e,0x2ab5e95,0x3f9e781,0x3411794,
|
|
0x1410b05,0x17c3a00,0x0aaa91b,0x074ed7c,0x3fbb352,0x3477c01,
|
|
0x3ee9ab3,0x0cfb1ca,0x0011c4b } },
|
|
/* 227 */
|
|
{ { 0x3c3a7f3,0x2e60ca0,0x2354d32,0x33e2362,0x28083ab,0x03d3b16,
|
|
0x3164045,0x0a41f7a,0x3f0641e,0x38635d1,0x31bbf03,0x225e2bb,
|
|
0x0cd894e,0x1f72228,0x0093244 },
|
|
{ 0x33d5897,0x383faf3,0x0e6d561,0x0bc4d80,0x3fc3a68,0x05a9adc,
|
|
0x0b9d73d,0x3d6031e,0x2ded29b,0x339c4ff,0x08d69e5,0x089488c,
|
|
0x3fda40a,0x295c7fd,0x003a924 } },
|
|
/* 228 */
|
|
{ { 0x0093bee,0x115532d,0x2ec0fb6,0x0969631,0x3a6d65a,0x0f43b4d,
|
|
0x26994d4,0x0b51104,0x2515515,0x3695a26,0x284caa8,0x397aa30,
|
|
0x25538b8,0x353f47c,0x0033f05 },
|
|
{ 0x3615d6e,0x37f8246,0x07dae0f,0x23dc154,0x02ded7e,0x1eef320,
|
|
0x1631e51,0x3447f75,0x13e267f,0x353e1d1,0x3f89d62,0x369c8ff,
|
|
0x1a21dc6,0x2b8b8f3,0x0055cbc } },
|
|
/* 229 */
|
|
{ { 0x34e84f3,0x2f2539a,0x2c35336,0x0c53bdc,0x1728630,0x3ad5fe6,
|
|
0x05fdeee,0x3386db6,0x272a42e,0x29fd38c,0x36f0320,0x21b2ed4,
|
|
0x331e67f,0x28ae48c,0x00f09b6 },
|
|
{ 0x2778435,0x0fb3c55,0x32d221d,0x2660c8e,0x32977ba,0x1c12f03,
|
|
0x1b57fb1,0x01229a8,0x38b389f,0x375ddf3,0x2c6b42c,0x3885d3e,
|
|
0x2c55a9c,0x2ffc279,0x00404e2 } },
|
|
/* 230 */
|
|
{ { 0x04c5ddb,0x2c4d788,0x150e9b9,0x110fbfd,0x29dbfe0,0x30ef83d,
|
|
0x2ab4bfe,0x395bcd7,0x30d0a43,0x0e2d30f,0x0e73f9b,0x07199cc,
|
|
0x0c9054c,0x22f4b1e,0x0092ed3 },
|
|
{ 0x386e27c,0x00fdaa8,0x0507c70,0x1beb3b6,0x0b9c4f4,0x277d519,
|
|
0x024ec85,0x1cbaba8,0x1524295,0x112be58,0x21fc119,0x273578b,
|
|
0x2358c27,0x280ca07,0x00aa376 } },
|
|
/* 231 */
|
|
{ { 0x0dbc95c,0x16488cf,0x337a078,0x1abbcb8,0x0aae1aa,0x1caa151,
|
|
0x00108d4,0x1edf701,0x3e68d03,0x1203214,0x0c7eee2,0x084c572,
|
|
0x07752d2,0x215a3b9,0x00195d3 },
|
|
{ 0x2cd7fbe,0x06e80f6,0x052bd4b,0x07b4f83,0x24b5ac6,0x2aaded4,
|
|
0x13c0526,0x0ffa9a3,0x08c660e,0x13c35c9,0x3145efb,0x36cfe24,
|
|
0x0936daf,0x268e3d0,0x00a73fd } },
|
|
/* 232 */
|
|
{ { 0x31b17ce,0x2e7bcee,0x3f31891,0x19f1849,0x1140236,0x015487f,
|
|
0x32e58d3,0x202204a,0x049e350,0x1ce91f9,0x3f75150,0x27f212f,
|
|
0x0d16ee4,0x1c894c4,0x004023f },
|
|
{ 0x33399fa,0x2397b6d,0x2a3ea60,0x36354ca,0x1f12632,0x117a105,
|
|
0x22758e8,0x361844e,0x3851fc2,0x0ab92db,0x339d02f,0x1e7d6c4,
|
|
0x19ebd38,0x0a9a036,0x00446d2 } },
|
|
/* 233 */
|
|
{ { 0x3e164f1,0x008c092,0x19200f5,0x35a22e0,0x38d09d2,0x212b3bf,
|
|
0x0056f19,0x3a03545,0x1f075e9,0x0e97137,0x1f496a9,0x32d1f9b,
|
|
0x36bf738,0x35ace37,0x00899e1 },
|
|
{ 0x19eb2a6,0x21fa22d,0x338b69e,0x18e6d1f,0x1280d9d,0x1953a55,
|
|
0x1411ea3,0x2960566,0x0fd969a,0x1f3e375,0x130742a,0x170aebd,
|
|
0x33085ff,0x14d868d,0x00a4391 } },
|
|
/* 234 */
|
|
{ { 0x0a4bdd2,0x39ca8ea,0x37026ac,0x346da3b,0x0c656cd,0x03136b6,
|
|
0x233e7e9,0x0714352,0x08a9d95,0x192bb38,0x085d68e,0x20016b8,
|
|
0x102b8ea,0x1f5dbdd,0x00fdd7a },
|
|
{ 0x0d6fa45,0x3ec29a6,0x2b8cce6,0x1c84413,0x0228f86,0x28275f7,
|
|
0x3d8787d,0x0c19748,0x28b2ae9,0x1954850,0x2a56c36,0x3eae8f7,
|
|
0x0aca595,0x00e42a2,0x00edbe5 } },
|
|
/* 235 */
|
|
{ { 0x3b26c82,0x3682b6f,0x2f9cd64,0x0f254b0,0x0e5d70b,0x1f9dfda,
|
|
0x28f365f,0x35a57d7,0x00208f2,0x19c8d38,0x112e7be,0x3e403bb,
|
|
0x3734efa,0x24d12b3,0x0027dc6 },
|
|
{ 0x260a46a,0x13fd7b0,0x1c2880e,0x338b70c,0x27da5eb,0x29a7d54,
|
|
0x1c5d73c,0x2130921,0x32969cc,0x2b37eda,0x2d6d4ec,0x0716bfb,
|
|
0x0763703,0x1320889,0x00c7bbf } },
|
|
/* 236 */
|
|
{ { 0x1fe01b2,0x2dcb1d2,0x11b89d5,0x219e4ea,0x0347851,0x3d1810e,
|
|
0x3a3c54c,0x06dbe8e,0x03d3ab2,0x2dcfa39,0x3e57b8a,0x337a382,
|
|
0x0426450,0x0e9f748,0x006488b },
|
|
{ 0x1dc4582,0x0e62cf7,0x06fea9e,0x2a56fb1,0x31698c1,0x15b4e10,
|
|
0x1446ef1,0x0a689fc,0x1d87703,0x20ff497,0x2c71066,0x2c48868,
|
|
0x2e6cf05,0x30aa9cb,0x0065b2d } },
|
|
/* 237 */
|
|
{ { 0x1021d63,0x2217df3,0x1f0821a,0x057fa98,0x23f344b,0x173dcf9,
|
|
0x1ba6ddc,0x22c8eb5,0x18f227a,0x0455343,0x1c55931,0x1d0dcf3,
|
|
0x20fa19b,0x1c56618,0x004feab },
|
|
{ 0x19ec924,0x224e39f,0x2550509,0x179b51f,0x284d54a,0x2d85d41,
|
|
0x2d1bdc1,0x1a29068,0x3826158,0x1267f85,0x3005a92,0x0769e00,
|
|
0x379b617,0x17b5f63,0x00a70bf } },
|
|
/* 238 */
|
|
{ { 0x22216c5,0x049437f,0x33510bc,0x141d806,0x22c37e2,0x1bc1adf,
|
|
0x300175d,0x2e6ded8,0x0a18bfe,0x35377a3,0x382f843,0x08410ca,
|
|
0x00afd4f,0x0be6c6b,0x008d70e },
|
|
{ 0x2e91abb,0x1cede2a,0x28f225c,0x28e18c0,0x30230dc,0x173cc2d,
|
|
0x123ecfe,0x3c9962e,0x2c25506,0x27b5d53,0x329a5e3,0x106e231,
|
|
0x3889b8e,0x3b0aeaf,0x00ee67c } },
|
|
/* 239 */
|
|
{ { 0x3e46c65,0x0eb3d46,0x1d7ae18,0x23f9d59,0x2978953,0x2589ed3,
|
|
0x073391d,0x2461e1e,0x0c19f1d,0x22fd2b1,0x0691f5c,0x2e67d8d,
|
|
0x1fb985d,0x200dd28,0x00a68df },
|
|
{ 0x392b5fa,0x123b46f,0x1c323c4,0x104f82f,0x0a098c8,0x26fc05b,
|
|
0x34cd557,0x0913639,0x09c115e,0x3977c34,0x3410b66,0x062b404,
|
|
0x0213094,0x132c5e8,0x008b612 } },
|
|
/* 240 */
|
|
{ { 0x26e3392,0x3b0ebf0,0x2e00425,0x1c285c8,0x3c07f84,0x08d5ad0,
|
|
0x028190e,0x1669b73,0x1ffb1ef,0x053b65f,0x063028c,0x0aceb47,
|
|
0x18988c2,0x0f09a30,0x0007072 },
|
|
{ 0x0f49e7d,0x28c0bd3,0x252270d,0x24cfc4a,0x0c5e87c,0x2165052,
|
|
0x2cdd1d1,0x04931d2,0x3abca74,0x22b57dc,0x169fd47,0x0b928fb,
|
|
0x17cc3e7,0x21a1ec4,0x0061593 } },
|
|
/* 241 */
|
|
{ { 0x1aa0486,0x2e55dea,0x15577b7,0x0d6818f,0x36e41fb,0x2a411f5,
|
|
0x17d5c7d,0x1eea6c0,0x28068a8,0x0e31d20,0x1f08ad9,0x117e973,
|
|
0x08a28ab,0x085d30a,0x00cd9fb },
|
|
{ 0x347843d,0x1119095,0x11e3595,0x1b29584,0x134d64c,0x2ff3a35,
|
|
0x247ea14,0x099fc4b,0x2056169,0x145dd03,0x2ed03fb,0x1250e3b,
|
|
0x3f5135c,0x2b753f0,0x009da30 } },
|
|
/* 242 */
|
|
{ { 0x0fa5200,0x214a0b3,0x313dc4e,0x23da866,0x3270760,0x15c9b8b,
|
|
0x39a53df,0x1f79772,0x3c9e942,0x2984901,0x154d582,0x1685f87,
|
|
0x2e1183e,0x1f79956,0x00b9987 },
|
|
{ 0x15254de,0x3a5cac0,0x37c56f0,0x2c7c29b,0x292a56d,0x195be2c,
|
|
0x17e4e1a,0x0660f4a,0x052ad98,0x1267f80,0x07cfed8,0x194b4bc,
|
|
0x01738d3,0x14ba10f,0x00c7843 } },
|
|
/* 243 */
|
|
{ { 0x29b2d8a,0x242bc1f,0x19646ee,0x0615f3c,0x0ac8d70,0x07ca3bf,
|
|
0x2d90317,0x2c83bdb,0x1a96812,0x39fdc35,0x31c61ee,0x2d55fd3,
|
|
0x2375827,0x355f189,0x00f1c9b },
|
|
{ 0x21a6194,0x1f4050a,0x2b845cf,0x02c6242,0x2dd614e,0x3a4f0a9,
|
|
0x39de100,0x24714fb,0x175e0cd,0x0be633d,0x14befc3,0x13b0318,
|
|
0x1d68c50,0x299989e,0x00d0513 } },
|
|
/* 244 */
|
|
{ { 0x059fb6a,0x2b6eb6a,0x3666a8e,0x39f6ca0,0x1cf8346,0x388b8d5,
|
|
0x35e61a3,0x271adec,0x22c9963,0x20a4fb3,0x16f241c,0x0058b89,
|
|
0x21ddafa,0x1ee6fde,0x00d2e6c },
|
|
{ 0x0075e63,0x39894d0,0x0286d0d,0x187e7b2,0x02405aa,0x3f91525,
|
|
0x37830a8,0x2723088,0x2c7364e,0x013f406,0x104ba75,0x270f486,
|
|
0x3520b4d,0x3852bc6,0x00d589b } },
|
|
/* 245 */
|
|
{ { 0x262e53b,0x1da93d1,0x3676135,0x147e41d,0x335ec2f,0x1f02be5,
|
|
0x297d139,0x22d6198,0x1fe9e59,0x13b4c80,0x1e70f60,0x2f1d4a9,
|
|
0x2d95149,0x14d6ec4,0x00b54af },
|
|
{ 0x12c1c76,0x2930ac8,0x0dfd36e,0x31fac94,0x218f5bb,0x2828691,
|
|
0x1466cc9,0x3645e83,0x1a4dac2,0x1549593,0x0e95fab,0x19567d2,
|
|
0x27a3320,0x0642729,0x007487c } },
|
|
/* 246 */
|
|
{ { 0x1e98e9c,0x2ff8df7,0x119975a,0x098a904,0x099b90b,0x336c7df,
|
|
0x010996d,0x159d46d,0x3118b3b,0x3aacd1b,0x31f8ae1,0x214864f,
|
|
0x398c104,0x089dae2,0x001ec4d },
|
|
{ 0x1452baa,0x2f24991,0x2572ba3,0x162b312,0x2387d18,0x147c5c7,
|
|
0x38eff6e,0x0700251,0x37d931e,0x23cd5c1,0x254c8ca,0x3b9df37,
|
|
0x1c9a4ff,0x0bfd547,0x00fb489 } },
|
|
/* 247 */
|
|
{ { 0x1b8dff8,0x2f6b40b,0x05a25b1,0x3f5688a,0x1d462f4,0x2802d18,
|
|
0x2aad8ed,0x1b46c75,0x3cf4130,0x250fefb,0x2a13fe1,0x23a1bcd,
|
|
0x0940442,0x04605fe,0x00c8b2f },
|
|
{ 0x0d51afb,0x14a2abc,0x1d06762,0x291526c,0x2a3e2fe,0x28f77d9,
|
|
0x3ad8f2e,0x3481a1b,0x04b4fbd,0x2836733,0x0189ff5,0x3a5f533,
|
|
0x319a6cd,0x0f58667,0x00c3679 } },
|
|
/* 248 */
|
|
{ { 0x1b85197,0x22426d4,0x2895ea3,0x342d324,0x3ffb17d,0x376cfcf,
|
|
0x30878b1,0x3c3c83a,0x0ffc57c,0x0ac174a,0x1abd57e,0x2f78b9c,
|
|
0x01b20d8,0x0a37103,0x007f2be },
|
|
{ 0x19a2d48,0x137288a,0x182d655,0x0ba0dde,0x25130ba,0x01c65c6,
|
|
0x23205f1,0x2097621,0x2827cf2,0x2c57b98,0x03748f2,0x2db15fc,
|
|
0x385a0d4,0x13690c0,0x00a9e3f } },
|
|
/* 249 */
|
|
{ { 0x3fbc9c6,0x2df3b20,0x377e33e,0x31d1505,0x024a311,0x3c1d9ff,
|
|
0x1377f74,0x00b6b20,0x2364ab7,0x184ab6b,0x2a77969,0x3f2db6c,
|
|
0x2a6adb7,0x0a10073,0x004a6fb },
|
|
{ 0x1fc73de,0x2c74ab3,0x3d325e8,0x2346c0b,0x1d0efae,0x2076146,
|
|
0x19c190d,0x225c4fe,0x3fafc80,0x2cf063d,0x11b7ae7,0x3dc4f9d,
|
|
0x3c3f841,0x10d7c1f,0x000a4b3 } },
|
|
/* 250 */
|
|
{ { 0x19b7d2e,0x28f1300,0x0b897dd,0x06b5371,0x0631c8d,0x336cc4f,
|
|
0x09cd6e1,0x2ec1952,0x1104c07,0x07512bb,0x35f000d,0x25f84e9,
|
|
0x1df4d8f,0x193f769,0x000e9ee },
|
|
{ 0x2346910,0x267cecf,0x0ad7eaa,0x087e8a5,0x1622f69,0x342cbfa,
|
|
0x2aa20d0,0x206e88a,0x3991e58,0x093fb4b,0x0157180,0x3cecb5b,
|
|
0x2e17c9a,0x1ea371f,0x00919e6 } },
|
|
/* 251 */
|
|
{ { 0x2250533,0x13f931d,0x3ef8c72,0x395f605,0x18a2080,0x1cb25d4,
|
|
0x2fb0f41,0x1c0ba8a,0x1eb17c0,0x266c433,0x09b7e3e,0x0e5d78f,
|
|
0x0cdc5bf,0x1f7c734,0x0020611 },
|
|
{ 0x205ebd5,0x127986f,0x02c0fb0,0x1705b1e,0x1eb0bb5,0x2dffb42,
|
|
0x2331b8a,0x18fc04e,0x31d6328,0x17db162,0x0d3b619,0x193bdb9,
|
|
0x3f11662,0x2d8e694,0x0092c51 } },
|
|
/* 252 */
|
|
{ { 0x08b364d,0x31ef20a,0x25c4a57,0x021ed07,0x14a562e,0x262a684,
|
|
0x1d21c66,0x126e5a6,0x181f3f8,0x2a93b65,0x1eb726b,0x08fbbce,
|
|
0x084f9a2,0x308f30a,0x0013159 },
|
|
{ 0x23f4963,0x0c7960e,0x2a81739,0x2242b69,0x3965003,0x2aca542,
|
|
0x28a1c65,0x2ad48fb,0x149775f,0x1bbb7d2,0x0f2671b,0x3594b85,
|
|
0x22f5563,0x2470f13,0x00fed44 } },
|
|
/* 253 */
|
|
{ { 0x0eb453e,0x3ab70fd,0x1a5b335,0x18f2b74,0x25ff74b,0x3612a46,
|
|
0x33d0d75,0x28cdda4,0x2b9b49b,0x22728fb,0x004c15b,0x1beb33b,
|
|
0x1a7e41f,0x0c9b702,0x004ef19 },
|
|
{ 0x1ca3233,0x0b4c90f,0x1d4b53d,0x2428896,0x20ee405,0x151bc00,
|
|
0x022edb5,0x1adc463,0x00109ea,0x06490a6,0x30e91e6,0x3682b76,
|
|
0x23c50aa,0x3bd2665,0x005fe53 } },
|
|
/* 254 */
|
|
{ { 0x0c28c65,0x3741ae4,0x247d372,0x0b04673,0x2176524,0x2c8bf20,
|
|
0x01fb806,0x3330701,0x307b0a7,0x3999fb7,0x1261bec,0x256679c,
|
|
0x3f22ac7,0x26e8673,0x00bc69d },
|
|
{ 0x3c06819,0x35df344,0x379d009,0x2bb8a0a,0x0635a66,0x096c6fa,
|
|
0x1ac4a62,0x023e53b,0x0e45240,0x115f53d,0x3056af8,0x0a66b16,
|
|
0x3c386ee,0x1130e82,0x00cc384 } },
|
|
/* 255 */
|
|
{ { 0x14c2356,0x190ec73,0x07be490,0x145d415,0x0740a48,0x1251301,
|
|
0x3eaf29d,0x2628190,0x079299a,0x26e95c9,0x2e05fdf,0x2ca7c5b,
|
|
0x32d7b48,0x3d84226,0x0033fb4 },
|
|
{ 0x150f955,0x01240aa,0x3ddf867,0x137fb70,0x297e103,0x17eeda8,
|
|
0x1320b60,0x266ec84,0x13f4322,0x0c8f5ee,0x0590e4a,0x386815e,
|
|
0x00ce61f,0x161bd63,0x008e1d0 } },
|
|
};
|
|
|
|
/* Multiply the base point of P384 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^48, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_mulmod_base_15(sp_point_384* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
return sp_384_ecc_mulmod_stripe_15(r, &p384_base, p384_table,
|
|
k, map, ct, heap);
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Multiply the base point of P384 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_384(const mp_int* km, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_384 point[1];
|
|
sp_digit k[15];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_384_from_mp(k, 15, km);
|
|
|
|
err = sp_384_ecc_mulmod_base_15(point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_point_to_ecc_point_15(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the base point of P384 by the scalar, add point a and return
|
|
* the result. If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_add_384(const mp_int* km, const ecc_point* am,
|
|
int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_384 point[2];
|
|
sp_digit k[15 + 15 * 2 * 6];
|
|
#endif
|
|
sp_point_384* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (15 + 15 * 2 * 6),
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 15;
|
|
|
|
sp_384_from_mp(k, 15, km);
|
|
sp_384_point_from_ecc_point_15(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_384_mod_mul_norm_15(addP->x, addP->x, p384_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_384_mod_mul_norm_15(addP->y, addP->y, p384_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_384_mod_mul_norm_15(addP->z, addP->z, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_ecc_mulmod_base_15(point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_384_proj_point_add_15(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_384_map_15(point, point, tmp);
|
|
}
|
|
|
|
err = sp_384_point_to_ecc_point_15(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
|
|
defined(HAVE_ECC_VERIFY)
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
|
|
/* Add 1 to a. (a = a + 1)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_384_add_one_15(sp_digit* a)
|
|
{
|
|
a[0]++;
|
|
sp_384_norm_15(a);
|
|
}
|
|
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_384_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 18U) {
|
|
r[j] &= 0x3ffffff;
|
|
s = 26U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Generates a scalar that is in the range 1..order-1.
|
|
*
|
|
* rng Random number generator.
|
|
* k Scalar value.
|
|
* returns RNG failures, MEMORY_E when memory allocation fails and
|
|
* MP_OKAY on success.
|
|
*/
|
|
static int sp_384_ecc_gen_k_15(WC_RNG* rng, sp_digit* k)
|
|
{
|
|
int err;
|
|
byte buf[48];
|
|
|
|
do {
|
|
err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
|
|
if (err == 0) {
|
|
sp_384_from_bin(k, 15, buf, (int)sizeof(buf));
|
|
if (sp_384_cmp_15(k, p384_order2) <= 0) {
|
|
sp_384_add_one_15(k);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while (err == 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Makes a random EC key pair.
|
|
*
|
|
* rng Random number generator.
|
|
* priv Generated private value.
|
|
* pub Generated public point.
|
|
* heap Heap to use for allocation.
|
|
* returns ECC_INF_E when the point does not have the correct order, RNG
|
|
* failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_make_key_384(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_384 point[2];
|
|
#else
|
|
sp_point_384 point[1];
|
|
#endif
|
|
sp_digit k[15];
|
|
#endif
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_384* infinity = NULL;
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap, DYNAMIC_TYPE_ECC);
|
|
#else
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
infinity = point + 1;
|
|
#endif
|
|
|
|
err = sp_384_ecc_gen_k_15(rng, k);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_ecc_mulmod_15(infinity, point, p384_order, 1, 1, NULL);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (sp_384_iszero_15(point->x) || sp_384_iszero_15(point->y)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(k, priv);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_point_to_ecc_point_15(point, pub);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL) {
|
|
/* point is not sensitive, so no need to zeroize */
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
}
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_key_gen_384_ctx {
|
|
int state;
|
|
sp_384_ecc_mulmod_15_ctx mulmod_ctx;
|
|
sp_digit k[15];
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_384 point[2];
|
|
#else
|
|
sp_point_384 point[1];
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
} sp_ecc_key_gen_384_ctx;
|
|
|
|
int sp_ecc_make_key_384_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv,
|
|
ecc_point* pub, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_key_gen_384_ctx* ctx = (sp_ecc_key_gen_384_ctx*)sp_ctx->data;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_384* infinity = ctx->point + 1;
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_key_gen_384_ctx)
|
|
>= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
err = sp_384_ecc_gen_k_15(rng, ctx->k);
|
|
if (err == MP_OKAY) {
|
|
err = FP_WOULDBLOCK;
|
|
ctx->state = 1;
|
|
}
|
|
break;
|
|
case 1:
|
|
err = sp_384_ecc_mulmod_base_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
ctx->point, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
err = FP_WOULDBLOCK;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 2;
|
|
#else
|
|
ctx->state = 3;
|
|
#endif
|
|
}
|
|
break;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
case 2:
|
|
err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
infinity, ctx->point, p384_order, 1, 1);
|
|
if (err == MP_OKAY) {
|
|
if (sp_384_iszero_15(ctx->point->x) ||
|
|
sp_384_iszero_15(ctx->point->y)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
else {
|
|
err = FP_WOULDBLOCK;
|
|
ctx->state = 3;
|
|
}
|
|
}
|
|
break;
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
case 3:
|
|
err = sp_384_to_mp(ctx->k, priv);
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_point_to_ecc_point_15(ctx->point, pub);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_384_ctx));
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#ifdef HAVE_ECC_DHE
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 48
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_384_to_bin_15(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<14; i++) {
|
|
r[i+1] += r[i] >> 26;
|
|
r[i] &= 0x3ffffff;
|
|
}
|
|
j = 391 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<15 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 26) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 26);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Multiply the point by the scalar and serialize the X ordinate.
|
|
* The number is 0 padded to maximum size on output.
|
|
*
|
|
* priv Scalar to multiply the point by.
|
|
* pub Point to multiply.
|
|
* out Buffer to hold X ordinate.
|
|
* outLen On entry, size of the buffer in bytes.
|
|
* On exit, length of data in buffer in bytes.
|
|
* heap Heap to use for allocation.
|
|
* returns BUFFER_E if the buffer is to small for output size,
|
|
* MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_secret_gen_384(const mp_int* priv, const ecc_point* pub, byte* out,
|
|
word32* outLen, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_384 point[1];
|
|
sp_digit k[15];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 48U) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_384_from_mp(k, 15, priv);
|
|
sp_384_point_from_ecc_point_15(point, pub);
|
|
err = sp_384_ecc_mulmod_15(point, point, k, 1, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_384_to_bin_15(point->x, out);
|
|
*outLen = 48;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_sec_gen_384_ctx {
|
|
int state;
|
|
union {
|
|
sp_384_ecc_mulmod_15_ctx mulmod_ctx;
|
|
};
|
|
sp_digit k[15];
|
|
sp_point_384 point;
|
|
} sp_ecc_sec_gen_384_ctx;
|
|
|
|
int sp_ecc_secret_gen_384_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
|
const ecc_point* pub, byte* out, word32* outLen, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_sec_gen_384_ctx* ctx = (sp_ecc_sec_gen_384_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
if (*outLen < 32U) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
sp_384_from_mp(ctx->k, 15, priv);
|
|
sp_384_point_from_ecc_point_15(&ctx->point, pub);
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
&ctx->point, &ctx->point, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
sp_384_to_bin_15(ctx->point.x, out);
|
|
*outLen = 48;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 1) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_384_ctx));
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_DHE */
|
|
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
SP_NOINLINE static void sp_384_rshift_15(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
for (i=0; i<14; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (26 - n))) & 0x3ffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<8; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (26 - n)) & 0x3ffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (26 - n)) & 0x3ffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (26 - n)) & 0x3ffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (26 - n)) & 0x3ffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (26 - n)) & 0x3ffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (26 - n)) & 0x3ffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (26 - n)) & 0x3ffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (26 - n)) & 0x3ffffff);
|
|
}
|
|
r[8] = (a[8] >> n) | ((a[9] << (26 - n)) & 0x3ffffff);
|
|
r[9] = (a[9] >> n) | ((a[10] << (26 - n)) & 0x3ffffff);
|
|
r[10] = (a[10] >> n) | ((a[11] << (26 - n)) & 0x3ffffff);
|
|
r[11] = (a[11] >> n) | ((a[12] << (26 - n)) & 0x3ffffff);
|
|
r[12] = (a[12] >> n) | ((a[13] << (26 - n)) & 0x3ffffff);
|
|
r[13] = (a[13] >> n) | ((a[14] << (26 - n)) & 0x3ffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[14] = a[14] >> n;
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_384_mul_d_15(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 15; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x3ffffff);
|
|
t >>= 26;
|
|
}
|
|
r[15] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[15];
|
|
|
|
t[ 0] = tb * a[ 0];
|
|
t[ 1] = tb * a[ 1];
|
|
t[ 2] = tb * a[ 2];
|
|
t[ 3] = tb * a[ 3];
|
|
t[ 4] = tb * a[ 4];
|
|
t[ 5] = tb * a[ 5];
|
|
t[ 6] = tb * a[ 6];
|
|
t[ 7] = tb * a[ 7];
|
|
t[ 8] = tb * a[ 8];
|
|
t[ 9] = tb * a[ 9];
|
|
t[10] = tb * a[10];
|
|
t[11] = tb * a[11];
|
|
t[12] = tb * a[12];
|
|
t[13] = tb * a[13];
|
|
t[14] = tb * a[14];
|
|
r[ 0] = (sp_digit) (t[ 0] & 0x3ffffff);
|
|
r[ 1] = (sp_digit)((t[ 0] >> 26) + (t[ 1] & 0x3ffffff));
|
|
r[ 2] = (sp_digit)((t[ 1] >> 26) + (t[ 2] & 0x3ffffff));
|
|
r[ 3] = (sp_digit)((t[ 2] >> 26) + (t[ 3] & 0x3ffffff));
|
|
r[ 4] = (sp_digit)((t[ 3] >> 26) + (t[ 4] & 0x3ffffff));
|
|
r[ 5] = (sp_digit)((t[ 4] >> 26) + (t[ 5] & 0x3ffffff));
|
|
r[ 6] = (sp_digit)((t[ 5] >> 26) + (t[ 6] & 0x3ffffff));
|
|
r[ 7] = (sp_digit)((t[ 6] >> 26) + (t[ 7] & 0x3ffffff));
|
|
r[ 8] = (sp_digit)((t[ 7] >> 26) + (t[ 8] & 0x3ffffff));
|
|
r[ 9] = (sp_digit)((t[ 8] >> 26) + (t[ 9] & 0x3ffffff));
|
|
r[10] = (sp_digit)((t[ 9] >> 26) + (t[10] & 0x3ffffff));
|
|
r[11] = (sp_digit)((t[10] >> 26) + (t[11] & 0x3ffffff));
|
|
r[12] = (sp_digit)((t[11] >> 26) + (t[12] & 0x3ffffff));
|
|
r[13] = (sp_digit)((t[12] >> 26) + (t[13] & 0x3ffffff));
|
|
r[14] = (sp_digit)((t[13] >> 26) + (t[14] & 0x3ffffff));
|
|
r[15] = (sp_digit) (t[14] >> 26);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
SP_NOINLINE static void sp_384_lshift_30(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
r[30] = a[29] >> (26 - n);
|
|
for (i=29; i>0; i--) {
|
|
r[i] = ((a[i] << n) | (a[i-1] >> (26 - n))) & 0x3ffffff;
|
|
}
|
|
#else
|
|
sp_int_digit s;
|
|
sp_int_digit t;
|
|
|
|
s = (sp_int_digit)a[29];
|
|
r[30] = s >> (26U - n);
|
|
s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
|
|
r[29] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
|
|
r[28] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
|
|
r[27] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
|
|
r[26] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
|
|
r[25] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
|
|
r[24] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
|
|
r[23] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
|
|
r[22] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
|
|
r[21] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
|
|
r[20] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
|
|
r[19] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
|
|
r[18] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
|
|
r[17] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
|
|
r[16] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
|
|
r[15] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
|
|
r[14] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
|
|
r[13] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
|
|
r[12] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
|
|
r[11] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
|
|
r[10] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
|
|
r[9] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
|
|
r[8] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
|
|
r[7] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
|
|
r[6] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
|
|
r[5] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
|
|
r[4] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
|
|
r[3] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
|
|
r[2] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
|
|
r[1] = ((s << n) | (t >> (26U - n))) & 0x3ffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[0] = (a[0] << n) & 0x3ffffff;
|
|
}
|
|
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Simplified based on top word of divisor being (1 << 26) - 1
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_384_div_15(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
sp_digit r1;
|
|
sp_digit mask;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 15 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 15 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 30 + 1;
|
|
sd = t2 + 15 + 1;
|
|
|
|
sp_384_mul_d_15(sd, d, (sp_digit)1 << 6);
|
|
sp_384_lshift_30(t1, a, 6);
|
|
t1[15 + 15] += t1[15 + 15 - 1] >> 26;
|
|
t1[15 + 15 - 1] &= 0x3ffffff;
|
|
for (i=14; i>=0; i--) {
|
|
r1 = t1[15 + i];
|
|
sp_384_mul_d_15(t2, sd, r1);
|
|
(void)sp_384_sub_15(&t1[i], &t1[i], t2);
|
|
t1[15 + i] -= t2[15];
|
|
sp_384_norm_15(&t1[i + 1]);
|
|
|
|
mask = ~((t1[15 + i] - 1) >> 31);
|
|
sp_384_cond_sub_15(t1 + i, t1 + i, sd, mask);
|
|
sp_384_norm_15(&t1[i + 1]);
|
|
}
|
|
sp_384_norm_15(t1);
|
|
sp_384_rshift_15(r, t1, 6);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_384_mod_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_384_div_15(a, m, NULL, r);
|
|
}
|
|
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* Multiply two number mod the order of P384 curve. (r = a * b mod order)
|
|
*
|
|
* r Result of the multiplication.
|
|
* a First operand of the multiplication.
|
|
* b Second operand of the multiplication.
|
|
*/
|
|
static void sp_384_mont_mul_order_15(sp_digit* r, const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_384_mul_15(r, a, b);
|
|
sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order);
|
|
}
|
|
|
|
#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Order-2 for the P384 curve. */
|
|
static const uint32_t p384_order_minus_2[12] = {
|
|
0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U,
|
|
0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU
|
|
};
|
|
#else
|
|
/* The low half of the order-2 of the P384 curve. */
|
|
static const uint32_t p384_order_low[6] = {
|
|
0xccc52971U,0xecec196aU,0x48b0a77aU,0x581a0db2U,0xf4372ddfU,0xc7634d81U
|
|
};
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Square number mod the order of P384 curve. (r = a * a mod order)
|
|
*
|
|
* r Result of the squaring.
|
|
* a Number to square.
|
|
*/
|
|
static void sp_384_mont_sqr_order_15(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_384_sqr_15(r, a);
|
|
sp_384_mont_reduce_order_15(r, p384_order, p384_mp_order);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Square number mod the order of P384 curve a number of times.
|
|
* (r = a ^ n mod order)
|
|
*
|
|
* r Result of the squaring.
|
|
* a Number to square.
|
|
*/
|
|
static void sp_384_mont_sqr_n_order_15(sp_digit* r, const sp_digit* a, int n)
|
|
{
|
|
int i;
|
|
|
|
sp_384_mont_sqr_order_15(r, a);
|
|
for (i=1; i<n; i++) {
|
|
sp_384_mont_sqr_order_15(r, r);
|
|
}
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Invert the number, in Montgomery form, modulo the order of the P384 curve.
|
|
* (r = 1 / a mod order)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_384_mont_inv_order_15_ctx {
|
|
int state;
|
|
int i;
|
|
} sp_384_mont_inv_order_15_ctx;
|
|
static int sp_384_mont_inv_order_15_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
|
|
sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_384_mont_inv_order_15_ctx* ctx = (sp_384_mont_inv_order_15_ctx*)sp_ctx;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_384_mont_inv_order_15_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 15);
|
|
ctx->i = 382;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
sp_384_mont_sqr_order_15(t, t);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
if ((p384_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
|
|
sp_384_mont_mul_order_15(t, t, a);
|
|
}
|
|
ctx->i--;
|
|
ctx->state = (ctx->i == 0) ? 3 : 1;
|
|
break;
|
|
case 3:
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 15U);
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
static void sp_384_mont_inv_order_15(sp_digit* r, const sp_digit* a,
|
|
sp_digit* td)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_digit* t = td;
|
|
int i;
|
|
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 15);
|
|
for (i=382; i>=0; i--) {
|
|
sp_384_mont_sqr_order_15(t, t);
|
|
if ((p384_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_384_mont_mul_order_15(t, t, a);
|
|
}
|
|
}
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 15U);
|
|
#else
|
|
sp_digit* t = td;
|
|
sp_digit* t2 = td + 2 * 15;
|
|
sp_digit* t3 = td + 4 * 15;
|
|
int i;
|
|
|
|
/* t = a^2 */
|
|
sp_384_mont_sqr_order_15(t, a);
|
|
/* t = a^3 = t * a */
|
|
sp_384_mont_mul_order_15(t, t, a);
|
|
/* t2= a^c = t ^ 2 ^ 2 */
|
|
sp_384_mont_sqr_n_order_15(t2, t, 2);
|
|
/* t = a^f = t2 * t */
|
|
sp_384_mont_mul_order_15(t, t2, t);
|
|
/* t2= a^f0 = t ^ 2 ^ 4 */
|
|
sp_384_mont_sqr_n_order_15(t2, t, 4);
|
|
/* t = a^ff = t2 * t */
|
|
sp_384_mont_mul_order_15(t, t2, t);
|
|
/* t2= a^ff00 = t ^ 2 ^ 8 */
|
|
sp_384_mont_sqr_n_order_15(t2, t, 8);
|
|
/* t3= a^ffff = t2 * t */
|
|
sp_384_mont_mul_order_15(t3, t2, t);
|
|
/* t2= a^ffff0000 = t3 ^ 2 ^ 16 */
|
|
sp_384_mont_sqr_n_order_15(t2, t3, 16);
|
|
/* t = a^ffffffff = t2 * t3 */
|
|
sp_384_mont_mul_order_15(t, t2, t3);
|
|
/* t2= a^ffffffff0000 = t ^ 2 ^ 16 */
|
|
sp_384_mont_sqr_n_order_15(t2, t, 16);
|
|
/* t = a^ffffffffffff = t2 * t3 */
|
|
sp_384_mont_mul_order_15(t, t2, t3);
|
|
/* t2= a^ffffffffffff000000000000 = t ^ 2 ^ 48 */
|
|
sp_384_mont_sqr_n_order_15(t2, t, 48);
|
|
/* t= a^fffffffffffffffffffffffff = t2 * t */
|
|
sp_384_mont_mul_order_15(t, t2, t);
|
|
/* t2= a^ffffffffffffffffffffffff000000000000000000000000 */
|
|
sp_384_mont_sqr_n_order_15(t2, t, 96);
|
|
/* t2= a^ffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */
|
|
sp_384_mont_mul_order_15(t2, t2, t);
|
|
for (i=191; i>=1; i--) {
|
|
sp_384_mont_sqr_order_15(t2, t2);
|
|
if ((p384_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_384_mont_mul_order_15(t2, t2, a);
|
|
}
|
|
}
|
|
sp_384_mont_sqr_order_15(t2, t2);
|
|
sp_384_mont_mul_order_15(r, t2, a);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
|
|
#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
|
|
#ifdef HAVE_ECC_SIGN
|
|
#ifndef SP_ECC_MAX_SIG_GEN
|
|
#define SP_ECC_MAX_SIG_GEN 64
|
|
#endif
|
|
|
|
/* Calculate second signature value S from R, k and private value.
|
|
*
|
|
* s = (r * x + e) / k
|
|
*
|
|
* s Signature value.
|
|
* r First signature value.
|
|
* k Ephemeral private key.
|
|
* x Private key as a number.
|
|
* e Hash of message as a number.
|
|
* tmp Temporary storage for intermediate numbers.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_calc_s_15(sp_digit* s, const sp_digit* r, sp_digit* k,
|
|
sp_digit* x, const sp_digit* e, sp_digit* tmp)
|
|
{
|
|
int err;
|
|
sp_digit carry;
|
|
sp_int32 c;
|
|
sp_digit* kInv = k;
|
|
|
|
/* Conv k to Montgomery form (mod order) */
|
|
sp_384_mul_15(k, k, p384_norm_order);
|
|
err = sp_384_mod_15(k, k, p384_order);
|
|
if (err == MP_OKAY) {
|
|
sp_384_norm_15(k);
|
|
|
|
/* kInv = 1/k mod order */
|
|
sp_384_mont_inv_order_15(kInv, k, tmp);
|
|
sp_384_norm_15(kInv);
|
|
|
|
/* s = r * x + e */
|
|
sp_384_mul_15(x, x, r);
|
|
err = sp_384_mod_15(x, x, p384_order);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_384_norm_15(x);
|
|
carry = sp_384_add_15(s, e, x);
|
|
sp_384_cond_sub_15(s, s, p384_order, 0 - carry);
|
|
sp_384_norm_15(s);
|
|
c = sp_384_cmp_15(s, p384_order);
|
|
sp_384_cond_sub_15(s, s, p384_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_384_norm_15(s);
|
|
|
|
/* s = s * k^-1 mod order */
|
|
sp_384_mont_mul_order_15(s, s, kInv);
|
|
sp_384_norm_15(s);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Sign the hash using the private key.
|
|
* e = [hash, 384 bits] from binary
|
|
* r = (k.G)->x mod order
|
|
* s = (r * x + e) / k mod order
|
|
* The hash is truncated to the first 384 bits.
|
|
*
|
|
* hash Hash to sign.
|
|
* hashLen Length of the hash data.
|
|
* rng Random number generator.
|
|
* priv Private part of key - scalar.
|
|
* rm First part of result as an mp_int.
|
|
* sm Sirst part of result as an mp_int.
|
|
* heap Heap to use for allocation.
|
|
* returns RNG failures, MEMORY_E when memory allocation fails and
|
|
* MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_sign_384(const byte* hash, word32 hashLen, WC_RNG* rng,
|
|
const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* e = NULL;
|
|
sp_point_384* point = NULL;
|
|
#else
|
|
sp_digit e[7 * 2 * 15];
|
|
sp_point_384 point[1];
|
|
#endif
|
|
sp_digit* x = NULL;
|
|
sp_digit* k = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit* s = NULL;
|
|
sp_int32 c;
|
|
int err = MP_OKAY;
|
|
int i;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_384*)XMALLOC(sizeof(sp_point_384), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (e == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
x = e + 2 * 15;
|
|
k = e + 4 * 15;
|
|
r = e + 6 * 15;
|
|
tmp = e + 8 * 15;
|
|
s = e;
|
|
|
|
if (hashLen > 48U) {
|
|
hashLen = 48U;
|
|
}
|
|
}
|
|
|
|
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
|
|
/* New random point. */
|
|
if (km == NULL || mp_iszero(km)) {
|
|
err = sp_384_ecc_gen_k_15(rng, k);
|
|
}
|
|
else {
|
|
sp_384_from_mp(k, 15, km);
|
|
mp_zero(km);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_ecc_mulmod_base_15(point, k, 1, 1, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* r = point->x mod order */
|
|
XMEMCPY(r, point->x, sizeof(sp_digit) * 15U);
|
|
sp_384_norm_15(r);
|
|
c = sp_384_cmp_15(r, p384_order);
|
|
sp_384_cond_sub_15(r, r, p384_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_384_norm_15(r);
|
|
|
|
if (!sp_384_iszero_15(r)) {
|
|
/* x is modified in calculation of s. */
|
|
sp_384_from_mp(x, 15, priv);
|
|
/* s ptr == e ptr, e is modified in calculation of s. */
|
|
sp_384_from_bin(e, 15, hash, (int)hashLen);
|
|
|
|
err = sp_384_calc_s_15(s, r, k, x, e, tmp);
|
|
|
|
/* Check that signature is usable. */
|
|
if ((err == MP_OKAY) && (!sp_384_iszero_15(s))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
|
|
i = 1;
|
|
#endif
|
|
}
|
|
|
|
if (i == 0) {
|
|
err = RNG_FAILURE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(r, rm);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(s, sm);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (e != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(e, sizeof(sp_digit) * 7 * 2 * 15);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(e, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (point != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(point, sizeof(sp_point_384));
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_sign_384_ctx {
|
|
int state;
|
|
union {
|
|
sp_384_ecc_mulmod_15_ctx mulmod_ctx;
|
|
sp_384_mont_inv_order_15_ctx mont_inv_order_ctx;
|
|
};
|
|
sp_digit e[2*15];
|
|
sp_digit x[2*15];
|
|
sp_digit k[2*15];
|
|
sp_digit r[2*15];
|
|
sp_digit tmp[3 * 2*15];
|
|
sp_point_384 point;
|
|
sp_digit* s;
|
|
sp_digit* kInv;
|
|
int i;
|
|
} sp_ecc_sign_384_ctx;
|
|
|
|
int sp_ecc_sign_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
|
|
mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_sign_384_ctx* ctx = (sp_ecc_sign_384_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_sign_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->s = ctx->e;
|
|
ctx->kInv = ctx->k;
|
|
|
|
ctx->i = SP_ECC_MAX_SIG_GEN;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* GEN */
|
|
/* New random point. */
|
|
if (km == NULL || mp_iszero(km)) {
|
|
err = sp_384_ecc_gen_k_15(rng, ctx->k);
|
|
}
|
|
else {
|
|
sp_384_from_mp(ctx->k, 15, km);
|
|
mp_zero(km);
|
|
}
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* MULMOD */
|
|
err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
&ctx->point, &p384_base, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
ctx->state = 3;
|
|
}
|
|
break;
|
|
case 3: /* MODORDER */
|
|
{
|
|
sp_int32 c;
|
|
/* r = point->x mod order */
|
|
XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 15U);
|
|
sp_384_norm_15(ctx->r);
|
|
c = sp_384_cmp_15(ctx->r, p384_order);
|
|
sp_384_cond_sub_15(ctx->r, ctx->r, p384_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_384_norm_15(ctx->r);
|
|
|
|
if (hashLen > 48U) {
|
|
hashLen = 48U;
|
|
}
|
|
sp_384_from_mp(ctx->x, 15, priv);
|
|
sp_384_from_bin(ctx->e, 15, hash, (int)hashLen);
|
|
ctx->state = 4;
|
|
break;
|
|
}
|
|
case 4: /* KMODORDER */
|
|
/* Conv k to Montgomery form (mod order) */
|
|
sp_384_mul_15(ctx->k, ctx->k, p384_norm_order);
|
|
err = sp_384_mod_15(ctx->k, ctx->k, p384_order);
|
|
if (err == MP_OKAY) {
|
|
sp_384_norm_15(ctx->k);
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 5;
|
|
}
|
|
break;
|
|
case 5: /* KINV */
|
|
/* kInv = 1/k mod order */
|
|
err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* KINVNORM */
|
|
sp_384_norm_15(ctx->kInv);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7: /* R */
|
|
/* s = r * x + e */
|
|
sp_384_mul_15(ctx->x, ctx->x, ctx->r);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8: /* S1 */
|
|
err = sp_384_mod_15(ctx->x, ctx->x, p384_order);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 9;
|
|
break;
|
|
case 9: /* S2 */
|
|
{
|
|
sp_digit carry;
|
|
sp_int32 c;
|
|
sp_384_norm_15(ctx->x);
|
|
carry = sp_384_add_15(ctx->s, ctx->e, ctx->x);
|
|
sp_384_cond_sub_15(ctx->s, ctx->s,
|
|
p384_order, 0 - carry);
|
|
sp_384_norm_15(ctx->s);
|
|
c = sp_384_cmp_15(ctx->s, p384_order);
|
|
sp_384_cond_sub_15(ctx->s, ctx->s, p384_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_384_norm_15(ctx->s);
|
|
|
|
/* s = s * k^-1 mod order */
|
|
sp_384_mont_mul_order_15(ctx->s, ctx->s, ctx->kInv);
|
|
sp_384_norm_15(ctx->s);
|
|
|
|
/* Check that signature is usable. */
|
|
if (sp_384_iszero_15(ctx->s) == 0) {
|
|
ctx->state = 10;
|
|
break;
|
|
}
|
|
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
|
|
ctx->i = 1;
|
|
#endif
|
|
|
|
/* not usable gen, try again */
|
|
ctx->i--;
|
|
if (ctx->i == 0) {
|
|
err = RNG_FAILURE_E;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
}
|
|
case 10: /* RES */
|
|
err = sp_384_to_mp(ctx->r, rm);
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(ctx->s, sm);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 10) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 15U);
|
|
XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 15U);
|
|
XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 15U);
|
|
XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 15U);
|
|
XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 15U);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_SIGN */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
static const char sp_384_tab32_15[32] = {
|
|
1, 10, 2, 11, 14, 22, 3, 30,
|
|
12, 15, 17, 19, 23, 26, 4, 31,
|
|
9, 13, 21, 29, 16, 18, 25, 8,
|
|
20, 28, 24, 7, 27, 6, 5, 32};
|
|
|
|
static int sp_384_num_bits_26_15(sp_digit v)
|
|
{
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
return sp_384_tab32_15[(uint32_t)(v*0x07C4ACDD) >> 27];
|
|
}
|
|
|
|
static int sp_384_num_bits_15(const sp_digit* a)
|
|
{
|
|
int i;
|
|
int r = 0;
|
|
|
|
for (i = 14; i >= 0; i--) {
|
|
if (a[i] != 0) {
|
|
r = sp_384_num_bits_26_15(a[i]);
|
|
r += i * 26;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Non-constant time modular inversion.
|
|
*
|
|
* @param [out] r Resulting number.
|
|
* @param [in] a Number to invert.
|
|
* @param [in] m Modulus.
|
|
* @return MP_OKAY on success.
|
|
* @return MEMEORY_E when dynamic memory allocation fails.
|
|
*/
|
|
static int sp_384_mod_inv_15(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* u = NULL;
|
|
#else
|
|
sp_digit u[15 * 4];
|
|
#endif
|
|
sp_digit* v = NULL;
|
|
sp_digit* b = NULL;
|
|
sp_digit* d = NULL;
|
|
int ut;
|
|
int vt;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (u == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
v = u + 15;
|
|
b = u + 2 * 15;
|
|
d = u + 3 * 15;
|
|
|
|
XMEMCPY(u, m, sizeof(sp_digit) * 15);
|
|
XMEMCPY(v, a, sizeof(sp_digit) * 15);
|
|
|
|
ut = sp_384_num_bits_15(u);
|
|
vt = sp_384_num_bits_15(v);
|
|
|
|
XMEMSET(b, 0, sizeof(sp_digit) * 15);
|
|
if ((v[0] & 1) == 0) {
|
|
sp_384_rshift1_15(v, v);
|
|
XMEMCPY(d, m, sizeof(sp_digit) * 15);
|
|
d[0]++;
|
|
sp_384_rshift1_15(d, d);
|
|
vt--;
|
|
|
|
while ((v[0] & 1) == 0) {
|
|
sp_384_rshift1_15(v, v);
|
|
if (d[0] & 1)
|
|
sp_384_add_15(d, d, m);
|
|
sp_384_rshift1_15(d, d);
|
|
vt--;
|
|
}
|
|
}
|
|
else {
|
|
XMEMSET(d+1, 0, sizeof(sp_digit) * (15 - 1));
|
|
d[0] = 1;
|
|
}
|
|
|
|
while (ut > 1 && vt > 1) {
|
|
if (ut > vt || (ut == vt &&
|
|
sp_384_cmp_15(u, v) >= 0)) {
|
|
sp_384_sub_15(u, u, v);
|
|
sp_384_norm_15(u);
|
|
|
|
sp_384_sub_15(b, b, d);
|
|
sp_384_norm_15(b);
|
|
if (b[14] < 0)
|
|
sp_384_add_15(b, b, m);
|
|
sp_384_norm_15(b);
|
|
ut = sp_384_num_bits_15(u);
|
|
|
|
do {
|
|
sp_384_rshift1_15(u, u);
|
|
if (b[0] & 1)
|
|
sp_384_add_15(b, b, m);
|
|
sp_384_rshift1_15(b, b);
|
|
ut--;
|
|
}
|
|
while (ut > 0 && (u[0] & 1) == 0);
|
|
}
|
|
else {
|
|
sp_384_sub_15(v, v, u);
|
|
sp_384_norm_15(v);
|
|
|
|
sp_384_sub_15(d, d, b);
|
|
sp_384_norm_15(d);
|
|
if (d[14] < 0)
|
|
sp_384_add_15(d, d, m);
|
|
sp_384_norm_15(d);
|
|
vt = sp_384_num_bits_15(v);
|
|
|
|
do {
|
|
sp_384_rshift1_15(v, v);
|
|
if (d[0] & 1)
|
|
sp_384_add_15(d, d, m);
|
|
sp_384_rshift1_15(d, d);
|
|
vt--;
|
|
}
|
|
while (vt > 0 && (v[0] & 1) == 0);
|
|
}
|
|
}
|
|
|
|
if (ut == 1)
|
|
XMEMCPY(r, b, sizeof(sp_digit) * 15);
|
|
else
|
|
XMEMCPY(r, d, sizeof(sp_digit) * 15);
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (u != NULL)
|
|
XFREE(u, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
|
|
*
|
|
* p1 First point to add and holds result.
|
|
* p2 Second point to add.
|
|
* tmp Temporary storage for intermediate numbers.
|
|
*/
|
|
static void sp_384_add_points_15(sp_point_384* p1, const sp_point_384* p2,
|
|
sp_digit* tmp)
|
|
{
|
|
|
|
sp_384_proj_point_add_15(p1, p1, p2, tmp);
|
|
if (sp_384_iszero_15(p1->z)) {
|
|
if (sp_384_iszero_15(p1->x) && sp_384_iszero_15(p1->y)) {
|
|
sp_384_proj_point_dbl_15(p1, p2, tmp);
|
|
}
|
|
else {
|
|
/* Y ordinate is not used from here - don't set. */
|
|
p1->x[0] = 0;
|
|
p1->x[1] = 0;
|
|
p1->x[2] = 0;
|
|
p1->x[3] = 0;
|
|
p1->x[4] = 0;
|
|
p1->x[5] = 0;
|
|
p1->x[6] = 0;
|
|
p1->x[7] = 0;
|
|
p1->x[8] = 0;
|
|
p1->x[9] = 0;
|
|
p1->x[10] = 0;
|
|
p1->x[11] = 0;
|
|
p1->x[12] = 0;
|
|
p1->x[13] = 0;
|
|
p1->x[14] = 0;
|
|
XMEMCPY(p1->z, p384_norm_mod, sizeof(p384_norm_mod));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Calculate the verification point: [e/s]G + [r/s]Q
|
|
*
|
|
* p1 Calculated point.
|
|
* p2 Public point and temporary.
|
|
* s Second part of signature as a number.
|
|
* u1 Temporary number.
|
|
* u2 Temproray number.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_384_calc_vfy_point_15(sp_point_384* p1, sp_point_384* p2,
|
|
sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
|
|
{
|
|
int err;
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
err = sp_384_mod_inv_15(s, s, p384_order);
|
|
if (err == MP_OKAY)
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
{
|
|
sp_384_mul_15(s, s, p384_norm_order);
|
|
err = sp_384_mod_15(s, s, p384_order);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_384_norm_15(s);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
{
|
|
sp_384_mont_inv_order_15(s, s, tmp);
|
|
sp_384_mont_mul_order_15(u1, u1, s);
|
|
sp_384_mont_mul_order_15(u2, u2, s);
|
|
}
|
|
#else
|
|
{
|
|
sp_384_mont_mul_order_15(u1, u1, s);
|
|
sp_384_mont_mul_order_15(u2, u2, s);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
{
|
|
err = sp_384_ecc_mulmod_base_15(p1, u1, 0, 0, heap);
|
|
}
|
|
}
|
|
if ((err == MP_OKAY) && sp_384_iszero_15(p1->z)) {
|
|
p1->infinity = 1;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_ecc_mulmod_15(p2, p2, u2, 0, 0, heap);
|
|
}
|
|
if ((err == MP_OKAY) && sp_384_iszero_15(p2->z)) {
|
|
p2->infinity = 1;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_384_add_points_15(p1, p2, tmp);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef HAVE_ECC_VERIFY
|
|
/* Verify the signature values with the hash and public key.
|
|
* e = Truncate(hash, 384)
|
|
* u1 = e/s mod order
|
|
* u2 = r/s mod order
|
|
* r == (u1.G + u2.Q)->x mod order
|
|
* Optimization: Leave point in projective form.
|
|
* (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
|
|
* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
|
|
* The hash is truncated to the first 384 bits.
|
|
*
|
|
* hash Hash to sign.
|
|
* hashLen Length of the hash data.
|
|
* rng Random number generator.
|
|
* priv Private part of key - scalar.
|
|
* rm First part of result as an mp_int.
|
|
* sm Sirst part of result as an mp_int.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_verify_384(const byte* hash, word32 hashLen, const mp_int* pX,
|
|
const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
|
|
int* res, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* u1 = NULL;
|
|
sp_point_384* p1 = NULL;
|
|
#else
|
|
sp_digit u1[18 * 15];
|
|
sp_point_384 p1[2];
|
|
#endif
|
|
sp_digit* u2 = NULL;
|
|
sp_digit* s = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_point_384* p2 = NULL;
|
|
sp_digit carry;
|
|
sp_int32 c = 0;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p1 = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p1 == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (u1 == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
u2 = u1 + 2 * 15;
|
|
s = u1 + 4 * 15;
|
|
tmp = u1 + 6 * 15;
|
|
p2 = p1 + 1;
|
|
|
|
if (hashLen > 48U) {
|
|
hashLen = 48U;
|
|
}
|
|
|
|
sp_384_from_bin(u1, 15, hash, (int)hashLen);
|
|
sp_384_from_mp(u2, 15, rm);
|
|
sp_384_from_mp(s, 15, sm);
|
|
sp_384_from_mp(p2->x, 15, pX);
|
|
sp_384_from_mp(p2->y, 15, pY);
|
|
sp_384_from_mp(p2->z, 15, pZ);
|
|
|
|
err = sp_384_calc_vfy_point_15(p1, p2, s, u1, u2, tmp, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
|
|
/* Reload r and convert to Montgomery form. */
|
|
sp_384_from_mp(u2, 15, rm);
|
|
err = sp_384_mod_mul_norm_15(u2, u2, p384_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* u1 = r.z'.z' mod prime */
|
|
sp_384_mont_sqr_15(p1->z, p1->z, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod);
|
|
*res = (int)(sp_384_cmp_15(p1->x, u1) == 0);
|
|
if (*res == 0) {
|
|
/* Reload r and add order. */
|
|
sp_384_from_mp(u2, 15, rm);
|
|
carry = sp_384_add_15(u2, u2, p384_order);
|
|
/* Carry means result is greater than mod and is not valid. */
|
|
if (carry == 0) {
|
|
sp_384_norm_15(u2);
|
|
|
|
/* Compare with mod and if greater or equal then not valid. */
|
|
c = sp_384_cmp_15(u2, p384_mod);
|
|
}
|
|
}
|
|
if ((*res == 0) && (c < 0)) {
|
|
/* Convert to Montogomery form */
|
|
err = sp_384_mod_mul_norm_15(u2, u2, p384_mod);
|
|
if (err == MP_OKAY) {
|
|
/* u1 = (r + 1*order).z'.z' mod prime */
|
|
{
|
|
sp_384_mont_mul_15(u1, u2, p1->z, p384_mod, p384_mp_mod);
|
|
}
|
|
*res = (sp_384_cmp_15(p1->x, u1) == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (u1 != NULL)
|
|
XFREE(u1, heap, DYNAMIC_TYPE_ECC);
|
|
if (p1 != NULL)
|
|
XFREE(p1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_verify_384_ctx {
|
|
int state;
|
|
union {
|
|
sp_384_ecc_mulmod_15_ctx mulmod_ctx;
|
|
sp_384_mont_inv_order_15_ctx mont_inv_order_ctx;
|
|
sp_384_proj_point_dbl_15_ctx dbl_ctx;
|
|
sp_384_proj_point_add_15_ctx add_ctx;
|
|
};
|
|
sp_digit u1[2*15];
|
|
sp_digit u2[2*15];
|
|
sp_digit s[2*15];
|
|
sp_digit tmp[2*15 * 6];
|
|
sp_point_384 p1;
|
|
sp_point_384 p2;
|
|
} sp_ecc_verify_384_ctx;
|
|
|
|
int sp_ecc_verify_384_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
|
|
word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
|
|
const mp_int* rm, const mp_int* sm, int* res, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_verify_384_ctx* ctx = (sp_ecc_verify_384_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_verify_384_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
if (hashLen > 48U) {
|
|
hashLen = 48U;
|
|
}
|
|
|
|
sp_384_from_bin(ctx->u1, 15, hash, (int)hashLen);
|
|
sp_384_from_mp(ctx->u2, 15, rm);
|
|
sp_384_from_mp(ctx->s, 15, sm);
|
|
sp_384_from_mp(ctx->p2.x, 15, pX);
|
|
sp_384_from_mp(ctx->p2.y, 15, pY);
|
|
sp_384_from_mp(ctx->p2.z, 15, pZ);
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* NORMS0 */
|
|
sp_384_mul_15(ctx->s, ctx->s, p384_norm_order);
|
|
err = sp_384_mod_15(ctx->s, ctx->s, p384_order);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* NORMS1 */
|
|
sp_384_norm_15(ctx->s);
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* NORMS2 */
|
|
err = sp_384_mont_inv_order_15_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
ctx->state = 4;
|
|
}
|
|
break;
|
|
case 4: /* NORMS3 */
|
|
sp_384_mont_mul_order_15(ctx->u1, ctx->u1, ctx->s);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* NORMS4 */
|
|
sp_384_mont_mul_order_15(ctx->u2, ctx->u2, ctx->s);
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 6;
|
|
break;
|
|
case 6: /* MULBASE */
|
|
err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p384_base, ctx->u1, 0, 0, heap);
|
|
if (err == MP_OKAY) {
|
|
if (sp_384_iszero_15(ctx->p1.z)) {
|
|
ctx->p1.infinity = 1;
|
|
}
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 7;
|
|
}
|
|
break;
|
|
case 7: /* MULMOD */
|
|
err = sp_384_ecc_mulmod_15_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
|
|
if (err == MP_OKAY) {
|
|
if (sp_384_iszero_15(ctx->p2.z)) {
|
|
ctx->p2.infinity = 1;
|
|
}
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 8;
|
|
}
|
|
break;
|
|
case 8: /* ADD */
|
|
err = sp_384_proj_point_add_15_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 9;
|
|
break;
|
|
case 9: /* MONT */
|
|
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
|
|
/* Reload r and convert to Montgomery form. */
|
|
sp_384_from_mp(ctx->u2, 15, rm);
|
|
err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 10;
|
|
break;
|
|
case 10: /* SQR */
|
|
/* u1 = r.z'.z' mod prime */
|
|
sp_384_mont_sqr_15(ctx->p1.z, ctx->p1.z, p384_mod, p384_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11: /* MUL */
|
|
sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod, p384_mp_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12: /* RES */
|
|
{
|
|
sp_int32 c = 0;
|
|
err = MP_OKAY; /* math okay, now check result */
|
|
*res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0);
|
|
if (*res == 0) {
|
|
sp_digit carry;
|
|
|
|
/* Reload r and add order. */
|
|
sp_384_from_mp(ctx->u2, 15, rm);
|
|
carry = sp_384_add_15(ctx->u2, ctx->u2, p384_order);
|
|
/* Carry means result is greater than mod and is not valid. */
|
|
if (carry == 0) {
|
|
sp_384_norm_15(ctx->u2);
|
|
|
|
/* Compare with mod and if greater or equal then not valid. */
|
|
c = sp_384_cmp_15(ctx->u2, p384_mod);
|
|
}
|
|
}
|
|
if ((*res == 0) && (c < 0)) {
|
|
/* Convert to Montogomery form */
|
|
err = sp_384_mod_mul_norm_15(ctx->u2, ctx->u2, p384_mod);
|
|
if (err == MP_OKAY) {
|
|
/* u1 = (r + 1*order).z'.z' mod prime */
|
|
sp_384_mont_mul_15(ctx->u1, ctx->u2, ctx->p1.z, p384_mod,
|
|
p384_mp_mod);
|
|
*res = (int)(sp_384_cmp_15(ctx->p1.x, ctx->u1) == 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
} /* switch */
|
|
|
|
if (err == MP_OKAY && ctx->state != 12) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_VERIFY */
|
|
|
|
#ifdef HAVE_ECC_CHECK_KEY
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* point EC point.
|
|
* heap Heap to use if dynamically allocating.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_384_ecc_is_point_15(const sp_point_384* point,
|
|
void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[15 * 4];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15 * 4, heap, DYNAMIC_TYPE_ECC);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
(void)heap;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 2 * 15;
|
|
|
|
sp_384_sqr_15(t1, point->y);
|
|
(void)sp_384_mod_15(t1, t1, p384_mod);
|
|
sp_384_sqr_15(t2, point->x);
|
|
(void)sp_384_mod_15(t2, t2, p384_mod);
|
|
sp_384_mul_15(t2, t2, point->x);
|
|
(void)sp_384_mod_15(t2, t2, p384_mod);
|
|
(void)sp_384_sub_15(t2, p384_mod, t2);
|
|
sp_384_mont_add_15(t1, t1, t2, p384_mod);
|
|
|
|
sp_384_mont_add_15(t1, t1, point->x, p384_mod);
|
|
sp_384_mont_add_15(t1, t1, point->x, p384_mod);
|
|
sp_384_mont_add_15(t1, t1, point->x, p384_mod);
|
|
|
|
if (sp_384_cmp_15(t1, p384_b) != 0) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_is_point_384(const mp_int* pX, const mp_int* pY)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_384* pub = NULL;
|
|
#else
|
|
sp_point_384 pub[1];
|
|
#endif
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_384_from_mp(pub->x, 15, pX);
|
|
sp_384_from_mp(pub->y, 15, pY);
|
|
sp_384_from_bin(pub->z, 15, one, (int)sizeof(one));
|
|
|
|
err = sp_384_ecc_is_point_15(pub, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the private scalar generates the EC point (px, py), the point is
|
|
* on the curve and the point has the correct order.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* privm Private scalar that generates EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve, ECC_INF_E if the point does not have the correct order,
|
|
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
|
|
* MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_check_key_384(const mp_int* pX, const mp_int* pY,
|
|
const mp_int* privm, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* priv = NULL;
|
|
sp_point_384* pub = NULL;
|
|
#else
|
|
sp_digit priv[15];
|
|
sp_point_384 pub[2];
|
|
#endif
|
|
sp_point_384* p = NULL;
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
|
|
/* Quick check the lengs of public key ordinates and private key are in
|
|
* range. Proper check later.
|
|
*/
|
|
if (((mp_count_bits(pX) > 384) ||
|
|
(mp_count_bits(pY) > 384) ||
|
|
((privm != NULL) && (mp_count_bits(privm) > 384)))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
pub = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY && privm) {
|
|
priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 15, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (priv == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = pub + 1;
|
|
|
|
sp_384_from_mp(pub->x, 15, pX);
|
|
sp_384_from_mp(pub->y, 15, pY);
|
|
sp_384_from_bin(pub->z, 15, one, (int)sizeof(one));
|
|
if (privm)
|
|
sp_384_from_mp(priv, 15, privm);
|
|
|
|
/* Check point at infinitiy. */
|
|
if ((sp_384_iszero_15(pub->x) != 0) &&
|
|
(sp_384_iszero_15(pub->y) != 0)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
|
|
/* Check range of X and Y */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_384_cmp_15(pub->x, p384_mod) >= 0) ||
|
|
(sp_384_cmp_15(pub->y, p384_mod) >= 0))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Check point is on curve */
|
|
err = sp_384_ecc_is_point_15(pub, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Point * order = infinity */
|
|
err = sp_384_ecc_mulmod_15(p, pub, p384_order, 1, 1, heap);
|
|
}
|
|
/* Check result is infinity */
|
|
if ((err == MP_OKAY) && ((sp_384_iszero_15(p->x) == 0) ||
|
|
(sp_384_iszero_15(p->y) == 0))) {
|
|
err = ECC_INF_E;
|
|
}
|
|
|
|
if (privm) {
|
|
if (err == MP_OKAY) {
|
|
/* Base * private = point */
|
|
err = sp_384_ecc_mulmod_base_15(p, priv, 1, 1, heap);
|
|
}
|
|
/* Check result is public key */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_384_cmp_15(p->x, pub->x) != 0) ||
|
|
(sp_384_cmp_15(p->y, pub->y) != 0))) {
|
|
err = ECC_PRIV_KEY_E;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, heap, DYNAMIC_TYPE_ECC);
|
|
if (priv != NULL)
|
|
XFREE(priv, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
|
|
/* Add two projective EC points together.
|
|
* (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
|
|
*
|
|
* pX First EC point's X ordinate.
|
|
* pY First EC point's Y ordinate.
|
|
* pZ First EC point's Z ordinate.
|
|
* qX Second EC point's X ordinate.
|
|
* qY Second EC point's Y ordinate.
|
|
* qZ Second EC point's Z ordinate.
|
|
* rX Resultant EC point's X ordinate.
|
|
* rY Resultant EC point's Y ordinate.
|
|
* rZ Resultant EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_proj_add_point_384(mp_int* pX, mp_int* pY, mp_int* pZ,
|
|
mp_int* qX, mp_int* qY, mp_int* qZ,
|
|
mp_int* rX, mp_int* rY, mp_int* rZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_384* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 15 * 6];
|
|
sp_point_384 p[2];
|
|
#endif
|
|
sp_point_384* q = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_384*)XMALLOC(sizeof(sp_point_384) * 2, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
q = p + 1;
|
|
|
|
sp_384_from_mp(p->x, 15, pX);
|
|
sp_384_from_mp(p->y, 15, pY);
|
|
sp_384_from_mp(p->z, 15, pZ);
|
|
sp_384_from_mp(q->x, 15, qX);
|
|
sp_384_from_mp(q->y, 15, qY);
|
|
sp_384_from_mp(q->z, 15, qZ);
|
|
p->infinity = sp_384_iszero_15(p->x) &
|
|
sp_384_iszero_15(p->y);
|
|
q->infinity = sp_384_iszero_15(q->x) &
|
|
sp_384_iszero_15(q->y);
|
|
|
|
sp_384_proj_point_add_15(p, p, q, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->x, rX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->y, rY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->z, rZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Double a projective EC point.
|
|
* (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
|
|
*
|
|
* pX EC point's X ordinate.
|
|
* pY EC point's Y ordinate.
|
|
* pZ EC point's Z ordinate.
|
|
* rX Resultant EC point's X ordinate.
|
|
* rY Resultant EC point's Y ordinate.
|
|
* rZ Resultant EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_proj_dbl_point_384(mp_int* pX, mp_int* pY, mp_int* pZ,
|
|
mp_int* rX, mp_int* rY, mp_int* rZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_384* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 15 * 2];
|
|
sp_point_384 p[1];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 2, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_384_from_mp(p->x, 15, pX);
|
|
sp_384_from_mp(p->y, 15, pY);
|
|
sp_384_from_mp(p->z, 15, pZ);
|
|
p->infinity = sp_384_iszero_15(p->x) &
|
|
sp_384_iszero_15(p->y);
|
|
|
|
sp_384_proj_point_dbl_15(p, p, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->x, rX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->y, rY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->z, rZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Map a projective EC point to affine in place.
|
|
* pZ will be one.
|
|
*
|
|
* pX EC point's X ordinate.
|
|
* pY EC point's Y ordinate.
|
|
* pZ EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_map_384(mp_int* pX, mp_int* pY, mp_int* pZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_384* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 15 * 6];
|
|
sp_point_384 p[1];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_384*)XMALLOC(sizeof(sp_point_384), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 15 * 6, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
sp_384_from_mp(p->x, 15, pX);
|
|
sp_384_from_mp(p->y, 15, pY);
|
|
sp_384_from_mp(p->z, 15, pZ);
|
|
p->infinity = sp_384_iszero_15(p->x) &
|
|
sp_384_iszero_15(p->y);
|
|
|
|
sp_384_map_15(p, p, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->x, pX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->y, pY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_384_to_mp(p->z, pZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
|
|
#ifdef HAVE_COMP_KEY
|
|
/* Find the square root of a number mod the prime of the curve.
|
|
*
|
|
* y The number to operate on and the result.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_384_mont_sqrt_15(sp_digit* y)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[5 * 2 * 15];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* t3 = NULL;
|
|
sp_digit* t4 = NULL;
|
|
sp_digit* t5 = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 2 * 15, NULL, DYNAMIC_TYPE_ECC);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 2 * 15;
|
|
t3 = t1 + 4 * 15;
|
|
t4 = t1 + 6 * 15;
|
|
t5 = t1 + 8 * 15;
|
|
|
|
{
|
|
/* t2 = y ^ 0x2 */
|
|
sp_384_mont_sqr_15(t2, y, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0x3 */
|
|
sp_384_mont_mul_15(t1, t2, y, p384_mod, p384_mp_mod);
|
|
/* t5 = y ^ 0xc */
|
|
sp_384_mont_sqr_n_15(t5, t1, 2, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0xf */
|
|
sp_384_mont_mul_15(t1, t1, t5, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x1e */
|
|
sp_384_mont_sqr_15(t2, t1, p384_mod, p384_mp_mod);
|
|
/* t3 = y ^ 0x1f */
|
|
sp_384_mont_mul_15(t3, t2, y, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x3e0 */
|
|
sp_384_mont_sqr_n_15(t2, t3, 5, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0x3ff */
|
|
sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x7fe0 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 5, p384_mod, p384_mp_mod);
|
|
/* t3 = y ^ 0x7fff */
|
|
sp_384_mont_mul_15(t3, t3, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x3fff800 */
|
|
sp_384_mont_sqr_n_15(t2, t3, 15, p384_mod, p384_mp_mod);
|
|
/* t4 = y ^ 0x3ffffff */
|
|
sp_384_mont_mul_15(t4, t3, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0xffffffc000000 */
|
|
sp_384_mont_sqr_n_15(t2, t4, 30, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0xfffffffffffff */
|
|
sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0xfffffffffffffff000000000000000 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 60, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0xffffffffffffffffffffffffffffff */
|
|
sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0xffffffffffffffffffffffffffffff000000000000000000000000000000 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 120, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_384_mont_mul_15(t1, t1, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8000 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 15, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_384_mont_mul_15(t1, t3, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80000000 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 31, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff */
|
|
sp_384_mont_mul_15(t1, t4, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffff0 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 4, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc */
|
|
sp_384_mont_mul_15(t1, t5, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000000 */
|
|
sp_384_mont_sqr_n_15(t2, t1, 62, p384_mod, p384_mp_mod);
|
|
/* t1 = y ^ 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeffffffff0000000000000001 */
|
|
sp_384_mont_mul_15(t1, y, t2, p384_mod, p384_mp_mod);
|
|
/* t2 = y ^ 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffffffc00000000000000040000000 */
|
|
sp_384_mont_sqr_n_15(y, t1, 30, p384_mod, p384_mp_mod);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/* Uncompress the point given the X ordinate.
|
|
*
|
|
* xm X ordinate.
|
|
* odd Whether the Y ordinate is odd.
|
|
* ym Calculated Y ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_uncompress_384(mp_int* xm, int odd, mp_int* ym)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* x = NULL;
|
|
#else
|
|
sp_digit x[4 * 15];
|
|
#endif
|
|
sp_digit* y = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 15, NULL, DYNAMIC_TYPE_ECC);
|
|
if (x == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
y = x + 2 * 15;
|
|
|
|
sp_384_from_mp(x, 15, xm);
|
|
err = sp_384_mod_mul_norm_15(x, x, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* y = x^3 */
|
|
{
|
|
sp_384_mont_sqr_15(y, x, p384_mod, p384_mp_mod);
|
|
sp_384_mont_mul_15(y, y, x, p384_mod, p384_mp_mod);
|
|
}
|
|
/* y = x^3 - 3x */
|
|
sp_384_mont_sub_15(y, y, x, p384_mod);
|
|
sp_384_mont_sub_15(y, y, x, p384_mod);
|
|
sp_384_mont_sub_15(y, y, x, p384_mod);
|
|
/* y = x^3 - 3x + b */
|
|
err = sp_384_mod_mul_norm_15(x, p384_b, p384_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_384_mont_add_15(y, y, x, p384_mod);
|
|
/* y = sqrt(x^3 - 3x + b) */
|
|
err = sp_384_mont_sqrt_15(y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(y + 15, 0, 15U * sizeof(sp_digit));
|
|
sp_384_mont_reduce_15(y, p384_mod, p384_mp_mod);
|
|
if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
|
|
sp_384_mont_sub_15(y, p384_mod, y, p384_mod);
|
|
}
|
|
|
|
err = sp_384_to_mp(y, ym);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (x != NULL)
|
|
XFREE(x, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#endif /* WOLFSSL_SP_384 */
|
|
#ifdef WOLFSSL_SP_521
|
|
|
|
/* Point structure to use. */
|
|
typedef struct sp_point_521 {
|
|
/* X ordinate of point. */
|
|
sp_digit x[2 * 21];
|
|
/* Y ordinate of point. */
|
|
sp_digit y[2 * 21];
|
|
/* Z ordinate of point. */
|
|
sp_digit z[2 * 21];
|
|
/* Indicates point is at infinity. */
|
|
int infinity;
|
|
} sp_point_521;
|
|
|
|
/* The modulus (prime) of the curve P521. */
|
|
static const sp_digit p521_mod[21] = {
|
|
0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,
|
|
0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,
|
|
0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff
|
|
};
|
|
/* The Montgomery normalizer for modulus of the curve P521. */
|
|
static const sp_digit p521_norm_mod[21] = {
|
|
0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000
|
|
};
|
|
/* The Montgomery multiplier for modulus of the curve P521. */
|
|
static sp_digit p521_mp_mod = 0x000001;
|
|
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
|
|
defined(HAVE_ECC_VERIFY)
|
|
/* The order of the curve P521. */
|
|
static const sp_digit p521_order[21] = {
|
|
0x1386409,0x1db8f48,0x1ebaedb,0x1113388,0x1bb5c9b,0x04d2e81,0x00523dc,
|
|
0x0d6ff98,0x1bf2f96,0x0c343c1,0x1fffe94,0x1ffffff,0x1ffffff,0x1ffffff,
|
|
0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff
|
|
};
|
|
#endif
|
|
/* The order of the curve P521 minus 2. */
|
|
static const sp_digit p521_order2[21] = {
|
|
0x1386407,0x1db8f48,0x1ebaedb,0x1113388,0x1bb5c9b,0x04d2e81,0x00523dc,
|
|
0x0d6ff98,0x1bf2f96,0x0c343c1,0x1fffe94,0x1ffffff,0x1ffffff,0x1ffffff,
|
|
0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x1ffffff,0x01fffff
|
|
};
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* The Montgomery normalizer for order of the curve P521. */
|
|
static const sp_digit p521_norm_order[21] = {
|
|
0x0c79bf7,0x02470b7,0x0145124,0x0eecc77,0x044a364,0x1b2d17e,0x1fadc23,
|
|
0x1290067,0x040d069,0x13cbc3e,0x000016b,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000
|
|
};
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* The Montgomery multiplier for order of the curve P521. */
|
|
static sp_digit p521_mp_order = 0x1a995c7;
|
|
#endif
|
|
/* The base point of curve P521. */
|
|
static const sp_point_521 p521_base = {
|
|
/* X ordinate */
|
|
{
|
|
0x0e5bd66,0x13f18e1,0x0a6fe5f,0x030ad48,0x1348b3c,0x1fd46f1,0x1049e8b,
|
|
0x051fc3b,0x1efe759,0x0a5af3b,0x14f6ea8,0x1ec0d69,0x01f828a,0x029fda9,
|
|
0x19204e4,0x1688538,0x1662395,0x0cf1f65,0x1013a73,0x1c0d6e0,0x00c6858,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0
|
|
},
|
|
/* Y ordinate */
|
|
{
|
|
0x1d16650,0x14a3b4f,0x090222f,0x0d44e58,0x153c708,0x1683b09,0x0e404fe,
|
|
0x0818aa1,0x15ef426,0x1f7394c,0x1998b25,0x1a2e4e7,0x0817afb,0x0bcda23,
|
|
0x1d51125,0x037b331,0x1b42c7d,0x02e452f,0x08ef001,0x12d4f13,0x0118392,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0
|
|
},
|
|
/* Z ordinate */
|
|
{
|
|
0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0
|
|
},
|
|
/* infinity */
|
|
0
|
|
};
|
|
#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY)
|
|
static const sp_digit p521_b[21] = {
|
|
0x1503f00,0x08fea35,0x13c7bd1,0x107a586,0x1573df8,0x18df839,0x102f4ee,
|
|
0x0f62ca5,0x1ec7e93,0x10c9ca8,0x0427855,0x13231de,0x13b8b48,0x0cd98af,
|
|
0x169c96e,0x081dd45,0x1a0b685,0x1c94d10,0x1872687,0x1d72c31,0x0051953
|
|
};
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_521_mul_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[20]) * b[20];
|
|
r[41] = (sp_digit)(c >> 25);
|
|
c &= 0x1ffffff;
|
|
for (k = 39; k >= 0; k--) {
|
|
if (k >= 21) {
|
|
i = k - 20;
|
|
imax = 20;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 25;
|
|
r[k + 2] += (sp_digit)(c >> 25);
|
|
r[k + 1] = (sp_digit)(c & 0x1ffffff);
|
|
c = lo & 0x1ffffff;
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
#else
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_521_mul_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int j;
|
|
sp_int64 t[42];
|
|
|
|
XMEMSET(t, 0, sizeof(t));
|
|
for (i=0; i<21; i++) {
|
|
for (j=0; j<21; j++) {
|
|
t[i+j] += ((sp_int64)a[i]) * b[j];
|
|
}
|
|
}
|
|
for (i=0; i<41; i++) {
|
|
r[i] = t[i] & 0x1ffffff;
|
|
t[i+1] += t[i] >> 25;
|
|
}
|
|
r[41] = (sp_digit)t[41];
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_521_sqr_21(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[20]) * a[20];
|
|
r[41] = (sp_digit)(c >> 25);
|
|
c = (c & 0x1ffffff) << 25;
|
|
for (k = 39; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 20) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 20;
|
|
}
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 50);
|
|
r[k + 1] = (sp_digit)((c >> 25) & 0x1ffffff);
|
|
c = (c & 0x1ffffff) << 25;
|
|
}
|
|
r[0] = (sp_digit)(c >> 25);
|
|
}
|
|
|
|
#else
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_521_sqr_21(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
sp_int64 t[42];
|
|
|
|
XMEMSET(t, 0, sizeof(t));
|
|
for (i=0; i<21; i++) {
|
|
for (j=0; j<i; j++) {
|
|
t[i+j] += (((sp_int64)a[i]) * a[j]) * 2;
|
|
}
|
|
t[i+i] += ((sp_int64)a[i]) * a[i];
|
|
}
|
|
for (i=0; i<41; i++) {
|
|
r[i] = t[i] & 0x1ffffff;
|
|
t[i+1] += t[i] >> 25;
|
|
}
|
|
r[41] = (sp_digit)t[41];
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_521_add_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#else
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_521_add_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[16] = a[16] + b[16];
|
|
r[17] = a[17] + b[17];
|
|
r[18] = a[18] + b[18];
|
|
r[19] = a[19] + b[19];
|
|
r[20] = a[20] + b[20];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_521_sub_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#else
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_521_sub_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[16] = a[16] - b[16];
|
|
r[17] = a[17] - b[17];
|
|
r[18] = a[18] - b[18];
|
|
r[19] = a[19] - b[19];
|
|
r[20] = a[20] - b[20];
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_521_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 25
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 25
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x1ffffff;
|
|
s = 25U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 25U) <= (word32)DIGIT_BIT) {
|
|
s += 25U;
|
|
r[j] &= 0x1ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 25) {
|
|
r[j] &= 0x1ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 25 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Convert a point of type ecc_point to type sp_point_521.
|
|
*
|
|
* p Point of type sp_point_521 (result).
|
|
* pm Point of type ecc_point.
|
|
*/
|
|
static void sp_521_point_from_ecc_point_21(sp_point_521* p,
|
|
const ecc_point* pm)
|
|
{
|
|
XMEMSET(p->x, 0, sizeof(p->x));
|
|
XMEMSET(p->y, 0, sizeof(p->y));
|
|
XMEMSET(p->z, 0, sizeof(p->z));
|
|
sp_521_from_mp(p->x, 21, pm->x);
|
|
sp_521_from_mp(p->y, 21, pm->y);
|
|
sp_521_from_mp(p->z, 21, pm->z);
|
|
p->infinity = 0;
|
|
}
|
|
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_521_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (521 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 25
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 21);
|
|
r->used = 21;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 25
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 21; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 25) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 25 - s;
|
|
}
|
|
r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 21; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 25 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 25 - s;
|
|
}
|
|
else {
|
|
s += 25;
|
|
}
|
|
}
|
|
r->used = (521 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Convert a point of type sp_point_521 to type ecc_point.
|
|
*
|
|
* p Point of type sp_point_521.
|
|
* pm Point of type ecc_point (result).
|
|
* returns MEMORY_E when allocation of memory in ecc_point fails otherwise
|
|
* MP_OKAY.
|
|
*/
|
|
static int sp_521_point_to_ecc_point_21(const sp_point_521* p, ecc_point* pm)
|
|
{
|
|
int err;
|
|
|
|
err = sp_521_to_mp(p->x, pm->x);
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->y, pm->y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->z, pm->z);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Normalize the values in each word to 25 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_521_norm_21(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 20; i++) {
|
|
a[i+1] += a[i] >> 25;
|
|
a[i] &= 0x1ffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 16; i += 8) {
|
|
a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff;
|
|
a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff;
|
|
a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff;
|
|
a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff;
|
|
a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff;
|
|
a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff;
|
|
a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff;
|
|
a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff;
|
|
}
|
|
a[17] += a[16] >> 25; a[16] &= 0x1ffffff;
|
|
a[18] += a[17] >> 25; a[17] &= 0x1ffffff;
|
|
a[19] += a[18] >> 25; a[18] &= 0x1ffffff;
|
|
a[20] += a[19] >> 25; a[19] &= 0x1ffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Reduce the number back to 521 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_521_mont_reduce_21(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
|
|
(void)m;
|
|
(void)mp;
|
|
|
|
for (i = 0; i < 20; i++) {
|
|
a[i] += ((a[20 + i] >> 21) + (a[20 + i + 1] << 4)) & 0x1ffffff;
|
|
}
|
|
a[20] &= 0x1fffff;
|
|
a[20] += ((a[40] >> 21) + (a[41] << 4)) & 0x1ffffff;
|
|
|
|
sp_521_norm_21(a);
|
|
|
|
a[0] += a[20] >> 21;
|
|
a[20] &= 0x1fffff;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_521_cmp_21(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=20; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 24);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
r |= (a[20] - b[20]) & (0 - (sp_digit)1);
|
|
r |= (a[19] - b[19]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[18] - b[18]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[17] - b[17]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[16] - b[16]) & ~(((sp_digit)0 - r) >> 24);
|
|
for (i = 8; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 24);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_521_cond_sub_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
r[16] = a[16] - (b[16] & m);
|
|
r[17] = a[17] - (b[17] & m);
|
|
r[18] = a[18] - (b[18] & m);
|
|
r[19] = a[19] - (b[19] & m);
|
|
r[20] = a[20] - (b[20] & m);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_521_mul_add_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 20; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1ffffff;
|
|
t[1] += t[0] >> 25;
|
|
r[i+1] = t[1] & 0x1ffffff;
|
|
t[2] += t[1] >> 25;
|
|
r[i+2] = t[2] & 0x1ffffff;
|
|
t[3] += t[2] >> 25;
|
|
r[i+3] = t[3] & 0x1ffffff;
|
|
t[0] = t[3] >> 25;
|
|
}
|
|
t[0] += (tb * a[20]) + r[20];
|
|
r[20] = t[0] & 0x1ffffff;
|
|
r[21] += (sp_digit)(t[0] >> 25);
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffff);
|
|
for (i = 0; i < 16; i += 8) {
|
|
t[1] = tb * a[i+1];
|
|
r[i+1] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
|
|
t[2] = tb * a[i+2];
|
|
r[i+2] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff));
|
|
t[3] = tb * a[i+3];
|
|
r[i+3] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff));
|
|
t[4] = tb * a[i+4];
|
|
r[i+4] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff));
|
|
t[5] = tb * a[i+5];
|
|
r[i+5] += (sp_digit)((t[4] >> 25) + (t[5] & 0x1ffffff));
|
|
t[6] = tb * a[i+6];
|
|
r[i+6] += (sp_digit)((t[5] >> 25) + (t[6] & 0x1ffffff));
|
|
t[7] = tb * a[i+7];
|
|
r[i+7] += (sp_digit)((t[6] >> 25) + (t[7] & 0x1ffffff));
|
|
t[0] = tb * a[i+8];
|
|
r[i+8] += (sp_digit)((t[7] >> 25) + (t[0] & 0x1ffffff));
|
|
}
|
|
t[1] = tb * a[17];
|
|
r[17] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
|
|
t[2] = tb * a[18];
|
|
r[18] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff));
|
|
t[3] = tb * a[19];
|
|
r[19] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff));
|
|
t[4] = tb * a[20];
|
|
r[20] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff));
|
|
r[21] += (sp_digit)(t[4] >> 25);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Shift the result in the high 521 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_521_mont_shift_21(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
sp_digit n;
|
|
sp_digit s;
|
|
|
|
s = a[21];
|
|
n = a[20] >> 21;
|
|
for (i = 0; i < 20; i++) {
|
|
n += (s & 0x1ffffff) << 4;
|
|
r[i] = n & 0x1ffffff;
|
|
n >>= 25;
|
|
s = a[22 + i] + (s >> 25);
|
|
}
|
|
n += s << 4;
|
|
r[20] = n;
|
|
#else
|
|
sp_digit n;
|
|
sp_digit s;
|
|
int i;
|
|
|
|
s = a[21]; n = a[20] >> 21;
|
|
for (i = 0; i < 16; i += 8) {
|
|
n += (s & 0x1ffffff) << 4; r[i+0] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+22] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+1] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+23] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+2] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+24] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+3] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+25] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+4] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+26] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+5] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+27] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+6] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+28] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[i+7] = n & 0x1ffffff;
|
|
n >>= 25; s = a[i+29] + (s >> 25);
|
|
}
|
|
n += (s & 0x1ffffff) << 4; r[16] = n & 0x1ffffff;
|
|
n >>= 25; s = a[38] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[17] = n & 0x1ffffff;
|
|
n >>= 25; s = a[39] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[18] = n & 0x1ffffff;
|
|
n >>= 25; s = a[40] + (s >> 25);
|
|
n += (s & 0x1ffffff) << 4; r[19] = n & 0x1ffffff;
|
|
n >>= 25; s = a[41] + (s >> 25);
|
|
n += s << 4; r[20] = n;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
XMEMSET(&r[21], 0, sizeof(*r) * 21U);
|
|
}
|
|
|
|
/* Reduce the number back to 521 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_521_mont_reduce_order_21(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_521_norm_21(a + 21);
|
|
|
|
for (i=0; i<20; i++) {
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1ffffff;
|
|
sp_521_mul_add_21(a+i, m, mu);
|
|
a[i+1] += a[i] >> 25;
|
|
}
|
|
mu = ((sp_uint32)a[i] * (sp_uint32)mp) & 0x1fffffL;
|
|
sp_521_mul_add_21(a+i, m, mu);
|
|
a[i+1] += a[i] >> 25;
|
|
a[i] &= 0x1ffffff;
|
|
sp_521_mont_shift_21(a, a);
|
|
over = a[20] >> 21;
|
|
sp_521_cond_sub_21(a, a, m, ~((over - 1) >> 31));
|
|
sp_521_norm_21(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_521_mont_mul_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_521_mul_21(r, a, b);
|
|
sp_521_mont_reduce_21(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_521_mont_sqr_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_521_sqr_21(r, a);
|
|
sp_521_mont_reduce_21(r, m, mp);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Square the Montgomery form number a number of times. (r = a ^ n mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* n Number of times to square.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
static void sp_521_mont_sqr_n_21(sp_digit* r, const sp_digit* a, int n,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_521_mont_sqr_21(r, a, m, mp);
|
|
for (; n > 1; n--) {
|
|
sp_521_mont_sqr_21(r, r, m, mp);
|
|
}
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Mod-2 for the P521 curve. */
|
|
static const uint32_t p521_mod_minus_2[17] = {
|
|
0xfffffffdU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,
|
|
0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,
|
|
0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU
|
|
};
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
|
|
* P521 curve. (r = 1 / a mod m)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
static void sp_521_mont_inv_21(sp_digit* r, const sp_digit* a, sp_digit* td)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_digit* t = td;
|
|
int i;
|
|
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 21);
|
|
for (i=519; i>=0; i--) {
|
|
sp_521_mont_sqr_21(t, t, p521_mod, p521_mp_mod);
|
|
if (p521_mod_minus_2[i / 32] & ((sp_digit)1 << (i % 32)))
|
|
sp_521_mont_mul_21(t, t, a, p521_mod, p521_mp_mod);
|
|
}
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 21);
|
|
#else
|
|
sp_digit* t1 = td;
|
|
sp_digit* t2 = td + 2 * 21;
|
|
sp_digit* t3 = td + 4 * 21;
|
|
|
|
/* 0x2 */
|
|
sp_521_mont_sqr_21(t1, a, p521_mod, p521_mp_mod);
|
|
/* 0x3 */
|
|
sp_521_mont_mul_21(t2, t1, a, p521_mod, p521_mp_mod);
|
|
/* 0x6 */
|
|
sp_521_mont_sqr_21(t1, t2, p521_mod, p521_mp_mod);
|
|
/* 0x7 */
|
|
sp_521_mont_mul_21(t3, t1, a, p521_mod, p521_mp_mod);
|
|
/* 0xc */
|
|
sp_521_mont_sqr_n_21(t1, t2, 2, p521_mod, p521_mp_mod);
|
|
/* 0xf */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0x78 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 3, p521_mod, p521_mp_mod);
|
|
/* 0x7f */
|
|
sp_521_mont_mul_21(t3, t3, t1, p521_mod, p521_mp_mod);
|
|
/* 0xf0 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 4, p521_mod, p521_mp_mod);
|
|
/* 0xff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0xff00 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 8, p521_mod, p521_mp_mod);
|
|
/* 0xffff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0xffff0000 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 16, p521_mod, p521_mp_mod);
|
|
/* 0xffffffff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0xffffffff00000000 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 32, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffff0000000000000000 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 64, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffffff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 128, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000000000 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 256, p521_mod, p521_mp_mod);
|
|
/* 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_521_mont_mul_21(t2, t2, t1, p521_mod, p521_mp_mod);
|
|
/* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff80 */
|
|
sp_521_mont_sqr_n_21(t1, t2, 7, p521_mod, p521_mp_mod);
|
|
/* 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff */
|
|
sp_521_mont_mul_21(t2, t3, t1, p521_mod, p521_mp_mod);
|
|
/* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc */
|
|
sp_521_mont_sqr_n_21(t1, t2, 2, p521_mod, p521_mp_mod);
|
|
/* 0x1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd */
|
|
sp_521_mont_mul_21(r, t1, a, p521_mod, p521_mp_mod);
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Map the Montgomery form projective coordinate point to an affine point.
|
|
*
|
|
* r Resulting affine coordinate point.
|
|
* p Montgomery form projective coordinate point.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_map_21(sp_point_521* r, const sp_point_521* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*21;
|
|
sp_int32 n;
|
|
|
|
sp_521_mont_inv_21(t1, p->z, t + 2*21);
|
|
|
|
sp_521_mont_sqr_21(t2, t1, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t1, t2, t1, p521_mod, p521_mp_mod);
|
|
|
|
/* x /= z^2 */
|
|
sp_521_mont_mul_21(r->x, p->x, t2, p521_mod, p521_mp_mod);
|
|
XMEMSET(r->x + 21, 0, sizeof(sp_digit) * 21U);
|
|
sp_521_mont_reduce_21(r->x, p521_mod, p521_mp_mod);
|
|
/* Reduce x to less than modulus */
|
|
n = sp_521_cmp_21(r->x, p521_mod);
|
|
sp_521_cond_sub_21(r->x, r->x, p521_mod, ~(n >> 24));
|
|
sp_521_norm_21(r->x);
|
|
|
|
/* y /= z^3 */
|
|
sp_521_mont_mul_21(r->y, p->y, t1, p521_mod, p521_mp_mod);
|
|
XMEMSET(r->y + 21, 0, sizeof(sp_digit) * 21U);
|
|
sp_521_mont_reduce_21(r->y, p521_mod, p521_mp_mod);
|
|
/* Reduce y to less than modulus */
|
|
n = sp_521_cmp_21(r->y, p521_mod);
|
|
sp_521_cond_sub_21(r->y, r->y, p521_mod, ~(n >> 24));
|
|
sp_521_norm_21(r->y);
|
|
|
|
XMEMSET(r->z, 0, sizeof(r->z) / 2);
|
|
r->z[0] = 1;
|
|
}
|
|
|
|
/* Add two Montgomery form numbers (r = a + b % m).
|
|
*
|
|
* r Result of addition.
|
|
* a First number to add in Montgomery form.
|
|
* b Second number to add in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_521_mont_add_21(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_521_add_21(r, a, b);
|
|
sp_521_norm_21(r);
|
|
over = r[20] >> 21;
|
|
sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
|
|
sp_521_norm_21(r);
|
|
}
|
|
|
|
/* Double a Montgomery form number (r = a + a % m).
|
|
*
|
|
* r Result of doubling.
|
|
* a Number to double in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_521_mont_dbl_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_521_add_21(r, a, a);
|
|
sp_521_norm_21(r);
|
|
over = r[20] >> 21;
|
|
sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
|
|
sp_521_norm_21(r);
|
|
}
|
|
|
|
/* Triple a Montgomery form number (r = a + a + a % m).
|
|
*
|
|
* r Result of Tripling.
|
|
* a Number to triple in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_521_mont_tpl_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_521_add_21(r, a, a);
|
|
sp_521_norm_21(r);
|
|
over = r[20] >> 21;
|
|
sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
|
|
sp_521_norm_21(r);
|
|
(void)sp_521_add_21(r, r, a);
|
|
sp_521_norm_21(r);
|
|
over = r[20] >> 21;
|
|
sp_521_cond_sub_21(r, r, m, ~((over - 1) >> 31));
|
|
sp_521_norm_21(r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_521_cond_add_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_521_cond_add_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
r[16] = a[16] + (b[16] & m);
|
|
r[17] = a[17] + (b[17] & m);
|
|
r[18] = a[18] + (b[18] & m);
|
|
r[19] = a[19] + (b[19] & m);
|
|
r[20] = a[20] + (b[20] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Subtract two Montgomery form numbers (r = a - b % m).
|
|
*
|
|
* r Result of subtration.
|
|
* a Number to subtract from in Montgomery form.
|
|
* b Number to subtract with in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_521_mont_sub_21(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
(void)sp_521_sub_21(r, a, b);
|
|
sp_521_norm_21(r);
|
|
sp_521_cond_add_21(r, r, m, r[20] >> 21);
|
|
sp_521_norm_21(r);
|
|
}
|
|
|
|
#define sp_521_mont_sub_lower_21 sp_521_mont_sub_21
|
|
/* Shift number left one bit.
|
|
* Bottom bit is lost.
|
|
*
|
|
* r Result of shift.
|
|
* a Number to shift.
|
|
*/
|
|
SP_NOINLINE static void sp_521_rshift1_21(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=0; i<20; i++) {
|
|
r[i] = (a[i] >> 1) + ((a[i + 1] << 24) & 0x1ffffff);
|
|
}
|
|
#else
|
|
r[0] = (a[0] >> 1) + ((a[1] << 24) & 0x1ffffff);
|
|
r[1] = (a[1] >> 1) + ((a[2] << 24) & 0x1ffffff);
|
|
r[2] = (a[2] >> 1) + ((a[3] << 24) & 0x1ffffff);
|
|
r[3] = (a[3] >> 1) + ((a[4] << 24) & 0x1ffffff);
|
|
r[4] = (a[4] >> 1) + ((a[5] << 24) & 0x1ffffff);
|
|
r[5] = (a[5] >> 1) + ((a[6] << 24) & 0x1ffffff);
|
|
r[6] = (a[6] >> 1) + ((a[7] << 24) & 0x1ffffff);
|
|
r[7] = (a[7] >> 1) + ((a[8] << 24) & 0x1ffffff);
|
|
r[8] = (a[8] >> 1) + ((a[9] << 24) & 0x1ffffff);
|
|
r[9] = (a[9] >> 1) + ((a[10] << 24) & 0x1ffffff);
|
|
r[10] = (a[10] >> 1) + ((a[11] << 24) & 0x1ffffff);
|
|
r[11] = (a[11] >> 1) + ((a[12] << 24) & 0x1ffffff);
|
|
r[12] = (a[12] >> 1) + ((a[13] << 24) & 0x1ffffff);
|
|
r[13] = (a[13] >> 1) + ((a[14] << 24) & 0x1ffffff);
|
|
r[14] = (a[14] >> 1) + ((a[15] << 24) & 0x1ffffff);
|
|
r[15] = (a[15] >> 1) + ((a[16] << 24) & 0x1ffffff);
|
|
r[16] = (a[16] >> 1) + ((a[17] << 24) & 0x1ffffff);
|
|
r[17] = (a[17] >> 1) + ((a[18] << 24) & 0x1ffffff);
|
|
r[18] = (a[18] >> 1) + ((a[19] << 24) & 0x1ffffff);
|
|
r[19] = (a[19] >> 1) + ((a[20] << 24) & 0x1ffffff);
|
|
#endif
|
|
r[20] = a[20] >> 1;
|
|
}
|
|
|
|
/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
|
|
*
|
|
* r Result of division by 2.
|
|
* a Number to divide.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_521_div2_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_521_cond_add_21(r, a, m, 0 - (a[0] & 1));
|
|
sp_521_norm_21(r);
|
|
sp_521_rshift1_21(r, r);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_proj_point_dbl_21(sp_point_521* r, const sp_point_521* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*21;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
|
|
x = r->x;
|
|
y = r->y;
|
|
z = r->z;
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
|
|
/* T1 = Z * Z */
|
|
sp_521_mont_sqr_21(t1, p->z, p521_mod, p521_mp_mod);
|
|
/* Z = Y * Z */
|
|
sp_521_mont_mul_21(z, p->y, p->z, p521_mod, p521_mp_mod);
|
|
/* Z = 2Z */
|
|
sp_521_mont_dbl_21(z, z, p521_mod);
|
|
/* T2 = X - T1 */
|
|
sp_521_mont_sub_21(t2, p->x, t1, p521_mod);
|
|
/* T1 = X + T1 */
|
|
sp_521_mont_add_21(t1, p->x, t1, p521_mod);
|
|
/* T2 = T1 * T2 */
|
|
sp_521_mont_mul_21(t2, t1, t2, p521_mod, p521_mp_mod);
|
|
/* T1 = 3T2 */
|
|
sp_521_mont_tpl_21(t1, t2, p521_mod);
|
|
/* Y = 2Y */
|
|
sp_521_mont_dbl_21(y, p->y, p521_mod);
|
|
/* Y = Y * Y */
|
|
sp_521_mont_sqr_21(y, y, p521_mod, p521_mp_mod);
|
|
/* T2 = Y * Y */
|
|
sp_521_mont_sqr_21(t2, y, p521_mod, p521_mp_mod);
|
|
/* T2 = T2/2 */
|
|
sp_521_div2_21(t2, t2, p521_mod);
|
|
/* Y = Y * X */
|
|
sp_521_mont_mul_21(y, y, p->x, p521_mod, p521_mp_mod);
|
|
/* X = T1 * T1 */
|
|
sp_521_mont_sqr_21(x, t1, p521_mod, p521_mp_mod);
|
|
/* X = X - Y */
|
|
sp_521_mont_sub_21(x, x, y, p521_mod);
|
|
/* X = X - Y */
|
|
sp_521_mont_sub_21(x, x, y, p521_mod);
|
|
/* Y = Y - X */
|
|
sp_521_mont_sub_lower_21(y, y, x, p521_mod);
|
|
/* Y = Y * T1 */
|
|
sp_521_mont_mul_21(y, y, t1, p521_mod, p521_mp_mod);
|
|
/* Y = Y - T2 */
|
|
sp_521_mont_sub_21(y, y, t2, p521_mod);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_521_proj_point_dbl_21_ctx {
|
|
int state;
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_521_proj_point_dbl_21_ctx;
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_521_proj_point_dbl_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r, const sp_point_521* p, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_521_proj_point_dbl_21_ctx* ctx = (sp_521_proj_point_dbl_21_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_521_proj_point_dbl_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*21;
|
|
ctx->x = r->x;
|
|
ctx->y = r->y;
|
|
ctx->z = r->z;
|
|
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* T1 = Z * Z */
|
|
sp_521_mont_sqr_21(ctx->t1, p->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
/* Z = Y * Z */
|
|
sp_521_mont_mul_21(ctx->z, p->y, p->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
/* Z = 2Z */
|
|
sp_521_mont_dbl_21(ctx->z, ctx->z, p521_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* T2 = X - T1 */
|
|
sp_521_mont_sub_21(ctx->t2, p->x, ctx->t1, p521_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
/* T1 = X + T1 */
|
|
sp_521_mont_add_21(ctx->t1, p->x, ctx->t1, p521_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
/* T2 = T1 * T2 */
|
|
sp_521_mont_mul_21(ctx->t2, ctx->t1, ctx->t2, p521_mod, p521_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* T1 = 3T2 */
|
|
sp_521_mont_tpl_21(ctx->t1, ctx->t2, p521_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* Y = 2Y */
|
|
sp_521_mont_dbl_21(ctx->y, p->y, p521_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Y = Y * Y */
|
|
sp_521_mont_sqr_21(ctx->y, ctx->y, p521_mod, p521_mp_mod);
|
|
ctx->state = 10;
|
|
break;
|
|
case 10:
|
|
/* T2 = Y * Y */
|
|
sp_521_mont_sqr_21(ctx->t2, ctx->y, p521_mod, p521_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* T2 = T2/2 */
|
|
sp_521_div2_21(ctx->t2, ctx->t2, p521_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* Y = Y * X */
|
|
sp_521_mont_mul_21(ctx->y, ctx->y, p->x, p521_mod, p521_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
/* X = T1 * T1 */
|
|
sp_521_mont_sqr_21(ctx->x, ctx->t1, p521_mod, p521_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
/* X = X - Y */
|
|
sp_521_mont_sub_21(ctx->x, ctx->x, ctx->y, p521_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* X = X - Y */
|
|
sp_521_mont_sub_21(ctx->x, ctx->x, ctx->y, p521_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
/* Y = Y - X */
|
|
sp_521_mont_sub_lower_21(ctx->y, ctx->y, ctx->x, p521_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
/* Y = Y * T1 */
|
|
sp_521_mont_mul_21(ctx->y, ctx->y, ctx->t1, p521_mod, p521_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
/* Y = Y - T2 */
|
|
sp_521_mont_sub_21(ctx->y, ctx->y, ctx->t2, p521_mod);
|
|
ctx->state = 19;
|
|
/* fall-through */
|
|
case 19:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 19) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
/* Compare two numbers to determine if they are equal.
|
|
* Constant time implementation.
|
|
*
|
|
* a First number to compare.
|
|
* b Second number to compare.
|
|
* returns 1 when equal and 0 otherwise.
|
|
*/
|
|
static int sp_521_cmp_equal_21(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
|
|
(a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
|
|
(a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
|
|
(a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
|
|
(a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) |
|
|
(a[15] ^ b[15]) | (a[16] ^ b[16]) | (a[17] ^ b[17]) |
|
|
(a[18] ^ b[18]) | (a[19] ^ b[19]) | (a[20] ^ b[20])) == 0;
|
|
}
|
|
|
|
/* Returns 1 if the number of zero.
|
|
* Implementation is constant time.
|
|
*
|
|
* a Number to check.
|
|
* returns 1 if the number is zero and 0 otherwise.
|
|
*/
|
|
static int sp_521_iszero_21(const sp_digit* a)
|
|
{
|
|
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
|
|
a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
|
|
a[16] | a[17] | a[18] | a[19] | a[20]) == 0;
|
|
}
|
|
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_proj_point_add_21(sp_point_521* r,
|
|
const sp_point_521* p, const sp_point_521* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*21;
|
|
sp_digit* t3 = t + 4*21;
|
|
sp_digit* t4 = t + 6*21;
|
|
sp_digit* t5 = t + 8*21;
|
|
sp_digit* t6 = t + 10*21;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_521_mont_sqr_21(t1, q->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t3, t1, q->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t1, t1, p->x, p521_mod, p521_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_521_mont_sqr_21(t2, p->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t4, t2, p->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_521_mont_mul_21(t3, t3, p->y, p521_mod, p521_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod);
|
|
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_521_cmp_equal_21(t2, t1) &
|
|
sp_521_cmp_equal_21(t4, t3)) {
|
|
sp_521_proj_point_dbl_21(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t6;
|
|
sp_digit* y = t1;
|
|
sp_digit* z = t2;
|
|
int i;
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
|
|
/* H = U2 - U1 */
|
|
sp_521_mont_sub_21(t2, t2, t1, p521_mod);
|
|
/* R = S2 - S1 */
|
|
sp_521_mont_sub_21(t4, t4, t3, p521_mod);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(y, t1, t5, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_521_mont_mul_21(z, p->z, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(z, z, q->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sqr_21(x, t4, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(x, x, t5, p521_mod);
|
|
sp_521_mont_mul_21(t5, t5, t3, p521_mod, p521_mp_mod);
|
|
sp_521_mont_dbl_21(t3, y, p521_mod);
|
|
sp_521_mont_sub_21(x, x, t3, p521_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_521_mont_sub_lower_21(y, y, x, p521_mod);
|
|
sp_521_mont_mul_21(y, y, t4, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(y, y, t5, p521_mod);
|
|
for (i = 0; i < 21; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_521_proj_point_add_21_ctx {
|
|
int state;
|
|
sp_521_proj_point_dbl_21_ctx dbl_ctx;
|
|
const sp_point_521* ap[2];
|
|
sp_point_521* rp[2];
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* t3;
|
|
sp_digit* t4;
|
|
sp_digit* t5;
|
|
sp_digit* t6;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_521_proj_point_add_21_ctx;
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_521_proj_point_add_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
|
|
const sp_point_521* p, const sp_point_521* q, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_521_proj_point_add_21_ctx* ctx = (sp_521_proj_point_add_21_ctx*)sp_ctx->data;
|
|
|
|
/* Ensure only the first point is the same as the result. */
|
|
if (q == r) {
|
|
const sp_point_521* a = p;
|
|
p = q;
|
|
q = a;
|
|
}
|
|
|
|
typedef char ctx_size_test[sizeof(sp_521_proj_point_add_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*21;
|
|
ctx->t3 = t + 4*21;
|
|
ctx->t4 = t + 6*21;
|
|
ctx->t5 = t + 8*21;
|
|
ctx->t6 = t + 10*21;
|
|
ctx->x = ctx->t6;
|
|
ctx->y = ctx->t1;
|
|
ctx->z = ctx->t2;
|
|
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* U1 = X1*Z2^2 */
|
|
sp_521_mont_sqr_21(ctx->t1, q->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
sp_521_mont_mul_21(ctx->t3, ctx->t1, q->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
sp_521_mont_mul_21(ctx->t1, ctx->t1, p->x, p521_mod, p521_mp_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* U2 = X2*Z1^2 */
|
|
sp_521_mont_sqr_21(ctx->t2, p->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
sp_521_mont_mul_21(ctx->t4, ctx->t2, p->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
sp_521_mont_mul_21(ctx->t2, ctx->t2, q->x, p521_mod, p521_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_521_mont_mul_21(ctx->t3, ctx->t3, p->y, p521_mod, p521_mp_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_521_mont_mul_21(ctx->t4, ctx->t4, q->y, p521_mod, p521_mp_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_521_cmp_equal_21(ctx->t2, ctx->t1) &
|
|
sp_521_cmp_equal_21(ctx->t4, ctx->t3)) {
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
sp_521_proj_point_dbl_21(r, p, t);
|
|
ctx->state = 25;
|
|
}
|
|
else {
|
|
ctx->state = 10;
|
|
}
|
|
break;
|
|
case 10:
|
|
/* H = U2 - U1 */
|
|
sp_521_mont_sub_21(ctx->t2, ctx->t2, ctx->t1, p521_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* R = S2 - S1 */
|
|
sp_521_mont_sub_21(ctx->t4, ctx->t4, ctx->t3, p521_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_521_mont_sqr_21(ctx->t5, ctx->t2, p521_mod, p521_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
sp_521_mont_mul_21(ctx->y, ctx->t1, ctx->t5, p521_mod, p521_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
sp_521_mont_mul_21(ctx->t5, ctx->t5, ctx->t2, p521_mod, p521_mp_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_521_mont_mul_21(ctx->z, p->z, ctx->t2, p521_mod, p521_mp_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
sp_521_mont_mul_21(ctx->z, ctx->z, q->z, p521_mod, p521_mp_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
sp_521_mont_sqr_21(ctx->x, ctx->t4, p521_mod, p521_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
sp_521_mont_sub_21(ctx->x, ctx->x, ctx->t5, p521_mod);
|
|
ctx->state = 19;
|
|
break;
|
|
case 19:
|
|
sp_521_mont_mul_21(ctx->t5, ctx->t5, ctx->t3, p521_mod, p521_mp_mod);
|
|
ctx->state = 20;
|
|
break;
|
|
case 20:
|
|
sp_521_mont_dbl_21(ctx->t3, ctx->y, p521_mod);
|
|
sp_521_mont_sub_21(ctx->x, ctx->x, ctx->t3, p521_mod);
|
|
ctx->state = 21;
|
|
break;
|
|
case 21:
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_521_mont_sub_lower_21(ctx->y, ctx->y, ctx->x, p521_mod);
|
|
ctx->state = 22;
|
|
break;
|
|
case 22:
|
|
sp_521_mont_mul_21(ctx->y, ctx->y, ctx->t4, p521_mod, p521_mp_mod);
|
|
ctx->state = 23;
|
|
break;
|
|
case 23:
|
|
sp_521_mont_sub_21(ctx->y, ctx->y, ctx->t5, p521_mod);
|
|
ctx->state = 24;
|
|
break;
|
|
case 24:
|
|
{
|
|
int i;
|
|
sp_digit maskp = 0 - (q->infinity & (!p->infinity));
|
|
sp_digit maskq = 0 - (p->infinity & (!q->infinity));
|
|
sp_digit maskt = ~(maskp | maskq);
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (ctx->x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (ctx->y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (ctx->z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
ctx->state = 25;
|
|
break;
|
|
}
|
|
case 25:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 25) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
/* Multiply a number by Montgomery normalizer mod modulus (prime).
|
|
*
|
|
* r The resulting Montgomery form number.
|
|
* a The number to convert.
|
|
* m The modulus (prime).
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_521_mod_mul_norm_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
(void)m;
|
|
|
|
if (r != a) {
|
|
XMEMCPY(r, a, 21 * sizeof(sp_digit));
|
|
}
|
|
|
|
return MP_OKAY;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Small implementation using add and double that is cache attack resistant but
|
|
* allocates memory rather than use large stacks.
|
|
* 521 adds and doubles.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_521 t[3];
|
|
sp_digit tmp[2 * 21 * 6];
|
|
#endif
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
int err = MP_OKAY;
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(t, 0, sizeof(sp_point_521) * 3);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod);
|
|
}
|
|
if (err == MP_OKAY)
|
|
err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod);
|
|
if (err == MP_OKAY)
|
|
err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod);
|
|
|
|
if (err == MP_OKAY) {
|
|
i = 20;
|
|
c = 21;
|
|
n = k[i--] << (25 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1)
|
|
break;
|
|
|
|
n = k[i--];
|
|
c = 25;
|
|
}
|
|
|
|
y = (n >> 24) & 1;
|
|
n <<= 1;
|
|
|
|
sp_521_proj_point_add_21(&t[y^1], &t[0], &t[1], tmp);
|
|
|
|
XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])),
|
|
sizeof(sp_point_521));
|
|
sp_521_proj_point_dbl_21(&t[2], &t[2], tmp);
|
|
XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])), &t[2],
|
|
sizeof(sp_point_521));
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_521_map_21(r, &t[0], tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &t[0], sizeof(sp_point_521));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(tmp, sizeof(sp_digit) * 2 * 21 * 6);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(t, sizeof(sp_point_521) * 3);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_521_ecc_mulmod_21_ctx {
|
|
int state;
|
|
union {
|
|
sp_521_proj_point_dbl_21_ctx dbl_ctx;
|
|
sp_521_proj_point_add_21_ctx add_ctx;
|
|
};
|
|
sp_point_521 t[3];
|
|
sp_digit tmp[2 * 21 * 6];
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
} sp_521_ecc_mulmod_21_ctx;
|
|
|
|
static int sp_521_ecc_mulmod_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
|
|
const sp_point_521* g, const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_521_ecc_mulmod_21_ctx* ctx = (sp_521_ecc_mulmod_21_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_521_ecc_mulmod_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
XMEMSET(ctx->t, 0, sizeof(sp_point_521) * 3);
|
|
ctx->i = 20;
|
|
ctx->c = 21;
|
|
ctx->n = k[ctx->i--] << (25 - ctx->c);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
ctx->t[0].infinity = 1;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* T1X */
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_521_mod_mul_norm_21(ctx->t[1].x, g->x, p521_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* T1Y */
|
|
err = sp_521_mod_mul_norm_21(ctx->t[1].y, g->y, p521_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* T1Z */
|
|
err = sp_521_mod_mul_norm_21(ctx->t[1].z, g->z, p521_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4: /* ADDPREP */
|
|
if (ctx->c == 0) {
|
|
if (ctx->i == -1) {
|
|
ctx->state = 7;
|
|
break;
|
|
}
|
|
|
|
ctx->n = k[ctx->i--];
|
|
ctx->c = 25;
|
|
}
|
|
ctx->y = (ctx->n >> 24) & 1;
|
|
ctx->n <<= 1;
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* ADD */
|
|
err = sp_521_proj_point_add_21_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
|
|
&ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])),
|
|
sizeof(sp_point_521));
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* DBL */
|
|
err = sp_521_proj_point_dbl_21_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
|
|
&ctx->t[2], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
|
|
sizeof(sp_point_521));
|
|
ctx->state = 4;
|
|
ctx->c--;
|
|
}
|
|
break;
|
|
case 7: /* MAP */
|
|
if (map != 0) {
|
|
sp_521_map_21(r, &ctx->t[0], ctx->tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &ctx->t[0], sizeof(sp_point_521));
|
|
}
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 7) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
ForceZero(ctx->tmp, sizeof(ctx->tmp));
|
|
ForceZero(ctx->t, sizeof(ctx->t));
|
|
}
|
|
|
|
(void)heap;
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#else
|
|
/* A table entry for pre-computed points. */
|
|
typedef struct sp_table_entry_521 {
|
|
sp_digit x[21];
|
|
sp_digit y[21];
|
|
} sp_table_entry_521;
|
|
|
|
/* Conditionally copy a into r using the mask m.
|
|
* m is -1 to copy and 0 when not.
|
|
*
|
|
* r A single precision number to copy over.
|
|
* a A single precision number to copy.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_521_cond_copy_21(sp_digit* r, const sp_digit* a, const sp_digit m)
|
|
{
|
|
sp_digit t[21];
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
t[i] = r[i] ^ a[i];
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r[i] ^= t[i] & m;
|
|
}
|
|
#else
|
|
t[ 0] = r[ 0] ^ a[ 0];
|
|
t[ 1] = r[ 1] ^ a[ 1];
|
|
t[ 2] = r[ 2] ^ a[ 2];
|
|
t[ 3] = r[ 3] ^ a[ 3];
|
|
t[ 4] = r[ 4] ^ a[ 4];
|
|
t[ 5] = r[ 5] ^ a[ 5];
|
|
t[ 6] = r[ 6] ^ a[ 6];
|
|
t[ 7] = r[ 7] ^ a[ 7];
|
|
t[ 8] = r[ 8] ^ a[ 8];
|
|
t[ 9] = r[ 9] ^ a[ 9];
|
|
t[10] = r[10] ^ a[10];
|
|
t[11] = r[11] ^ a[11];
|
|
t[12] = r[12] ^ a[12];
|
|
t[13] = r[13] ^ a[13];
|
|
t[14] = r[14] ^ a[14];
|
|
t[15] = r[15] ^ a[15];
|
|
t[16] = r[16] ^ a[16];
|
|
t[17] = r[17] ^ a[17];
|
|
t[18] = r[18] ^ a[18];
|
|
t[19] = r[19] ^ a[19];
|
|
t[20] = r[20] ^ a[20];
|
|
r[ 0] ^= t[ 0] & m;
|
|
r[ 1] ^= t[ 1] & m;
|
|
r[ 2] ^= t[ 2] & m;
|
|
r[ 3] ^= t[ 3] & m;
|
|
r[ 4] ^= t[ 4] & m;
|
|
r[ 5] ^= t[ 5] & m;
|
|
r[ 6] ^= t[ 6] & m;
|
|
r[ 7] ^= t[ 7] & m;
|
|
r[ 8] ^= t[ 8] & m;
|
|
r[ 9] ^= t[ 9] & m;
|
|
r[10] ^= t[10] & m;
|
|
r[11] ^= t[11] & m;
|
|
r[12] ^= t[12] & m;
|
|
r[13] ^= t[13] & m;
|
|
r[14] ^= t[14] & m;
|
|
r[15] ^= t[15] & m;
|
|
r[16] ^= t[16] & m;
|
|
r[17] ^= t[17] & m;
|
|
r[18] ^= t[18] & m;
|
|
r[19] ^= t[19] & m;
|
|
r[20] ^= t[20] & m;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#define sp_521_mont_dbl_lower_21 sp_521_mont_dbl_21
|
|
#define sp_521_mont_tpl_lower_21 sp_521_mont_tpl_21
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_proj_point_dbl_n_21(sp_point_521* p, int i,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*21;
|
|
sp_digit* b = t + 4*21;
|
|
sp_digit* t1 = t + 6*21;
|
|
sp_digit* t2 = t + 8*21;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
volatile int n = i;
|
|
|
|
x = p->x;
|
|
y = p->y;
|
|
z = p->z;
|
|
|
|
/* Y = 2*Y */
|
|
sp_521_mont_dbl_21(y, y, p521_mod);
|
|
/* W = Z^4 */
|
|
sp_521_mont_sqr_21(w, z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sqr_21(w, w, p521_mod, p521_mp_mod);
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
while (--n > 0)
|
|
#else
|
|
while (--n >= 0)
|
|
#endif
|
|
{
|
|
/* A = 3*(X^2 - W) */
|
|
sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(t1, t1, w, p521_mod);
|
|
sp_521_mont_tpl_lower_21(a, t1, p521_mod);
|
|
/* B = X*Y^2 */
|
|
sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod);
|
|
sp_521_mont_dbl_21(t2, b, p521_mod);
|
|
sp_521_mont_sub_21(x, x, t2, p521_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_521_mont_sub_lower_21(t2, b, x, p521_mod);
|
|
sp_521_mont_dbl_lower_21(b, t2, p521_mod);
|
|
/* Z = Z*Y */
|
|
sp_521_mont_mul_21(z, z, y, p521_mod, p521_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
if (n != 0)
|
|
#endif
|
|
{
|
|
/* W = W*Y^4 */
|
|
sp_521_mont_mul_21(w, w, t1, p521_mod, p521_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(y, y, t1, p521_mod);
|
|
}
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* A = 3*(X^2 - W) */
|
|
sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(t1, t1, w, p521_mod);
|
|
sp_521_mont_tpl_lower_21(a, t1, p521_mod);
|
|
/* B = X*Y^2 */
|
|
sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod);
|
|
sp_521_mont_dbl_21(t2, b, p521_mod);
|
|
sp_521_mont_sub_21(x, x, t2, p521_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_521_mont_sub_lower_21(t2, b, x, p521_mod);
|
|
sp_521_mont_dbl_lower_21(b, t2, p521_mod);
|
|
/* Z = Z*Y */
|
|
sp_521_mont_mul_21(z, z, y, p521_mod, p521_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod);
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(y, y, t1, p521_mod);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Y = Y/2 */
|
|
sp_521_div2_21(y, y, p521_mod);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_proj_point_dbl_n_store_21(sp_point_521* r,
|
|
const sp_point_521* p, int n, int m, sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*21;
|
|
sp_digit* b = t + 4*21;
|
|
sp_digit* t1 = t + 6*21;
|
|
sp_digit* t2 = t + 8*21;
|
|
sp_digit* x = r[2*m].x;
|
|
sp_digit* y = r[(1<<n)*m].y;
|
|
sp_digit* z = r[2*m].z;
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0; i<21; i++) {
|
|
x[i] = p->x[i];
|
|
}
|
|
for (i=0; i<21; i++) {
|
|
y[i] = p->y[i];
|
|
}
|
|
for (i=0; i<21; i++) {
|
|
z[i] = p->z[i];
|
|
}
|
|
|
|
/* Y = 2*Y */
|
|
sp_521_mont_dbl_21(y, y, p521_mod);
|
|
/* W = Z^4 */
|
|
sp_521_mont_sqr_21(w, z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sqr_21(w, w, p521_mod, p521_mp_mod);
|
|
j = m;
|
|
for (i=1; i<=n; i++) {
|
|
j *= 2;
|
|
|
|
/* A = 3*(X^2 - W) */
|
|
sp_521_mont_sqr_21(t1, x, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(t1, t1, w, p521_mod);
|
|
sp_521_mont_tpl_lower_21(a, t1, p521_mod);
|
|
/* B = X*Y^2 */
|
|
sp_521_mont_sqr_21(t1, y, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(b, t1, x, p521_mod, p521_mp_mod);
|
|
x = r[j].x;
|
|
/* X = A^2 - 2B */
|
|
sp_521_mont_sqr_21(x, a, p521_mod, p521_mp_mod);
|
|
sp_521_mont_dbl_21(t2, b, p521_mod);
|
|
sp_521_mont_sub_21(x, x, t2, p521_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_521_mont_sub_lower_21(t2, b, x, p521_mod);
|
|
sp_521_mont_dbl_lower_21(b, t2, p521_mod);
|
|
/* Z = Z*Y */
|
|
sp_521_mont_mul_21(r[j].z, z, y, p521_mod, p521_mp_mod);
|
|
z = r[j].z;
|
|
/* t1 = Y^4 */
|
|
sp_521_mont_sqr_21(t1, t1, p521_mod, p521_mp_mod);
|
|
if (i != n) {
|
|
/* W = W*Y^4 */
|
|
sp_521_mont_mul_21(w, w, t1, p521_mod, p521_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_521_mont_mul_21(y, b, a, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(y, y, t1, p521_mod);
|
|
/* Y = Y/2 */
|
|
sp_521_div2_21(r[j].y, y, p521_mod);
|
|
r[j].infinity = 0;
|
|
}
|
|
}
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* ra Result of addition.
|
|
* rs Result of subtraction.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_proj_point_add_sub_21(sp_point_521* ra,
|
|
sp_point_521* rs, const sp_point_521* p, const sp_point_521* q,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*21;
|
|
sp_digit* t3 = t + 4*21;
|
|
sp_digit* t4 = t + 6*21;
|
|
sp_digit* t5 = t + 8*21;
|
|
sp_digit* t6 = t + 10*21;
|
|
sp_digit* xa = ra->x;
|
|
sp_digit* ya = ra->y;
|
|
sp_digit* za = ra->z;
|
|
sp_digit* xs = rs->x;
|
|
sp_digit* ys = rs->y;
|
|
sp_digit* zs = rs->z;
|
|
|
|
|
|
XMEMCPY(xa, p->x, sizeof(p->x) / 2);
|
|
XMEMCPY(ya, p->y, sizeof(p->y) / 2);
|
|
XMEMCPY(za, p->z, sizeof(p->z) / 2);
|
|
ra->infinity = 0;
|
|
rs->infinity = 0;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_521_mont_sqr_21(t1, q->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t3, t1, q->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t1, t1, xa, p521_mod, p521_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_521_mont_sqr_21(t2, za, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t4, t2, za, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_521_mont_mul_21(t3, t3, ya, p521_mod, p521_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod);
|
|
/* H = U2 - U1 */
|
|
sp_521_mont_sub_21(t2, t2, t1, p521_mod);
|
|
/* RS = S2 + S1 */
|
|
sp_521_mont_add_21(t6, t4, t3, p521_mod);
|
|
/* R = S2 - S1 */
|
|
sp_521_mont_sub_21(t4, t4, t3, p521_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
/* ZS = H*Z1*Z2 */
|
|
sp_521_mont_mul_21(za, za, q->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(za, za, t2, p521_mod, p521_mp_mod);
|
|
XMEMCPY(zs, za, sizeof(p->z)/2);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
/* XS = RS^2 - H^3 - 2*U1*H^2 */
|
|
sp_521_mont_sqr_21(xa, t4, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sqr_21(xs, t6, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(ya, t1, t5, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(xa, xa, t5, p521_mod);
|
|
sp_521_mont_sub_21(xs, xs, t5, p521_mod);
|
|
sp_521_mont_dbl_21(t1, ya, p521_mod);
|
|
sp_521_mont_sub_21(xa, xa, t1, p521_mod);
|
|
sp_521_mont_sub_21(xs, xs, t1, p521_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
/* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
|
|
sp_521_mont_sub_lower_21(ys, ya, xs, p521_mod);
|
|
sp_521_mont_sub_lower_21(ya, ya, xa, p521_mod);
|
|
sp_521_mont_mul_21(ya, ya, t4, p521_mod, p521_mp_mod);
|
|
sp_521_sub_21(t6, p521_mod, t6);
|
|
sp_521_mont_mul_21(ys, ys, t6, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t5, t5, t3, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(ya, ya, t5, p521_mod);
|
|
sp_521_mont_sub_21(ys, ys, t5, p521_mod);
|
|
}
|
|
|
|
/* Structure used to describe recoding of scalar multiplication. */
|
|
typedef struct ecc_recode_521 {
|
|
/* Index into pre-computation table. */
|
|
uint8_t i;
|
|
/* Use the negative of the point. */
|
|
uint8_t neg;
|
|
} ecc_recode_521;
|
|
|
|
/* The index into pre-computation table to use. */
|
|
static const uint8_t recode_index_21_6[66] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
|
|
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
|
0, 1,
|
|
};
|
|
|
|
/* Whether to negate y-ordinate. */
|
|
static const uint8_t recode_neg_21_6[66] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 0,
|
|
};
|
|
|
|
/* Recode the scalar for multiplication using pre-computed values and
|
|
* subtraction.
|
|
*
|
|
* k Scalar to multiply by.
|
|
* v Vector of operations to perform.
|
|
*/
|
|
static void sp_521_ecc_recode_6_21(const sp_digit* k, ecc_recode_521* v)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint8_t y;
|
|
int carry = 0;
|
|
int o;
|
|
sp_digit n;
|
|
|
|
j = 0;
|
|
n = k[j];
|
|
o = 0;
|
|
for (i=0; i<87; i++) {
|
|
y = (int8_t)n;
|
|
if (o + 6 < 25) {
|
|
y &= 0x3f;
|
|
n >>= 6;
|
|
o += 6;
|
|
}
|
|
else if (o + 6 == 25) {
|
|
n >>= 6;
|
|
if (++j < 21)
|
|
n = k[j];
|
|
o = 0;
|
|
}
|
|
else if (++j < 21) {
|
|
n = k[j];
|
|
y |= (uint8_t)((n << (25 - o)) & 0x3f);
|
|
o -= 19;
|
|
n >>= o;
|
|
}
|
|
|
|
y += (uint8_t)carry;
|
|
v[i].i = recode_index_21_6[y];
|
|
v[i].neg = recode_neg_21_6[y];
|
|
carry = (y >> 6) + v[i].neg;
|
|
}
|
|
}
|
|
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
/* Touch each possible point that could be being copied.
|
|
*
|
|
* r Point to copy into.
|
|
* table Table - start of the entires to access
|
|
* idx Index of entry to retrieve.
|
|
*/
|
|
static void sp_521_get_point_33_21(sp_point_521* r, const sp_point_521* table,
|
|
int idx)
|
|
{
|
|
int i;
|
|
sp_digit mask;
|
|
|
|
r->x[0] = 0;
|
|
r->x[1] = 0;
|
|
r->x[2] = 0;
|
|
r->x[3] = 0;
|
|
r->x[4] = 0;
|
|
r->x[5] = 0;
|
|
r->x[6] = 0;
|
|
r->x[7] = 0;
|
|
r->x[8] = 0;
|
|
r->x[9] = 0;
|
|
r->x[10] = 0;
|
|
r->x[11] = 0;
|
|
r->x[12] = 0;
|
|
r->x[13] = 0;
|
|
r->x[14] = 0;
|
|
r->x[15] = 0;
|
|
r->x[16] = 0;
|
|
r->x[17] = 0;
|
|
r->x[18] = 0;
|
|
r->x[19] = 0;
|
|
r->x[20] = 0;
|
|
r->y[0] = 0;
|
|
r->y[1] = 0;
|
|
r->y[2] = 0;
|
|
r->y[3] = 0;
|
|
r->y[4] = 0;
|
|
r->y[5] = 0;
|
|
r->y[6] = 0;
|
|
r->y[7] = 0;
|
|
r->y[8] = 0;
|
|
r->y[9] = 0;
|
|
r->y[10] = 0;
|
|
r->y[11] = 0;
|
|
r->y[12] = 0;
|
|
r->y[13] = 0;
|
|
r->y[14] = 0;
|
|
r->y[15] = 0;
|
|
r->y[16] = 0;
|
|
r->y[17] = 0;
|
|
r->y[18] = 0;
|
|
r->y[19] = 0;
|
|
r->y[20] = 0;
|
|
r->z[0] = 0;
|
|
r->z[1] = 0;
|
|
r->z[2] = 0;
|
|
r->z[3] = 0;
|
|
r->z[4] = 0;
|
|
r->z[5] = 0;
|
|
r->z[6] = 0;
|
|
r->z[7] = 0;
|
|
r->z[8] = 0;
|
|
r->z[9] = 0;
|
|
r->z[10] = 0;
|
|
r->z[11] = 0;
|
|
r->z[12] = 0;
|
|
r->z[13] = 0;
|
|
r->z[14] = 0;
|
|
r->z[15] = 0;
|
|
r->z[16] = 0;
|
|
r->z[17] = 0;
|
|
r->z[18] = 0;
|
|
r->z[19] = 0;
|
|
r->z[20] = 0;
|
|
for (i = 1; i < 33; i++) {
|
|
mask = 0 - (i == idx);
|
|
r->x[0] |= mask & table[i].x[0];
|
|
r->x[1] |= mask & table[i].x[1];
|
|
r->x[2] |= mask & table[i].x[2];
|
|
r->x[3] |= mask & table[i].x[3];
|
|
r->x[4] |= mask & table[i].x[4];
|
|
r->x[5] |= mask & table[i].x[5];
|
|
r->x[6] |= mask & table[i].x[6];
|
|
r->x[7] |= mask & table[i].x[7];
|
|
r->x[8] |= mask & table[i].x[8];
|
|
r->x[9] |= mask & table[i].x[9];
|
|
r->x[10] |= mask & table[i].x[10];
|
|
r->x[11] |= mask & table[i].x[11];
|
|
r->x[12] |= mask & table[i].x[12];
|
|
r->x[13] |= mask & table[i].x[13];
|
|
r->x[14] |= mask & table[i].x[14];
|
|
r->x[15] |= mask & table[i].x[15];
|
|
r->x[16] |= mask & table[i].x[16];
|
|
r->x[17] |= mask & table[i].x[17];
|
|
r->x[18] |= mask & table[i].x[18];
|
|
r->x[19] |= mask & table[i].x[19];
|
|
r->x[20] |= mask & table[i].x[20];
|
|
r->y[0] |= mask & table[i].y[0];
|
|
r->y[1] |= mask & table[i].y[1];
|
|
r->y[2] |= mask & table[i].y[2];
|
|
r->y[3] |= mask & table[i].y[3];
|
|
r->y[4] |= mask & table[i].y[4];
|
|
r->y[5] |= mask & table[i].y[5];
|
|
r->y[6] |= mask & table[i].y[6];
|
|
r->y[7] |= mask & table[i].y[7];
|
|
r->y[8] |= mask & table[i].y[8];
|
|
r->y[9] |= mask & table[i].y[9];
|
|
r->y[10] |= mask & table[i].y[10];
|
|
r->y[11] |= mask & table[i].y[11];
|
|
r->y[12] |= mask & table[i].y[12];
|
|
r->y[13] |= mask & table[i].y[13];
|
|
r->y[14] |= mask & table[i].y[14];
|
|
r->y[15] |= mask & table[i].y[15];
|
|
r->y[16] |= mask & table[i].y[16];
|
|
r->y[17] |= mask & table[i].y[17];
|
|
r->y[18] |= mask & table[i].y[18];
|
|
r->y[19] |= mask & table[i].y[19];
|
|
r->y[20] |= mask & table[i].y[20];
|
|
r->z[0] |= mask & table[i].z[0];
|
|
r->z[1] |= mask & table[i].z[1];
|
|
r->z[2] |= mask & table[i].z[2];
|
|
r->z[3] |= mask & table[i].z[3];
|
|
r->z[4] |= mask & table[i].z[4];
|
|
r->z[5] |= mask & table[i].z[5];
|
|
r->z[6] |= mask & table[i].z[6];
|
|
r->z[7] |= mask & table[i].z[7];
|
|
r->z[8] |= mask & table[i].z[8];
|
|
r->z[9] |= mask & table[i].z[9];
|
|
r->z[10] |= mask & table[i].z[10];
|
|
r->z[11] |= mask & table[i].z[11];
|
|
r->z[12] |= mask & table[i].z[12];
|
|
r->z[13] |= mask & table[i].z[13];
|
|
r->z[14] |= mask & table[i].z[14];
|
|
r->z[15] |= mask & table[i].z[15];
|
|
r->z[16] |= mask & table[i].z[16];
|
|
r->z[17] |= mask & table[i].z[17];
|
|
r->z[18] |= mask & table[i].z[18];
|
|
r->z[19] |= mask & table[i].z[19];
|
|
r->z[20] |= mask & table[i].z[20];
|
|
}
|
|
}
|
|
#endif /* !WC_NO_CACHE_RESISTANT */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Window technique of 6 bits. (Add-Sub variation.)
|
|
* Calculate 0..32 times the point. Use function that adds and
|
|
* subtracts the same two points.
|
|
* Recode to add or subtract one of the computed points.
|
|
* Double to push up.
|
|
* NOT a sliding window.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_mulmod_win_add_sub_21(sp_point_521* r, const sp_point_521* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_521 t[33+2];
|
|
sp_digit tmp[2 * 21 * 6];
|
|
#endif
|
|
sp_point_521* rt = NULL;
|
|
sp_point_521* p = NULL;
|
|
sp_digit* negy;
|
|
int i;
|
|
ecc_recode_521 v[87];
|
|
int err = MP_OKAY;
|
|
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) *
|
|
(33+2), heap, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6,
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
rt = t + 33;
|
|
p = t + 33+1;
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
XMEMSET(&t[0], 0, sizeof(t[0]));
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_521_mod_mul_norm_21(t[1].x, g->x, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_mod_mul_norm_21(t[1].y, g->y, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_mod_mul_norm_21(t[1].z, g->z, p521_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
t[1].infinity = 0;
|
|
/* t[2] ... t[32] */
|
|
sp_521_proj_point_dbl_n_store_21(t, &t[ 1], 5, 1, tmp);
|
|
sp_521_proj_point_add_21(&t[ 3], &t[ 2], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[ 6], &t[ 3], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[10], &t[ 5], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[12], &t[ 6], tmp);
|
|
sp_521_proj_point_dbl_21(&t[14], &t[ 7], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[15], &t[13], &t[14], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[18], &t[ 9], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[19], &t[17], &t[18], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[20], &t[10], tmp);
|
|
sp_521_proj_point_dbl_21(&t[22], &t[11], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[23], &t[21], &t[22], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[24], &t[12], tmp);
|
|
sp_521_proj_point_dbl_21(&t[26], &t[13], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[27], &t[25], &t[26], &t[ 1], tmp);
|
|
sp_521_proj_point_dbl_21(&t[28], &t[14], tmp);
|
|
sp_521_proj_point_dbl_21(&t[30], &t[15], tmp);
|
|
sp_521_proj_point_add_sub_21(&t[31], &t[29], &t[30], &t[ 1], tmp);
|
|
|
|
negy = t[0].y;
|
|
|
|
sp_521_ecc_recode_6_21(k, v);
|
|
|
|
i = 86;
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_521_get_point_33_21(rt, t, v[i].i);
|
|
rt->infinity = !v[i].i;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_521));
|
|
}
|
|
for (--i; i>=0; i--) {
|
|
sp_521_proj_point_dbl_n_21(rt, 6, tmp);
|
|
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_521_get_point_33_21(p, t, v[i].i);
|
|
p->infinity = !v[i].i;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(p, &t[v[i].i], sizeof(sp_point_521));
|
|
}
|
|
sp_521_sub_21(negy, p521_mod, p->y);
|
|
sp_521_norm_21(negy);
|
|
sp_521_cond_copy_21(p->y, negy, (sp_digit)0 - v[i].neg);
|
|
sp_521_proj_point_add_21(rt, rt, p, tmp);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_521_map_21(r, rt, tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_521));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp != NULL)
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#endif /* FP_ECC */
|
|
/* Add two Montgomery form projective points. The second point has a q value of
|
|
* one.
|
|
* Only the first point can be the same pointer as the result point.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_521_proj_point_add_qz1_21(sp_point_521* r,
|
|
const sp_point_521* p, const sp_point_521* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*21;
|
|
sp_digit* t3 = t + 4*21;
|
|
sp_digit* t4 = t + 6*21;
|
|
sp_digit* t5 = t + 8*21;
|
|
sp_digit* t6 = t + 10*21;
|
|
|
|
/* Calculate values to subtract from P->x and P->y. */
|
|
/* U2 = X2*Z1^2 */
|
|
sp_521_mont_sqr_21(t2, p->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t4, t2, p->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t2, t2, q->x, p521_mod, p521_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_521_mont_mul_21(t4, t4, q->y, p521_mod, p521_mp_mod);
|
|
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_521_cmp_equal_21(p->x, t2) &
|
|
sp_521_cmp_equal_21(p->y, t4)) {
|
|
sp_521_proj_point_dbl_21(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t2;
|
|
sp_digit* y = t5;
|
|
sp_digit* z = t6;
|
|
int i;
|
|
|
|
/* H = U2 - X1 */
|
|
sp_521_mont_sub_21(t2, t2, p->x, p521_mod);
|
|
/* R = S2 - Y1 */
|
|
sp_521_mont_sub_21(t4, t4, p->y, p521_mod);
|
|
/* Z3 = H*Z1 */
|
|
sp_521_mont_mul_21(z, p->z, t2, p521_mod, p521_mp_mod);
|
|
/* X3 = R^2 - H^3 - 2*X1*H^2 */
|
|
sp_521_mont_sqr_21(t1, t4, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sqr_21(t5, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t3, p->x, t5, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t5, t5, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(x, t1, t5, p521_mod);
|
|
sp_521_mont_dbl_21(t1, t3, p521_mod);
|
|
sp_521_mont_sub_21(x, x, t1, p521_mod);
|
|
/* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
|
|
sp_521_mont_sub_lower_21(t3, t3, x, p521_mod);
|
|
sp_521_mont_mul_21(t3, t3, t4, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t5, t5, p->y, p521_mod, p521_mp_mod);
|
|
sp_521_mont_sub_21(y, t3, t5, p521_mod);
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
for (i = 0; i < 21; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 21; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
/* Convert the projective point to affine.
|
|
* Ordinates are in Montgomery form.
|
|
*
|
|
* a Point to convert.
|
|
* t Temporary data.
|
|
*/
|
|
static void sp_521_proj_to_affine_21(sp_point_521* a, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 21;
|
|
sp_digit* tmp = t + 4 * 21;
|
|
|
|
sp_521_mont_inv_21(t1, a->z, tmp);
|
|
|
|
sp_521_mont_sqr_21(t2, t1, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(t1, t2, t1, p521_mod, p521_mp_mod);
|
|
|
|
sp_521_mont_mul_21(a->x, a->x, t2, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(a->y, a->y, t1, p521_mod, p521_mp_mod);
|
|
XMEMCPY(a->z, p521_norm_mod, sizeof(p521_norm_mod));
|
|
}
|
|
|
|
/* Generate the pre-computed table of points for the base point.
|
|
*
|
|
* width = 8
|
|
* 256 entries
|
|
* 65 bits between
|
|
*
|
|
* a The base point.
|
|
* table Place to store generated point data.
|
|
* tmp Temporary data.
|
|
* heap Heap to use for allocation.
|
|
*/
|
|
static int sp_521_gen_stripe_table_21(const sp_point_521* a,
|
|
sp_table_entry_521* table, sp_digit* tmp, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* t = NULL;
|
|
#else
|
|
sp_point_521 t[3];
|
|
#endif
|
|
sp_point_521* s1 = NULL;
|
|
sp_point_521* s2 = NULL;
|
|
int i;
|
|
int j;
|
|
int err = MP_OKAY;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
s1 = t + 1;
|
|
s2 = t + 2;
|
|
|
|
err = sp_521_mod_mul_norm_21(t->x, a->x, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_mod_mul_norm_21(t->y, a->y, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_mod_mul_norm_21(t->z, a->z, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
t->infinity = 0;
|
|
sp_521_proj_to_affine_21(t, tmp);
|
|
|
|
XMEMCPY(s1->z, p521_norm_mod, sizeof(p521_norm_mod));
|
|
s1->infinity = 0;
|
|
XMEMCPY(s2->z, p521_norm_mod, sizeof(p521_norm_mod));
|
|
s2->infinity = 0;
|
|
|
|
/* table[0] = {0, 0, infinity} */
|
|
XMEMSET(&table[0], 0, sizeof(sp_table_entry_521));
|
|
/* table[1] = Affine version of 'a' in Montgomery form */
|
|
XMEMCPY(table[1].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1].y, t->y, sizeof(table->y));
|
|
|
|
for (i=1; i<8; i++) {
|
|
sp_521_proj_point_dbl_n_21(t, 66, tmp);
|
|
sp_521_proj_to_affine_21(t, tmp);
|
|
XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
|
|
}
|
|
|
|
for (i=1; i<8; i++) {
|
|
XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
|
|
XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
|
|
for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
|
|
XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
|
|
XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
|
|
sp_521_proj_point_add_qz1_21(t, s1, s2, tmp);
|
|
sp_521_proj_to_affine_21(t, tmp);
|
|
XMEMCPY(table[j].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[j].y, t->y, sizeof(table->y));
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* FP_ECC */
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
/* Touch each possible entry that could be being copied.
|
|
*
|
|
* r Point to copy into.
|
|
* table Table - start of the entires to access
|
|
* idx Index of entry to retrieve.
|
|
*/
|
|
static void sp_521_get_entry_256_21(sp_point_521* r,
|
|
const sp_table_entry_521* table, int idx)
|
|
{
|
|
int i;
|
|
sp_digit mask;
|
|
|
|
r->x[0] = 0;
|
|
r->x[1] = 0;
|
|
r->x[2] = 0;
|
|
r->x[3] = 0;
|
|
r->x[4] = 0;
|
|
r->x[5] = 0;
|
|
r->x[6] = 0;
|
|
r->x[7] = 0;
|
|
r->x[8] = 0;
|
|
r->x[9] = 0;
|
|
r->x[10] = 0;
|
|
r->x[11] = 0;
|
|
r->x[12] = 0;
|
|
r->x[13] = 0;
|
|
r->x[14] = 0;
|
|
r->x[15] = 0;
|
|
r->x[16] = 0;
|
|
r->x[17] = 0;
|
|
r->x[18] = 0;
|
|
r->x[19] = 0;
|
|
r->x[20] = 0;
|
|
r->y[0] = 0;
|
|
r->y[1] = 0;
|
|
r->y[2] = 0;
|
|
r->y[3] = 0;
|
|
r->y[4] = 0;
|
|
r->y[5] = 0;
|
|
r->y[6] = 0;
|
|
r->y[7] = 0;
|
|
r->y[8] = 0;
|
|
r->y[9] = 0;
|
|
r->y[10] = 0;
|
|
r->y[11] = 0;
|
|
r->y[12] = 0;
|
|
r->y[13] = 0;
|
|
r->y[14] = 0;
|
|
r->y[15] = 0;
|
|
r->y[16] = 0;
|
|
r->y[17] = 0;
|
|
r->y[18] = 0;
|
|
r->y[19] = 0;
|
|
r->y[20] = 0;
|
|
for (i = 1; i < 256; i++) {
|
|
mask = 0 - (i == idx);
|
|
r->x[0] |= mask & table[i].x[0];
|
|
r->x[1] |= mask & table[i].x[1];
|
|
r->x[2] |= mask & table[i].x[2];
|
|
r->x[3] |= mask & table[i].x[3];
|
|
r->x[4] |= mask & table[i].x[4];
|
|
r->x[5] |= mask & table[i].x[5];
|
|
r->x[6] |= mask & table[i].x[6];
|
|
r->x[7] |= mask & table[i].x[7];
|
|
r->x[8] |= mask & table[i].x[8];
|
|
r->x[9] |= mask & table[i].x[9];
|
|
r->x[10] |= mask & table[i].x[10];
|
|
r->x[11] |= mask & table[i].x[11];
|
|
r->x[12] |= mask & table[i].x[12];
|
|
r->x[13] |= mask & table[i].x[13];
|
|
r->x[14] |= mask & table[i].x[14];
|
|
r->x[15] |= mask & table[i].x[15];
|
|
r->x[16] |= mask & table[i].x[16];
|
|
r->x[17] |= mask & table[i].x[17];
|
|
r->x[18] |= mask & table[i].x[18];
|
|
r->x[19] |= mask & table[i].x[19];
|
|
r->x[20] |= mask & table[i].x[20];
|
|
r->y[0] |= mask & table[i].y[0];
|
|
r->y[1] |= mask & table[i].y[1];
|
|
r->y[2] |= mask & table[i].y[2];
|
|
r->y[3] |= mask & table[i].y[3];
|
|
r->y[4] |= mask & table[i].y[4];
|
|
r->y[5] |= mask & table[i].y[5];
|
|
r->y[6] |= mask & table[i].y[6];
|
|
r->y[7] |= mask & table[i].y[7];
|
|
r->y[8] |= mask & table[i].y[8];
|
|
r->y[9] |= mask & table[i].y[9];
|
|
r->y[10] |= mask & table[i].y[10];
|
|
r->y[11] |= mask & table[i].y[11];
|
|
r->y[12] |= mask & table[i].y[12];
|
|
r->y[13] |= mask & table[i].y[13];
|
|
r->y[14] |= mask & table[i].y[14];
|
|
r->y[15] |= mask & table[i].y[15];
|
|
r->y[16] |= mask & table[i].y[16];
|
|
r->y[17] |= mask & table[i].y[17];
|
|
r->y[18] |= mask & table[i].y[18];
|
|
r->y[19] |= mask & table[i].y[19];
|
|
r->y[20] |= mask & table[i].y[20];
|
|
}
|
|
}
|
|
#endif /* !WC_NO_CACHE_RESISTANT */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^65, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* table Pre-computed table.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_mulmod_stripe_21(sp_point_521* r, const sp_point_521* g,
|
|
const sp_table_entry_521* table, const sp_digit* k, int map,
|
|
int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* rt = NULL;
|
|
sp_digit* t = NULL;
|
|
#else
|
|
sp_point_521 rt[2];
|
|
sp_digit t[2 * 21 * 6];
|
|
#endif
|
|
sp_point_521* p = NULL;
|
|
int i;
|
|
int j;
|
|
int y;
|
|
int x;
|
|
int err = MP_OKAY;
|
|
|
|
(void)g;
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
rt = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (rt == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = rt + 1;
|
|
|
|
XMEMCPY(p->z, p521_norm_mod, sizeof(p521_norm_mod));
|
|
XMEMCPY(rt->z, p521_norm_mod, sizeof(p521_norm_mod));
|
|
|
|
y = 0;
|
|
x = 65;
|
|
for (j=0; j<8 && x<521; j++) {
|
|
y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
|
|
x += 66;
|
|
}
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_521_get_entry_256_21(rt, table, y);
|
|
} else
|
|
#endif
|
|
{
|
|
XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
|
|
}
|
|
rt->infinity = !y;
|
|
for (i=64; i>=0; i--) {
|
|
y = 0;
|
|
x = i;
|
|
for (j=0; j<8 && x<521; j++) {
|
|
y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
|
|
x += 66;
|
|
}
|
|
|
|
sp_521_proj_point_dbl_21(rt, rt, t);
|
|
#ifndef WC_NO_CACHE_RESISTANT
|
|
if (ct) {
|
|
sp_521_get_entry_256_21(p, table, y);
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
|
|
}
|
|
p->infinity = !y;
|
|
sp_521_proj_point_add_qz1_21(rt, rt, p, t);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_521_map_21(r, rt, t);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_521));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (rt != NULL)
|
|
XFREE(rt, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#ifndef FP_ENTRIES
|
|
#define FP_ENTRIES 16
|
|
#endif
|
|
|
|
/* Cache entry - holds precomputation tables for a point. */
|
|
typedef struct sp_cache_521_t {
|
|
/* X ordinate of point that table was generated from. */
|
|
sp_digit x[21];
|
|
/* Y ordinate of point that table was generated from. */
|
|
sp_digit y[21];
|
|
/* Precomputation table for point. */
|
|
sp_table_entry_521 table[256];
|
|
/* Count of entries in table. */
|
|
uint32_t cnt;
|
|
/* Point and table set in entry. */
|
|
int set;
|
|
} sp_cache_521_t;
|
|
|
|
/* Cache of tables. */
|
|
static THREAD_LS_T sp_cache_521_t sp_cache_521[FP_ENTRIES];
|
|
/* Index of last entry in cache. */
|
|
static THREAD_LS_T int sp_cache_521_last = -1;
|
|
/* Cache has been initialized. */
|
|
static THREAD_LS_T int sp_cache_521_inited = 0;
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
static volatile int initCacheMutex_521 = 0;
|
|
static wolfSSL_Mutex sp_cache_521_lock;
|
|
#endif
|
|
|
|
/* Get the cache entry for the point.
|
|
*
|
|
* g [in] Point scalar multipling.
|
|
* cache [out] Cache table to use.
|
|
*/
|
|
static void sp_ecc_get_cache_521(const sp_point_521* g, sp_cache_521_t** cache)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint32_t least;
|
|
|
|
if (sp_cache_521_inited == 0) {
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
sp_cache_521[i].set = 0;
|
|
}
|
|
sp_cache_521_inited = 1;
|
|
}
|
|
|
|
/* Compare point with those in cache. */
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
if (!sp_cache_521[i].set)
|
|
continue;
|
|
|
|
if (sp_521_cmp_equal_21(g->x, sp_cache_521[i].x) &
|
|
sp_521_cmp_equal_21(g->y, sp_cache_521[i].y)) {
|
|
sp_cache_521[i].cnt++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* No match. */
|
|
if (i == FP_ENTRIES) {
|
|
/* Find empty entry. */
|
|
i = (sp_cache_521_last + 1) % FP_ENTRIES;
|
|
for (; i != sp_cache_521_last; i=(i+1)%FP_ENTRIES) {
|
|
if (!sp_cache_521[i].set) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Evict least used. */
|
|
if (i == sp_cache_521_last) {
|
|
least = sp_cache_521[0].cnt;
|
|
for (j=1; j<FP_ENTRIES; j++) {
|
|
if (sp_cache_521[j].cnt < least) {
|
|
i = j;
|
|
least = sp_cache_521[i].cnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
XMEMCPY(sp_cache_521[i].x, g->x, sizeof(sp_cache_521[i].x));
|
|
XMEMCPY(sp_cache_521[i].y, g->y, sizeof(sp_cache_521[i].y));
|
|
sp_cache_521[i].set = 1;
|
|
sp_cache_521[i].cnt = 1;
|
|
}
|
|
|
|
*cache = &sp_cache_521[i];
|
|
sp_cache_521_last = i;
|
|
}
|
|
#endif /* FP_ECC */
|
|
|
|
/* Multiply the base point of P521 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_mulmod_21(sp_point_521* r, const sp_point_521* g, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
#ifndef FP_ECC
|
|
return sp_521_ecc_mulmod_win_add_sub_21(r, g, k, map, ct, heap);
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp;
|
|
#else
|
|
sp_digit tmp[2 * 21 * 6];
|
|
#endif
|
|
sp_cache_521_t* cache;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
#ifndef HAVE_THREAD_LS
|
|
if (err == MP_OKAY) {
|
|
if (initCacheMutex_521 == 0) {
|
|
wc_InitMutex(&sp_cache_521_lock);
|
|
initCacheMutex_521 = 1;
|
|
}
|
|
if (wc_LockMutex(&sp_cache_521_lock) != 0) {
|
|
err = BAD_MUTEX_E;
|
|
}
|
|
}
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_ecc_get_cache_521(g, &cache);
|
|
if (cache->cnt == 2)
|
|
sp_521_gen_stripe_table_21(g, cache->table, tmp, heap);
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
wc_UnLockMutex(&sp_cache_521_lock);
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (cache->cnt < 2) {
|
|
err = sp_521_ecc_mulmod_win_add_sub_21(r, g, k, map, ct, heap);
|
|
}
|
|
else {
|
|
err = sp_521_ecc_mulmod_stripe_21(r, g, cache->table, k,
|
|
map, ct, heap);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_521(const mp_int* km, const ecc_point* gm, ecc_point* r,
|
|
int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_521 point[1];
|
|
sp_digit k[21];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_521_from_mp(k, 21, km);
|
|
sp_521_point_from_ecc_point_21(point, gm);
|
|
|
|
err = sp_521_ecc_mulmod_21(point, point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_point_to_ecc_point_21(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the point by the scalar, add point a and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_add_521(const mp_int* km, const ecc_point* gm,
|
|
const ecc_point* am, int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_521 point[2];
|
|
sp_digit k[21 + 21 * 2 * 6];
|
|
#endif
|
|
sp_point_521* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (21 + 21 * 2 * 6), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 21;
|
|
|
|
sp_521_from_mp(k, 21, km);
|
|
sp_521_point_from_ecc_point_21(point, gm);
|
|
sp_521_point_from_ecc_point_21(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_521_mod_mul_norm_21(addP->x, addP->x, p521_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_521_mod_mul_norm_21(addP->y, addP->y, p521_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_521_mod_mul_norm_21(addP->z, addP->z, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_ecc_mulmod_21(point, point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_521_proj_point_add_21(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_521_map_21(point, point, tmp);
|
|
}
|
|
|
|
err = sp_521_point_to_ecc_point_21(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the base point of P521 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_521_ecc_mulmod_21(r, &p521_base, k, map, ct, heap);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
static int sp_521_ecc_mulmod_base_21_nb(sp_ecc_ctx_t* sp_ctx, sp_point_521* r,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_521_ecc_mulmod_21_nb(sp_ctx, r, &p521_base, k, map, ct, heap);
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
|
|
#else
|
|
/* Striping precomputation table.
|
|
* 8 points combined into a table of 256 points.
|
|
* Distance of 66 between points.
|
|
*/
|
|
static const sp_table_entry_521 p521_table[256] = {
|
|
/* 0 */
|
|
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
|
|
/* 1 */
|
|
{ { 0x0e5bd66,0x13f18e1,0x0a6fe5f,0x030ad48,0x1348b3c,0x1fd46f1,
|
|
0x1049e8b,0x051fc3b,0x1efe759,0x0a5af3b,0x14f6ea8,0x1ec0d69,
|
|
0x01f828a,0x029fda9,0x19204e4,0x1688538,0x1662395,0x0cf1f65,
|
|
0x1013a73,0x1c0d6e0,0x00c6858 },
|
|
{ 0x1d16650,0x14a3b4f,0x090222f,0x0d44e58,0x153c708,0x1683b09,
|
|
0x0e404fe,0x0818aa1,0x15ef426,0x1f7394c,0x1998b25,0x1a2e4e7,
|
|
0x0817afb,0x0bcda23,0x1d51125,0x037b331,0x1b42c7d,0x02e452f,
|
|
0x08ef001,0x12d4f13,0x0118392 } },
|
|
/* 2 */
|
|
{ { 0x10ccb51,0x0c33387,0x1d2a00e,0x026ca92,0x187e1d0,0x194f6cd,
|
|
0x13c86ca,0x06efeb1,0x0a3add3,0x16074d5,0x023fec1,0x0ba1d3a,
|
|
0x07f13b3,0x0b3b0b1,0x02fd132,0x07de9bb,0x014758a,0x1d250c6,
|
|
0x0010eb6,0x0aedbb4,0x013e96a },
|
|
{ 0x12d95a3,0x1127c31,0x00a4af7,0x0298a49,0x19f15ef,0x0d5d0cb,
|
|
0x018fa6f,0x00f55bb,0x0a962b7,0x0f029fa,0x1636637,0x05bc284,
|
|
0x1cc598a,0x030e11a,0x0968674,0x1a6593f,0x110e8ff,0x0076a32,
|
|
0x1de33ab,0x153ba3d,0x01852ae } },
|
|
/* 3 */
|
|
{ { 0x0af1fe3,0x08eec75,0x14af42a,0x0488016,0x0db3866,0x15f8690,
|
|
0x01aa486,0x081fed4,0x0a768c9,0x00943cd,0x1bb0de5,0x1579343,
|
|
0x1cf3791,0x139c1a1,0x04fef98,0x1578392,0x0abe222,0x1b945a1,
|
|
0x0e7bcc4,0x18150c5,0x0157874 },
|
|
{ 0x0f03d49,0x078c273,0x180c2b2,0x083c917,0x09c357e,0x0e5ef7d,
|
|
0x17bce05,0x078059c,0x15fd8dc,0x120e3d5,0x0c4275e,0x0f93f5d,
|
|
0x184bef6,0x1427a69,0x0633286,0x0155c5f,0x07d672f,0x1bf01ea,
|
|
0x15625a2,0x0356b03,0x000724b } },
|
|
/* 4 */
|
|
{ { 0x19314e0,0x196a5ef,0x0ab2413,0x1bcf401,0x1aae850,0x177d81e,
|
|
0x0420d60,0x1a4f246,0x1ec7fe6,0x078e141,0x15d2a20,0x132c333,
|
|
0x072d5b3,0x1ca803f,0x0482e6c,0x1e07cbe,0x1734773,0x118691b,
|
|
0x0de2da1,0x0324e67,0x0121f4c },
|
|
{ 0x08b51f0,0x1ffb6fd,0x17c3c40,0x0281c57,0x0e7afb5,0x12a0b8d,
|
|
0x0e03a0c,0x12a2260,0x0cda10d,0x01a80dc,0x0a3007a,0x0e3c9e7,
|
|
0x0910577,0x1640383,0x14865aa,0x070431e,0x0aaa562,0x09b04d8,
|
|
0x12829fc,0x0af20d2,0x01db8c2 } },
|
|
/* 5 */
|
|
{ { 0x0c0958d,0x1b86659,0x0e1cc00,0x0cd34f6,0x09aef16,0x064d9c4,
|
|
0x1cf3d20,0x0924f25,0x0fab3e1,0x194c279,0x12259c2,0x086ca0e,
|
|
0x0a9751e,0x1699ed9,0x0ae6756,0x09b5539,0x132b44a,0x0a6ca2e,
|
|
0x1b1dcc9,0x1994a42,0x000aa26 },
|
|
{ 0x1e66d18,0x10ea0fc,0x19eb36f,0x0d5422f,0x00aeef9,0x186925c,
|
|
0x0528b76,0x17e0a64,0x15c98b7,0x0e7d913,0x0f2121b,0x086dbfa,
|
|
0x0c613e7,0x1e526a9,0x1c0fe84,0x03cc8dc,0x1771855,0x0864714,
|
|
0x1ea149f,0x121d597,0x01c6f5e } },
|
|
/* 6 */
|
|
{ { 0x0b2d58f,0x178f3a5,0x000a8b0,0x185412f,0x01bbf82,0x05dbb56,
|
|
0x1ac91dc,0x17acb07,0x15667f7,0x1276cf6,0x1a25fa3,0x1b0dfb2,
|
|
0x15d8c01,0x1fdf078,0x0e5684c,0x1b962cc,0x19dd99c,0x0a8f279,
|
|
0x0837ac9,0x108494e,0x0082de0 },
|
|
{ 0x0ea91af,0x129d930,0x1f765ea,0x0ef463b,0x04384af,0x084ddf5,
|
|
0x1c8e573,0x1c39b05,0x0f30058,0x0be0ced,0x1e3a5e6,0x018dcb8,
|
|
0x05443b6,0x0bad8c2,0x0ba6d7d,0x19c2df5,0x13308c2,0x12e7437,
|
|
0x1d8fea1,0x19cb1e9,0x0073983 } },
|
|
/* 7 */
|
|
{ { 0x017609d,0x09898c1,0x1002bba,0x084825f,0x1f8a9dd,0x163194b,
|
|
0x19930a1,0x0bdc22f,0x07bf1c6,0x01bc16b,0x0fbb973,0x09b71a0,
|
|
0x19e8c14,0x0d5c9bc,0x0b2b2ca,0x1098e03,0x1b5b077,0x190af58,
|
|
0x0bff361,0x013f503,0x00f82c4 },
|
|
{ 0x18139a4,0x09bb31b,0x0a4c01f,0x176ab7d,0x06d969e,0x045e4ee,
|
|
0x035bda3,0x0858f8c,0x15f93f2,0x0274230,0x1c5f661,0x1454e82,
|
|
0x0e8461c,0x185f890,0x04c39e7,0x133af1d,0x0026b56,0x170aaa5,
|
|
0x093edb7,0x18ee04d,0x007de69 } },
|
|
/* 8 */
|
|
{ { 0x1ee80d7,0x08dd825,0x19a586d,0x1eed25b,0x0e1f6a1,0x15e1de8,
|
|
0x191b283,0x1e106f3,0x1930644,0x005ffd3,0x16c1dc7,0x170e721,
|
|
0x0997c67,0x1d6d0e7,0x170cf87,0x16a2412,0x0ddac54,0x11e2805,
|
|
0x0c46195,0x03a6c1a,0x00b0c23 },
|
|
{ 0x1bcab2f,0x0494c1c,0x082818a,0x00c9ba4,0x00c0678,0x1ee1506,
|
|
0x18211d8,0x1c60c5e,0x11938c3,0x074ed39,0x11bae62,0x1e5aa5c,
|
|
0x1d69be8,0x152ef07,0x17234b5,0x01c4dca,0x163db2c,0x1f9d1fe,
|
|
0x192ffd5,0x18db3e3,0x014a899 } },
|
|
/* 9 */
|
|
{ { 0x005ce88,0x171d0f6,0x080a7fd,0x0d6d5fa,0x18fc249,0x1f5803f,
|
|
0x081ddbe,0x080173a,0x1eebded,0x087605e,0x1c03ded,0x0e84d26,
|
|
0x0eaef97,0x1fbd818,0x1b8de84,0x03eef00,0x1171b90,0x1ae78be,
|
|
0x0a56b83,0x0dcbbf9,0x0159903 },
|
|
{ 0x00e8e0c,0x1b25a80,0x17e402b,0x080df69,0x13f2ae0,0x0f91dd6,
|
|
0x1699d12,0x152bec3,0x0255b25,0x0548c21,0x0f19403,0x07cd1c6,
|
|
0x01fa6af,0x016013e,0x0dcf003,0x0814a28,0x1a19728,0x04cf9e6,
|
|
0x03a1090,0x0c56f3a,0x00e798c } },
|
|
/* 10 */
|
|
{ { 0x04d0f28,0x1e25457,0x01bba31,0x1eacda0,0x1a8a55e,0x1720119,
|
|
0x17d9419,0x0ec6f30,0x15d321b,0x0f6655a,0x146c1e3,0x0dad706,
|
|
0x0b38b96,0x0beaa45,0x022794d,0x156165d,0x02fe631,0x1bd4f47,
|
|
0x1d714de,0x0c1f2bc,0x005945c },
|
|
{ 0x067d79c,0x13e9a3c,0x0602f28,0x0b03903,0x1f460b1,0x15c628b,
|
|
0x166ae5d,0x1b2fd85,0x061b91e,0x0682243,0x07457ff,0x144bb38,
|
|
0x19730a7,0x1ca64ed,0x0b3c967,0x0b47714,0x1875dec,0x1473c25,
|
|
0x1944c7b,0x0a4c0e7,0x0004062 } },
|
|
/* 11 */
|
|
{ { 0x1631bba,0x0272e78,0x14937b8,0x1e2ade8,0x00e6c1d,0x0184c82,
|
|
0x0fcc393,0x18e0cc0,0x16b6abe,0x1b24d21,0x053dbb6,0x0139ed7,
|
|
0x15354f5,0x1b5bf05,0x1b3d1a4,0x0dba4ff,0x07eba1e,0x153d388,
|
|
0x0251432,0x1db58ad,0x0022889 },
|
|
{ 0x05596f2,0x148b768,0x0e2e404,0x1960479,0x03901da,0x0a55f0f,
|
|
0x14fb39f,0x0264a03,0x0a9c903,0x140a820,0x051b42c,0x07e38da,
|
|
0x169dbcd,0x1a770c4,0x08756c5,0x04df6df,0x161a912,0x024d750,
|
|
0x02a0261,0x19ddbf7,0x0154754 } },
|
|
/* 12 */
|
|
{ { 0x070b2f0,0x113d821,0x135ed93,0x117e9ae,0x04b34e4,0x13915d4,
|
|
0x0fa2c30,0x039630d,0x19ff9b7,0x0a52c4e,0x15af13d,0x09be69f,
|
|
0x1d9887e,0x1a097a4,0x119a7f5,0x13a2d6f,0x1bb77f8,0x020046c,
|
|
0x040b81d,0x1284d79,0x01cfafb },
|
|
{ 0x02935ca,0x07968b3,0x111b329,0x0732fb9,0x0847c70,0x1e3cfc1,
|
|
0x1a794d4,0x1e98113,0x15215f0,0x16c6cc4,0x046e767,0x1179012,
|
|
0x0359cf0,0x16f13d5,0x00d5039,0x0641a96,0x03ef69e,0x1a97a6b,
|
|
0x13bc64e,0x02ffad2,0x00e6a02 } },
|
|
/* 13 */
|
|
{ { 0x0214780,0x0f313ba,0x07aaddf,0x0e40e8b,0x0a06681,0x03fd80e,
|
|
0x1e6dfa7,0x18fef0a,0x1d6d4b7,0x0aaa460,0x12a8e79,0x03214cd,
|
|
0x0f45756,0x0c282d2,0x0506c0e,0x0c9d7f0,0x17c4c88,0x1d2e506,
|
|
0x184a74f,0x15f2a13,0x0053bf8 },
|
|
{ 0x1285092,0x194ec42,0x197ef26,0x151ddab,0x02f31da,0x0c555cc,
|
|
0x1a43bd8,0x1a33866,0x0d2626e,0x1770a7a,0x1638243,0x0e160fd,
|
|
0x0042295,0x039b682,0x1de483a,0x1a03a32,0x1ffede7,0x1a3f712,
|
|
0x11eadce,0x0438757,0x01b93c9 } },
|
|
/* 14 */
|
|
{ { 0x08b2b14,0x103e650,0x11fc2da,0x177e2e9,0x0a978de,0x0659525,
|
|
0x0e0a310,0x0705239,0x090adc8,0x0e3c139,0x1b779a5,0x1655183,
|
|
0x0008da8,0x087de91,0x073acbe,0x1729ce8,0x1e5322d,0x12fc4e4,
|
|
0x1cf1523,0x0cc10b6,0x007d182 },
|
|
{ 0x1efd012,0x1fc1516,0x1fbda7a,0x08b42a6,0x01ecb09,0x18408e8,
|
|
0x1d4d4fb,0x1d478aa,0x1b2bd4d,0x0e44153,0x05a7216,0x12e4f7f,
|
|
0x1b00a1f,0x0592d68,0x0eb7d78,0x0c00a0c,0x106f253,0x0260ff9,
|
|
0x044bf86,0x02b7d88,0x01178e5 } },
|
|
/* 15 */
|
|
{ { 0x1e3d3d5,0x03c3ff7,0x089e4c5,0x0b3b12e,0x09e76f6,0x1b567a9,
|
|
0x1fb4782,0x1b22b8e,0x01c5e8d,0x015bd90,0x199ebe7,0x11e2bea,
|
|
0x1478803,0x19abb77,0x031d9bf,0x02a95e7,0x1c80040,0x1cf8311,
|
|
0x1a20ed4,0x078897b,0x009647d },
|
|
{ 0x01b21a4,0x1ab1c6f,0x0704c81,0x02ae210,0x1b6399c,0x001accd,
|
|
0x1819dd7,0x1ea645c,0x1ade60c,0x03fef3f,0x0641657,0x0881df8,
|
|
0x001b195,0x0ebd9cb,0x1c2b233,0x14e7cfc,0x03d6a6f,0x02552d4,
|
|
0x0c201d9,0x119f58c,0x004234f } },
|
|
/* 16 */
|
|
{ { 0x06492ad,0x0f38d14,0x0b13b8c,0x08cbf0d,0x08f3de4,0x189e5a0,
|
|
0x0035369,0x009d12e,0x1a86b71,0x1687af4,0x0b0585e,0x1c9e4ae,
|
|
0x19d9a62,0x12e60e4,0x1488fbc,0x05c18ef,0x1613b96,0x0f6ffb4,
|
|
0x0762c81,0x1a51e70,0x008e818 },
|
|
{ 0x0df1f60,0x118e7c6,0x183dc84,0x16ce2ee,0x0b640f2,0x02d201c,
|
|
0x1be3381,0x13f7ce4,0x0037068,0x11142ee,0x08372d0,0x1f1ee5d,
|
|
0x037196b,0x0404331,0x1bde157,0x1fc9142,0x1c7c326,0x06a70cf,
|
|
0x1da2fd1,0x190add1,0x013efdb } },
|
|
/* 17 */
|
|
{ { 0x0a3ace5,0x06827f3,0x070778d,0x1d12c32,0x0dbb603,0x0f687a0,
|
|
0x0001fdd,0x16b69b8,0x095b259,0x0f0735e,0x17c0805,0x14cc4c2,
|
|
0x18dfbcb,0x098f51f,0x1b150cf,0x1f04965,0x0e4103f,0x1215858,
|
|
0x1200ccb,0x02a0c18,0x0111193 },
|
|
{ 0x05452f1,0x1f51402,0x1cee665,0x1ee3e7e,0x00b678c,0x1499474,
|
|
0x0f77107,0x04694a5,0x0e6af1c,0x1f932b7,0x08579ed,0x0b73688,
|
|
0x0bc4380,0x1852014,0x09cd3cb,0x0edc475,0x0794224,0x1f1e392,
|
|
0x031833d,0x05d160d,0x01f16dc } },
|
|
/* 18 */
|
|
{ { 0x1fc0de5,0x1d737ff,0x1c92f37,0x1f5694b,0x0801814,0x15546ed,
|
|
0x0d963a8,0x0823202,0x1da4f04,0x1d8e57a,0x001847c,0x19b6682,
|
|
0x08f24b9,0x0b7067c,0x10c93b6,0x0b90491,0x1342305,0x0a5bf51,
|
|
0x0424b8a,0x06b6c91,0x01d36e8 },
|
|
{ 0x1372f27,0x1bd7383,0x0669fad,0x150775c,0x0779b4f,0x014f5da,
|
|
0x16b8595,0x07f42eb,0x0fc03ef,0x0176133,0x071f125,0x0d52d32,
|
|
0x1c0e5fc,0x0b129e9,0x1d8793d,0x1ce7141,0x158de74,0x0bd08ff,
|
|
0x0937a46,0x0499a8c,0x0002605 } },
|
|
/* 19 */
|
|
{ { 0x1342e08,0x0e86500,0x02bd16d,0x016e93e,0x109ed4f,0x14ec022,
|
|
0x00b6594,0x139d6aa,0x16d8035,0x15843ed,0x0120017,0x150e987,
|
|
0x04eaa66,0x03ad43c,0x1cb1e83,0x062fdd2,0x0216874,0x0460b4f,
|
|
0x1727efd,0x0aadc1c,0x014f81c },
|
|
{ 0x120674d,0x05895f0,0x02b09ac,0x12433e0,0x06bf09b,0x0c65536,
|
|
0x1ccb759,0x13c3c3c,0x18292d9,0x1b8e2d7,0x16fe031,0x0a524bf,
|
|
0x1d5d813,0x1b3361b,0x06f5e60,0x1ed01cc,0x06a1d0d,0x1c6d64a,
|
|
0x0e7c260,0x19ed098,0x009f58d } },
|
|
/* 20 */
|
|
{ { 0x17dc837,0x148813d,0x0710505,0x096a1d6,0x0d71975,0x133a0d9,
|
|
0x024ab5f,0x07009e8,0x1bc824a,0x0853f8e,0x082f3c7,0x00ad91c,
|
|
0x10570b2,0x0d0c0ed,0x0cb8ee7,0x0a114ce,0x16e0a7b,0x13c4031,
|
|
0x07dc124,0x1ea0599,0x004511a },
|
|
{ 0x16f4ffa,0x106ca62,0x03e82e0,0x0589e18,0x1c6205a,0x1030350,
|
|
0x0f53a86,0x1f733e6,0x079b316,0x1d5b233,0x0903f06,0x10a5c9e,
|
|
0x0305aa0,0x096bee2,0x14e6de2,0x180e644,0x11206e3,0x181b2bf,
|
|
0x1b6d98c,0x00a5019,0x0059284 } },
|
|
/* 21 */
|
|
{ { 0x197760c,0x04388a1,0x141a434,0x0c393f9,0x19020b7,0x1f127bd,
|
|
0x11fea61,0x1418ffd,0x0522335,0x119dc50,0x0728403,0x15fb5c4,
|
|
0x0073dbe,0x1d81911,0x0301828,0x0bb4c8b,0x1b8ee14,0x1cdce39,
|
|
0x1ffd8bb,0x0cc3ca4,0x00aa31c },
|
|
{ 0x1430b5e,0x0c75840,0x15a6bd4,0x14a1dc1,0x132f9ce,0x175f45d,
|
|
0x0c2d6a9,0x1121d9b,0x09fe1d6,0x18afbf9,0x0732687,0x11e634b,
|
|
0x03ce5d6,0x0455953,0x159e650,0x19ca9e9,0x0ef4347,0x1742d8e,
|
|
0x01b41dd,0x0847805,0x01768ff } },
|
|
/* 22 */
|
|
{ { 0x1dcec23,0x0082619,0x1466159,0x179ba0e,0x1af0d61,0x07984d5,
|
|
0x0bd4531,0x02a90db,0x1de4887,0x00de47a,0x0e6e8fc,0x15e3a6a,
|
|
0x0cddd6b,0x1d1df47,0x1f99974,0x10cbf76,0x0c3cb5d,0x07c8ced,
|
|
0x0485268,0x007b47e,0x0173fe2 },
|
|
{ 0x0d4a3d1,0x174d0bc,0x1b6010e,0x110ca62,0x04d5cf5,0x0bb231d,
|
|
0x09b0104,0x089d5e0,0x1f84afa,0x0b631c7,0x0908b4c,0x072fffd,
|
|
0x13512f2,0x13115b0,0x07aa811,0x00d1ad2,0x0a397e7,0x02442b7,
|
|
0x1286ccf,0x0365c7e,0x01b542d } },
|
|
/* 23 */
|
|
{ { 0x1487402,0x196af0f,0x1757d46,0x0cf55e3,0x036016e,0x14e1057,
|
|
0x1c7d5b6,0x1fa3d67,0x1ece45b,0x0dbe9b0,0x0a78609,0x0c6604f,
|
|
0x0942db0,0x14208b2,0x08a1ddf,0x0e7a17e,0x0c44587,0x07afe70,
|
|
0x175e97c,0x062a3a5,0x001fb2b },
|
|
{ 0x1aa096a,0x1b9f47d,0x01e0409,0x17c1275,0x152726e,0x1f8bc08,
|
|
0x1341cb1,0x0ecb8a7,0x0ab5dca,0x069efe8,0x1cb528e,0x1b0b0fd,
|
|
0x02bb4a7,0x1bf588e,0x070804e,0x1445eb9,0x0340b6d,0x0af1a9e,
|
|
0x0c97b2b,0x1aa14b4,0x0039846 } },
|
|
/* 24 */
|
|
{ { 0x077df58,0x13b9b0b,0x15b1db6,0x0e396a1,0x164bd56,0x0407f91,
|
|
0x11f5c28,0x0600887,0x1865324,0x0542a14,0x04079e8,0x1ba586a,
|
|
0x1682002,0x0462e6b,0x0f1850d,0x1e27f7d,0x1aeca6c,0x07f8ac8,
|
|
0x02fe370,0x0f85cd3,0x00fb91c },
|
|
{ 0x0de14d5,0x02e5689,0x0089a9f,0x1ecac39,0x1c448c5,0x0dd9ed5,
|
|
0x190c1f3,0x1af3f1b,0x1c76811,0x02c7808,0x1881267,0x00dcea8,
|
|
0x091e898,0x04d3a72,0x0ab428b,0x06f87ca,0x05cb2be,0x0901a34,
|
|
0x082f1cb,0x0c648a1,0x00ec7a8 } },
|
|
/* 25 */
|
|
{ { 0x086786e,0x0c610c5,0x0b20ce0,0x08426fc,0x0d537f7,0x1375907,
|
|
0x043469f,0x006bb2d,0x05cdc48,0x1c87638,0x1ef5d65,0x059049e,
|
|
0x1446916,0x070f878,0x19fbe75,0x02b9413,0x08bce99,0x1e98609,
|
|
0x11c489b,0x028becd,0x002d810 },
|
|
{ 0x11d87e5,0x1a4fadb,0x1b68c49,0x02f6059,0x05f3b14,0x1d7f8b1,
|
|
0x1b4bb82,0x04e048a,0x1fcae66,0x1fbd9d4,0x16617e5,0x1f1e6f7,
|
|
0x010d6eb,0x1fd3686,0x0aa06e5,0x1e26e41,0x00121f2,0x0d94f8d,
|
|
0x130376c,0x0d45f0b,0x003de32 } },
|
|
/* 26 */
|
|
{ { 0x0c2ee78,0x19cc59c,0x0fb89bc,0x034eb41,0x00c3d10,0x0d3fc72,
|
|
0x05c1959,0x0ba6b46,0x104019e,0x094c2f1,0x1d2dbb4,0x0c85702,
|
|
0x0a21e2a,0x17c0529,0x0857ba2,0x1b01c4b,0x1e68518,0x12e8f07,
|
|
0x13dbaa6,0x1782700,0x00848cb },
|
|
{ 0x1d45169,0x143486f,0x0341da0,0x10b3a7d,0x18d7e09,0x1c5fe11,
|
|
0x0204736,0x09046eb,0x0162cf6,0x04caa3d,0x056e321,0x167769a,
|
|
0x06494ba,0x03024cd,0x0b2f15f,0x19fdb04,0x04ea8a1,0x1d62191,
|
|
0x1f19662,0x0c68d2a,0x00d9435 } },
|
|
/* 27 */
|
|
{ { 0x0271323,0x14929b4,0x135cac1,0x10939a0,0x04d9e0a,0x18e63e9,
|
|
0x17efcac,0x0c355c6,0x157a3e3,0x07b25a7,0x13a1591,0x0d0c052,
|
|
0x0e14904,0x01e76a5,0x120bb9d,0x1b48fbb,0x0a57e2c,0x065c953,
|
|
0x1f07e5a,0x1885df7,0x013f989 },
|
|
{ 0x0651600,0x0c5efdc,0x0bbafb6,0x08f479f,0x0c36343,0x18d1134,
|
|
0x0950cd6,0x00f2742,0x1d58255,0x0c6d3ee,0x1ac7a55,0x16470a5,
|
|
0x05a5173,0x114afaa,0x16b9614,0x1a203be,0x0ef6646,0x172a371,
|
|
0x1627e18,0x02d458b,0x01faf7e } },
|
|
/* 28 */
|
|
{ { 0x1ec136d,0x0364763,0x146c35d,0x0f9a226,0x18e1d82,0x03d08b7,
|
|
0x0eb4fc6,0x0caec94,0x1136e84,0x18dcb47,0x060f08b,0x05290a1,
|
|
0x19d41aa,0x1f38b92,0x08fb312,0x0293842,0x152763c,0x0ee6e55,
|
|
0x008ae0b,0x0a16302,0x016da7f },
|
|
{ 0x0a5e258,0x1299686,0x09efe67,0x0f2f6c5,0x0148ad1,0x1feef7d,
|
|
0x090bb1d,0x1891a14,0x174f9b6,0x028c5e6,0x048b516,0x0170ffa,
|
|
0x17c53b3,0x1da8596,0x033464f,0x155d377,0x0eebc01,0x08d0b4d,
|
|
0x1789b82,0x1362143,0x01c57e4 } },
|
|
/* 29 */
|
|
{ { 0x1210716,0x1f33a90,0x1000b2a,0x060fc04,0x01a296a,0x01bcadc,
|
|
0x1047632,0x0d5295f,0x0dd9efa,0x079019a,0x15a1bda,0x13d6cef,
|
|
0x155be2f,0x1fae713,0x04fc9de,0x0f8b8d4,0x041b975,0x07bec91,
|
|
0x1d3d2e3,0x07a5e98,0x013270c },
|
|
{ 0x1209aa4,0x0304e46,0x10dbe72,0x05b656a,0x06f413a,0x091a2ea,
|
|
0x0b468a6,0x09f2d6e,0x19487c3,0x0379575,0x028dd46,0x02ed688,
|
|
0x0e4fa72,0x1ed29ac,0x10824d9,0x1662074,0x1e3ff25,0x0788f56,
|
|
0x017582e,0x0e02a6a,0x01a99a5 } },
|
|
/* 30 */
|
|
{ { 0x07495bb,0x089c9b7,0x0746b85,0x109210f,0x0bd2fd2,0x1ebb7e7,
|
|
0x0ac2ca7,0x0393846,0x1c60e72,0x0d06a4d,0x08278a8,0x1706a2f,
|
|
0x189f582,0x0ec5d6f,0x0de027a,0x1176958,0x09e0ad4,0x1a5526f,
|
|
0x0db3121,0x0826259,0x0027fd0 },
|
|
{ 0x0d4fb6d,0x0817775,0x12fb015,0x1a14c05,0x160c25e,0x1fa503b,
|
|
0x1a106f5,0x028b174,0x054edce,0x145b019,0x1d85330,0x1c72072,
|
|
0x13b9d41,0x0c0f76c,0x086dc74,0x0961684,0x1c2332d,0x0e80871,
|
|
0x0ac3906,0x0b144fb,0x0096dfe } },
|
|
/* 31 */
|
|
{ { 0x1ebd24e,0x17e6b3e,0x01d5335,0x0135c56,0x1e3fca6,0x0be1365,
|
|
0x108bbc8,0x07f4fb1,0x0b9620e,0x01681f0,0x07e1f75,0x042d8ff,
|
|
0x0e634bf,0x04b97ff,0x0c7b14e,0x07cee45,0x1c1d60d,0x141d4ab,
|
|
0x1da94df,0x1cbf0c1,0x0162edf },
|
|
{ 0x0ea20b8,0x02a0078,0x0401028,0x1c3af2d,0x0872ac7,0x0d86561,
|
|
0x097243b,0x14eeecb,0x0b62939,0x0fadc98,0x12dc227,0x0edd5e5,
|
|
0x12f78a6,0x097f5e0,0x01ccafd,0x015a606,0x0deba19,0x09d3320,
|
|
0x0f9f8d0,0x15c2bf2,0x00d536e } },
|
|
/* 32 */
|
|
{ { 0x1c88f3c,0x08cfb50,0x1129b18,0x185d8d2,0x124e5fe,0x017f954,
|
|
0x0b1815d,0x0f89915,0x0ddb22c,0x056ef0f,0x1496ed8,0x0719f4b,
|
|
0x0097289,0x1608bef,0x16b13df,0x05383f4,0x0b74829,0x0a0f9ad,
|
|
0x0bf657d,0x09d1f21,0x0180d1c },
|
|
{ 0x1cd8358,0x0739ed3,0x0480bf1,0x0fe5439,0x19361a5,0x0a69441,
|
|
0x1c4c2b6,0x1c5ede5,0x02b6a78,0x1bf1233,0x098b378,0x1f16f38,
|
|
0x190babf,0x10dacbd,0x0b807bd,0x09cc8d9,0x1f0a60d,0x0ce0f19,
|
|
0x1407e11,0x084501b,0x000e52a } },
|
|
/* 33 */
|
|
{ { 0x1013755,0x1205207,0x03a5cb5,0x0ff7070,0x0b6dce7,0x1b25988,
|
|
0x139e5fa,0x06c4f13,0x193ca5a,0x1382585,0x17ff263,0x01feb17,
|
|
0x1218c36,0x191861b,0x0c7cc8e,0x10ba2a7,0x0885a73,0x1eb59c8,
|
|
0x1ae4efd,0x0261eaa,0x004a071 },
|
|
{ 0x0ef3f88,0x104b5ff,0x0514a68,0x1370567,0x02eba86,0x1332539,
|
|
0x0612a1c,0x084ffc4,0x1858ff9,0x06e05d0,0x03276a8,0x1d6ae92,
|
|
0x0833799,0x00ac467,0x0d5bd8a,0x19dc43a,0x07fa7b2,0x0beecde,
|
|
0x0f3ebba,0x0349d14,0x00d21e6 } },
|
|
/* 34 */
|
|
{ { 0x1068656,0x0db14f4,0x137fb17,0x193fdbc,0x023bd70,0x0a2aa33,
|
|
0x156f7f3,0x0838f15,0x06291a7,0x1cc0ee9,0x19a23bd,0x1b24ec3,
|
|
0x0f3ac53,0x0adc939,0x05a24a9,0x0dfd8d5,0x1b80654,0x1210bf3,
|
|
0x0e78bd5,0x1807975,0x015e793 },
|
|
{ 0x0ff39be,0x0caa1b7,0x1da023f,0x1db7fe9,0x1a1af07,0x120b0b2,
|
|
0x1eaf6c0,0x05307a8,0x1d47980,0x1e2e97e,0x0b9becd,0x12f0c16,
|
|
0x189d86d,0x0746dcc,0x18ca13b,0x17377c7,0x0b5d868,0x1cf824f,
|
|
0x16b462c,0x1d14f13,0x018e3b3 } },
|
|
/* 35 */
|
|
{ { 0x11e61f0,0x1362b72,0x1d5d5c0,0x0660fe4,0x1ddbcaa,0x1757a0e,
|
|
0x09baec6,0x1752540,0x0e2d7f5,0x19f49be,0x1ab6468,0x003d78b,
|
|
0x1d1f7cc,0x1723403,0x0ad9974,0x12a3321,0x1555341,0x0e15227,
|
|
0x0599012,0x18394cf,0x00aa099 },
|
|
{ 0x197e387,0x0d484c7,0x15a6d58,0x108bc3b,0x1605177,0x18eb55f,
|
|
0x144adff,0x1123ff4,0x0d09a9c,0x16d2ad2,0x00b8ad0,0x18e3a45,
|
|
0x0d5e5a7,0x13a0c2d,0x096880f,0x15dffbf,0x09dea0b,0x10cd89b,
|
|
0x1b30285,0x1df2283,0x01a3a5e } },
|
|
/* 36 */
|
|
{ { 0x0573b81,0x106853d,0x13bcabc,0x10cc329,0x1eac1ca,0x188e1a3,
|
|
0x0b6342d,0x085de1a,0x0ba099d,0x17500b6,0x1ea329a,0x1a50a0c,
|
|
0x0fa6609,0x1d09a8f,0x14b1801,0x04c68d4,0x018b11c,0x06d5c2c,
|
|
0x0c700cf,0x1f48bb7,0x0121f17 },
|
|
{ 0x03279d6,0x05c3d7e,0x07867ee,0x178403e,0x030e76a,0x1610eef,
|
|
0x1aa0e01,0x09e055e,0x1c63f82,0x17ebf15,0x14694fa,0x1c4c8d7,
|
|
0x047b074,0x1109c8b,0x1bd24c6,0x1b37f9a,0x139c172,0x0d5967e,
|
|
0x16d673c,0x07d6969,0x010a62f } },
|
|
/* 37 */
|
|
{ { 0x0689a1b,0x16f1b70,0x19cb900,0x1afb95f,0x1dccc9f,0x0e85fdc,
|
|
0x0b5f895,0x1b3c9bd,0x04ada04,0x1f743f7,0x0b9dd35,0x073d7fa,
|
|
0x1b5a850,0x1b8595c,0x0b1995d,0x0777450,0x026ba10,0x0d3d654,
|
|
0x1f3541c,0x0051758,0x011aac7 },
|
|
{ 0x00c8f04,0x0e9ce34,0x0d78b98,0x1969167,0x0f09c4c,0x1a279e1,
|
|
0x026f655,0x126262c,0x0aaccb5,0x0b9725a,0x1ec825b,0x0194b5b,
|
|
0x0fdb706,0x0fe9f66,0x1f6790c,0x054e78c,0x06fe175,0x00a43d1,
|
|
0x134215f,0x0a6cc6c,0x01e33d9 } },
|
|
/* 38 */
|
|
{ { 0x0ec9e7f,0x02835a6,0x063f999,0x0861557,0x044564b,0x1fd1425,
|
|
0x1407c5c,0x0e4bc36,0x015c974,0x1dbdebf,0x1b00cf9,0x0f5105b,
|
|
0x02d6cc6,0x0531dbb,0x18ba4d0,0x05f9a3f,0x01b3f8e,0x11d0427,
|
|
0x0b9b9d4,0x1c9b513,0x00fdccc },
|
|
{ 0x12fd820,0x1fc7760,0x1ccc1e5,0x152db48,0x125f892,0x0cbdfa1,
|
|
0x0907556,0x19eb2fa,0x002b753,0x1779ad6,0x1f3ae8e,0x12bbece,
|
|
0x0c8a73f,0x08ddd63,0x0a24adf,0x0f160b6,0x183cc52,0x1483a8a,
|
|
0x11fd17d,0x1daa7f4,0x001c2f5 } },
|
|
/* 39 */
|
|
{ { 0x140b79c,0x00b2f55,0x06a0e45,0x104b691,0x1fb6eed,0x16083fd,
|
|
0x1adf629,0x117b426,0x18e01f2,0x018edc5,0x1e641f5,0x01bb49a,
|
|
0x0584e5d,0x1238f34,0x0a451ca,0x0dff0d3,0x1699837,0x0ac6834,
|
|
0x118c47f,0x0d36e98,0x0006ce3 },
|
|
{ 0x0dd1452,0x1b9e88d,0x08a9b01,0x0bdb1d3,0x0e4e9c9,0x0ad2061,
|
|
0x038cb28,0x11fd1ff,0x0af62f1,0x1e5be9b,0x05212cf,0x0ddddd9,
|
|
0x1b2ca33,0x1d90202,0x15b9ea4,0x106a549,0x031956d,0x1b6c868,
|
|
0x07280f9,0x0eac07b,0x00e5dd3 } },
|
|
/* 40 */
|
|
{ { 0x1481bf7,0x194bec5,0x00f3317,0x0854267,0x06a2a3e,0x005cb60,
|
|
0x14a3371,0x0793c28,0x11189da,0x115f9af,0x15fe9e6,0x1312d9a,
|
|
0x0bb8adb,0x09abe99,0x0924d72,0x0df5b83,0x180c2d7,0x0a8fd92,
|
|
0x13c8f78,0x043d684,0x01ba987 },
|
|
{ 0x0a4b397,0x16d57a9,0x1952300,0x181a169,0x03c5f4c,0x1f3ce6e,
|
|
0x136cded,0x16c537c,0x0b33970,0x1a19b76,0x0231ffc,0x16f9250,
|
|
0x11ed3dc,0x011446d,0x0a43bfc,0x1ab35d8,0x151e96e,0x19523ce,
|
|
0x1b63e97,0x1db0e0e,0x00929d7 } },
|
|
/* 41 */
|
|
{ { 0x060043c,0x0d785f3,0x1d3763b,0x1602dc0,0x04aa2cc,0x061d9ec,
|
|
0x1a39f8b,0x1893a46,0x05c269f,0x1da8098,0x0cf8d91,0x1dc27bc,
|
|
0x04d0194,0x1c4e528,0x0cd86e5,0x1623bb6,0x033984d,0x0466a8c,
|
|
0x03b24bc,0x1003d99,0x00c6d5b },
|
|
{ 0x1ab9887,0x08e0aa3,0x0044cfe,0x14d6b56,0x0f285e2,0x1fe40c1,
|
|
0x139684c,0x05936e6,0x038d869,0x021ad3a,0x00ba057,0x08f8865,
|
|
0x0a3c92b,0x0e3de6d,0x048c7d6,0x1190c32,0x1c34d15,0x11d7212,
|
|
0x1688f32,0x0d1fd78,0x00117f5 } },
|
|
/* 42 */
|
|
{ { 0x15caa87,0x1eceadf,0x1276332,0x1ed1bb1,0x17bfc60,0x0a6f6f0,
|
|
0x136ef1f,0x17ec7d6,0x18270b5,0x1b72ca2,0x063f9ef,0x0f4b981,
|
|
0x1588713,0x02ebdc7,0x17ada1c,0x14a6794,0x0ee4b25,0x025bef7,
|
|
0x09c029b,0x08b8649,0x00ef8e0 },
|
|
{ 0x0cf52bc,0x00e4938,0x0a60583,0x152198c,0x0bf3f63,0x18147da,
|
|
0x10872fc,0x1e2bffe,0x1523bef,0x140816b,0x1384142,0x1347173,
|
|
0x1eff330,0x03310d8,0x0769340,0x0f00f1d,0x09fcc0a,0x14bbafc,
|
|
0x005e184,0x0890ca0,0x00eb590 } },
|
|
/* 43 */
|
|
{ { 0x1bd33ec,0x1327ef5,0x15e6299,0x019cb5a,0x0cf9a66,0x1dab768,
|
|
0x1b01543,0x0ddd9a0,0x11d5aaa,0x0652fd6,0x09fc1ed,0x1cb7291,
|
|
0x1a36dae,0x17f0e08,0x18de21f,0x0a897a5,0x0c491d2,0x120fb0d,
|
|
0x0fff63a,0x1ee0e25,0x00be49d },
|
|
{ 0x1acdb56,0x178fab2,0x0f79838,0x08bcbcb,0x12f13c8,0x1d02097,
|
|
0x14d5385,0x1df72ff,0x1d9c93b,0x11433e7,0x055f922,0x02d64b5,
|
|
0x1f9ca9d,0x050c31a,0x157066d,0x15ce23e,0x0f58d26,0x0cd9c34,
|
|
0x1251507,0x0900829,0x0000ac4 } },
|
|
/* 44 */
|
|
{ { 0x0ad38db,0x1e7c4ea,0x1445b06,0x027ae28,0x1180f38,0x18121d0,
|
|
0x09d672d,0x0d8b698,0x1163a71,0x0eb26b1,0x122f6d7,0x1fd426c,
|
|
0x09bbd2e,0x126f4cb,0x1c61fe7,0x1188b48,0x112e2de,0x1b2ef34,
|
|
0x0f6b429,0x0be5389,0x0048e07 },
|
|
{ 0x04dd88d,0x1aa3a2f,0x0bf000c,0x1100aef,0x1828363,0x19447b8,
|
|
0x1700489,0x1bdc966,0x1e68989,0x0047ec8,0x1dc6eb4,0x062b9a7,
|
|
0x0242142,0x1f26d0f,0x0c08ffc,0x05762b9,0x035b566,0x0bf35ce,
|
|
0x1ec13f9,0x1e82caf,0x0072143 } },
|
|
/* 45 */
|
|
{ { 0x0f40f2c,0x1823613,0x0c76c1a,0x18d9af8,0x1d5d246,0x09d4dbd,
|
|
0x189c065,0x0df554a,0x08f0043,0x16494dc,0x0198356,0x125843a,
|
|
0x0619373,0x0deb6df,0x1e7b456,0x087f3a4,0x15ad17c,0x09bbe26,
|
|
0x03f3409,0x1db4a17,0x0179800 },
|
|
{ 0x0132f31,0x0ee059b,0x0e8ee23,0x0255bce,0x0f8f4f0,0x1ef15cb,
|
|
0x07b0c80,0x066710b,0x0231b65,0x0d81c0a,0x024f2bb,0x1a41428,
|
|
0x19ad08c,0x0e15f17,0x1e1b511,0x1813f73,0x132f6eb,0x0fe9eca,
|
|
0x0bbd1e3,0x16b1323,0x013d757 } },
|
|
/* 46 */
|
|
{ { 0x00f894b,0x168802c,0x11bdf66,0x15b24bc,0x1612488,0x0d3432d,
|
|
0x1f850b9,0x0268a92,0x117f9a8,0x0370829,0x0cd5072,0x0415f14,
|
|
0x18d8aa8,0x1d336ab,0x1e41981,0x11c474c,0x0ae5f75,0x023efb0,
|
|
0x1fe2ad7,0x1a99214,0x0107cad },
|
|
{ 0x164ad0e,0x18227b3,0x06ccd5a,0x024a031,0x169fe0e,0x0a6db57,
|
|
0x129897c,0x0a85bd5,0x11bd77d,0x0f93bcf,0x0a2573a,0x03e4b9f,
|
|
0x0397991,0x1b78cd6,0x1a533b6,0x08963a9,0x01701af,0x0e1a99a,
|
|
0x031c9fd,0x087ffea,0x003bcac } },
|
|
/* 47 */
|
|
{ { 0x1c1d4cf,0x14a8e41,0x0d3c5d0,0x01648b8,0x003791d,0x16e638f,
|
|
0x03bda70,0x0cfd51f,0x12a3107,0x152bd14,0x0522f4b,0x0d77625,
|
|
0x03255b4,0x07f575c,0x1707824,0x17eb255,0x18c449a,0x0d06968,
|
|
0x12a29a2,0x193feb8,0x00199e8 },
|
|
{ 0x128171a,0x1dce6f5,0x01ef27d,0x07aaed3,0x0fd7840,0x1fc1267,
|
|
0x1cefc8b,0x18ab169,0x1bf333c,0x104d9c9,0x13adcbb,0x0745603,
|
|
0x0debff8,0x11014ce,0x0cd3114,0x1eea2b7,0x0a066eb,0x1d1e1f4,
|
|
0x074173c,0x1c0f769,0x01a65de } },
|
|
/* 48 */
|
|
{ { 0x114257b,0x0ac6b58,0x18c026a,0x03a92eb,0x129afd4,0x173d88b,
|
|
0x1e6d4ea,0x1060e50,0x1edd1ac,0x1c8d849,0x19e5d41,0x0fa23d6,
|
|
0x0acfefc,0x1133ada,0x152f4df,0x0a2fe1c,0x17e8d69,0x1c4d316,
|
|
0x0084268,0x100bb04,0x006b96f },
|
|
{ 0x1b5f9f4,0x0ea8bab,0x1345205,0x0c80b68,0x05c9e43,0x0380b07,
|
|
0x1778392,0x1f06885,0x11ef6b3,0x09ff7ca,0x05febe5,0x19ebee9,
|
|
0x17919e4,0x00b7785,0x18f3134,0x1ddda49,0x0872512,0x1fe2e55,
|
|
0x0ef45c0,0x1480534,0x01b6f1b } },
|
|
/* 49 */
|
|
{ { 0x09252ac,0x1421aa9,0x0360a99,0x00e9cf6,0x1da626c,0x1f43559,
|
|
0x0330782,0x0a6aa10,0x14ed5dc,0x1a529fb,0x107f414,0x028019a,
|
|
0x1ca9eff,0x0b3a448,0x1f25171,0x16b5a1c,0x095ec53,0x06f525c,
|
|
0x1454262,0x0cf7de2,0x01ffefc },
|
|
{ 0x06033fd,0x0e08498,0x1766623,0x13e6d0e,0x1b28797,0x019ae28,
|
|
0x0bc9b8f,0x1ac9a73,0x1124e29,0x0392cfe,0x16f7f29,0x0ae1883,
|
|
0x155d60c,0x06606c4,0x0892d84,0x1ff0c0c,0x0e5eea8,0x1d020ea,
|
|
0x19361c1,0x01c2b95,0x01fd292 } },
|
|
/* 50 */
|
|
{ { 0x167da85,0x0af8666,0x08559b4,0x08b58a9,0x0e98b6f,0x1638e1d,
|
|
0x18087c6,0x0485e0b,0x0475592,0x1f59113,0x015b707,0x0ac2cdd,
|
|
0x072a2f1,0x17da5d2,0x1ac5159,0x12416cb,0x1d2a29d,0x19a3445,
|
|
0x07532e6,0x19d0ddf,0x0061943 },
|
|
{ 0x0c91174,0x0b10c55,0x08d2d1a,0x1883bb2,0x05b519e,0x03b1d24,
|
|
0x0b7ca7c,0x0676fdf,0x1712c8b,0x028bf93,0x0e18c26,0x1d8760a,
|
|
0x04a02e7,0x0ff9f1f,0x0f116ec,0x0c90c8d,0x16f2949,0x1a35744,
|
|
0x0f4ae4f,0x162c93d,0x01462ae } },
|
|
/* 51 */
|
|
{ { 0x0e4d3c3,0x07a0ff4,0x076c7cd,0x1eb76fd,0x080d87f,0x085abce,
|
|
0x1b02b64,0x15de042,0x1b87349,0x1125bb0,0x09b300a,0x0a50561,
|
|
0x17054bc,0x17968ca,0x131c0a6,0x0d9ba76,0x0e2adbe,0x00725c8,
|
|
0x181828d,0x0e9f024,0x00cf8e7 },
|
|
{ 0x0229950,0x1cede17,0x0dc0f1f,0x0db3f05,0x0b11f84,0x0602f9d,
|
|
0x1668fc4,0x19456f5,0x10f1820,0x01f56a7,0x1eccc88,0x1791997,
|
|
0x1151dbc,0x0333837,0x1672bc0,0x13abc77,0x0250605,0x12d1cdf,
|
|
0x12bf993,0x070f91b,0x014c984 } },
|
|
/* 52 */
|
|
{ { 0x0011531,0x13abfc7,0x15f1c22,0x0587b9a,0x1f45b17,0x0ccf14b,
|
|
0x127f70b,0x02b51d5,0x1b93b64,0x0a7740f,0x023a1a7,0x16a94a9,
|
|
0x10a5833,0x05dbd5b,0x155870c,0x1e753bb,0x184b3bd,0x1daded1,
|
|
0x177ccca,0x13f1c03,0x0124f90 },
|
|
{ 0x141e782,0x0554255,0x0e1f16e,0x0d0a3bb,0x1de2012,0x0415e90,
|
|
0x0a9f665,0x077e937,0x1f4b641,0x0cb1ef5,0x0788901,0x1f76f9a,
|
|
0x0eed369,0x0dd6b07,0x1d25774,0x061dbb9,0x093892e,0x0f5a3ab,
|
|
0x1c2884b,0x0237b15,0x010baaf } },
|
|
/* 53 */
|
|
{ { 0x0ec64e2,0x100ba0b,0x1af9c51,0x1efaf8d,0x1fd14ac,0x05b8bb5,
|
|
0x0128d9a,0x0383c6a,0x1741b04,0x171f9f9,0x0d9ec1c,0x0a945a7,
|
|
0x0d651fa,0x12bec94,0x0fb728f,0x1e832c4,0x08b72c8,0x194dba7,
|
|
0x09eaebb,0x13968e6,0x00383d9 },
|
|
{ 0x0342a3f,0x0e859ed,0x0552023,0x05bde95,0x1200246,0x1ad4300,
|
|
0x190bbaa,0x0da3638,0x106e54b,0x10f1502,0x1b3c697,0x021e218,
|
|
0x109ba17,0x07c81e6,0x13f0d98,0x0cdea66,0x0011341,0x1cb4f00,
|
|
0x15710d4,0x04c0e82,0x00fafaa } },
|
|
/* 54 */
|
|
{ { 0x12de285,0x0687338,0x1717217,0x010d3eb,0x0d2ff8b,0x0769c4e,
|
|
0x0ae4b7d,0x1086e54,0x055b99c,0x1a92698,0x0800cd8,0x0b45c0f,
|
|
0x1346fef,0x0b704a4,0x0b20b6b,0x12a5614,0x02172a8,0x159b133,
|
|
0x1c85fad,0x1963115,0x002c9af },
|
|
{ 0x064c5b5,0x0ea3b4d,0x1f874ee,0x1c89899,0x00d8d5d,0x036dffd,
|
|
0x163bc47,0x1daac10,0x141c14a,0x10ecbc7,0x1fa1533,0x1ce46bd,
|
|
0x1d251f9,0x023a2ba,0x1430530,0x13807f3,0x18ebda8,0x0069641,
|
|
0x1b32770,0x1e08166,0x016fa25 } },
|
|
/* 55 */
|
|
{ { 0x0ad682d,0x0cef54e,0x0e46c8f,0x068c6d2,0x07acb1b,0x07926bc,
|
|
0x0662170,0x19d3eb8,0x1d41883,0x1fb17e3,0x15791b7,0x13bea6a,
|
|
0x05d1ab2,0x048e6d0,0x06c72ca,0x067daad,0x1c452c6,0x06d8a6d,
|
|
0x08d150a,0x1770d85,0x01941ac },
|
|
{ 0x0db8127,0x1386412,0x1d6f61a,0x1e836f9,0x04a6563,0x046cda4,
|
|
0x16afae4,0x0151b09,0x1899c26,0x1755731,0x0da55ea,0x1656888,
|
|
0x0d13ed6,0x0854964,0x1253e67,0x1972e77,0x02bd04b,0x1cbc797,
|
|
0x05a9597,0x0711dee,0x007456a } },
|
|
/* 56 */
|
|
{ { 0x0fc1f77,0x16ff24b,0x15a9820,0x1e268f5,0x104c435,0x15f22bd,
|
|
0x0537097,0x155e84d,0x1b6f764,0x050b834,0x00f6859,0x07aa09b,
|
|
0x10e0387,0x1064119,0x0e76d4b,0x1367d61,0x14ed423,0x14c4359,
|
|
0x0620536,0x10fe54b,0x016a765 },
|
|
{ 0x1c71a5d,0x07c7475,0x08cda46,0x050a80a,0x09141a4,0x0165e62,
|
|
0x0273306,0x14fac7e,0x1e09057,0x17f2ce9,0x0763ad2,0x161bc47,
|
|
0x12e633d,0x1eca4a5,0x12160b7,0x1fac375,0x0414704,0x0c5c8ad,
|
|
0x13abbf6,0x0cd53bf,0x010ee08 } },
|
|
/* 57 */
|
|
{ { 0x0e07a4d,0x0623829,0x1740ad4,0x11cbae8,0x1f6d38b,0x1789133,
|
|
0x111f386,0x1ef6829,0x139c505,0x1f25a25,0x1ce6f80,0x0f2b0de,
|
|
0x1c59f3d,0x13e178d,0x066f29f,0x1f5a994,0x01ec063,0x18e28e0,
|
|
0x1d0a2be,0x126f4af,0x0080da3 },
|
|
{ 0x02369fa,0x0654e88,0x18d7a76,0x16e0d81,0x0009bff,0x1aaec07,
|
|
0x0669e5a,0x0985c14,0x0ac0d09,0x107216f,0x1061eb6,0x058af0f,
|
|
0x166c1be,0x0e7d025,0x12b8b32,0x0e680da,0x0607657,0x0ad8675,
|
|
0x1f258a1,0x04a48b8,0x00d82d5 } },
|
|
/* 58 */
|
|
{ { 0x093de69,0x191c657,0x1a6db72,0x0677fb5,0x0963c83,0x1bcc1b2,
|
|
0x07d37a2,0x15c6790,0x0ae8bf8,0x09d1122,0x1aeb338,0x0f0c987,
|
|
0x160bc6e,0x0aad2d6,0x0de94f1,0x128b350,0x135bc7e,0x0c3aec6,
|
|
0x07d1bf3,0x00aa69f,0x001fb37 },
|
|
{ 0x1b974a1,0x093863f,0x1205e3a,0x01d3da4,0x03448fa,0x1ffdea1,
|
|
0x1b0f592,0x078282c,0x1d79f4b,0x02d5221,0x1cca828,0x09e2773,
|
|
0x1ed855a,0x164811a,0x1af3e36,0x0569097,0x1878db5,0x0b2c24c,
|
|
0x1234274,0x1ab3e3c,0x0183aa4 } },
|
|
/* 59 */
|
|
{ { 0x1ffad9f,0x02ebaed,0x03f3b96,0x09e833b,0x04df617,0x0349a2b,
|
|
0x0fd679b,0x018dee7,0x183d59b,0x003c9e8,0x122542e,0x1f87253,
|
|
0x0b6baf4,0x14cb15d,0x1116a54,0x024e77a,0x145eaa9,0x1a95b0c,
|
|
0x1471e16,0x19bffe7,0x01be4fc },
|
|
{ 0x0b2857f,0x1c26cbe,0x0fd0170,0x100d6f5,0x0cf8305,0x1673592,
|
|
0x1745d0e,0x16dea51,0x0bc43d6,0x03dc7d1,0x1592e4b,0x117e29c,
|
|
0x1a8f0e2,0x095cf80,0x1a6f1cf,0x107cc36,0x1403dd3,0x1d5c5f5,
|
|
0x1e4651a,0x1d418b2,0x00aeacc } },
|
|
/* 60 */
|
|
{ { 0x163c2de,0x05d7700,0x029269a,0x17d64ed,0x042d0b2,0x0d73b3e,
|
|
0x1c493ff,0x086ad0d,0x10aaca9,0x136d2ea,0x02473e4,0x099dc02,
|
|
0x0d699c3,0x09925f6,0x0951501,0x141527a,0x0f14193,0x08db5ac,
|
|
0x1847327,0x0924bda,0x014ff14 },
|
|
{ 0x1ed9259,0x0d30660,0x09fdfd8,0x065e3ab,0x1be37aa,0x177a188,
|
|
0x1c4f41e,0x1740708,0x14e6fa7,0x0f99ea4,0x0dcc326,0x182d17a,
|
|
0x1c43928,0x0dcaabe,0x13e333d,0x17dcae7,0x060d1a2,0x005e36a,
|
|
0x0ec5584,0x1a32870,0x014527c } },
|
|
/* 61 */
|
|
{ { 0x027af4e,0x1289a9a,0x0df52f9,0x02621b2,0x0e6c0bb,0x1338e19,
|
|
0x09dab2a,0x0ed7b1d,0x0d3a9c3,0x0bd9fea,0x1c26aa7,0x10c68e2,
|
|
0x00124ce,0x00c028e,0x1739074,0x1dc3844,0x04ff9e8,0x02a4494,
|
|
0x0d713b2,0x105392a,0x013d22d },
|
|
{ 0x1b15e02,0x0f6ced0,0x01a1ac0,0x18603cb,0x1d092ba,0x1209ad8,
|
|
0x0860d5d,0x1497f4f,0x16f7159,0x0772cdb,0x0434370,0x00a2301,
|
|
0x169171a,0x1c0290c,0x054c6ee,0x0f208b8,0x0fc2092,0x0ba0498,
|
|
0x18cdda1,0x169198e,0x0008963 } },
|
|
/* 62 */
|
|
{ { 0x0aaaed5,0x05b107a,0x1ba03fa,0x1bfd0e3,0x1068de7,0x1fe5a58,
|
|
0x00c3ffa,0x0b65644,0x1c3a215,0x06fdf73,0x06e0175,0x15184ed,
|
|
0x10a7a26,0x169cf57,0x1f79dc1,0x1e0646e,0x047f615,0x0f8d492,
|
|
0x0b66dcc,0x1035088,0x012aa1b },
|
|
{ 0x1152e8f,0x133e858,0x0530a67,0x0f256bc,0x0e773d9,0x05abd11,
|
|
0x041cfc7,0x145c1b0,0x0bf1da4,0x1d7854e,0x0d12680,0x0c1d845,
|
|
0x1d169b1,0x0e96be8,0x0b06b23,0x11dc970,0x0a6bfc9,0x0ba8456,
|
|
0x0f2fa85,0x124881c,0x0150549 } },
|
|
/* 63 */
|
|
{ { 0x13a4602,0x0250550,0x1839c00,0x07a1a58,0x105c71a,0x0bcde2a,
|
|
0x0918e9b,0x1e949fc,0x0d54d9d,0x03c759d,0x0f1ee3a,0x120ee7a,
|
|
0x057ecca,0x122767d,0x0eec9e0,0x1a2f2b6,0x01fb124,0x045187b,
|
|
0x1d8cabc,0x1ca0029,0x01155b7 },
|
|
{ 0x0f0021a,0x017664f,0x07518b1,0x0ff0ad9,0x18017fd,0x123c5e2,
|
|
0x10ee0b9,0x1b621c4,0x11505a4,0x183a334,0x1fba96b,0x143899a,
|
|
0x0ad9bb0,0x0a95768,0x0e8e68b,0x1e13bd1,0x09ab549,0x003a3a2,
|
|
0x195fe99,0x11ef7b3,0x013fd5c } },
|
|
/* 64 */
|
|
{ { 0x053c22b,0x0673dad,0x11a86f6,0x1af9568,0x18733fc,0x1659ca3,
|
|
0x0938922,0x01f8899,0x0a38c79,0x0c4458f,0x0d08dea,0x0dd62b8,
|
|
0x0336afb,0x1db8103,0x04ee2a3,0x011f572,0x0c59175,0x19a5bbe,
|
|
0x0791cca,0x03af4ff,0x0050a93 },
|
|
{ 0x0d21d18,0x121482b,0x0286a42,0x0eab682,0x0266630,0x053582c,
|
|
0x12a2e25,0x0b968d0,0x1828cf7,0x10d6f31,0x1c0a8e2,0x10b424e,
|
|
0x094fb2f,0x16fbdb8,0x1fdf416,0x03b6d07,0x092a68d,0x00e9fad,
|
|
0x024f357,0x19c3b78,0x00f5243 } },
|
|
/* 65 */
|
|
{ { 0x17d7891,0x0c1e1e9,0x1b2a3f0,0x13fb0cb,0x17b5014,0x10c2208,
|
|
0x10f5a3c,0x0b01edc,0x15a07f6,0x1a8f612,0x00c80ab,0x0d975a6,
|
|
0x158fe5a,0x0833b77,0x179a3cc,0x000192b,0x11fca4e,0x03a8471,
|
|
0x1dcd495,0x1cb52ae,0x0159783 },
|
|
{ 0x0537ad9,0x0dab897,0x13def07,0x1a6b7d3,0x1e87112,0x1fcde5a,
|
|
0x0ad2355,0x18f76a4,0x0a8b3cb,0x17fbc48,0x136d707,0x1c23cbd,
|
|
0x0d4f306,0x19c3f3f,0x16a0e48,0x03c7a61,0x0f47232,0x026c8fe,
|
|
0x104a99f,0x0f76c5c,0x009f848 } },
|
|
/* 66 */
|
|
{ { 0x0b8e08e,0x0fc07c6,0x1b5a1bd,0x02492df,0x1cfd2c4,0x1bee6fb,
|
|
0x0dd0d82,0x0be00c3,0x157f4d0,0x0dd7fef,0x0187c93,0x18548b0,
|
|
0x04b1993,0x0ef4ca6,0x1b2a342,0x1c0c4d8,0x04d2747,0x077b869,
|
|
0x066572f,0x0ba9c77,0x00ffd4e },
|
|
{ 0x0f40077,0x0f122e3,0x1418c5c,0x0a0e47c,0x1592e04,0x15fec40,
|
|
0x1bdf9a9,0x1c06b90,0x16d9d9c,0x104ace8,0x15dc32e,0x1fd07d6,
|
|
0x1d2e7f8,0x0206b1e,0x1ac2207,0x08832b1,0x1daeb9e,0x0ab199d,
|
|
0x0bf47d3,0x072fbe7,0x0034fb0 } },
|
|
/* 67 */
|
|
{ { 0x158815c,0x0702f59,0x1f65ee1,0x09c8210,0x1abcb2d,0x182ebd1,
|
|
0x162241f,0x0390f4e,0x17a9d48,0x083bc6a,0x1932f4d,0x1ff085a,
|
|
0x1e9d34c,0x067944f,0x167356b,0x058dc10,0x191dd2b,0x141b96a,
|
|
0x02d02d8,0x1a905c3,0x006bc06 },
|
|
{ 0x04ed375,0x14ad06d,0x0bab441,0x10531b5,0x11baf58,0x1b84962,
|
|
0x086d3d2,0x06b6051,0x07a335b,0x15c3ed7,0x1fbf622,0x06c40ac,
|
|
0x14a7359,0x199061b,0x127f040,0x11660f4,0x0c4a355,0x1b9bd65,
|
|
0x103f3a6,0x0d2d469,0x001ed30 } },
|
|
/* 68 */
|
|
{ { 0x13902fe,0x085585e,0x0ecf655,0x170d53a,0x1bba4b4,0x0e561bc,
|
|
0x182a65d,0x1b874b3,0x1333605,0x02f4398,0x10b1601,0x118435f,
|
|
0x11f2c59,0x177ce5f,0x1fe35bf,0x0788503,0x1d09bf8,0x0c15f6a,
|
|
0x0a04c75,0x1b3ab6a,0x01579d1 },
|
|
{ 0x119258e,0x0d182aa,0x0aa1a1f,0x1204fbc,0x13f539f,0x11186b3,
|
|
0x05d1f5a,0x108d3f5,0x15f5d16,0x18d7591,0x1907d6a,0x128ebef,
|
|
0x135bbfe,0x0b53ff5,0x151aaec,0x0a30f7a,0x0e8e16d,0x0957dea,
|
|
0x13254f7,0x0f7c277,0x0160743 } },
|
|
/* 69 */
|
|
{ { 0x09755a3,0x0b2d4f7,0x0ac557c,0x1570593,0x0c8d5a1,0x15cbf30,
|
|
0x1916aad,0x0e2cb43,0x0ab05e2,0x00266d8,0x020c3cc,0x16a4db6,
|
|
0x0b9e0c3,0x1ad65ef,0x187b069,0x1093155,0x084761e,0x1209ea2,
|
|
0x06e718b,0x1c13776,0x01e9589 },
|
|
{ 0x072258d,0x09040ce,0x0f519d4,0x08b82b2,0x01dcd73,0x008fedb,
|
|
0x1e9ee47,0x11cd8c4,0x1885790,0x0e9f4df,0x0f1a3b4,0x0dfca61,
|
|
0x1f9aac0,0x15ada27,0x1705aed,0x1dbaa24,0x1b6db90,0x01c4305,
|
|
0x0efb6d7,0x1d1611f,0x01aa96f } },
|
|
/* 70 */
|
|
{ { 0x057c0f8,0x12eec79,0x0364c8e,0x05ba742,0x0884dc9,0x1c6701a,
|
|
0x1e73aee,0x15207e6,0x1a47262,0x10bd6a9,0x01b1b58,0x002ea5c,
|
|
0x0da1df2,0x0192146,0x0dc8f83,0x18c59eb,0x0892c30,0x00f2e9c,
|
|
0x1dfe0b3,0x121e3e8,0x01fdd9a },
|
|
{ 0x163ab59,0x093dd0b,0x0fa60c3,0x1ce46f0,0x0f27d93,0x0cb4556,
|
|
0x0099251,0x1ab02ab,0x01700d5,0x1928d19,0x11b67d8,0x1ce6062,
|
|
0x12cf6bb,0x132df87,0x173d157,0x047f6d9,0x0ce6323,0x0405500,
|
|
0x05a91d1,0x13cc59b,0x01496e4 } },
|
|
/* 71 */
|
|
{ { 0x0574c09,0x185bf20,0x1a5afbf,0x067fd01,0x176f264,0x11bec8d,
|
|
0x14d4bac,0x0041677,0x17edc31,0x006315b,0x08db70f,0x1296849,
|
|
0x1ef9893,0x1e3621a,0x1a99309,0x1a0edd3,0x1c4e388,0x196fe10,
|
|
0x139a792,0x10a5ed4,0x0139cc3 },
|
|
{ 0x1096b91,0x051ffdd,0x10f948e,0x0ae7b1a,0x0e72c9e,0x0bbaac7,
|
|
0x16c4631,0x169822d,0x0dc47d4,0x07644e9,0x06557d5,0x1a6a85c,
|
|
0x1c2006d,0x1a1ba3a,0x12bb5a9,0x1208200,0x12a2bee,0x0e0eee1,
|
|
0x164ccb2,0x082f45d,0x01fb597 } },
|
|
/* 72 */
|
|
{ { 0x19bae66,0x18cc0c2,0x106cf03,0x0308baf,0x0b48e9b,0x151e0f5,
|
|
0x0700d14,0x0738d9d,0x0ff8103,0x1c25006,0x035bf88,0x1c22bf3,
|
|
0x1bcd7ed,0x1c506ea,0x08038f4,0x0380def,0x08a3c7e,0x1ab6eca,
|
|
0x194e987,0x034fa31,0x00d09d2 },
|
|
{ 0x00eb3fb,0x1edd7c4,0x1f27e73,0x0ebd07e,0x04cfd29,0x053a5a3,
|
|
0x1f5be8a,0x006c374,0x1dfb13e,0x01006af,0x0984a2e,0x1e96465,
|
|
0x0e03bc8,0x00d46c3,0x1ee4b0a,0x0dd4fa3,0x1ae706d,0x13433af,
|
|
0x1eac630,0x10c115d,0x011d9b0 } },
|
|
/* 73 */
|
|
{ { 0x1d2f539,0x1b0a35d,0x0e885f3,0x00edc4d,0x16052fc,0x1f2533c,
|
|
0x0746352,0x1506d04,0x09f3f39,0x1c11a11,0x1e1cea3,0x0d72867,
|
|
0x0868b84,0x18b7a2b,0x074fcd9,0x0eea0f4,0x0282fd4,0x16fb01f,
|
|
0x05d7889,0x16058ad,0x000377c },
|
|
{ 0x001dd59,0x0d6e9c6,0x0debc9d,0x1d73834,0x1c213a9,0x1e2a01c,
|
|
0x1441137,0x10cd215,0x007ee0d,0x0177103,0x1f10388,0x1d2acc3,
|
|
0x16896ed,0x085817a,0x135ce63,0x03448d6,0x191e5af,0x0e65cb4,
|
|
0x04fdc49,0x05035f8,0x009fd5c } },
|
|
/* 74 */
|
|
{ { 0x1073a5a,0x062a5eb,0x11f7216,0x190c3d5,0x07c81a5,0x10100d4,
|
|
0x128e79c,0x19ca3f0,0x040e003,0x0954fc7,0x06677a5,0x0956b1e,
|
|
0x0b76bdc,0x0ab6601,0x1c48c8b,0x0c5e639,0x06383f1,0x0db31a7,
|
|
0x1e5a784,0x002fdd1,0x016984c },
|
|
{ 0x089f1fa,0x019b12e,0x01e3c7d,0x016d2f6,0x0a02a63,0x02dbfa2,
|
|
0x079712c,0x1986662,0x14fede4,0x1e65728,0x096a929,0x10e8960,
|
|
0x0d0d26e,0x1c26dbd,0x16ddeef,0x183fcfa,0x0a8f571,0x01cf78d,
|
|
0x0633348,0x1752508,0x018d65e } },
|
|
/* 75 */
|
|
{ { 0x0bb2537,0x03355c5,0x05be8de,0x16cb661,0x14ac4cb,0x0145698,
|
|
0x09fb4a9,0x12d04ff,0x010e9e1,0x0e8cfb1,0x006d3a5,0x0f41130,
|
|
0x0331eb9,0x15745c1,0x19de98a,0x12c8555,0x02a5f5c,0x04b49eb,
|
|
0x18da2e1,0x17fd2e7,0x00adff5 },
|
|
{ 0x12b0dee,0x1d710a4,0x0b3a8fb,0x1d2c058,0x0143e9e,0x1dccf29,
|
|
0x1f265bc,0x0b2426c,0x0e93b8f,0x0bc5958,0x1304fb7,0x187020c,
|
|
0x1a8d541,0x1ab9c73,0x0e5c36b,0x16349cd,0x0168373,0x1d7b766,
|
|
0x12b8823,0x147e9ee,0x0180dbf } },
|
|
/* 76 */
|
|
{ { 0x07a6aa0,0x0310d48,0x07dac09,0x1080f0f,0x0f56cb6,0x14549a7,
|
|
0x02da205,0x0908987,0x19b9a90,0x06b1c69,0x107c81c,0x154104a,
|
|
0x106968c,0x0fe445a,0x165c14c,0x0af0818,0x0d5af63,0x1aab26f,
|
|
0x1352533,0x11318f8,0x0097e7e },
|
|
{ 0x16ebb2f,0x04c6cb5,0x049b877,0x18f553c,0x092a17f,0x1516341,
|
|
0x03f6fe8,0x0376c1e,0x0b2e185,0x0319386,0x0933fa7,0x04cb039,
|
|
0x15898db,0x188cace,0x02098e2,0x11a3328,0x08ea54b,0x0722798,
|
|
0x1398c25,0x133d708,0x00d6963 } },
|
|
/* 77 */
|
|
{ { 0x03769ee,0x079b15c,0x12cfe80,0x187df89,0x12d040a,0x15eb43b,
|
|
0x0e2255e,0x0518726,0x1940a71,0x1132212,0x10a8c58,0x191fd84,
|
|
0x11909c4,0x12d0d2a,0x1923c79,0x042e5a3,0x0f1049c,0x0345eb8,
|
|
0x026dff5,0x125a56e,0x0041c86 },
|
|
{ 0x1816784,0x04550ef,0x173938e,0x0a037ce,0x0a58c8a,0x133c092,
|
|
0x17fec0a,0x1c13693,0x0eda721,0x1994cf0,0x0997b29,0x03ebccf,
|
|
0x168a0bd,0x02b638d,0x07a47a2,0x15461b0,0x0f4c005,0x11bd771,
|
|
0x1656efc,0x000ea00,0x0073d94 } },
|
|
/* 78 */
|
|
{ { 0x10c0ef3,0x1562500,0x0682a44,0x109d036,0x0e654bd,0x1a9a848,
|
|
0x18f713c,0x1351e0a,0x1b47d18,0x06e20f9,0x0302704,0x1a0de47,
|
|
0x07122ed,0x020d67b,0x1305abf,0x10a4044,0x1348375,0x18e65c9,
|
|
0x09d6b9b,0x16be524,0x01271a4 },
|
|
{ 0x0e688b5,0x1ea399e,0x1a2de4b,0x0fb9538,0x14566d3,0x0b88e80,
|
|
0x0c9b950,0x151f9d2,0x03cc341,0x1dd0a77,0x0b047f8,0x0998424,
|
|
0x156b8ab,0x1ae9bcd,0x1e9d8ef,0x05f2381,0x0aef152,0x0caf169,
|
|
0x073e569,0x04367a6,0x00acd4e } },
|
|
/* 79 */
|
|
{ { 0x18e061a,0x1d3bc8e,0x08c1004,0x0159909,0x02707e7,0x17b1b53,
|
|
0x0099bac,0x13ad581,0x177b25c,0x08bf510,0x1cd73fa,0x177ae1f,
|
|
0x1eddb78,0x020c4c5,0x0236cac,0x1c88aa0,0x0fcce0a,0x187ac52,
|
|
0x095f439,0x12472e4,0x0043ed0 },
|
|
{ 0x0e129e6,0x0bbd9f1,0x135cb2b,0x0e1e37c,0x1b8c4a8,0x02b199f,
|
|
0x037fc80,0x0875dca,0x12a6915,0x0132c60,0x189902f,0x199571f,
|
|
0x0f95dc0,0x0cb2d05,0x13ad610,0x1b33cd2,0x053edd1,0x1be9dd5,
|
|
0x087b721,0x0276411,0x00832df } },
|
|
/* 80 */
|
|
{ { 0x181c3f2,0x09123e8,0x08fffab,0x1de66f6,0x115d35b,0x0483394,
|
|
0x1f2e9d2,0x143b699,0x1fda7a3,0x07b86c7,0x1d5a1b9,0x0832f24,
|
|
0x1e226b6,0x17f8fbc,0x010218d,0x149d1d0,0x139cf5f,0x04c7425,
|
|
0x02827d8,0x1417d3b,0x00da57a },
|
|
{ 0x0fcea66,0x0767aa7,0x1ebb503,0x195f8ed,0x18df2ae,0x0ac2d44,
|
|
0x0692324,0x14ac7e3,0x113f00a,0x088ded3,0x172e7ec,0x1f56896,
|
|
0x116687a,0x1293106,0x157ec49,0x06b578d,0x11bbacb,0x157ca9f,
|
|
0x1e53134,0x0126e1f,0x00ed997 } },
|
|
/* 81 */
|
|
{ { 0x0b54c89,0x1ab7034,0x108ab27,0x1b9ce6f,0x08ecc17,0x044da98,
|
|
0x1a0feac,0x036411d,0x1543fbd,0x079d094,0x175c1ac,0x19f1089,
|
|
0x0d1b204,0x0f61720,0x05d7227,0x1229501,0x1ae9399,0x1845808,
|
|
0x119d37d,0x1742e0e,0x00176b4 },
|
|
{ 0x1dfc175,0x0b754c7,0x0c31c48,0x06fc1eb,0x17b7fc6,0x199d1a3,
|
|
0x0a17f3a,0x16f11a0,0x10223ea,0x13cc0a7,0x1b648ad,0x0416a38,
|
|
0x1d90787,0x0e09fa8,0x1675692,0x0c16ab0,0x10bfaed,0x1734fc2,
|
|
0x14332ac,0x135088d,0x005c249 } },
|
|
/* 82 */
|
|
{ { 0x1e7bcf1,0x0c0fdb9,0x1ef9075,0x19ba782,0x16dde61,0x0ccfec8,
|
|
0x05fb3e8,0x12f8c53,0x1c159db,0x13ac439,0x0ca0c06,0x112cc82,
|
|
0x184ed77,0x14a1548,0x1cb3a24,0x149772c,0x187816b,0x1f9f722,
|
|
0x195375f,0x0f42919,0x01234fb },
|
|
{ 0x009be8c,0x0c057f8,0x0e87c17,0x0ef1be3,0x02e938d,0x16f3103,
|
|
0x0ba10c4,0x1734fc4,0x16070c4,0x0694f3f,0x1768dd2,0x07d7436,
|
|
0x135cd9c,0x1238ba2,0x146f4be,0x13cce3c,0x0b056ab,0x0ca04c5,
|
|
0x07df1a8,0x1095789,0x0049bb5 } },
|
|
/* 83 */
|
|
{ { 0x0a470f7,0x12a980f,0x18c2a7c,0x11d24a9,0x001bf80,0x1001c6d,
|
|
0x1a7a9c6,0x10e130a,0x15913ca,0x0959770,0x007f6c3,0x0097705,
|
|
0x0aae170,0x08c72e1,0x171bac0,0x08757b6,0x04c1fa9,0x0d2b563,
|
|
0x0a4b540,0x1ec8ee3,0x00531aa },
|
|
{ 0x0345730,0x0f7a483,0x1f0a59e,0x1d08de6,0x146aaa4,0x1e1d55c,
|
|
0x09ac069,0x09df02e,0x08166df,0x1c046d1,0x1370fb2,0x1f849c0,
|
|
0x14e9fb3,0x1b760cd,0x02d876d,0x1a27d3c,0x05eeed6,0x0373fb3,
|
|
0x1a9d4e1,0x1b180f0,0x00e570e } },
|
|
/* 84 */
|
|
{ { 0x08ce13f,0x0b72c08,0x004d991,0x1a1c72f,0x15bfc58,0x1ca4f4d,
|
|
0x0a12fa8,0x0fa096d,0x075af66,0x14db35e,0x0559afa,0x0db9512,
|
|
0x1a7cb4d,0x1fb0aca,0x0f3b3c2,0x04a4036,0x13d002e,0x1218963,
|
|
0x04d697e,0x0ed130c,0x014b81d },
|
|
{ 0x01078ec,0x1de12c2,0x1535011,0x0c2f388,0x15aa9c9,0x08fc7e3,
|
|
0x0182521,0x03ed42c,0x0ce3409,0x0c6a71f,0x15040a6,0x0e0911c,
|
|
0x1e9a9f6,0x0ed4562,0x0a03e21,0x046197e,0x0a08fec,0x0e32656,
|
|
0x0252ddd,0x10c960a,0x002b0ac } },
|
|
/* 85 */
|
|
{ { 0x15daf7f,0x0371cc7,0x1419ad8,0x122124e,0x0838548,0x02c5392,
|
|
0x1717023,0x1c7444a,0x0c90f3e,0x19b17e8,0x057c08b,0x15e810f,
|
|
0x0ac9633,0x0212fad,0x1c42f44,0x1b7f6e2,0x005ec06,0x0e100bf,
|
|
0x06e2ef3,0x0fb9058,0x01c8d9c },
|
|
{ 0x0b8bed9,0x00fef8c,0x0495f6d,0x11c7446,0x0948330,0x08e25df,
|
|
0x0779dca,0x15f79f2,0x141448a,0x185cb95,0x16918a6,0x0c67889,
|
|
0x0295dfc,0x00dfa85,0x0e7118c,0x0626321,0x177869e,0x08c5b37,
|
|
0x086eab6,0x09c5f42,0x00f5a8a } },
|
|
/* 86 */
|
|
{ { 0x00251ea,0x0a884e5,0x06c2329,0x164f4d9,0x12aeed8,0x107a947,
|
|
0x02fad58,0x0ad2035,0x0ae13fc,0x14210f4,0x04f01e6,0x03890b3,
|
|
0x171349f,0x068d586,0x1820d64,0x1b21253,0x09baeb5,0x1cb7149,
|
|
0x166699b,0x05e3f1e,0x00ce96c },
|
|
{ 0x0be8bd7,0x025a889,0x066f92f,0x1e78cfd,0x14846a0,0x1d1c327,
|
|
0x11f4d34,0x103b139,0x073f439,0x1b23889,0x13959c7,0x06484db,
|
|
0x0bc32bc,0x181584b,0x04d3aff,0x1056fee,0x00b0d06,0x0ab0278,
|
|
0x0f3a2d6,0x07afd5c,0x011cfd2 } },
|
|
/* 87 */
|
|
{ { 0x07689a6,0x1236651,0x1cafe25,0x06aac82,0x16a7dc4,0x1e5fe66,
|
|
0x0923ad5,0x1ca617b,0x15b1adf,0x188fffd,0x162fd26,0x01b6e23,
|
|
0x1b9f2d8,0x1b872d2,0x1e7f7c2,0x1143bd0,0x1836bd1,0x04ba9a0,
|
|
0x12ff541,0x0a4d7b1,0x0114c8c },
|
|
{ 0x17388bd,0x1392df7,0x1a9f57f,0x1fcfff5,0x11c3dbd,0x16f1567,
|
|
0x16e25f9,0x1f6f072,0x09ebf1b,0x0d3964d,0x01451a0,0x0e0ed2f,
|
|
0x0f65265,0x1a93385,0x097b367,0x0fa9072,0x1d283d5,0x121bde6,
|
|
0x003b2c0,0x0e654f9,0x01ceb5d } },
|
|
/* 88 */
|
|
{ { 0x1d376d7,0x0fe6767,0x01369fe,0x1d4cd61,0x0b4eab3,0x1c8dec3,
|
|
0x0342356,0x1b0d592,0x08aa304,0x11eadbf,0x19a93ea,0x0856ff0,
|
|
0x0127f3d,0x1dc09d7,0x1467ea2,0x1240d2b,0x0d7e34a,0x0e9c3cc,
|
|
0x0cb0737,0x1814d34,0x0073df7 },
|
|
{ 0x0315b16,0x000dd9c,0x03e6f8b,0x133c319,0x1daa7c8,0x1b5c298,
|
|
0x0fed022,0x10347a8,0x068092a,0x0acf246,0x1eab52c,0x1b3d06d,
|
|
0x1077e93,0x1234cb9,0x1b58d86,0x1c8eda9,0x1f66297,0x12b4e59,
|
|
0x1e047e9,0x1b0307c,0x0185b69 } },
|
|
/* 89 */
|
|
{ { 0x19cb764,0x13f59d5,0x15b463c,0x031d783,0x1bbefc2,0x1cd53cd,
|
|
0x0376c11,0x1ea8eec,0x009e542,0x068b692,0x066e5ad,0x11a378d,
|
|
0x0ae35c3,0x0646c64,0x0cab896,0x148ba27,0x15267a3,0x042bce0,
|
|
0x1155301,0x16e6aed,0x00d9773 },
|
|
{ 0x018c299,0x0523981,0x08ce588,0x0733ef1,0x09be29b,0x07a0a7b,
|
|
0x0802521,0x1a88d09,0x19a2ca4,0x163a49b,0x0deacec,0x0e7cd1b,
|
|
0x1f09c07,0x09ae1ab,0x007c166,0x1c7e4c3,0x03d8b7d,0x0049898,
|
|
0x03edb82,0x1ff9a1c,0x0060f3e } },
|
|
/* 90 */
|
|
{ { 0x05d6530,0x00a5f59,0x103dc8f,0x13352fa,0x1e015b3,0x1bfb112,
|
|
0x0f12fef,0x1e24138,0x014b4f0,0x1ec62ce,0x1a3b3e0,0x1fbc7ef,
|
|
0x0fcf002,0x0f58f78,0x14d4f24,0x018c06b,0x0a5201f,0x01ca621,
|
|
0x0fa3b8d,0x025156f,0x01b5787 },
|
|
{ 0x10110cd,0x1be9d5b,0x06d6824,0x188ef22,0x00fa4ef,0x1d260cf,
|
|
0x0bd6f14,0x1e58d59,0x138d509,0x0980879,0x0b071af,0x1057ca9,
|
|
0x1f3ee2a,0x127951d,0x1a99f0f,0x18f7263,0x06ef089,0x1bd2653,
|
|
0x1288d8b,0x14589e6,0x00b05bd } },
|
|
/* 91 */
|
|
{ { 0x1f575cd,0x05038e8,0x060ad09,0x034a46e,0x15693b0,0x164ea00,
|
|
0x0d80a68,0x0c02826,0x19c914a,0x0621a45,0x0cc7054,0x0e7a12b,
|
|
0x0290245,0x117ea4b,0x05d7f48,0x164eedf,0x086e210,0x1d0b824,
|
|
0x16ea4de,0x137026d,0x01f6ac2 },
|
|
{ 0x15da491,0x0f7aabb,0x160827b,0x1c56d55,0x05953f9,0x1a06ad9,
|
|
0x084186e,0x1b0cd2d,0x14d5127,0x1e22988,0x0b418b3,0x195303d,
|
|
0x032f21d,0x179db89,0x0f93c1e,0x1e41a7e,0x0b89646,0x1896683,
|
|
0x0443d6e,0x06c6d2d,0x015e241 } },
|
|
/* 92 */
|
|
{ { 0x0cfc44e,0x027e81f,0x0f54321,0x10a0876,0x0095f2c,0x1e82cd2,
|
|
0x19f6f26,0x1bf34bf,0x0f65bec,0x1c9947d,0x0587348,0x08e34cf,
|
|
0x1de3102,0x1ddaefe,0x078e6fe,0x18b75d5,0x0d0133d,0x0c0115b,
|
|
0x1c4b0de,0x0f5536b,0x0141bed },
|
|
{ 0x194d941,0x1802cfe,0x006025b,0x00fa9fe,0x1c6e9f0,0x0f82f1f,
|
|
0x1d661de,0x133cc75,0x100483c,0x0207859,0x0661c13,0x1ddee54,
|
|
0x1104d2f,0x0325253,0x1dced6d,0x0fe3db6,0x10f4936,0x1005b3b,
|
|
0x0a7ef4a,0x1c06025,0x01694f7 } },
|
|
/* 93 */
|
|
{ { 0x09095fd,0x0eeb9c5,0x15e837d,0x03a79d0,0x04b7a02,0x16e3b3e,
|
|
0x1e5af97,0x0112154,0x1180a08,0x124bf7f,0x042aad5,0x1c3ecde,
|
|
0x06b9856,0x1cc3cbb,0x0a62090,0x00c0262,0x0f73ba8,0x0b0ba46,
|
|
0x1576a4a,0x120ed8a,0x001207d },
|
|
{ 0x044394d,0x04d008e,0x19142c1,0x0e19c93,0x15f25ef,0x14a132f,
|
|
0x027c2c5,0x1f03c74,0x0109b33,0x02decff,0x04cb90b,0x087f461,
|
|
0x1207f2a,0x0367c57,0x1aaff2b,0x0ce44e6,0x004f336,0x056fbfd,
|
|
0x0a749ac,0x1d25f7f,0x00e02f1 } },
|
|
/* 94 */
|
|
{ { 0x1be4d4a,0x0725331,0x1246549,0x1acde79,0x1fa57be,0x1d3e668,
|
|
0x04fe9f9,0x1a7baf9,0x088c5d1,0x07467b5,0x147c79c,0x12f47e4,
|
|
0x15b2579,0x11aaa67,0x17b163b,0x0e21214,0x0d7065a,0x1346934,
|
|
0x014227a,0x07a9a41,0x004c7c2 },
|
|
{ 0x152d132,0x12badde,0x13158eb,0x0e71903,0x0fb8daa,0x131dcc8,
|
|
0x1b94793,0x10e12d4,0x0b239d3,0x0eb59b3,0x127fb54,0x10e94ba,
|
|
0x1aed5f8,0x01d4603,0x1424765,0x0d5c404,0x05ae468,0x10807c2,
|
|
0x1ad3bd6,0x0b3ae8f,0x01c21af } },
|
|
/* 95 */
|
|
{ { 0x1441308,0x1e00f6e,0x02417de,0x090c611,0x0dc3494,0x0b08e68,
|
|
0x029d1d6,0x0cc55e7,0x14c23ce,0x0d38930,0x0bfb484,0x0f6bf17,
|
|
0x1937f31,0x0649f03,0x1eee7fd,0x0a59e9d,0x0dd8ecc,0x1440787,
|
|
0x172760a,0x19ba59b,0x0028480 },
|
|
{ 0x1f807ac,0x0e506e1,0x1527a3c,0x057a0e0,0x0a3e4fc,0x1c5db63,
|
|
0x0285247,0x19b5a7a,0x13d6dfa,0x1f70e7e,0x11bfef8,0x0372bf6,
|
|
0x1cee46b,0x1eeae7d,0x01eceb1,0x1d16ea4,0x0d9b1b8,0x16ac060,
|
|
0x1ef7446,0x0cd3e98,0x008452c } },
|
|
/* 96 */
|
|
{ { 0x0ace6d5,0x1a3a3e0,0x1eb690a,0x177ce50,0x15acb64,0x1e130a6,
|
|
0x1226626,0x03de660,0x0ff05c7,0x0bff41b,0x0b11420,0x048da6b,
|
|
0x1c772eb,0x1bad4e1,0x17f0858,0x1adfafe,0x01acbc0,0x1fdb7cf,
|
|
0x083a5cc,0x07862ae,0x009a764 },
|
|
{ 0x1845ccf,0x10b5a79,0x16f52c8,0x0121780,0x1c174e8,0x02481bc,
|
|
0x031d358,0x00cf4aa,0x16358c8,0x0b91050,0x1dedb6f,0x188354c,
|
|
0x0e838f9,0x1371704,0x0ccb065,0x0db4a6e,0x15e496f,0x0d81943,
|
|
0x10c18c3,0x04e99f3,0x000c52b } },
|
|
/* 97 */
|
|
{ { 0x0a58beb,0x173c147,0x0921bb0,0x1a6ccbf,0x0b404c1,0x1a07f81,
|
|
0x17eb482,0x14aa8da,0x029d3e6,0x1aefbdb,0x006647e,0x08dacd9,
|
|
0x1ef1868,0x17167f1,0x1a42f79,0x1a2d77c,0x1a01410,0x14bd75c,
|
|
0x0b323a4,0x102a917,0x00cb59d },
|
|
{ 0x0f66a23,0x0e9d6dd,0x0207641,0x0e81bf6,0x0333738,0x007a196,
|
|
0x0d7792c,0x07cdaaa,0x007d3a0,0x0bff474,0x0f2a038,0x1fee0cd,
|
|
0x1529544,0x1d6ffd2,0x10ae5b2,0x0dd48c1,0x19445a2,0x04f80c6,
|
|
0x128d3ff,0x0702ce4,0x011ed54 } },
|
|
/* 98 */
|
|
{ { 0x17f8a61,0x039fdde,0x02ed8aa,0x0377cb0,0x1e18cd7,0x1fb4c02,
|
|
0x07acd99,0x181fab9,0x1571d3d,0x1c6a7b0,0x1e6f22a,0x042af07,
|
|
0x14e2e45,0x121cc58,0x10ddd2c,0x0236a6d,0x16374d8,0x196da51,
|
|
0x17af8f0,0x1e252e5,0x01389f7 },
|
|
{ 0x18fefb2,0x1f90e3c,0x09caee5,0x0a20f75,0x1c76fcb,0x0ddab44,
|
|
0x1dd83eb,0x18a25f7,0x1d33ea6,0x13245f3,0x04d2946,0x132646c,
|
|
0x1b412a2,0x04c2c49,0x0f605a6,0x15b4894,0x18f3e66,0x1b0a24a,
|
|
0x1a1ed15,0x1f8f36e,0x0140b4d } },
|
|
/* 99 */
|
|
{ { 0x0be5bb9,0x0a2b83d,0x06fa0ec,0x11ca3b0,0x0e0cbfd,0x013d7fd,
|
|
0x17d2726,0x0a841b5,0x0a687b5,0x1d392a4,0x105ccf0,0x07f7dd6,
|
|
0x0308026,0x09c13e3,0x053f70f,0x16e1ce0,0x184b5e3,0x03e80c7,
|
|
0x0f3dc5a,0x107c01f,0x00151d4 },
|
|
{ 0x1578aa3,0x11e3e35,0x16b8553,0x0ba6087,0x111ce9b,0x004080a,
|
|
0x07a6ed8,0x0deabf1,0x0f405ac,0x1618889,0x02b1ed3,0x09b0401,
|
|
0x067e66a,0x12e297d,0x10034e4,0x185d6e7,0x1988aca,0x1f70dcc,
|
|
0x02d5d14,0x063b2ac,0x008fdfa } },
|
|
/* 100 */
|
|
{ { 0x11cf8d8,0x0507012,0x0f4b31d,0x1a083e5,0x14d8949,0x15e7296,
|
|
0x12924cf,0x15c16e6,0x15c5bcd,0x0d62fa8,0x002e4f8,0x1f982c4,
|
|
0x0ed3ecd,0x13c9b9b,0x01a899a,0x0d2804a,0x08bea6e,0x0ac2d0e,
|
|
0x0643e4d,0x19baa72,0x000e081 },
|
|
{ 0x1e28412,0x1ccab29,0x192c157,0x05b64e2,0x0d1526f,0x19d6e38,
|
|
0x097ac77,0x1bb9aac,0x0dd35de,0x16229e5,0x03ff8b4,0x1093507,
|
|
0x09ed442,0x0e0672c,0x08304dd,0x16c135a,0x081bd99,0x196afdd,
|
|
0x08bbec1,0x083b98c,0x01ad5be } },
|
|
/* 101 */
|
|
{ { 0x1850756,0x17b33c7,0x165d58e,0x1ca5e76,0x06d37aa,0x14217ac,
|
|
0x0294de5,0x12e21a7,0x1f743f9,0x0d57ccf,0x06a2eb3,0x0bcb27e,
|
|
0x192fa75,0x004fbe6,0x1c13855,0x0ca1635,0x00ad6d0,0x131dfcd,
|
|
0x16aff66,0x039d5aa,0x000e67b },
|
|
{ 0x1f43178,0x054705a,0x0cccd98,0x1b3986b,0x16bd412,0x07b4042,
|
|
0x1e98e20,0x0e27af7,0x02e622c,0x19b96b3,0x009115f,0x17cedff,
|
|
0x11ad7b7,0x06d8272,0x0af7a02,0x0b91a1e,0x1fe4bd1,0x170f3c0,
|
|
0x03940bc,0x0eb7f77,0x01941f4 } },
|
|
/* 102 */
|
|
{ { 0x03543ec,0x015fceb,0x1cf9e52,0x19422fd,0x185cb67,0x066631c,
|
|
0x018e058,0x03d158a,0x1729bdc,0x0b65f6a,0x1a1b7d5,0x12fb444,
|
|
0x1cd62ed,0x040f5bb,0x0932d7f,0x05db362,0x16672fa,0x126bda7,
|
|
0x00cd6e5,0x05354ef,0x017260b },
|
|
{ 0x03df7c6,0x1e3db52,0x01b086f,0x077840e,0x05acac2,0x0ecac04,
|
|
0x0def0d1,0x179d6de,0x0a32a08,0x0c79069,0x14f17a7,0x09eda32,
|
|
0x10f0892,0x027b406,0x0975f1b,0x12258fa,0x0372de9,0x0327351,
|
|
0x0b39913,0x180d88a,0x00ebda1 } },
|
|
/* 103 */
|
|
{ { 0x11dd110,0x1be2e20,0x1128999,0x1459323,0x0d6787a,0x0b336b0,
|
|
0x1a90691,0x02aa77c,0x0c15f9f,0x1f38b55,0x131ec9c,0x0c7e1c1,
|
|
0x10a93b8,0x1531255,0x015c45c,0x184c148,0x16e1a39,0x072f3b2,
|
|
0x1bdbc4c,0x1af16a5,0x0046af8 },
|
|
{ 0x0f38dff,0x10a58b8,0x0415e58,0x1024742,0x1e35d82,0x1f6c091,
|
|
0x1135255,0x0c208d4,0x00da601,0x0c7d4dd,0x01104d8,0x054aa9f,
|
|
0x0be7cdd,0x0cf54ad,0x10958f8,0x06169e3,0x014cb2a,0x0e222cf,
|
|
0x07fe6aa,0x115bacc,0x0183c74 } },
|
|
/* 104 */
|
|
{ { 0x1e58caf,0x00f9cce,0x0990ca6,0x1b0ea7d,0x05bb80f,0x08ca430,
|
|
0x07c90b4,0x015907f,0x003eeb0,0x0486783,0x0f5e73d,0x04a2f8e,
|
|
0x1b4037f,0x1926a30,0x10827f5,0x0419f08,0x0d22724,0x13581fb,
|
|
0x0d0e3e8,0x17a53d6,0x01526f4 },
|
|
{ 0x189e51c,0x081a561,0x063a593,0x12db6fb,0x0cda55e,0x09e2c1d,
|
|
0x05f7ba4,0x081655d,0x1feb034,0x1c983bd,0x1878a41,0x06f13a8,
|
|
0x1eaa16e,0x021dfc5,0x099d4cc,0x1187f61,0x042ba7d,0x04eba4d,
|
|
0x0ee4977,0x03cdacd,0x00ec7c4 } },
|
|
/* 105 */
|
|
{ { 0x1da8398,0x19a2ee2,0x10c0ba6,0x1f76718,0x1c66841,0x1dda3d5,
|
|
0x11589f0,0x1bb9c75,0x1738d2c,0x1df5895,0x0c46163,0x15aed0e,
|
|
0x14d4bc2,0x1dea7a7,0x0876c72,0x0361d2a,0x0aefe4e,0x1153486,
|
|
0x0ffaf8f,0x042bd6f,0x0194375 },
|
|
{ 0x0dfd661,0x11a7897,0x07d132c,0x1ddaa58,0x0149984,0x1c7cc60,
|
|
0x1c98363,0x12065a4,0x07be385,0x13b7272,0x02d9cbf,0x0e7b2bd,
|
|
0x0254358,0x1958074,0x1b0e5ff,0x03d7122,0x105bad6,0x11dcdfb,
|
|
0x184c6ef,0x1203055,0x00007ee } },
|
|
/* 106 */
|
|
{ { 0x1fbcb5c,0x1f54f49,0x0a6f4db,0x073f50a,0x182be58,0x108dd01,
|
|
0x0c497f5,0x06e1648,0x1cd8a26,0x0cd71bf,0x151c129,0x0c1c7b1,
|
|
0x19ab78c,0x02620db,0x0b090f5,0x1398a37,0x1eaeda4,0x1e2000f,
|
|
0x0f71fa7,0x1d48950,0x00f6988 },
|
|
{ 0x077f79e,0x0655278,0x0435364,0x03b3c4b,0x14d1760,0x0da5bbf,
|
|
0x0eecf48,0x16c23bd,0x09037e1,0x18d9fb0,0x0fb3c00,0x1b0426b,
|
|
0x1af113e,0x19481ee,0x1004de7,0x1252ded,0x1caa6f1,0x09b5ef3,
|
|
0x16eeb61,0x076d093,0x006c57d } },
|
|
/* 107 */
|
|
{ { 0x0bfccb0,0x1f71c4d,0x198e58f,0x0972ced,0x0c6e2a2,0x1d3693b,
|
|
0x03c0a12,0x1a3f0ed,0x0465853,0x1c5d1dd,0x0ae6db0,0x06da371,
|
|
0x116e3ab,0x03d0399,0x1f25d09,0x07e6403,0x1182523,0x17eea0b,
|
|
0x118779e,0x19f5035,0x00214da },
|
|
{ 0x0a3198c,0x14f9bf5,0x0754d96,0x0bf9173,0x0be8a34,0x1af65e6,
|
|
0x1c4ab53,0x029484f,0x00c2375,0x020ffb0,0x09ec17a,0x18b4514,
|
|
0x135d9e8,0x1142cff,0x0ddd111,0x1bc6e5a,0x0ffea8b,0x00e0230,
|
|
0x073d6fe,0x1c93425,0x01810a0 } },
|
|
/* 108 */
|
|
{ { 0x1843c3e,0x101d7a2,0x0b9da20,0x07557d7,0x0601e30,0x06fb15a,
|
|
0x023cd89,0x15072f6,0x0d21e5a,0x1439a45,0x10ac395,0x18e7344,
|
|
0x0d2cf12,0x1953b63,0x123b404,0x0a34590,0x1c2f527,0x0db9550,
|
|
0x0b00b41,0x052d872,0x00f3b63 },
|
|
{ 0x0f3d1f0,0x1a156e3,0x0e53392,0x065ea65,0x0f0dcc5,0x021ece1,
|
|
0x0ccd60d,0x196af02,0x0dc8dd9,0x0808c77,0x1c64bed,0x034bdd0,
|
|
0x023039e,0x0aba0ce,0x1dc99f5,0x0d61932,0x04c30f9,0x123177d,
|
|
0x134f0d6,0x1f6f2c7,0x01f7454 } },
|
|
/* 109 */
|
|
{ { 0x1153926,0x140ca4e,0x152043c,0x03056ae,0x02e28c9,0x0f4a64a,
|
|
0x0ecc142,0x0ae9684,0x0de9d6b,0x0d66295,0x128c531,0x1873167,
|
|
0x05aa746,0x031eade,0x13a8c1f,0x193121e,0x1a2e1cc,0x0212aa9,
|
|
0x1db6465,0x03317fe,0x008e271 },
|
|
{ 0x08e672b,0x007231e,0x109f1e4,0x1a7e5bf,0x103675c,0x10b1e4b,
|
|
0x147debc,0x160e092,0x07aceaa,0x06b4c84,0x148da5d,0x0352fd1,
|
|
0x15482f2,0x009ee08,0x1ef0772,0x19a27b9,0x08004f6,0x106715e,
|
|
0x0afebfc,0x08cc590,0x003f2a5 } },
|
|
/* 110 */
|
|
{ { 0x188a8bc,0x1a0f30a,0x0b2c373,0x1c4218a,0x0f48cd0,0x073d22b,
|
|
0x18af5d6,0x0ae670a,0x148b9b9,0x1006aa5,0x026e785,0x10174d7,
|
|
0x0f461df,0x04c6641,0x1f53c5c,0x0e28fef,0x1cd1497,0x08b3f80,
|
|
0x045b17e,0x070a22c,0x0048b13 },
|
|
{ 0x12617f0,0x1b199ae,0x181b7ad,0x04dd970,0x1f9a577,0x08fe749,
|
|
0x00cb46e,0x12f5278,0x16c84b9,0x1d21c45,0x1296fbd,0x044b047,
|
|
0x0bbfe80,0x1ad197b,0x06700a0,0x0b8b0de,0x1ade3cb,0x0f9366a,
|
|
0x1430776,0x1bb8eed,0x01e77f5 } },
|
|
/* 111 */
|
|
{ { 0x0e764c9,0x1f76437,0x0b30f27,0x0d60f90,0x11bec83,0x02d8a16,
|
|
0x0cb9a80,0x1d4d7e3,0x129e8a5,0x077a8d1,0x189071c,0x131c7ff,
|
|
0x08517d2,0x194b361,0x0e278a1,0x198ed76,0x0a92c7a,0x09d16d4,
|
|
0x0ca886d,0x19224ce,0x004a902 },
|
|
{ 0x17ce110,0x08dce47,0x1bc65b1,0x0f5d606,0x1cc33a8,0x152cf16,
|
|
0x1426029,0x00104d2,0x1e78db5,0x1579353,0x0ec0c33,0x070992b,
|
|
0x0282f3c,0x126217a,0x15ba7dc,0x09414db,0x02970ac,0x03b46ef,
|
|
0x0f48bbf,0x1b9c960,0x016f4ae } },
|
|
/* 112 */
|
|
{ { 0x1ed03c0,0x1819576,0x15341df,0x04b11bb,0x0684a05,0x02df079,
|
|
0x0f13e6a,0x176da13,0x1e0b9b6,0x0ed063f,0x0d621ef,0x18fde5f,
|
|
0x1e19689,0x161e673,0x0a5a583,0x055cbf1,0x1d5768d,0x15821ec,
|
|
0x0c84866,0x101037b,0x006829c },
|
|
{ 0x059f006,0x0397d6f,0x1d69afe,0x0d972fd,0x02b9ffc,0x173f7c6,
|
|
0x0576d62,0x03e6e32,0x1f4ccaa,0x1711e50,0x09f3130,0x0c1d138,
|
|
0x061af8c,0x0435ee6,0x1975f9f,0x1bc87dd,0x07f9bd8,0x1c912da,
|
|
0x0c93c22,0x0fe8c69,0x00b453e } },
|
|
/* 113 */
|
|
{ { 0x1048bda,0x04b6871,0x1939531,0x128787b,0x02b6749,0x16a84f7,
|
|
0x127dd30,0x1135840,0x0543c50,0x00fb48f,0x08d96ec,0x014620b,
|
|
0x09cd996,0x1c58b82,0x164fff9,0x128ce69,0x1b3f82c,0x0814fcc,
|
|
0x05869d5,0x18bd440,0x0091785 },
|
|
{ 0x13dbdb6,0x0fcbc4a,0x067ed15,0x132fd94,0x0a9e84d,0x0a6bad7,
|
|
0x140a4db,0x1f48e77,0x0c15276,0x0e0be54,0x1d8d5aa,0x02668f8,
|
|
0x129cf66,0x01cb9c6,0x1a0d82c,0x06c1294,0x0a86973,0x0e9f218,
|
|
0x0ac9fc8,0x0a65bdc,0x01b40ae } },
|
|
/* 114 */
|
|
{ { 0x164cb8b,0x0874128,0x19f5a04,0x1e4aa54,0x0979af4,0x0c2a93b,
|
|
0x1b43a34,0x189c21a,0x1fb64ea,0x1b62bc3,0x09164b3,0x0c77588,
|
|
0x1084081,0x1e706c0,0x03ffcdf,0x182b8bb,0x049da84,0x0c59427,
|
|
0x0998fb2,0x00aace6,0x0010ed8 },
|
|
{ 0x1f3ee9e,0x1a01828,0x1c7841b,0x136715b,0x0e8e3ee,0x1eb2249,
|
|
0x1e9ba84,0x163a790,0x180e1ab,0x1da4fa2,0x15ca609,0x02f217f,
|
|
0x1fc283d,0x17e3d1a,0x1943e96,0x15a9f1f,0x145ade3,0x13b9ed2,
|
|
0x068877c,0x1f55c9b,0x01f878b } },
|
|
/* 115 */
|
|
{ { 0x1ad5678,0x06c7455,0x096eb98,0x1dcc018,0x0afa72c,0x1447108,
|
|
0x182d130,0x13f73a9,0x0d254cf,0x0223fbb,0x18ae959,0x17892b3,
|
|
0x0c1fb36,0x14b0899,0x0f1135c,0x01e3272,0x01ffc14,0x06bd444,
|
|
0x1425992,0x10c2511,0x009127a },
|
|
{ 0x09e690c,0x16010c5,0x0856d4d,0x03d569f,0x05dcc52,0x0772a64,
|
|
0x1108ec0,0x090135e,0x1af3a8e,0x1bc9a92,0x0c7616c,0x06116ee,
|
|
0x15e1f36,0x0a0e7da,0x0d875e0,0x08a536a,0x09eeffc,0x07520f9,
|
|
0x1df498d,0x0eab633,0x00e8cf5 } },
|
|
/* 116 */
|
|
{ { 0x012b398,0x0dc06e9,0x0dcc07b,0x03aa7ba,0x1039618,0x097d4ae,
|
|
0x1811e29,0x0da1c10,0x0a7825e,0x08f3219,0x1b393eb,0x178a661,
|
|
0x0fe0185,0x183c49b,0x03dcc4e,0x0dd46a1,0x0fd9e7f,0x00ee4c1,
|
|
0x1555ad8,0x074c05a,0x00e8dbf },
|
|
{ 0x19e05bc,0x1191a13,0x0f4f0dd,0x19e888a,0x1f5f40e,0x1183c9b,
|
|
0x17d35fe,0x0446218,0x0108d7e,0x07fd69b,0x062ef17,0x1de7855,
|
|
0x00f2f01,0x0bea3fc,0x0ac5c67,0x05c3861,0x118a9b2,0x03de4fc,
|
|
0x00d37e5,0x1b8a55d,0x01f9f53 } },
|
|
/* 117 */
|
|
{ { 0x183f89b,0x15a4f60,0x1b53c99,0x04beb00,0x13fb5f0,0x1618406,
|
|
0x10ad653,0x02fa614,0x0371cd9,0x1b58ca0,0x1f89b52,0x15576fe,
|
|
0x04f7541,0x16adbdb,0x149a7ac,0x06d8bca,0x1c17f80,0x0870d42,
|
|
0x097c99d,0x1e1e45b,0x01cea0f },
|
|
{ 0x08e11f8,0x1eab51d,0x0d5180a,0x03ebf35,0x0986402,0x06496b9,
|
|
0x0b16833,0x0178ce8,0x0523f65,0x122b4f3,0x0afed35,0x1037eff,
|
|
0x0bc8e46,0x01e4f36,0x09d651f,0x1fe4168,0x0d538f5,0x1159ca9,
|
|
0x1c12ba8,0x1f1c703,0x01b0818 } },
|
|
/* 118 */
|
|
{ { 0x10d90f0,0x0dffd72,0x1370ef9,0x17ea023,0x0cb3b11,0x08efd62,
|
|
0x09c469a,0x0e7c219,0x14ea1a7,0x176108e,0x1bbad98,0x1d77cb0,
|
|
0x1d5a979,0x106178f,0x1c5aac6,0x17fd49b,0x17ec57b,0x17f4f1f,
|
|
0x0b949bd,0x0b2c1cb,0x015e1b0 },
|
|
{ 0x030e62e,0x10252c3,0x06dc723,0x1cc88fc,0x1d00310,0x1a223d1,
|
|
0x1ad850e,0x1479e3c,0x17462e7,0x155dc28,0x09c9364,0x1410000,
|
|
0x1f8309e,0x12294b6,0x00175c3,0x1b0243b,0x1b33d4e,0x1079c24,
|
|
0x00d3513,0x17ff78d,0x00962d6 } },
|
|
/* 119 */
|
|
{ { 0x0e07711,0x1f2c6a4,0x0ecb44f,0x11a4e14,0x10f8364,0x0ff8263,
|
|
0x024b633,0x0282a2f,0x051411f,0x0ddb2bc,0x1e29545,0x1b207c9,
|
|
0x0f6c31c,0x02099b1,0x1e1c548,0x0da9ae7,0x1eeeca0,0x197f012,
|
|
0x1538c5f,0x0dc82f2,0x00ad32a },
|
|
{ 0x1d147df,0x0631fb4,0x0dedf8e,0x1ce217e,0x169bb06,0x0a8a6f5,
|
|
0x1afbca3,0x1b3729b,0x18d11c3,0x19183fd,0x1718112,0x1bf2070,
|
|
0x033b369,0x13c0074,0x1a8bd27,0x03838d1,0x0587d50,0x0781459,
|
|
0x13bde06,0x0f0442b,0x0055970 } },
|
|
/* 120 */
|
|
{ { 0x0c1d751,0x1a8edaa,0x1448430,0x03741f2,0x0144530,0x0e45f6c,
|
|
0x0cd3eff,0x0154efd,0x0cf2368,0x0c6c09c,0x1ca1812,0x0949c09,
|
|
0x1a928c1,0x0b52db6,0x064b6e8,0x122072c,0x15b5f9a,0x124ef54,
|
|
0x05c9040,0x1a8af00,0x008580d },
|
|
{ 0x009221c,0x1928007,0x015ba41,0x03e43bc,0x02e05b2,0x1304a83,
|
|
0x0be8783,0x0528919,0x16f7751,0x0bfdcbd,0x0d2b299,0x037be3e,
|
|
0x165d299,0x04ff8ae,0x1b356b1,0x1d8f34c,0x097d049,0x06e0eb4,
|
|
0x1caebaa,0x1f9509c,0x0067388 } },
|
|
/* 121 */
|
|
{ { 0x0ef1dd3,0x05a4ed3,0x15d9948,0x1c774d9,0x191a045,0x1eafa41,
|
|
0x0602bcc,0x0953909,0x0ef0747,0x09e7ad9,0x1ec7ab9,0x1d34f17,
|
|
0x1aa35b2,0x16d4837,0x0a5ff5b,0x059e9d9,0x1891b9f,0x0f8d49b,
|
|
0x0aca162,0x0a66d27,0x010d667 },
|
|
{ 0x1691faf,0x0824b39,0x18616d4,0x13aafd8,0x1c73d3a,0x054292e,
|
|
0x086ee4c,0x0d2fc52,0x040b05b,0x0a7ab8f,0x0fb7282,0x002e827,
|
|
0x185e96a,0x068d35c,0x1f53dca,0x1d16f3c,0x1da3ead,0x0aa8a1f,
|
|
0x05b9153,0x170889a,0x00fb859 } },
|
|
/* 122 */
|
|
{ { 0x0667aaf,0x1041f3e,0x12e9f08,0x1295239,0x13545cb,0x1074a51,
|
|
0x064c632,0x18f943d,0x1e4eaa0,0x1d7ff91,0x15a1130,0x086c85e,
|
|
0x0ba21ac,0x106a968,0x11a2a2d,0x003a9f9,0x05b6a93,0x0a00d2c,
|
|
0x01eaf38,0x1eec592,0x00a3547 },
|
|
{ 0x1e260ce,0x09f69fd,0x07e98f7,0x1b01b80,0x0717752,0x0ed1f21,
|
|
0x0dd75bc,0x01dabf5,0x05261f1,0x18b4325,0x135aed7,0x1ec7a41,
|
|
0x16be7b1,0x110d632,0x18e3040,0x1231d3a,0x0f6673b,0x0189bdc,
|
|
0x0b68bee,0x1688709,0x017423e } },
|
|
/* 123 */
|
|
{ { 0x01fbcf4,0x113e215,0x17b8653,0x16bf59a,0x0c0d285,0x0f3303a,
|
|
0x1af7645,0x134eb85,0x0ef0a6a,0x134b288,0x13d1607,0x1f420cf,
|
|
0x1a13c5a,0x1df70fd,0x1804f05,0x0f3ce57,0x0d6dad2,0x0c2d203,
|
|
0x050b3d6,0x052a3aa,0x0031004 },
|
|
{ 0x02bbc45,0x1af60d1,0x1361a9c,0x14feade,0x0ee5391,0x1000ef2,
|
|
0x1e7408d,0x04a60b5,0x1aa2f8d,0x0590c28,0x16de2aa,0x0db030f,
|
|
0x030e2c3,0x10d4446,0x13020fe,0x0fab79f,0x17fbd3e,0x1dc8ed5,
|
|
0x13f7408,0x10a8c1e,0x00f462d } },
|
|
/* 124 */
|
|
{ { 0x172d703,0x05d0124,0x080fd5a,0x1a72131,0x1c44ca1,0x14642af,
|
|
0x1950ab8,0x06dd371,0x05b1b45,0x1ea79b0,0x1df9213,0x00f698f,
|
|
0x1d2e08b,0x1118411,0x0bcee60,0x1fa2608,0x1131889,0x0e4ffe9,
|
|
0x1b1a0d6,0x1e0ca58,0x01bb56a },
|
|
{ 0x0e0f16a,0x182f103,0x1297b6f,0x15ae8c8,0x1c1ac2f,0x09638d7,
|
|
0x02a603e,0x143cb34,0x136c800,0x1d71beb,0x05e3704,0x1f8c46c,
|
|
0x105f20e,0x15a3778,0x0e962e0,0x013c888,0x1cf4425,0x064a8be,
|
|
0x103b66c,0x17682ac,0x01667d0 } },
|
|
/* 125 */
|
|
{ { 0x122842d,0x185309e,0x1380ea8,0x0b6789d,0x0c6e00f,0x1c15bcc,
|
|
0x13e1db7,0x18b0ec9,0x178d208,0x1496c36,0x02152b6,0x0723cf1,
|
|
0x140a52d,0x12cd84c,0x06c9bee,0x1f93493,0x1ad04c5,0x02ee099,
|
|
0x138fc4d,0x0124d26,0x01dda5c },
|
|
{ 0x0d6d673,0x0e5617d,0x0ff9bc3,0x0a01e76,0x0d8fdf0,0x0bab74b,
|
|
0x065058c,0x1c7d9ce,0x10a4d80,0x0c87a49,0x04c004e,0x126c63a,
|
|
0x18f2aca,0x1aac0b1,0x04659b1,0x0acf3dd,0x174e6dd,0x136f87a,
|
|
0x135c736,0x0490d19,0x0111be1 } },
|
|
/* 126 */
|
|
{ { 0x15cc1b4,0x0639323,0x1e33d91,0x1256e72,0x115fc2f,0x1ebf5bc,
|
|
0x19b4438,0x1c0cb4f,0x0f40c38,0x1a2710d,0x1493f2e,0x0573c35,
|
|
0x0598866,0x01ab037,0x02e9377,0x127ee4e,0x02c1a4f,0x1e1c1a5,
|
|
0x0d8a935,0x0193446,0x002193d },
|
|
{ 0x169fd7f,0x1bdc67b,0x0ee78b2,0x0f13442,0x1815da9,0x0887f78,
|
|
0x03159ae,0x070f69f,0x1269314,0x0445984,0x0cdf008,0x037b24b,
|
|
0x05477b7,0x1353207,0x126a484,0x18ddf40,0x1bdfd21,0x169eef8,
|
|
0x0ca95ac,0x1f3afa4,0x00649b5 } },
|
|
/* 127 */
|
|
{ { 0x19a9c35,0x056fc33,0x1e5b590,0x0796e9a,0x0dad98e,0x074ed7e,
|
|
0x03aed7e,0x0788c97,0x0ad4a07,0x19c30a7,0x17955d1,0x01dc5db,
|
|
0x19bd86c,0x0bb6705,0x0cc5ce1,0x1f72cee,0x1274095,0x0cdae99,
|
|
0x1826bab,0x015d67d,0x013672f },
|
|
{ 0x0e54ba5,0x063b6b2,0x14868e2,0x03b88e9,0x03fe7af,0x13b840b,
|
|
0x1a746ca,0x15aff47,0x0de1240,0x023da4f,0x00c0e81,0x16cd8e4,
|
|
0x13d9f64,0x135e810,0x11e00a7,0x07d4b63,0x0700aa0,0x18e578e,
|
|
0x0ee174a,0x0301d67,0x0103179 } },
|
|
/* 128 */
|
|
{ { 0x12ed12f,0x1a7cfd7,0x162ab6f,0x09e701f,0x0e1d19e,0x0f40d76,
|
|
0x0f6d68e,0x17812af,0x1626ef6,0x0c19990,0x16ca37e,0x0bd419e,
|
|
0x14110ae,0x101c966,0x0565140,0x0f0ab56,0x0876bc6,0x133e24c,
|
|
0x0ff5871,0x1cb2714,0x004ace7 },
|
|
{ 0x0c7dea9,0x0dcf794,0x0611671,0x1414d4e,0x102f95b,0x013b4e6,
|
|
0x1095e08,0x12c069b,0x094dd68,0x09d8584,0x1aa5688,0x16ff6bb,
|
|
0x0903730,0x10be544,0x090fb41,0x140a5fc,0x117fb1b,0x10b67a6,
|
|
0x09be5b6,0x123ad64,0x01c0d86 } },
|
|
/* 129 */
|
|
{ { 0x18015c2,0x16f9fdf,0x0b62a8b,0x1b892a0,0x07f8236,0x1218abf,
|
|
0x1db829a,0x019d121,0x1a2d04b,0x0c77992,0x076eacc,0x0d1b501,
|
|
0x019cc06,0x0d33e51,0x09a4deb,0x17893ba,0x12c83fe,0x04793e0,
|
|
0x126e611,0x07b65e7,0x002987b },
|
|
{ 0x12e3dc7,0x1d7687e,0x1554df9,0x16e82bf,0x098e8bd,0x122f92a,
|
|
0x1b26962,0x1a1f81a,0x0209c85,0x1eadd5d,0x0787ba0,0x1b8daaf,
|
|
0x0d31ec8,0x12815ff,0x132b42e,0x17de23e,0x0ce1f41,0x0e21973,
|
|
0x0fff299,0x015f557,0x01913b1 } },
|
|
/* 130 */
|
|
{ { 0x1053af7,0x1bef829,0x13d2f67,0x0b65143,0x0030476,0x14821c3,
|
|
0x1e3f1f3,0x1ba882e,0x0ac8c5d,0x1df69b7,0x07b1863,0x0277f6b,
|
|
0x0f27b13,0x10d8df6,0x0995bfe,0x0e7533a,0x1459459,0x099a709,
|
|
0x0d8ad65,0x0311198,0x018c326 },
|
|
{ 0x07f6ff8,0x1d20a55,0x11ebd04,0x107f56f,0x092aeb8,0x0183dd0,
|
|
0x021adf3,0x01df43b,0x1234610,0x040e092,0x10324f7,0x04e6042,
|
|
0x1593d4d,0x1308241,0x1b5f8f3,0x12be743,0x0cfdf17,0x1715c8f,
|
|
0x1a7b505,0x1b82346,0x0191160 } },
|
|
/* 131 */
|
|
{ { 0x157d7cc,0x17a3745,0x0e1a69c,0x0a97e04,0x1140b0e,0x19d48e9,
|
|
0x0e5b816,0x1c110d8,0x1a4ec26,0x1cd59d4,0x1d63a46,0x15d78a1,
|
|
0x10742fe,0x0af1357,0x04b1821,0x1b3ee2b,0x076bb1c,0x0ca1e6a,
|
|
0x1fc0b22,0x12ffa98,0x017c3ed },
|
|
{ 0x0d54964,0x01281f3,0x03014ec,0x058d463,0x19bd116,0x0146116,
|
|
0x1b3d273,0x08031fe,0x0035346,0x02e3c20,0x1019a29,0x06bd699,
|
|
0x038ea33,0x1a16df0,0x15c9fe3,0x1879af5,0x111fdf6,0x158abf4,
|
|
0x1264b5d,0x112993d,0x01b3a7f } },
|
|
/* 132 */
|
|
{ { 0x109ea77,0x171cbd7,0x1716479,0x12ebb84,0x06a760b,0x050cbd9,
|
|
0x03022e5,0x0331808,0x0b68ce6,0x00dd654,0x08d5901,0x1a2ab7a,
|
|
0x1fa19a0,0x0cbbd99,0x1296e53,0x1a0530d,0x1f8e5fb,0x0f98fc3,
|
|
0x06407e6,0x18ab4d6,0x00b8f76 },
|
|
{ 0x046ec9f,0x1fc619c,0x09185d6,0x193bd59,0x1462205,0x0846f87,
|
|
0x17b028c,0x0512596,0x1cfaed9,0x1ced941,0x127eca1,0x0008ca0,
|
|
0x11477dc,0x0b77281,0x1492eb2,0x19c8a91,0x11656ad,0x1d3edb5,
|
|
0x0c71a13,0x019b575,0x00fc011 } },
|
|
/* 133 */
|
|
{ { 0x1308bf2,0x1b36c26,0x0010546,0x1facc70,0x19013c9,0x1c1dfcc,
|
|
0x17e4bf4,0x1f8d125,0x03ffc8e,0x0877ec2,0x1a8a1e8,0x02d8627,
|
|
0x00527e3,0x1d06fba,0x1db8f34,0x1a5431d,0x030f6eb,0x165cb72,
|
|
0x1c3b933,0x17d9e54,0x018cc1e },
|
|
{ 0x070404c,0x0a56b8d,0x08c2034,0x01f39c5,0x0ad21dd,0x11f0393,
|
|
0x0f378ea,0x1217299,0x16363a6,0x15acb08,0x078ad02,0x1e8b8d6,
|
|
0x1be70bf,0x1367762,0x05b742d,0x0af8025,0x0747477,0x06a6595,
|
|
0x15f647a,0x11194c7,0x00aa089 } },
|
|
/* 134 */
|
|
{ { 0x0db0396,0x0e7e57c,0x09daa8b,0x0f6845b,0x08ae8f3,0x042b927,
|
|
0x00d2659,0x07eca5f,0x07bf149,0x123e1e2,0x11e93bd,0x168d604,
|
|
0x0e8b600,0x1d75ed4,0x1cf90e5,0x11be157,0x11fa795,0x1170e91,
|
|
0x0206eac,0x0d2563f,0x00ef38e },
|
|
{ 0x0cf3047,0x00b4493,0x01607cf,0x08b2a73,0x1ad14f9,0x1f905b6,
|
|
0x17470a4,0x02ffbd0,0x0f57abb,0x152a1b7,0x1378e0b,0x1ff82f2,
|
|
0x0f0d1a8,0x15ff669,0x0942388,0x0c08537,0x07fdb78,0x0088785,
|
|
0x1378c7e,0x1cdec8f,0x01962ad } },
|
|
/* 135 */
|
|
{ { 0x0c78898,0x1529bff,0x1dff265,0x05bc1f4,0x0b39de7,0x0658478,
|
|
0x1dab34d,0x0a7eda0,0x0da78d3,0x06c5dc1,0x04b306b,0x09a7407,
|
|
0x1d5fe80,0x12c0aa4,0x1eb7b7b,0x18db356,0x1a0c067,0x1c41c80,
|
|
0x1b64fcd,0x0bff449,0x0191585 },
|
|
{ 0x19ebef3,0x1871b5f,0x05dca55,0x0bbe966,0x021046a,0x00b5ae7,
|
|
0x06a569a,0x023f371,0x1288d0e,0x0f9c940,0x04566ab,0x17ca72f,
|
|
0x12d6baa,0x0e47d5d,0x06bfb81,0x15e2082,0x1afe5c7,0x1f8c961,
|
|
0x1f738de,0x05d039a,0x00f7aa7 } },
|
|
/* 136 */
|
|
{ { 0x0c386ee,0x11e078b,0x00e483e,0x13a9813,0x133b046,0x15189b5,
|
|
0x15c8a1d,0x00cf3c1,0x03c406c,0x01e0549,0x0f89f4d,0x1c7c9bd,
|
|
0x0aef220,0x0cb7807,0x15ec784,0x1b9fe13,0x1d824a9,0x0a507ae,
|
|
0x0707421,0x105d8b3,0x01e2535 },
|
|
{ 0x138c7ed,0x1793128,0x0237323,0x08ca8ff,0x1ec4319,0x054a446,
|
|
0x14eb774,0x1b856dc,0x08257eb,0x1cf8f7d,0x032627a,0x0dd63e1,
|
|
0x08c583c,0x000b1bb,0x1cda445,0x01c7be2,0x18bdbc2,0x131417f,
|
|
0x12f5453,0x10200b3,0x00d526b } },
|
|
/* 137 */
|
|
{ { 0x0025949,0x0a917d0,0x0514912,0x1e177b1,0x126d888,0x1b90b7d,
|
|
0x0bd7f98,0x1ec6688,0x0472827,0x0761db2,0x109a076,0x034733f,
|
|
0x0d91d8a,0x1463b88,0x08cbab5,0x04ec4da,0x02fe51b,0x1c72dff,
|
|
0x14427e9,0x1e9fdbf,0x00040f9 },
|
|
{ 0x14a05e0,0x17528b5,0x03ac654,0x1de438f,0x0b0d48e,0x0befede,
|
|
0x1986466,0x1fac9a6,0x08b4c21,0x088d902,0x08c0e83,0x136d7d2,
|
|
0x09a6f56,0x1c62f40,0x03d8259,0x0bb1c57,0x1ab3680,0x139135a,
|
|
0x0cd2728,0x1fe301b,0x01bdd6c } },
|
|
/* 138 */
|
|
{ { 0x03cc612,0x1c2bb4a,0x071e927,0x1d06566,0x0914319,0x056f5ee,
|
|
0x18a5f33,0x043244b,0x0b06198,0x08c7da1,0x0731f12,0x01084b6,
|
|
0x10accb3,0x132372f,0x074cd1e,0x07c44ea,0x0ae590e,0x0757da5,
|
|
0x1128002,0x08c0705,0x0151821 },
|
|
{ 0x196a461,0x040eddf,0x0e90f09,0x136a547,0x11c122e,0x06d845a,
|
|
0x0163919,0x03a4385,0x06d6a08,0x080a5bc,0x0f3bdec,0x1da9ea6,
|
|
0x1c167d3,0x00aa2fb,0x1ecca52,0x0f73ed9,0x11c449b,0x0f52369,
|
|
0x18870a6,0x1aec272,0x0081cfa } },
|
|
/* 139 */
|
|
{ { 0x18a7f0e,0x0b193a3,0x0177bde,0x05bc2ee,0x114183e,0x108bf44,
|
|
0x09b7d5c,0x19fa494,0x1b7cd52,0x06d8d84,0x0f0580f,0x13f75b0,
|
|
0x099e42b,0x184f7c6,0x1c74ba9,0x0999ad2,0x05b8ee5,0x00c4a7e,
|
|
0x129483f,0x0f69ca6,0x00fcf75 },
|
|
{ 0x0b62347,0x08c6643,0x04a1695,0x04f7855,0x0c51c9d,0x13393ff,
|
|
0x0ac14a5,0x0de5dd4,0x00ae43e,0x045471d,0x0819aef,0x16bc0b9,
|
|
0x0d80535,0x0419cc3,0x1ff36c6,0x099bb23,0x1ba3237,0x197a52d,
|
|
0x1480890,0x0c74921,0x0124087 } },
|
|
/* 140 */
|
|
{ { 0x0fac14d,0x05cb927,0x14f3926,0x1b4f353,0x16f4bf8,0x103e14d,
|
|
0x036f75b,0x0701e3d,0x1717715,0x161867e,0x00c98fe,0x1a44e36,
|
|
0x154c91e,0x0cda2af,0x04e0cd4,0x1257f7f,0x1891270,0x0bb52f3,
|
|
0x1204ef6,0x0ce9c36,0x0128a97 },
|
|
{ 0x03e5924,0x11e20ac,0x1418a6d,0x031e2e3,0x01f9aff,0x113d143,
|
|
0x0cf36ac,0x0e0568b,0x08a11ab,0x1ceaeed,0x0da5c64,0x0f61d1b,
|
|
0x052bfb4,0x0760840,0x08de77c,0x03002ac,0x08124ce,0x157ad32,
|
|
0x13e52ae,0x1188686,0x01508d9 } },
|
|
/* 141 */
|
|
{ { 0x1ffc80f,0x0ff39e7,0x0fdb7aa,0x17a868e,0x023e2e9,0x09bdd3f,
|
|
0x0fb4f27,0x0ae4ff6,0x07a3fc3,0x19bb369,0x1280f5c,0x19e71c0,
|
|
0x03d0db4,0x15df07a,0x1805d48,0x0de9f19,0x119da98,0x1ec3f5b,
|
|
0x1f9ac0d,0x16a15c5,0x01536d1 },
|
|
{ 0x040bab1,0x1aef7ed,0x098cdc7,0x1f3657b,0x07d6a8a,0x0565438,
|
|
0x1722435,0x156bd14,0x1643ff8,0x0b9787f,0x03b0bd3,0x01b297f,
|
|
0x029c4c1,0x075c9f1,0x0c3aae8,0x1fa026d,0x08f1d2d,0x15e2587,
|
|
0x14d2820,0x0a5cb53,0x01429f2 } },
|
|
/* 142 */
|
|
{ { 0x10e7020,0x1ea60be,0x05a12bf,0x156a904,0x1b169aa,0x079a47c,
|
|
0x05c2162,0x177b7c0,0x1885986,0x175fb7f,0x070e076,0x0fea2bf,
|
|
0x1bb3398,0x0254a53,0x1157cb0,0x0d092fc,0x042a0ed,0x01cd20a,
|
|
0x1bdde63,0x15a94c3,0x01541c1 },
|
|
{ 0x12709c4,0x1db1403,0x17f9d91,0x171021c,0x1330d68,0x1707b1d,
|
|
0x021d3a4,0x175a37b,0x1f8bea9,0x02727dc,0x0260685,0x1831063,
|
|
0x07c15af,0x1b46350,0x071720a,0x016cdc3,0x1a236e0,0x042c62b,
|
|
0x1f2debb,0x0aa2200,0x00119b2 } },
|
|
/* 143 */
|
|
{ { 0x087027d,0x07693e4,0x0a18487,0x0a57f56,0x0050f33,0x0a88f13,
|
|
0x0f07067,0x1eadc6e,0x17f4c69,0x16a61d4,0x09aed00,0x0d5e4a4,
|
|
0x10e6f35,0x01f3d61,0x040470e,0x1fbf677,0x03d33d8,0x1a1d861,
|
|
0x1cba8d8,0x0721ef5,0x000ba8c },
|
|
{ 0x0851bac,0x061eb3f,0x13f310c,0x134bea8,0x0991c38,0x1dd030c,
|
|
0x0f1919f,0x1e800d7,0x097cbdb,0x04e8127,0x12b6b75,0x0fbaee6,
|
|
0x0a4539b,0x1465b69,0x0ea3e7c,0x1675b21,0x0304de4,0x03d490c,
|
|
0x1ee5a4a,0x0e65df4,0x006ab28 } },
|
|
/* 144 */
|
|
{ { 0x0ed5986,0x15a9691,0x1819c76,0x14b0a67,0x1eee627,0x0aaff1e,
|
|
0x18deb3c,0x065d1fd,0x17ae8b1,0x0b0a486,0x022e533,0x030a694,
|
|
0x102706e,0x1ce0ae1,0x17ff54b,0x15a8d50,0x0f351a5,0x1ead112,
|
|
0x135c02e,0x036daaa,0x01e644d },
|
|
{ 0x02e4e9c,0x1834343,0x1f925a0,0x1890ec7,0x1e5cd76,0x01ce557,
|
|
0x059e702,0x05ac061,0x18d83d6,0x07265f5,0x112b8b0,0x0a9c237,
|
|
0x02911e2,0x127e503,0x0835f21,0x0e08b2d,0x1d5e9a2,0x07abc2e,
|
|
0x0f8104b,0x0cefa1e,0x01be2f4 } },
|
|
/* 145 */
|
|
{ { 0x101a6dc,0x0096ed5,0x0da5300,0x035c35b,0x191bd6c,0x18283c9,
|
|
0x16bb2e6,0x03e75cf,0x062a106,0x138a7cf,0x14dadf0,0x1dcf52c,
|
|
0x0b71978,0x0f0bb2a,0x1046f41,0x07ba9dd,0x0e0efab,0x0e388b3,
|
|
0x1fb6fd8,0x154ae50,0x01d70f7 },
|
|
{ 0x1eb5932,0x137bea8,0x12909ba,0x14bf105,0x154ea0a,0x1cfbee1,
|
|
0x1825ddc,0x0682eb6,0x09be579,0x19a8c95,0x117b334,0x0846f0a,
|
|
0x1d9801f,0x1db21e4,0x0e38959,0x157d865,0x1d723e3,0x0dca08e,
|
|
0x1c71942,0x1bd4d19,0x00ee656 } },
|
|
/* 146 */
|
|
{ { 0x0890deb,0x070a050,0x12f534e,0x1b79d70,0x1f7bd87,0x020ef65,
|
|
0x1fdcae8,0x1d2a3e1,0x0a6820b,0x1f76385,0x018a62b,0x0147189,
|
|
0x0475519,0x1380876,0x16e9563,0x0f363d9,0x1b88c78,0x0676c8e,
|
|
0x1d78857,0x1c7c99d,0x014c08d },
|
|
{ 0x0266da2,0x09a768b,0x0026705,0x16f6992,0x1ce322e,0x093b444,
|
|
0x12bbda6,0x09a6fbd,0x105c284,0x09284bf,0x1466ad9,0x1c26358,
|
|
0x06d23b7,0x12d1e64,0x0baedc9,0x08aead0,0x1b9628c,0x186298e,
|
|
0x0e014dc,0x01d170e,0x00be2e0 } },
|
|
/* 147 */
|
|
{ { 0x1ed32e9,0x1e4002b,0x065ce01,0x1ef8049,0x027e40c,0x1aa4182,
|
|
0x1aaeeae,0x1e8b0a0,0x1ce820b,0x124bbb7,0x10fa055,0x0527658,
|
|
0x08b5353,0x07f7b32,0x07a0d4f,0x1b94ace,0x13f903b,0x09390be,
|
|
0x004ff5e,0x1382135,0x01dc40a },
|
|
{ 0x1b21a38,0x153619e,0x1f91afa,0x03ae7de,0x0ae222e,0x0ea83fe,
|
|
0x0139ef4,0x1563fed,0x0587a77,0x0dd6332,0x12935bd,0x1ec418c,
|
|
0x0a58c74,0x153e1bc,0x0a0df65,0x1c81299,0x1313e42,0x1fa1efa,
|
|
0x0d27853,0x14868ff,0x013f8a9 } },
|
|
/* 148 */
|
|
{ { 0x12f8923,0x1a76fcc,0x07ce16a,0x00dfa41,0x024aa5e,0x09a0777,
|
|
0x06e1c6c,0x0804f7d,0x191e0bb,0x0abe88f,0x1318b0a,0x15a5e7a,
|
|
0x0f425af,0x03ffbd5,0x08c4a1b,0x197d25a,0x12b0114,0x0cb2095,
|
|
0x0f88d4a,0x0d44638,0x019f670 },
|
|
{ 0x05c02af,0x1dde911,0x06341ac,0x0c7f47d,0x13ebc16,0x07a4172,
|
|
0x0add6e1,0x1bf4dbe,0x12bfc55,0x095a290,0x09cf6a4,0x1a80a25,
|
|
0x0430bdb,0x1ea9f55,0x03d0f64,0x1faa758,0x1e40c27,0x07e1ac7,
|
|
0x065092d,0x03077d2,0x00a32cb } },
|
|
/* 149 */
|
|
{ { 0x1a6a746,0x186169f,0x12a38e6,0x043ab44,0x084a792,0x06f95af,
|
|
0x02451e3,0x166e14b,0x130666c,0x144033e,0x1c741a2,0x013deda,
|
|
0x04b09a7,0x0032e8c,0x001e8f8,0x12890a0,0x14bb8dc,0x0382357,
|
|
0x19524eb,0x1462538,0x01fd2b6 },
|
|
{ 0x05f2771,0x0eadef2,0x16574f5,0x15e865d,0x0542b08,0x19535dc,
|
|
0x103efc8,0x1645d9a,0x1e8becc,0x1e5b0a1,0x1891fc3,0x02757f1,
|
|
0x1bcecc5,0x06d181c,0x1755bde,0x141bf2a,0x01956c2,0x148abe3,
|
|
0x00c7f8a,0x06b97e6,0x018ca6d } },
|
|
/* 150 */
|
|
{ { 0x00c4923,0x0058ddf,0x01ef760,0x00d2052,0x046ae74,0x1de8638,
|
|
0x0cdfe55,0x1704731,0x19655f8,0x1470d4e,0x1d0542a,0x0ff4a01,
|
|
0x0ecd292,0x10173d7,0x1aa71b4,0x0d25d04,0x0b39f29,0x05a67ac,
|
|
0x1d055df,0x070d197,0x011f309 },
|
|
{ 0x13ed442,0x1af3d19,0x1deeb72,0x1f20dfd,0x0e5c8e2,0x0c79145,
|
|
0x0048cf6,0x0b85b36,0x07ffe12,0x119796d,0x0c60d51,0x0e63744,
|
|
0x1259487,0x0969628,0x12ab96c,0x1b38941,0x0589857,0x15f8073,
|
|
0x13c803d,0x02010ca,0x0172c5d } },
|
|
/* 151 */
|
|
{ { 0x1c283e0,0x0a02317,0x0039625,0x08fdc11,0x1763398,0x1e8b117,
|
|
0x0d03adf,0x1dbf5e3,0x0f598c5,0x07a8a8f,0x0366efb,0x05eefc0,
|
|
0x146b4d9,0x14621fe,0x10f8ece,0x1a3a4ea,0x12c6511,0x19cca70,
|
|
0x1c16db4,0x08343b5,0x00c6dd8 },
|
|
{ 0x1b991ad,0x10bf011,0x14508f6,0x06e3f74,0x0ab2b21,0x0e0c3cd,
|
|
0x1b16837,0x1b9682f,0x15f63ac,0x19de456,0x09f5405,0x04203c5,
|
|
0x082fcf5,0x1083680,0x0dcff41,0x0259ec6,0x1de7db0,0x18f4108,
|
|
0x1d9517b,0x0ecdb2a,0x018ca07 } },
|
|
/* 152 */
|
|
{ { 0x180dfaf,0x1a3dcd7,0x1fce390,0x1f388cc,0x080b631,0x0de11c5,
|
|
0x16c99b7,0x140dfe3,0x1aa8718,0x0b0f1b2,0x070d7d8,0x19215e6,
|
|
0x08e7f7a,0x1e34237,0x0e0c747,0x0eb6980,0x1106841,0x10f334e,
|
|
0x0d2dcc6,0x13ac412,0x00c76da },
|
|
{ 0x1e4e78b,0x1acbdd1,0x1e6a607,0x18aa133,0x0c14ded,0x0446309,
|
|
0x0e6564c,0x0b17e6e,0x19b2074,0x02b4183,0x1da401f,0x188f444,
|
|
0x13c4440,0x1bf36d7,0x17c8f23,0x122076d,0x0254292,0x1a7b316,
|
|
0x0cede58,0x14db631,0x00f9f4e } },
|
|
/* 153 */
|
|
{ { 0x0d36049,0x0f5c467,0x07e319a,0x03e8373,0x07a4ffe,0x1970844,
|
|
0x1d58da9,0x114d216,0x065a0bb,0x1eeb546,0x10a5559,0x18b12dc,
|
|
0x0d42cf8,0x0d55ffd,0x01ad7cc,0x04d48a5,0x0f28f6f,0x18fbefd,
|
|
0x186b940,0x13c1581,0x0120c5d },
|
|
{ 0x0c10da7,0x171ffd6,0x1b96bef,0x1328928,0x07e2d5f,0x01107fb,
|
|
0x1fa18f1,0x05d1d82,0x0bd6f63,0x137ba0a,0x127bd3f,0x181f87f,
|
|
0x104a9e3,0x01dfdc3,0x1fcf2e8,0x0685a4b,0x000bb03,0x10c7e9b,
|
|
0x014334b,0x07cea60,0x01ac1e6 } },
|
|
/* 154 */
|
|
{ { 0x13d6a02,0x1e83e47,0x0347760,0x18fde9a,0x11fc143,0x03d7b0b,
|
|
0x12fc353,0x1e19532,0x0827c5c,0x0549f4c,0x05e20b2,0x18f656d,
|
|
0x1a4a102,0x052af45,0x0f21f56,0x0c9e0c6,0x02fcc2d,0x00d7441,
|
|
0x01b407f,0x136a7f3,0x01c12ce },
|
|
{ 0x1dc1b79,0x11cfeca,0x05aa165,0x087e9cc,0x0728f75,0x117dcf9,
|
|
0x0f133b7,0x13cdce0,0x0d50fae,0x017bb40,0x14c3b41,0x187785a,
|
|
0x0c0546b,0x06eacc5,0x09001af,0x0922001,0x0c9e129,0x09f9943,
|
|
0x1afe58a,0x1044ab6,0x0146777 } },
|
|
/* 155 */
|
|
{ { 0x10c98fe,0x0a10f71,0x1c16be0,0x01f859a,0x1eb0feb,0x0fb5696,
|
|
0x1329853,0x1d13658,0x09ba314,0x1c09a6f,0x12c5b74,0x1d709e0,
|
|
0x08a443d,0x183fc65,0x155bb83,0x0722ff8,0x1bb3a4f,0x09e0e41,
|
|
0x06b7350,0x0fba496,0x0199839 },
|
|
{ 0x14781e6,0x0f0bf6f,0x0407280,0x128de3f,0x12d7c31,0x18486d1,
|
|
0x0984ed4,0x00f444f,0x0a7c8c6,0x04ad8ee,0x1a5c249,0x17ddbb8,
|
|
0x181cf2f,0x02b0404,0x0f60aed,0x069ae3a,0x1a30851,0x0e7e6ee,
|
|
0x19e6310,0x02e36b2,0x00d23dd } },
|
|
/* 156 */
|
|
{ { 0x0dd7e96,0x007c26a,0x10325e9,0x150813f,0x1114c8e,0x0889c9b,
|
|
0x0a79aa7,0x1ad8ade,0x18fd8c6,0x1b03310,0x1a79f0e,0x150c004,
|
|
0x1fad3ba,0x02c94ea,0x04f1ac0,0x06cb628,0x040222e,0x060d6bf,
|
|
0x1e62abb,0x04c4348,0x01d36a8 },
|
|
{ 0x1003c81,0x022e260,0x180abab,0x15e87b0,0x1ef9ef5,0x1bba34c,
|
|
0x17d7983,0x0b06d4c,0x1bf5d28,0x18973d5,0x0b3bc7c,0x1903909,
|
|
0x122f53e,0x0e9245a,0x18cb28a,0x0b8c0c7,0x1c581e6,0x1ff4d53,
|
|
0x0a1065c,0x10d934a,0x0017e36 } },
|
|
/* 157 */
|
|
{ { 0x090de99,0x17f32cf,0x0d8c2cb,0x195a0b5,0x1e4485b,0x0724495,
|
|
0x1a94b85,0x10f8914,0x0226286,0x16c2a18,0x0f6d50a,0x1d2abd6,
|
|
0x01261f0,0x0a2f2c2,0x1a0618f,0x0ae7291,0x00f8ed7,0x067f0e7,
|
|
0x1612b79,0x1e3feaf,0x003fbd6 },
|
|
{ 0x1bf968c,0x188eee8,0x11cb50d,0x1a91bf4,0x1558d7c,0x12d2b36,
|
|
0x0488f90,0x08293e1,0x05c26d0,0x07c199c,0x105d0c3,0x03e2f85,
|
|
0x19be7b8,0x08a1ece,0x0f70cf9,0x07f5dc7,0x03594fd,0x179c2d6,
|
|
0x1f46046,0x039e853,0x0113755 } },
|
|
/* 158 */
|
|
{ { 0x0193bb2,0x07aad90,0x01c924a,0x00e6217,0x16e579d,0x02e93b4,
|
|
0x18c274d,0x114bdc0,0x0a87186,0x121f219,0x0e1a0e6,0x07c2220,
|
|
0x0828c11,0x1199788,0x01bb3ce,0x1976905,0x0370385,0x199a455,
|
|
0x1c5636b,0x1ff955d,0x00c6698 },
|
|
{ 0x0908745,0x062a57b,0x0fee811,0x08d466a,0x06b336e,0x10f410d,
|
|
0x0a14b55,0x0fed298,0x0363491,0x194bcb8,0x184c546,0x077303e,
|
|
0x0f6e102,0x17a352f,0x05f70af,0x09efed0,0x0af8e11,0x1c9ef50,
|
|
0x15cb16f,0x1e79abd,0x0136c3c } },
|
|
/* 159 */
|
|
{ { 0x1080de4,0x1ccd5bd,0x0e5aee1,0x1bad3b0,0x1b8f781,0x17c7b19,
|
|
0x0aaaa61,0x194ed68,0x0a54bc5,0x0ba601c,0x0beee57,0x0c0b538,
|
|
0x1076fcb,0x000bc49,0x146d102,0x0de1b08,0x0389d28,0x1a07806,
|
|
0x1150c98,0x11d2a41,0x014c303 },
|
|
{ 0x177aad9,0x1e1c0b4,0x0f8f252,0x05ae10f,0x0dbfd08,0x0ff6845,
|
|
0x008321d,0x1f80da1,0x0345656,0x0e7426a,0x1b753b8,0x11c01fa,
|
|
0x0071c4d,0x152fd5a,0x0ce2c89,0x1d6de46,0x0c10bae,0x06a3bf5,
|
|
0x1e0309b,0x161176b,0x0078e4d } },
|
|
/* 160 */
|
|
{ { 0x078342a,0x0e89508,0x0190044,0x1cab342,0x0534725,0x09ffee8,
|
|
0x075643f,0x03fd48b,0x106f0ac,0x1b4a54f,0x06f1a73,0x15b67c3,
|
|
0x00f6d24,0x1ceee68,0x18e3d7a,0x1ba9c79,0x166b632,0x09c2007,
|
|
0x0578715,0x11fbf7c,0x0085cab },
|
|
{ 0x109422f,0x01fb5c6,0x10ec2a5,0x0c1f311,0x17d2975,0x19726c8,
|
|
0x107e8bb,0x07eab48,0x135f7c1,0x1a1a91d,0x0b4ffd9,0x080fdb5,
|
|
0x0d274d3,0x09a3921,0x10450d6,0x0c2bab2,0x1013bb8,0x08e5939,
|
|
0x15de533,0x06e0097,0x007da04 } },
|
|
/* 161 */
|
|
{ { 0x1712c44,0x1ccd316,0x15de092,0x114d2c4,0x148368f,0x0f11438,
|
|
0x010cb59,0x1f11dad,0x06f5bc5,0x0014183,0x0d1e745,0x02429d8,
|
|
0x10e6cf3,0x09936db,0x16dbd12,0x126d72d,0x098ca32,0x1e52d60,
|
|
0x1fa886b,0x04918e5,0x004d69e },
|
|
{ 0x11269fb,0x0484953,0x0d802aa,0x1030ca1,0x0f6bdba,0x1aaed91,
|
|
0x10a8e7e,0x1a03b39,0x16311e9,0x1e7586f,0x10b0743,0x0f39215,
|
|
0x0a6faeb,0x058f9b9,0x04ec88b,0x0832647,0x1dfbc8c,0x0315379,
|
|
0x1fa399d,0x1461645,0x00019de } },
|
|
/* 162 */
|
|
{ { 0x0b3118b,0x144d609,0x0959f7d,0x1ad96dd,0x106ee39,0x1e6cbc6,
|
|
0x08b0861,0x10f9f98,0x18d537d,0x0c2db40,0x15b6cae,0x02a5d3e,
|
|
0x1575845,0x0f04c60,0x00e61c5,0x059a41f,0x1c83b21,0x1df4b52,
|
|
0x06b0711,0x140671b,0x01fb3dd },
|
|
{ 0x1a0a9b8,0x1bff067,0x1dd7c1a,0x0fc45b9,0x1478bac,0x1443e44,
|
|
0x178104d,0x179e702,0x0914c54,0x0c08eef,0x07a993b,0x02c01ea,
|
|
0x17c8c24,0x064382b,0x045360d,0x17968c7,0x152a8ab,0x1769272,
|
|
0x1913d4b,0x1d73d04,0x00019e5 } },
|
|
/* 163 */
|
|
{ { 0x0d52313,0x0d02733,0x0af47d9,0x0a9a7ee,0x1d69454,0x1bd708f,
|
|
0x176be9a,0x08e5781,0x0571ab2,0x10fbcec,0x0a35a24,0x12cd5cb,
|
|
0x13d4c5f,0x1762e70,0x185dc5a,0x17a73fb,0x1a4b764,0x1b87376,
|
|
0x04359e0,0x12810b3,0x01efffe },
|
|
{ 0x08f92e8,0x10713ec,0x08f3cfe,0x1b38ee2,0x021ef0f,0x13a6dd5,
|
|
0x05d3224,0x0c4c4b3,0x1b9ba27,0x067d252,0x0f2bdb5,0x13a48dd,
|
|
0x1010c90,0x07c7143,0x05e8436,0x1dd4406,0x1e1453a,0x1d83b8e,
|
|
0x031ac28,0x188f22d,0x00eadf0 } },
|
|
/* 164 */
|
|
{ { 0x0854477,0x00f2426,0x11f046f,0x090c71c,0x0bec25b,0x0e2a6c9,
|
|
0x180ae1a,0x1a487a9,0x0be1e7e,0x18c6f19,0x18312b8,0x1d60d68,
|
|
0x1ef5471,0x1521357,0x0b9efce,0x05b8271,0x0ddd845,0x091d713,
|
|
0x1e0b7a7,0x1f83aaa,0x01649d3 },
|
|
{ 0x0de1979,0x0571885,0x1ca361f,0x1a76978,0x0847041,0x01e4df5,
|
|
0x0f1015b,0x0ce7124,0x0d74ae4,0x17f0c15,0x1926b8d,0x0de9d97,
|
|
0x1592bff,0x0e20fcf,0x0036e03,0x00e2acd,0x06fe463,0x19add60,
|
|
0x1b41cc1,0x11698fa,0x00c06d6 } },
|
|
/* 165 */
|
|
{ { 0x14dfcf2,0x115f3c2,0x0f436f8,0x1f4d5c7,0x0e21a7d,0x10f6237,
|
|
0x0eb4694,0x099e8c6,0x041a948,0x14a293d,0x048fcfb,0x1736554,
|
|
0x121145e,0x0571e54,0x0d2a0ab,0x1b24aac,0x0a0fc85,0x070bb56,
|
|
0x0420b63,0x19eff83,0x0078504 },
|
|
{ 0x199793c,0x073e21b,0x1ed75d3,0x116aa33,0x14ddd61,0x1fcc043,
|
|
0x17e4e57,0x1cc59ed,0x1b8bf61,0x07522e8,0x13d53c0,0x0c27b9f,
|
|
0x1026863,0x01801ad,0x108edd8,0x15396ce,0x1344028,0x14fde3a,
|
|
0x14681df,0x059c6e0,0x00f47b5 } },
|
|
/* 166 */
|
|
{ { 0x0bec962,0x1ec56cb,0x01ebafd,0x0c2fc02,0x11cc81f,0x07082c6,
|
|
0x1142485,0x13ec988,0x142394c,0x014c621,0x18144db,0x0a5a34c,
|
|
0x03d9100,0x086fc12,0x190dd52,0x1bd4986,0x01efe5c,0x09189df,
|
|
0x09fedec,0x14c1efa,0x0076249 },
|
|
{ 0x0f593a0,0x1ac1c0e,0x1679d25,0x1706c98,0x0c9ceef,0x0e4cc88,
|
|
0x04ccf81,0x1c65eb4,0x1421808,0x0752f0f,0x1a3d3cc,0x149e9eb,
|
|
0x0756fb3,0x1b6065a,0x0b9b8ba,0x198d459,0x1fd08bd,0x1b05983,
|
|
0x1fe3045,0x0f20381,0x001aee1 } },
|
|
/* 167 */
|
|
{ { 0x1aa9e14,0x019b5c4,0x003f012,0x03ecece,0x0663427,0x15b4c03,
|
|
0x010ce41,0x0469b54,0x1ebb7ab,0x0123f70,0x06814cc,0x154fd6b,
|
|
0x15969b4,0x00007a6,0x03be096,0x0d6b7af,0x0eb4602,0x072ed9c,
|
|
0x15a15b1,0x087cbaf,0x003b06a },
|
|
{ 0x12a0ee7,0x1741c76,0x004ea82,0x11e2dd1,0x04bbe52,0x13209b8,
|
|
0x17d713a,0x0cf156d,0x006e298,0x1f4065b,0x07b4ad6,0x16e5e8b,
|
|
0x1af19b1,0x0bb0a90,0x0733934,0x0de76f5,0x194aa51,0x09cd7fc,
|
|
0x0d05a49,0x125d0d6,0x000797d } },
|
|
/* 168 */
|
|
{ { 0x0f3a8ca,0x176f0ad,0x07b096b,0x054b86a,0x1392478,0x1f60401,
|
|
0x08fefe4,0x16883cf,0x0e6f425,0x027c9e2,0x1d8026c,0x05d903c,
|
|
0x06e4ec1,0x08c07fe,0x1cd9b51,0x1de74f2,0x1b50e0a,0x0e949e5,
|
|
0x035c764,0x12d288d,0x0061a14 },
|
|
{ 0x15a67a1,0x02a0e33,0x041bd4b,0x011ebfd,0x07d38d3,0x1f4c473,
|
|
0x0f333da,0x10c54e1,0x0185898,0x101f65f,0x1c116eb,0x0c2ce0c,
|
|
0x16ecd02,0x086546c,0x0b37664,0x0e6ba3f,0x08230c0,0x03d5085,
|
|
0x0ca3c87,0x0fcaa86,0x00152a2 } },
|
|
/* 169 */
|
|
{ { 0x0057e27,0x104f073,0x1368f75,0x0f8f48a,0x07e8b6a,0x196eadc,
|
|
0x045147c,0x1c5feb3,0x0d0ef51,0x11cbd44,0x19d51ba,0x0d424aa,
|
|
0x00c4986,0x19145a4,0x11722c4,0x132f5d4,0x077dd01,0x11edf07,
|
|
0x14619f4,0x1d451f8,0x01f80e2 },
|
|
{ 0x1d0820b,0x0a096b4,0x08618a5,0x0e3d4cb,0x0317312,0x031c068,
|
|
0x00887ac,0x00d84f9,0x075fe97,0x1fea77e,0x074941f,0x14aeb4e,
|
|
0x037b396,0x03e5baa,0x1200147,0x17dc6c3,0x0d7ad4d,0x0f03eda,
|
|
0x0c64b51,0x0903e93,0x01431c7 } },
|
|
/* 170 */
|
|
{ { 0x0e1cc4d,0x1968204,0x07b97aa,0x075a5b8,0x093758d,0x0e39c9f,
|
|
0x1f7f972,0x10619d6,0x1d33796,0x186c354,0x1e1b5d4,0x0795c49,
|
|
0x0bef528,0x1858dd8,0x1746993,0x09c7956,0x01f54db,0x0cb555e,
|
|
0x0f00316,0x1b0f987,0x01443e3 },
|
|
{ 0x160e7b0,0x141098e,0x0063942,0x16ba67a,0x1c9b629,0x0299c6f,
|
|
0x1b90bf4,0x1d58a95,0x0e821c6,0x13c7960,0x10272c1,0x0ebe0d5,
|
|
0x16e5c9d,0x0980c6f,0x0d5d44d,0x18ccf06,0x1ac0bf8,0x0c0e537,
|
|
0x142b8b7,0x10041d3,0x00e17fc } },
|
|
/* 171 */
|
|
{ { 0x1aaa5eb,0x0a3a08d,0x00da2b7,0x12f37b0,0x02cbb75,0x1ff6910,
|
|
0x0310337,0x083b0d0,0x04e0911,0x011d478,0x122e1c7,0x03da40e,
|
|
0x0965d14,0x12cf494,0x1a855d5,0x1b7fcb0,0x1cd5006,0x03e346b,
|
|
0x095a69d,0x15a1be4,0x0148da0 },
|
|
{ 0x19069d7,0x062edbf,0x069323f,0x0ab80a6,0x0487d24,0x116d9d1,
|
|
0x12267a6,0x0418b56,0x0b4fe97,0x15fea9c,0x1cd7914,0x1949a4f,
|
|
0x1373a04,0x1716d64,0x0ef1527,0x1cfc4f9,0x09dff3e,0x0014391,
|
|
0x036a4d8,0x130f1a5,0x00d0317 } },
|
|
/* 172 */
|
|
{ { 0x166c047,0x1f4dd9d,0x187626d,0x12c0547,0x02e6586,0x0dce001,
|
|
0x08a5f23,0x14689f0,0x1d08a74,0x13b5651,0x0e63783,0x0e3bf9a,
|
|
0x0afbf1a,0x0190733,0x0edbaaa,0x13f8a5f,0x0bc179c,0x0541687,
|
|
0x19eacad,0x019ede9,0x000f4e0 },
|
|
{ 0x090c439,0x0074d24,0x1ac9093,0x17786b4,0x17564a2,0x1ba4be9,
|
|
0x11e7766,0x0852b48,0x1612de9,0x0ff9f86,0x1400ce8,0x0ff9cc1,
|
|
0x1a35862,0x09120be,0x176a301,0x1070b02,0x0d4ef6b,0x1283082,
|
|
0x05ba5aa,0x0e51a5e,0x0120800 } },
|
|
/* 173 */
|
|
{ { 0x1039042,0x191b955,0x13b65db,0x193f410,0x10e6978,0x1f60a18,
|
|
0x174bd62,0x187a07f,0x1fe2045,0x1006080,0x16a4a0c,0x1ef5614,
|
|
0x18e6868,0x130fd7f,0x1257477,0x044ca4d,0x127b7b1,0x1d0f100,
|
|
0x0a97b45,0x07baf18,0x00898e6 },
|
|
{ 0x0bba4ee,0x099ed11,0x15d2ed9,0x0fe92d4,0x1eff639,0x19535c9,
|
|
0x0a7dc53,0x07e8126,0x11dfdd7,0x041245e,0x1286c68,0x1e5cd37,
|
|
0x0762f33,0x1d17019,0x05df992,0x1ee8334,0x19375dd,0x05e2874,
|
|
0x095af47,0x152f3e9,0x0095b87 } },
|
|
/* 174 */
|
|
{ { 0x1c1f177,0x19b54b3,0x0f27a0d,0x10c0026,0x1b6d350,0x164d2d8,
|
|
0x0ee49ba,0x0392849,0x0c27ef3,0x14e00d3,0x0d21c1e,0x174a245,
|
|
0x05ad93b,0x0e8d64c,0x0e538aa,0x02eb73d,0x006d53f,0x0288e01,
|
|
0x040b645,0x1d64a4a,0x00b1d13 },
|
|
{ 0x15a1171,0x1edf5b3,0x0ac73f9,0x182d81a,0x1228295,0x1e44655,
|
|
0x16d6815,0x19f1b64,0x0d300e9,0x1f54f4b,0x154badc,0x06fe4d2,
|
|
0x1fb0e00,0x0f07cc6,0x0740d72,0x0901fd5,0x1b8d290,0x0c30724,
|
|
0x00dacc6,0x1d2a258,0x0037a35 } },
|
|
/* 175 */
|
|
{ { 0x100df48,0x194f747,0x0c13159,0x0c23590,0x189ca7b,0x1d4091d,
|
|
0x15fe62c,0x1d492f4,0x1c21ca3,0x0218d8c,0x0cf39f8,0x1bd7c57,
|
|
0x1945a73,0x16e3bc0,0x01b30ae,0x07be25f,0x1e4e5eb,0x02ff802,
|
|
0x149f73c,0x0bbaf5b,0x005ef95 },
|
|
{ 0x0ee402f,0x117fd00,0x0d33830,0x1476617,0x1b335e2,0x1e5880a,
|
|
0x1474190,0x110a84a,0x13cd196,0x10c1fa2,0x1952d31,0x1e45e17,
|
|
0x04c6664,0x061066f,0x1d33fb9,0x188eb4b,0x12f80a4,0x0ee554b,
|
|
0x04447b6,0x15e400b,0x019cde4 } },
|
|
/* 176 */
|
|
{ { 0x171f428,0x085e46b,0x0e0a7a7,0x13c8794,0x1ac1ecd,0x09d6781,
|
|
0x19203ae,0x07f1abd,0x1065a2a,0x11197c0,0x0e29cc5,0x1f545e1,
|
|
0x021fc04,0x012a3a5,0x037df9c,0x0bede95,0x1f23bb1,0x128d627,
|
|
0x0254394,0x0436e7c,0x006b66e },
|
|
{ 0x1a41dee,0x0c24033,0x0cfd672,0x1cf67c5,0x0cfa95a,0x0a2a709,
|
|
0x00e1a24,0x148a9b3,0x1eefca6,0x06eedef,0x072dd7c,0x164823d,
|
|
0x035f691,0x1f79046,0x0e79d9b,0x079ed53,0x00018b3,0x0f46f88,
|
|
0x0705d2a,0x0ab593a,0x01c4b8a } },
|
|
/* 177 */
|
|
{ { 0x04cccb8,0x1ac312e,0x0fbea67,0x125de9a,0x10bf520,0x17e43c3,
|
|
0x195da27,0x0dc51e9,0x0da1420,0x11b37cb,0x0841f68,0x1400f8a,
|
|
0x1090331,0x0a50787,0x03533ab,0x08f608f,0x0e2472a,0x0d944cf,
|
|
0x1081d52,0x0ca69cc,0x0110ae9 },
|
|
{ 0x0ed05b0,0x0eb2ae6,0x150cb30,0x1202eb2,0x0bac3f0,0x0bbe6bd,
|
|
0x1c29239,0x0db75d6,0x140e98d,0x0580449,0x1493c61,0x0ca6c07,
|
|
0x1d26983,0x12b90b9,0x051620c,0x083bcdc,0x1266111,0x00e9a45,
|
|
0x1e89fcd,0x04afb9d,0x006be52 } },
|
|
/* 178 */
|
|
{ { 0x147e655,0x1c799e4,0x1e56499,0x1411246,0x1f0fb76,0x011ce8f,
|
|
0x19d15e4,0x19d65bf,0x03cdbb7,0x1043a49,0x1b5073a,0x1b720be,
|
|
0x0821326,0x1cee2ac,0x06ba6b9,0x02e04b6,0x00ce9c3,0x070a29a,
|
|
0x0b0e2a7,0x0058534,0x00c3075 },
|
|
{ 0x156ace2,0x12788e0,0x14a4304,0x0ef3fe4,0x0c170fe,0x08b8d91,
|
|
0x06a05b8,0x12ec1bf,0x155de27,0x0cde541,0x131e768,0x0fd4f8d,
|
|
0x101ad92,0x0eb0fbb,0x1640448,0x00d7650,0x026261c,0x1ff4064,
|
|
0x08990ae,0x01a6715,0x015e405 } },
|
|
/* 179 */
|
|
{ { 0x0ad87bc,0x0bc14f5,0x12f724e,0x0f03d09,0x00ac936,0x0f27ef7,
|
|
0x10935ab,0x0ad6af3,0x1690d7f,0x05cd5d2,0x1ec2e54,0x13a7a29,
|
|
0x16f09b2,0x12d073d,0x1a13c8c,0x09fe7a0,0x1d3606f,0x1828a74,
|
|
0x02b5cce,0x17ba4dd,0x0077e63 },
|
|
{ 0x0d25c6d,0x0837670,0x173c2bf,0x1401745,0x1d90021,0x0dd9cc6,
|
|
0x15dc231,0x1f83604,0x0198ff8,0x1bf836c,0x0b35a01,0x1fe36fc,
|
|
0x1287d50,0x131d1ab,0x1d7815c,0x0b535de,0x092fa92,0x0df92bc,
|
|
0x0e743a5,0x1a7be0e,0x0111847 } },
|
|
/* 180 */
|
|
{ { 0x0c82924,0x1ce63ff,0x15a54aa,0x134e441,0x1c76dd6,0x1778710,
|
|
0x09f7a81,0x0094c6a,0x0271839,0x19f28e1,0x001f22a,0x0bd4e2d,
|
|
0x06f4db3,0x1a47892,0x0fb7829,0x0c12b1e,0x0444115,0x178a49b,
|
|
0x1d2ce37,0x0b07a30,0x00f75f6 },
|
|
{ 0x1927eb7,0x0c4f085,0x049e8e4,0x1385c5e,0x087c635,0x14b37a5,
|
|
0x108cdff,0x10a16e5,0x0105e55,0x015c1c1,0x10e7e44,0x000dcb1,
|
|
0x0963fee,0x0c8da99,0x014bb8e,0x1f2f67e,0x14ccbaf,0x03fadc2,
|
|
0x1e01418,0x1cbed8b,0x016a935 } },
|
|
/* 181 */
|
|
{ { 0x1d88d38,0x101aaef,0x1d03c66,0x078a93b,0x155cd8e,0x080370a,
|
|
0x0a78c13,0x1cc644e,0x0fd0b0c,0x0b5b836,0x0ab4c7c,0x18126be,
|
|
0x1ff156d,0x1bd1efc,0x031484f,0x0bf6b66,0x092a55e,0x14f94e6,
|
|
0x0e16368,0x19fba85,0x0144a0e },
|
|
{ 0x0658a92,0x08aefa9,0x185ad70,0x0f88502,0x1ce3ed1,0x0c9548d,
|
|
0x17dc1ff,0x12d4ab2,0x19cd5d8,0x11e45fe,0x11cac59,0x087eb52,
|
|
0x1d07763,0x1819f0d,0x19132a2,0x005f629,0x1861e5c,0x113d0e4,
|
|
0x113fecc,0x01e5899,0x01b5ece } },
|
|
/* 182 */
|
|
{ { 0x1211943,0x13dd598,0x09705c4,0x0cad086,0x04a8cac,0x0afe1f2,
|
|
0x02e2361,0x14ba5fc,0x0ce91ee,0x1d5d586,0x11f4491,0x1b88f1d,
|
|
0x1a5d23d,0x066cff7,0x061b79c,0x0aecd47,0x0678265,0x11963dc,
|
|
0x1abb1fe,0x080317d,0x00873e5 },
|
|
{ 0x18d17c1,0x1437959,0x103725b,0x18e3f40,0x1cbfbd0,0x024ce5c,
|
|
0x0ade7e2,0x017c223,0x0f71ec8,0x0a3e2e7,0x025a487,0x17828d9,
|
|
0x11acaa3,0x1e98b19,0x0487038,0x0ecb6bf,0x01ee768,0x018fd04,
|
|
0x07bfc9c,0x15fabe8,0x00fed5d } },
|
|
/* 183 */
|
|
{ { 0x0da1348,0x085cea6,0x04ea2bc,0x044b860,0x10769fd,0x0be115d,
|
|
0x096c625,0x1888a15,0x1f5acf1,0x057eb63,0x1e00a57,0x02813fd,
|
|
0x1dcf71a,0x17044fa,0x080a7d7,0x05751c2,0x0fb0fbd,0x04ba954,
|
|
0x1dc32d6,0x044ebed,0x009061e },
|
|
{ 0x1bda16a,0x125628f,0x0a8adc2,0x13e3bf4,0x19910e7,0x0a2fb7b,
|
|
0x184cb66,0x1df7459,0x0eb4ba4,0x086acd7,0x0b54f51,0x136697e,
|
|
0x086a8e0,0x131063d,0x0040813,0x18de8ec,0x03d0a53,0x131fc4a,
|
|
0x1fabd5a,0x123a330,0x013214c } },
|
|
/* 184 */
|
|
{ { 0x10d66c3,0x1d89024,0x0813953,0x1141b90,0x0aed732,0x1a14a6f,
|
|
0x130e012,0x0cf7402,0x131ddc4,0x197d155,0x0bb444f,0x0bd5068,
|
|
0x0e70ff5,0x1181a70,0x0369cbc,0x1c78363,0x1bebd8a,0x156e186,
|
|
0x1a51680,0x17bede7,0x009c179 },
|
|
{ 0x084c26f,0x09477ba,0x0ec51b2,0x03de55b,0x006b7db,0x0c6ed39,
|
|
0x1d520fd,0x16c110f,0x04bc7ed,0x0f27106,0x12bf73f,0x043b2eb,
|
|
0x00484d1,0x035f761,0x0d659c2,0x1b6cf8b,0x088a6d6,0x05abcd5,
|
|
0x0461d22,0x0db0fc8,0x001522c } },
|
|
/* 185 */
|
|
{ { 0x071d4ae,0x083abe2,0x09d82a2,0x0a8743b,0x1ef4b1a,0x1380d0f,
|
|
0x0c609aa,0x1277125,0x059c65f,0x1a6a729,0x077cd6f,0x1253af1,
|
|
0x12923af,0x05bce1f,0x12d1b18,0x1e26079,0x0e7cf4c,0x04aac16,
|
|
0x15fc3b1,0x0103684,0x011c7da },
|
|
{ 0x0eef274,0x03572cd,0x020fe4b,0x1e286f8,0x06c5bf4,0x1e4357f,
|
|
0x0c08f84,0x0c154e9,0x02a2253,0x10ed673,0x027e974,0x057044b,
|
|
0x0fb3d57,0x0fd3a58,0x128e45b,0x123527a,0x0dcb128,0x0f3b66c,
|
|
0x07d33ef,0x12347eb,0x019aa03 } },
|
|
/* 186 */
|
|
{ { 0x03fc3f1,0x1d34f10,0x08a4152,0x16c420d,0x09168cc,0x0afd4f8,
|
|
0x01502ab,0x0df6103,0x0bff7ed,0x05c7907,0x052bf7b,0x0c317df,
|
|
0x1b2c80a,0x1855e8e,0x1763282,0x014f9c4,0x041028e,0x13af33d,
|
|
0x1ba56e6,0x0cc5bba,0x01b2dd7 },
|
|
{ 0x089d7ee,0x1f93cf9,0x01721f7,0x13dd444,0x0d755d5,0x056d632,
|
|
0x1f55306,0x0335d61,0x17ec010,0x1462367,0x15c290e,0x1cfd691,
|
|
0x186fc90,0x0859cf7,0x1714f04,0x0b4412c,0x1cc3854,0x122abbb,
|
|
0x1f7408f,0x0861eea,0x016ea33 } },
|
|
/* 187 */
|
|
{ { 0x1f53d2c,0x19ca487,0x06e7ea7,0x0d60069,0x0dc9159,0x0cbcb3c,
|
|
0x1405356,0x115e214,0x1a8a6b7,0x0eb96d5,0x05ec413,0x0a8116a,
|
|
0x00ef5de,0x1369cdf,0x0ae42f2,0x0fee028,0x1e9eda1,0x0657551,
|
|
0x1acc446,0x0d13ac0,0x016da01 },
|
|
{ 0x06afff7,0x052b1fa,0x17cfa9b,0x14694bc,0x1945c7b,0x0cc7ec1,
|
|
0x19322aa,0x0bd83ff,0x0b63f53,0x15300a3,0x1427950,0x1111a3e,
|
|
0x1b50816,0x0fc6686,0x04636aa,0x0cee5a3,0x0bb78a3,0x13282f3,
|
|
0x131b719,0x0075033,0x01ef4ab } },
|
|
/* 188 */
|
|
{ { 0x176d986,0x04e8a69,0x16c0182,0x0f45b86,0x10f4e07,0x1f96436,
|
|
0x1c2694f,0x1903822,0x1123c3f,0x17a5d22,0x15bf0bf,0x0b4e36c,
|
|
0x1b852cd,0x0ff7d45,0x1f1d224,0x016ef6a,0x03e4811,0x0c7829c,
|
|
0x0b1684a,0x0ba75aa,0x004c4b5 },
|
|
{ 0x1827633,0x067f9f9,0x1a59444,0x0bc015f,0x086784d,0x16997d0,
|
|
0x1e208fa,0x10d9670,0x02b91cd,0x0e7a68b,0x0d8e28f,0x14b1cde,
|
|
0x02078b6,0x145bfea,0x1e4844b,0x107ce66,0x04dee56,0x1b4b202,
|
|
0x038a10c,0x08421e5,0x01223b8 } },
|
|
/* 189 */
|
|
{ { 0x1ebeb27,0x054d4e1,0x03e1b0a,0x0a7deb2,0x17bcdcb,0x173f9be,
|
|
0x0b84536,0x193d114,0x0726ea7,0x19a9172,0x104e200,0x070d182,
|
|
0x1599d50,0x10b10ab,0x0c6bb29,0x0c9b0b3,0x1ebfcc5,0x138cfe7,
|
|
0x0bae38d,0x0ef5e23,0x00433a5 },
|
|
{ 0x1eba922,0x1367037,0x1a4f0fc,0x1c8eb4a,0x1f6c83e,0x1f9bc72,
|
|
0x19d00a2,0x1e2fef2,0x0bdc3f6,0x152f1b4,0x1642bb4,0x14154dd,
|
|
0x153d034,0x0523e5e,0x070e931,0x0579076,0x06e4dce,0x1d27855,
|
|
0x132803a,0x0f5e86e,0x01c097c } },
|
|
/* 190 */
|
|
{ { 0x1c28de7,0x1b8bc3c,0x0c3000d,0x1557386,0x017aa2a,0x1e30f5b,
|
|
0x060999a,0x0088610,0x14d78b5,0x05adae7,0x03f1cb8,0x0a5b30e,
|
|
0x05d76a7,0x0a05bde,0x11a27d7,0x1a07476,0x06787f2,0x0d4bfec,
|
|
0x158182a,0x0f6bddf,0x01c06ab },
|
|
{ 0x1b71704,0x156d8ff,0x0ec7a67,0x16721fc,0x036e58b,0x078cd52,
|
|
0x0e0b2ad,0x1b9dd95,0x0e0f3d9,0x12496fd,0x02b44b6,0x097adc4,
|
|
0x022a0f5,0x1edde93,0x027e83d,0x1d6a95f,0x01ae8d2,0x06e6285,
|
|
0x1df41d6,0x13f02dd,0x00b7979 } },
|
|
/* 191 */
|
|
{ { 0x04f98cc,0x0323108,0x1aba7b1,0x04e55db,0x0511592,0x110c37a,
|
|
0x0f741f9,0x16cf5d2,0x08d6d69,0x0be7013,0x0ea3cf4,0x0c11fa8,
|
|
0x17b5347,0x1e055bc,0x1fc704d,0x1323bd0,0x1a8139f,0x11dfacb,
|
|
0x151f835,0x0750b7c,0x008de29 },
|
|
{ 0x0f668b1,0x156e9c7,0x1d90260,0x1ac2392,0x054e6b2,0x0ea131e,
|
|
0x1ac4870,0x0e679ce,0x0eff64e,0x09a5947,0x0584a8c,0x135850e,
|
|
0x14af71a,0x1d049ac,0x1222bca,0x011d063,0x112ba91,0x105b248,
|
|
0x13d0df6,0x178b8ab,0x01138fe } },
|
|
/* 192 */
|
|
{ { 0x0a2daa2,0x052c4e2,0x0231fa7,0x18801ec,0x18ea703,0x0ba8818,
|
|
0x1416354,0x052df19,0x04abb6f,0x1249a39,0x05aad09,0x07c3285,
|
|
0x1d0be55,0x1628b2b,0x1e4e63e,0x01d5135,0x0ec4f88,0x0f1196f,
|
|
0x1ec786c,0x02ec3cc,0x01372f8 },
|
|
{ 0x020f662,0x0a5e39d,0x1409440,0x1893db2,0x1fb7e77,0x15cb290,
|
|
0x025bed8,0x0fd13ea,0x1a2e8d3,0x132ce33,0x105c38e,0x144cb00,
|
|
0x140f2b2,0x0f6a851,0x1d3f39a,0x1801e2c,0x17efdc3,0x1d55229,
|
|
0x13a6764,0x077fb49,0x0198f3c } },
|
|
/* 193 */
|
|
{ { 0x1614189,0x0fae6c0,0x07deeac,0x0a4964b,0x07d56c4,0x1da0af6,
|
|
0x092c917,0x1f38f75,0x07af6be,0x015e46e,0x123a08c,0x01c0e96,
|
|
0x1f91b77,0x0db68d8,0x04cdb82,0x0192e94,0x157e668,0x0942e09,
|
|
0x1f32d89,0x1970278,0x012d59b },
|
|
{ 0x0019927,0x0c1da3e,0x156f76b,0x0ec61bf,0x010f266,0x102e91f,
|
|
0x1b168c7,0x0c02bb7,0x0456ac4,0x15372fd,0x12b208a,0x0a52487,
|
|
0x0946956,0x06e464f,0x07271fd,0x080cb8d,0x009e24a,0x1d6d93f,
|
|
0x1904c06,0x0f469d5,0x01ccdfa } },
|
|
/* 194 */
|
|
{ { 0x1cb1a7d,0x14326ac,0x03b85da,0x06d5df7,0x0d864ca,0x11586c2,
|
|
0x0eb2c70,0x03a1dd0,0x1d980df,0x1405375,0x133b65f,0x1988ff2,
|
|
0x15f582a,0x1d39608,0x073448c,0x0f76f45,0x0a8c710,0x0670951,
|
|
0x1b6028c,0x1394ac9,0x0150022 },
|
|
{ 0x11c180b,0x05d6a97,0x08425dd,0x11ae935,0x108be99,0x0de8dd6,
|
|
0x122ad5b,0x1352f18,0x00afbea,0x169f1f2,0x1717f1b,0x12f62a7,
|
|
0x108a8be,0x0df49f6,0x11fc256,0x0477b5b,0x1082cee,0x1469214,
|
|
0x109ca77,0x0a478db,0x0016417 } },
|
|
/* 195 */
|
|
{ { 0x014a31e,0x16678b6,0x10b5d3b,0x0965bc7,0x088e253,0x1621e1a,
|
|
0x0d665f3,0x06df376,0x1916ac9,0x10822ce,0x1910010,0x18053ef,
|
|
0x0371d15,0x022a9ac,0x071f049,0x148cf19,0x08dec94,0x0e64baa,
|
|
0x059eeb6,0x0cf0306,0x014e4ca },
|
|
{ 0x10312bf,0x1782ac6,0x19980ce,0x0aa82c3,0x1d1bf4f,0x00bc0ed,
|
|
0x1169fe9,0x1aa4b32,0x000eef1,0x1a4a6d4,0x0ee340c,0x1d80f38,
|
|
0x096c505,0x0e4fb73,0x0b86b78,0x01554e1,0x0c17683,0x0014478,
|
|
0x18a8183,0x19fc774,0x000c7f4 } },
|
|
/* 196 */
|
|
{ { 0x17d6006,0x1a23e82,0x02c0362,0x0dfae39,0x18b976e,0x07a07a9,
|
|
0x180a6af,0x106bcef,0x0f103a7,0x1df71c3,0x1cb12c4,0x1840bc8,
|
|
0x1420a6a,0x18fe58c,0x0c117d8,0x17e9287,0x19fc00a,0x0f2ee0e,
|
|
0x1555ade,0x0178e14,0x01b528c },
|
|
{ 0x08640b8,0x083f745,0x004aea7,0x07a1c68,0x0561102,0x1257449,
|
|
0x1956ef8,0x19b8f9c,0x0fa579d,0x1ac7292,0x0eff978,0x0e2a6ef,
|
|
0x0457ce2,0x1e04a3f,0x19471b0,0x0f04cc8,0x150f4a9,0x12fdec6,
|
|
0x0b87056,0x1ba51fc,0x008d6fc } },
|
|
/* 197 */
|
|
{ { 0x07202c8,0x0517b2e,0x0362d59,0x04b4a96,0x1d63405,0x1a7dfab,
|
|
0x159c850,0x1470829,0x01d9830,0x08a10af,0x03ef860,0x11aabde,
|
|
0x1fc7a75,0x137abfc,0x01773e3,0x0d3a6ae,0x056d922,0x1aeea4d,
|
|
0x16d27e5,0x02baf57,0x00f18f0 },
|
|
{ 0x0799ce6,0x188885a,0x1f6c1c4,0x1259796,0x15bbfb9,0x1d10f11,
|
|
0x0327fde,0x1fd83e0,0x1b18f49,0x04eb489,0x1e566c0,0x12a3579,
|
|
0x0e8da61,0x06a10a3,0x1a1c84c,0x047e21c,0x017ae5f,0x1aac194,
|
|
0x0b9ce1a,0x0b76d13,0x0143c9b } },
|
|
/* 198 */
|
|
{ { 0x0c74424,0x1946da4,0x0bad08c,0x03a3396,0x12616e1,0x0b710b9,
|
|
0x064a903,0x0a5ca68,0x00cbdc7,0x0c1d4a6,0x0eec077,0x00a1ae6,
|
|
0x005c623,0x0dbd229,0x0358c69,0x023919a,0x0259a40,0x0e66e05,
|
|
0x11b9f35,0x022598c,0x01e622f },
|
|
{ 0x01e4c4b,0x1714d1f,0x12291f5,0x113f62a,0x15f8253,0x09f18ce,
|
|
0x016d53f,0x0ccfc6e,0x00a08b9,0x02672cd,0x0fa36e3,0x13cfb19,
|
|
0x15bca74,0x17761eb,0x1125baa,0x0627b98,0x03a8a1a,0x00bee39,
|
|
0x13ae4d8,0x1feef51,0x01a5250 } },
|
|
/* 199 */
|
|
{ { 0x029bd79,0x103937f,0x0cd2956,0x009f321,0x0574a81,0x0ab4c1b,
|
|
0x051b6ab,0x1ded20d,0x150d41f,0x12c055c,0x1dfd143,0x0a28dcd,
|
|
0x0abc75b,0x1879b8c,0x03325ef,0x0810ea1,0x0a4a563,0x028dd16,
|
|
0x1936244,0x0720efc,0x017275c },
|
|
{ 0x17ca6bd,0x06657fb,0x17d7cdf,0x037b631,0x00a0df4,0x0f00fbf,
|
|
0x13fe006,0x0573e8d,0x0aa65d7,0x1279ea2,0x198fa6f,0x1158dc6,
|
|
0x0d7822d,0x1f7cedb,0x0dfe488,0x15354be,0x19dabe4,0x13f8569,
|
|
0x1a7322e,0x0af8e1e,0x0098a0a } },
|
|
/* 200 */
|
|
{ { 0x0fd5286,0x0867a00,0x00f3671,0x0ae5496,0x1ea5b9d,0x0d739f0,
|
|
0x03e7814,0x049ebcc,0x0951b38,0x14da8a1,0x13599ff,0x05a13f6,
|
|
0x16b034b,0x16e2842,0x14dea03,0x0045c96,0x0128cb0,0x134f708,
|
|
0x09522bb,0x173cb8d,0x00ed7c8 },
|
|
{ 0x133619b,0x003de6c,0x1865d18,0x1c573bf,0x0ce7668,0x1715170,
|
|
0x1574f31,0x05f53dd,0x17eebf3,0x0d0a7af,0x113d90d,0x131acf9,
|
|
0x0c75cb8,0x1c2860b,0x08617f1,0x1392d96,0x07645f7,0x004c3a5,
|
|
0x1f6d1d1,0x11f15c4,0x0139746 } },
|
|
/* 201 */
|
|
{ { 0x08684f6,0x13456e4,0x16ff177,0x16c334f,0x1c1edaa,0x1d0c7ab,
|
|
0x05cd6c9,0x1d64b1a,0x18ecd89,0x13f3db2,0x07dfaac,0x138db0f,
|
|
0x1b3d888,0x13eadf7,0x1f725b5,0x1ae7951,0x0ae37ba,0x1e426c3,
|
|
0x1a395b5,0x1232ed9,0x01a4c7e },
|
|
{ 0x119ffa6,0x0d2a031,0x0131400,0x18269d8,0x0cae64e,0x0092160,
|
|
0x0a5b355,0x1dc3ed3,0x0bf2cae,0x0d12cf7,0x1ba0167,0x0f18517,
|
|
0x0488e79,0x1c74487,0x1212fae,0x0ffb3d2,0x0d0fb22,0x0072923,
|
|
0x09758c6,0x054a94c,0x01b78be } },
|
|
/* 202 */
|
|
{ { 0x072f13a,0x1aaa57a,0x0472888,0x0eae67d,0x1ac993b,0x00b4517,
|
|
0x1a7c25b,0x06a4d5f,0x14b1275,0x07f3b0e,0x01c329f,0x10e7cee,
|
|
0x1684301,0x03f3e6f,0x0daaab7,0x05da8cd,0x1eaa156,0x06d16ea,
|
|
0x07ebe36,0x145c007,0x0016a81 },
|
|
{ 0x03de3bf,0x03ace27,0x022aa20,0x02a5e61,0x0c1e2e1,0x1f5d2d8,
|
|
0x1b66aa9,0x195965b,0x19f9c11,0x032eaa9,0x1170653,0x1b0f61b,
|
|
0x010ab9b,0x051fa5b,0x0be325b,0x0bf3fa6,0x1cc28cb,0x1a4c217,
|
|
0x0438877,0x1c4f997,0x00f431a } },
|
|
/* 203 */
|
|
{ { 0x00ccd0a,0x10506b5,0x1554eca,0x04b3276,0x03eeec8,0x1339535,
|
|
0x01bf677,0x19f6269,0x00da05d,0x0ce28a4,0x061d363,0x089ace7,
|
|
0x09c4aa4,0x114d1ae,0x13cd6cb,0x0fd5bb3,0x15f8917,0x0eb5ecd,
|
|
0x0811c28,0x01eb3a5,0x01d69af },
|
|
{ 0x07535fd,0x02263dd,0x1ce6cbe,0x1b5085f,0x05bd4c3,0x08cba5a,
|
|
0x127b7a5,0x1d8bfc2,0x1fd4453,0x0c174cb,0x0df039a,0x00bbcd8,
|
|
0x0aa63f7,0x0961f7b,0x0c3daa7,0x151ac13,0x1861776,0x05f6e9a,
|
|
0x17846de,0x1148d5d,0x0176404 } },
|
|
/* 204 */
|
|
{ { 0x1a251d1,0x03772a8,0x17f691f,0x041a4f3,0x1ef4bf1,0x08c5145,
|
|
0x14e33b1,0x0dc985a,0x13880be,0x195bc43,0x06c82c6,0x1f1c37d,
|
|
0x1ec69cc,0x1bcb50c,0x077fab8,0x17bd5c8,0x1c9fb50,0x012b3b7,
|
|
0x0f86030,0x02b40a0,0x016a8b8 },
|
|
{ 0x1f5ef65,0x042fb29,0x0414b28,0x12ef64a,0x01dfbbf,0x1a37f33,
|
|
0x01f8e8c,0x1df11d5,0x01b95f7,0x0eefef7,0x17abb09,0x1cd2b6c,
|
|
0x1b22074,0x0617011,0x01a6855,0x0776a23,0x17742e8,0x0c300da,
|
|
0x0a1df9f,0x08ca59f,0x0015146 } },
|
|
/* 205 */
|
|
{ { 0x1fa58f1,0x029e42b,0x19c0942,0x1099498,0x158a4e6,0x00fa06d,
|
|
0x1b4286e,0x17a0f72,0x0558e8c,0x0328f08,0x0e233e9,0x08dc85c,
|
|
0x081a640,0x0221b04,0x0c354e5,0x11fa0a3,0x1b3e26b,0x1615f9a,
|
|
0x1c0b3f3,0x0f0e12a,0x00fd4ae },
|
|
{ 0x153d498,0x0de14ef,0x1890f1e,0x1c226fe,0x0cf31c4,0x11e76fa,
|
|
0x015b05e,0x0bb276d,0x06cd911,0x030898e,0x03376c9,0x08a7245,
|
|
0x11ab30a,0x069015f,0x1dd5eda,0x10c25d2,0x07ce610,0x053336f,
|
|
0x1d809ad,0x01fcca9,0x0051c20 } },
|
|
/* 206 */
|
|
{ { 0x1a2b4b5,0x1081e58,0x05a3aa5,0x1d08781,0x18dccbf,0x17fdadc,
|
|
0x01cb661,0x184d46e,0x0169d3a,0x1d03d79,0x0dc7c4b,0x1734ee2,
|
|
0x0f8bb85,0x13e14cf,0x18434d3,0x05df9d5,0x069e237,0x09ea5ee,
|
|
0x17615bc,0x1beebb1,0x0039378 },
|
|
{ 0x07ff5d9,0x0817fef,0x0728c7a,0x0464b41,0x0e9a85d,0x0c97e68,
|
|
0x04e9bd0,0x167ae37,0x115b076,0x0952b9b,0x047473d,0x150cdce,
|
|
0x19d726a,0x1614940,0x186c77c,0x0bbcc16,0x15cc801,0x191272b,
|
|
0x02de791,0x1127c23,0x01dc68e } },
|
|
/* 207 */
|
|
{ { 0x1feda73,0x127fcb7,0x0062de4,0x0d41b44,0x0709f40,0x0ac26ff,
|
|
0x083abe2,0x0806d1c,0x08355a0,0x04a8897,0x1df5f00,0x0a51fae,
|
|
0x08259d4,0x15fc796,0x1125594,0x0623761,0x12844c5,0x0bfb18c,
|
|
0x119b675,0x1a1c9f0,0x00d5698 },
|
|
{ 0x15d204d,0x0b27d00,0x114f843,0x14dba21,0x1b626bf,0x14c64a3,
|
|
0x0398e9d,0x0ac10ff,0x105337a,0x12d32a3,0x11e0bd4,0x0489beb,
|
|
0x1f558e2,0x02afdd7,0x0a87906,0x0706091,0x18e47ee,0x1a47910,
|
|
0x0e118f4,0x0472b22,0x004df25 } },
|
|
/* 208 */
|
|
{ { 0x0695310,0x07eb4ec,0x03a9dbd,0x1efd0ed,0x028eb09,0x0a99547,
|
|
0x0604b83,0x0f20738,0x0c572ac,0x0d33ba2,0x158a4f7,0x01c0f0b,
|
|
0x121f980,0x1ed3b5d,0x1f8a968,0x0e42e57,0x190a2bc,0x13768ad,
|
|
0x05e22a3,0x1cc37fa,0x004cd80 },
|
|
{ 0x0730056,0x001b80b,0x150ee7d,0x1fb9da7,0x06f45fe,0x1283a12,
|
|
0x1d8f06a,0x0e615fa,0x0ff92ae,0x0f2e329,0x0818fc8,0x061a376,
|
|
0x006ef08,0x096912a,0x0c1bb30,0x0003830,0x13a1f15,0x0276ecd,
|
|
0x0331509,0x164b718,0x01f4e4e } },
|
|
/* 209 */
|
|
{ { 0x1db5c18,0x0d38a50,0x1d33b58,0x1cecee0,0x1454e61,0x1b42ef4,
|
|
0x1ef95ef,0x1cbd2e1,0x1d2145b,0x10d8629,0x0697c88,0x1037dc9,
|
|
0x03b9318,0x0a588e8,0x0e46be8,0x0426e01,0x0493ec2,0x1e3577f,
|
|
0x098802b,0x0a9d28a,0x013c505 },
|
|
{ 0x164c92e,0x022f3b9,0x03a350b,0x0ae6a43,0x0050026,0x09f9e2f,
|
|
0x1680a13,0x0d7a503,0x0dbf764,0x097c212,0x1cc13cc,0x1e5490b,
|
|
0x13e1a88,0x0893d28,0x0fd58c4,0x1c178b0,0x0c71a60,0x076bca8,
|
|
0x0dedc29,0x0abc209,0x00c6928 } },
|
|
/* 210 */
|
|
{ { 0x04614e7,0x10c2e32,0x1092341,0x1c8e934,0x0e906ca,0x03f2941,
|
|
0x04ba896,0x19ab0a8,0x0d12857,0x1b1cc85,0x164ed4d,0x1ee174a,
|
|
0x06770c7,0x0eae952,0x13db713,0x1437585,0x0563b69,0x12b26d2,
|
|
0x01e2576,0x1efc283,0x01c8639 },
|
|
{ 0x0589620,0x0b5817c,0x0150172,0x0683c88,0x0fe468a,0x15684e1,
|
|
0x1684425,0x1dd7e45,0x09c652a,0x039e14c,0x186e3ef,0x1f16a8f,
|
|
0x13cdef9,0x0bbedfb,0x1cde16a,0x0aa5ae0,0x1aa7e13,0x1854950,
|
|
0x08e4f4f,0x0c22807,0x015b227 } },
|
|
/* 211 */
|
|
{ { 0x1bfaf32,0x0d3d80f,0x1486269,0x017ccc3,0x1c5a62d,0x11da26a,
|
|
0x03d7bd7,0x0c48f2e,0x1f43bbf,0x15000f6,0x0b9680f,0x050a4c1,
|
|
0x0ca8e74,0x134be31,0x0267af4,0x0ec87d7,0x1e6751a,0x11b5001,
|
|
0x081c969,0x0f18a37,0x00eaef1 },
|
|
{ 0x1d51f28,0x1c74fcd,0x0112ab3,0x1750e24,0x19febbd,0x1e41b29,
|
|
0x0b4e96f,0x11f0f01,0x110e6f0,0x0451a66,0x06ac390,0x1421048,
|
|
0x018104c,0x0c53315,0x0f9c73a,0x091ad08,0x1142320,0x1cee742,
|
|
0x13cf461,0x14477c3,0x01fa5cb } },
|
|
/* 212 */
|
|
{ { 0x173a15c,0x064e914,0x07ccbfa,0x1ba852f,0x06fec8d,0x157d9f3,
|
|
0x128e42d,0x044735e,0x0ab65ef,0x1d8f21b,0x17f36c2,0x003ccd8,
|
|
0x0b8f262,0x0d7a438,0x1ffa28d,0x09c4879,0x06f2bb4,0x132d714,
|
|
0x07745c8,0x1c5074a,0x0114da2 },
|
|
{ 0x1e3d708,0x04d2b60,0x1e992a7,0x1e3961d,0x0fe62d3,0x143aa02,
|
|
0x0a6125f,0x1f5e0e0,0x13cea46,0x1c5beb5,0x01898c4,0x069d071,
|
|
0x0907806,0x18e1848,0x1a10a01,0x10c8e4f,0x1d7e583,0x1f857bc,
|
|
0x08da899,0x10cb056,0x0104c1b } },
|
|
/* 213 */
|
|
{ { 0x126c894,0x184f6d2,0x148ccbf,0x002958f,0x15abf12,0x0c949a4,
|
|
0x13734f3,0x0ad6df2,0x092e6b5,0x1d57589,0x1b0c6ff,0x0dd4206,
|
|
0x0e19379,0x183ff99,0x148df9d,0x0cf7153,0x10d829d,0x1eb2d2d,
|
|
0x0ca4922,0x1b6aadb,0x01b348e },
|
|
{ 0x0d46575,0x0fcd96f,0x0b3dbba,0x15ff4d3,0x096ca08,0x169be8a,
|
|
0x0ce87c5,0x003ab5d,0x1789e5d,0x1283ed8,0x1f31152,0x1c53904,
|
|
0x1705e2c,0x14b2733,0x0db9294,0x08de453,0x0ba4c0e,0x082b1d8,
|
|
0x0f11921,0x1848909,0x00a3e75 } },
|
|
/* 214 */
|
|
{ { 0x0f6615d,0x1a3b7e9,0x06a43f2,0x11b31b5,0x0b7f9b7,0x1ef883a,
|
|
0x17c734a,0x063c5fb,0x09b956f,0x1ed1843,0x1bab7ca,0x05ef6b2,
|
|
0x18f3cca,0x1aad929,0x1027e2c,0x08db723,0x0f3c6c8,0x12379fb,
|
|
0x085190b,0x12731c5,0x01ff9bb },
|
|
{ 0x17bd645,0x06a7ad0,0x1549446,0x17b7ada,0x17033ea,0x0684aba,
|
|
0x01bf1cd,0x06a00fd,0x15f53c4,0x065032f,0x1f74666,0x137ffa4,
|
|
0x0a9949d,0x14a968e,0x1138c11,0x02039bb,0x0fb81ac,0x1c2655a,
|
|
0x095ac01,0x00f3f29,0x000346d } },
|
|
/* 215 */
|
|
{ { 0x0bfdedd,0x1c727d3,0x1be657a,0x1cf4e98,0x193a285,0x04d1294,
|
|
0x15344f4,0x0cf17ab,0x019a5f7,0x15085f3,0x0ecd03a,0x107c19d,
|
|
0x03d3db0,0x0edfbd4,0x0ce9e2c,0x047c38c,0x03ec30f,0x093325e,
|
|
0x1e820de,0x01f1e20,0x01c9663 },
|
|
{ 0x0f86a80,0x065a5ef,0x06aeefd,0x107f04b,0x1fa4ec7,0x0a99640,
|
|
0x1d81182,0x125497e,0x08b909e,0x0ddbd66,0x010581c,0x062e2f1,
|
|
0x08ca1d7,0x050d5c9,0x1fc52fb,0x0ab4afe,0x16e5f84,0x0dff500,
|
|
0x1c87a26,0x18ed737,0x002d7b8 } },
|
|
/* 216 */
|
|
{ { 0x19f8e7d,0x102b1a5,0x02a11a1,0x0ec7f8b,0x001176b,0x176b451,
|
|
0x169f8bf,0x121cf4b,0x0651831,0x033bb1f,0x1deb5b3,0x0205d26,
|
|
0x017d7d0,0x1b81919,0x1f11c81,0x16a0b99,0x031534b,0x0ab9f70,
|
|
0x1c689da,0x03df181,0x00f31bf },
|
|
{ 0x0935667,0x1ae2586,0x0e2d8d7,0x120c1a5,0x14152c3,0x01d2ba3,
|
|
0x0b0b8df,0x19bdff5,0x00b72e0,0x0afe626,0x18091ff,0x1373e9e,
|
|
0x13b743f,0x1cf0b79,0x10b8d51,0x1df380b,0x0473074,0x1d111a6,
|
|
0x056ab38,0x05e4f29,0x0124409 } },
|
|
/* 217 */
|
|
{ { 0x10f9170,0x0bc28d9,0x16c56ff,0x126ff9c,0x115aa1e,0x021bdcb,
|
|
0x157824a,0x0e79ffa,0x1c32f12,0x056692c,0x1878d22,0x19e4917,
|
|
0x0b5a145,0x1d2de31,0x0d02181,0x0de8c74,0x1151815,0x1b14b75,
|
|
0x1dd3870,0x1f5a324,0x01e7397 },
|
|
{ 0x08225b5,0x1ccfa4e,0x1134d8b,0x128d6ef,0x13efce4,0x00f48d9,
|
|
0x1d4c215,0x1268a3b,0x038f3d6,0x1e96c9a,0x1ed5382,0x05adce4,
|
|
0x000b5de,0x1b116ca,0x164a709,0x1529685,0x12356f6,0x09b5673,
|
|
0x132bc81,0x0319abf,0x004464a } },
|
|
/* 218 */
|
|
{ { 0x1a95d63,0x10555d5,0x11b636f,0x02f6966,0x12780c6,0x06c0a14,
|
|
0x1e18c38,0x098c861,0x0b56ef0,0x1adf015,0x18d8ce1,0x172af0b,
|
|
0x04c28fe,0x009649f,0x1005e57,0x10547aa,0x1c1e36f,0x144ffa8,
|
|
0x03babf5,0x11912a2,0x016b3c4 },
|
|
{ 0x0f064be,0x03f5d6a,0x0a65e4a,0x0aa9d7b,0x1a77d55,0x1b93f50,
|
|
0x17bc988,0x18c8ce8,0x189f366,0x088fac8,0x15baf6a,0x0b9b8b3,
|
|
0x137e543,0x1a92690,0x0136ba9,0x1671a75,0x11c4395,0x0e3d8ee,
|
|
0x0a08f12,0x07ce083,0x001cca1 } },
|
|
/* 219 */
|
|
{ { 0x14d64b0,0x0c30643,0x18318e6,0x042ca79,0x1375b09,0x108cc31,
|
|
0x00003aa,0x0ba2ce0,0x1621cd1,0x1633c84,0x1c37358,0x1bacefa,
|
|
0x0dbe1d7,0x182dea6,0x1c3c9c0,0x11e61df,0x021362f,0x003b763,
|
|
0x19116de,0x00902cf,0x01d8812 },
|
|
{ 0x01f9758,0x04d070b,0x138a05d,0x1d4789f,0x060915f,0x0eec57f,
|
|
0x1390644,0x013ea6f,0x079a51a,0x11b5456,0x173e3bf,0x0968594,
|
|
0x1567fb5,0x12482bf,0x172b81f,0x096c837,0x0c5a424,0x1db8ff8,
|
|
0x0d81960,0x0b4a6c9,0x0106481 } },
|
|
/* 220 */
|
|
{ { 0x139cc39,0x14e1f77,0x1b45e31,0x09f4c6a,0x1830456,0x17dcc84,
|
|
0x0d50904,0x14b7a78,0x179dbb2,0x0ea98e9,0x1d78f68,0x0311cfc,
|
|
0x114865f,0x0580a3d,0x0b13888,0x135605b,0x1ca33d2,0x1facf28,
|
|
0x1ec1d3b,0x09effc6,0x00f1c96 },
|
|
{ 0x0301262,0x0605307,0x08b5c20,0x00a7214,0x1a45806,0x054814c,
|
|
0x1fe6b32,0x185b4ce,0x114c0f1,0x1d7482b,0x1b67df7,0x1e2cdcc,
|
|
0x043665f,0x03c2349,0x19b7631,0x060f990,0x18fc4cc,0x062d7f4,
|
|
0x02fd439,0x0774c7c,0x003960e } },
|
|
/* 221 */
|
|
{ { 0x19ecdb3,0x0289b4a,0x06f869e,0x0ff3d2b,0x089af61,0x106e441,
|
|
0x0cae337,0x02aa28b,0x07c079e,0x1483858,0x089057f,0x09a6a1c,
|
|
0x02f77f0,0x1ac6b6a,0x0adcdc8,0x0c53567,0x1b9ba7b,0x08a7ea0,
|
|
0x1003f49,0x05b01ce,0x01937b3 },
|
|
{ 0x147886f,0x006a6b8,0x072b976,0x02aed90,0x008ced6,0x138bddf,
|
|
0x01a4990,0x043c29d,0x0abb4bd,0x0e6f8cc,0x00c22e7,0x0c8cca6,
|
|
0x07658be,0x0cce8ce,0x1c64b6b,0x1624df7,0x1b3304a,0x0aad1e8,
|
|
0x089378c,0x1e97cbf,0x000e943 } },
|
|
/* 222 */
|
|
{ { 0x1e9ea48,0x1202c3f,0x121b150,0x0ac36ae,0x0f24f82,0x18cba05,
|
|
0x104f1e1,0x09b3a58,0x170eb87,0x1d4df3c,0x0e8ea89,0x11c16c5,
|
|
0x0c43fef,0x160df85,0x08fca18,0x061c214,0x0f34af1,0x1a8e13b,
|
|
0x19573af,0x1a3d355,0x0185f6c },
|
|
{ 0x0369093,0x17d3fa0,0x1828937,0x0cb0b03,0x11f1d9d,0x0976cf0,
|
|
0x0fccf94,0x12d3201,0x1ed1208,0x1c5422c,0x0f0e66f,0x0abd16e,
|
|
0x1e83245,0x07b7aa7,0x08c15a6,0x046aaa9,0x1a53c25,0x0954eb6,
|
|
0x0824ecc,0x0df2085,0x016ae6a } },
|
|
/* 223 */
|
|
{ { 0x12cdd35,0x091e48a,0x1bc6cb8,0x110c805,0x0e6e43a,0x072dead,
|
|
0x1c37ee7,0x0291257,0x0758049,0x0565c25,0x0bbb0ad,0x0bffea0,
|
|
0x0e8c7f5,0x1519f7a,0x029ee4e,0x0400339,0x157fd9d,0x1835881,
|
|
0x0e8ef3a,0x033fe01,0x00273e3 },
|
|
{ 0x1e360a3,0x017bbd5,0x129860b,0x095bfdf,0x17ef5c8,0x05b7e62,
|
|
0x0329994,0x005349e,0x0aaf0b2,0x1a7c72b,0x1bc558f,0x1141449,
|
|
0x135c850,0x0f522f8,0x1d8bf64,0x0db7db1,0x1a02803,0x1f96491,
|
|
0x093440e,0x1949803,0x018a4a9 } },
|
|
/* 224 */
|
|
{ { 0x048e339,0x1dbcc2a,0x05d8a8f,0x1e31473,0x1e8770c,0x148b866,
|
|
0x15d35e9,0x15822c0,0x12b6067,0x1d82e2c,0x04e2ad2,0x1b61090,
|
|
0x14de0d2,0x0484f3c,0x076ae49,0x02bee29,0x0b67903,0x041d19b,
|
|
0x0cd6896,0x00e9b34,0x013ccd9 },
|
|
{ 0x01b784d,0x0e2f056,0x0b87a0e,0x0ddca4f,0x0b65c8c,0x0447605,
|
|
0x1851a87,0x0b1a790,0x046c1bf,0x100fbc8,0x0940a88,0x0c4e7fb,
|
|
0x0571cec,0x112dc83,0x0fe23ac,0x1bf9bfe,0x098c556,0x0360f86,
|
|
0x013e973,0x0445549,0x00acaa3 } },
|
|
/* 225 */
|
|
{ { 0x1b4dfd6,0x1a5e1e4,0x0a4c5f9,0x07f1cec,0x05ba805,0x061a901,
|
|
0x1701676,0x168060f,0x0b85a20,0x0481b66,0x1c4d647,0x1e14470,
|
|
0x0ef2c63,0x054afda,0x0676763,0x18d8c35,0x1399850,0x01ebe27,
|
|
0x00a659a,0x12d392d,0x0169162 },
|
|
{ 0x163ee53,0x1e133e5,0x0d4df44,0x02ebd58,0x07b12e6,0x0d5fe53,
|
|
0x0684464,0x13f666d,0x1ee1af6,0x168324e,0x10479d6,0x1e0023b,
|
|
0x054d7a6,0x0dcfcbb,0x1c0c2e3,0x0266501,0x1a3f0ab,0x1510000,
|
|
0x0763318,0x1931a47,0x0194e17 } },
|
|
/* 226 */
|
|
{ { 0x18fe898,0x0c05a0e,0x14d1c83,0x0e64308,0x0d7a28b,0x190ba04,
|
|
0x10e1413,0x15fe3e7,0x1166aa6,0x09c0e6a,0x1838d57,0x010998a,
|
|
0x0d9cde6,0x0f30f16,0x0107c29,0x12a3596,0x0f5d9b4,0x031088b,
|
|
0x1b8ab0b,0x1c2da6f,0x00c4509 },
|
|
{ 0x06fd79e,0x1106216,0x0c3ae0a,0x1c75ef1,0x15b7ee4,0x0c0ce54,
|
|
0x18f06eb,0x0d27b36,0x0985525,0x06b3a6f,0x06743c4,0x0965f38,
|
|
0x0917de6,0x03e2f35,0x0feaebd,0x1b6df40,0x0ad2ce2,0x142c5e2,
|
|
0x1f27463,0x0470143,0x00c976c } },
|
|
/* 227 */
|
|
{ { 0x064f114,0x18f7c58,0x1d32445,0x0a9e5e1,0x03cb156,0x19315bc,
|
|
0x161515e,0x0d860a4,0x10f3493,0x1463380,0x107fb51,0x05fd334,
|
|
0x09ef26d,0x13fbfb5,0x168899e,0x1f837ed,0x0dba01b,0x012b1dc,
|
|
0x0d03b50,0x06d90b8,0x000e14b },
|
|
{ 0x1db67e6,0x1f13212,0x017d795,0x12fe5d2,0x05df4e8,0x1621344,
|
|
0x1945009,0x126f065,0x03e8750,0x095f131,0x0e1a44c,0x17b078a,
|
|
0x1d856b5,0x0ab9a7c,0x072b956,0x090c2b6,0x1e2d5aa,0x02d03df,
|
|
0x1a2aed6,0x192de19,0x01d07a4 } },
|
|
/* 228 */
|
|
{ { 0x03aa2e9,0x0a682a9,0x0181efd,0x19da7a1,0x08841e0,0x0dfdb4e,
|
|
0x1db89fe,0x10aad07,0x0162bdf,0x0583fa2,0x0373277,0x10720f6,
|
|
0x0e62d17,0x12bd29b,0x12ee2ad,0x0fa7945,0x0d27cf4,0x04c5cd0,
|
|
0x1ba98dc,0x0a9ad0b,0x01f2ff1 },
|
|
{ 0x0b232ac,0x1bb452b,0x0aad5a2,0x0c7e54a,0x0e8d6e3,0x1bfe302,
|
|
0x1e85a20,0x12375d0,0x1d10a76,0x1e2c541,0x157efba,0x15e1f28,
|
|
0x0ead5e4,0x1eb2a71,0x0835b0d,0x104aa34,0x0b9da7c,0x0c6207e,
|
|
0x0366e4c,0x1679aec,0x00b26d7 } },
|
|
/* 229 */
|
|
{ { 0x12eaf45,0x0861f5d,0x04bdec2,0x18c5ff7,0x0d24d91,0x1b791ef,
|
|
0x0fa929c,0x1c77e54,0x16ff0fd,0x0dccf5e,0x040bd6d,0x0abb942,
|
|
0x08bca2b,0x03f0195,0x080f360,0x02f51ec,0x048a8bf,0x0aa085a,
|
|
0x077156c,0x0cc14fc,0x0109b86 },
|
|
{ 0x0a2fbd8,0x058ed01,0x0296c52,0x167645d,0x1ed85e8,0x095a84f,
|
|
0x083921c,0x02c26f1,0x0c6a3e5,0x02b00a4,0x0ed40da,0x04382c6,
|
|
0x1171009,0x12a8938,0x049450c,0x0208f27,0x1d207d3,0x1bda498,
|
|
0x150b82e,0x1ce4570,0x00ea623 } },
|
|
/* 230 */
|
|
{ { 0x0972688,0x011e992,0x1d88212,0x04007ea,0x18b83c1,0x06a2942,
|
|
0x19a41b4,0x0fc329a,0x02c6f74,0x010cac2,0x1b626a1,0x05d2028,
|
|
0x02c8f8a,0x1a28dde,0x1b0779d,0x109f453,0x0b8f7f2,0x1fb115b,
|
|
0x0dc7913,0x03b7d2f,0x006083f },
|
|
{ 0x19dd56b,0x04999cc,0x17a6659,0x152f48f,0x0cfac0b,0x147d901,
|
|
0x162baef,0x194ccc1,0x0f61d7b,0x1e14eec,0x1705351,0x0a3b0b5,
|
|
0x1c6f5fb,0x07cfea0,0x16b1e21,0x07cd9cc,0x1d4ff51,0x10e734e,
|
|
0x1f9674f,0x1cb23df,0x00231ac } },
|
|
/* 231 */
|
|
{ { 0x1fda771,0x1d21c54,0x0038b99,0x190cc62,0x026f652,0x19f91db,
|
|
0x0792384,0x03fbf63,0x0035d2d,0x0cfc479,0x0fa1e16,0x02251a2,
|
|
0x071723a,0x1da8e70,0x02a8a4b,0x1750512,0x10ebbd9,0x072f9d3,
|
|
0x1d1452d,0x104ce66,0x0155dde },
|
|
{ 0x0f59a95,0x15bbf6b,0x108022c,0x0604040,0x13f853e,0x163bcbc,
|
|
0x0ab07ae,0x0eca44a,0x1b56b66,0x166e5cc,0x0a9401b,0x13f32e4,
|
|
0x104abdb,0x02715d6,0x0843cfc,0x1ba9a4c,0x0ff3034,0x08652d0,
|
|
0x0b02e03,0x1b0101b,0x0041333 } },
|
|
/* 232 */
|
|
{ { 0x1a85a06,0x083849a,0x0d13a14,0x0c85de3,0x0e166e7,0x1d9d36a,
|
|
0x02dc681,0x0d50952,0x030329e,0x16eb600,0x1549675,0x14ca7aa,
|
|
0x1e20c4b,0x17c5682,0x0ec9abd,0x1999bdc,0x1412ab4,0x01071ea,
|
|
0x0501909,0x1312695,0x01bd797 },
|
|
{ 0x00c7ff0,0x0e8c247,0x0d03ca8,0x192a876,0x1ae85ef,0x0e98c5d,
|
|
0x0c6bbd4,0x14dd2c8,0x075878f,0x0e9f6a7,0x057d4b9,0x13b7851,
|
|
0x1c4d2a2,0x0f88833,0x1c9e1dc,0x09dca75,0x1649e7f,0x13666f4,
|
|
0x15b5d36,0x111b434,0x0192351 } },
|
|
/* 233 */
|
|
{ { 0x1d310ed,0x1909001,0x0c46c20,0x1930f60,0x120ee8c,0x02ac546,
|
|
0x0749a13,0x1913ca9,0x0b7167e,0x112f9e7,0x156ed57,0x09e897e,
|
|
0x17acf11,0x030e480,0x07b71dc,0x0878103,0x0e6deb3,0x0bacd22,
|
|
0x1326d7b,0x1f3efc0,0x007858d },
|
|
{ 0x1f13222,0x03f5d9d,0x08453e9,0x1bd40fb,0x1e451dc,0x0c12178,
|
|
0x1eb0f03,0x03c37d3,0x136eb87,0x192bea6,0x0c64364,0x0eb57d4,
|
|
0x13f49e7,0x075f159,0x1b4647d,0x0012c80,0x13c0c11,0x033d562,
|
|
0x0e06b1e,0x0b9f17a,0x01f4521 } },
|
|
/* 234 */
|
|
{ { 0x0493b79,0x145477d,0x0ab0e1f,0x169d638,0x120e270,0x1911905,
|
|
0x0fe827f,0x07b3e72,0x0a91c39,0x170dd57,0x0a36597,0x0c34271,
|
|
0x04deda9,0x0bdea87,0x0ac8e32,0x191c0d3,0x08a2363,0x17fb46a,
|
|
0x1931305,0x1c01cb9,0x0158af8 },
|
|
{ 0x1c509a1,0x0e78367,0x01d5b33,0x1f84d98,0x00f411e,0x0e2bf83,
|
|
0x17f5936,0x158da19,0x132e99c,0x0a8a429,0x1a5442a,0x167b171,
|
|
0x1d58f9a,0x1886e1f,0x1a61c26,0x06a134f,0x03d75ef,0x1c1c842,
|
|
0x0a4c4b1,0x1993a0b,0x01b628c } },
|
|
/* 235 */
|
|
{ { 0x141463f,0x1a78071,0x1e80764,0x1c2a1b4,0x14c8a6c,0x04aa9f8,
|
|
0x183f104,0x123b690,0x0a93f4a,0x11def2d,0x16019f0,0x0f0e59a,
|
|
0x009f47c,0x0219ee4,0x0cc0152,0x054fa3a,0x1f975a3,0x08605f3,
|
|
0x031d76a,0x0eefab1,0x012e08b },
|
|
{ 0x1a10d37,0x0940bb0,0x16977f0,0x02b8a1e,0x0d7b618,0x03be307,
|
|
0x0576de5,0x016515f,0x133c531,0x05515bb,0x06099e8,0x1570a62,
|
|
0x1f905fa,0x15a0cac,0x03a6059,0x0ef09e8,0x05216b3,0x04e65a1,
|
|
0x0619ab3,0x0baef8d,0x00c5683 } },
|
|
/* 236 */
|
|
{ { 0x1450a66,0x18a6595,0x1053a75,0x18fb7fb,0x1318885,0x1350600,
|
|
0x03616d1,0x14ccab5,0x15bdfc1,0x1510f4c,0x1e4b440,0x1931cce,
|
|
0x177a0d7,0x1aa853c,0x006ed5e,0x1a66e54,0x0335d74,0x0a16231,
|
|
0x036b525,0x09c3811,0x008b7be },
|
|
{ 0x1812273,0x1d81fca,0x15fc61c,0x05dc7ee,0x0e26ed3,0x1310bd1,
|
|
0x03ab9b6,0x09e58e2,0x0261d9f,0x1a85aba,0x0768b66,0x1f536f8,
|
|
0x0743971,0x02542ef,0x113ee1f,0x026f645,0x051ec22,0x17b961a,
|
|
0x1ee8649,0x0acd18e,0x0173134 } },
|
|
/* 237 */
|
|
{ { 0x03ba183,0x1463d45,0x1e9cf8f,0x17fc713,0x0e8cebb,0x0dd307a,
|
|
0x11a1c3e,0x1071d48,0x1cb601a,0x08bb71a,0x14b6d15,0x184c25c,
|
|
0x11f90bd,0x07b895f,0x1e79166,0x0a99b2b,0x00fbea0,0x1cde990,
|
|
0x157f502,0x0337edb,0x017a2cf },
|
|
{ 0x0736feb,0x1b65133,0x18bdc73,0x13bcf9f,0x1de86f4,0x1482b1d,
|
|
0x0f3a3f0,0x09f8c15,0x0726b6e,0x17451e7,0x048d6ea,0x088a7e5,
|
|
0x1ed2382,0x1287fd2,0x0d55fd5,0x1ee8949,0x054113e,0x150a29f,
|
|
0x1909b74,0x0ed4a67,0x01b07c6 } },
|
|
/* 238 */
|
|
{ { 0x1d96872,0x101f91a,0x032bd79,0x187f4b7,0x0b1a23c,0x046e2fd,
|
|
0x01c6fa6,0x17aa8b3,0x1d430c0,0x1974244,0x16730f8,0x13c0ec9,
|
|
0x0d7ec26,0x1960620,0x08e084b,0x10769ee,0x183887b,0x096ca30,
|
|
0x1c62904,0x1f4ce25,0x0010281 },
|
|
{ 0x0858b37,0x00247b2,0x176600a,0x1e6afbc,0x00e149a,0x0f5d8c7,
|
|
0x01e4586,0x1416443,0x19f2b0b,0x0810059,0x072eb88,0x15cc207,
|
|
0x1d5a87e,0x1cabce8,0x1f7376c,0x0a2bc9d,0x0aa2788,0x10d9c47,
|
|
0x0061e2a,0x0a58799,0x002c1a5 } },
|
|
/* 239 */
|
|
{ { 0x0a723dc,0x1fa8007,0x08c5eb1,0x088562a,0x0a5f04f,0x042e430,
|
|
0x05116fa,0x004c7a9,0x1ff1197,0x0fccc9f,0x1633a98,0x08b9898,
|
|
0x16c3fba,0x1ce6b01,0x145479a,0x04777cd,0x11557b9,0x13ad1d5,
|
|
0x1acbf51,0x00f8a59,0x01474ec },
|
|
{ 0x188239d,0x11e9976,0x1a5311a,0x0d06b5c,0x0d1b8ae,0x1759738,
|
|
0x18c967f,0x16be9fb,0x043bc0b,0x11dfb8e,0x0a9c148,0x016f1ec,
|
|
0x053cd22,0x0ff3ccd,0x092183a,0x0ff2644,0x10324ab,0x1ec2ac3,
|
|
0x1652562,0x1ee6616,0x010f8e0 } },
|
|
/* 240 */
|
|
{ { 0x067d520,0x0e3dd9e,0x07b2bcd,0x1647f95,0x18f4958,0x1d54046,
|
|
0x1c6522e,0x15c0ef1,0x02135e8,0x0c61867,0x03bfdd0,0x1353911,
|
|
0x0bcdd8d,0x1b98a25,0x01d77c3,0x14a68e4,0x0954506,0x0daa4e4,
|
|
0x1eedff1,0x0712f2b,0x011c4ef },
|
|
{ 0x1f5e698,0x164d621,0x18e8ff8,0x19c714b,0x0e77fcb,0x04e170e,
|
|
0x12438c2,0x002da0b,0x1ac1d58,0x13a79ff,0x0e74a96,0x0440703,
|
|
0x0baeeda,0x1af9cb0,0x162c50f,0x1577db2,0x0510db7,0x032ffe8,
|
|
0x0816dc6,0x0fcd00f,0x00ce8e9 } },
|
|
/* 241 */
|
|
{ { 0x0e86a83,0x0f30dc6,0x0580894,0x1f7efce,0x0604159,0x1819bbc,
|
|
0x1f75d23,0x085f824,0x1450522,0x1e5961b,0x1a826e1,0x01e9269,
|
|
0x01bd495,0x0233ca2,0x11b100f,0x082d4a2,0x11023ba,0x0f456a3,
|
|
0x1d8e3ac,0x1034c15,0x01b389b },
|
|
{ 0x0150c69,0x0c9a774,0x12f39a6,0x11c4f82,0x14f7590,0x00ca7fb,
|
|
0x0a245a8,0x0ecbb81,0x01bd51b,0x07a4e99,0x1e58c0e,0x00bc30e,
|
|
0x086bc33,0x1e9da53,0x0bcfeff,0x1e313fc,0x177d7ca,0x18a04d9,
|
|
0x0e3c426,0x1d42773,0x01b3029 } },
|
|
/* 242 */
|
|
{ { 0x1a2fd88,0x09c6912,0x180fbde,0x199d740,0x090f2f7,0x136ffa4,
|
|
0x072035e,0x10c987c,0x02883f9,0x063c79b,0x194c140,0x0b25331,
|
|
0x13ed92b,0x192eee3,0x02a3c6c,0x0e11403,0x187d5d3,0x1b6ffec,
|
|
0x147ca2e,0x06aa9e1,0x0059dcd },
|
|
{ 0x1a74e7d,0x1720e91,0x17d85f1,0x1cbb665,0x14b61eb,0x1ffd05c,
|
|
0x1fe9e79,0x01a785f,0x12ebb7a,0x19b315b,0x17e70d1,0x0bdc035,
|
|
0x04a8641,0x0a33c93,0x00b0c99,0x138ae2a,0x1492fa0,0x10b4889,
|
|
0x11d2421,0x1e69544,0x0195897 } },
|
|
/* 243 */
|
|
{ { 0x1adc253,0x0e9acd5,0x0579211,0x198f2f9,0x0054b92,0x10c1097,
|
|
0x0d6f668,0x04e4553,0x0a52b88,0x1dc052f,0x0719da6,0x0f1c5cc,
|
|
0x13ea38e,0x04587c5,0x09d2c68,0x10a99f6,0x0e3db9d,0x1db5521,
|
|
0x1804b5c,0x044a46a,0x01638ba },
|
|
{ 0x1c8c576,0x00737ba,0x1749f3b,0x19c978f,0x0bb20e7,0x0c03935,
|
|
0x08321a7,0x16e12b1,0x08a023e,0x0846335,0x042c56a,0x01d4ec2,
|
|
0x06ca9f5,0x0c37b0d,0x0326650,0x0d3b0cd,0x0ed2a0a,0x1ceef91,
|
|
0x0fe2843,0x1c312f7,0x01e0bfe } },
|
|
/* 244 */
|
|
{ { 0x0319e4f,0x0340c24,0x1e809b6,0x0ab4b0d,0x0be6f6b,0x189932b,
|
|
0x1621899,0x1f57deb,0x198529c,0x0129562,0x0a73eeb,0x0be2c56,
|
|
0x0de7cc4,0x11531ac,0x0141826,0x158e1dc,0x0a42940,0x07be5ce,
|
|
0x0216c7c,0x0955d95,0x01adfb4 },
|
|
{ 0x198678e,0x1d49b73,0x10e19ad,0x0732a80,0x0a01e10,0x14305be,
|
|
0x078de05,0x0afe492,0x1b745d8,0x17fea41,0x017b5bb,0x0c5148e,
|
|
0x175dbb3,0x1952e87,0x15a3526,0x1fdc6af,0x09a2389,0x168d429,
|
|
0x09ff5a1,0x184a923,0x01addbb } },
|
|
/* 245 */
|
|
{ { 0x09686a3,0x05d104b,0x0fd7843,0x0bc780a,0x108b1c5,0x1a38811,
|
|
0x0c4d09b,0x0702e25,0x1490330,0x1c8b2d8,0x0549ec7,0x002e5a0,
|
|
0x0245b72,0x154d1a7,0x13d991e,0x06b90df,0x194b0be,0x128faa5,
|
|
0x08578e0,0x16454ab,0x00e3fcc },
|
|
{ 0x14dc0be,0x0f2762d,0x1712a9c,0x11b639a,0x1b13624,0x170803d,
|
|
0x1fd0c11,0x147e6d7,0x1da9c99,0x134036b,0x06f1416,0x0ddd069,
|
|
0x109cbfc,0x109f042,0x01c79cf,0x091824d,0x02767f4,0x0af3551,
|
|
0x169eebe,0x0ef0f85,0x01b9ba7 } },
|
|
/* 246 */
|
|
{ { 0x1a73375,0x12c7762,0x10e06af,0x1af5158,0x175df69,0x0541ad0,
|
|
0x0542b3b,0x01e59e6,0x1f507d3,0x03d8304,0x0c1092e,0x14578c1,
|
|
0x0c9ae53,0x0087c87,0x0c78609,0x1137692,0x10fadd6,0x122963e,
|
|
0x1d8c6a3,0x0a69228,0x0013ab4 },
|
|
{ 0x084f3af,0x0ec2b46,0x0cfabcb,0x043755c,0x029dc09,0x0b58384,
|
|
0x0aa162e,0x02c8ca8,0x0e8a825,0x11306a0,0x14c8ad0,0x1b58b86,
|
|
0x12b9e5e,0x1cf6d06,0x09e5580,0x1721579,0x1c6b962,0x1435e83,
|
|
0x07b14c0,0x05b58f6,0x010a2e2 } },
|
|
/* 247 */
|
|
{ { 0x19d8f0a,0x1e04e91,0x0085997,0x1957142,0x12b2e03,0x19a3bdc,
|
|
0x05da005,0x009c86d,0x18e3616,0x19c76cf,0x0186faa,0x123b3d6,
|
|
0x1079b00,0x1f422b3,0x1089950,0x145c19a,0x0c72fe1,0x1d07bbf,
|
|
0x18280c3,0x0842c4e,0x00931d2 },
|
|
{ 0x0646bc3,0x1c1a67c,0x1be7ea7,0x04815d2,0x1df94a5,0x08bbe8b,
|
|
0x0e240de,0x19b2038,0x0ffeb66,0x0fe8322,0x0491967,0x05d8ef7,
|
|
0x0f81aec,0x06cc0ea,0x1cedfcb,0x161265b,0x169f377,0x1e4de1f,
|
|
0x1616762,0x1e69e7b,0x0125dae } },
|
|
/* 248 */
|
|
{ { 0x0c123bc,0x0228dd1,0x0952b02,0x101031f,0x11e83a6,0x0abdc56,
|
|
0x15c0a62,0x02cadba,0x0f0f12f,0x03f971a,0x1e85373,0x1866153,
|
|
0x0c1f6a9,0x197f3c1,0x1268aee,0x0a9bbdf,0x097709f,0x1e98ce3,
|
|
0x1918294,0x047197a,0x01dc0b8 },
|
|
{ 0x0dfb6f6,0x09480a2,0x149bd92,0x08dc803,0x070d7cb,0x09bd6c1,
|
|
0x0903921,0x1b234e1,0x170d8db,0x06b30da,0x03562e1,0x0475e2e,
|
|
0x12ca272,0x11a270e,0x0d33c51,0x1c3f5dd,0x095ab9d,0x1912afe,
|
|
0x0f717a9,0x1c2215b,0x01f8cd6 } },
|
|
/* 249 */
|
|
{ { 0x0b8a0a7,0x1e35cbc,0x17a8a95,0x0dd067d,0x04b4aeb,0x089ff39,
|
|
0x05f052f,0x1c93c8c,0x0fc2e8e,0x00c3444,0x11fbbf1,0x1493f62,
|
|
0x1b8d398,0x1733167,0x1c647c4,0x145d9d3,0x089958b,0x0b0c391,
|
|
0x02e3543,0x1a1e360,0x002dbd6 },
|
|
{ 0x0c93cc9,0x07eff12,0x039e257,0x0173ce3,0x09ed778,0x1d7bf59,
|
|
0x0e960e2,0x0d20391,0x04ddcbf,0x1129c3f,0x035aec0,0x017f430,
|
|
0x0264b25,0x04a3e3e,0x1a39523,0x1e79ada,0x0329923,0x14153db,
|
|
0x1440f34,0x006c265,0x000fb8f } },
|
|
/* 250 */
|
|
{ { 0x0d9d494,0x059f846,0x07ce066,0x1329e9f,0x1b2065b,0x19c7d4c,
|
|
0x08880f1,0x196ecc9,0x0d8d229,0x0cfa60a,0x1152cc6,0x0b898a3,
|
|
0x12ddad7,0x0909d19,0x0cb382f,0x0f65f34,0x085888c,0x179d108,
|
|
0x0c7fc82,0x1f46c4b,0x00d16de },
|
|
{ 0x1a296eb,0x002a40c,0x0c4d138,0x0ba3522,0x1d94ff1,0x1522a78,
|
|
0x0b4affa,0x0ffafbd,0x14d40bd,0x132d401,0x0692beb,0x08fc300,
|
|
0x17604f1,0x12f06f3,0x0c123e6,0x0594130,0x0a5ff57,0x1d1d8ce,
|
|
0x0087445,0x0fb74e3,0x00e0a23 } },
|
|
/* 251 */
|
|
{ { 0x1630ee8,0x15fc248,0x0c07b6e,0x040bd6a,0x1e6589c,0x08fa3de,
|
|
0x0acb681,0x1033efa,0x0212bbe,0x1554fcb,0x048492b,0x1abd285,
|
|
0x1bdced3,0x1a21af2,0x07d6e27,0x1ecded2,0x0339411,0x10cb026,
|
|
0x0d5bc36,0x1813948,0x00e6b7f },
|
|
{ 0x14f811c,0x07209fb,0x176c4a5,0x03bf1b1,0x1a42d83,0x1a0c648,
|
|
0x1c85e58,0x1d84fea,0x088ebcd,0x1ef290c,0x016f257,0x00ddd46,
|
|
0x01fdd5e,0x163345b,0x0798222,0x030c3da,0x016eb81,0x0199d78,
|
|
0x17773af,0x16325a2,0x01c95ec } },
|
|
/* 252 */
|
|
{ { 0x0bde442,0x19bd1f0,0x1cfa49e,0x10cdef4,0x00543fe,0x0886177,
|
|
0x074823b,0x065a61b,0x1a6617a,0x1bce1a0,0x173e2eb,0x10e1a3a,
|
|
0x0be7367,0x11d5e7c,0x14373a7,0x0bcf605,0x0dd772b,0x0ff11e9,
|
|
0x1ff1c31,0x19dd403,0x010b29f },
|
|
{ 0x0d803ff,0x05726b1,0x1aa4c6f,0x1fb7860,0x13ee913,0x0083314,
|
|
0x19eaf63,0x0b15e3b,0x0e7a6d6,0x042bc15,0x1d381b5,0x125c205,
|
|
0x0691265,0x09b7d7f,0x08c49fc,0x0242723,0x0408837,0x0235c9a,
|
|
0x0c7858d,0x1687014,0x00ba53b } },
|
|
/* 253 */
|
|
{ { 0x05636b0,0x08bfe65,0x171d8b9,0x02d5742,0x0296e02,0x173d96a,
|
|
0x1f5f084,0x108b551,0x15717ad,0x08be736,0x0bcd5e5,0x10b7316,
|
|
0x1ce762b,0x0facd83,0x1e65ad7,0x1ede085,0x0bbf37e,0x0f9b995,
|
|
0x150ad22,0x028bd48,0x015da5d },
|
|
{ 0x07f6e3f,0x1e2af55,0x16f079d,0x0f54940,0x1f4d99a,0x0141139,
|
|
0x1f5dd16,0x1f74ada,0x177b748,0x1844afd,0x07d7476,0x199c0c5,
|
|
0x1b1c484,0x1acc01f,0x0c72428,0x171a1eb,0x1291720,0x121d627,
|
|
0x0ab04fc,0x017fd0e,0x00e98c1 } },
|
|
/* 254 */
|
|
{ { 0x06c4fd6,0x023c2e0,0x0e76747,0x0ba4b85,0x1f4b902,0x0c17925,
|
|
0x17ac752,0x0560826,0x0ba4fef,0x159f6e1,0x181eace,0x073f31b,
|
|
0x1d55a52,0x04b7a5b,0x1f126ac,0x1902bab,0x1603844,0x1e28514,
|
|
0x159daca,0x0291a02,0x0047db1 },
|
|
{ 0x0f3bad9,0x1ce6288,0x0753127,0x1804520,0x090888f,0x1da26fa,
|
|
0x157af11,0x0d122f4,0x0f39f2b,0x05975e3,0x0658a88,0x075e09d,
|
|
0x170c58e,0x0b9eead,0x0adf06d,0x1eed8a5,0x1d6a329,0x195aa56,
|
|
0x0bd328e,0x15a3d70,0x010859d } },
|
|
/* 255 */
|
|
{ { 0x182d1ad,0x0209450,0x111598b,0x1c4122d,0x1751796,0x140b23b,
|
|
0x109cae9,0x1834ee0,0x0b92c85,0x164587d,0x0cb81fe,0x05bf5df,
|
|
0x0d207ab,0x1c30d99,0x0d4c281,0x1a28b8e,0x16588ae,0x0b1edf6,
|
|
0x094e927,0x179b941,0x00bd547 },
|
|
{ 0x1056b51,0x09c17c3,0x044a9f0,0x16261f3,0x03d91ed,0x002da16,
|
|
0x1791b4e,0x12bef8f,0x1fd31a9,0x0b080f5,0x1ee2a91,0x05699a7,
|
|
0x0e1efd2,0x0f58bde,0x0e477de,0x01865fc,0x0c6616c,0x05a6a60,
|
|
0x046fbbd,0x00477ce,0x011219f } },
|
|
};
|
|
|
|
/* Multiply the base point of P521 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^65, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_mulmod_base_21(sp_point_521* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
return sp_521_ecc_mulmod_stripe_21(r, &p521_base, p521_table,
|
|
k, map, ct, heap);
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Multiply the base point of P521 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_521(const mp_int* km, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_521 point[1];
|
|
sp_digit k[21];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_521_from_mp(k, 21, km);
|
|
|
|
err = sp_521_ecc_mulmod_base_21(point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_point_to_ecc_point_21(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the base point of P521 by the scalar, add point a and return
|
|
* the result. If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_add_521(const mp_int* km, const ecc_point* am,
|
|
int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_521 point[2];
|
|
sp_digit k[21 + 21 * 2 * 6];
|
|
#endif
|
|
sp_point_521* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (21 + 21 * 2 * 6),
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 21;
|
|
|
|
sp_521_from_mp(k, 21, km);
|
|
sp_521_point_from_ecc_point_21(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_521_mod_mul_norm_21(addP->x, addP->x, p521_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_521_mod_mul_norm_21(addP->y, addP->y, p521_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_521_mod_mul_norm_21(addP->z, addP->z, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_ecc_mulmod_base_21(point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_521_proj_point_add_21(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_521_map_21(point, point, tmp);
|
|
}
|
|
|
|
err = sp_521_point_to_ecc_point_21(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
|
|
defined(HAVE_ECC_VERIFY)
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN | HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
|
|
/* Add 1 to a. (a = a + 1)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_521_add_one_21(sp_digit* a)
|
|
{
|
|
a[0]++;
|
|
sp_521_norm_21(a);
|
|
}
|
|
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_521_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 17U) {
|
|
r[j] &= 0x1ffffff;
|
|
s = 25U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Generates a scalar that is in the range 1..order-1.
|
|
*
|
|
* rng Random number generator.
|
|
* k Scalar value.
|
|
* returns RNG failures, MEMORY_E when memory allocation fails and
|
|
* MP_OKAY on success.
|
|
*/
|
|
static int sp_521_ecc_gen_k_21(WC_RNG* rng, sp_digit* k)
|
|
{
|
|
int err;
|
|
byte buf[66];
|
|
|
|
do {
|
|
err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf));
|
|
if (err == 0) {
|
|
buf[0] &= 0x1;
|
|
sp_521_from_bin(k, 21, buf, (int)sizeof(buf));
|
|
if (sp_521_cmp_21(k, p521_order2) <= 0) {
|
|
sp_521_add_one_21(k);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
while (err == 0);
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Makes a random EC key pair.
|
|
*
|
|
* rng Random number generator.
|
|
* priv Generated private value.
|
|
* pub Generated public point.
|
|
* heap Heap to use for allocation.
|
|
* returns ECC_INF_E when the point does not have the correct order, RNG
|
|
* failures, MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_make_key_521(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_521 point[2];
|
|
#else
|
|
sp_point_521 point[1];
|
|
#endif
|
|
sp_digit k[21];
|
|
#endif
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_521* infinity = NULL;
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap, DYNAMIC_TYPE_ECC);
|
|
#else
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
infinity = point + 1;
|
|
#endif
|
|
|
|
err = sp_521_ecc_gen_k_21(rng, k);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_ecc_mulmod_21(infinity, point, p521_order, 1, 1, NULL);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
if (sp_521_iszero_21(point->x) || sp_521_iszero_21(point->y)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(k, priv);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_point_to_ecc_point_21(point, pub);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL) {
|
|
/* point is not sensitive, so no need to zeroize */
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
}
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_key_gen_521_ctx {
|
|
int state;
|
|
sp_521_ecc_mulmod_21_ctx mulmod_ctx;
|
|
sp_digit k[21];
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_521 point[2];
|
|
#else
|
|
sp_point_521 point[1];
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
} sp_ecc_key_gen_521_ctx;
|
|
|
|
int sp_ecc_make_key_521_nb(sp_ecc_ctx_t* sp_ctx, WC_RNG* rng, mp_int* priv,
|
|
ecc_point* pub, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_key_gen_521_ctx* ctx = (sp_ecc_key_gen_521_ctx*)sp_ctx->data;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
sp_point_521* infinity = ctx->point + 1;
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_key_gen_521_ctx)
|
|
>= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
err = sp_521_ecc_gen_k_21(rng, ctx->k);
|
|
if (err == MP_OKAY) {
|
|
err = FP_WOULDBLOCK;
|
|
ctx->state = 1;
|
|
}
|
|
break;
|
|
case 1:
|
|
err = sp_521_ecc_mulmod_base_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
ctx->point, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
err = FP_WOULDBLOCK;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 2;
|
|
#else
|
|
ctx->state = 3;
|
|
#endif
|
|
}
|
|
break;
|
|
#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
|
case 2:
|
|
err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
infinity, ctx->point, p521_order, 1, 1);
|
|
if (err == MP_OKAY) {
|
|
if (sp_521_iszero_21(ctx->point->x) ||
|
|
sp_521_iszero_21(ctx->point->y)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
else {
|
|
err = FP_WOULDBLOCK;
|
|
ctx->state = 3;
|
|
}
|
|
}
|
|
break;
|
|
#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN */
|
|
case 3:
|
|
err = sp_521_to_mp(ctx->k, priv);
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_point_to_ecc_point_21(ctx->point, pub);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx, 0, sizeof(sp_ecc_key_gen_521_ctx));
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#ifdef HAVE_ECC_DHE
|
|
/* Write r as big endian to byte array.
|
|
* Fixed length number of bytes written: 66
|
|
*
|
|
* r A single precision integer.
|
|
* a Byte array.
|
|
*/
|
|
static void sp_521_to_bin_21(sp_digit* r, byte* a)
|
|
{
|
|
int i;
|
|
int j;
|
|
int s = 0;
|
|
int b;
|
|
|
|
for (i=0; i<20; i++) {
|
|
r[i+1] += r[i] >> 25;
|
|
r[i] &= 0x1ffffff;
|
|
}
|
|
j = 528 / 8 - 1;
|
|
a[j] = 0;
|
|
for (i=0; i<21 && j>=0; i++) {
|
|
b = 0;
|
|
/* lint allow cast of mismatch sp_digit and int */
|
|
a[j--] |= (byte)(r[i] << s); /*lint !e9033*/
|
|
b += 8 - s;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
while (b < 25) {
|
|
a[j--] = (byte)(r[i] >> b);
|
|
b += 8;
|
|
if (j < 0) {
|
|
break;
|
|
}
|
|
}
|
|
s = 8 - (b - 25);
|
|
if (j >= 0) {
|
|
a[j] = 0;
|
|
}
|
|
if (s != 0) {
|
|
j++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Multiply the point by the scalar and serialize the X ordinate.
|
|
* The number is 0 padded to maximum size on output.
|
|
*
|
|
* priv Scalar to multiply the point by.
|
|
* pub Point to multiply.
|
|
* out Buffer to hold X ordinate.
|
|
* outLen On entry, size of the buffer in bytes.
|
|
* On exit, length of data in buffer in bytes.
|
|
* heap Heap to use for allocation.
|
|
* returns BUFFER_E if the buffer is to small for output size,
|
|
* MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_secret_gen_521(const mp_int* priv, const ecc_point* pub, byte* out,
|
|
word32* outLen, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_521 point[1];
|
|
sp_digit k[21];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
if (*outLen < 65U) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_521_from_mp(k, 21, priv);
|
|
sp_521_point_from_ecc_point_21(point, pub);
|
|
err = sp_521_ecc_mulmod_21(point, point, k, 1, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_521_to_bin_21(point->x, out);
|
|
*outLen = 66;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_sec_gen_521_ctx {
|
|
int state;
|
|
union {
|
|
sp_521_ecc_mulmod_21_ctx mulmod_ctx;
|
|
};
|
|
sp_digit k[21];
|
|
sp_point_521 point;
|
|
} sp_ecc_sec_gen_521_ctx;
|
|
|
|
int sp_ecc_secret_gen_521_nb(sp_ecc_ctx_t* sp_ctx, const mp_int* priv,
|
|
const ecc_point* pub, byte* out, word32* outLen, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_sec_gen_521_ctx* ctx = (sp_ecc_sec_gen_521_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_sec_gen_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
if (*outLen < 32U) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
sp_521_from_mp(ctx->k, 21, priv);
|
|
sp_521_point_from_ecc_point_21(&ctx->point, pub);
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
&ctx->point, &ctx->point, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
sp_521_to_bin_21(ctx->point.x, out);
|
|
*outLen = 66;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 1) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx, 0, sizeof(sp_ecc_sec_gen_521_ctx));
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_DHE */
|
|
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
SP_NOINLINE static void sp_521_rshift_21(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
for (i=0; i<20; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (25 - n))) & 0x1ffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<16; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (25 - n)) & 0x1ffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (25 - n)) & 0x1ffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (25 - n)) & 0x1ffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (25 - n)) & 0x1ffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (25 - n)) & 0x1ffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (25 - n)) & 0x1ffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (25 - n)) & 0x1ffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (25 - n)) & 0x1ffffff);
|
|
}
|
|
r[16] = (a[16] >> n) | ((a[17] << (25 - n)) & 0x1ffffff);
|
|
r[17] = (a[17] >> n) | ((a[18] << (25 - n)) & 0x1ffffff);
|
|
r[18] = (a[18] >> n) | ((a[19] << (25 - n)) & 0x1ffffff);
|
|
r[19] = (a[19] >> n) | ((a[20] << (25 - n)) & 0x1ffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[20] = a[20] >> n;
|
|
}
|
|
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_521_mul_d_21(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 21; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
}
|
|
r[21] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 20; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
t += tb * a[20];
|
|
r[20] = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[21] = (sp_digit)(t & 0x1ffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
SP_NOINLINE static void sp_521_lshift_42(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
r[42] = a[41] >> (25 - n);
|
|
for (i=41; i>0; i--) {
|
|
r[i] = ((a[i] << n) | (a[i-1] >> (25 - n))) & 0x1ffffff;
|
|
}
|
|
#else
|
|
sp_int_digit s;
|
|
sp_int_digit t;
|
|
|
|
s = (sp_int_digit)a[41];
|
|
r[42] = s >> (25U - n);
|
|
s = (sp_int_digit)(a[41]); t = (sp_int_digit)(a[40]);
|
|
r[41] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[40]); t = (sp_int_digit)(a[39]);
|
|
r[40] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[39]); t = (sp_int_digit)(a[38]);
|
|
r[39] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[38]); t = (sp_int_digit)(a[37]);
|
|
r[38] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[37]); t = (sp_int_digit)(a[36]);
|
|
r[37] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[36]); t = (sp_int_digit)(a[35]);
|
|
r[36] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[35]); t = (sp_int_digit)(a[34]);
|
|
r[35] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[34]); t = (sp_int_digit)(a[33]);
|
|
r[34] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[33]); t = (sp_int_digit)(a[32]);
|
|
r[33] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[32]); t = (sp_int_digit)(a[31]);
|
|
r[32] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[31]); t = (sp_int_digit)(a[30]);
|
|
r[31] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[30]); t = (sp_int_digit)(a[29]);
|
|
r[30] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[29]); t = (sp_int_digit)(a[28]);
|
|
r[29] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[28]); t = (sp_int_digit)(a[27]);
|
|
r[28] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[27]); t = (sp_int_digit)(a[26]);
|
|
r[27] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[26]); t = (sp_int_digit)(a[25]);
|
|
r[26] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[25]); t = (sp_int_digit)(a[24]);
|
|
r[25] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[24]); t = (sp_int_digit)(a[23]);
|
|
r[24] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[23]); t = (sp_int_digit)(a[22]);
|
|
r[23] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[22]); t = (sp_int_digit)(a[21]);
|
|
r[22] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[21]); t = (sp_int_digit)(a[20]);
|
|
r[21] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[20]); t = (sp_int_digit)(a[19]);
|
|
r[20] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[19]); t = (sp_int_digit)(a[18]);
|
|
r[19] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[18]); t = (sp_int_digit)(a[17]);
|
|
r[18] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[17]); t = (sp_int_digit)(a[16]);
|
|
r[17] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[16]); t = (sp_int_digit)(a[15]);
|
|
r[16] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[15]); t = (sp_int_digit)(a[14]);
|
|
r[15] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[14]); t = (sp_int_digit)(a[13]);
|
|
r[14] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[13]); t = (sp_int_digit)(a[12]);
|
|
r[13] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[12]); t = (sp_int_digit)(a[11]);
|
|
r[12] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[11]); t = (sp_int_digit)(a[10]);
|
|
r[11] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[10]); t = (sp_int_digit)(a[9]);
|
|
r[10] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[9]); t = (sp_int_digit)(a[8]);
|
|
r[9] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[8]); t = (sp_int_digit)(a[7]);
|
|
r[8] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[7]); t = (sp_int_digit)(a[6]);
|
|
r[7] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[6]); t = (sp_int_digit)(a[5]);
|
|
r[6] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[5]); t = (sp_int_digit)(a[4]);
|
|
r[5] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[4]); t = (sp_int_digit)(a[3]);
|
|
r[4] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[3]); t = (sp_int_digit)(a[2]);
|
|
r[3] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[2]); t = (sp_int_digit)(a[1]);
|
|
r[2] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
s = (sp_int_digit)(a[1]); t = (sp_int_digit)(a[0]);
|
|
r[1] = ((s << n) | (t >> (25U - n))) & 0x1ffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[0] = (a[0] << n) & 0x1ffffff;
|
|
}
|
|
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Simplified based on top word of divisor being (1 << 25) - 1
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_521_div_21(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
sp_digit r1;
|
|
sp_digit mask;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 21 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 21 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 42 + 1;
|
|
sd = t2 + 21 + 1;
|
|
|
|
sp_521_mul_d_21(sd, d, (sp_digit)1 << 4);
|
|
sp_521_lshift_42(t1, a, 4);
|
|
t1[21 + 21] += t1[21 + 21 - 1] >> 25;
|
|
t1[21 + 21 - 1] &= 0x1ffffff;
|
|
for (i=20; i>=0; i--) {
|
|
r1 = t1[21 + i];
|
|
sp_521_mul_d_21(t2, sd, r1);
|
|
(void)sp_521_sub_21(&t1[i], &t1[i], t2);
|
|
t1[21 + i] -= t2[21];
|
|
sp_521_norm_21(&t1[i + 1]);
|
|
|
|
mask = ~((t1[21 + i] - 1) >> 31);
|
|
sp_521_cond_sub_21(t1 + i, t1 + i, sd, mask);
|
|
sp_521_norm_21(&t1[i + 1]);
|
|
}
|
|
sp_521_norm_21(t1);
|
|
sp_521_rshift_21(r, t1, 4);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_521_mod_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_521_div_21(a, m, NULL, r);
|
|
}
|
|
|
|
#endif
|
|
#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY)
|
|
/* Multiply two number mod the order of P521 curve. (r = a * b mod order)
|
|
*
|
|
* r Result of the multiplication.
|
|
* a First operand of the multiplication.
|
|
* b Second operand of the multiplication.
|
|
*/
|
|
static void sp_521_mont_mul_order_21(sp_digit* r, const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_521_mul_21(r, a, b);
|
|
sp_521_mont_reduce_order_21(r, p521_order, p521_mp_order);
|
|
}
|
|
|
|
#if defined(HAVE_ECC_SIGN) || (defined(HAVE_ECC_VERIFY) && defined(WOLFSSL_SP_SMALL))
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Order-2 for the P521 curve. */
|
|
static const uint32_t p521_order_minus_2[17] = {
|
|
0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U,
|
|
0xbf2f966bU,0x51868783U,0xfffffffaU,0xffffffffU,0xffffffffU,0xffffffffU,
|
|
0xffffffffU,0xffffffffU,0xffffffffU,0xffffffffU,0x000001ffU
|
|
};
|
|
#else
|
|
/* The low half of the order-2 of the P521 curve. */
|
|
static const uint32_t p521_order_low[9] = {
|
|
0x91386407U,0xbb6fb71eU,0x899c47aeU,0x3bb5c9b8U,0xf709a5d0U,0x7fcc0148U,
|
|
0xbf2f966bU,0x51868783U,0xfffffffaU
|
|
};
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Square number mod the order of P521 curve. (r = a * a mod order)
|
|
*
|
|
* r Result of the squaring.
|
|
* a Number to square.
|
|
*/
|
|
static void sp_521_mont_sqr_order_21(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_521_sqr_21(r, a);
|
|
sp_521_mont_reduce_order_21(r, p521_order, p521_mp_order);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Square number mod the order of P521 curve a number of times.
|
|
* (r = a ^ n mod order)
|
|
*
|
|
* r Result of the squaring.
|
|
* a Number to square.
|
|
*/
|
|
static void sp_521_mont_sqr_n_order_21(sp_digit* r, const sp_digit* a, int n)
|
|
{
|
|
int i;
|
|
|
|
sp_521_mont_sqr_order_21(r, a);
|
|
for (i=1; i<n; i++) {
|
|
sp_521_mont_sqr_order_21(r, r);
|
|
}
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
/* Invert the number, in Montgomery form, modulo the order of the P521 curve.
|
|
* (r = 1 / a mod order)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_521_mont_inv_order_21_ctx {
|
|
int state;
|
|
int i;
|
|
} sp_521_mont_inv_order_21_ctx;
|
|
static int sp_521_mont_inv_order_21_nb(sp_ecc_ctx_t* sp_ctx, sp_digit* r, const sp_digit* a,
|
|
sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_521_mont_inv_order_21_ctx* ctx = (sp_521_mont_inv_order_21_ctx*)sp_ctx;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_521_mont_inv_order_21_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 21);
|
|
ctx->i = 519;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
sp_521_mont_sqr_order_21(t, t);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
if ((p521_order_minus_2[ctx->i / 32] & ((sp_int_digit)1 << (ctx->i % 32))) != 0) {
|
|
sp_521_mont_mul_order_21(t, t, a);
|
|
}
|
|
ctx->i--;
|
|
ctx->state = (ctx->i == 0) ? 3 : 1;
|
|
break;
|
|
case 3:
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 21U);
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
static void sp_521_mont_inv_order_21(sp_digit* r, const sp_digit* a,
|
|
sp_digit* td)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_digit* t = td;
|
|
int i;
|
|
|
|
XMEMCPY(t, a, sizeof(sp_digit) * 21);
|
|
for (i=519; i>=0; i--) {
|
|
sp_521_mont_sqr_order_21(t, t);
|
|
if ((p521_order_minus_2[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_521_mont_mul_order_21(t, t, a);
|
|
}
|
|
}
|
|
XMEMCPY(r, t, sizeof(sp_digit) * 21U);
|
|
#else
|
|
sp_digit* t = td;
|
|
sp_digit* t2 = td + 2 * 21;
|
|
sp_digit* t3 = td + 4 * 21;
|
|
int i;
|
|
|
|
/* t = a^2 */
|
|
sp_521_mont_sqr_order_21(t, a);
|
|
/* t = a^3 = t * a */
|
|
sp_521_mont_mul_order_21(t, t, a);
|
|
/* t= a^c = t ^ 2 ^ 2 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 2);
|
|
/* t = a^f = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
|
|
/* t3 = a^1e */
|
|
sp_521_mont_sqr_order_21(t3, t);
|
|
/* t3 = a^1f = t3 * a */
|
|
sp_521_mont_mul_order_21(t3, t3, a);
|
|
|
|
/* t2= a^f0 = t ^ 2 ^ 4 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 4);
|
|
/* t = a^ff = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
/* t2= a^ff00 = t ^ 2 ^ 8 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 8);
|
|
/* t3= a^ffff = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
/* t2= a^ffff0000 = t ^ 2 ^ 16 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 16);
|
|
/* t = a^ffffffff = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
|
|
/* t2= a^ffffffff00000000 = t ^ 2 ^ 32 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 32);
|
|
/* t = a^ffffffffffffffff = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
/* t2= a^ffffffffffffffff0000000000000000 = t ^ 2 ^ 64 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 64);
|
|
/* t = a^ffffffffffffffffffffffffffffffff = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
/* t2= a^ffffffffffffffffffffffffffffffff00000000000000000000000000000000 = t ^ 2 ^ 128 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 128);
|
|
/* t = a^ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t2 * t */
|
|
sp_521_mont_mul_order_21(t, t2, t);
|
|
|
|
/* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0 */
|
|
sp_521_mont_sqr_n_order_21(t2, t, 5);
|
|
/* t2 = a^1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff = t * t3 */
|
|
sp_521_mont_mul_order_21(t2, t2, t3);
|
|
|
|
for (i=259; i>=1; i--) {
|
|
sp_521_mont_sqr_order_21(t2, t2);
|
|
if ((p521_order_low[i / 32] & ((sp_int_digit)1 << (i % 32))) != 0) {
|
|
sp_521_mont_mul_order_21(t2, t2, a);
|
|
}
|
|
}
|
|
sp_521_mont_sqr_order_21(t2, t2);
|
|
sp_521_mont_mul_order_21(r, t2, a);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#endif /* HAVE_ECC_SIGN || (HAVE_ECC_VERIFY && WOLFSSL_SP_SMALL) */
|
|
#endif /* HAVE_ECC_SIGN | HAVE_ECC_VERIFY */
|
|
#ifdef HAVE_ECC_SIGN
|
|
#ifndef SP_ECC_MAX_SIG_GEN
|
|
#define SP_ECC_MAX_SIG_GEN 64
|
|
#endif
|
|
|
|
/* Calculate second signature value S from R, k and private value.
|
|
*
|
|
* s = (r * x + e) / k
|
|
*
|
|
* s Signature value.
|
|
* r First signature value.
|
|
* k Ephemeral private key.
|
|
* x Private key as a number.
|
|
* e Hash of message as a number.
|
|
* tmp Temporary storage for intermediate numbers.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_calc_s_21(sp_digit* s, const sp_digit* r, sp_digit* k,
|
|
sp_digit* x, const sp_digit* e, sp_digit* tmp)
|
|
{
|
|
int err;
|
|
sp_digit carry;
|
|
sp_int32 c;
|
|
sp_digit* kInv = k;
|
|
|
|
/* Conv k to Montgomery form (mod order) */
|
|
sp_521_mul_21(k, k, p521_norm_order);
|
|
err = sp_521_mod_21(k, k, p521_order);
|
|
if (err == MP_OKAY) {
|
|
sp_521_norm_21(k);
|
|
|
|
/* kInv = 1/k mod order */
|
|
sp_521_mont_inv_order_21(kInv, k, tmp);
|
|
sp_521_norm_21(kInv);
|
|
|
|
/* s = r * x + e */
|
|
sp_521_mul_21(x, x, r);
|
|
err = sp_521_mod_21(x, x, p521_order);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_521_norm_21(x);
|
|
carry = sp_521_add_21(s, e, x);
|
|
sp_521_cond_sub_21(s, s, p521_order, 0 - carry);
|
|
sp_521_norm_21(s);
|
|
c = sp_521_cmp_21(s, p521_order);
|
|
sp_521_cond_sub_21(s, s, p521_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_521_norm_21(s);
|
|
|
|
/* s = s * k^-1 mod order */
|
|
sp_521_mont_mul_order_21(s, s, kInv);
|
|
sp_521_norm_21(s);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Sign the hash using the private key.
|
|
* e = [hash, 521 bits] from binary
|
|
* r = (k.G)->x mod order
|
|
* s = (r * x + e) / k mod order
|
|
* The hash is truncated to the first 521 bits.
|
|
*
|
|
* hash Hash to sign.
|
|
* hashLen Length of the hash data.
|
|
* rng Random number generator.
|
|
* priv Private part of key - scalar.
|
|
* rm First part of result as an mp_int.
|
|
* sm Sirst part of result as an mp_int.
|
|
* heap Heap to use for allocation.
|
|
* returns RNG failures, MEMORY_E when memory allocation fails and
|
|
* MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_sign_521(const byte* hash, word32 hashLen, WC_RNG* rng,
|
|
const mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* e = NULL;
|
|
sp_point_521* point = NULL;
|
|
#else
|
|
sp_digit e[7 * 2 * 21];
|
|
sp_point_521 point[1];
|
|
#endif
|
|
sp_digit* x = NULL;
|
|
sp_digit* k = NULL;
|
|
sp_digit* r = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_digit* s = NULL;
|
|
sp_int32 c;
|
|
int err = MP_OKAY;
|
|
int i;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_521*)XMALLOC(sizeof(sp_point_521), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
e = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (e == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
x = e + 2 * 21;
|
|
k = e + 4 * 21;
|
|
r = e + 6 * 21;
|
|
tmp = e + 8 * 21;
|
|
s = e;
|
|
|
|
if (hashLen > 66U) {
|
|
hashLen = 66U;
|
|
}
|
|
}
|
|
|
|
for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) {
|
|
/* New random point. */
|
|
if (km == NULL || mp_iszero(km)) {
|
|
err = sp_521_ecc_gen_k_21(rng, k);
|
|
}
|
|
else {
|
|
sp_521_from_mp(k, 21, km);
|
|
mp_zero(km);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_ecc_mulmod_base_21(point, k, 1, 1, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* r = point->x mod order */
|
|
XMEMCPY(r, point->x, sizeof(sp_digit) * 21U);
|
|
sp_521_norm_21(r);
|
|
c = sp_521_cmp_21(r, p521_order);
|
|
sp_521_cond_sub_21(r, r, p521_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_521_norm_21(r);
|
|
|
|
if (!sp_521_iszero_21(r)) {
|
|
/* x is modified in calculation of s. */
|
|
sp_521_from_mp(x, 21, priv);
|
|
/* s ptr == e ptr, e is modified in calculation of s. */
|
|
sp_521_from_bin(e, 21, hash, (int)hashLen);
|
|
|
|
/* Take 521 leftmost bits of hash. */
|
|
if (hashLen == 66U) {
|
|
sp_521_rshift_21(e, e, 7);
|
|
e[20] |= ((sp_digit)hash[0]) << 13;
|
|
}
|
|
|
|
err = sp_521_calc_s_21(s, r, k, x, e, tmp);
|
|
|
|
/* Check that signature is usable. */
|
|
if ((err == MP_OKAY) && (!sp_521_iszero_21(s))) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
|
|
i = 1;
|
|
#endif
|
|
}
|
|
|
|
if (i == 0) {
|
|
err = RNG_FAILURE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(r, rm);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(s, sm);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (e != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(e, sizeof(sp_digit) * 7 * 2 * 21);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(e, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (point != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(point, sizeof(sp_point_521));
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_sign_521_ctx {
|
|
int state;
|
|
union {
|
|
sp_521_ecc_mulmod_21_ctx mulmod_ctx;
|
|
sp_521_mont_inv_order_21_ctx mont_inv_order_ctx;
|
|
};
|
|
sp_digit e[2*21];
|
|
sp_digit x[2*21];
|
|
sp_digit k[2*21];
|
|
sp_digit r[2*21];
|
|
sp_digit tmp[3 * 2*21];
|
|
sp_point_521 point;
|
|
sp_digit* s;
|
|
sp_digit* kInv;
|
|
int i;
|
|
} sp_ecc_sign_521_ctx;
|
|
|
|
int sp_ecc_sign_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash, word32 hashLen, WC_RNG* rng,
|
|
mp_int* priv, mp_int* rm, mp_int* sm, mp_int* km, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_sign_521_ctx* ctx = (sp_ecc_sign_521_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_sign_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->s = ctx->e;
|
|
ctx->kInv = ctx->k;
|
|
|
|
ctx->i = SP_ECC_MAX_SIG_GEN;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* GEN */
|
|
/* New random point. */
|
|
if (km == NULL || mp_iszero(km)) {
|
|
err = sp_521_ecc_gen_k_21(rng, ctx->k);
|
|
}
|
|
else {
|
|
sp_521_from_mp(ctx->k, 21, km);
|
|
mp_zero(km);
|
|
}
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* MULMOD */
|
|
err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx,
|
|
&ctx->point, &p521_base, ctx->k, 1, 1, heap);
|
|
if (err == MP_OKAY) {
|
|
ctx->state = 3;
|
|
}
|
|
break;
|
|
case 3: /* MODORDER */
|
|
{
|
|
sp_int32 c;
|
|
/* r = point->x mod order */
|
|
XMEMCPY(ctx->r, ctx->point.x, sizeof(sp_digit) * 21U);
|
|
sp_521_norm_21(ctx->r);
|
|
c = sp_521_cmp_21(ctx->r, p521_order);
|
|
sp_521_cond_sub_21(ctx->r, ctx->r, p521_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_521_norm_21(ctx->r);
|
|
|
|
if (hashLen > 66U) {
|
|
hashLen = 66U;
|
|
}
|
|
sp_521_from_mp(ctx->x, 21, priv);
|
|
sp_521_from_bin(ctx->e, 21, hash, (int)hashLen);
|
|
if (hashLen == 66U) {
|
|
sp_521_rshift_21(ctx->e, ctx->e, 7);
|
|
ctx->e[20] |= ((sp_digit)hash[0]) << 13;
|
|
}
|
|
ctx->state = 4;
|
|
break;
|
|
}
|
|
case 4: /* KMODORDER */
|
|
/* Conv k to Montgomery form (mod order) */
|
|
sp_521_mul_21(ctx->k, ctx->k, p521_norm_order);
|
|
err = sp_521_mod_21(ctx->k, ctx->k, p521_order);
|
|
if (err == MP_OKAY) {
|
|
sp_521_norm_21(ctx->k);
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 5;
|
|
}
|
|
break;
|
|
case 5: /* KINV */
|
|
/* kInv = 1/k mod order */
|
|
err = sp_521_mont_inv_order_21_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->kInv, ctx->k, ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* KINVNORM */
|
|
sp_521_norm_21(ctx->kInv);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7: /* R */
|
|
/* s = r * x + e */
|
|
sp_521_mul_21(ctx->x, ctx->x, ctx->r);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8: /* S1 */
|
|
err = sp_521_mod_21(ctx->x, ctx->x, p521_order);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 9;
|
|
break;
|
|
case 9: /* S2 */
|
|
{
|
|
sp_digit carry;
|
|
sp_int32 c;
|
|
sp_521_norm_21(ctx->x);
|
|
carry = sp_521_add_21(ctx->s, ctx->e, ctx->x);
|
|
sp_521_cond_sub_21(ctx->s, ctx->s,
|
|
p521_order, 0 - carry);
|
|
sp_521_norm_21(ctx->s);
|
|
c = sp_521_cmp_21(ctx->s, p521_order);
|
|
sp_521_cond_sub_21(ctx->s, ctx->s, p521_order,
|
|
(sp_digit)0 - (sp_digit)(c >= 0));
|
|
sp_521_norm_21(ctx->s);
|
|
|
|
/* s = s * k^-1 mod order */
|
|
sp_521_mont_mul_order_21(ctx->s, ctx->s, ctx->kInv);
|
|
sp_521_norm_21(ctx->s);
|
|
|
|
/* Check that signature is usable. */
|
|
if (sp_521_iszero_21(ctx->s) == 0) {
|
|
ctx->state = 10;
|
|
break;
|
|
}
|
|
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
|
|
ctx->i = 1;
|
|
#endif
|
|
|
|
/* not usable gen, try again */
|
|
ctx->i--;
|
|
if (ctx->i == 0) {
|
|
err = RNG_FAILURE_E;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
}
|
|
case 10: /* RES */
|
|
err = sp_521_to_mp(ctx->r, rm);
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(ctx->s, sm);
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 10) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
XMEMSET(ctx->e, 0, sizeof(sp_digit) * 2U * 21U);
|
|
XMEMSET(ctx->x, 0, sizeof(sp_digit) * 2U * 21U);
|
|
XMEMSET(ctx->k, 0, sizeof(sp_digit) * 2U * 21U);
|
|
XMEMSET(ctx->r, 0, sizeof(sp_digit) * 2U * 21U);
|
|
XMEMSET(ctx->tmp, 0, sizeof(sp_digit) * 3U * 2U * 21U);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_SIGN */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
static const char sp_521_tab32_21[32] = {
|
|
1, 10, 2, 11, 14, 22, 3, 30,
|
|
12, 15, 17, 19, 23, 26, 4, 31,
|
|
9, 13, 21, 29, 16, 18, 25, 8,
|
|
20, 28, 24, 7, 27, 6, 5, 32};
|
|
|
|
static int sp_521_num_bits_25_21(sp_digit v)
|
|
{
|
|
v |= v >> 1;
|
|
v |= v >> 2;
|
|
v |= v >> 4;
|
|
v |= v >> 8;
|
|
v |= v >> 16;
|
|
return sp_521_tab32_21[(uint32_t)(v*0x07C4ACDD) >> 27];
|
|
}
|
|
|
|
static int sp_521_num_bits_21(const sp_digit* a)
|
|
{
|
|
int i;
|
|
int r = 0;
|
|
|
|
for (i = 20; i >= 0; i--) {
|
|
if (a[i] != 0) {
|
|
r = sp_521_num_bits_25_21(a[i]);
|
|
r += i * 25;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Non-constant time modular inversion.
|
|
*
|
|
* @param [out] r Resulting number.
|
|
* @param [in] a Number to invert.
|
|
* @param [in] m Modulus.
|
|
* @return MP_OKAY on success.
|
|
* @return MEMEORY_E when dynamic memory allocation fails.
|
|
*/
|
|
static int sp_521_mod_inv_21(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
int err = MP_OKAY;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* u = NULL;
|
|
#else
|
|
sp_digit u[21 * 4];
|
|
#endif
|
|
sp_digit* v = NULL;
|
|
sp_digit* b = NULL;
|
|
sp_digit* d = NULL;
|
|
int ut;
|
|
int vt;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
u = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21 * 4, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (u == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
v = u + 21;
|
|
b = u + 2 * 21;
|
|
d = u + 3 * 21;
|
|
|
|
XMEMCPY(u, m, sizeof(sp_digit) * 21);
|
|
XMEMCPY(v, a, sizeof(sp_digit) * 21);
|
|
|
|
ut = sp_521_num_bits_21(u);
|
|
vt = sp_521_num_bits_21(v);
|
|
|
|
XMEMSET(b, 0, sizeof(sp_digit) * 21);
|
|
if ((v[0] & 1) == 0) {
|
|
sp_521_rshift1_21(v, v);
|
|
XMEMCPY(d, m, sizeof(sp_digit) * 21);
|
|
d[0]++;
|
|
sp_521_rshift1_21(d, d);
|
|
vt--;
|
|
|
|
while ((v[0] & 1) == 0) {
|
|
sp_521_rshift1_21(v, v);
|
|
if (d[0] & 1)
|
|
sp_521_add_21(d, d, m);
|
|
sp_521_rshift1_21(d, d);
|
|
vt--;
|
|
}
|
|
}
|
|
else {
|
|
XMEMSET(d+1, 0, sizeof(sp_digit) * (21 - 1));
|
|
d[0] = 1;
|
|
}
|
|
|
|
while (ut > 1 && vt > 1) {
|
|
if (ut > vt || (ut == vt &&
|
|
sp_521_cmp_21(u, v) >= 0)) {
|
|
sp_521_sub_21(u, u, v);
|
|
sp_521_norm_21(u);
|
|
|
|
sp_521_sub_21(b, b, d);
|
|
sp_521_norm_21(b);
|
|
if (b[20] < 0)
|
|
sp_521_add_21(b, b, m);
|
|
sp_521_norm_21(b);
|
|
ut = sp_521_num_bits_21(u);
|
|
|
|
do {
|
|
sp_521_rshift1_21(u, u);
|
|
if (b[0] & 1)
|
|
sp_521_add_21(b, b, m);
|
|
sp_521_rshift1_21(b, b);
|
|
ut--;
|
|
}
|
|
while (ut > 0 && (u[0] & 1) == 0);
|
|
}
|
|
else {
|
|
sp_521_sub_21(v, v, u);
|
|
sp_521_norm_21(v);
|
|
|
|
sp_521_sub_21(d, d, b);
|
|
sp_521_norm_21(d);
|
|
if (d[20] < 0)
|
|
sp_521_add_21(d, d, m);
|
|
sp_521_norm_21(d);
|
|
vt = sp_521_num_bits_21(v);
|
|
|
|
do {
|
|
sp_521_rshift1_21(v, v);
|
|
if (d[0] & 1)
|
|
sp_521_add_21(d, d, m);
|
|
sp_521_rshift1_21(d, d);
|
|
vt--;
|
|
}
|
|
while (vt > 0 && (v[0] & 1) == 0);
|
|
}
|
|
}
|
|
|
|
if (ut == 1)
|
|
XMEMCPY(r, b, sizeof(sp_digit) * 21);
|
|
else
|
|
XMEMCPY(r, d, sizeof(sp_digit) * 21);
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (u != NULL)
|
|
XFREE(u, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
/* Add point p1 into point p2. Handles p1 == p2 and result at infinity.
|
|
*
|
|
* p1 First point to add and holds result.
|
|
* p2 Second point to add.
|
|
* tmp Temporary storage for intermediate numbers.
|
|
*/
|
|
static void sp_521_add_points_21(sp_point_521* p1, const sp_point_521* p2,
|
|
sp_digit* tmp)
|
|
{
|
|
|
|
sp_521_proj_point_add_21(p1, p1, p2, tmp);
|
|
if (sp_521_iszero_21(p1->z)) {
|
|
if (sp_521_iszero_21(p1->x) && sp_521_iszero_21(p1->y)) {
|
|
sp_521_proj_point_dbl_21(p1, p2, tmp);
|
|
}
|
|
else {
|
|
/* Y ordinate is not used from here - don't set. */
|
|
p1->x[0] = 0;
|
|
p1->x[1] = 0;
|
|
p1->x[2] = 0;
|
|
p1->x[3] = 0;
|
|
p1->x[4] = 0;
|
|
p1->x[5] = 0;
|
|
p1->x[6] = 0;
|
|
p1->x[7] = 0;
|
|
p1->x[8] = 0;
|
|
p1->x[9] = 0;
|
|
p1->x[10] = 0;
|
|
p1->x[11] = 0;
|
|
p1->x[12] = 0;
|
|
p1->x[13] = 0;
|
|
p1->x[14] = 0;
|
|
p1->x[15] = 0;
|
|
p1->x[16] = 0;
|
|
p1->x[17] = 0;
|
|
p1->x[18] = 0;
|
|
p1->x[19] = 0;
|
|
p1->x[20] = 0;
|
|
XMEMCPY(p1->z, p521_norm_mod, sizeof(p521_norm_mod));
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Calculate the verification point: [e/s]G + [r/s]Q
|
|
*
|
|
* p1 Calculated point.
|
|
* p2 Public point and temporary.
|
|
* s Second part of signature as a number.
|
|
* u1 Temporary number.
|
|
* u2 Temproray number.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_521_calc_vfy_point_21(sp_point_521* p1, sp_point_521* p2,
|
|
sp_digit* s, sp_digit* u1, sp_digit* u2, sp_digit* tmp, void* heap)
|
|
{
|
|
int err;
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
err = sp_521_mod_inv_21(s, s, p521_order);
|
|
if (err == MP_OKAY)
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
{
|
|
sp_521_mul_21(s, s, p521_norm_order);
|
|
err = sp_521_mod_21(s, s, p521_order);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_521_norm_21(s);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
{
|
|
sp_521_mont_inv_order_21(s, s, tmp);
|
|
sp_521_mont_mul_order_21(u1, u1, s);
|
|
sp_521_mont_mul_order_21(u2, u2, s);
|
|
}
|
|
#else
|
|
{
|
|
sp_521_mont_mul_order_21(u1, u1, s);
|
|
sp_521_mont_mul_order_21(u2, u2, s);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
{
|
|
err = sp_521_ecc_mulmod_base_21(p1, u1, 0, 0, heap);
|
|
}
|
|
}
|
|
if ((err == MP_OKAY) && sp_521_iszero_21(p1->z)) {
|
|
p1->infinity = 1;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_ecc_mulmod_21(p2, p2, u2, 0, 0, heap);
|
|
}
|
|
if ((err == MP_OKAY) && sp_521_iszero_21(p2->z)) {
|
|
p2->infinity = 1;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_521_add_points_21(p1, p2, tmp);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef HAVE_ECC_VERIFY
|
|
/* Verify the signature values with the hash and public key.
|
|
* e = Truncate(hash, 521)
|
|
* u1 = e/s mod order
|
|
* u2 = r/s mod order
|
|
* r == (u1.G + u2.Q)->x mod order
|
|
* Optimization: Leave point in projective form.
|
|
* (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z')
|
|
* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x'
|
|
* The hash is truncated to the first 521 bits.
|
|
*
|
|
* hash Hash to sign.
|
|
* hashLen Length of the hash data.
|
|
* rng Random number generator.
|
|
* priv Private part of key - scalar.
|
|
* rm First part of result as an mp_int.
|
|
* sm Sirst part of result as an mp_int.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_verify_521(const byte* hash, word32 hashLen, const mp_int* pX,
|
|
const mp_int* pY, const mp_int* pZ, const mp_int* rm, const mp_int* sm,
|
|
int* res, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* u1 = NULL;
|
|
sp_point_521* p1 = NULL;
|
|
#else
|
|
sp_digit u1[18 * 21];
|
|
sp_point_521 p1[2];
|
|
#endif
|
|
sp_digit* u2 = NULL;
|
|
sp_digit* s = NULL;
|
|
sp_digit* tmp = NULL;
|
|
sp_point_521* p2 = NULL;
|
|
sp_digit carry;
|
|
sp_int32 c = 0;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p1 = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p1 == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
u1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (u1 == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
u2 = u1 + 2 * 21;
|
|
s = u1 + 4 * 21;
|
|
tmp = u1 + 6 * 21;
|
|
p2 = p1 + 1;
|
|
|
|
if (hashLen > 66U) {
|
|
hashLen = 66U;
|
|
}
|
|
|
|
sp_521_from_bin(u1, 21, hash, (int)hashLen);
|
|
sp_521_from_mp(u2, 21, rm);
|
|
sp_521_from_mp(s, 21, sm);
|
|
sp_521_from_mp(p2->x, 21, pX);
|
|
sp_521_from_mp(p2->y, 21, pY);
|
|
sp_521_from_mp(p2->z, 21, pZ);
|
|
|
|
if (hashLen == 66U) {
|
|
sp_521_rshift_21(u1, u1, 7);
|
|
u1[20] |= ((sp_digit)hash[0]) << 13;
|
|
}
|
|
|
|
err = sp_521_calc_vfy_point_21(p1, p2, s, u1, u2, tmp, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
|
|
/* Reload r and convert to Montgomery form. */
|
|
sp_521_from_mp(u2, 21, rm);
|
|
err = sp_521_mod_mul_norm_21(u2, u2, p521_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* u1 = r.z'.z' mod prime */
|
|
sp_521_mont_sqr_21(p1->z, p1->z, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod);
|
|
*res = (int)(sp_521_cmp_21(p1->x, u1) == 0);
|
|
if (*res == 0) {
|
|
/* Reload r and add order. */
|
|
sp_521_from_mp(u2, 21, rm);
|
|
carry = sp_521_add_21(u2, u2, p521_order);
|
|
/* Carry means result is greater than mod and is not valid. */
|
|
if (carry == 0) {
|
|
sp_521_norm_21(u2);
|
|
|
|
/* Compare with mod and if greater or equal then not valid. */
|
|
c = sp_521_cmp_21(u2, p521_mod);
|
|
}
|
|
}
|
|
if ((*res == 0) && (c < 0)) {
|
|
/* Convert to Montogomery form */
|
|
err = sp_521_mod_mul_norm_21(u2, u2, p521_mod);
|
|
if (err == MP_OKAY) {
|
|
/* u1 = (r + 1*order).z'.z' mod prime */
|
|
{
|
|
sp_521_mont_mul_21(u1, u2, p1->z, p521_mod, p521_mp_mod);
|
|
}
|
|
*res = (sp_521_cmp_21(p1->x, u1) == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (u1 != NULL)
|
|
XFREE(u1, heap, DYNAMIC_TYPE_ECC);
|
|
if (p1 != NULL)
|
|
XFREE(p1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_ecc_verify_521_ctx {
|
|
int state;
|
|
union {
|
|
sp_521_ecc_mulmod_21_ctx mulmod_ctx;
|
|
sp_521_mont_inv_order_21_ctx mont_inv_order_ctx;
|
|
sp_521_proj_point_dbl_21_ctx dbl_ctx;
|
|
sp_521_proj_point_add_21_ctx add_ctx;
|
|
};
|
|
sp_digit u1[2*21];
|
|
sp_digit u2[2*21];
|
|
sp_digit s[2*21];
|
|
sp_digit tmp[2*21 * 6];
|
|
sp_point_521 p1;
|
|
sp_point_521 p2;
|
|
} sp_ecc_verify_521_ctx;
|
|
|
|
int sp_ecc_verify_521_nb(sp_ecc_ctx_t* sp_ctx, const byte* hash,
|
|
word32 hashLen, const mp_int* pX, const mp_int* pY, const mp_int* pZ,
|
|
const mp_int* rm, const mp_int* sm, int* res, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_ecc_verify_521_ctx* ctx = (sp_ecc_verify_521_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_ecc_verify_521_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
if (hashLen > 66U) {
|
|
hashLen = 66U;
|
|
}
|
|
|
|
sp_521_from_bin(ctx->u1, 21, hash, (int)hashLen);
|
|
sp_521_from_mp(ctx->u2, 21, rm);
|
|
sp_521_from_mp(ctx->s, 21, sm);
|
|
sp_521_from_mp(ctx->p2.x, 21, pX);
|
|
sp_521_from_mp(ctx->p2.y, 21, pY);
|
|
sp_521_from_mp(ctx->p2.z, 21, pZ);
|
|
if (hashLen == 66U) {
|
|
sp_521_rshift_21(ctx->u1, ctx->u1, 7);
|
|
ctx->u1[20] |= ((sp_digit)hash[0]) << 13;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* NORMS0 */
|
|
sp_521_mul_21(ctx->s, ctx->s, p521_norm_order);
|
|
err = sp_521_mod_21(ctx->s, ctx->s, p521_order);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* NORMS1 */
|
|
sp_521_norm_21(ctx->s);
|
|
XMEMSET(&ctx->mont_inv_order_ctx, 0, sizeof(ctx->mont_inv_order_ctx));
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* NORMS2 */
|
|
err = sp_521_mont_inv_order_21_nb((sp_ecc_ctx_t*)&ctx->mont_inv_order_ctx, ctx->s, ctx->s, ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
ctx->state = 4;
|
|
}
|
|
break;
|
|
case 4: /* NORMS3 */
|
|
sp_521_mont_mul_order_21(ctx->u1, ctx->u1, ctx->s);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* NORMS4 */
|
|
sp_521_mont_mul_order_21(ctx->u2, ctx->u2, ctx->s);
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 6;
|
|
break;
|
|
case 6: /* MULBASE */
|
|
err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p1, &p521_base, ctx->u1, 0, 0, heap);
|
|
if (err == MP_OKAY) {
|
|
if (sp_521_iszero_21(ctx->p1.z)) {
|
|
ctx->p1.infinity = 1;
|
|
}
|
|
XMEMSET(&ctx->mulmod_ctx, 0, sizeof(ctx->mulmod_ctx));
|
|
ctx->state = 7;
|
|
}
|
|
break;
|
|
case 7: /* MULMOD */
|
|
err = sp_521_ecc_mulmod_21_nb((sp_ecc_ctx_t*)&ctx->mulmod_ctx, &ctx->p2, &ctx->p2, ctx->u2, 0, 0, heap);
|
|
if (err == MP_OKAY) {
|
|
if (sp_521_iszero_21(ctx->p2.z)) {
|
|
ctx->p2.infinity = 1;
|
|
}
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 8;
|
|
}
|
|
break;
|
|
case 8: /* ADD */
|
|
err = sp_521_proj_point_add_21_nb((sp_ecc_ctx_t*)&ctx->add_ctx, &ctx->p1, &ctx->p1, &ctx->p2, ctx->tmp);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 9;
|
|
break;
|
|
case 9: /* MONT */
|
|
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
|
|
/* Reload r and convert to Montgomery form. */
|
|
sp_521_from_mp(ctx->u2, 21, rm);
|
|
err = sp_521_mod_mul_norm_21(ctx->u2, ctx->u2, p521_mod);
|
|
if (err == MP_OKAY)
|
|
ctx->state = 10;
|
|
break;
|
|
case 10: /* SQR */
|
|
/* u1 = r.z'.z' mod prime */
|
|
sp_521_mont_sqr_21(ctx->p1.z, ctx->p1.z, p521_mod, p521_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11: /* MUL */
|
|
sp_521_mont_mul_21(ctx->u1, ctx->u2, ctx->p1.z, p521_mod, p521_mp_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12: /* RES */
|
|
{
|
|
sp_int32 c = 0;
|
|
err = MP_OKAY; /* math okay, now check result */
|
|
*res = (int)(sp_521_cmp_21(ctx->p1.x, ctx->u1) == 0);
|
|
if (*res == 0) {
|
|
sp_digit carry;
|
|
|
|
/* Reload r and add order. */
|
|
sp_521_from_mp(ctx->u2, 21, rm);
|
|
carry = sp_521_add_21(ctx->u2, ctx->u2, p521_order);
|
|
/* Carry means result is greater than mod and is not valid. */
|
|
if (carry == 0) {
|
|
sp_521_norm_21(ctx->u2);
|
|
|
|
/* Compare with mod and if greater or equal then not valid. */
|
|
c = sp_521_cmp_21(ctx->u2, p521_mod);
|
|
}
|
|
}
|
|
if ((*res == 0) && (c < 0)) {
|
|
/* Convert to Montogomery form */
|
|
err = sp_521_mod_mul_norm_21(ctx->u2, ctx->u2, p521_mod);
|
|
if (err == MP_OKAY) {
|
|
/* u1 = (r + 1*order).z'.z' mod prime */
|
|
sp_521_mont_mul_21(ctx->u1, ctx->u2, ctx->p1.z, p521_mod,
|
|
p521_mp_mod);
|
|
*res = (int)(sp_521_cmp_21(ctx->p1.x, ctx->u1) == 0);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
} /* switch */
|
|
|
|
if (err == MP_OKAY && ctx->state != 12) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
#endif /* HAVE_ECC_VERIFY */
|
|
|
|
#ifdef HAVE_ECC_CHECK_KEY
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* point EC point.
|
|
* heap Heap to use if dynamically allocating.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_521_ecc_is_point_21(const sp_point_521* point,
|
|
void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[21 * 4];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21 * 4, heap, DYNAMIC_TYPE_ECC);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
(void)heap;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 2 * 21;
|
|
|
|
sp_521_sqr_21(t1, point->y);
|
|
(void)sp_521_mod_21(t1, t1, p521_mod);
|
|
sp_521_sqr_21(t2, point->x);
|
|
(void)sp_521_mod_21(t2, t2, p521_mod);
|
|
sp_521_mul_21(t2, t2, point->x);
|
|
(void)sp_521_mod_21(t2, t2, p521_mod);
|
|
(void)sp_521_sub_21(t2, p521_mod, t2);
|
|
sp_521_mont_add_21(t1, t1, t2, p521_mod);
|
|
|
|
sp_521_mont_add_21(t1, t1, point->x, p521_mod);
|
|
sp_521_mont_add_21(t1, t1, point->x, p521_mod);
|
|
sp_521_mont_add_21(t1, t1, point->x, p521_mod);
|
|
|
|
if (sp_521_cmp_21(t1, p521_b) != 0) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_is_point_521(const mp_int* pX, const mp_int* pY)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_521* pub = NULL;
|
|
#else
|
|
sp_point_521 pub[1];
|
|
#endif
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
pub = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_521_from_mp(pub->x, 21, pX);
|
|
sp_521_from_mp(pub->y, 21, pY);
|
|
sp_521_from_bin(pub->z, 21, one, (int)sizeof(one));
|
|
|
|
err = sp_521_ecc_is_point_21(pub, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the private scalar generates the EC point (px, py), the point is
|
|
* on the curve and the point has the correct order.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* privm Private scalar that generates EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve, ECC_INF_E if the point does not have the correct order,
|
|
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
|
|
* MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_check_key_521(const mp_int* pX, const mp_int* pY,
|
|
const mp_int* privm, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* priv = NULL;
|
|
sp_point_521* pub = NULL;
|
|
#else
|
|
sp_digit priv[21];
|
|
sp_point_521 pub[2];
|
|
#endif
|
|
sp_point_521* p = NULL;
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
|
|
/* Quick check the lengs of public key ordinates and private key are in
|
|
* range. Proper check later.
|
|
*/
|
|
if (((mp_count_bits(pX) > 521) ||
|
|
(mp_count_bits(pY) > 521) ||
|
|
((privm != NULL) && (mp_count_bits(privm) > 521)))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
pub = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY && privm) {
|
|
priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 21, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (priv == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = pub + 1;
|
|
|
|
sp_521_from_mp(pub->x, 21, pX);
|
|
sp_521_from_mp(pub->y, 21, pY);
|
|
sp_521_from_bin(pub->z, 21, one, (int)sizeof(one));
|
|
if (privm)
|
|
sp_521_from_mp(priv, 21, privm);
|
|
|
|
/* Check point at infinitiy. */
|
|
if ((sp_521_iszero_21(pub->x) != 0) &&
|
|
(sp_521_iszero_21(pub->y) != 0)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
|
|
/* Check range of X and Y */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_521_cmp_21(pub->x, p521_mod) >= 0) ||
|
|
(sp_521_cmp_21(pub->y, p521_mod) >= 0))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Check point is on curve */
|
|
err = sp_521_ecc_is_point_21(pub, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Point * order = infinity */
|
|
err = sp_521_ecc_mulmod_21(p, pub, p521_order, 1, 1, heap);
|
|
}
|
|
/* Check result is infinity */
|
|
if ((err == MP_OKAY) && ((sp_521_iszero_21(p->x) == 0) ||
|
|
(sp_521_iszero_21(p->y) == 0))) {
|
|
err = ECC_INF_E;
|
|
}
|
|
|
|
if (privm) {
|
|
if (err == MP_OKAY) {
|
|
/* Base * private = point */
|
|
err = sp_521_ecc_mulmod_base_21(p, priv, 1, 1, heap);
|
|
}
|
|
/* Check result is public key */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_521_cmp_21(p->x, pub->x) != 0) ||
|
|
(sp_521_cmp_21(p->y, pub->y) != 0))) {
|
|
err = ECC_PRIV_KEY_E;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, heap, DYNAMIC_TYPE_ECC);
|
|
if (priv != NULL)
|
|
XFREE(priv, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL
|
|
/* Add two projective EC points together.
|
|
* (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ)
|
|
*
|
|
* pX First EC point's X ordinate.
|
|
* pY First EC point's Y ordinate.
|
|
* pZ First EC point's Z ordinate.
|
|
* qX Second EC point's X ordinate.
|
|
* qY Second EC point's Y ordinate.
|
|
* qZ Second EC point's Z ordinate.
|
|
* rX Resultant EC point's X ordinate.
|
|
* rY Resultant EC point's Y ordinate.
|
|
* rZ Resultant EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_proj_add_point_521(mp_int* pX, mp_int* pY, mp_int* pZ,
|
|
mp_int* qX, mp_int* qY, mp_int* qZ,
|
|
mp_int* rX, mp_int* rY, mp_int* rZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_521* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 21 * 6];
|
|
sp_point_521 p[2];
|
|
#endif
|
|
sp_point_521* q = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_521*)XMALLOC(sizeof(sp_point_521) * 2, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 6, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
q = p + 1;
|
|
|
|
sp_521_from_mp(p->x, 21, pX);
|
|
sp_521_from_mp(p->y, 21, pY);
|
|
sp_521_from_mp(p->z, 21, pZ);
|
|
sp_521_from_mp(q->x, 21, qX);
|
|
sp_521_from_mp(q->y, 21, qY);
|
|
sp_521_from_mp(q->z, 21, qZ);
|
|
p->infinity = sp_521_iszero_21(p->x) &
|
|
sp_521_iszero_21(p->y);
|
|
q->infinity = sp_521_iszero_21(q->x) &
|
|
sp_521_iszero_21(q->y);
|
|
|
|
sp_521_proj_point_add_21(p, p, q, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->x, rX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->y, rY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->z, rZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Double a projective EC point.
|
|
* (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ)
|
|
*
|
|
* pX EC point's X ordinate.
|
|
* pY EC point's Y ordinate.
|
|
* pZ EC point's Z ordinate.
|
|
* rX Resultant EC point's X ordinate.
|
|
* rY Resultant EC point's Y ordinate.
|
|
* rZ Resultant EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_proj_dbl_point_521(mp_int* pX, mp_int* pY, mp_int* pZ,
|
|
mp_int* rX, mp_int* rY, mp_int* rZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_521* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 21 * 2];
|
|
sp_point_521 p[1];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 2, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_521_from_mp(p->x, 21, pX);
|
|
sp_521_from_mp(p->y, 21, pY);
|
|
sp_521_from_mp(p->z, 21, pZ);
|
|
p->infinity = sp_521_iszero_21(p->x) &
|
|
sp_521_iszero_21(p->y);
|
|
|
|
sp_521_proj_point_dbl_21(p, p, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->x, rX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->y, rY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->z, rZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Map a projective EC point to affine in place.
|
|
* pZ will be one.
|
|
*
|
|
* pX EC point's X ordinate.
|
|
* pY EC point's Y ordinate.
|
|
* pZ EC point's Z ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_map_521(mp_int* pX, mp_int* pY, mp_int* pZ)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp = NULL;
|
|
sp_point_521* p = NULL;
|
|
#else
|
|
sp_digit tmp[2 * 21 * 5];
|
|
sp_point_521 p[1];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
p = (sp_point_521*)XMALLOC(sizeof(sp_point_521), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (p == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21 * 5, NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
if (err == MP_OKAY) {
|
|
sp_521_from_mp(p->x, 21, pX);
|
|
sp_521_from_mp(p->y, 21, pY);
|
|
sp_521_from_mp(p->z, 21, pZ);
|
|
p->infinity = sp_521_iszero_21(p->x) &
|
|
sp_521_iszero_21(p->y);
|
|
|
|
sp_521_map_21(p, p, tmp);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->x, pX);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->y, pY);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_521_to_mp(p->z, pZ);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
XFREE(tmp, NULL, DYNAMIC_TYPE_ECC);
|
|
if (p != NULL)
|
|
XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */
|
|
#ifdef HAVE_COMP_KEY
|
|
/* Square root power for the P521 curve. */
|
|
static const uint32_t p521_sqrt_power[17] = {
|
|
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
|
|
0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000,
|
|
0x00000000,0x00000000,0x00000080
|
|
};
|
|
|
|
/* Find the square root of a number mod the prime of the curve.
|
|
*
|
|
* y The number to operate on and the result.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_521_mont_sqrt_21(sp_digit* y)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t = NULL;
|
|
#else
|
|
sp_digit t[2 * 21];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 21, NULL, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
|
|
{
|
|
int i;
|
|
|
|
XMEMCPY(t, y, sizeof(sp_digit) * 21);
|
|
for (i=518; i>=0; i--) {
|
|
sp_521_mont_sqr_21(t, t, p521_mod, p521_mp_mod);
|
|
if (p521_sqrt_power[i / 32] & ((sp_digit)1 << (i % 32)))
|
|
sp_521_mont_mul_21(t, t, y, p521_mod, p521_mp_mod);
|
|
}
|
|
XMEMCPY(y, t, sizeof(sp_digit) * 21);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
/* Uncompress the point given the X ordinate.
|
|
*
|
|
* xm X ordinate.
|
|
* odd Whether the Y ordinate is odd.
|
|
* ym Calculated Y ordinate.
|
|
* returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_uncompress_521(mp_int* xm, int odd, mp_int* ym)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* x = NULL;
|
|
#else
|
|
sp_digit x[4 * 21];
|
|
#endif
|
|
sp_digit* y = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
x = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 21, NULL, DYNAMIC_TYPE_ECC);
|
|
if (x == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
y = x + 2 * 21;
|
|
|
|
sp_521_from_mp(x, 21, xm);
|
|
err = sp_521_mod_mul_norm_21(x, x, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* y = x^3 */
|
|
{
|
|
sp_521_mont_sqr_21(y, x, p521_mod, p521_mp_mod);
|
|
sp_521_mont_mul_21(y, y, x, p521_mod, p521_mp_mod);
|
|
}
|
|
/* y = x^3 - 3x */
|
|
sp_521_mont_sub_21(y, y, x, p521_mod);
|
|
sp_521_mont_sub_21(y, y, x, p521_mod);
|
|
sp_521_mont_sub_21(y, y, x, p521_mod);
|
|
/* y = x^3 - 3x + b */
|
|
err = sp_521_mod_mul_norm_21(x, p521_b, p521_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_521_mont_add_21(y, y, x, p521_mod);
|
|
/* y = sqrt(x^3 - 3x + b) */
|
|
err = sp_521_mont_sqrt_21(y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(y + 21, 0, 21U * sizeof(sp_digit));
|
|
sp_521_mont_reduce_21(y, p521_mod, p521_mp_mod);
|
|
if ((((word32)y[0] ^ (word32)odd) & 1U) != 0U) {
|
|
sp_521_mont_sub_21(y, p521_mod, y, p521_mod);
|
|
}
|
|
|
|
err = sp_521_to_mp(y, ym);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (x != NULL)
|
|
XFREE(x, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#endif /* WOLFSSL_SP_521 */
|
|
#ifdef WOLFCRYPT_HAVE_SAKKE
|
|
#ifdef WOLFSSL_SP_1024
|
|
|
|
/* Point structure to use. */
|
|
typedef struct sp_point_1024 {
|
|
/* X ordinate of point. */
|
|
sp_digit x[2 * 42];
|
|
/* Y ordinate of point. */
|
|
sp_digit y[2 * 42];
|
|
/* Z ordinate of point. */
|
|
sp_digit z[2 * 42];
|
|
/* Indicates point is at infinity. */
|
|
int infinity;
|
|
} sp_point_1024;
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_7(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_int64 t0 = ((sp_int64)a[ 0]) * b[ 0];
|
|
sp_int64 t1 = ((sp_int64)a[ 0]) * b[ 1]
|
|
+ ((sp_int64)a[ 1]) * b[ 0];
|
|
sp_int64 t2 = ((sp_int64)a[ 0]) * b[ 2]
|
|
+ ((sp_int64)a[ 1]) * b[ 1]
|
|
+ ((sp_int64)a[ 2]) * b[ 0];
|
|
sp_int64 t3 = ((sp_int64)a[ 0]) * b[ 3]
|
|
+ ((sp_int64)a[ 1]) * b[ 2]
|
|
+ ((sp_int64)a[ 2]) * b[ 1]
|
|
+ ((sp_int64)a[ 3]) * b[ 0];
|
|
sp_int64 t4 = ((sp_int64)a[ 0]) * b[ 4]
|
|
+ ((sp_int64)a[ 1]) * b[ 3]
|
|
+ ((sp_int64)a[ 2]) * b[ 2]
|
|
+ ((sp_int64)a[ 3]) * b[ 1]
|
|
+ ((sp_int64)a[ 4]) * b[ 0];
|
|
sp_int64 t5 = ((sp_int64)a[ 0]) * b[ 5]
|
|
+ ((sp_int64)a[ 1]) * b[ 4]
|
|
+ ((sp_int64)a[ 2]) * b[ 3]
|
|
+ ((sp_int64)a[ 3]) * b[ 2]
|
|
+ ((sp_int64)a[ 4]) * b[ 1]
|
|
+ ((sp_int64)a[ 5]) * b[ 0];
|
|
sp_int64 t6 = ((sp_int64)a[ 0]) * b[ 6]
|
|
+ ((sp_int64)a[ 1]) * b[ 5]
|
|
+ ((sp_int64)a[ 2]) * b[ 4]
|
|
+ ((sp_int64)a[ 3]) * b[ 3]
|
|
+ ((sp_int64)a[ 4]) * b[ 2]
|
|
+ ((sp_int64)a[ 5]) * b[ 1]
|
|
+ ((sp_int64)a[ 6]) * b[ 0];
|
|
sp_int64 t7 = ((sp_int64)a[ 1]) * b[ 6]
|
|
+ ((sp_int64)a[ 2]) * b[ 5]
|
|
+ ((sp_int64)a[ 3]) * b[ 4]
|
|
+ ((sp_int64)a[ 4]) * b[ 3]
|
|
+ ((sp_int64)a[ 5]) * b[ 2]
|
|
+ ((sp_int64)a[ 6]) * b[ 1];
|
|
sp_int64 t8 = ((sp_int64)a[ 2]) * b[ 6]
|
|
+ ((sp_int64)a[ 3]) * b[ 5]
|
|
+ ((sp_int64)a[ 4]) * b[ 4]
|
|
+ ((sp_int64)a[ 5]) * b[ 3]
|
|
+ ((sp_int64)a[ 6]) * b[ 2];
|
|
sp_int64 t9 = ((sp_int64)a[ 3]) * b[ 6]
|
|
+ ((sp_int64)a[ 4]) * b[ 5]
|
|
+ ((sp_int64)a[ 5]) * b[ 4]
|
|
+ ((sp_int64)a[ 6]) * b[ 3];
|
|
sp_int64 t10 = ((sp_int64)a[ 4]) * b[ 6]
|
|
+ ((sp_int64)a[ 5]) * b[ 5]
|
|
+ ((sp_int64)a[ 6]) * b[ 4];
|
|
sp_int64 t11 = ((sp_int64)a[ 5]) * b[ 6]
|
|
+ ((sp_int64)a[ 6]) * b[ 5];
|
|
sp_int64 t12 = ((sp_int64)a[ 6]) * b[ 6];
|
|
|
|
t1 += t0 >> 25; r[ 0] = t0 & 0x1ffffff;
|
|
t2 += t1 >> 25; r[ 1] = t1 & 0x1ffffff;
|
|
t3 += t2 >> 25; r[ 2] = t2 & 0x1ffffff;
|
|
t4 += t3 >> 25; r[ 3] = t3 & 0x1ffffff;
|
|
t5 += t4 >> 25; r[ 4] = t4 & 0x1ffffff;
|
|
t6 += t5 >> 25; r[ 5] = t5 & 0x1ffffff;
|
|
t7 += t6 >> 25; r[ 6] = t6 & 0x1ffffff;
|
|
t8 += t7 >> 25; r[ 7] = t7 & 0x1ffffff;
|
|
t9 += t8 >> 25; r[ 8] = t8 & 0x1ffffff;
|
|
t10 += t9 >> 25; r[ 9] = t9 & 0x1ffffff;
|
|
t11 += t10 >> 25; r[10] = t10 & 0x1ffffff;
|
|
t12 += t11 >> 25; r[11] = t11 & 0x1ffffff;
|
|
r[13] = (sp_digit)(t12 >> 25);
|
|
r[12] = t12 & 0x1ffffff;
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_sqr_7(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_int64 t0 = ((sp_int64)a[ 0]) * a[ 0];
|
|
sp_int64 t1 = (((sp_int64)a[ 0]) * a[ 1]) * 2;
|
|
sp_int64 t2 = (((sp_int64)a[ 0]) * a[ 2]) * 2
|
|
+ ((sp_int64)a[ 1]) * a[ 1];
|
|
sp_int64 t3 = (((sp_int64)a[ 0]) * a[ 3]
|
|
+ ((sp_int64)a[ 1]) * a[ 2]) * 2;
|
|
sp_int64 t4 = (((sp_int64)a[ 0]) * a[ 4]
|
|
+ ((sp_int64)a[ 1]) * a[ 3]) * 2
|
|
+ ((sp_int64)a[ 2]) * a[ 2];
|
|
sp_int64 t5 = (((sp_int64)a[ 0]) * a[ 5]
|
|
+ ((sp_int64)a[ 1]) * a[ 4]
|
|
+ ((sp_int64)a[ 2]) * a[ 3]) * 2;
|
|
sp_int64 t6 = (((sp_int64)a[ 0]) * a[ 6]
|
|
+ ((sp_int64)a[ 1]) * a[ 5]
|
|
+ ((sp_int64)a[ 2]) * a[ 4]) * 2
|
|
+ ((sp_int64)a[ 3]) * a[ 3];
|
|
sp_int64 t7 = (((sp_int64)a[ 1]) * a[ 6]
|
|
+ ((sp_int64)a[ 2]) * a[ 5]
|
|
+ ((sp_int64)a[ 3]) * a[ 4]) * 2;
|
|
sp_int64 t8 = (((sp_int64)a[ 2]) * a[ 6]
|
|
+ ((sp_int64)a[ 3]) * a[ 5]) * 2
|
|
+ ((sp_int64)a[ 4]) * a[ 4];
|
|
sp_int64 t9 = (((sp_int64)a[ 3]) * a[ 6]
|
|
+ ((sp_int64)a[ 4]) * a[ 5]) * 2;
|
|
sp_int64 t10 = (((sp_int64)a[ 4]) * a[ 6]) * 2
|
|
+ ((sp_int64)a[ 5]) * a[ 5];
|
|
sp_int64 t11 = (((sp_int64)a[ 5]) * a[ 6]) * 2;
|
|
sp_int64 t12 = ((sp_int64)a[ 6]) * a[ 6];
|
|
|
|
t1 += t0 >> 25; r[ 0] = t0 & 0x1ffffff;
|
|
t2 += t1 >> 25; r[ 1] = t1 & 0x1ffffff;
|
|
t3 += t2 >> 25; r[ 2] = t2 & 0x1ffffff;
|
|
t4 += t3 >> 25; r[ 3] = t3 & 0x1ffffff;
|
|
t5 += t4 >> 25; r[ 4] = t4 & 0x1ffffff;
|
|
t6 += t5 >> 25; r[ 5] = t5 & 0x1ffffff;
|
|
t7 += t6 >> 25; r[ 6] = t6 & 0x1ffffff;
|
|
t8 += t7 >> 25; r[ 7] = t7 & 0x1ffffff;
|
|
t9 += t8 >> 25; r[ 8] = t8 & 0x1ffffff;
|
|
t10 += t9 >> 25; r[ 9] = t9 & 0x1ffffff;
|
|
t11 += t10 >> 25; r[10] = t10 & 0x1ffffff;
|
|
t12 += t11 >> 25; r[11] = t11 & 0x1ffffff;
|
|
r[13] = (sp_digit)(t12 >> 25);
|
|
r[12] = t12 & 0x1ffffff;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_add_7(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_sub_14(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] - b[ 0];
|
|
r[ 1] = a[ 1] - b[ 1];
|
|
r[ 2] = a[ 2] - b[ 2];
|
|
r[ 3] = a[ 3] - b[ 3];
|
|
r[ 4] = a[ 4] - b[ 4];
|
|
r[ 5] = a[ 5] - b[ 5];
|
|
r[ 6] = a[ 6] - b[ 6];
|
|
r[ 7] = a[ 7] - b[ 7];
|
|
r[ 8] = a[ 8] - b[ 8];
|
|
r[ 9] = a[ 9] - b[ 9];
|
|
r[10] = a[10] - b[10];
|
|
r[11] = a[11] - b[11];
|
|
r[12] = a[12] - b[12];
|
|
r[13] = a[13] - b[13];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_add_14(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
r[ 0] = a[ 0] + b[ 0];
|
|
r[ 1] = a[ 1] + b[ 1];
|
|
r[ 2] = a[ 2] + b[ 2];
|
|
r[ 3] = a[ 3] + b[ 3];
|
|
r[ 4] = a[ 4] + b[ 4];
|
|
r[ 5] = a[ 5] + b[ 5];
|
|
r[ 6] = a[ 6] + b[ 6];
|
|
r[ 7] = a[ 7] + b[ 7];
|
|
r[ 8] = a[ 8] + b[ 8];
|
|
r[ 9] = a[ 9] + b[ 9];
|
|
r[10] = a[10] + b[10];
|
|
r[11] = a[11] + b[11];
|
|
r[12] = a[12] + b[12];
|
|
r[13] = a[13] + b[13];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit p0[14];
|
|
sp_digit p1[14];
|
|
sp_digit p2[14];
|
|
sp_digit p3[14];
|
|
sp_digit p4[14];
|
|
sp_digit p5[14];
|
|
sp_digit t0[14];
|
|
sp_digit t1[14];
|
|
sp_digit t2[14];
|
|
sp_digit a0[7];
|
|
sp_digit a1[7];
|
|
sp_digit a2[7];
|
|
sp_digit b0[7];
|
|
sp_digit b1[7];
|
|
sp_digit b2[7];
|
|
(void)sp_1024_add_7(a0, a, &a[7]);
|
|
(void)sp_1024_add_7(b0, b, &b[7]);
|
|
(void)sp_1024_add_7(a1, &a[7], &a[14]);
|
|
(void)sp_1024_add_7(b1, &b[7], &b[14]);
|
|
(void)sp_1024_add_7(a2, a0, &a[14]);
|
|
(void)sp_1024_add_7(b2, b0, &b[14]);
|
|
sp_1024_mul_7(p0, a, b);
|
|
sp_1024_mul_7(p2, &a[7], &b[7]);
|
|
sp_1024_mul_7(p4, &a[14], &b[14]);
|
|
sp_1024_mul_7(p1, a0, b0);
|
|
sp_1024_mul_7(p3, a1, b1);
|
|
sp_1024_mul_7(p5, a2, b2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*21U);
|
|
(void)sp_1024_sub_14(t0, p3, p2);
|
|
(void)sp_1024_sub_14(t1, p1, p2);
|
|
(void)sp_1024_sub_14(t2, p5, t0);
|
|
(void)sp_1024_sub_14(t2, t2, t1);
|
|
(void)sp_1024_sub_14(t0, t0, p4);
|
|
(void)sp_1024_sub_14(t1, t1, p0);
|
|
(void)sp_1024_add_14(r, r, p0);
|
|
(void)sp_1024_add_14(&r[7], &r[7], t1);
|
|
(void)sp_1024_add_14(&r[14], &r[14], t2);
|
|
(void)sp_1024_add_14(&r[21], &r[21], t0);
|
|
(void)sp_1024_add_14(&r[28], &r[28], p4);
|
|
}
|
|
|
|
/* Square a into r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_sqr_21(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit p0[14];
|
|
sp_digit p1[14];
|
|
sp_digit p2[14];
|
|
sp_digit p3[14];
|
|
sp_digit p4[14];
|
|
sp_digit p5[14];
|
|
sp_digit t0[14];
|
|
sp_digit t1[14];
|
|
sp_digit t2[14];
|
|
sp_digit a0[7];
|
|
sp_digit a1[7];
|
|
sp_digit a2[7];
|
|
(void)sp_1024_add_7(a0, a, &a[7]);
|
|
(void)sp_1024_add_7(a1, &a[7], &a[14]);
|
|
(void)sp_1024_add_7(a2, a0, &a[14]);
|
|
sp_1024_sqr_7(p0, a);
|
|
sp_1024_sqr_7(p2, &a[7]);
|
|
sp_1024_sqr_7(p4, &a[14]);
|
|
sp_1024_sqr_7(p1, a0);
|
|
sp_1024_sqr_7(p3, a1);
|
|
sp_1024_sqr_7(p5, a2);
|
|
XMEMSET(r, 0, sizeof(*r)*2U*21U);
|
|
(void)sp_1024_sub_14(t0, p3, p2);
|
|
(void)sp_1024_sub_14(t1, p1, p2);
|
|
(void)sp_1024_sub_14(t2, p5, t0);
|
|
(void)sp_1024_sub_14(t2, t2, t1);
|
|
(void)sp_1024_sub_14(t0, t0, p4);
|
|
(void)sp_1024_sub_14(t1, t1, p0);
|
|
(void)sp_1024_add_14(r, r, p0);
|
|
(void)sp_1024_add_14(&r[7], &r[7], t1);
|
|
(void)sp_1024_add_14(&r[14], &r[14], t2);
|
|
(void)sp_1024_add_14(&r[21], &r[21], t0);
|
|
(void)sp_1024_add_14(&r[28], &r[28], p4);
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_add_21(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 16; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[16] = a[16] + b[16];
|
|
r[17] = a[17] + b[17];
|
|
r[18] = a[18] + b[18];
|
|
r[19] = a[19] + b[19];
|
|
r[20] = a[20] + b[20];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_add_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 40; i += 8) {
|
|
r[i + 0] = a[i + 0] + b[i + 0];
|
|
r[i + 1] = a[i + 1] + b[i + 1];
|
|
r[i + 2] = a[i + 2] + b[i + 2];
|
|
r[i + 3] = a[i + 3] + b[i + 3];
|
|
r[i + 4] = a[i + 4] + b[i + 4];
|
|
r[i + 5] = a[i + 5] + b[i + 5];
|
|
r[i + 6] = a[i + 6] + b[i + 6];
|
|
r[i + 7] = a[i + 7] + b[i + 7];
|
|
}
|
|
r[40] = a[40] + b[40];
|
|
r[41] = a[41] + b[41];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_sub_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 40; i += 8) {
|
|
r[i + 0] = a[i + 0] - b[i + 0];
|
|
r[i + 1] = a[i + 1] - b[i + 1];
|
|
r[i + 2] = a[i + 2] - b[i + 2];
|
|
r[i + 3] = a[i + 3] - b[i + 3];
|
|
r[i + 4] = a[i + 4] - b[i + 4];
|
|
r[i + 5] = a[i + 5] - b[i + 5];
|
|
r[i + 6] = a[i + 6] - b[i + 6];
|
|
r[i + 7] = a[i + 7] - b[i + 7];
|
|
}
|
|
r[40] = a[40] - b[40];
|
|
r[41] = a[41] - b[41];
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[42];
|
|
sp_digit* a1 = z1;
|
|
sp_digit b1[21];
|
|
sp_digit* z2 = r + 42;
|
|
(void)sp_1024_add_21(a1, a, &a[21]);
|
|
(void)sp_1024_add_21(b1, b, &b[21]);
|
|
sp_1024_mul_21(z2, &a[21], &b[21]);
|
|
sp_1024_mul_21(z0, a, b);
|
|
sp_1024_mul_21(z1, a1, b1);
|
|
(void)sp_1024_sub_42(z1, z1, z2);
|
|
(void)sp_1024_sub_42(z1, z1, z0);
|
|
(void)sp_1024_add_42(r + 21, r + 21, z1);
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_sqr_42(sp_digit* r, const sp_digit* a)
|
|
{
|
|
sp_digit* z0 = r;
|
|
sp_digit z1[42];
|
|
sp_digit* a1 = z1;
|
|
sp_digit* z2 = r + 42;
|
|
(void)sp_1024_add_21(a1, a, &a[21]);
|
|
sp_1024_sqr_21(z2, &a[21]);
|
|
sp_1024_sqr_21(z0, a);
|
|
sp_1024_sqr_21(z1, a1);
|
|
(void)sp_1024_sub_42(z1, z1, z2);
|
|
(void)sp_1024_sub_42(z1, z1, z0);
|
|
(void)sp_1024_add_42(r + 21, r + 21, z1);
|
|
}
|
|
|
|
#else
|
|
/* Multiply a and b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 lo;
|
|
|
|
c = ((sp_uint64)a[41]) * b[41];
|
|
r[83] = (sp_digit)(c >> 25);
|
|
c &= 0x1ffffff;
|
|
for (k = 81; k >= 0; k--) {
|
|
if (k >= 42) {
|
|
i = k - 41;
|
|
imax = 41;
|
|
}
|
|
else {
|
|
i = 0;
|
|
imax = k;
|
|
}
|
|
lo = 0;
|
|
for (; i <= imax; i++) {
|
|
lo += ((sp_uint64)a[i]) * b[k - i];
|
|
}
|
|
c += lo >> 25;
|
|
r[k + 2] += (sp_digit)(c >> 25);
|
|
r[k + 1] = (sp_digit)(c & 0x1ffffff);
|
|
c = lo & 0x1ffffff;
|
|
}
|
|
r[0] = (sp_digit)c;
|
|
}
|
|
|
|
/* Square a and put result in r. (r = a * a)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_sqr_42(sp_digit* r, const sp_digit* a)
|
|
{
|
|
int i;
|
|
int imax;
|
|
int k;
|
|
sp_uint64 c;
|
|
sp_uint64 t;
|
|
|
|
c = ((sp_uint64)a[41]) * a[41];
|
|
r[83] = (sp_digit)(c >> 25);
|
|
c = (c & 0x1ffffff) << 25;
|
|
for (k = 81; k >= 0; k--) {
|
|
i = (k + 1) / 2;
|
|
if ((k & 1) == 0) {
|
|
c += ((sp_uint64)a[i]) * a[i];
|
|
i++;
|
|
}
|
|
if (k < 41) {
|
|
imax = k;
|
|
}
|
|
else {
|
|
imax = 41;
|
|
}
|
|
t = 0;
|
|
for (; i <= imax; i++) {
|
|
t += ((sp_uint64)a[i]) * a[k - i];
|
|
}
|
|
c += t * 2;
|
|
|
|
r[k + 2] += (sp_digit) (c >> 50);
|
|
r[k + 1] = (sp_digit)((c >> 25) & 0x1ffffff);
|
|
c = (c & 0x1ffffff) << 25;
|
|
}
|
|
r[0] = (sp_digit)(c >> 25);
|
|
}
|
|
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
/* The modulus (prime) of the curve P1024. */
|
|
static const sp_digit p1024_mod[42] = {
|
|
0x0a85feb,0x0c03d7f,0x1a1d99b,0x0158f59,0x00c5df1,0x02bed84,0x1a08e26,
|
|
0x03ff9c7,0x156971f,0x1ca6b57,0x1026aa7,0x18a4387,0x02a7cf3,0x18c2954,
|
|
0x0bfd2a0,0x039c36d,0x1cd6568,0x0289562,0x09ad335,0x18c90e6,0x06d0e26,
|
|
0x1a53335,0x0d5b49f,0x1911432,0x1b39ff7,0x05873c8,0x14c6967,0x050e61a,
|
|
0x1c0f1b2,0x1593f17,0x0bbd02a,0x167c034,0x09ae358,0x04130df,0x138672d,
|
|
0x1482d81,0x1ad0657,0x0308cc6,0x0ff6997,0x03e14ac,0x0997abb,0x0000000
|
|
};
|
|
/* The Montgomery normalizer for modulus of the curve P1024. */
|
|
static const sp_digit p1024_norm_mod[42] = {
|
|
0x157a015,0x13fc280,0x05e2664,0x1ea70a6,0x1f3a20e,0x1d4127b,0x05f71d9,
|
|
0x1c00638,0x0a968e0,0x03594a8,0x0fd9558,0x075bc78,0x1d5830c,0x073d6ab,
|
|
0x1402d5f,0x1c63c92,0x0329a97,0x1d76a9d,0x1652cca,0x0736f19,0x192f1d9,
|
|
0x05accca,0x12a4b60,0x06eebcd,0x04c6008,0x1a78c37,0x0b39698,0x1af19e5,
|
|
0x03f0e4d,0x0a6c0e8,0x1442fd5,0x0983fcb,0x1651ca7,0x1becf20,0x0c798d2,
|
|
0x0b7d27e,0x052f9a8,0x1cf7339,0x1009668,0x1c1eb53,0x0668544,0x0000000
|
|
};
|
|
/* The Montgomery multiplier for modulus of the curve P1024. */
|
|
static sp_digit p1024_mp_mod = 0x8f2f3d;
|
|
#if defined(WOLFSSL_SP_SMALL) || defined(HAVE_ECC_CHECK_KEY)
|
|
/* The order of the curve P1024. */
|
|
static const sp_digit p1024_order[42] = {
|
|
0x1aa17fb,0x1b00f5f,0x0e87666,0x08563d6,0x003177c,0x10afb61,0x1e82389,
|
|
0x18ffe71,0x1d5a5c7,0x1f29ad5,0x1c09aa9,0x1e290e1,0x00a9f3c,0x0630a55,
|
|
0x0aff4a8,0x00e70db,0x173595a,0x08a2558,0x126b4cd,0x1632439,0x09b4389,
|
|
0x1e94ccd,0x1356d27,0x1e4450c,0x06ce7fd,0x1961cf2,0x1531a59,0x1143986,
|
|
0x1f03c6c,0x1564fc5,0x02ef40a,0x059f00d,0x1a6b8d6,0x0904c37,0x0ce19cb,
|
|
0x1d20b60,0x16b4195,0x18c2331,0x03fda65,0x18f852b,0x0265eae,0x0000000
|
|
};
|
|
#endif
|
|
/* The base point of curve P1024. */
|
|
static const sp_point_1024 p1024_base = {
|
|
/* X ordinate */
|
|
{
|
|
0x0e63895,0x0e455f5,0x05e6203,0x092cfc1,0x00ec46c,0x1fb9f64,0x18e96d8,
|
|
0x10fdd22,0x080728d,0x0e7da66,0x1a44375,0x029b74c,0x14a7c15,0x1d306f3,
|
|
0x00b0ce5,0x1e5c34e,0x0548b72,0x199be43,0x1756f32,0x015eecb,0x0890976,
|
|
0x13a0367,0x1c62f67,0x13bf4aa,0x1f22cdb,0x10821ea,0x00c2c27,0x1621b72,
|
|
0x0e2308a,0x1b607b6,0x0fed7b6,0x16dfef9,0x0b2f204,0x034e34c,0x1f582bb,
|
|
0x1456345,0x1ed9b52,0x1cc8029,0x0a6b429,0x1dc6658,0x053fc09,0x0000000,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0
|
|
},
|
|
/* Y ordinate */
|
|
{
|
|
0x1ef16d7,0x19feb8d,0x1379d55,0x00d4cfb,0x0db9b57,0x1da31b5,0x0b56b56,
|
|
0x153017b,0x1e9cb99,0x1a8ad6b,0x1357c84,0x0f3f8b4,0x09492d9,0x0b2554c,
|
|
0x1bc7a00,0x05fc158,0x0b5b765,0x0656b4b,0x1551f1b,0x15c22f5,0x12b970d,
|
|
0x0654f01,0x105b3fc,0x028165c,0x18ccf9a,0x0fb35ac,0x17c3795,0x0fefebc,
|
|
0x0ec2b9e,0x14fa32a,0x1e3d7a9,0x03c2822,0x1778d82,0x0834b1e,0x00580a6,
|
|
0x0ba7d04,0x1634a13,0x18f8299,0x027c7e7,0x00c7ec0,0x00a8249,0x0000000,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0
|
|
},
|
|
/* Z ordinate */
|
|
{
|
|
0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0, (sp_digit)0,
|
|
(sp_digit)0, (sp_digit)0
|
|
},
|
|
/* infinity */
|
|
0
|
|
};
|
|
|
|
/* Normalize the values in each word to 25 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_1024_norm_41(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 40; i++) {
|
|
a[i+1] += a[i] >> 25;
|
|
a[i] &= 0x1ffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 40; i += 8) {
|
|
a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff;
|
|
a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff;
|
|
a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff;
|
|
a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff;
|
|
a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff;
|
|
a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff;
|
|
a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff;
|
|
a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff;
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_d_42(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
}
|
|
r[42] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 40; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
t += tb * a[40];
|
|
r[40] = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
t += tb * a[41];
|
|
r[41] = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[42] = (sp_digit)(t & 0x1ffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Multiply a by scalar b into r. (r = a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_d_84(sp_digit* r, const sp_digit* a,
|
|
sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
int i;
|
|
|
|
for (i = 0; i < 84; i++) {
|
|
t += tb * a[i];
|
|
r[i] = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
}
|
|
r[84] = (sp_digit)t;
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t = 0;
|
|
sp_digit t2;
|
|
sp_int64 p[4];
|
|
int i;
|
|
|
|
for (i = 0; i < 84; i += 4) {
|
|
p[0] = tb * a[i + 0];
|
|
p[1] = tb * a[i + 1];
|
|
p[2] = tb * a[i + 2];
|
|
p[3] = tb * a[i + 3];
|
|
t += p[0];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 0] = (sp_digit)t2;
|
|
t += p[1];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 1] = (sp_digit)t2;
|
|
t += p[2];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 2] = (sp_digit)t2;
|
|
t += p[3];
|
|
t2 = (sp_digit)(t & 0x1ffffff);
|
|
t >>= 25;
|
|
r[i + 3] = (sp_digit)t2;
|
|
}
|
|
r[84] = (sp_digit)(t & 0x1ffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_1024_cond_add_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
r[i] = a[i] + (b[i] & m);
|
|
}
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Conditionally add a and b using the mask m.
|
|
* m is -1 to add and 0 when not.
|
|
*
|
|
* r A single precision number representing conditional add result.
|
|
* a A single precision number to add with.
|
|
* b A single precision number to add.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_1024_cond_add_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 40; i += 8) {
|
|
r[i + 0] = a[i + 0] + (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] + (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] + (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] + (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] + (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] + (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] + (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] + (b[i + 7] & m);
|
|
}
|
|
r[40] = a[40] + (b[40] & m);
|
|
r[41] = a[41] + (b[41] & m);
|
|
}
|
|
#endif /* !WOLFSSL_SP_SMALL */
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Sub b from a into r. (r = a - b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_sub_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
r[i] = a[i] - b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#endif
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Add b to a into r. (r = a + b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
*/
|
|
SP_NOINLINE static int sp_1024_add_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
r[i] = a[i] + b[i];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
SP_NOINLINE static void sp_1024_rshift_42(sp_digit* r, const sp_digit* a,
|
|
byte n)
|
|
{
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
for (i=0; i<41; i++) {
|
|
r[i] = ((a[i] >> n) | (a[i + 1] << (25 - n))) & 0x1ffffff;
|
|
}
|
|
#else
|
|
for (i=0; i<40; i += 8) {
|
|
r[i+0] = (a[i+0] >> n) | ((a[i+1] << (25 - n)) & 0x1ffffff);
|
|
r[i+1] = (a[i+1] >> n) | ((a[i+2] << (25 - n)) & 0x1ffffff);
|
|
r[i+2] = (a[i+2] >> n) | ((a[i+3] << (25 - n)) & 0x1ffffff);
|
|
r[i+3] = (a[i+3] >> n) | ((a[i+4] << (25 - n)) & 0x1ffffff);
|
|
r[i+4] = (a[i+4] >> n) | ((a[i+5] << (25 - n)) & 0x1ffffff);
|
|
r[i+5] = (a[i+5] >> n) | ((a[i+6] << (25 - n)) & 0x1ffffff);
|
|
r[i+6] = (a[i+6] >> n) | ((a[i+7] << (25 - n)) & 0x1ffffff);
|
|
r[i+7] = (a[i+7] >> n) | ((a[i+8] << (25 - n)) & 0x1ffffff);
|
|
}
|
|
r[40] = (a[40] >> n) | ((a[41] << (25 - n)) & 0x1ffffff);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
r[41] = a[41] >> n;
|
|
}
|
|
|
|
static WC_INLINE sp_digit sp_1024_div_word_42(sp_digit d1, sp_digit d0,
|
|
sp_digit div)
|
|
{
|
|
#ifdef SP_USE_DIVTI3
|
|
sp_int64 d = ((sp_int64)d1 << 25) + d0;
|
|
|
|
return d / div;
|
|
#elif defined(__x86_64__) || defined(__i386__)
|
|
sp_int64 d = ((sp_int64)d1 << 25) + d0;
|
|
sp_uint32 lo = (sp_uint32)d;
|
|
sp_digit hi = (sp_digit)(d >> 32);
|
|
|
|
__asm__ __volatile__ (
|
|
"idiv %2"
|
|
: "+a" (lo)
|
|
: "d" (hi), "r" (div)
|
|
: "cc"
|
|
);
|
|
|
|
return (sp_digit)lo;
|
|
#elif !defined(__aarch64__) && !defined(SP_DIV_WORD_USE_DIV)
|
|
sp_int64 d = ((sp_int64)d1 << 25) + d0;
|
|
sp_digit dv = (div >> 1) + 1;
|
|
sp_digit t1 = (sp_digit)(d >> 25);
|
|
sp_digit t0 = (sp_digit)(d & 0x1ffffff);
|
|
sp_digit t2;
|
|
sp_digit sign;
|
|
sp_digit r;
|
|
int i;
|
|
sp_int64 m;
|
|
|
|
r = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
t1 -= dv & (0 - r);
|
|
for (i = 23; i >= 1; i--) {
|
|
t1 += t1 + (((sp_uint32)t0 >> 24) & 1);
|
|
t0 <<= 1;
|
|
t2 = (sp_digit)(((sp_uint32)(dv - t1)) >> 31);
|
|
r += r + t2;
|
|
t1 -= dv & (0 - t2);
|
|
t1 += t2;
|
|
}
|
|
r += r + 1;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 25);
|
|
m = d - ((sp_int64)r * div);
|
|
r += (sp_digit)(m >> 50) - (sp_digit)(d >> 50);
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
|
|
m = d - ((sp_int64)r * div);
|
|
sign = (sp_digit)(0 - ((sp_uint32)m >> 31)) * 2 + 1;
|
|
m *= sign;
|
|
t2 = (sp_digit)(((sp_uint32)(div - m)) >> 31);
|
|
r += sign * t2;
|
|
return r;
|
|
#else
|
|
sp_int64 d = ((sp_int64)d1 << 25) + d0;
|
|
sp_digit r = 0;
|
|
sp_digit t;
|
|
sp_digit dv = (div >> 10) + 1;
|
|
|
|
t = (sp_digit)(d >> 20);
|
|
t = (t / dv) << 10;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)(d >> 5);
|
|
t = t / (dv << 5);
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
t = (sp_digit)d;
|
|
t = t / div;
|
|
r += t;
|
|
d -= (sp_int64)t * div;
|
|
return r;
|
|
#endif
|
|
}
|
|
static WC_INLINE sp_digit sp_1024_word_div_word_42(sp_digit d, sp_digit div)
|
|
{
|
|
#if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || \
|
|
defined(SP_DIV_WORD_USE_DIV)
|
|
return d / div;
|
|
#else
|
|
return (sp_digit)((sp_uint32)(div - d) >> 31);
|
|
#endif
|
|
}
|
|
/* Divide d in a and put remainder into r (m*d + r = a)
|
|
* m is not calculated as it is not needed at this time.
|
|
*
|
|
* Full implementation.
|
|
*
|
|
* a Number to be divided.
|
|
* d Number to divide with.
|
|
* m Multiplier result.
|
|
* r Remainder from the division.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_1024_div_42(const sp_digit* a, const sp_digit* d,
|
|
const sp_digit* m, sp_digit* r)
|
|
{
|
|
int i;
|
|
#ifndef WOLFSSL_SP_DIV_32
|
|
#endif
|
|
sp_digit dv;
|
|
sp_digit r1;
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[4 * 42 + 3];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_digit* sd = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
(void)m;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 42 + 3), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
(void)m;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 84 + 1;
|
|
sd = t2 + 42 + 1;
|
|
|
|
sp_1024_mul_d_42(sd, d, (sp_digit)1 << 1);
|
|
sp_1024_mul_d_84(t1, a, (sp_digit)1 << 1);
|
|
dv = sd[40];
|
|
t1[41 + 41] += t1[41 + 41 - 1] >> 25;
|
|
t1[41 + 41 - 1] &= 0x1ffffff;
|
|
for (i=41; i>=0; i--) {
|
|
r1 = sp_1024_div_word_42(t1[41 + i], t1[41 + i - 1], dv);
|
|
|
|
sp_1024_mul_d_42(t2, sd, r1);
|
|
(void)sp_1024_sub_42(&t1[i], &t1[i], t2);
|
|
sp_1024_norm_41(&t1[i]);
|
|
t1[41 + i] += t1[41 + i - 1] >> 25;
|
|
t1[41 + i - 1] &= 0x1ffffff;
|
|
r1 = sp_1024_div_word_42(-t1[41 + i], -t1[41 + i - 1], dv);
|
|
r1 -= t1[41 + i];
|
|
sp_1024_mul_d_42(t2, sd, r1);
|
|
(void)sp_1024_add_42(&t1[i], &t1[i], t2);
|
|
t1[41 + i] += t1[41 + i - 1] >> 25;
|
|
t1[41 + i - 1] &= 0x1ffffff;
|
|
}
|
|
t1[41 - 1] += t1[41 - 2] >> 25;
|
|
t1[41 - 2] &= 0x1ffffff;
|
|
r1 = sp_1024_word_div_word_42(t1[41 - 1], dv);
|
|
|
|
sp_1024_mul_d_42(t2, sd, r1);
|
|
sp_1024_sub_42(t1, t1, t2);
|
|
XMEMCPY(r, t1, sizeof(*r) * 84U);
|
|
for (i=0; i<40; i++) {
|
|
r[i+1] += r[i] >> 25;
|
|
r[i] &= 0x1ffffff;
|
|
}
|
|
sp_1024_cond_add_42(r, r, sd, r[40] >> 31);
|
|
|
|
sp_1024_norm_41(r);
|
|
sp_1024_rshift_42(r, r, 1);
|
|
r[41] = 0;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Reduce a modulo m into r. (r = a mod m)
|
|
*
|
|
* r A single precision number that is the reduced result.
|
|
* a A single precision number that is to be reduced.
|
|
* m A single precision number that is the modulus to reduce with.
|
|
* returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_1024_mod_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
return sp_1024_div_42(a, m, NULL, r);
|
|
}
|
|
|
|
/* Multiply a number by Montgomery normalizer mod modulus (prime).
|
|
*
|
|
* r The resulting Montgomery form number.
|
|
* a The number to convert.
|
|
* m The modulus (prime).
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_1024_mod_mul_norm_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m)
|
|
{
|
|
sp_1024_mul_42(r, a, p1024_norm_mod);
|
|
return sp_1024_mod_42(r, r, m);
|
|
}
|
|
|
|
|
|
#ifdef WOLFCRYPT_HAVE_SAKKE
|
|
/* Create a new point.
|
|
*
|
|
* heap [in] Buffer to allocate dynamic memory from.
|
|
* sp [in] Data for point - only if not allocating.
|
|
* p [out] New point.
|
|
* returns MEMORY_E when dynamic memory allocation fails and 0 otherwise.
|
|
*/
|
|
static int sp_1024_point_new_ex_42(void* heap, sp_point_1024* sp,
|
|
sp_point_1024** p)
|
|
{
|
|
int ret = MP_OKAY;
|
|
(void)heap;
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
(void)sp;
|
|
*p = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap, DYNAMIC_TYPE_ECC);
|
|
#else
|
|
*p = sp;
|
|
#endif
|
|
if (*p == NULL) {
|
|
ret = MEMORY_E;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
/* Allocate memory for point and return error. */
|
|
#define sp_1024_point_new_42(heap, sp, p) sp_1024_point_new_ex_42((heap), NULL, &(p))
|
|
#else
|
|
/* Set pointer to data and return no error. */
|
|
#define sp_1024_point_new_42(heap, sp, p) sp_1024_point_new_ex_42((heap), &(sp), &(p))
|
|
#endif
|
|
#endif /* WOLFCRYPT_HAVE_SAKKE */
|
|
#ifdef WOLFCRYPT_HAVE_SAKKE
|
|
/* Free the point.
|
|
*
|
|
* p [in,out] Point to free.
|
|
* clear [in] Indicates whether to zeroize point.
|
|
* heap [in] Buffer from which dynamic memory was allocate from.
|
|
*/
|
|
static void sp_1024_point_free_42(sp_point_1024* p, int clear, void* heap)
|
|
{
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
/* If valid pointer then clear point data if requested and free data. */
|
|
if (p != NULL) {
|
|
if (clear != 0) {
|
|
XMEMSET(p, 0, sizeof(*p));
|
|
}
|
|
XFREE(p, heap, DYNAMIC_TYPE_ECC);
|
|
}
|
|
#else
|
|
/* Clear point data if requested. */
|
|
if ((p != NULL) && (clear != 0)) {
|
|
XMEMSET(p, 0, sizeof(*p));
|
|
}
|
|
#endif
|
|
(void)heap;
|
|
}
|
|
#endif /* WOLFCRYPT_HAVE_SAKKE */
|
|
|
|
/* Convert an mp_int to an array of sp_digit.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a A multi-precision integer.
|
|
*/
|
|
static void sp_1024_from_mp(sp_digit* r, int size, const mp_int* a)
|
|
{
|
|
#if DIGIT_BIT == 25
|
|
int i;
|
|
int j = 0;
|
|
|
|
for (i = 0; i < size; i++) {
|
|
sp_digit mask =
|
|
(((sp_digit)((int)a->used - i - 1)) >> (SP_WORD_SIZE - 1)) - 1;
|
|
r[i] = a->dp[j] & mask;
|
|
j += (int)(((sp_digit)1) -
|
|
(((sp_digit)((int)a->used - i - 2)) >> (SP_WORD_SIZE - 1)));
|
|
}
|
|
#elif DIGIT_BIT > 25
|
|
unsigned int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i] << s);
|
|
r[j] &= 0x1ffffff;
|
|
s = 25U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
while ((s + 25U) <= (word32)DIGIT_BIT) {
|
|
s += 25U;
|
|
r[j] &= 0x1ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
if (s < (word32)DIGIT_BIT) {
|
|
/* lint allow cast of mismatch word32 and mp_digit */
|
|
r[++j] = (sp_digit)(a->dp[i] >> s); /*lint !e9033*/
|
|
}
|
|
else {
|
|
r[++j] = (sp_digit)0;
|
|
}
|
|
}
|
|
s = (word32)DIGIT_BIT - s;
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#else
|
|
unsigned int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = 0; i < (unsigned int)a->used && j < size; i++) {
|
|
r[j] |= ((sp_digit)a->dp[i]) << s;
|
|
if (s + DIGIT_BIT >= 25) {
|
|
r[j] &= 0x1ffffff;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
s = 25 - s;
|
|
if (s == DIGIT_BIT) {
|
|
r[++j] = 0;
|
|
s = 0;
|
|
}
|
|
else {
|
|
r[++j] = a->dp[i] >> s;
|
|
s = DIGIT_BIT - s;
|
|
}
|
|
}
|
|
else {
|
|
s += DIGIT_BIT;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Convert a point of type ecc_point to type sp_point_1024.
|
|
*
|
|
* p Point of type sp_point_1024 (result).
|
|
* pm Point of type ecc_point.
|
|
*/
|
|
static void sp_1024_point_from_ecc_point_42(sp_point_1024* p,
|
|
const ecc_point* pm)
|
|
{
|
|
XMEMSET(p->x, 0, sizeof(p->x));
|
|
XMEMSET(p->y, 0, sizeof(p->y));
|
|
XMEMSET(p->z, 0, sizeof(p->z));
|
|
sp_1024_from_mp(p->x, 42, pm->x);
|
|
sp_1024_from_mp(p->y, 42, pm->y);
|
|
sp_1024_from_mp(p->z, 42, pm->z);
|
|
p->infinity = 0;
|
|
}
|
|
|
|
/* Convert an array of sp_digit to an mp_int.
|
|
*
|
|
* a A single precision integer.
|
|
* r A multi-precision integer.
|
|
*/
|
|
static int sp_1024_to_mp(const sp_digit* a, mp_int* r)
|
|
{
|
|
int err;
|
|
|
|
err = mp_grow(r, (1024 + DIGIT_BIT - 1) / DIGIT_BIT);
|
|
if (err == MP_OKAY) { /*lint !e774 case where err is always MP_OKAY*/
|
|
#if DIGIT_BIT == 25
|
|
XMEMCPY(r->dp, a, sizeof(sp_digit) * 41);
|
|
r->used = 41;
|
|
mp_clamp(r);
|
|
#elif DIGIT_BIT < 25
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 41; i++) {
|
|
r->dp[j] |= (mp_digit)(a[i] << s);
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = (mp_digit)(a[i] >> s);
|
|
while (s + DIGIT_BIT <= 25) {
|
|
s += DIGIT_BIT;
|
|
r->dp[j++] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
if (s == SP_WORD_SIZE) {
|
|
r->dp[j] = 0;
|
|
}
|
|
else {
|
|
r->dp[j] = (mp_digit)(a[i] >> s);
|
|
}
|
|
}
|
|
s = 25 - s;
|
|
}
|
|
r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#else
|
|
int i;
|
|
int j = 0;
|
|
int s = 0;
|
|
|
|
r->dp[0] = 0;
|
|
for (i = 0; i < 41; i++) {
|
|
r->dp[j] |= ((mp_digit)a[i]) << s;
|
|
if (s + 25 >= DIGIT_BIT) {
|
|
#if DIGIT_BIT != 32 && DIGIT_BIT != 64
|
|
r->dp[j] &= ((sp_digit)1 << DIGIT_BIT) - 1;
|
|
#endif
|
|
s = DIGIT_BIT - s;
|
|
r->dp[++j] = a[i] >> s;
|
|
s = 25 - s;
|
|
}
|
|
else {
|
|
s += 25;
|
|
}
|
|
}
|
|
r->used = (1024 + DIGIT_BIT - 1) / DIGIT_BIT;
|
|
mp_clamp(r);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Convert a point of type sp_point_1024 to type ecc_point.
|
|
*
|
|
* p Point of type sp_point_1024.
|
|
* pm Point of type ecc_point (result).
|
|
* returns MEMORY_E when allocation of memory in ecc_point fails otherwise
|
|
* MP_OKAY.
|
|
*/
|
|
static int sp_1024_point_to_ecc_point_42(const sp_point_1024* p, ecc_point* pm)
|
|
{
|
|
int err;
|
|
|
|
err = sp_1024_to_mp(p->x, pm->x);
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_to_mp(p->y, pm->y);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_to_mp(p->z, pm->z);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Compare a with b in constant time.
|
|
*
|
|
* a A single precision integer.
|
|
* b A single precision integer.
|
|
* return -ve, 0 or +ve if a is less than, equal to or greater than b
|
|
* respectively.
|
|
*/
|
|
static sp_digit sp_1024_cmp_42(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
sp_digit r = 0;
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=41; i>=0; i--) {
|
|
r |= (a[i] - b[i]) & ~(((sp_digit)0 - r) >> 24);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
r |= (a[41] - b[41]) & (0 - (sp_digit)1);
|
|
r |= (a[40] - b[40]) & ~(((sp_digit)0 - r) >> 24);
|
|
for (i = 32; i >= 0; i -= 8) {
|
|
r |= (a[i + 7] - b[i + 7]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 6] - b[i + 6]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 5] - b[i + 5]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 4] - b[i + 4]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 3] - b[i + 3]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 2] - b[i + 2]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 1] - b[i + 1]) & ~(((sp_digit)0 - r) >> 24);
|
|
r |= (a[i + 0] - b[i + 0]) & ~(((sp_digit)0 - r) >> 24);
|
|
}
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
|
|
return r;
|
|
}
|
|
|
|
/* Conditionally subtract b from a using the mask m.
|
|
* m is -1 to subtract and 0 when not.
|
|
*
|
|
* r A single precision number representing condition subtract result.
|
|
* a A single precision number to subtract from.
|
|
* b A single precision number to subtract.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_1024_cond_sub_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit m)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
r[i] = a[i] - (b[i] & m);
|
|
}
|
|
#else
|
|
int i;
|
|
|
|
for (i = 0; i < 40; i += 8) {
|
|
r[i + 0] = a[i + 0] - (b[i + 0] & m);
|
|
r[i + 1] = a[i + 1] - (b[i + 1] & m);
|
|
r[i + 2] = a[i + 2] - (b[i + 2] & m);
|
|
r[i + 3] = a[i + 3] - (b[i + 3] & m);
|
|
r[i + 4] = a[i + 4] - (b[i + 4] & m);
|
|
r[i + 5] = a[i + 5] - (b[i + 5] & m);
|
|
r[i + 6] = a[i + 6] - (b[i + 6] & m);
|
|
r[i + 7] = a[i + 7] - (b[i + 7] & m);
|
|
}
|
|
r[40] = a[40] - (b[40] & m);
|
|
r[41] = a[41] - (b[41] & m);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Mul a by scalar b and add into r. (r += a * b)
|
|
*
|
|
* r A single precision integer.
|
|
* a A single precision integer.
|
|
* b A scalar.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mul_add_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit b)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
sp_int64 tb = b;
|
|
sp_int64 t[4];
|
|
int i;
|
|
|
|
t[0] = 0;
|
|
for (i = 0; i < 40; i += 4) {
|
|
t[0] += (tb * a[i+0]) + r[i+0];
|
|
t[1] = (tb * a[i+1]) + r[i+1];
|
|
t[2] = (tb * a[i+2]) + r[i+2];
|
|
t[3] = (tb * a[i+3]) + r[i+3];
|
|
r[i+0] = t[0] & 0x1ffffff;
|
|
t[1] += t[0] >> 25;
|
|
r[i+1] = t[1] & 0x1ffffff;
|
|
t[2] += t[1] >> 25;
|
|
r[i+2] = t[2] & 0x1ffffff;
|
|
t[3] += t[2] >> 25;
|
|
r[i+3] = t[3] & 0x1ffffff;
|
|
t[0] = t[3] >> 25;
|
|
}
|
|
t[0] += (tb * a[40]) + r[40];
|
|
t[1] = (tb * a[41]) + r[41];
|
|
r[40] = t[0] & 0x1ffffff;
|
|
t[1] += t[0] >> 25;
|
|
r[41] = t[1] & 0x1ffffff;
|
|
r[42] += (sp_digit)(t[1] >> 25);
|
|
#else
|
|
sp_int64 tb = b;
|
|
sp_int64 t[8];
|
|
int i;
|
|
|
|
t[0] = tb * a[0]; r[0] += (sp_digit)(t[0] & 0x1ffffff);
|
|
for (i = 0; i < 40; i += 8) {
|
|
t[1] = tb * a[i+1];
|
|
r[i+1] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
|
|
t[2] = tb * a[i+2];
|
|
r[i+2] += (sp_digit)((t[1] >> 25) + (t[2] & 0x1ffffff));
|
|
t[3] = tb * a[i+3];
|
|
r[i+3] += (sp_digit)((t[2] >> 25) + (t[3] & 0x1ffffff));
|
|
t[4] = tb * a[i+4];
|
|
r[i+4] += (sp_digit)((t[3] >> 25) + (t[4] & 0x1ffffff));
|
|
t[5] = tb * a[i+5];
|
|
r[i+5] += (sp_digit)((t[4] >> 25) + (t[5] & 0x1ffffff));
|
|
t[6] = tb * a[i+6];
|
|
r[i+6] += (sp_digit)((t[5] >> 25) + (t[6] & 0x1ffffff));
|
|
t[7] = tb * a[i+7];
|
|
r[i+7] += (sp_digit)((t[6] >> 25) + (t[7] & 0x1ffffff));
|
|
t[0] = tb * a[i+8];
|
|
r[i+8] += (sp_digit)((t[7] >> 25) + (t[0] & 0x1ffffff));
|
|
}
|
|
t[1] = tb * a[41];
|
|
r[41] += (sp_digit)((t[0] >> 25) + (t[1] & 0x1ffffff));
|
|
r[42] += (sp_digit)(t[1] >> 25);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Normalize the values in each word to 25 bits.
|
|
*
|
|
* a Array of sp_digit to normalize.
|
|
*/
|
|
static void sp_1024_norm_42(sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
for (i = 0; i < 41; i++) {
|
|
a[i+1] += a[i] >> 25;
|
|
a[i] &= 0x1ffffff;
|
|
}
|
|
#else
|
|
int i;
|
|
for (i = 0; i < 40; i += 8) {
|
|
a[i+1] += a[i+0] >> 25; a[i+0] &= 0x1ffffff;
|
|
a[i+2] += a[i+1] >> 25; a[i+1] &= 0x1ffffff;
|
|
a[i+3] += a[i+2] >> 25; a[i+2] &= 0x1ffffff;
|
|
a[i+4] += a[i+3] >> 25; a[i+3] &= 0x1ffffff;
|
|
a[i+5] += a[i+4] >> 25; a[i+4] &= 0x1ffffff;
|
|
a[i+6] += a[i+5] >> 25; a[i+5] &= 0x1ffffff;
|
|
a[i+7] += a[i+6] >> 25; a[i+6] &= 0x1ffffff;
|
|
a[i+8] += a[i+7] >> 25; a[i+7] &= 0x1ffffff;
|
|
}
|
|
a[41] += a[40] >> 25; a[40] &= 0x1ffffff;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
/* Shift the result in the high 1024 bits down to the bottom.
|
|
*
|
|
* r A single precision number.
|
|
* a A single precision number.
|
|
*/
|
|
static void sp_1024_mont_shift_42(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
sp_uint32 n;
|
|
|
|
n = a[40] >> 24;
|
|
for (i = 0; i < 40; i++) {
|
|
n += (sp_uint32)a[41 + i] << 1;
|
|
r[i] = n & 0x1ffffff;
|
|
n >>= 25;
|
|
}
|
|
n += (sp_uint32)a[81] << 1;
|
|
r[40] = n;
|
|
#else
|
|
sp_uint32 n;
|
|
int i;
|
|
|
|
n = (sp_uint32)a[40];
|
|
n = n >> 24U;
|
|
for (i = 0; i < 40; i += 8) {
|
|
n += (sp_uint32)a[i+41] << 1U; r[i+0] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+42] << 1U; r[i+1] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+43] << 1U; r[i+2] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+44] << 1U; r[i+3] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+45] << 1U; r[i+4] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+46] << 1U; r[i+5] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+47] << 1U; r[i+6] = n & 0x1ffffff; n >>= 25U;
|
|
n += (sp_uint32)a[i+48] << 1U; r[i+7] = n & 0x1ffffff; n >>= 25U;
|
|
}
|
|
n += (sp_uint32)a[81] << 1U; r[40] = n;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
XMEMSET(&r[41], 0, sizeof(*r) * 41U);
|
|
}
|
|
|
|
/* Reduce the number back to 1024 bits using Montgomery reduction.
|
|
*
|
|
* a A single precision number to reduce in place.
|
|
* m The single precision number representing the modulus.
|
|
* mp The digit representing the negative inverse of m mod 2^n.
|
|
*/
|
|
static void sp_1024_mont_reduce_42(sp_digit* a, const sp_digit* m, sp_digit mp)
|
|
{
|
|
int i;
|
|
sp_digit mu;
|
|
sp_digit over;
|
|
|
|
sp_1024_norm_42(a + 41);
|
|
|
|
if (mp != 1) {
|
|
for (i=0; i<40; i++) {
|
|
mu = (a[i] * mp) & 0x1ffffff;
|
|
sp_1024_mul_add_42(a+i, m, mu);
|
|
a[i+1] += a[i] >> 25;
|
|
}
|
|
mu = (a[i] * mp) & 0xffffffL;
|
|
sp_1024_mul_add_42(a+i, m, mu);
|
|
a[i+1] += a[i] >> 25;
|
|
a[i] &= 0x1ffffff;
|
|
}
|
|
else {
|
|
for (i=0; i<40; i++) {
|
|
mu = a[i] & 0x1ffffff;
|
|
sp_1024_mul_add_42(a+i, m, mu);
|
|
a[i+1] += a[i] >> 25;
|
|
}
|
|
mu = a[i] & 0xffffffL;
|
|
sp_1024_mul_add_42(a+i, m, mu);
|
|
a[i+1] += a[i] >> 25;
|
|
a[i] &= 0x1ffffff;
|
|
}
|
|
sp_1024_norm_42(a + 41);
|
|
sp_1024_mont_shift_42(a, a);
|
|
over = a[40] - m[40];
|
|
sp_1024_cond_sub_42(a, a, m, ~((over - 1) >> 31));
|
|
sp_1024_norm_42(a);
|
|
}
|
|
|
|
/* Multiply two Montgomery form numbers mod the modulus (prime).
|
|
* (r = a * b mod m)
|
|
*
|
|
* r Result of multiplication.
|
|
* a First number to multiply in Montgomery form.
|
|
* b Second number to multiply in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mont_mul_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* b, const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_1024_mul_42(r, a, b);
|
|
sp_1024_mont_reduce_42(r, m, mp);
|
|
}
|
|
|
|
/* Square the Montgomery form number. (r = a * a mod m)
|
|
*
|
|
* r Result of squaring.
|
|
* a Number to square in Montgomery form.
|
|
* m Modulus (prime).
|
|
* mp Montgomery mulitplier.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_mont_sqr_42(sp_digit* r, const sp_digit* a,
|
|
const sp_digit* m, sp_digit mp)
|
|
{
|
|
sp_1024_sqr_42(r, a);
|
|
sp_1024_mont_reduce_42(r, m, mp);
|
|
}
|
|
|
|
/* Mod-2 for the P1024 curve. */
|
|
static const uint8_t p1024_mod_minus_2[] = {
|
|
6,0x06, 7,0x0f, 7,0x0b, 6,0x0c, 7,0x1e, 9,0x09, 7,0x0c, 7,0x1f,
|
|
6,0x16, 6,0x06, 7,0x0e, 8,0x10, 6,0x03, 8,0x11, 6,0x0d, 7,0x14,
|
|
9,0x12, 6,0x0f, 7,0x04, 9,0x0d, 6,0x00, 7,0x13, 6,0x01, 6,0x07,
|
|
8,0x0d, 8,0x00, 6,0x06, 9,0x17, 6,0x14, 6,0x15, 6,0x11, 6,0x0b,
|
|
9,0x0c, 6,0x1e, 13,0x14, 7,0x0e, 6,0x1d, 12,0x0a, 6,0x0b, 8,0x07,
|
|
6,0x18, 6,0x0f, 6,0x10, 8,0x1c, 7,0x16, 7,0x02, 6,0x01, 6,0x13,
|
|
10,0x15, 7,0x06, 8,0x14, 6,0x0c, 6,0x19, 7,0x10, 6,0x19, 6,0x19,
|
|
9,0x16, 7,0x19, 6,0x1f, 6,0x17, 6,0x12, 8,0x02, 6,0x01, 6,0x04,
|
|
6,0x15, 7,0x16, 6,0x04, 6,0x1f, 6,0x09, 7,0x06, 7,0x13, 7,0x09,
|
|
6,0x0d, 10,0x18, 6,0x06, 6,0x11, 6,0x04, 6,0x01, 6,0x13, 8,0x06,
|
|
6,0x0d, 8,0x13, 7,0x08, 6,0x08, 6,0x05, 7,0x0c, 7,0x0e, 7,0x15,
|
|
6,0x05, 7,0x14, 10,0x19, 6,0x10, 6,0x16, 6,0x15, 7,0x1f, 6,0x14,
|
|
6,0x0a, 10,0x11, 6,0x01, 7,0x05, 7,0x08, 8,0x0a, 7,0x1e, 7,0x1c,
|
|
6,0x1c, 7,0x09, 10,0x18, 7,0x1c, 10,0x06, 6,0x0a, 6,0x07, 6,0x19,
|
|
7,0x06, 6,0x0d, 7,0x0f, 7,0x0b, 7,0x05, 6,0x11, 6,0x1c, 7,0x1f,
|
|
6,0x1e, 7,0x18, 6,0x1e, 6,0x00, 6,0x03, 6,0x02, 7,0x10, 6,0x0b,
|
|
6,0x1b, 7,0x10, 6,0x00, 8,0x11, 7,0x1b, 6,0x18, 6,0x01, 7,0x0c,
|
|
7,0x1d, 7,0x13, 6,0x08, 7,0x1b, 8,0x13, 7,0x16, 13,0x1d, 7,0x1f,
|
|
6,0x0a, 6,0x01, 7,0x1f, 6,0x14, 1,0x01
|
|
};
|
|
|
|
/* Invert the number, in Montgomery form, modulo the modulus (prime) of the
|
|
* P1024 curve. (r = 1 / a mod m)
|
|
*
|
|
* r Inverse result.
|
|
* a Number to invert.
|
|
* td Temporary data.
|
|
*/
|
|
static void sp_1024_mont_inv_42(sp_digit* r, const sp_digit* a,
|
|
sp_digit* td)
|
|
{
|
|
sp_digit* t = &td[32 * 2 * 42];
|
|
int i;
|
|
int j;
|
|
sp_digit* table[32];
|
|
|
|
for (i = 0; i < 32; i++) {
|
|
table[i] = &td[2 * 42 * i];
|
|
}
|
|
XMEMCPY(table[0], a, sizeof(sp_digit) * 42);
|
|
for (i = 1; i < 6; i++) {
|
|
sp_1024_mont_sqr_42(table[0], table[0], p1024_mod, p1024_mp_mod);
|
|
}
|
|
for (i = 1; i < 32; i++) {
|
|
sp_1024_mont_mul_42(table[i], table[i-1], a, p1024_mod, p1024_mp_mod);
|
|
}
|
|
|
|
XMEMCPY(t, table[p1024_mod_minus_2[1]], sizeof(sp_digit) * 42);
|
|
for (i = 2; i < (int)sizeof(p1024_mod_minus_2) - 2; i += 2) {
|
|
for (j = 0; j < p1024_mod_minus_2[i]; j++) {
|
|
sp_1024_mont_sqr_42(t, t, p1024_mod, p1024_mp_mod);
|
|
}
|
|
sp_1024_mont_mul_42(t, t, table[p1024_mod_minus_2[i+1]], p1024_mod,
|
|
p1024_mp_mod);
|
|
}
|
|
sp_1024_mont_sqr_42(t, t, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(r, t, a, p1024_mod, p1024_mp_mod);
|
|
}
|
|
|
|
/* Map the Montgomery form projective coordinate point to an affine point.
|
|
*
|
|
* r Resulting affine coordinate point.
|
|
* p Montgomery form projective coordinate point.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_map_42(sp_point_1024* r, const sp_point_1024* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*42;
|
|
sp_int32 n;
|
|
|
|
sp_1024_mont_inv_42(t1, p->z, t + 2*42);
|
|
|
|
sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod);
|
|
|
|
/* x /= z^2 */
|
|
sp_1024_mont_mul_42(r->x, p->x, t2, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(r->x + 42, 0, sizeof(sp_digit) * 42U);
|
|
sp_1024_mont_reduce_42(r->x, p1024_mod, p1024_mp_mod);
|
|
/* Reduce x to less than modulus */
|
|
n = sp_1024_cmp_42(r->x, p1024_mod);
|
|
sp_1024_cond_sub_42(r->x, r->x, p1024_mod, ~(n >> 24));
|
|
sp_1024_norm_42(r->x);
|
|
|
|
/* y /= z^3 */
|
|
sp_1024_mont_mul_42(r->y, p->y, t1, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(r->y + 42, 0, sizeof(sp_digit) * 42U);
|
|
sp_1024_mont_reduce_42(r->y, p1024_mod, p1024_mp_mod);
|
|
/* Reduce y to less than modulus */
|
|
n = sp_1024_cmp_42(r->y, p1024_mod);
|
|
sp_1024_cond_sub_42(r->y, r->y, p1024_mod, ~(n >> 24));
|
|
sp_1024_norm_42(r->y);
|
|
|
|
XMEMSET(r->z, 0, sizeof(r->z) / 2);
|
|
r->z[0] = 1;
|
|
}
|
|
|
|
/* Add two Montgomery form numbers (r = a + b % m).
|
|
*
|
|
* r Result of addition.
|
|
* a First number to add in Montgomery form.
|
|
* b Second number to add in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_1024_mont_add_42(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_1024_add_42(r, a, b);
|
|
sp_1024_norm_42(r);
|
|
over = r[40] - m[40];
|
|
sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
|
|
sp_1024_norm_42(r);
|
|
}
|
|
|
|
/* Double a Montgomery form number (r = a + a % m).
|
|
*
|
|
* r Result of doubling.
|
|
* a Number to double in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_1024_mont_dbl_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_1024_add_42(r, a, a);
|
|
sp_1024_norm_42(r);
|
|
over = r[40] - m[40];
|
|
sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
|
|
sp_1024_norm_42(r);
|
|
}
|
|
|
|
/* Triple a Montgomery form number (r = a + a + a % m).
|
|
*
|
|
* r Result of Tripling.
|
|
* a Number to triple in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_1024_mont_tpl_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_digit over;
|
|
(void)sp_1024_add_42(r, a, a);
|
|
sp_1024_norm_42(r);
|
|
over = r[40] - m[40];
|
|
sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
|
|
sp_1024_norm_42(r);
|
|
(void)sp_1024_add_42(r, r, a);
|
|
sp_1024_norm_42(r);
|
|
over = r[40] - m[40];
|
|
sp_1024_cond_sub_42(r, r, m, ~((over - 1) >> 31));
|
|
sp_1024_norm_42(r);
|
|
}
|
|
|
|
/* Subtract two Montgomery form numbers (r = a - b % m).
|
|
*
|
|
* r Result of subtration.
|
|
* a Number to subtract from in Montgomery form.
|
|
* b Number to subtract with in Montgomery form.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_1024_mont_sub_42(sp_digit* r, const sp_digit* a, const sp_digit* b,
|
|
const sp_digit* m)
|
|
{
|
|
(void)sp_1024_sub_42(r, a, b);
|
|
sp_1024_norm_42(r);
|
|
sp_1024_cond_add_42(r, r, m, r[41] >> 7);
|
|
sp_1024_norm_42(r);
|
|
}
|
|
|
|
#define sp_1024_mont_sub_lower_42 sp_1024_mont_sub_42
|
|
/* Shift number left one bit.
|
|
* Bottom bit is lost.
|
|
*
|
|
* r Result of shift.
|
|
* a Number to shift.
|
|
*/
|
|
SP_NOINLINE static void sp_1024_rshift1_42(sp_digit* r, const sp_digit* a)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i=0; i<41; i++) {
|
|
r[i] = (a[i] >> 1) + ((a[i + 1] << 24) & 0x1ffffff);
|
|
}
|
|
#else
|
|
r[0] = (a[0] >> 1) + ((a[1] << 24) & 0x1ffffff);
|
|
r[1] = (a[1] >> 1) + ((a[2] << 24) & 0x1ffffff);
|
|
r[2] = (a[2] >> 1) + ((a[3] << 24) & 0x1ffffff);
|
|
r[3] = (a[3] >> 1) + ((a[4] << 24) & 0x1ffffff);
|
|
r[4] = (a[4] >> 1) + ((a[5] << 24) & 0x1ffffff);
|
|
r[5] = (a[5] >> 1) + ((a[6] << 24) & 0x1ffffff);
|
|
r[6] = (a[6] >> 1) + ((a[7] << 24) & 0x1ffffff);
|
|
r[7] = (a[7] >> 1) + ((a[8] << 24) & 0x1ffffff);
|
|
r[8] = (a[8] >> 1) + ((a[9] << 24) & 0x1ffffff);
|
|
r[9] = (a[9] >> 1) + ((a[10] << 24) & 0x1ffffff);
|
|
r[10] = (a[10] >> 1) + ((a[11] << 24) & 0x1ffffff);
|
|
r[11] = (a[11] >> 1) + ((a[12] << 24) & 0x1ffffff);
|
|
r[12] = (a[12] >> 1) + ((a[13] << 24) & 0x1ffffff);
|
|
r[13] = (a[13] >> 1) + ((a[14] << 24) & 0x1ffffff);
|
|
r[14] = (a[14] >> 1) + ((a[15] << 24) & 0x1ffffff);
|
|
r[15] = (a[15] >> 1) + ((a[16] << 24) & 0x1ffffff);
|
|
r[16] = (a[16] >> 1) + ((a[17] << 24) & 0x1ffffff);
|
|
r[17] = (a[17] >> 1) + ((a[18] << 24) & 0x1ffffff);
|
|
r[18] = (a[18] >> 1) + ((a[19] << 24) & 0x1ffffff);
|
|
r[19] = (a[19] >> 1) + ((a[20] << 24) & 0x1ffffff);
|
|
r[20] = (a[20] >> 1) + ((a[21] << 24) & 0x1ffffff);
|
|
r[21] = (a[21] >> 1) + ((a[22] << 24) & 0x1ffffff);
|
|
r[22] = (a[22] >> 1) + ((a[23] << 24) & 0x1ffffff);
|
|
r[23] = (a[23] >> 1) + ((a[24] << 24) & 0x1ffffff);
|
|
r[24] = (a[24] >> 1) + ((a[25] << 24) & 0x1ffffff);
|
|
r[25] = (a[25] >> 1) + ((a[26] << 24) & 0x1ffffff);
|
|
r[26] = (a[26] >> 1) + ((a[27] << 24) & 0x1ffffff);
|
|
r[27] = (a[27] >> 1) + ((a[28] << 24) & 0x1ffffff);
|
|
r[28] = (a[28] >> 1) + ((a[29] << 24) & 0x1ffffff);
|
|
r[29] = (a[29] >> 1) + ((a[30] << 24) & 0x1ffffff);
|
|
r[30] = (a[30] >> 1) + ((a[31] << 24) & 0x1ffffff);
|
|
r[31] = (a[31] >> 1) + ((a[32] << 24) & 0x1ffffff);
|
|
r[32] = (a[32] >> 1) + ((a[33] << 24) & 0x1ffffff);
|
|
r[33] = (a[33] >> 1) + ((a[34] << 24) & 0x1ffffff);
|
|
r[34] = (a[34] >> 1) + ((a[35] << 24) & 0x1ffffff);
|
|
r[35] = (a[35] >> 1) + ((a[36] << 24) & 0x1ffffff);
|
|
r[36] = (a[36] >> 1) + ((a[37] << 24) & 0x1ffffff);
|
|
r[37] = (a[37] >> 1) + ((a[38] << 24) & 0x1ffffff);
|
|
r[38] = (a[38] >> 1) + ((a[39] << 24) & 0x1ffffff);
|
|
r[39] = (a[39] >> 1) + ((a[40] << 24) & 0x1ffffff);
|
|
r[40] = (a[40] >> 1) + ((a[41] << 24) & 0x1ffffff);
|
|
#endif
|
|
r[41] = a[41] >> 1;
|
|
}
|
|
|
|
/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m)
|
|
*
|
|
* r Result of division by 2.
|
|
* a Number to divide.
|
|
* m Modulus (prime).
|
|
*/
|
|
static void sp_1024_div2_42(sp_digit* r, const sp_digit* a, const sp_digit* m)
|
|
{
|
|
sp_1024_cond_add_42(r, a, m, 0 - (a[0] & 1));
|
|
sp_1024_norm_42(r);
|
|
sp_1024_rshift1_42(r, r);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_proj_point_dbl_42(sp_point_1024* r, const sp_point_1024* p,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*42;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
|
|
x = r->x;
|
|
y = r->y;
|
|
z = r->z;
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
|
|
/* T1 = Z * Z */
|
|
sp_1024_mont_sqr_42(t1, p->z, p1024_mod, p1024_mp_mod);
|
|
/* Z = Y * Z */
|
|
sp_1024_mont_mul_42(z, p->y, p->z, p1024_mod, p1024_mp_mod);
|
|
/* Z = 2Z */
|
|
sp_1024_mont_dbl_42(z, z, p1024_mod);
|
|
/* T2 = X - T1 */
|
|
sp_1024_mont_sub_42(t2, p->x, t1, p1024_mod);
|
|
/* T1 = X + T1 */
|
|
sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
|
|
/* T2 = T1 * T2 */
|
|
sp_1024_mont_mul_42(t2, t1, t2, p1024_mod, p1024_mp_mod);
|
|
/* T1 = 3T2 */
|
|
sp_1024_mont_tpl_42(t1, t2, p1024_mod);
|
|
/* Y = 2Y */
|
|
sp_1024_mont_dbl_42(y, p->y, p1024_mod);
|
|
/* Y = Y * Y */
|
|
sp_1024_mont_sqr_42(y, y, p1024_mod, p1024_mp_mod);
|
|
/* T2 = Y * Y */
|
|
sp_1024_mont_sqr_42(t2, y, p1024_mod, p1024_mp_mod);
|
|
/* T2 = T2/2 */
|
|
sp_1024_div2_42(t2, t2, p1024_mod);
|
|
/* Y = Y * X */
|
|
sp_1024_mont_mul_42(y, y, p->x, p1024_mod, p1024_mp_mod);
|
|
/* X = T1 * T1 */
|
|
sp_1024_mont_sqr_42(x, t1, p1024_mod, p1024_mp_mod);
|
|
/* X = X - Y */
|
|
sp_1024_mont_sub_42(x, x, y, p1024_mod);
|
|
/* X = X - Y */
|
|
sp_1024_mont_sub_42(x, x, y, p1024_mod);
|
|
/* Y = Y - X */
|
|
sp_1024_mont_sub_lower_42(y, y, x, p1024_mod);
|
|
/* Y = Y * T1 */
|
|
sp_1024_mont_mul_42(y, y, t1, p1024_mod, p1024_mp_mod);
|
|
/* Y = Y - T2 */
|
|
sp_1024_mont_sub_42(y, y, t2, p1024_mod);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_1024_proj_point_dbl_42_ctx {
|
|
int state;
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_1024_proj_point_dbl_42_ctx;
|
|
|
|
/* Double the Montgomery form projective point p.
|
|
*
|
|
* r Result of doubling point.
|
|
* p Point to double.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_1024_proj_point_dbl_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r, const sp_point_1024* p, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_1024_proj_point_dbl_42_ctx* ctx = (sp_1024_proj_point_dbl_42_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_1024_proj_point_dbl_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0:
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*42;
|
|
ctx->x = r->x;
|
|
ctx->y = r->y;
|
|
ctx->z = r->z;
|
|
|
|
/* Put infinity into result. */
|
|
if (r != p) {
|
|
r->infinity = p->infinity;
|
|
}
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* T1 = Z * Z */
|
|
sp_1024_mont_sqr_42(ctx->t1, p->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
/* Z = Y * Z */
|
|
sp_1024_mont_mul_42(ctx->z, p->y, p->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
/* Z = 2Z */
|
|
sp_1024_mont_dbl_42(ctx->z, ctx->z, p1024_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* T2 = X - T1 */
|
|
sp_1024_mont_sub_42(ctx->t2, p->x, ctx->t1, p1024_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
/* T1 = X + T1 */
|
|
sp_1024_mont_add_42(ctx->t1, p->x, ctx->t1, p1024_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
/* T2 = T1 * T2 */
|
|
sp_1024_mont_mul_42(ctx->t2, ctx->t1, ctx->t2, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* T1 = 3T2 */
|
|
sp_1024_mont_tpl_42(ctx->t1, ctx->t2, p1024_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* Y = 2Y */
|
|
sp_1024_mont_dbl_42(ctx->y, p->y, p1024_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Y = Y * Y */
|
|
sp_1024_mont_sqr_42(ctx->y, ctx->y, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 10;
|
|
break;
|
|
case 10:
|
|
/* T2 = Y * Y */
|
|
sp_1024_mont_sqr_42(ctx->t2, ctx->y, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* T2 = T2/2 */
|
|
sp_1024_div2_42(ctx->t2, ctx->t2, p1024_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* Y = Y * X */
|
|
sp_1024_mont_mul_42(ctx->y, ctx->y, p->x, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
/* X = T1 * T1 */
|
|
sp_1024_mont_sqr_42(ctx->x, ctx->t1, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
/* X = X - Y */
|
|
sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->y, p1024_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* X = X - Y */
|
|
sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->y, p1024_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
/* Y = Y - X */
|
|
sp_1024_mont_sub_lower_42(ctx->y, ctx->y, ctx->x, p1024_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
/* Y = Y * T1 */
|
|
sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t1, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
/* Y = Y - T2 */
|
|
sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t2, p1024_mod);
|
|
ctx->state = 19;
|
|
/* fall-through */
|
|
case 19:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 19) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
/* Compare two numbers to determine if they are equal.
|
|
* Constant time implementation.
|
|
*
|
|
* a First number to compare.
|
|
* b Second number to compare.
|
|
* returns 1 when equal and 0 otherwise.
|
|
*/
|
|
static int sp_1024_cmp_equal_42(const sp_digit* a, const sp_digit* b)
|
|
{
|
|
return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) |
|
|
(a[3] ^ b[3]) | (a[4] ^ b[4]) | (a[5] ^ b[5]) |
|
|
(a[6] ^ b[6]) | (a[7] ^ b[7]) | (a[8] ^ b[8]) |
|
|
(a[9] ^ b[9]) | (a[10] ^ b[10]) | (a[11] ^ b[11]) |
|
|
(a[12] ^ b[12]) | (a[13] ^ b[13]) | (a[14] ^ b[14]) |
|
|
(a[15] ^ b[15]) | (a[16] ^ b[16]) | (a[17] ^ b[17]) |
|
|
(a[18] ^ b[18]) | (a[19] ^ b[19]) | (a[20] ^ b[20]) |
|
|
(a[21] ^ b[21]) | (a[22] ^ b[22]) | (a[23] ^ b[23]) |
|
|
(a[24] ^ b[24]) | (a[25] ^ b[25]) | (a[26] ^ b[26]) |
|
|
(a[27] ^ b[27]) | (a[28] ^ b[28]) | (a[29] ^ b[29]) |
|
|
(a[30] ^ b[30]) | (a[31] ^ b[31]) | (a[32] ^ b[32]) |
|
|
(a[33] ^ b[33]) | (a[34] ^ b[34]) | (a[35] ^ b[35]) |
|
|
(a[36] ^ b[36]) | (a[37] ^ b[37]) | (a[38] ^ b[38]) |
|
|
(a[39] ^ b[39]) | (a[40] ^ b[40]) | (a[41] ^ b[41])) == 0;
|
|
}
|
|
|
|
/* Returns 1 if the number of zero.
|
|
* Implementation is constant time.
|
|
*
|
|
* a Number to check.
|
|
* returns 1 if the number is zero and 0 otherwise.
|
|
*/
|
|
static int sp_1024_iszero_42(const sp_digit* a)
|
|
{
|
|
return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] |
|
|
a[8] | a[9] | a[10] | a[11] | a[12] | a[13] | a[14] | a[15] |
|
|
a[16] | a[17] | a[18] | a[19] | a[20] | a[21] | a[22] | a[23] |
|
|
a[24] | a[25] | a[26] | a[27] | a[28] | a[29] | a[30] | a[31] |
|
|
a[32] | a[33] | a[34] | a[35] | a[36] | a[37] | a[38] | a[39] |
|
|
a[40] | a[41]) == 0;
|
|
}
|
|
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_proj_point_add_42(sp_point_1024* r,
|
|
const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*42;
|
|
sp_digit* t3 = t + 4*42;
|
|
sp_digit* t4 = t + 6*42;
|
|
sp_digit* t5 = t + 8*42;
|
|
sp_digit* t6 = t + 10*42;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_1024_mont_sqr_42(t1, q->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t3, t1, q->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t1, t1, p->x, p1024_mod, p1024_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_1024_mont_sqr_42(t2, p->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t4, t2, p->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_1024_mont_mul_42(t3, t3, p->y, p1024_mod, p1024_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod);
|
|
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_1024_cmp_equal_42(t2, t1) &
|
|
sp_1024_cmp_equal_42(t4, t3)) {
|
|
sp_1024_proj_point_dbl_42(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t6;
|
|
sp_digit* y = t1;
|
|
sp_digit* z = t2;
|
|
int i;
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
|
|
/* H = U2 - U1 */
|
|
sp_1024_mont_sub_42(t2, t2, t1, p1024_mod);
|
|
/* R = S2 - S1 */
|
|
sp_1024_mont_sub_42(t4, t4, t3, p1024_mod);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(y, t1, t5, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_1024_mont_mul_42(z, p->z, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(z, z, q->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sqr_42(x, t4, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(x, x, t5, p1024_mod);
|
|
sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_dbl_42(t3, y, p1024_mod);
|
|
sp_1024_mont_sub_42(x, x, t3, p1024_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_1024_mont_sub_lower_42(y, y, x, p1024_mod);
|
|
sp_1024_mont_mul_42(y, y, t4, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(y, y, t5, p1024_mod);
|
|
for (i = 0; i < 42; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_1024_proj_point_add_42_ctx {
|
|
int state;
|
|
sp_1024_proj_point_dbl_42_ctx dbl_ctx;
|
|
const sp_point_1024* ap[2];
|
|
sp_point_1024* rp[2];
|
|
sp_digit* t1;
|
|
sp_digit* t2;
|
|
sp_digit* t3;
|
|
sp_digit* t4;
|
|
sp_digit* t5;
|
|
sp_digit* t6;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
} sp_1024_proj_point_add_42_ctx;
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static int sp_1024_proj_point_add_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
|
|
const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_1024_proj_point_add_42_ctx* ctx = (sp_1024_proj_point_add_42_ctx*)sp_ctx->data;
|
|
|
|
/* Ensure only the first point is the same as the result. */
|
|
if (q == r) {
|
|
const sp_point_1024* a = p;
|
|
p = q;
|
|
q = a;
|
|
}
|
|
|
|
typedef char ctx_size_test[sizeof(sp_1024_proj_point_add_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
ctx->t1 = t;
|
|
ctx->t2 = t + 2*42;
|
|
ctx->t3 = t + 4*42;
|
|
ctx->t4 = t + 6*42;
|
|
ctx->t5 = t + 8*42;
|
|
ctx->t6 = t + 10*42;
|
|
ctx->x = ctx->t6;
|
|
ctx->y = ctx->t1;
|
|
ctx->z = ctx->t2;
|
|
|
|
ctx->state = 1;
|
|
break;
|
|
case 1:
|
|
/* U1 = X1*Z2^2 */
|
|
sp_1024_mont_sqr_42(ctx->t1, q->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2:
|
|
sp_1024_mont_mul_42(ctx->t3, ctx->t1, q->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3:
|
|
sp_1024_mont_mul_42(ctx->t1, ctx->t1, p->x, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4:
|
|
/* U2 = X2*Z1^2 */
|
|
sp_1024_mont_sqr_42(ctx->t2, p->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 5;
|
|
break;
|
|
case 5:
|
|
sp_1024_mont_mul_42(ctx->t4, ctx->t2, p->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 6;
|
|
break;
|
|
case 6:
|
|
sp_1024_mont_mul_42(ctx->t2, ctx->t2, q->x, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 7;
|
|
break;
|
|
case 7:
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_1024_mont_mul_42(ctx->t3, ctx->t3, p->y, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 8;
|
|
break;
|
|
case 8:
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_1024_mont_mul_42(ctx->t4, ctx->t4, q->y, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 9;
|
|
break;
|
|
case 9:
|
|
/* Check double */
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_1024_cmp_equal_42(ctx->t2, ctx->t1) &
|
|
sp_1024_cmp_equal_42(ctx->t4, ctx->t3)) {
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
sp_1024_proj_point_dbl_42(r, p, t);
|
|
ctx->state = 25;
|
|
}
|
|
else {
|
|
ctx->state = 10;
|
|
}
|
|
break;
|
|
case 10:
|
|
/* H = U2 - U1 */
|
|
sp_1024_mont_sub_42(ctx->t2, ctx->t2, ctx->t1, p1024_mod);
|
|
ctx->state = 11;
|
|
break;
|
|
case 11:
|
|
/* R = S2 - S1 */
|
|
sp_1024_mont_sub_42(ctx->t4, ctx->t4, ctx->t3, p1024_mod);
|
|
ctx->state = 12;
|
|
break;
|
|
case 12:
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
sp_1024_mont_sqr_42(ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 13;
|
|
break;
|
|
case 13:
|
|
sp_1024_mont_mul_42(ctx->y, ctx->t1, ctx->t5, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 14;
|
|
break;
|
|
case 14:
|
|
sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t2, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 15;
|
|
break;
|
|
case 15:
|
|
/* Z3 = H*Z1*Z2 */
|
|
sp_1024_mont_mul_42(ctx->z, p->z, ctx->t2, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 16;
|
|
break;
|
|
case 16:
|
|
sp_1024_mont_mul_42(ctx->z, ctx->z, q->z, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 17;
|
|
break;
|
|
case 17:
|
|
sp_1024_mont_sqr_42(ctx->x, ctx->t4, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 18;
|
|
break;
|
|
case 18:
|
|
sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t5, p1024_mod);
|
|
ctx->state = 19;
|
|
break;
|
|
case 19:
|
|
sp_1024_mont_mul_42(ctx->t5, ctx->t5, ctx->t3, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 20;
|
|
break;
|
|
case 20:
|
|
sp_1024_mont_dbl_42(ctx->t3, ctx->y, p1024_mod);
|
|
sp_1024_mont_sub_42(ctx->x, ctx->x, ctx->t3, p1024_mod);
|
|
ctx->state = 21;
|
|
break;
|
|
case 21:
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
sp_1024_mont_sub_lower_42(ctx->y, ctx->y, ctx->x, p1024_mod);
|
|
ctx->state = 22;
|
|
break;
|
|
case 22:
|
|
sp_1024_mont_mul_42(ctx->y, ctx->y, ctx->t4, p1024_mod, p1024_mp_mod);
|
|
ctx->state = 23;
|
|
break;
|
|
case 23:
|
|
sp_1024_mont_sub_42(ctx->y, ctx->y, ctx->t5, p1024_mod);
|
|
ctx->state = 24;
|
|
break;
|
|
case 24:
|
|
{
|
|
int i;
|
|
sp_digit maskp = 0 - (q->infinity & (!p->infinity));
|
|
sp_digit maskq = 0 - (p->infinity & (!q->infinity));
|
|
sp_digit maskt = ~(maskp | maskq);
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (ctx->x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (ctx->y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (ctx->z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
ctx->state = 25;
|
|
break;
|
|
}
|
|
case 25:
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 25) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
return err;
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Small implementation using add and double that is cache attack resistant but
|
|
* allocates memory rather than use large stacks.
|
|
* 1024 adds and doubles.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_1024 t[3];
|
|
sp_digit tmp[2 * 42 * 37];
|
|
#endif
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
int err = MP_OKAY;
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 37, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
XMEMSET(t, 0, sizeof(sp_point_1024) * 3);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY)
|
|
err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod);
|
|
if (err == MP_OKAY)
|
|
err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod);
|
|
|
|
if (err == MP_OKAY) {
|
|
i = 40;
|
|
c = 24;
|
|
n = k[i--] << (25 - c);
|
|
for (; ; c--) {
|
|
if (c == 0) {
|
|
if (i == -1)
|
|
break;
|
|
|
|
n = k[i--];
|
|
c = 25;
|
|
}
|
|
|
|
y = (n >> 24) & 1;
|
|
n <<= 1;
|
|
|
|
sp_1024_proj_point_add_42(&t[y^1], &t[0], &t[1], tmp);
|
|
|
|
XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])),
|
|
sizeof(sp_point_1024));
|
|
sp_1024_proj_point_dbl_42(&t[2], &t[2], tmp);
|
|
XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) +
|
|
((size_t)&t[1] & addr_mask[y])), &t[2],
|
|
sizeof(sp_point_1024));
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_1024_map_42(r, &t[0], tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &t[0], sizeof(sp_point_1024));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (tmp != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(tmp, sizeof(sp_digit) * 2 * 42 * 37);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
#endif
|
|
{
|
|
ForceZero(t, sizeof(sp_point_1024) * 3);
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
typedef struct sp_1024_ecc_mulmod_42_ctx {
|
|
int state;
|
|
union {
|
|
sp_1024_proj_point_dbl_42_ctx dbl_ctx;
|
|
sp_1024_proj_point_add_42_ctx add_ctx;
|
|
};
|
|
sp_point_1024 t[3];
|
|
sp_digit tmp[2 * 42 * 37];
|
|
sp_digit n;
|
|
int i;
|
|
int c;
|
|
int y;
|
|
} sp_1024_ecc_mulmod_42_ctx;
|
|
|
|
static int sp_1024_ecc_mulmod_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
|
|
const sp_point_1024* g, const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
int err = FP_WOULDBLOCK;
|
|
sp_1024_ecc_mulmod_42_ctx* ctx = (sp_1024_ecc_mulmod_42_ctx*)sp_ctx->data;
|
|
|
|
typedef char ctx_size_test[sizeof(sp_1024_ecc_mulmod_42_ctx) >= sizeof(*sp_ctx) ? -1 : 1];
|
|
(void)sizeof(ctx_size_test);
|
|
|
|
/* Implementation is constant time. */
|
|
(void)ct;
|
|
|
|
switch (ctx->state) {
|
|
case 0: /* INIT */
|
|
XMEMSET(ctx->t, 0, sizeof(sp_point_1024) * 3);
|
|
ctx->i = 40;
|
|
ctx->c = 24;
|
|
ctx->n = k[ctx->i--] << (25 - ctx->c);
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
ctx->t[0].infinity = 1;
|
|
ctx->state = 1;
|
|
break;
|
|
case 1: /* T1X */
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_1024_mod_mul_norm_42(ctx->t[1].x, g->x, p1024_mod);
|
|
ctx->state = 2;
|
|
break;
|
|
case 2: /* T1Y */
|
|
err = sp_1024_mod_mul_norm_42(ctx->t[1].y, g->y, p1024_mod);
|
|
ctx->state = 3;
|
|
break;
|
|
case 3: /* T1Z */
|
|
err = sp_1024_mod_mul_norm_42(ctx->t[1].z, g->z, p1024_mod);
|
|
ctx->state = 4;
|
|
break;
|
|
case 4: /* ADDPREP */
|
|
if (ctx->c == 0) {
|
|
if (ctx->i == -1) {
|
|
ctx->state = 7;
|
|
break;
|
|
}
|
|
|
|
ctx->n = k[ctx->i--];
|
|
ctx->c = 25;
|
|
}
|
|
ctx->y = (ctx->n >> 24) & 1;
|
|
ctx->n <<= 1;
|
|
XMEMSET(&ctx->add_ctx, 0, sizeof(ctx->add_ctx));
|
|
ctx->state = 5;
|
|
break;
|
|
case 5: /* ADD */
|
|
err = sp_1024_proj_point_add_42_nb((sp_ecc_ctx_t*)&ctx->add_ctx,
|
|
&ctx->t[ctx->y^1], &ctx->t[0], &ctx->t[1], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(&ctx->t[2], (void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])),
|
|
sizeof(sp_point_1024));
|
|
XMEMSET(&ctx->dbl_ctx, 0, sizeof(ctx->dbl_ctx));
|
|
ctx->state = 6;
|
|
}
|
|
break;
|
|
case 6: /* DBL */
|
|
err = sp_1024_proj_point_dbl_42_nb((sp_ecc_ctx_t*)&ctx->dbl_ctx, &ctx->t[2],
|
|
&ctx->t[2], ctx->tmp);
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY((void*)(((size_t)&ctx->t[0] & addr_mask[ctx->y^1]) +
|
|
((size_t)&ctx->t[1] & addr_mask[ctx->y])), &ctx->t[2],
|
|
sizeof(sp_point_1024));
|
|
ctx->state = 4;
|
|
ctx->c--;
|
|
}
|
|
break;
|
|
case 7: /* MAP */
|
|
if (map != 0) {
|
|
sp_1024_map_42(r, &ctx->t[0], ctx->tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, &ctx->t[0], sizeof(sp_point_1024));
|
|
}
|
|
err = MP_OKAY;
|
|
break;
|
|
}
|
|
|
|
if (err == MP_OKAY && ctx->state != 7) {
|
|
err = FP_WOULDBLOCK;
|
|
}
|
|
if (err != FP_WOULDBLOCK) {
|
|
ForceZero(ctx->tmp, sizeof(ctx->tmp));
|
|
ForceZero(ctx->t, sizeof(ctx->t));
|
|
}
|
|
|
|
(void)heap;
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
#else
|
|
/* A table entry for pre-computed points. */
|
|
typedef struct sp_table_entry_1024 {
|
|
sp_digit x[42];
|
|
sp_digit y[42];
|
|
} sp_table_entry_1024;
|
|
|
|
/* Conditionally copy a into r using the mask m.
|
|
* m is -1 to copy and 0 when not.
|
|
*
|
|
* r A single precision number to copy over.
|
|
* a A single precision number to copy.
|
|
* m Mask value to apply.
|
|
*/
|
|
static void sp_1024_cond_copy_42(sp_digit* r, const sp_digit* a, const sp_digit m)
|
|
{
|
|
sp_digit t[42];
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
int i;
|
|
|
|
for (i = 0; i < 42; i++) {
|
|
t[i] = r[i] ^ a[i];
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r[i] ^= t[i] & m;
|
|
}
|
|
#else
|
|
t[ 0] = r[ 0] ^ a[ 0];
|
|
t[ 1] = r[ 1] ^ a[ 1];
|
|
t[ 2] = r[ 2] ^ a[ 2];
|
|
t[ 3] = r[ 3] ^ a[ 3];
|
|
t[ 4] = r[ 4] ^ a[ 4];
|
|
t[ 5] = r[ 5] ^ a[ 5];
|
|
t[ 6] = r[ 6] ^ a[ 6];
|
|
t[ 7] = r[ 7] ^ a[ 7];
|
|
t[ 8] = r[ 8] ^ a[ 8];
|
|
t[ 9] = r[ 9] ^ a[ 9];
|
|
t[10] = r[10] ^ a[10];
|
|
t[11] = r[11] ^ a[11];
|
|
t[12] = r[12] ^ a[12];
|
|
t[13] = r[13] ^ a[13];
|
|
t[14] = r[14] ^ a[14];
|
|
t[15] = r[15] ^ a[15];
|
|
t[16] = r[16] ^ a[16];
|
|
t[17] = r[17] ^ a[17];
|
|
t[18] = r[18] ^ a[18];
|
|
t[19] = r[19] ^ a[19];
|
|
t[20] = r[20] ^ a[20];
|
|
t[21] = r[21] ^ a[21];
|
|
t[22] = r[22] ^ a[22];
|
|
t[23] = r[23] ^ a[23];
|
|
t[24] = r[24] ^ a[24];
|
|
t[25] = r[25] ^ a[25];
|
|
t[26] = r[26] ^ a[26];
|
|
t[27] = r[27] ^ a[27];
|
|
t[28] = r[28] ^ a[28];
|
|
t[29] = r[29] ^ a[29];
|
|
t[30] = r[30] ^ a[30];
|
|
t[31] = r[31] ^ a[31];
|
|
t[32] = r[32] ^ a[32];
|
|
t[33] = r[33] ^ a[33];
|
|
t[34] = r[34] ^ a[34];
|
|
t[35] = r[35] ^ a[35];
|
|
t[36] = r[36] ^ a[36];
|
|
t[37] = r[37] ^ a[37];
|
|
t[38] = r[38] ^ a[38];
|
|
t[39] = r[39] ^ a[39];
|
|
t[40] = r[40] ^ a[40];
|
|
t[41] = r[41] ^ a[41];
|
|
r[ 0] ^= t[ 0] & m;
|
|
r[ 1] ^= t[ 1] & m;
|
|
r[ 2] ^= t[ 2] & m;
|
|
r[ 3] ^= t[ 3] & m;
|
|
r[ 4] ^= t[ 4] & m;
|
|
r[ 5] ^= t[ 5] & m;
|
|
r[ 6] ^= t[ 6] & m;
|
|
r[ 7] ^= t[ 7] & m;
|
|
r[ 8] ^= t[ 8] & m;
|
|
r[ 9] ^= t[ 9] & m;
|
|
r[10] ^= t[10] & m;
|
|
r[11] ^= t[11] & m;
|
|
r[12] ^= t[12] & m;
|
|
r[13] ^= t[13] & m;
|
|
r[14] ^= t[14] & m;
|
|
r[15] ^= t[15] & m;
|
|
r[16] ^= t[16] & m;
|
|
r[17] ^= t[17] & m;
|
|
r[18] ^= t[18] & m;
|
|
r[19] ^= t[19] & m;
|
|
r[20] ^= t[20] & m;
|
|
r[21] ^= t[21] & m;
|
|
r[22] ^= t[22] & m;
|
|
r[23] ^= t[23] & m;
|
|
r[24] ^= t[24] & m;
|
|
r[25] ^= t[25] & m;
|
|
r[26] ^= t[26] & m;
|
|
r[27] ^= t[27] & m;
|
|
r[28] ^= t[28] & m;
|
|
r[29] ^= t[29] & m;
|
|
r[30] ^= t[30] & m;
|
|
r[31] ^= t[31] & m;
|
|
r[32] ^= t[32] & m;
|
|
r[33] ^= t[33] & m;
|
|
r[34] ^= t[34] & m;
|
|
r[35] ^= t[35] & m;
|
|
r[36] ^= t[36] & m;
|
|
r[37] ^= t[37] & m;
|
|
r[38] ^= t[38] & m;
|
|
r[39] ^= t[39] & m;
|
|
r[40] ^= t[40] & m;
|
|
r[41] ^= t[41] & m;
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
}
|
|
|
|
#define sp_1024_mont_dbl_lower_42 sp_1024_mont_dbl_42
|
|
#define sp_1024_mont_tpl_lower_42 sp_1024_mont_tpl_42
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_proj_point_dbl_n_42(sp_point_1024* p, int i,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*42;
|
|
sp_digit* b = t + 4*42;
|
|
sp_digit* t1 = t + 6*42;
|
|
sp_digit* t2 = t + 8*42;
|
|
sp_digit* x;
|
|
sp_digit* y;
|
|
sp_digit* z;
|
|
volatile int n = i;
|
|
|
|
x = p->x;
|
|
y = p->y;
|
|
z = p->z;
|
|
|
|
/* Y = 2*Y */
|
|
sp_1024_mont_dbl_42(y, y, p1024_mod);
|
|
/* W = Z^4 */
|
|
sp_1024_mont_sqr_42(w, z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sqr_42(w, w, p1024_mod, p1024_mp_mod);
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
while (--n > 0)
|
|
#else
|
|
while (--n >= 0)
|
|
#endif
|
|
{
|
|
/* A = 3*(X^2 - W) */
|
|
sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(t1, t1, w, p1024_mod);
|
|
sp_1024_mont_tpl_lower_42(a, t1, p1024_mod);
|
|
/* B = X*Y^2 */
|
|
sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_dbl_42(t2, b, p1024_mod);
|
|
sp_1024_mont_sub_42(x, x, t2, p1024_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_1024_mont_sub_lower_42(t2, b, x, p1024_mod);
|
|
sp_1024_mont_dbl_lower_42(b, t2, p1024_mod);
|
|
/* Z = Z*Y */
|
|
sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod);
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
if (n != 0)
|
|
#endif
|
|
{
|
|
/* W = W*Y^4 */
|
|
sp_1024_mont_mul_42(w, w, t1, p1024_mod, p1024_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(y, y, t1, p1024_mod);
|
|
}
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* A = 3*(X^2 - W) */
|
|
sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(t1, t1, w, p1024_mod);
|
|
sp_1024_mont_tpl_lower_42(a, t1, p1024_mod);
|
|
/* B = X*Y^2 */
|
|
sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod);
|
|
/* X = A^2 - 2B */
|
|
sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_dbl_42(t2, b, p1024_mod);
|
|
sp_1024_mont_sub_42(x, x, t2, p1024_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_1024_mont_sub_lower_42(t2, b, x, p1024_mod);
|
|
sp_1024_mont_dbl_lower_42(b, t2, p1024_mod);
|
|
/* Z = Z*Y */
|
|
sp_1024_mont_mul_42(z, z, y, p1024_mod, p1024_mp_mod);
|
|
/* t1 = Y^4 */
|
|
sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod);
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(y, y, t1, p1024_mod);
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Y = Y/2 */
|
|
sp_1024_div2_42(y, y, p1024_mod);
|
|
}
|
|
|
|
/* Double the Montgomery form projective point p a number of times.
|
|
*
|
|
* r Result of repeated doubling of point.
|
|
* p Point to double.
|
|
* n Number of times to double
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_proj_point_dbl_n_store_42(sp_point_1024* r,
|
|
const sp_point_1024* p, int n, int m, sp_digit* t)
|
|
{
|
|
sp_digit* w = t;
|
|
sp_digit* a = t + 2*42;
|
|
sp_digit* b = t + 4*42;
|
|
sp_digit* t1 = t + 6*42;
|
|
sp_digit* t2 = t + 8*42;
|
|
sp_digit* x = r[2*m].x;
|
|
sp_digit* y = r[(1<<n)*m].y;
|
|
sp_digit* z = r[2*m].z;
|
|
int i;
|
|
int j;
|
|
|
|
for (i=0; i<42; i++) {
|
|
x[i] = p->x[i];
|
|
}
|
|
for (i=0; i<42; i++) {
|
|
y[i] = p->y[i];
|
|
}
|
|
for (i=0; i<42; i++) {
|
|
z[i] = p->z[i];
|
|
}
|
|
|
|
/* Y = 2*Y */
|
|
sp_1024_mont_dbl_42(y, y, p1024_mod);
|
|
/* W = Z^4 */
|
|
sp_1024_mont_sqr_42(w, z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sqr_42(w, w, p1024_mod, p1024_mp_mod);
|
|
j = m;
|
|
for (i=1; i<=n; i++) {
|
|
j *= 2;
|
|
|
|
/* A = 3*(X^2 - W) */
|
|
sp_1024_mont_sqr_42(t1, x, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(t1, t1, w, p1024_mod);
|
|
sp_1024_mont_tpl_lower_42(a, t1, p1024_mod);
|
|
/* B = X*Y^2 */
|
|
sp_1024_mont_sqr_42(t1, y, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(b, t1, x, p1024_mod, p1024_mp_mod);
|
|
x = r[j].x;
|
|
/* X = A^2 - 2B */
|
|
sp_1024_mont_sqr_42(x, a, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_dbl_42(t2, b, p1024_mod);
|
|
sp_1024_mont_sub_42(x, x, t2, p1024_mod);
|
|
/* B = 2.(B - X) */
|
|
sp_1024_mont_sub_lower_42(t2, b, x, p1024_mod);
|
|
sp_1024_mont_dbl_lower_42(b, t2, p1024_mod);
|
|
/* Z = Z*Y */
|
|
sp_1024_mont_mul_42(r[j].z, z, y, p1024_mod, p1024_mp_mod);
|
|
z = r[j].z;
|
|
/* t1 = Y^4 */
|
|
sp_1024_mont_sqr_42(t1, t1, p1024_mod, p1024_mp_mod);
|
|
if (i != n) {
|
|
/* W = W*Y^4 */
|
|
sp_1024_mont_mul_42(w, w, t1, p1024_mod, p1024_mp_mod);
|
|
}
|
|
/* y = 2*A*(B - X) - Y^4 */
|
|
sp_1024_mont_mul_42(y, b, a, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(y, y, t1, p1024_mod);
|
|
/* Y = Y/2 */
|
|
sp_1024_div2_42(r[j].y, y, p1024_mod);
|
|
r[j].infinity = 0;
|
|
}
|
|
}
|
|
|
|
/* Add two Montgomery form projective points.
|
|
*
|
|
* ra Result of addition.
|
|
* rs Result of subtraction.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_proj_point_add_sub_42(sp_point_1024* ra,
|
|
sp_point_1024* rs, const sp_point_1024* p, const sp_point_1024* q,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*42;
|
|
sp_digit* t3 = t + 4*42;
|
|
sp_digit* t4 = t + 6*42;
|
|
sp_digit* t5 = t + 8*42;
|
|
sp_digit* t6 = t + 10*42;
|
|
sp_digit* xa = ra->x;
|
|
sp_digit* ya = ra->y;
|
|
sp_digit* za = ra->z;
|
|
sp_digit* xs = rs->x;
|
|
sp_digit* ys = rs->y;
|
|
sp_digit* zs = rs->z;
|
|
|
|
|
|
XMEMCPY(xa, p->x, sizeof(p->x) / 2);
|
|
XMEMCPY(ya, p->y, sizeof(p->y) / 2);
|
|
XMEMCPY(za, p->z, sizeof(p->z) / 2);
|
|
ra->infinity = 0;
|
|
rs->infinity = 0;
|
|
|
|
/* U1 = X1*Z2^2 */
|
|
sp_1024_mont_sqr_42(t1, q->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t3, t1, q->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t1, t1, xa, p1024_mod, p1024_mp_mod);
|
|
/* U2 = X2*Z1^2 */
|
|
sp_1024_mont_sqr_42(t2, za, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t4, t2, za, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod);
|
|
/* S1 = Y1*Z2^3 */
|
|
sp_1024_mont_mul_42(t3, t3, ya, p1024_mod, p1024_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod);
|
|
/* H = U2 - U1 */
|
|
sp_1024_mont_sub_42(t2, t2, t1, p1024_mod);
|
|
/* RS = S2 + S1 */
|
|
sp_1024_mont_add_42(t6, t4, t3, p1024_mod);
|
|
/* R = S2 - S1 */
|
|
sp_1024_mont_sub_42(t4, t4, t3, p1024_mod);
|
|
/* Z3 = H*Z1*Z2 */
|
|
/* ZS = H*Z1*Z2 */
|
|
sp_1024_mont_mul_42(za, za, q->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(za, za, t2, p1024_mod, p1024_mp_mod);
|
|
XMEMCPY(zs, za, sizeof(p->z)/2);
|
|
/* X3 = R^2 - H^3 - 2*U1*H^2 */
|
|
/* XS = RS^2 - H^3 - 2*U1*H^2 */
|
|
sp_1024_mont_sqr_42(xa, t4, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sqr_42(xs, t6, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(ya, t1, t5, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(xa, xa, t5, p1024_mod);
|
|
sp_1024_mont_sub_42(xs, xs, t5, p1024_mod);
|
|
sp_1024_mont_dbl_42(t1, ya, p1024_mod);
|
|
sp_1024_mont_sub_42(xa, xa, t1, p1024_mod);
|
|
sp_1024_mont_sub_42(xs, xs, t1, p1024_mod);
|
|
/* Y3 = R*(U1*H^2 - X3) - S1*H^3 */
|
|
/* YS = -RS*(U1*H^2 - XS) - S1*H^3 */
|
|
sp_1024_mont_sub_lower_42(ys, ya, xs, p1024_mod);
|
|
sp_1024_mont_sub_lower_42(ya, ya, xa, p1024_mod);
|
|
sp_1024_mont_mul_42(ya, ya, t4, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(t6, p1024_mod, t6, p1024_mod);
|
|
sp_1024_mont_mul_42(ys, ys, t6, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t5, t5, t3, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(ya, ya, t5, p1024_mod);
|
|
sp_1024_mont_sub_42(ys, ys, t5, p1024_mod);
|
|
}
|
|
|
|
/* Structure used to describe recoding of scalar multiplication. */
|
|
typedef struct ecc_recode_1024 {
|
|
/* Index into pre-computation table. */
|
|
uint8_t i;
|
|
/* Use the negative of the point. */
|
|
uint8_t neg;
|
|
} ecc_recode_1024;
|
|
|
|
/* The index into pre-computation table to use. */
|
|
static const uint8_t recode_index_42_7[130] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
|
|
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
|
|
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
|
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
|
|
64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49,
|
|
48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33,
|
|
32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17,
|
|
16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,
|
|
0, 1,
|
|
};
|
|
|
|
/* Whether to negate y-ordinate. */
|
|
static const uint8_t recode_neg_42_7[130] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
|
0, 0,
|
|
};
|
|
|
|
/* Recode the scalar for multiplication using pre-computed values and
|
|
* subtraction.
|
|
*
|
|
* k Scalar to multiply by.
|
|
* v Vector of operations to perform.
|
|
*/
|
|
static void sp_1024_ecc_recode_7_42(const sp_digit* k, ecc_recode_1024* v)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint8_t y;
|
|
int carry = 0;
|
|
int o;
|
|
sp_digit n;
|
|
|
|
j = 0;
|
|
n = k[j];
|
|
o = 0;
|
|
for (i=0; i<147; i++) {
|
|
y = (int8_t)n;
|
|
if (o + 7 < 25) {
|
|
y &= 0x7f;
|
|
n >>= 7;
|
|
o += 7;
|
|
}
|
|
else if (o + 7 == 25) {
|
|
n >>= 7;
|
|
if (++j < 42)
|
|
n = k[j];
|
|
o = 0;
|
|
}
|
|
else if (++j < 42) {
|
|
n = k[j];
|
|
y |= (uint8_t)((n << (25 - o)) & 0x7f);
|
|
o -= 18;
|
|
n >>= o;
|
|
}
|
|
|
|
y += (uint8_t)carry;
|
|
v[i].i = recode_index_42_7[y];
|
|
v[i].neg = recode_neg_42_7[y];
|
|
carry = (y >> 7) + v[i].neg;
|
|
}
|
|
}
|
|
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Window technique of 7 bits. (Add-Sub variation.)
|
|
* Calculate 0..64 times the point. Use function that adds and
|
|
* subtracts the same two points.
|
|
* Recode to add or subtract one of the computed points.
|
|
* Double to push up.
|
|
* NOT a sliding window.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_1024_ecc_mulmod_win_add_sub_42(sp_point_1024* r, const sp_point_1024* g,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* t = NULL;
|
|
sp_digit* tmp = NULL;
|
|
#else
|
|
sp_point_1024 t[65+2];
|
|
sp_digit tmp[2 * 42 * 37];
|
|
#endif
|
|
sp_point_1024* rt = NULL;
|
|
sp_point_1024* p = NULL;
|
|
sp_digit* negy;
|
|
int i;
|
|
ecc_recode_1024 v[147];
|
|
int err = MP_OKAY;
|
|
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) *
|
|
(65+2), heap, DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 37,
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
rt = t + 65;
|
|
p = t + 65+1;
|
|
|
|
/* t[0] = {0, 0, 1} * norm */
|
|
XMEMSET(&t[0], 0, sizeof(t[0]));
|
|
t[0].infinity = 1;
|
|
/* t[1] = {g->x, g->y, g->z} * norm */
|
|
err = sp_1024_mod_mul_norm_42(t[1].x, g->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(t[1].y, g->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(t[1].z, g->z, p1024_mod);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
t[1].infinity = 0;
|
|
/* t[2] ... t[64] */
|
|
sp_1024_proj_point_dbl_n_store_42(t, &t[ 1], 6, 1, tmp);
|
|
sp_1024_proj_point_add_42(&t[ 3], &t[ 2], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[ 6], &t[ 3], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[10], &t[ 5], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[11], &t[ 9], &t[10], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[12], &t[ 6], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[14], &t[ 7], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[15], &t[13], &t[14], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[18], &t[ 9], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[19], &t[17], &t[18], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[20], &t[10], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[22], &t[11], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[23], &t[21], &t[22], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[24], &t[12], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[26], &t[13], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[27], &t[25], &t[26], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[28], &t[14], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[30], &t[15], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[31], &t[29], &t[30], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[34], &t[17], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[35], &t[33], &t[34], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[36], &t[18], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[38], &t[19], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[39], &t[37], &t[38], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[40], &t[20], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[42], &t[21], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[43], &t[41], &t[42], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[44], &t[22], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[46], &t[23], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[47], &t[45], &t[46], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[48], &t[24], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[50], &t[25], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[51], &t[49], &t[50], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[52], &t[26], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[54], &t[27], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[55], &t[53], &t[54], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[56], &t[28], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[58], &t[29], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[59], &t[57], &t[58], &t[ 1], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[60], &t[30], tmp);
|
|
sp_1024_proj_point_dbl_42(&t[62], &t[31], tmp);
|
|
sp_1024_proj_point_add_sub_42(&t[63], &t[61], &t[62], &t[ 1], tmp);
|
|
|
|
negy = t[0].y;
|
|
|
|
sp_1024_ecc_recode_7_42(k, v);
|
|
|
|
i = 146;
|
|
XMEMCPY(rt, &t[v[i].i], sizeof(sp_point_1024));
|
|
for (--i; i>=0; i--) {
|
|
sp_1024_proj_point_dbl_n_42(rt, 7, tmp);
|
|
XMEMCPY(p, &t[v[i].i], sizeof(sp_point_1024));
|
|
sp_1024_mont_sub_42(negy, p1024_mod, p->y, p1024_mod);
|
|
sp_1024_norm_42(negy);
|
|
sp_1024_cond_copy_42(p->y, negy, (sp_digit)0 - v[i].neg);
|
|
sp_1024_proj_point_add_42(rt, rt, p, tmp);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_1024_map_42(r, rt, tmp);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_1024));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp != NULL)
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#endif /* FP_ECC */
|
|
/* Add two Montgomery form projective points. The second point has a q value of
|
|
* one.
|
|
* Only the first point can be the same pointer as the result point.
|
|
*
|
|
* r Result of addition.
|
|
* p First point to add.
|
|
* q Second point to add.
|
|
* t Temporary ordinate data.
|
|
*/
|
|
static void sp_1024_proj_point_add_qz1_42(sp_point_1024* r,
|
|
const sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2*42;
|
|
sp_digit* t3 = t + 4*42;
|
|
sp_digit* t4 = t + 6*42;
|
|
sp_digit* t5 = t + 8*42;
|
|
sp_digit* t6 = t + 10*42;
|
|
|
|
/* Calculate values to subtract from P->x and P->y. */
|
|
/* U2 = X2*Z1^2 */
|
|
sp_1024_mont_sqr_42(t2, p->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t4, t2, p->z, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t2, t2, q->x, p1024_mod, p1024_mp_mod);
|
|
/* S2 = Y2*Z1^3 */
|
|
sp_1024_mont_mul_42(t4, t4, q->y, p1024_mod, p1024_mp_mod);
|
|
|
|
if ((~p->infinity) & (~q->infinity) &
|
|
sp_1024_cmp_equal_42(p->x, t2) &
|
|
sp_1024_cmp_equal_42(p->y, t4)) {
|
|
sp_1024_proj_point_dbl_42(r, p, t);
|
|
}
|
|
else {
|
|
sp_digit maskp;
|
|
sp_digit maskq;
|
|
sp_digit maskt;
|
|
sp_digit* x = t2;
|
|
sp_digit* y = t5;
|
|
sp_digit* z = t6;
|
|
int i;
|
|
|
|
/* H = U2 - X1 */
|
|
sp_1024_mont_sub_42(t2, t2, p->x, p1024_mod);
|
|
/* R = S2 - Y1 */
|
|
sp_1024_mont_sub_42(t4, t4, p->y, p1024_mod);
|
|
/* Z3 = H*Z1 */
|
|
sp_1024_mont_mul_42(z, p->z, t2, p1024_mod, p1024_mp_mod);
|
|
/* X3 = R^2 - H^3 - 2*X1*H^2 */
|
|
sp_1024_mont_sqr_42(t1, t4, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sqr_42(t5, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t3, p->x, t5, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t5, t5, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(x, t1, t5, p1024_mod);
|
|
sp_1024_mont_dbl_42(t1, t3, p1024_mod);
|
|
sp_1024_mont_sub_42(x, x, t1, p1024_mod);
|
|
/* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */
|
|
sp_1024_mont_sub_lower_42(t3, t3, x, p1024_mod);
|
|
sp_1024_mont_mul_42(t3, t3, t4, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t5, t5, p->y, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_sub_42(y, t3, t5, p1024_mod);
|
|
|
|
maskp = 0 - (q->infinity & (!p->infinity));
|
|
maskq = 0 - (p->infinity & (!q->infinity));
|
|
maskt = ~(maskp | maskq);
|
|
for (i = 0; i < 42; i++) {
|
|
r->x[i] = (p->x[i] & maskp) | (q->x[i] & maskq) | (x[i] & maskt);
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r->y[i] = (p->y[i] & maskp) | (q->y[i] & maskq) | (y[i] & maskt);
|
|
}
|
|
for (i = 0; i < 42; i++) {
|
|
r->z[i] = (p->z[i] & maskp) | (q->z[i] & maskq) | (z[i] & maskt);
|
|
}
|
|
r->z[0] |= p->infinity & q->infinity;
|
|
r->infinity = p->infinity & q->infinity;
|
|
}
|
|
}
|
|
|
|
#if defined(FP_ECC) || !defined(WOLFSSL_SP_SMALL)
|
|
/* Convert the projective point to affine.
|
|
* Ordinates are in Montgomery form.
|
|
*
|
|
* a Point to convert.
|
|
* t Temporary data.
|
|
*/
|
|
static void sp_1024_proj_to_affine_42(sp_point_1024* a, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
sp_digit* tmp = t + 4 * 42;
|
|
|
|
sp_1024_mont_inv_42(t1, a->z, tmp);
|
|
|
|
sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod);
|
|
|
|
sp_1024_mont_mul_42(a->x, a->x, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(a->y, a->y, t1, p1024_mod, p1024_mp_mod);
|
|
XMEMCPY(a->z, p1024_norm_mod, sizeof(p1024_norm_mod));
|
|
}
|
|
|
|
/* Generate the pre-computed table of points for the base point.
|
|
*
|
|
* width = 8
|
|
* 256 entries
|
|
* 128 bits between
|
|
*
|
|
* a The base point.
|
|
* table Place to store generated point data.
|
|
* tmp Temporary data.
|
|
* heap Heap to use for allocation.
|
|
*/
|
|
static int sp_1024_gen_stripe_table_42(const sp_point_1024* a,
|
|
sp_table_entry_1024* table, sp_digit* tmp, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* t = NULL;
|
|
#else
|
|
sp_point_1024 t[3];
|
|
#endif
|
|
sp_point_1024* s1 = NULL;
|
|
sp_point_1024* s2 = NULL;
|
|
int i;
|
|
int j;
|
|
int err = MP_OKAY;
|
|
|
|
(void)heap;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 3, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
s1 = t + 1;
|
|
s2 = t + 2;
|
|
|
|
err = sp_1024_mod_mul_norm_42(t->x, a->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(t->y, a->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(t->z, a->z, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
t->infinity = 0;
|
|
sp_1024_proj_to_affine_42(t, tmp);
|
|
|
|
XMEMCPY(s1->z, p1024_norm_mod, sizeof(p1024_norm_mod));
|
|
s1->infinity = 0;
|
|
XMEMCPY(s2->z, p1024_norm_mod, sizeof(p1024_norm_mod));
|
|
s2->infinity = 0;
|
|
|
|
/* table[0] = {0, 0, infinity} */
|
|
XMEMSET(&table[0], 0, sizeof(sp_table_entry_1024));
|
|
/* table[1] = Affine version of 'a' in Montgomery form */
|
|
XMEMCPY(table[1].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1].y, t->y, sizeof(table->y));
|
|
|
|
for (i=1; i<8; i++) {
|
|
sp_1024_proj_point_dbl_n_42(t, 128, tmp);
|
|
sp_1024_proj_to_affine_42(t, tmp);
|
|
XMEMCPY(table[1<<i].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[1<<i].y, t->y, sizeof(table->y));
|
|
}
|
|
|
|
for (i=1; i<8; i++) {
|
|
XMEMCPY(s1->x, table[1<<i].x, sizeof(table->x));
|
|
XMEMCPY(s1->y, table[1<<i].y, sizeof(table->y));
|
|
for (j=(1<<i)+1; j<(1<<(i+1)); j++) {
|
|
XMEMCPY(s2->x, table[j-(1<<i)].x, sizeof(table->x));
|
|
XMEMCPY(s2->y, table[j-(1<<i)].y, sizeof(table->y));
|
|
sp_1024_proj_point_add_qz1_42(t, s1, s2, tmp);
|
|
sp_1024_proj_to_affine_42(t, tmp);
|
|
XMEMCPY(table[j].x, t->x, sizeof(table->x));
|
|
XMEMCPY(table[j].y, t->y, sizeof(table->y));
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#endif /* FP_ECC | !WOLFSSL_SP_SMALL */
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^128, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* table Pre-computed table.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_1024_ecc_mulmod_stripe_42(sp_point_1024* r, const sp_point_1024* g,
|
|
const sp_table_entry_1024* table, const sp_digit* k, int map,
|
|
int ct, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* rt = NULL;
|
|
sp_digit* t = NULL;
|
|
#else
|
|
sp_point_1024 rt[2];
|
|
sp_digit t[2 * 42 * 37];
|
|
#endif
|
|
sp_point_1024* p = NULL;
|
|
int i;
|
|
int j;
|
|
int y;
|
|
int x;
|
|
int err = MP_OKAY;
|
|
|
|
(void)g;
|
|
/* Constant time used for cache attack resistance implementation. */
|
|
(void)ct;
|
|
(void)heap;
|
|
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
rt = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (rt == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 37, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = rt + 1;
|
|
|
|
XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
|
|
XMEMCPY(rt->z, p1024_norm_mod, sizeof(p1024_norm_mod));
|
|
|
|
y = 0;
|
|
x = 127;
|
|
for (j=0; j<8; j++) {
|
|
y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
|
|
x += 128;
|
|
}
|
|
XMEMCPY(rt->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(rt->y, table[y].y, sizeof(table[y].y));
|
|
rt->infinity = !y;
|
|
for (i=126; i>=0; i--) {
|
|
y = 0;
|
|
x = i;
|
|
for (j=0; j<8; j++) {
|
|
y |= (int)(((k[x / 25] >> (x % 25)) & 1) << j);
|
|
x += 128;
|
|
}
|
|
|
|
sp_1024_proj_point_dbl_42(rt, rt, t);
|
|
XMEMCPY(p->x, table[y].x, sizeof(table[y].x));
|
|
XMEMCPY(p->y, table[y].y, sizeof(table[y].y));
|
|
p->infinity = !y;
|
|
sp_1024_proj_point_add_qz1_42(rt, rt, p, t);
|
|
}
|
|
|
|
if (map != 0) {
|
|
sp_1024_map_42(r, rt, t);
|
|
}
|
|
else {
|
|
XMEMCPY(r, rt, sizeof(sp_point_1024));
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (rt != NULL)
|
|
XFREE(rt, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef FP_ECC
|
|
#ifndef FP_ENTRIES
|
|
#define FP_ENTRIES 16
|
|
#endif
|
|
|
|
/* Cache entry - holds precomputation tables for a point. */
|
|
typedef struct sp_cache_1024_t {
|
|
/* X ordinate of point that table was generated from. */
|
|
sp_digit x[42];
|
|
/* Y ordinate of point that table was generated from. */
|
|
sp_digit y[42];
|
|
/* Precomputation table for point. */
|
|
sp_table_entry_1024 table[256];
|
|
/* Count of entries in table. */
|
|
uint32_t cnt;
|
|
/* Point and table set in entry. */
|
|
int set;
|
|
} sp_cache_1024_t;
|
|
|
|
/* Cache of tables. */
|
|
static THREAD_LS_T sp_cache_1024_t sp_cache_1024[FP_ENTRIES];
|
|
/* Index of last entry in cache. */
|
|
static THREAD_LS_T int sp_cache_1024_last = -1;
|
|
/* Cache has been initialized. */
|
|
static THREAD_LS_T int sp_cache_1024_inited = 0;
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
static volatile int initCacheMutex_1024 = 0;
|
|
static wolfSSL_Mutex sp_cache_1024_lock;
|
|
#endif
|
|
|
|
/* Get the cache entry for the point.
|
|
*
|
|
* g [in] Point scalar multipling.
|
|
* cache [out] Cache table to use.
|
|
*/
|
|
static void sp_ecc_get_cache_1024(const sp_point_1024* g, sp_cache_1024_t** cache)
|
|
{
|
|
int i;
|
|
int j;
|
|
uint32_t least;
|
|
|
|
if (sp_cache_1024_inited == 0) {
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
sp_cache_1024[i].set = 0;
|
|
}
|
|
sp_cache_1024_inited = 1;
|
|
}
|
|
|
|
/* Compare point with those in cache. */
|
|
for (i=0; i<FP_ENTRIES; i++) {
|
|
if (!sp_cache_1024[i].set)
|
|
continue;
|
|
|
|
if (sp_1024_cmp_equal_42(g->x, sp_cache_1024[i].x) &
|
|
sp_1024_cmp_equal_42(g->y, sp_cache_1024[i].y)) {
|
|
sp_cache_1024[i].cnt++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* No match. */
|
|
if (i == FP_ENTRIES) {
|
|
/* Find empty entry. */
|
|
i = (sp_cache_1024_last + 1) % FP_ENTRIES;
|
|
for (; i != sp_cache_1024_last; i=(i+1)%FP_ENTRIES) {
|
|
if (!sp_cache_1024[i].set) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Evict least used. */
|
|
if (i == sp_cache_1024_last) {
|
|
least = sp_cache_1024[0].cnt;
|
|
for (j=1; j<FP_ENTRIES; j++) {
|
|
if (sp_cache_1024[j].cnt < least) {
|
|
i = j;
|
|
least = sp_cache_1024[i].cnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
XMEMCPY(sp_cache_1024[i].x, g->x, sizeof(sp_cache_1024[i].x));
|
|
XMEMCPY(sp_cache_1024[i].y, g->y, sizeof(sp_cache_1024[i].y));
|
|
sp_cache_1024[i].set = 1;
|
|
sp_cache_1024[i].cnt = 1;
|
|
}
|
|
|
|
*cache = &sp_cache_1024[i];
|
|
sp_cache_1024_last = i;
|
|
}
|
|
#endif /* FP_ECC */
|
|
|
|
/* Multiply the base point of P1024 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* g Point to multiply.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_1024_ecc_mulmod_42(sp_point_1024* r, const sp_point_1024* g, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
#ifndef FP_ECC
|
|
return sp_1024_ecc_mulmod_win_add_sub_42(r, g, k, map, ct, heap);
|
|
#else
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* tmp;
|
|
#else
|
|
sp_digit tmp[2 * 42 * 38];
|
|
#endif
|
|
sp_cache_1024_t* cache;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 42 * 38, heap, DYNAMIC_TYPE_ECC);
|
|
if (tmp == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
#ifndef HAVE_THREAD_LS
|
|
if (err == MP_OKAY) {
|
|
if (initCacheMutex_1024 == 0) {
|
|
wc_InitMutex(&sp_cache_1024_lock);
|
|
initCacheMutex_1024 = 1;
|
|
}
|
|
if (wc_LockMutex(&sp_cache_1024_lock) != 0) {
|
|
err = BAD_MUTEX_E;
|
|
}
|
|
}
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_ecc_get_cache_1024(g, &cache);
|
|
if (cache->cnt == 2)
|
|
sp_1024_gen_stripe_table_42(g, cache->table, tmp, heap);
|
|
|
|
#ifndef HAVE_THREAD_LS
|
|
wc_UnLockMutex(&sp_cache_1024_lock);
|
|
#endif /* HAVE_THREAD_LS */
|
|
|
|
if (cache->cnt < 2) {
|
|
err = sp_1024_ecc_mulmod_win_add_sub_42(r, g, k, map, ct, heap);
|
|
}
|
|
else {
|
|
err = sp_1024_ecc_mulmod_stripe_42(r, g, cache->table, k,
|
|
map, ct, heap);
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
XFREE(tmp, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
return err;
|
|
#endif
|
|
}
|
|
|
|
#endif
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* p Point to multiply.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_1024(const mp_int* km, const ecc_point* gm, ecc_point* r,
|
|
int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_1024 point[1];
|
|
sp_digit k[42];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_from_mp(k, 42, km);
|
|
sp_1024_point_from_ecc_point_42(point, gm);
|
|
|
|
err = sp_1024_ecc_mulmod_42(point, point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_to_ecc_point_42(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Multiply the base point of P1024 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_1024_ecc_mulmod_42(r, &p1024_base, k, map, ct, heap);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_NONBLOCK
|
|
static int sp_1024_ecc_mulmod_base_42_nb(sp_ecc_ctx_t* sp_ctx, sp_point_1024* r,
|
|
const sp_digit* k, int map, int ct, void* heap)
|
|
{
|
|
/* No pre-computed values. */
|
|
return sp_1024_ecc_mulmod_42_nb(sp_ctx, r, &p1024_base, k, map, ct, heap);
|
|
}
|
|
#endif /* WOLFSSL_SP_NONBLOCK */
|
|
|
|
|
|
#else
|
|
/* Striping precomputation table.
|
|
* 8 points combined into a table of 256 points.
|
|
* Distance of 128 between points.
|
|
*/
|
|
static const sp_table_entry_1024 p1024_table[256] = {
|
|
/* 0 */
|
|
{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x00 } },
|
|
/* 1 */
|
|
{ { 0x0162bc2,0x03f6370,0x0a26fe7,0x0621512,0x1decc6e,0x04cec0e,
|
|
0x077c279,0x030bab3,0x06d3582,0x14b7514,0x17e36e6,0x0fa6e18,
|
|
0x0601aec,0x067ae83,0x0b92656,0x1aff1ce,0x17d3e91,0x1617394,
|
|
0x0a7cbd6,0x03b725b,0x19ed862,0x13ad2b3,0x12c9b21,0x0ad5582,
|
|
0x185df2c,0x1cc9199,0x131a84f,0x111ce9a,0x08ec11b,0x18b9ffd,
|
|
0x1bc4852,0x03e7f3f,0x0386a27,0x1da2750,0x0d3b039,0x0d7b363,
|
|
0x0ecd349,0x12946e7,0x1e02ebf,0x0d43893,0x08dfff9 },
|
|
{ 0x03c0c83,0x03a9d60,0x15d6d29,0x11579b9,0x08e69d1,0x1adb24b,
|
|
0x06e23dd,0x0a5c707,0x0bf58f3,0x01fca4d,0x0f05720,0x0cf37a1,
|
|
0x025f702,0x07f94c6,0x0fd745a,0x12edd0b,0x198c6c7,0x01fb75e,
|
|
0x178f86d,0x0315e88,0x0093206,0x072a732,0x19f5566,0x09fdb3c,
|
|
0x1283b50,0x08bd823,0x15c361d,0x0a1957f,0x1addbe4,0x145f9fa,
|
|
0x1291f58,0x0f19699,0x037ef30,0x0248400,0x14f1ac7,0x0e9c291,
|
|
0x0fcfd83,0x0b6994a,0x007cf89,0x0f7bc78,0x02aa120 } },
|
|
/* 2 */
|
|
{ { 0x1900955,0x1b6d700,0x15b6a56,0x039d68c,0x05dc9cc,0x17f4add,
|
|
0x0241f9c,0x068a18f,0x1a040c3,0x0d72a23,0x0ba9ba8,0x06e0f2a,
|
|
0x0591191,0x1684b98,0x1fdcd0d,0x1a21ea9,0x074bda4,0x0526d80,
|
|
0x059101c,0x060de32,0x122cfd5,0x19c5922,0x052e7f9,0x093eec4,
|
|
0x0dad678,0x1720a34,0x02c3734,0x0f65343,0x1ad4928,0x18d0af0,
|
|
0x06ab75f,0x1b77454,0x0c63a81,0x119bccd,0x116e048,0x10026f3,
|
|
0x10e53bc,0x0159785,0x0ed87d0,0x0fe17e2,0x08c3eb2 },
|
|
{ 0x113696f,0x169f0f2,0x1fea692,0x1831903,0x0350ba5,0x019e898,
|
|
0x104d8f0,0x1783c5f,0x117a531,0x1ed3738,0x1584354,0x092035d,
|
|
0x0742ec6,0x14cffab,0x0fa37df,0x1a255a6,0x13e3dee,0x1f2556b,
|
|
0x003d37a,0x0768ca3,0x10b4d98,0x14a8179,0x064d949,0x1231aff,
|
|
0x199aba8,0x1cd3f13,0x19c03f1,0x1ffd096,0x1fd8c20,0x006b205,
|
|
0x0f5ed10,0x0ba4c83,0x1a21d21,0x110e5e1,0x110b0c9,0x06f3072,
|
|
0x11401e8,0x132805d,0x10c42b3,0x07c4a38,0x07bf416 } },
|
|
/* 3 */
|
|
{ { 0x1fd589e,0x1a7c471,0x080c705,0x01bf2e9,0x1b50179,0x182a4fe,
|
|
0x08f8cf9,0x069a12c,0x115924f,0x0848f7f,0x196b163,0x195bf36,
|
|
0x0feef79,0x1fb4e16,0x1310988,0x10579a5,0x03252cd,0x0c0bec8,
|
|
0x17c7777,0x09e9b34,0x16bdacf,0x1aa808d,0x1418498,0x1a28193,
|
|
0x0490d2e,0x1694fba,0x1136da1,0x08125d1,0x0b0fcc6,0x178b3bb,
|
|
0x0d8897b,0x1be2d5d,0x08c01e9,0x1ec1507,0x1d0612e,0x0ec506c,
|
|
0x0956e33,0x1aba714,0x1fc1dd5,0x18ce0b4,0x09871ed },
|
|
{ 0x16535f7,0x1bb6abb,0x0ee2f42,0x044c6b6,0x1214d60,0x10b7b22,
|
|
0x16b6674,0x0eb8184,0x15515bf,0x0a6f9d3,0x1c59d7f,0x0b78bd3,
|
|
0x0724a62,0x003439f,0x0d7bedd,0x0b89478,0x033bb2e,0x177ae4d,
|
|
0x01ac662,0x0366bd0,0x10eda97,0x12d1e34,0x07d7032,0x03c4683,
|
|
0x1dd898e,0x0f2546a,0x1a556b6,0x19d9799,0x0d34164,0x0203924,
|
|
0x1b8bb3d,0x08b815e,0x0bb3811,0x007ff8d,0x1a0871e,0x0e7e97d,
|
|
0x0272ed5,0x06fbb46,0x0deb745,0x0146e2c,0x0397ed1 } },
|
|
/* 4 */
|
|
{ { 0x15c2a27,0x105d93a,0x11133cf,0x12b2b0b,0x138e42f,0x142f306,
|
|
0x0f83c64,0x01e8d62,0x076273d,0x1f66860,0x115a6b0,0x010a327,
|
|
0x0a7800f,0x01a8c0c,0x139d2ad,0x06c77e0,0x0388496,0x1492c55,
|
|
0x032253f,0x0cc2f97,0x09a0845,0x15157cb,0x02f18aa,0x08cd1b3,
|
|
0x0280b5a,0x07d3361,0x1aa64bd,0x193beb1,0x001e99b,0x1bec9fa,
|
|
0x03976c2,0x1898718,0x0614fe1,0x0fb59f0,0x1470b33,0x11aa622,
|
|
0x0143b61,0x1abaf67,0x0629071,0x10bbf27,0x0402479 },
|
|
{ 0x1055746,0x128bc47,0x1b83ee8,0x001563c,0x05ba004,0x14934be,
|
|
0x053eeb0,0x081c363,0x15b4f47,0x18a908c,0x1ee951d,0x03a1376,
|
|
0x0425009,0x1cd09cd,0x19d2186,0x154fcf4,0x1b3f353,0x15d4209,
|
|
0x110f3bb,0x0ee3244,0x1bd0afe,0x1b1c23d,0x0511a34,0x149285a,
|
|
0x19ff63d,0x02b30fb,0x075096d,0x0ac7438,0x1f46301,0x07e6baf,
|
|
0x124f09c,0x1d65005,0x0072090,0x0380221,0x172f217,0x08d1e19,
|
|
0x1a032e7,0x01b97df,0x0760329,0x1cd916f,0x01a6fd1 } },
|
|
/* 5 */
|
|
{ { 0x15116a3,0x1480d46,0x11fe59e,0x0965ebe,0x0b84439,0x15d79d8,
|
|
0x1514983,0x019c735,0x160ccfc,0x10df30b,0x1d4fc87,0x07a5987,
|
|
0x16ac07e,0x0f688dd,0x00e3838,0x16185bb,0x1071c15,0x022a3a9,
|
|
0x083f96e,0x1a8e912,0x096d70d,0x16f238c,0x06882f8,0x04ed8f8,
|
|
0x1ad8a59,0x1039e1f,0x0f221bb,0x04d4398,0x031ac40,0x179bb74,
|
|
0x1967f6d,0x158a03a,0x0a35d1a,0x142ba13,0x0415036,0x0a15d31,
|
|
0x0bd734e,0x0ef0525,0x11d4197,0x1b82ac2,0x029b7d4 },
|
|
{ 0x1f4e20b,0x1e165e5,0x131512c,0x1eb1988,0x1c3f548,0x06560f8,
|
|
0x06d516c,0x0427301,0x100f806,0x007815a,0x0417803,0x11200cd,
|
|
0x0ce612b,0x01a80c4,0x0563b5e,0x0ed651e,0x0583f55,0x0600ee2,
|
|
0x11524b8,0x0064e54,0x0443298,0x1d07fc9,0x1de9588,0x1a1b882,
|
|
0x02b0029,0x03d6895,0x049e03a,0x0824a8b,0x13f272b,0x1c8186a,
|
|
0x0347af3,0x048603d,0x0e6ea40,0x083cc5d,0x1cbe8df,0x183cbe7,
|
|
0x02b4126,0x0161881,0x125fa4d,0x004a704,0x05d0928 } },
|
|
/* 6 */
|
|
{ { 0x12f780d,0x115bf7f,0x0c7560e,0x01afaed,0x14d2682,0x1ba5761,
|
|
0x0a11e1b,0x1d7c786,0x010823f,0x1ea1109,0x19efd03,0x02fdf6b,
|
|
0x0d227e4,0x12b47c6,0x03526da,0x177d8a2,0x1d61781,0x1a9de73,
|
|
0x1cdc62d,0x1c7e445,0x0c1f9cf,0x0fecef3,0x1fd13a2,0x15936aa,
|
|
0x0553f3f,0x05e78e6,0x1b9bcc0,0x1a5a108,0x0ae6b19,0x01514f8,
|
|
0x1825db2,0x0497177,0x03dbf5e,0x12d53f3,0x1d165ce,0x0e9958f,
|
|
0x04dd33c,0x15b11bc,0x1b9771b,0x068285f,0x00a26e4 },
|
|
{ 0x0aa9a08,0x099cfd6,0x1386020,0x0aa48dd,0x00f3110,0x1c9ba3a,
|
|
0x005c184,0x1c31259,0x1242f02,0x0c6a081,0x17a62a3,0x1a4076b,
|
|
0x12482bf,0x0d5df4a,0x1be51ad,0x1049313,0x0b93769,0x15c690c,
|
|
0x1985f1e,0x0d1d12c,0x0b91d52,0x08c5be9,0x058b9d5,0x11acf87,
|
|
0x07973fe,0x028962e,0x08ac05f,0x05c62a1,0x0294694,0x0f5e60d,
|
|
0x00dbd39,0x0a638e1,0x19910ce,0x1cf2851,0x1ad2dde,0x015e9ed,
|
|
0x1a120ad,0x05d8bae,0x0dbb1a3,0x0c3724c,0x019497c } },
|
|
/* 7 */
|
|
{ { 0x17659a8,0x0586320,0x03fda48,0x0f25965,0x077ab9c,0x03bcbfe,
|
|
0x1c602da,0x0c6ab6c,0x1e77593,0x057ac60,0x06c6193,0x1b6caac,
|
|
0x065155b,0x1c07a4a,0x1938d55,0x116405c,0x1b7229a,0x0758564,
|
|
0x15c6f58,0x129af04,0x18f9885,0x1cf1fd3,0x1773024,0x185a6f2,
|
|
0x148302a,0x0223dc5,0x02e43c5,0x00bf7ec,0x04b3c15,0x07409e7,
|
|
0x062b184,0x1ab36b8,0x1a4f27a,0x101111c,0x05cdf3a,0x16bf467,
|
|
0x0dff1c7,0x1c3985c,0x1de9b95,0x116a2f7,0x096b91b },
|
|
{ 0x0ac087c,0x0c8fa4d,0x0a3706a,0x1cd9fb6,0x0e62f74,0x1b006b6,
|
|
0x1fe697d,0x19211ad,0x0f917f9,0x1c0e682,0x14b6ff5,0x0bec7bc,
|
|
0x007796f,0x176b90c,0x16d9380,0x026fbcf,0x0f66fa4,0x107843b,
|
|
0x1287dc5,0x03dcc87,0x18a3327,0x0c3e255,0x12e6c81,0x090208f,
|
|
0x1710739,0x01be5d0,0x1566317,0x1f34321,0x00e125d,0x1395379,
|
|
0x0b432db,0x1e9e520,0x1142204,0x16e7dd1,0x12e5f38,0x0285a51,
|
|
0x03d3c35,0x130dc55,0x092777c,0x02b9ff8,0x073f3d3 } },
|
|
/* 8 */
|
|
{ { 0x0fd3673,0x142adf3,0x0ded761,0x1f3a429,0x109b70a,0x0236699,
|
|
0x0be4373,0x1bd1a66,0x1595510,0x0a9e00a,0x0494739,0x012c718,
|
|
0x095746a,0x02e60de,0x1f3a96e,0x1751f9a,0x068002e,0x027fd0a,
|
|
0x0bf35df,0x0796e04,0x05e310a,0x1de2750,0x0da6677,0x1f4eadd,
|
|
0x1a0d04e,0x1ec19ba,0x1b73b57,0x1b204f3,0x1fd56e4,0x1201928,
|
|
0x1c52064,0x105498b,0x07633a4,0x0082df4,0x04c06cd,0x1062e1a,
|
|
0x1247e57,0x0cc587b,0x087ea4e,0x0c886d7,0x088934f },
|
|
{ 0x113eabc,0x1a1d823,0x145fc27,0x03599b8,0x0ca7dd9,0x09e53e2,
|
|
0x098efbc,0x0964fb5,0x0258818,0x1972d3d,0x1709a62,0x0c25b2b,
|
|
0x0c0a8cb,0x10f978a,0x1a5d68b,0x126b868,0x0ede172,0x18f94dc,
|
|
0x102f078,0x17fadda,0x03dac3c,0x1f89931,0x14fd1ac,0x016ed03,
|
|
0x1be6dfb,0x1a2608a,0x155b690,0x1c63868,0x043d985,0x1f8c547,
|
|
0x1aa9f18,0x097bb69,0x1cb2083,0x07ac62a,0x10e1295,0x1362d41,
|
|
0x06fd69d,0x1566512,0x12385d3,0x1762a6a,0x00d1898 } },
|
|
/* 9 */
|
|
{ { 0x15ef043,0x19a30f1,0x15913a9,0x12692d6,0x107b67d,0x1c1d1e0,
|
|
0x05cef43,0x06bac58,0x051d29c,0x16a581c,0x070693e,0x1054e36,
|
|
0x1e3f428,0x0a5a1dc,0x0af3d99,0x1ea86ba,0x1aa2abd,0x0e3bd8a,
|
|
0x0af8f70,0x071501b,0x073b5cb,0x175240b,0x057f682,0x1721d7c,
|
|
0x16b4de7,0x1ec434c,0x14af23c,0x09f0fc4,0x04e4248,0x01eb1be,
|
|
0x162b7b4,0x1af4f5f,0x1ede666,0x05c9d72,0x168a873,0x0301bb2,
|
|
0x06fba39,0x0e7e92a,0x0b98295,0x1b88df0,0x02bdab1 },
|
|
{ 0x06fed61,0x0f115fd,0x0539e93,0x0b991bb,0x0a458aa,0x09117ae,
|
|
0x0b7c41c,0x0ee7c6e,0x1e5aff3,0x1525a27,0x0e39b41,0x174e94e,
|
|
0x16bc2d0,0x0f98f89,0x11c3875,0x1522234,0x13ae102,0x0bbffc9,
|
|
0x0431e21,0x1014a06,0x05ac8b3,0x143c1fe,0x07cf008,0x0e4ba0d,
|
|
0x0892544,0x110f633,0x196b210,0x0f1e1c2,0x1a6e8a8,0x18d7e7e,
|
|
0x0ea68eb,0x0f19a55,0x183ed37,0x0875700,0x158209b,0x0a659b7,
|
|
0x0bee641,0x11a330e,0x00482cc,0x1257382,0x0353eb8 } },
|
|
/* 10 */
|
|
{ { 0x0b5521e,0x0e56b08,0x0bc323f,0x00a5ce0,0x1a11b44,0x1ed24e0,
|
|
0x1a0363f,0x15ac604,0x0cbf36b,0x0dcb2a5,0x028b5f3,0x1c22982,
|
|
0x007b58c,0x131873f,0x1747df7,0x150263c,0x17d6760,0x1c65f1e,
|
|
0x12035df,0x0b0cd6c,0x0219eb3,0x19bf81b,0x161ca33,0x1514eae,
|
|
0x065ed42,0x0386eac,0x1641a8a,0x107e3e3,0x1f906b2,0x1fd2528,
|
|
0x0a1e788,0x0a87641,0x0ac6e83,0x13baa79,0x0de6e07,0x1c9e16c,
|
|
0x040016e,0x1de06a4,0x0d9f55f,0x0e3cc43,0x08da207 },
|
|
{ 0x0ce65ec,0x0a80276,0x0178f21,0x1f6e903,0x16d10d1,0x1cbd693,
|
|
0x1ef29e1,0x15ac97c,0x077e54a,0x1a226d8,0x17c3fd0,0x01937c1,
|
|
0x0417b6b,0x02a8435,0x11095b0,0x1ab471f,0x03bfd74,0x07ca962,
|
|
0x0713b6e,0x1c00b40,0x0328501,0x1e252bf,0x1545cb7,0x0baddc7,
|
|
0x0ce4e53,0x08c6da0,0x1031942,0x15de3cb,0x1561fcb,0x02f3c2b,
|
|
0x11ba145,0x0694449,0x068536a,0x0705172,0x089c3b0,0x18d351c,
|
|
0x042b03f,0x1a91239,0x0f57ecf,0x1c5877d,0x0862f55 } },
|
|
/* 11 */
|
|
{ { 0x06049fe,0x11c8791,0x07ecb5a,0x11b9779,0x0c92a57,0x11a7dbe,
|
|
0x1b2925d,0x1274a5f,0x03dea58,0x19a065b,0x07a458a,0x0714549,
|
|
0x13a39f3,0x0a4f20f,0x0cb7cf6,0x0fc804d,0x0db065a,0x1638e3e,
|
|
0x1a0a068,0x1709408,0x0eca4a9,0x01b98f7,0x18fbad4,0x1976e4a,
|
|
0x0913476,0x1c67368,0x06e5299,0x19f2f35,0x0fd9f10,0x061dc04,
|
|
0x0e6d136,0x1c15f8b,0x00da613,0x0df34f3,0x1f78fa9,0x1ea5b9c,
|
|
0x1c1ee74,0x0eb4326,0x01e40e9,0x1227790,0x071ab28 },
|
|
{ 0x15b60ad,0x0c7e21d,0x06133d8,0x0094186,0x0afb5e3,0x0019810,
|
|
0x00732f1,0x0cda447,0x1db1c0c,0x1e7c4a9,0x04aa34c,0x1c9b4c2,
|
|
0x069c994,0x08cb3d4,0x0ab8b0f,0x19a53af,0x0935b7a,0x1e146aa,
|
|
0x12695fe,0x0b7a26d,0x07f9807,0x1f4e421,0x12700dc,0x0644beb,
|
|
0x0a18d19,0x0c6165e,0x0d10b00,0x06eefa2,0x13a7277,0x16a3fdd,
|
|
0x063af97,0x032c5b8,0x0437d49,0x0440338,0x1824b70,0x19e7383,
|
|
0x15fff35,0x14e37b8,0x029940f,0x16cbc6c,0x08d087b } },
|
|
/* 12 */
|
|
{ { 0x1dc1844,0x091811f,0x115af88,0x1e20bd5,0x0eca27e,0x1451a43,
|
|
0x0981bc5,0x1964307,0x1e1d7a4,0x0afc03e,0x1750f8a,0x0c64fde,
|
|
0x077246a,0x03b812e,0x050c817,0x09c7d5c,0x1caf348,0x0a5efe3,
|
|
0x1d4b01d,0x07312bb,0x0ac0ec9,0x1b6bd4e,0x00b9957,0x15dbb61,
|
|
0x1fe208b,0x198cc2e,0x1149f79,0x13902fc,0x1de1ea7,0x07de189,
|
|
0x0ecc338,0x1989ed9,0x1f95b89,0x19066ce,0x1c7bd6e,0x03e55db,
|
|
0x1a8cfb0,0x0f05448,0x0dfb3f0,0x094c7db,0x0225ed3 },
|
|
{ 0x0bb1a85,0x18aa6dd,0x1968f84,0x0e3cd4a,0x13d8dae,0x058807e,
|
|
0x1f55aad,0x035a642,0x0ebc78e,0x026c9a7,0x1cf4df5,0x043691c,
|
|
0x0b02153,0x100f21e,0x1242fe8,0x0120b77,0x1d02750,0x09e11f8,
|
|
0x019a468,0x1ca0019,0x041c2a2,0x093032c,0x022caeb,0x004d6c0,
|
|
0x01caf30,0x1308aea,0x1149db3,0x0e2585e,0x132ffb1,0x01f38ac,
|
|
0x1c80713,0x0d4e995,0x094e13d,0x09bd23c,0x177c301,0x1c05ade,
|
|
0x02b1c97,0x1dbb016,0x1f1eea3,0x1cba110,0x0612b60 } },
|
|
/* 13 */
|
|
{ { 0x0245d6b,0x04ae7dd,0x1fdbbf5,0x0f459c7,0x1cf0cbb,0x1aff772,
|
|
0x0ab037f,0x14649b4,0x0cf28c6,0x0648a7c,0x0295ae4,0x0a1a861,
|
|
0x1472fdb,0x09eb901,0x16fdde4,0x193d207,0x091822a,0x0e7d2f6,
|
|
0x0ba8fa0,0x1ce7907,0x11390dd,0x1133144,0x1516ea5,0x0d597a6,
|
|
0x1648bca,0x01d5297,0x1a6281a,0x1ede4ed,0x18ed52f,0x09d651b,
|
|
0x16494db,0x110b583,0x13c2c54,0x042539a,0x0b6802f,0x0f95fea,
|
|
0x1768416,0x18fc0e1,0x061b8e5,0x1c3a5af,0x00f7334 },
|
|
{ 0x196067e,0x1ae41b2,0x001abee,0x1271833,0x13e54e1,0x0586e61,
|
|
0x1659ce7,0x1f3050b,0x1424035,0x1a9fa1e,0x1e4254a,0x03f1bfd,
|
|
0x1a38c53,0x0d87ab8,0x1efa393,0x14f0f21,0x0d2a39c,0x04d060f,
|
|
0x01bc988,0x1983acc,0x0b4a2fe,0x18b95be,0x0772242,0x176f0d1,
|
|
0x0a6fbcc,0x124e19e,0x0bf9cfb,0x0362210,0x166c48d,0x1e8bfe5,
|
|
0x1cd642d,0x10dc28a,0x156b0a6,0x156c2c9,0x0b1014f,0x16ebad0,
|
|
0x054d30f,0x172afd6,0x1a526ca,0x0e5f15d,0x067636a } },
|
|
/* 14 */
|
|
{ { 0x11d6bea,0x031de5c,0x0e598e0,0x1d247d9,0x0e263a2,0x13d6535,
|
|
0x0264b18,0x0fd3af6,0x077af9e,0x176800d,0x0bfaef1,0x199e495,
|
|
0x109214a,0x1c02ad4,0x1592e59,0x0933b46,0x11ce027,0x0804ccd,
|
|
0x11a81a9,0x0749c3c,0x0fe7e41,0x1b1728f,0x081744f,0x150877d,
|
|
0x07d349b,0x0cf1af4,0x14c60c5,0x14c6704,0x0019230,0x145d2a3,
|
|
0x1c9808f,0x16ffa39,0x1107721,0x17ea9cd,0x10aff7c,0x108d6aa,
|
|
0x1c18af3,0x0a7a7c0,0x02596cc,0x0ecc159,0x0086f98 },
|
|
{ 0x0bb9850,0x00caa46,0x1231d9c,0x01441a5,0x0210b73,0x1ab3863,
|
|
0x1415d4c,0x1d48109,0x10324ba,0x166e2ca,0x1ba6d0f,0x0be58ed,
|
|
0x04607fc,0x0207fd3,0x04f403d,0x08c79e7,0x1962dc1,0x1f0088b,
|
|
0x11dc979,0x1704a33,0x1186f00,0x1b2de8e,0x0d7981c,0x1ee5558,
|
|
0x0554c2c,0x0bef9ec,0x1bbe8d2,0x09ba1fb,0x06ad11b,0x13467b2,
|
|
0x0b75c48,0x13ef71d,0x1c20afb,0x16ff283,0x0753f01,0x14c612d,
|
|
0x1245549,0x1bef8e3,0x1a041da,0x007cc35,0x0681f94 } },
|
|
/* 15 */
|
|
{ { 0x1a0623b,0x0a8b1e4,0x0351f2b,0x0ecff57,0x1bf8295,0x17be3e6,
|
|
0x0c3b206,0x1845995,0x0e966d5,0x14f1c64,0x1390711,0x1aa5e1a,
|
|
0x1c34430,0x12959ac,0x181d68a,0x0024e84,0x1e333bd,0x09216e9,
|
|
0x1fb48d0,0x07ec6b3,0x0ffacda,0x186bea9,0x137ccdc,0x08187de,
|
|
0x156f076,0x0be2fff,0x106ef79,0x0f07843,0x0bb3364,0x051575c,
|
|
0x01761e1,0x1d5a108,0x0c7c533,0x115ea0f,0x108fe6d,0x1e96fe2,
|
|
0x1075d4a,0x018a2e3,0x1642955,0x09574c0,0x00c9de9 },
|
|
{ 0x1d5682b,0x1939aca,0x1bb63b5,0x065d84e,0x111c428,0x1b50693,
|
|
0x0bb562c,0x11fa3e9,0x08498a8,0x155a062,0x03d1458,0x18c4890,
|
|
0x0258c8f,0x1bce7ff,0x123292e,0x06b3b17,0x03c701a,0x0c855ac,
|
|
0x1f57457,0x0634e67,0x133caee,0x1de4891,0x00a9565,0x187c784,
|
|
0x1cae4b6,0x044080c,0x10a64e0,0x0a26085,0x1c8199e,0x141efa3,
|
|
0x0483800,0x1e5401d,0x0d68e58,0x0d71dc8,0x1d069dd,0x04d3c5b,
|
|
0x071c30b,0x097652c,0x18e5ae3,0x01d763b,0x0733dca } },
|
|
/* 16 */
|
|
{ { 0x159213a,0x04ae825,0x003bd6d,0x131ae04,0x0a67203,0x13b8e0e,
|
|
0x02698ad,0x1969796,0x02b9eb0,0x156f76a,0x0e88489,0x0ea919b,
|
|
0x11eb544,0x1844486,0x06aff37,0x08d681c,0x163698e,0x029284c,
|
|
0x0ba704e,0x1fe1610,0x1a71e1b,0x06a884c,0x0862793,0x172398f,
|
|
0x0c9bcc9,0x05f11b0,0x104dfb1,0x17a9afb,0x119f6e9,0x1290e8a,
|
|
0x00f40d5,0x19f064a,0x15f6d78,0x1515a5f,0x00c637b,0x19c8602,
|
|
0x0f4c319,0x09924a7,0x09f5f0c,0x08e1e3f,0x02ab3bd },
|
|
{ 0x02c9fbb,0x1db4049,0x1b455d4,0x101e2d8,0x069e7dc,0x00b77e4,
|
|
0x144d6eb,0x1370688,0x0846d1d,0x19351da,0x18b0850,0x1dc765a,
|
|
0x15b517f,0x0594956,0x016be88,0x15826d2,0x11a2cad,0x0952b89,
|
|
0x0f6f2a3,0x009b1fd,0x1fb2cd9,0x179f9b2,0x17fb6a1,0x0fd5439,
|
|
0x1b208dc,0x1e0384b,0x129179d,0x1346b50,0x1d118e8,0x031667a,
|
|
0x1a105e8,0x03edd33,0x00c04a8,0x1043e9e,0x12c2e9e,0x05888e0,
|
|
0x1ea22ad,0x0513e89,0x148a5be,0x02c984f,0x093a4b4 } },
|
|
/* 17 */
|
|
{ { 0x11efb7a,0x18de08f,0x1037509,0x0c67f99,0x0e4e68e,0x0fa8545,
|
|
0x123c6c4,0x1133b37,0x1af0760,0x0181cc7,0x14380d5,0x05f6887,
|
|
0x0145e24,0x1b71ea6,0x1b09467,0x15a12e7,0x190ba9b,0x1d5b87b,
|
|
0x06b7443,0x0255abf,0x02b4de6,0x070a74a,0x0e0df95,0x1716d15,
|
|
0x056d3dd,0x0040bad,0x106b0a9,0x10b6467,0x080f94e,0x1618786,
|
|
0x1e7e3fd,0x1131b69,0x17f3fb7,0x1ee6ea5,0x113d169,0x0b458c0,
|
|
0x1e3d389,0x15d97b7,0x1dd8fce,0x1ae65dc,0x0342ce0 },
|
|
{ 0x1491b1f,0x109ca67,0x0e57ac9,0x0e3213c,0x1caaeed,0x126df56,
|
|
0x0156a7f,0x09bb988,0x1493d60,0x1d3308e,0x17afbc5,0x147439c,
|
|
0x15ba445,0x11cc4e5,0x0b8a163,0x1080dd0,0x08283f5,0x0dcb7a1,
|
|
0x055b3d5,0x0ef7334,0x0a0e998,0x13270b3,0x0be41a9,0x12eda27,
|
|
0x1d353b2,0x100e750,0x1cdb186,0x1f82de4,0x155d86e,0x0219d87,
|
|
0x0076c13,0x11d6698,0x0b4b269,0x101401e,0x1de0ab9,0x0a71a0f,
|
|
0x03be3ec,0x161de5a,0x1f4810e,0x1e7c2ad,0x0455f4a } },
|
|
/* 18 */
|
|
{ { 0x14ec21c,0x1f9313a,0x08e3015,0x13c7437,0x1eacd4c,0x160ff49,
|
|
0x0434445,0x16c7404,0x0eacc8a,0x075274a,0x1ccb2b9,0x1935d4d,
|
|
0x0e31c00,0x035cbae,0x0d88e76,0x143d2b9,0x18ca14e,0x1b2a6ae,
|
|
0x019ff22,0x1a63e8a,0x1ecb230,0x05b1aaf,0x122ee43,0x02e5d1c,
|
|
0x01ecedc,0x19bbc7c,0x032c019,0x1107015,0x02d0122,0x1700f0b,
|
|
0x17066c0,0x18b5e28,0x0087a06,0x0e1aa07,0x02dedcb,0x0de09b9,
|
|
0x0de3c06,0x07790a4,0x07edfdc,0x0862601,0x04f1482 },
|
|
{ 0x02055e2,0x027e737,0x019d780,0x150d864,0x09e247e,0x0ed5514,
|
|
0x0f6557e,0x0769d79,0x1ceb7f6,0x0af9097,0x1e12834,0x183f0c6,
|
|
0x115ecc5,0x1abb012,0x0ce002d,0x052a8a7,0x1c38a6a,0x0f5c980,
|
|
0x04f3746,0x0d74314,0x0d240f1,0x08c43e1,0x00c4f49,0x12827ed,
|
|
0x035859a,0x1e2fcc9,0x1bf8ff5,0x04680bc,0x00ee054,0x159a0b7,
|
|
0x0c19e2b,0x07f5b55,0x13be7bb,0x022388f,0x08b20a2,0x0cf203f,
|
|
0x0d662ff,0x086d982,0x05c2f25,0x1a87802,0x074d5d2 } },
|
|
/* 19 */
|
|
{ { 0x15bfe11,0x016e015,0x079e8c0,0x1aa5a64,0x0733410,0x1cdd448,
|
|
0x03d9659,0x0dc2b24,0x0685b23,0x112460a,0x1d81003,0x0b2868d,
|
|
0x108cfab,0x00638bf,0x15ebedd,0x08aed3e,0x08c6604,0x186dd59,
|
|
0x1370c91,0x0132d13,0x0d050fa,0x1161187,0x10780ab,0x0b7dee8,
|
|
0x01554e4,0x1b786cb,0x0b3935e,0x0d11530,0x02d22e9,0x1d63af3,
|
|
0x0a3eb7b,0x17a5974,0x11512a6,0x03a4fd7,0x198af9f,0x16f10d1,
|
|
0x0e9f5a6,0x0246c0d,0x1e8a620,0x0858b0a,0x06b1a54 },
|
|
{ 0x1242066,0x15cd6a1,0x0aba7d6,0x0a59994,0x0afef1b,0x076e270,
|
|
0x0fb1e62,0x1ab6368,0x10341b0,0x0860078,0x0aacdc3,0x11ef6a1,
|
|
0x194d68b,0x19d3254,0x03939bf,0x0d09d35,0x0fb7f1a,0x00cc19c,
|
|
0x14683d7,0x01ce906,0x05158bc,0x06ed622,0x0b2b3cb,0x13feed6,
|
|
0x139995e,0x02ae0a6,0x1c58e4c,0x0940367,0x0d83765,0x1752c44,
|
|
0x0c5ab0f,0x0e464ef,0x04d9a9a,0x0dddfdc,0x1a47847,0x1132264,
|
|
0x0bb6717,0x1b8bd75,0x12b2165,0x04d1762,0x04c2135 } },
|
|
/* 20 */
|
|
{ { 0x1532833,0x1f0534a,0x019cb9b,0x1dac4da,0x0bca228,0x0f39ded,
|
|
0x1cf6592,0x018455d,0x0f03c4c,0x041d43d,0x1a6d148,0x0eba6a2,
|
|
0x09e954e,0x1a28354,0x1d427b9,0x19f20ae,0x16e2aea,0x0a4e593,
|
|
0x09027e4,0x0ebaeff,0x16b9082,0x1ef85de,0x187adbc,0x0264e08,
|
|
0x002cbe4,0x058ca41,0x06c7126,0x0be7f84,0x1fee593,0x05d41b0,
|
|
0x1cddb1a,0x0a1c0a3,0x18cbbd9,0x1382150,0x01e4c63,0x1647095,
|
|
0x00dd1e8,0x155f56c,0x10cd0a4,0x052b86f,0x065713c },
|
|
{ 0x0b77b9a,0x05474e7,0x11a7733,0x0e476d2,0x0f97e72,0x0eb5941,
|
|
0x0fb9a80,0x1fd8ed5,0x15abecd,0x092901e,0x0435c0e,0x0104525,
|
|
0x1889448,0x1818a21,0x04c5092,0x08f87f3,0x1f17cd4,0x182104e,
|
|
0x0157209,0x1e40b39,0x00697c6,0x112b607,0x165f5e1,0x05b2989,
|
|
0x1b6fe41,0x0eead4e,0x0665310,0x134c8b2,0x1e21a31,0x0550e44,
|
|
0x03848d2,0x18d407e,0x0904b50,0x17f566b,0x055a985,0x16ab82a,
|
|
0x1cc7693,0x1b68dab,0x0f0e138,0x0d8775c,0x06b0e99 } },
|
|
/* 21 */
|
|
{ { 0x0eced00,0x04fd5e6,0x0998c9e,0x15cb6f5,0x1237e71,0x0f5e6f9,
|
|
0x189a4b7,0x11f0f65,0x0b61dad,0x1922890,0x1e00f2d,0x1c91a6b,
|
|
0x0de11e5,0x0c72878,0x137d75e,0x15725f6,0x0b4bcd2,0x0b07734,
|
|
0x138cd8f,0x165eb83,0x064798a,0x0d3e6a1,0x056e8e7,0x1e9f67e,
|
|
0x172eb83,0x06d8d32,0x0395bc2,0x1eefbd1,0x0562c20,0x1b0f0b9,
|
|
0x1d05d0d,0x114b1e1,0x0349ff8,0x0eb715f,0x1c6e134,0x09c09b4,
|
|
0x1e9ff3b,0x0781a14,0x08fe0da,0x00acf04,0x04022a2 },
|
|
{ 0x1847375,0x1de82c1,0x0bc149e,0x047e8a3,0x1ae56b6,0x163f8c1,
|
|
0x1c9352c,0x11ac331,0x14525b9,0x1191fad,0x0212d7b,0x07341c1,
|
|
0x16a9d8d,0x1d8963b,0x0175fdb,0x182a9a0,0x03e708b,0x06b8e24,
|
|
0x109506f,0x0dfa50e,0x1ddb8ca,0x06fc1cb,0x02bcf73,0x199e486,
|
|
0x131253e,0x1c6dc06,0x0163606,0x0e87421,0x191f68c,0x1590b89,
|
|
0x1fcfd23,0x06776ca,0x13aff88,0x03f18a4,0x15981f9,0x0c3a2bd,
|
|
0x008279f,0x0acd88f,0x0a55840,0x196494d,0x0312179 } },
|
|
/* 22 */
|
|
{ { 0x1615ac2,0x061e503,0x1606a53,0x082435a,0x05865e6,0x0c35bcc,
|
|
0x185be9e,0x03b5c8e,0x19d5e0f,0x0ad2075,0x115fa8e,0x04c87b2,
|
|
0x19a9143,0x1d1432e,0x19b5a8f,0x15d191b,0x1961014,0x183b8ed,
|
|
0x1daa1f2,0x0f99cd2,0x0f6077a,0x108a1d0,0x09f790b,0x127b269,
|
|
0x1cc09d9,0x01ef101,0x0e63b13,0x04030d2,0x05df4b9,0x036c1d1,
|
|
0x1af5dd5,0x0c5605a,0x0d9eb47,0x138c485,0x0823416,0x17f555e,
|
|
0x031221b,0x1c0c0fa,0x047a948,0x0f0e66a,0x0417d6c },
|
|
{ 0x091e9a8,0x0c0db87,0x1accf2f,0x1186e1a,0x1334041,0x1511b9b,
|
|
0x0c42a3a,0x0ad04bb,0x06c7d67,0x19584f2,0x0cf7b63,0x1d37298,
|
|
0x1be288e,0x0b4af1f,0x0109aec,0x1d1119b,0x086dce9,0x1530bb6,
|
|
0x05978d8,0x191244c,0x1b093f4,0x0fb031f,0x1453904,0x1f3c098,
|
|
0x1ac20c8,0x0b0b483,0x137f4ab,0x1dee8d3,0x12199ac,0x1d72422,
|
|
0x18ae8c2,0x0255868,0x0681293,0x0a41698,0x01cf24b,0x0a0237d,
|
|
0x0833099,0x065fc4f,0x0282bfd,0x0a5a28e,0x002189d } },
|
|
/* 23 */
|
|
{ { 0x0599c69,0x00ceec9,0x0b29cf9,0x16ffd86,0x1b94221,0x1dfdfea,
|
|
0x06f4826,0x0b7657f,0x063ed89,0x0f54bd2,0x01bde58,0x08d67e9,
|
|
0x1966091,0x1e8a0d1,0x071e817,0x0826b7a,0x0cf83d6,0x1e3cf64,
|
|
0x020d41e,0x1fa85f3,0x10277f8,0x1b8bd9e,0x0bf2d4e,0x194b443,
|
|
0x18dcd67,0x1c34332,0x1334525,0x0d4d815,0x195067a,0x0b871a5,
|
|
0x0305bcf,0x1be892b,0x11208e3,0x001091b,0x139bb0a,0x03a5bac,
|
|
0x10782c7,0x1962559,0x1dbe8ce,0x17aa422,0x07bbf8a },
|
|
{ 0x18b981a,0x12557d3,0x00a2fa7,0x0c609d9,0x188b4e3,0x0cef51b,
|
|
0x13ce4e5,0x18e188b,0x1240b39,0x054dee9,0x00edf5c,0x0fba507,
|
|
0x06499cd,0x183d081,0x1a42cb8,0x1e36660,0x198ee92,0x011316a,
|
|
0x11c9692,0x1aefbd6,0x0a0ec62,0x1e3de1d,0x085bc96,0x0bdeff5,
|
|
0x18b65d1,0x147b16e,0x142e5b5,0x12f2443,0x0f1906d,0x02e1d00,
|
|
0x102e4a2,0x1d6e98e,0x0476b9b,0x1b1117d,0x0ed71d5,0x1e42fbb,
|
|
0x1788504,0x1c16182,0x1c5af09,0x0d9f024,0x0860d09 } },
|
|
/* 24 */
|
|
{ { 0x179bbf9,0x019bea6,0x1e03faf,0x10d3ee9,0x1d53eab,0x0826a9a,
|
|
0x08254cc,0x12ffe6d,0x0196f8b,0x15c106d,0x19a424a,0x1a3eeb9,
|
|
0x14961d3,0x02341ba,0x05fb010,0x1973763,0x1bf93a6,0x1d34670,
|
|
0x17c0868,0x08adff8,0x1fdb503,0x18c4a07,0x0d428b6,0x0008413,
|
|
0x10f8fef,0x03abbe2,0x1c12596,0x0c6ba2e,0x18770ad,0x136cc5d,
|
|
0x0f9c95d,0x140f1ca,0x019b028,0x041bc47,0x132be7f,0x006c9a9,
|
|
0x10dd39a,0x1efa08f,0x1e48068,0x084075b,0x07e80e4 },
|
|
{ 0x19a1ddf,0x1c52ba9,0x15892d7,0x1ddc90c,0x1248e7a,0x1010f0e,
|
|
0x1247605,0x18838f6,0x1fd36d2,0x13dc38d,0x100364b,0x0a0815d,
|
|
0x13da38b,0x10c9f8d,0x009d849,0x0f1ade5,0x086fb1f,0x1b4e1ff,
|
|
0x009eb0c,0x116f0dd,0x08f756c,0x039a43e,0x05a1fdb,0x1bdcb78,
|
|
0x1221719,0x00c55c7,0x1ffce65,0x09d08e7,0x027c800,0x000a548,
|
|
0x0a3ce13,0x1543a5c,0x167be9a,0x0f778cc,0x1b4f819,0x190d2d0,
|
|
0x07bd837,0x1e35846,0x1618dcd,0x1a33d17,0x05dcab5 } },
|
|
/* 25 */
|
|
{ { 0x07d772b,0x0141d4d,0x166c1e1,0x0bca812,0x0b49e52,0x00a55ab,
|
|
0x0c02219,0x152a8d7,0x09d74b2,0x02240b1,0x0c2c6f5,0x015a407,
|
|
0x0b26789,0x0469fc3,0x1ea0af3,0x1078e3c,0x1b5d85a,0x189a95f,
|
|
0x0b41f33,0x1e2dc7f,0x043ff29,0x1c20f06,0x100a98e,0x06f3fdf,
|
|
0x122c56b,0x1934827,0x0ec4913,0x13b14ca,0x08bdea1,0x1b6f9d1,
|
|
0x13998d6,0x1eda8ab,0x0b68851,0x19b9a8c,0x006273f,0x16e9585,
|
|
0x0b2cbda,0x007cefc,0x15262b5,0x13d5b93,0x008cc2d },
|
|
{ 0x170c84b,0x1343360,0x1210b9a,0x16b4934,0x1b989e8,0x0644c95,
|
|
0x0038341,0x046f61c,0x061b3a4,0x0d69a3c,0x0062655,0x08a161a,
|
|
0x133c952,0x1188065,0x0488557,0x0eda1c7,0x16ef032,0x18c932d,
|
|
0x1b50ad4,0x10b2b4e,0x13b60fe,0x107e31a,0x02a5b7b,0x0df127c,
|
|
0x00dc824,0x05d3b0f,0x1bc29d3,0x1d92057,0x1fad9b4,0x03421fe,
|
|
0x1d58402,0x09fb6d2,0x16a60e4,0x1ac852e,0x0b21fbd,0x0e7ea75,
|
|
0x12870a3,0x0f35f00,0x156c34a,0x182ab54,0x0991fad } },
|
|
/* 26 */
|
|
{ { 0x0844ffe,0x02587da,0x01c60af,0x08c1f17,0x1392271,0x11f8f9b,
|
|
0x0038933,0x1d91580,0x0163519,0x06aa45a,0x022d7fc,0x0857105,
|
|
0x107aaf8,0x15ee4d3,0x02c3130,0x1facf3d,0x1524ba5,0x1d036a8,
|
|
0x04f37b0,0x035f41f,0x18f0d0b,0x1d6fc4f,0x0a02556,0x1465924,
|
|
0x1e92dee,0x1f24365,0x04ff816,0x195c7f3,0x0919aa0,0x184afd3,
|
|
0x02fc981,0x0dc1e37,0x154741e,0x07cc407,0x1dd0c3b,0x0e55da3,
|
|
0x134991d,0x0b7bb5b,0x03fa64a,0x0504b3e,0x066cf8d },
|
|
{ 0x06f5868,0x0c82d91,0x1a7a6c0,0x182d213,0x0102e88,0x1bf5aa6,
|
|
0x0245928,0x04657a1,0x0c98163,0x19129f4,0x0b14f3d,0x1d3b0d7,
|
|
0x1737f84,0x17f5557,0x0d49152,0x008dc5c,0x1772ca0,0x133e437,
|
|
0x198cdcb,0x19ca1cc,0x0a0486b,0x105b4a8,0x1da8ea5,0x0357527,
|
|
0x194d7fc,0x13730fc,0x0f04c9b,0x12af825,0x16b0051,0x07f2172,
|
|
0x0326d96,0x10b24e8,0x0d297fc,0x19352ce,0x1a6c5df,0x16eca99,
|
|
0x079d2eb,0x134cedd,0x19122aa,0x0b41d96,0x05fca0c } },
|
|
/* 27 */
|
|
{ { 0x09a6663,0x112f9ab,0x129f89b,0x0fcd549,0x09597ee,0x0c5c060,
|
|
0x1369a34,0x0604b49,0x1229267,0x083015a,0x01c8251,0x0ca00e7,
|
|
0x139af5f,0x13399d2,0x1bb6cd0,0x052a3fd,0x1688657,0x107ae73,
|
|
0x0e62ba6,0x146c170,0x16c3872,0x0015987,0x180d1ea,0x02c42b0,
|
|
0x13b231a,0x0f66908,0x0bb9b1b,0x1fb39f2,0x1cf9e66,0x12d42e5,
|
|
0x01217c2,0x05747fd,0x1a5a6e4,0x06b93eb,0x1c8147b,0x0155fcc,
|
|
0x02081a1,0x0e35d95,0x0c2d382,0x1e172e7,0x0657acb },
|
|
{ 0x074c8d4,0x02337e1,0x1344c4c,0x0c61532,0x0276517,0x1ca1afa,
|
|
0x16329c1,0x00c42e4,0x0eb897a,0x0428203,0x1b84c11,0x1ddcac3,
|
|
0x1bf38df,0x150bbc5,0x1d3eb3e,0x173d223,0x017b9ab,0x13b2e33,
|
|
0x03c424c,0x0a9337b,0x1159b13,0x1bd39dc,0x103ad8c,0x0fd16d5,
|
|
0x1ccf16f,0x1a9f960,0x0861f7b,0x1665807,0x0b9c625,0x0ea4c18,
|
|
0x0e226b4,0x05e21ca,0x135eae3,0x1aade0b,0x070a757,0x1b6397b,
|
|
0x0539db0,0x014623f,0x0ceed09,0x02590a5,0x03d2da4 } },
|
|
/* 28 */
|
|
{ { 0x11f2865,0x015b743,0x035a5dc,0x1e28524,0x16cb639,0x1ac308a,
|
|
0x08a8116,0x024650a,0x1f3b138,0x1ca1d68,0x081ba3c,0x0014e24,
|
|
0x0ae6c22,0x11a6acf,0x024396a,0x1eeb385,0x140f6b7,0x1d5a97e,
|
|
0x002fd59,0x0591bc3,0x0396f52,0x1956677,0x0607a5e,0x1d4b976,
|
|
0x15819c4,0x1f7f01b,0x02ad474,0x1b330bd,0x150fd80,0x0b655e5,
|
|
0x03789b2,0x12fc390,0x19d6b13,0x11abefd,0x0053de5,0x16b0563,
|
|
0x07f4c7f,0x13c1108,0x1f98626,0x05b806a,0x002aeef },
|
|
{ 0x07ec9be,0x1c93796,0x0804ae9,0x1ce4b16,0x092f307,0x1d35a51,
|
|
0x0a8431b,0x156e9cc,0x1e2bcc5,0x06042a4,0x0301ce0,0x1b70f77,
|
|
0x0db4160,0x194f8ca,0x1bc14a4,0x09539ab,0x0146dda,0x0875c6d,
|
|
0x17a88f4,0x1a87a42,0x1fae0b5,0x017e1a5,0x1b3afbc,0x10eaf4e,
|
|
0x164d084,0x051d669,0x00b4d33,0x028026d,0x0d95e2c,0x13a10e9,
|
|
0x0a02729,0x0f0dd54,0x1fd1d6e,0x12ff661,0x0db68a5,0x073d622,
|
|
0x0077920,0x038dd56,0x0bac122,0x002962b,0x06b446c } },
|
|
/* 29 */
|
|
{ { 0x1e8fe80,0x0f59712,0x085f206,0x0d30471,0x0b5f790,0x120c249,
|
|
0x1a65a07,0x08bade3,0x098ea6d,0x056c56b,0x00b9016,0x15a97fa,
|
|
0x0d5bae5,0x140920b,0x1b70c9e,0x0f94202,0x185a334,0x0c598d4,
|
|
0x0a994e4,0x1b4c210,0x15fb0b4,0x16da461,0x072e46c,0x155f188,
|
|
0x0817cd2,0x0e04f4b,0x0f37f73,0x14c6090,0x1692541,0x09b0895,
|
|
0x05dc156,0x1f14541,0x1dcd712,0x02940af,0x08e8d73,0x0ab356c,
|
|
0x132b609,0x0475f04,0x014bcc3,0x097611c,0x0861342 },
|
|
{ 0x0231d8a,0x01031d9,0x199ca24,0x13b34c2,0x10f6232,0x0d4f93d,
|
|
0x03f9c1c,0x0fd55f4,0x0603f04,0x1e6c4b0,0x0a870da,0x14edfb2,
|
|
0x16118cc,0x18ea41d,0x05398ad,0x0a4c468,0x0ddba70,0x15091e6,
|
|
0x166d716,0x0ec86ff,0x0fa31a5,0x0126468,0x094c06f,0x0484f9b,
|
|
0x0ad4410,0x0014b78,0x034ea9b,0x1cdf6bc,0x0a39960,0x0440039,
|
|
0x0b73631,0x1081a7f,0x1afca12,0x0eaa0a6,0x08f77a4,0x1a53e99,
|
|
0x0441734,0x1be2cc4,0x195f000,0x133399f,0x086333a } },
|
|
/* 30 */
|
|
{ { 0x0f53b40,0x1d3a8f6,0x150b484,0x045ef14,0x0ff2c6f,0x1d72b6e,
|
|
0x1c38bc4,0x11c1eb3,0x10e6174,0x0fc665f,0x1105164,0x1973ae5,
|
|
0x170aade,0x064e6e5,0x0bb6149,0x1f8e0d6,0x12c1eaf,0x147005b,
|
|
0x09ca040,0x04850b5,0x0afa89b,0x105b3ce,0x0a9fa9f,0x014dedf,
|
|
0x18c264f,0x1cbae95,0x0c3a010,0x1daf62e,0x1730497,0x15a2e42,
|
|
0x0f96a4f,0x0130dd2,0x12bf5d4,0x06057e4,0x0a71a88,0x1ea4d6b,
|
|
0x199dc3a,0x0fa3e4d,0x0b3242b,0x1c57440,0x012b25f },
|
|
{ 0x1eea395,0x06bc519,0x117026e,0x11ec67f,0x07a9361,0x076777e,
|
|
0x058a49c,0x018fd04,0x0c628ed,0x123bcdc,0x1a24e54,0x194343a,
|
|
0x1091db5,0x0c376e4,0x09b8639,0x1e77f0c,0x08bfeb3,0x07f011f,
|
|
0x09405c7,0x13fbc20,0x12de627,0x0e2af0b,0x194bb1f,0x1a9948b,
|
|
0x08695c6,0x078a22f,0x02f6f04,0x05bc70f,0x03835e4,0x06f437e,
|
|
0x148ac45,0x0fc216c,0x1aba456,0x13c7f4f,0x00a8e43,0x148223b,
|
|
0x0edf0ac,0x15b0e15,0x12dd15d,0x152e959,0x0216279 } },
|
|
/* 31 */
|
|
{ { 0x047f747,0x06d5fa0,0x087b053,0x1b8262b,0x03ca233,0x12e8538,
|
|
0x12f4d03,0x0d2b3cf,0x1bb4138,0x1e86274,0x07ef607,0x11621e0,
|
|
0x1d189d0,0x13b5c11,0x112710a,0x00142a0,0x0a1398b,0x040e112,
|
|
0x1a05e79,0x109c9f1,0x01e9080,0x0a34c72,0x1f62be6,0x0217e5d,
|
|
0x0e37c56,0x0878f18,0x1e9f49e,0x1cd4087,0x1953884,0x1306598,
|
|
0x1f6765b,0x006f33b,0x15f986d,0x1c817f3,0x1c47e3f,0x1c76951,
|
|
0x1588416,0x0a29bc3,0x14d7bea,0x07f304e,0x020683e },
|
|
{ 0x0378878,0x0171368,0x1e1f2d6,0x074f28a,0x1e214c2,0x134459c,
|
|
0x002fe3d,0x0e027a0,0x1405152,0x0a46a7a,0x047d75d,0x02ba802,
|
|
0x027113c,0x145ffc8,0x1d6949a,0x08b9877,0x0109b49,0x0ded358,
|
|
0x10bce81,0x198e9d7,0x1fa183d,0x0221f7e,0x0abbd8a,0x0b8b7e8,
|
|
0x00ee956,0x01d6973,0x1564bc9,0x1e1f421,0x03bf514,0x05990de,
|
|
0x1d1ab96,0x0c0aed4,0x13b0868,0x1840d40,0x0fe135c,0x1217804,
|
|
0x12dcee5,0x081d501,0x11e567f,0x1ea4fad,0x05e416b } },
|
|
/* 32 */
|
|
{ { 0x06cc23c,0x09bb001,0x016090c,0x1d6b652,0x1819aae,0x09770bf,
|
|
0x1cbe317,0x0055244,0x1ee5cc4,0x02473e5,0x1bc1f60,0x0ddcefb,
|
|
0x1edbc7d,0x1b57c10,0x15a4913,0x17712c3,0x0ed996c,0x02fbcb3,
|
|
0x1a85569,0x162fd52,0x0d56f81,0x1801f9f,0x0cb67bd,0x1054b65,
|
|
0x05906e8,0x0c02f37,0x0aba51c,0x0df420e,0x0c76f48,0x1e28b2c,
|
|
0x080d367,0x19606b5,0x1603dc0,0x13240cf,0x1fadd6f,0x1f6f673,
|
|
0x0f04a9e,0x03aaa56,0x1f78f2a,0x1d90f69,0x04ff682 },
|
|
{ 0x0a10ad5,0x0b13fe8,0x1d14c49,0x052d1cd,0x1fd45c7,0x1508b1b,
|
|
0x0f5ae01,0x1c65303,0x1de5033,0x096f0e6,0x1e2622e,0x08bd7e9,
|
|
0x1c3b44b,0x0d73f0e,0x06e625b,0x1b0f194,0x05a0778,0x1a90b37,
|
|
0x1445a11,0x08e57d4,0x144582d,0x157944a,0x1ef74e0,0x0dd8993,
|
|
0x116025d,0x1811176,0x12d954a,0x0c29d63,0x06210f3,0x0fb9d0f,
|
|
0x09d8f17,0x00434e9,0x1160285,0x05ea6f4,0x1003197,0x1348994,
|
|
0x0f15e29,0x058c3f0,0x141f123,0x11c6804,0x051eb81 } },
|
|
/* 33 */
|
|
{ { 0x12100ab,0x0e8bc5c,0x00e47f0,0x012c0b7,0x1f2e3d6,0x0f2ce86,
|
|
0x10956dc,0x008254f,0x114fcbe,0x1c5b33a,0x141abcf,0x126ab3f,
|
|
0x070e8a3,0x0901068,0x0c99408,0x0f7caac,0x0d1528e,0x0334b7e,
|
|
0x11edd95,0x10a2961,0x05b5658,0x062c895,0x033603e,0x04996fe,
|
|
0x1ef04f3,0x0bac5d7,0x1f1b68f,0x16a7dd9,0x11df2f6,0x046c18e,
|
|
0x1b7b7bd,0x0e70256,0x136b965,0x13018f9,0x192bb98,0x17905d5,
|
|
0x1244f09,0x055e996,0x191fcc0,0x0aa63b2,0x08b0af9 },
|
|
{ 0x0603544,0x00c0517,0x167addc,0x0644359,0x0b573ac,0x0038191,
|
|
0x1d99589,0x07a742f,0x1b89abc,0x09f3a56,0x0c896ab,0x1c75af2,
|
|
0x0b8a3d2,0x17812b2,0x1eee813,0x1a56a8a,0x12ffc2d,0x0443ab2,
|
|
0x19c50fa,0x00ba2bc,0x0d70d29,0x0101724,0x1b6212d,0x0c6d4ae,
|
|
0x19219c7,0x06f837c,0x04d78de,0x11b8684,0x064a02a,0x0b9e886,
|
|
0x19a5707,0x1982af4,0x16a4ece,0x051aa66,0x0722389,0x1b75b98,
|
|
0x1839329,0x1278d94,0x02b4200,0x0929b49,0x05363e5 } },
|
|
/* 34 */
|
|
{ { 0x03fc641,0x091dbf1,0x018c7d5,0x1f0ccce,0x1e54e72,0x004e97f,
|
|
0x057d638,0x1c25294,0x18c57f5,0x101ccbf,0x159373c,0x049962d,
|
|
0x1ba2297,0x05d517f,0x1ef93f5,0x11dacd2,0x0460a6e,0x11fa83f,
|
|
0x014214d,0x1c74baf,0x02080af,0x0ecaa04,0x1bbbdb3,0x18846f9,
|
|
0x1d889f2,0x129b80f,0x0970e14,0x12db107,0x0212f14,0x13f6b95,
|
|
0x1378971,0x03fef1f,0x1416783,0x1a0a325,0x001305b,0x0fd32ce,
|
|
0x045b069,0x02e1d0e,0x0c30fe9,0x0307f7a,0x0633340 },
|
|
{ 0x0fbbbce,0x0d06651,0x1d10e72,0x1954196,0x076f6e5,0x1c7671c,
|
|
0x00438d0,0x10539cc,0x013802d,0x1568a47,0x11686c2,0x18c139a,
|
|
0x009c3e5,0x1de7e0f,0x172e165,0x09ba10e,0x190d858,0x1d8cffb,
|
|
0x0070a8a,0x11703db,0x07e3259,0x17815f0,0x0462f7c,0x0ecb9d2,
|
|
0x1c8eeb9,0x0d703a7,0x02c93e5,0x04bd3b1,0x18f09d1,0x166e064,
|
|
0x09ceec4,0x1416e96,0x06aee07,0x03be725,0x0be7020,0x1e8e47a,
|
|
0x1ea8026,0x0a23eb5,0x02dce56,0x0b82c50,0x093a707 } },
|
|
/* 35 */
|
|
{ { 0x15b27f9,0x1f7f138,0x048c9ae,0x0454501,0x0935a5e,0x0c51355,
|
|
0x08ebff5,0x128bbbe,0x07c1386,0x0641f0b,0x08854d5,0x1793125,
|
|
0x1544799,0x0dc684f,0x1b91c42,0x1d4d09c,0x016d588,0x1631d7b,
|
|
0x00eac6d,0x12ce0d1,0x13365e8,0x101e904,0x0f04e4e,0x1847bb4,
|
|
0x1292192,0x121e817,0x0b73dba,0x16e196f,0x1559e1a,0x07543c8,
|
|
0x02c490d,0x0dae1fe,0x00680db,0x15d2282,0x1948a0c,0x1e3421f,
|
|
0x05f0cb8,0x0fce047,0x107f75a,0x1588962,0x01a7422 },
|
|
{ 0x140b675,0x0ee974f,0x1ce70ea,0x07f98e3,0x0a7c660,0x0471a11,
|
|
0x0698465,0x1083127,0x0ed0ab4,0x19db0ac,0x0729ae3,0x1b2fdc6,
|
|
0x03a3aa7,0x1bd46db,0x07a197b,0x0c5c978,0x0092c7c,0x198afc6,
|
|
0x1d71b43,0x00f11f3,0x1ec5a26,0x14a5b79,0x0c60cc4,0x169b093,
|
|
0x1bcd636,0x14db9d6,0x02f1a66,0x0dc2912,0x1175e76,0x086c150,
|
|
0x13efcde,0x1f8a794,0x143605a,0x1b048bf,0x111e1ff,0x0caefed,
|
|
0x000c82b,0x1e3aa93,0x1667209,0x0613a4a,0x00944d6 } },
|
|
/* 36 */
|
|
{ { 0x0ab9620,0x15b1f73,0x00233f7,0x1af0d9b,0x1ff4fa6,0x119059e,
|
|
0x1760915,0x02a28bd,0x0c49439,0x172fc31,0x0cfe1ca,0x10276e7,
|
|
0x099508e,0x1297cbd,0x16017cf,0x136c477,0x028c982,0x07b8dae,
|
|
0x1b833bf,0x098e1d0,0x136eb39,0x1491ded,0x14d3ec6,0x1c4fcb4,
|
|
0x15862db,0x0b4eb27,0x0e0ead8,0x15c47be,0x0828cbb,0x18d893e,
|
|
0x02b75b7,0x07460f5,0x101899f,0x0efb30c,0x1966047,0x0e6d990,
|
|
0x19943b7,0x05bbba3,0x195da8f,0x106dfb0,0x07d89f3 },
|
|
{ 0x1f92b2b,0x1212164,0x0af7e15,0x0b88dc6,0x100c6a7,0x0cd2e2b,
|
|
0x1a2ddfe,0x0d127ce,0x0031495,0x177f42c,0x199c26d,0x1433859,
|
|
0x13bbfe8,0x1737624,0x068ec6f,0x1851ae4,0x0a9c371,0x0937777,
|
|
0x145df87,0x1022bc2,0x05a5d79,0x0758345,0x15efcef,0x1a56965,
|
|
0x1a22046,0x0fe6fc6,0x0d66fa7,0x1be132b,0x040b793,0x0bde3bb,
|
|
0x11725a2,0x0b457a7,0x00cf4c2,0x1f3a267,0x15ba26b,0x162de8b,
|
|
0x1a8509b,0x1f9d659,0x09b9ad4,0x03ec7e5,0x0449af8 } },
|
|
/* 37 */
|
|
{ { 0x16d9377,0x0789950,0x1e7b0bf,0x06fc345,0x1ab377b,0x08cd72c,
|
|
0x084ba1b,0x162e5c3,0x0d013bb,0x1589733,0x1d9aeb4,0x00ab96b,
|
|
0x100972e,0x1ccf55a,0x0778700,0x0bd85a2,0x0fdc65f,0x1e0f98a,
|
|
0x0a7fd64,0x0230831,0x06e6fc3,0x1670292,0x17dcf07,0x04a0adb,
|
|
0x1136316,0x10ce146,0x1dbec97,0x0153b7a,0x1cd2d73,0x0922422,
|
|
0x0b4127b,0x1a6dd0a,0x179b83f,0x04541e3,0x1f1fda3,0x070b46b,
|
|
0x095e803,0x0df8f0e,0x06bd4a6,0x1864112,0x00e8617 },
|
|
{ 0x1c81b5c,0x1030133,0x1cf14dc,0x1bce6f0,0x0fa89dc,0x0a27e81,
|
|
0x0c2c2a0,0x10654e8,0x126208c,0x00362d3,0x0903d4c,0x0cc1b1d,
|
|
0x044e066,0x04b209d,0x14097e6,0x0293f3b,0x0cc46b9,0x15ef9c0,
|
|
0x0849730,0x0acc321,0x1c37801,0x1ba93c9,0x0135a8e,0x0f4c5e4,
|
|
0x013746b,0x0bc5b00,0x0161756,0x139fc4d,0x15fe66a,0x065c41c,
|
|
0x1db72b4,0x08d64c3,0x0b468fc,0x0c90c5d,0x17be767,0x05941de,
|
|
0x1e45240,0x03ea542,0x1da1f14,0x1e264d9,0x06f4404 } },
|
|
/* 38 */
|
|
{ { 0x1ebd3ff,0x0c905a7,0x0eea8f8,0x11fbfa5,0x0a6234d,0x0d4c14e,
|
|
0x0bcab86,0x0416fa3,0x0c6f5bc,0x1ef0b08,0x0e72a48,0x17e7b54,
|
|
0x0be204d,0x16c6385,0x0b7a6e1,0x06e1654,0x0377c9d,0x1139706,
|
|
0x1595443,0x02980dc,0x16b0809,0x142be5d,0x0d8479e,0x04cd4dd,
|
|
0x1c6efd8,0x00e03b7,0x18c2560,0x1f5869d,0x024063d,0x00515cf,
|
|
0x115a7fd,0x0f0f54b,0x1ba31a9,0x1866953,0x1f7ccf1,0x081c9a3,
|
|
0x0895f07,0x1f18993,0x1c78a40,0x1f0ff6c,0x0905771 },
|
|
{ 0x0062bee,0x0dd06d2,0x07e5466,0x1929afb,0x18e7238,0x0491600,
|
|
0x0a6f078,0x0bfea7e,0x1b12d85,0x14d9540,0x0328a77,0x1ddadad,
|
|
0x1f649f3,0x028604b,0x0b7f0d3,0x13140c9,0x0b99db3,0x040cb25,
|
|
0x0961c89,0x0b388ef,0x103a00d,0x0b3a62c,0x027fa8e,0x0087ba0,
|
|
0x1d8ee15,0x0103557,0x197c7b3,0x0ae434d,0x19b7b4c,0x124186d,
|
|
0x0aadb5a,0x0cd91aa,0x0ffc617,0x0151383,0x075ab32,0x107bc48,
|
|
0x07f2f7a,0x02f8291,0x17b3018,0x076c809,0x06a2295 } },
|
|
/* 39 */
|
|
{ { 0x0fce389,0x096c7ba,0x1592491,0x0055f4a,0x059634c,0x16bc128,
|
|
0x132efc3,0x01b26ef,0x137718e,0x0fa022d,0x1a69362,0x1cfb3f4,
|
|
0x1a11074,0x194ad85,0x1c2ec1d,0x1dbccba,0x0adf107,0x1d916aa,
|
|
0x068a71e,0x1347b14,0x03ab5c3,0x016bcaf,0x0dc8db0,0x0b132a2,
|
|
0x02d002b,0x1717b94,0x195e42f,0x1c44cb7,0x065ea25,0x1508d47,
|
|
0x0f64783,0x0c0039d,0x071a708,0x02a0107,0x1d68b07,0x022d201,
|
|
0x157f698,0x196ae01,0x0d09f0e,0x140c33c,0x0528c9e },
|
|
{ 0x126c577,0x0435a2f,0x15147b7,0x1128717,0x1807470,0x12c153f,
|
|
0x0404de4,0x13e5bfc,0x0de1e56,0x0475650,0x168d5b8,0x1df534a,
|
|
0x165f952,0x124bb10,0x1602d4f,0x0e3e549,0x055cd5d,0x0695b2c,
|
|
0x1b3a8fc,0x0e097ec,0x03ca246,0x0fa4919,0x064fd90,0x1b6264a,
|
|
0x1855c9a,0x1295340,0x18b4675,0x0daa459,0x02ed7b8,0x0f882dc,
|
|
0x0a54d82,0x11c2a1a,0x10f0094,0x1f4489d,0x0fec2c4,0x12475b1,
|
|
0x1794b44,0x18aab67,0x13d5f2e,0x126e717,0x0200f90 } },
|
|
/* 40 */
|
|
{ { 0x188387f,0x117e2c1,0x0f17e6c,0x0051d10,0x0f26f17,0x1bcb9e6,
|
|
0x0ae4346,0x0e288f9,0x0f6ec91,0x0aea751,0x136f023,0x0931861,
|
|
0x0b2e16f,0x04311e1,0x04a4431,0x18a8bb9,0x1b030db,0x0758a48,
|
|
0x137886c,0x1bd65c2,0x10f4631,0x1317f41,0x0128841,0x1383e7e,
|
|
0x0979c37,0x1cad263,0x03ec1a9,0x14e656d,0x19dfa98,0x193d0b0,
|
|
0x06ce910,0x11b7c59,0x1a307d3,0x04ff548,0x03480e6,0x1f27379,
|
|
0x0f4a331,0x155d790,0x15770f6,0x131ba1e,0x05c307e },
|
|
{ 0x1b233da,0x070621a,0x0616ef1,0x0a45edf,0x03d2908,0x1812347,
|
|
0x0b486a2,0x1cf33ba,0x1a96916,0x1c7a074,0x0f33b65,0x10d8c29,
|
|
0x0c0327d,0x19483b1,0x1a5540a,0x1e5db2b,0x197a879,0x187fe90,
|
|
0x0382f4c,0x0ca26ea,0x04c4c43,0x050413e,0x09b0c52,0x19f8164,
|
|
0x012a83f,0x0c4e3cc,0x18c64a1,0x07b1a2f,0x10f42dc,0x167f441,
|
|
0x0fe2d5c,0x0960ff0,0x0d9ff92,0x08a47be,0x0540294,0x1866395,
|
|
0x0c59f9a,0x029cb42,0x11e1743,0x1f58286,0x01df16d } },
|
|
/* 41 */
|
|
{ { 0x0bcacc3,0x1da5634,0x033f31e,0x1e861eb,0x06ded34,0x10c2ad0,
|
|
0x07d3f51,0x1798b3f,0x045c9f0,0x0a48cca,0x17224bd,0x1d8c86e,
|
|
0x1adc5f7,0x1e42cc1,0x01c23c4,0x1a10e37,0x0c482fc,0x1d9952e,
|
|
0x15ad303,0x19b86a5,0x1b2defd,0x0245637,0x12ec93c,0x120c8e2,
|
|
0x0d4f533,0x1622cc1,0x1ee0e8e,0x0c5d6a5,0x17a2231,0x0f94119,
|
|
0x14dc4c3,0x19787b7,0x0e7b802,0x1d6076e,0x0564919,0x1d1672b,
|
|
0x1b56717,0x09e9740,0x0985c87,0x0a08ca2,0x0729a7f },
|
|
{ 0x020f90a,0x168d542,0x01561d3,0x1c1fc99,0x0368e19,0x1f3a57b,
|
|
0x12aaac2,0x1536c5a,0x08ca60c,0x17e6240,0x16a19dd,0x0b4aec8,
|
|
0x0cf310b,0x0ed8d92,0x06eb26f,0x0b68826,0x11d2dea,0x177bbeb,
|
|
0x0bf3193,0x0da420e,0x17f0470,0x08b39eb,0x0a6e49a,0x13c0cc6,
|
|
0x00bf3e8,0x0a01170,0x0dd01df,0x0e5a19a,0x1232e24,0x0206c14,
|
|
0x0ccf884,0x071b90a,0x1916dfb,0x07b3397,0x166c52e,0x1a91776,
|
|
0x144be19,0x0f4fa56,0x0757067,0x092465b,0x07f6d36 } },
|
|
/* 42 */
|
|
{ { 0x0794819,0x0326f37,0x1684ef4,0x1df05d7,0x1a6b694,0x0f14022,
|
|
0x1ff82e4,0x1a43e02,0x107a43c,0x08698f9,0x10cfa46,0x044cc60,
|
|
0x146c26f,0x055fee5,0x1222a9c,0x0238174,0x085a464,0x020c6c8,
|
|
0x1fed620,0x069fcd7,0x18491b9,0x1bf1007,0x1d74788,0x0a827b6,
|
|
0x0d63fa5,0x1bbef82,0x1788ecf,0x042ddae,0x11bd30e,0x136587c,
|
|
0x0268161,0x0ee538a,0x0c395d9,0x1596bc2,0x062114a,0x0dd92fc,
|
|
0x0093d68,0x1be0fc8,0x021b232,0x12ac51e,0x02d0323 },
|
|
{ 0x044b4c5,0x04a03a5,0x1262a07,0x1398e05,0x1984687,0x186e4bd,
|
|
0x08a1f3a,0x04396a0,0x06e3aa3,0x0180893,0x095b08c,0x0ec7c98,
|
|
0x05c0ac8,0x12ada42,0x00d3483,0x1e6b6ca,0x040f240,0x0554b50,
|
|
0x13dfbb7,0x1a4da6f,0x0656046,0x109dc08,0x18a96a3,0x1ae1856,
|
|
0x04b9783,0x147c302,0x0167936,0x1f75ff1,0x17f5d12,0x080d2a2,
|
|
0x15e4a76,0x16a636e,0x09e1eb2,0x14b9ce9,0x0f72793,0x12429b5,
|
|
0x0eaa9bd,0x0b927e2,0x0ee6d6f,0x1663df3,0x0734c12 } },
|
|
/* 43 */
|
|
{ { 0x0f9b086,0x11e1749,0x151263f,0x1d67fa8,0x0641b93,0x01632e2,
|
|
0x0822d70,0x0848f9c,0x1c4f032,0x1296e50,0x14a7da2,0x0fb2cf3,
|
|
0x14b5ec1,0x0a037af,0x14bfb42,0x1502223,0x1dc0d9b,0x19307b1,
|
|
0x151ca8f,0x160ade2,0x10e6de2,0x0f80394,0x06c5c36,0x16b91f2,
|
|
0x03e8db6,0x1f75171,0x073cd30,0x08b4507,0x173ee23,0x0a308dc,
|
|
0x1166f71,0x17649a3,0x1bda6c2,0x0a0d0b2,0x0e8cf18,0x032faa5,
|
|
0x1d2eb20,0x1d8b094,0x1927d1e,0x10e43f7,0x07c558a },
|
|
{ 0x1350fec,0x02d291f,0x1302e52,0x0ad471a,0x016678c,0x0d53268,
|
|
0x11a8835,0x1c91de6,0x0d96da2,0x02ed501,0x11ecf2e,0x09d49ec,
|
|
0x0c845ec,0x06af4a3,0x1469b28,0x1e95781,0x1c14fa9,0x1a0ec68,
|
|
0x122c4c0,0x0e598b3,0x1bfb439,0x06a1a7f,0x19f87d2,0x13a4630,
|
|
0x0e93a81,0x11f9a86,0x01b77bc,0x13ea612,0x0cf12c4,0x167c900,
|
|
0x1f0f0b9,0x0c80865,0x0691cc1,0x0b5a921,0x12d1c92,0x1d7ffee,
|
|
0x020a97b,0x093e4f8,0x10d2111,0x194f678,0x034cd7d } },
|
|
/* 44 */
|
|
{ { 0x1e7fe87,0x0bb0d2c,0x15cbc0c,0x14008f9,0x11eae31,0x1187b15,
|
|
0x0b9a3eb,0x0864f20,0x1b71db1,0x1337a46,0x00e3d29,0x0cf01c0,
|
|
0x0d75ee6,0x015eebb,0x116b19c,0x19ab876,0x028a0d6,0x08697dc,
|
|
0x16316c4,0x1cfe3b3,0x1e9627c,0x120905a,0x0507f83,0x04cf86e,
|
|
0x1b984b9,0x166cad0,0x07580c4,0x040dcb1,0x1493565,0x1a176d2,
|
|
0x0b0619c,0x00e18e9,0x14520b9,0x1d8599b,0x0ed6555,0x084e079,
|
|
0x06ed8c1,0x10face5,0x0e21fd8,0x18557ef,0x07ceb1c },
|
|
{ 0x17fd65b,0x1d2dded,0x15f0191,0x006d928,0x18d45cc,0x0938c56,
|
|
0x0676e78,0x1638db5,0x0e93a7f,0x08eddfa,0x159a87b,0x12b97a2,
|
|
0x194512c,0x0de0648,0x186e803,0x0a4d290,0x0989e7f,0x11e3661,
|
|
0x0506aab,0x12c2a01,0x18e3671,0x07e4629,0x0ff3d74,0x0b4aa3f,
|
|
0x09929a2,0x19356b7,0x145f283,0x00e2130,0x09ef7e9,0x1c757d4,
|
|
0x125d0ed,0x0e3568a,0x1d5ea31,0x0e1b69c,0x0fcf9b4,0x1ae885e,
|
|
0x059d568,0x1341f00,0x1b57096,0x13244f9,0x01f629a } },
|
|
/* 45 */
|
|
{ { 0x05a1c3e,0x0eed672,0x117e249,0x0a83eea,0x12d2936,0x13fc143,
|
|
0x0bf2cdf,0x1a48ac4,0x13e4c79,0x011a289,0x19175a2,0x1f09384,
|
|
0x195dffa,0x0ca4015,0x1e3d376,0x13f4060,0x1f09d33,0x02b3493,
|
|
0x1f64773,0x00143d3,0x0bd79a5,0x0005585,0x1380206,0x129cbbf,
|
|
0x135a381,0x0446cb8,0x1e62b7c,0x1d0ec60,0x05a2a79,0x00dc4d2,
|
|
0x064eebc,0x0f11687,0x1ed6154,0x14cbeb7,0x1c8b9de,0x1b301ca,
|
|
0x0a378ee,0x0487fd1,0x0168aab,0x14517b0,0x04a75fd },
|
|
{ 0x1e74cbc,0x147ddaa,0x1c97426,0x1df5631,0x137738c,0x12761d3,
|
|
0x0eb5a5d,0x0621f84,0x1e7e0ad,0x0d3e9ad,0x07326f1,0x0d1dc90,
|
|
0x14e75e0,0x1ea5761,0x10baa64,0x0c789e1,0x1e80d4a,0x0789927,
|
|
0x06c164b,0x16f82d3,0x146b5db,0x06d3f07,0x110b59d,0x001f5d4,
|
|
0x166c7a3,0x041ad2e,0x04ccceb,0x107b904,0x008496e,0x0097462,
|
|
0x105c3be,0x133debf,0x0e1dcb6,0x074314b,0x1c6c5cd,0x10dc56e,
|
|
0x183507d,0x114e6e2,0x05e6811,0x15c47b0,0x05819f9 } },
|
|
/* 46 */
|
|
{ { 0x0a78811,0x14890b5,0x1f0f665,0x084207c,0x164ee8f,0x1cf34c7,
|
|
0x041c08a,0x1bdbbe0,0x04f582c,0x1000fcf,0x1eb06b9,0x115e5d9,
|
|
0x0924a60,0x031c980,0x1d31e10,0x05222dd,0x0e6ebf7,0x0293175,
|
|
0x113b968,0x1a15eb1,0x1bc7ddb,0x08766c3,0x01d6bfe,0x049e229,
|
|
0x1b34c6f,0x0b917ee,0x07a197c,0x1020850,0x0c1b9a4,0x1213443,
|
|
0x07e55a4,0x13de846,0x15f3208,0x1f41737,0x0b3f429,0x115eb0f,
|
|
0x1ac395c,0x0b8c8bc,0x09d4359,0x07826c9,0x0745960 },
|
|
{ 0x01ae519,0x03adffa,0x0944709,0x0295f1e,0x14401fb,0x1d961e9,
|
|
0x1f34abb,0x010e1bb,0x151cdaf,0x1969c2d,0x02ec666,0x04ad041,
|
|
0x168531c,0x0619f9f,0x12277d9,0x02ed22d,0x0992457,0x1611e7d,
|
|
0x1b4042e,0x136a3d0,0x0313233,0x069131c,0x0236c3a,0x1fdbd6e,
|
|
0x1e17900,0x178fbb4,0x0e8da1f,0x1fb2db9,0x0764753,0x1591c8a,
|
|
0x1773411,0x0188b91,0x1ff2064,0x01ebc79,0x1ef6e0d,0x01dfa2c,
|
|
0x0b77ee9,0x1e65b6a,0x1ed1524,0x027679e,0x0330255 } },
|
|
/* 47 */
|
|
{ { 0x1eaaca1,0x002349a,0x0408dbc,0x0b12232,0x0c384b7,0x094aa60,
|
|
0x159979b,0x1af966e,0x1b1e9d6,0x1c8ccdc,0x109d5f2,0x0693853,
|
|
0x1075852,0x1c739c6,0x12f46ea,0x1484f13,0x0905923,0x0cdc6df,
|
|
0x03f8622,0x0ef27c3,0x0083a23,0x0bd3a17,0x0909c5d,0x1d7ac27,
|
|
0x179d24e,0x1bbc624,0x1353cb3,0x0064a0a,0x0705de4,0x1048cac,
|
|
0x0ea8ee2,0x067b333,0x1191bd9,0x1f70f0d,0x0e90ec3,0x0975fdf,
|
|
0x1facdf1,0x1d68c21,0x15872ce,0x160870e,0x09328ad },
|
|
{ 0x106b872,0x027407c,0x1996afa,0x00f04c4,0x105523a,0x0c667bb,
|
|
0x1a9f8ce,0x047b138,0x1f55b53,0x1d5aa8e,0x137aa0b,0x1d940aa,
|
|
0x0da0578,0x1baac4e,0x09948f4,0x1aea1de,0x042864a,0x16c7eb1,
|
|
0x1e3f87f,0x04ff8a2,0x142293f,0x184efc3,0x1ecf9bc,0x0a1a0a8,
|
|
0x0e49e37,0x0509431,0x097700e,0x1b218d6,0x1b682b7,0x1711426,
|
|
0x02b0686,0x1310326,0x1f3dab7,0x1f05223,0x154aebc,0x0a61cd7,
|
|
0x162d25c,0x00012df,0x1579c1a,0x19f5ba1,0x00aa1f3 } },
|
|
/* 48 */
|
|
{ { 0x0a10453,0x110c811,0x042ea60,0x1854074,0x1d1eb91,0x12379de,
|
|
0x1765659,0x18d5f76,0x0f38b6f,0x0c6f1a2,0x1f28769,0x07cb719,
|
|
0x04ce47c,0x07b86d0,0x16385b4,0x05dadf9,0x09bda26,0x156221a,
|
|
0x15b8be3,0x01b0f78,0x0e58932,0x040c89c,0x0738fa8,0x1646d81,
|
|
0x02dffa2,0x186d2c3,0x1239fbe,0x161f34b,0x0c78eb6,0x01958b5,
|
|
0x0bd2d4d,0x0e136a3,0x1f43105,0x0cb1437,0x1be23d4,0x1a11c46,
|
|
0x0ed403a,0x09f8bb7,0x151787e,0x1c12c6c,0x0559337 },
|
|
{ 0x0fd807a,0x0fb9c6c,0x0888c37,0x1b56262,0x14e0ec9,0x0d7de1f,
|
|
0x1d36d89,0x12a2945,0x09f12f8,0x0db8302,0x0113f75,0x1847586,
|
|
0x0fb46f3,0x1aa00a4,0x08cb47f,0x1caa836,0x0f539b4,0x0b0da2c,
|
|
0x175c2dd,0x0964941,0x01d9f69,0x0c944ac,0x03f190a,0x0bfc45a,
|
|
0x149beee,0x1b1e02e,0x1da862f,0x15e688f,0x1929d67,0x0ee13f8,
|
|
0x033a5a8,0x182aa3d,0x0fe6028,0x0a7d135,0x0bccad7,0x084fb59,
|
|
0x145c2cb,0x0b18de2,0x0534d28,0x1f36192,0x0930070 } },
|
|
/* 49 */
|
|
{ { 0x1a9bc05,0x1962f34,0x0dcf4bc,0x0cb1389,0x0a5c19c,0x132fce0,
|
|
0x0797a51,0x07212b9,0x1bcfb4c,0x1587949,0x0df0c62,0x10ee3bb,
|
|
0x08b9070,0x1359c02,0x13a5961,0x1b37b12,0x0cf606b,0x0f8cd48,
|
|
0x1bf4b5a,0x1ab1bf6,0x0a69cc1,0x07230ec,0x021b731,0x19c9063,
|
|
0x1c277f9,0x141622a,0x19d97e2,0x0934b32,0x1adc8d7,0x134661d,
|
|
0x0acbff1,0x122259b,0x0018396,0x1e3e59c,0x170ec90,0x09530f2,
|
|
0x010a222,0x1af9880,0x178521d,0x082b0f6,0x0043a21 },
|
|
{ 0x0873752,0x14ede1d,0x1fb9eef,0x085e885,0x0e1493f,0x0610c0f,
|
|
0x08b2306,0x1cf3039,0x0e29769,0x0671848,0x1a317c0,0x1591bce,
|
|
0x1eb4626,0x1a6bb3b,0x1a73918,0x129cc67,0x0ade0fa,0x1fc4e16,
|
|
0x07d6d6f,0x0b98228,0x012c04f,0x1b11146,0x09597dc,0x00b99ca,
|
|
0x1706a0c,0x027f8df,0x1ef921f,0x1a0ffff,0x19f1a45,0x1e04d24,
|
|
0x000fb10,0x131b290,0x14e79bb,0x1897c27,0x08581cf,0x1b1466b,
|
|
0x0f970d6,0x1af57b8,0x02ba12e,0x0f7e49a,0x018d074 } },
|
|
/* 50 */
|
|
{ { 0x0601faf,0x1e3be42,0x1dc9634,0x055e383,0x09465be,0x0b6c036,
|
|
0x19e6344,0x079fec4,0x0d5b0d9,0x0cb6063,0x19c8e8e,0x1aeabd8,
|
|
0x092fa1a,0x01dd29a,0x1aa0510,0x09b152c,0x0222ac3,0x0ee264a,
|
|
0x159d619,0x08e3bdd,0x128fddf,0x0bca9ea,0x162b296,0x1d7ecfb,
|
|
0x063b524,0x069d972,0x05f896d,0x0b0490e,0x159daa2,0x16dd218,
|
|
0x1008f16,0x1066aea,0x058f9c6,0x058d32a,0x169fe4e,0x039ed0b,
|
|
0x0efed23,0x0d27ed6,0x1796660,0x1da1176,0x0711093 },
|
|
{ 0x01f161a,0x11fe320,0x1a1c4aa,0x012e98b,0x1735856,0x1aefc17,
|
|
0x14bec5e,0x1329544,0x1a48e62,0x05c1583,0x1611f6c,0x02ae53b,
|
|
0x0600234,0x0294e2d,0x1953401,0x1ea71e3,0x19e6d98,0x1e60e29,
|
|
0x034eaf2,0x0c56a65,0x10cd361,0x1c15427,0x1d68de4,0x1dce908,
|
|
0x1a81b4d,0x18dfb8b,0x0d308ef,0x0d9e6bf,0x1e8b3e1,0x014fbc3,
|
|
0x0c1ff47,0x0b36f35,0x1da7e68,0x16305db,0x028217d,0x0a0e420,
|
|
0x07ed48b,0x0200acf,0x05f50c6,0x1b49b39,0x017898b } },
|
|
/* 51 */
|
|
{ { 0x01b8cf8,0x041ec57,0x015b361,0x05d3451,0x123d4b4,0x0525e11,
|
|
0x1613c81,0x1f4ec66,0x0ca7a69,0x1059114,0x1eeac93,0x1517eea,
|
|
0x0a8afbd,0x1662fce,0x0c90221,0x12b870b,0x013d41a,0x1a3fda4,
|
|
0x0aaaf9a,0x178a798,0x199d3f1,0x1f8d68a,0x1c8b368,0x03d5363,
|
|
0x0c081c3,0x1608d97,0x0c05852,0x091e609,0x0fa7ab0,0x0774e35,
|
|
0x0f738c7,0x08281b8,0x1af7633,0x055dd2a,0x0cdf73a,0x1d096f5,
|
|
0x07cf3ef,0x0f3b246,0x1aac943,0x19e2a6a,0x073a88d },
|
|
{ 0x0e83b39,0x1414403,0x0df4fe1,0x073e880,0x077a441,0x0de420a,
|
|
0x02c3c5f,0x093f20b,0x154d175,0x0db27a7,0x01fff8b,0x14d5e46,
|
|
0x01a23ce,0x0789313,0x0fbf555,0x0fe4c72,0x18a10f3,0x097a732,
|
|
0x13b878d,0x06f9c7e,0x1e8ba44,0x13d49e6,0x193bd0a,0x1355202,
|
|
0x1c9f493,0x06a0ef5,0x08f5ed7,0x08447ad,0x0a3acc4,0x1508fc4,
|
|
0x0b5e269,0x058c114,0x0fb9df8,0x0b6032b,0x038eefd,0x01cf3b7,
|
|
0x068fa30,0x02b5793,0x1a879cf,0x02f5c72,0x052f32b } },
|
|
/* 52 */
|
|
{ { 0x114f71a,0x09260f3,0x14655bd,0x0535bb0,0x01be126,0x056df1e,
|
|
0x0276197,0x0935b23,0x05a0fb6,0x045fae4,0x064b676,0x152443a,
|
|
0x0f9efa6,0x17b925b,0x1fa0e25,0x02339c7,0x024b250,0x0761fd7,
|
|
0x0b834f0,0x15f3ec5,0x024d4b6,0x05eb0cb,0x03f3ae8,0x1b6dc75,
|
|
0x1092b2f,0x094bee1,0x18c98f3,0x123b46e,0x1c43bdc,0x1b0f7ca,
|
|
0x164c301,0x19bd689,0x1136400,0x0698ec4,0x1a110f0,0x1ffafb9,
|
|
0x1871899,0x1f61d8c,0x16305e3,0x051dfbe,0x079e14d },
|
|
{ 0x1b40c55,0x1111acd,0x090b8e0,0x1a1da0f,0x0a27202,0x1c60fa0,
|
|
0x106a520,0x11c91cd,0x1d864a7,0x1af9253,0x115724a,0x081418d,
|
|
0x087e7f1,0x07096a8,0x0b0412b,0x03c21cc,0x07ec11b,0x0cd850d,
|
|
0x1eecf75,0x144ebf5,0x0b30fd8,0x1f4d1db,0x17fcd53,0x0c05403,
|
|
0x05d9e46,0x0fbad08,0x164eed9,0x1a6e369,0x02fdeb3,0x1f8587c,
|
|
0x1176972,0x1bc8d0a,0x001229b,0x0a8bf23,0x02e71cf,0x04a0bc2,
|
|
0x072ff49,0x07d2a0b,0x1b389df,0x11532ac,0x00d8ec2 } },
|
|
/* 53 */
|
|
{ { 0x1eee995,0x07b9f65,0x0030053,0x19a923d,0x12eb88b,0x15d2ea5,
|
|
0x1b2b766,0x09ac2b4,0x19304c8,0x1bea319,0x00f268b,0x03a5156,
|
|
0x14ba050,0x08dd5dc,0x1dc8f7a,0x0aee591,0x1775040,0x06442fc,
|
|
0x1ff2c25,0x03a5678,0x071ab5e,0x0aefcb6,0x187b9e6,0x0c8933c,
|
|
0x0daab34,0x0995c64,0x157d81e,0x1684bbb,0x043587d,0x0e50d89,
|
|
0x101c094,0x13f8e86,0x0d7d3be,0x1564493,0x0c43240,0x1f182f2,
|
|
0x0559a74,0x09160aa,0x12bf1c9,0x04f86e6,0x086001e },
|
|
{ 0x1693947,0x005d2f3,0x18ac4ec,0x1c02580,0x0478641,0x0a48543,
|
|
0x0e383a1,0x0bdc348,0x1d9574d,0x0b9eddf,0x0ee9854,0x171937a,
|
|
0x159532e,0x0f9f503,0x106f2e1,0x125723e,0x0478cbb,0x0560e61,
|
|
0x1be406d,0x08c91c3,0x12ee0f3,0x0f6959d,0x1764a74,0x1aeb7f9,
|
|
0x11eabc3,0x0692387,0x1c4e73d,0x19b78de,0x0249535,0x02a6f82,
|
|
0x00f3619,0x08ff967,0x0079812,0x1c9860f,0x06d05f7,0x0173e41,
|
|
0x114ebc0,0x12fe188,0x11b0508,0x19668f2,0x0020591 } },
|
|
/* 54 */
|
|
{ { 0x15e0af4,0x01b9093,0x092f8c0,0x1fcf149,0x121141e,0x1aba42b,
|
|
0x1f3db45,0x13cccd9,0x1168e65,0x1d0eb9b,0x010bb97,0x1ca81c5,
|
|
0x16263e3,0x0a45eaf,0x1b30f52,0x020955b,0x03d246b,0x000cef0,
|
|
0x0d0f606,0x13d207e,0x0d31f8a,0x052d860,0x12d5ee9,0x1c4ecbf,
|
|
0x0c50651,0x1b3c123,0x1d9466f,0x018aea3,0x119a018,0x0100790,
|
|
0x1d17c17,0x0f043a9,0x06487b8,0x01d033f,0x12a8987,0x044c5f2,
|
|
0x1214605,0x07f244b,0x017bd5b,0x0bf43be,0x0511998 },
|
|
{ 0x18586c0,0x0a4bed8,0x0989606,0x0d8ddd5,0x004415d,0x06d1458,
|
|
0x11ada5f,0x128f8d4,0x07c1945,0x10a4d94,0x0e941a6,0x13f49da,
|
|
0x14b5636,0x01e4a65,0x04aa999,0x1ddc4e1,0x13aa9e9,0x0aade73,
|
|
0x1e24d42,0x1650e0e,0x132634b,0x180375a,0x02be57e,0x071e90b,
|
|
0x1032396,0x1fc43e6,0x016e9d6,0x126ec4d,0x02d5812,0x179ecea,
|
|
0x137ccb5,0x0cb8dac,0x0cad574,0x0f6a0d2,0x03eecb3,0x0f30bea,
|
|
0x1006a06,0x1a67074,0x1fe6b3c,0x0cab14a,0x059eaf2 } },
|
|
/* 55 */
|
|
{ { 0x0c3876f,0x03f7db7,0x1921ed0,0x07e1e90,0x180c612,0x04981cb,
|
|
0x15bfefe,0x1605576,0x045a91a,0x0c97550,0x046e0a5,0x09aef10,
|
|
0x09ce5b8,0x0fcf9fe,0x09c68d0,0x1c2770d,0x186f0e7,0x060bfee,
|
|
0x1568220,0x1b052ec,0x066688e,0x1a40eaf,0x1d75b71,0x02e2f2e,
|
|
0x09df61d,0x10ff7fe,0x178fde7,0x0d5a991,0x06192e3,0x18be902,
|
|
0x18b6c54,0x04e9fb4,0x0c9fa7a,0x0cc8a3c,0x093e0b7,0x1809d92,
|
|
0x1a64971,0x0e8f1c1,0x0efec16,0x1d44c41,0x03b4450 },
|
|
{ 0x176dcdb,0x1d4aae3,0x091cf6d,0x1903917,0x15c4a57,0x0bb07d9,
|
|
0x1400d41,0x0a75c50,0x1b3aec3,0x1f40348,0x05ef978,0x0b7c8e2,
|
|
0x0138033,0x02b667b,0x111f8e8,0x0f22dc3,0x1eb3397,0x0929e7e,
|
|
0x172dfb8,0x19bf75e,0x17043de,0x07be7a5,0x1cf25e5,0x1f028c5,
|
|
0x1680c9f,0x14f9200,0x06f8f6a,0x1c881c2,0x191d8a4,0x01bbb4f,
|
|
0x1771741,0x196bd38,0x106c7a8,0x1e926a0,0x0684ced,0x0432321,
|
|
0x1764b4a,0x09e41c1,0x0d853a2,0x0198853,0x04a7fe3 } },
|
|
/* 56 */
|
|
{ { 0x055c7c5,0x19d3812,0x1d539e3,0x10e02ae,0x1b7636e,0x1193162,
|
|
0x11491d8,0x18fe658,0x01bc780,0x04c588f,0x1b61dcb,0x1d5922b,
|
|
0x14d48ea,0x0cc932f,0x0134f00,0x0401f76,0x19bcfa5,0x035a958,
|
|
0x0fa8ffa,0x1413032,0x0059c46,0x1edd3ac,0x160b1cc,0x12d5599,
|
|
0x0bbd618,0x0a8e992,0x133a3b3,0x181345f,0x1c44b3a,0x0c7e817,
|
|
0x12d4a64,0x15542f0,0x0c45e4a,0x1042e78,0x0d03f88,0x026ac4c,
|
|
0x050c7d6,0x05db3b6,0x1ac8d4f,0x146ca24,0x083fa1e },
|
|
{ 0x0ccc646,0x0436d08,0x07a582b,0x1ef608a,0x0ce0637,0x0443081,
|
|
0x1d8c228,0x1057779,0x1203499,0x1e0c80c,0x0f36808,0x0739f81,
|
|
0x1d707fc,0x0dea7eb,0x1347c54,0x07776fe,0x0744471,0x06b5327,
|
|
0x16b2798,0x1b8ced8,0x116957b,0x019bdb0,0x115b14c,0x1e8143a,
|
|
0x11396dc,0x163e9a2,0x15265f4,0x07dbd84,0x04a739f,0x14d2616,
|
|
0x1894d2b,0x0d4d5a5,0x001397e,0x0afc08a,0x15348fa,0x1e40ed3,
|
|
0x1e98fab,0x1003e36,0x147833b,0x0f32638,0x0614097 } },
|
|
/* 57 */
|
|
{ { 0x1156623,0x1996d8a,0x1f08f76,0x1956f4c,0x08137fb,0x0cf1e13,
|
|
0x07d41bc,0x0c24c02,0x089924c,0x010c581,0x013070d,0x161f8d0,
|
|
0x07492a0,0x17d5735,0x16f9c1a,0x17cc3ac,0x03e0d01,0x09d89e9,
|
|
0x01fd31a,0x08b68ff,0x1aa3445,0x11026e0,0x15088db,0x0a2c3d9,
|
|
0x1261d3c,0x003b09a,0x0ef622f,0x1d68d4c,0x19d7201,0x0c1b0ac,
|
|
0x1cde31b,0x0d375e1,0x0955fe1,0x194107b,0x0f585c1,0x148cfdd,
|
|
0x1e3a340,0x0dc5151,0x17e20bc,0x0ec5a16,0x0636dac },
|
|
{ 0x0c80af3,0x006dcda,0x0aae50a,0x029c712,0x1a189cd,0x03beee4,
|
|
0x00b8345,0x09e4dce,0x068f9f1,0x08d771c,0x0a82cba,0x0c75017,
|
|
0x092864f,0x05b8a51,0x1607dce,0x0f96d59,0x070c5fe,0x09870dc,
|
|
0x0420dff,0x1d43876,0x089f883,0x09b5902,0x0b689e5,0x145b4be,
|
|
0x12a6858,0x10a1d75,0x080ea3e,0x046617e,0x10b1c4e,0x045aee3,
|
|
0x1d2d712,0x0532cf1,0x078c4d9,0x1b3ae05,0x0260977,0x104677a,
|
|
0x1b67d36,0x1ae03b3,0x1bcfcde,0x1fc9a17,0x02f6dbd } },
|
|
/* 58 */
|
|
{ { 0x04da7c7,0x0397e97,0x04c8be1,0x035ccef,0x108cfc9,0x0134713,
|
|
0x1c228f7,0x0486c95,0x0799a24,0x1886ff0,0x162ffc3,0x1ab0e3a,
|
|
0x06ef912,0x0c44b17,0x1cd77f2,0x1d414d7,0x1a95f47,0x0945cb7,
|
|
0x0b4c230,0x14f3d55,0x1bba734,0x1bcfa1b,0x055cc0c,0x1ea9eeb,
|
|
0x0bd8e6c,0x1760016,0x1f9d8cb,0x0ec0db9,0x1931044,0x0f65a98,
|
|
0x075012d,0x0159ee5,0x0e0897c,0x0f8ef05,0x0e18ef7,0x1112c51,
|
|
0x187d744,0x168aa77,0x1753bb3,0x12e8b1a,0x05cb6e1 },
|
|
{ 0x08c75ed,0x178cb80,0x0be2633,0x1deddd5,0x1cf49d3,0x1af4b6b,
|
|
0x0780861,0x1143adf,0x0dd9b0d,0x076167f,0x1db6abf,0x19fd72a,
|
|
0x1838a61,0x1b53edd,0x000fce4,0x029e820,0x06823b8,0x1d9be1c,
|
|
0x0038c54,0x0cdb977,0x07a89fb,0x1d02cc2,0x079f8ba,0x14e4ee1,
|
|
0x063fd35,0x1685276,0x07f2783,0x023e7b2,0x15baa43,0x004a6a8,
|
|
0x18cf077,0x14119a9,0x1a06ebc,0x0f7553a,0x08e0bb5,0x1f56c2e,
|
|
0x01f52c1,0x015dd87,0x15b94ba,0x060a2eb,0x02149d6 } },
|
|
/* 59 */
|
|
{ { 0x19311f6,0x14737af,0x1e17b86,0x1f75783,0x097e3c9,0x0a104d6,
|
|
0x114bad2,0x1c29f4f,0x019774f,0x0617a8e,0x16113c1,0x02450aa,
|
|
0x135cefd,0x1ac39d5,0x0e18a8e,0x033f96a,0x1d6cbed,0x13b477e,
|
|
0x19611a6,0x0248f3d,0x009ccdc,0x189ec06,0x0448df8,0x0898518,
|
|
0x0a290c0,0x143eeba,0x0af51f8,0x1dcca2f,0x0ffeef9,0x0914568,
|
|
0x07f0908,0x1031a50,0x073088f,0x006f0a1,0x12f10fb,0x07d78e8,
|
|
0x1415bd7,0x137667d,0x109b16c,0x0a1960f,0x014e2f3 },
|
|
{ 0x016946b,0x0950821,0x04b5523,0x0ef497b,0x0e801f0,0x14a8b03,
|
|
0x1428d0d,0x192b32d,0x163a197,0x18dae17,0x1ddf243,0x189e0c3,
|
|
0x0279da3,0x09ffbd9,0x07358d2,0x0247e38,0x050a234,0x02f30db,
|
|
0x0a100cf,0x16698be,0x0214826,0x146179a,0x1c62e43,0x100dd8a,
|
|
0x15620ae,0x0da52f9,0x178c92a,0x05f5c68,0x13cb51a,0x1caf45a,
|
|
0x1e2302e,0x1f32cae,0x14f6ac2,0x0f79964,0x01f5ae7,0x0e0fd8c,
|
|
0x10ed8f2,0x1f8edd6,0x0793d8e,0x005b96c,0x058537e } },
|
|
/* 60 */
|
|
{ { 0x0f80ba2,0x0583232,0x116c7d9,0x0e0ab34,0x08e055e,0x1a5b1a7,
|
|
0x0acd3c7,0x105864c,0x1de8c84,0x1a7beaf,0x11e02bb,0x1d41861,
|
|
0x139d55d,0x07d0f34,0x102bee7,0x186962e,0x0667460,0x1167f35,
|
|
0x061f07b,0x12b2822,0x0d94f66,0x1bafcba,0x04e0bc9,0x08a93d6,
|
|
0x0ace400,0x0810e50,0x1eeaf7b,0x1048967,0x1653eaf,0x0683271,
|
|
0x00f0dbd,0x18ab8bf,0x0b9f0dc,0x1e74875,0x13beb3a,0x0bb2773,
|
|
0x1906142,0x12c7390,0x05c3459,0x0bf05af,0x0485783 },
|
|
{ 0x0576210,0x092de69,0x110f735,0x0faa36a,0x1f378aa,0x0c1cca4,
|
|
0x0fc5c6f,0x043fd2f,0x1f38ac6,0x18687b1,0x1023324,0x182f030,
|
|
0x16af8f2,0x1307a9f,0x04b21f8,0x0ebc84d,0x007db0a,0x187722a,
|
|
0x1f6c6cd,0x08f5cbf,0x044b0ec,0x0e3d535,0x1da44a7,0x0816eba,
|
|
0x132b22e,0x1bbdb7c,0x0257bce,0x00cec9a,0x1c63e8e,0x03fab45,
|
|
0x100a3f5,0x1380029,0x1810494,0x0aec768,0x0ff75e6,0x1f21c5a,
|
|
0x0c2a85a,0x1cd02eb,0x0c4a3ac,0x17b443e,0x06c0277 } },
|
|
/* 61 */
|
|
{ { 0x109e7ef,0x1b8435a,0x1e47906,0x167aff3,0x0842ec7,0x135c45c,
|
|
0x17e5154,0x1579a50,0x0051dd0,0x1227032,0x1c73adb,0x1820ee9,
|
|
0x1b90198,0x091f330,0x12afa60,0x08fb2dd,0x13632f6,0x1224088,
|
|
0x1b14abb,0x10568a4,0x09d51dd,0x1fc9cee,0x1594241,0x1a8ab7f,
|
|
0x0eef2fc,0x0be5eaf,0x1634b97,0x102b49b,0x1c9f2a7,0x1649445,
|
|
0x0896b53,0x0af4766,0x0f10d0b,0x0e5ede3,0x079c82e,0x11d1a18,
|
|
0x1b774ee,0x05838d4,0x13e3d68,0x135e45f,0x03067bc },
|
|
{ 0x1ca9326,0x0c4f95b,0x1d8f839,0x1b62449,0x17a106f,0x1d2bde8,
|
|
0x11485d1,0x05d646a,0x162b088,0x10a4c16,0x07ff3c9,0x0a88872,
|
|
0x0d7f3af,0x1427220,0x0a8cdee,0x160e235,0x1b0941b,0x014751b,
|
|
0x1929fd5,0x0fb9685,0x15fba95,0x160d356,0x19ead98,0x186d441,
|
|
0x1e381f7,0x1b5e89a,0x126ea82,0x05cf301,0x04671f4,0x01864a7,
|
|
0x18d08dc,0x1161245,0x0cc63ff,0x12c4f92,0x09e5116,0x19a21aa,
|
|
0x0870ff6,0x0ce98b5,0x10656ee,0x195532d,0x0390c83 } },
|
|
/* 62 */
|
|
{ { 0x1c4a73f,0x1fd417f,0x0c0d434,0x0a77aa6,0x0665d63,0x05dbbe9,
|
|
0x1be2899,0x1090140,0x022d73d,0x0e02537,0x0ee2aa0,0x1fea064,
|
|
0x1a2409c,0x062626a,0x173885e,0x1383263,0x00e0c0f,0x01ba554,
|
|
0x0061aee,0x0b470e0,0x087f0b2,0x085578a,0x142dde8,0x0931bc3,
|
|
0x19ad5ab,0x08b0af9,0x186a830,0x05c65b4,0x025ce89,0x1edecb7,
|
|
0x1448a38,0x0bd0c8d,0x17c88dc,0x18e345a,0x059099e,0x0ace562,
|
|
0x000bdec,0x06c03fb,0x15ce974,0x0fa447c,0x03ea400 },
|
|
{ 0x195d0a3,0x0f5e852,0x0ed35db,0x175fe16,0x06bd76c,0x0dedcbd,
|
|
0x0553e6c,0x0e37e58,0x04c714c,0x158cd5a,0x0bd98d8,0x0772443,
|
|
0x16c9bf3,0x064a0f7,0x161f126,0x01eda47,0x0c3d79f,0x092ac02,
|
|
0x09eb2f0,0x14200a5,0x08af6f1,0x0caa829,0x176ade7,0x1a2c426,
|
|
0x1a6f0c8,0x014febb,0x1779784,0x00a116d,0x1da12b4,0x00797ca,
|
|
0x087656b,0x0eb1517,0x060af71,0x0647dc4,0x120dc58,0x0816329,
|
|
0x0e004d3,0x0736406,0x0aa8290,0x02ed629,0x009f82a } },
|
|
/* 63 */
|
|
{ { 0x01366dc,0x1f2c461,0x0be582a,0x1f5eebb,0x129c0a4,0x1c9f6a3,
|
|
0x07f66b2,0x0e0e0a0,0x087a16d,0x0bf3a27,0x1cd86ee,0x14f531c,
|
|
0x13a42e0,0x145aa67,0x136bfc8,0x120f035,0x0bbb7bd,0x1f843e6,
|
|
0x18c9439,0x1e7306c,0x1c09da6,0x175d783,0x19b5a4f,0x175e2ae,
|
|
0x0f4c38c,0x0e83cdd,0x1f7f2a6,0x15309c0,0x0d8dab5,0x1923f93,
|
|
0x1e6ad34,0x0fd746d,0x10be701,0x0e90b26,0x19943a3,0x066f773,
|
|
0x131c4f0,0x1527122,0x16169ca,0x1096ea7,0x077d1e9 },
|
|
{ 0x0e62367,0x1991cec,0x13c764d,0x1773041,0x1361848,0x0e4be21,
|
|
0x18d116a,0x1f8018f,0x014f960,0x10764d7,0x11d2d66,0x019ee80,
|
|
0x15cf41f,0x167032e,0x1bb7a3f,0x10c214b,0x04e9e80,0x0d8ef2d,
|
|
0x1833dd7,0x0895c95,0x0d0b17c,0x11b58a4,0x0be958c,0x13fe5b8,
|
|
0x0740fd2,0x097327d,0x0a232c8,0x0c0bd71,0x063016c,0x18d6b54,
|
|
0x05fcb1d,0x0c0f698,0x16112e7,0x04bc2b6,0x101d035,0x0bfd21d,
|
|
0x0256e0e,0x0df0c5f,0x0b6c166,0x1d994a9,0x04e6eab } },
|
|
/* 64 */
|
|
{ { 0x199cfe6,0x191e9fd,0x05e2540,0x0d92668,0x1b09bc2,0x1efdb7b,
|
|
0x07905f2,0x0c0c822,0x089a757,0x08a0ba2,0x0672c24,0x1bf2212,
|
|
0x0f4c633,0x1cb5fe9,0x17f1f1c,0x0c5b6e2,0x1128cab,0x04650ca,
|
|
0x16e06ab,0x0e48e69,0x054a306,0x15da626,0x199e891,0x0452c8d,
|
|
0x0a0fabf,0x0b86bbf,0x07e96d7,0x17da2be,0x1192f35,0x16d2e17,
|
|
0x0b695a1,0x0fecd21,0x0cac72a,0x085beef,0x0a8b2a9,0x1e1895e,
|
|
0x0049ad2,0x0318e0b,0x1c15bd1,0x12c09d9,0x0325d27 },
|
|
{ 0x048c144,0x0fdaaa4,0x1ccbb84,0x0b6d4f5,0x0e06292,0x0f07cd2,
|
|
0x1a384da,0x03c24b6,0x0ca53b2,0x0cded73,0x03a86eb,0x00b85d3,
|
|
0x15f50d6,0x0f97d1c,0x0e7854e,0x065eb7b,0x12de915,0x1a2b871,
|
|
0x1a89435,0x0d315c8,0x1145810,0x1656cec,0x1ff6551,0x1d2f4bc,
|
|
0x0772111,0x174d5fb,0x14927e0,0x1453efa,0x11df63c,0x1cd4cc2,
|
|
0x196a714,0x0e3a1c7,0x184d54b,0x095ab7e,0x1670107,0x15a3c08,
|
|
0x1d80096,0x19f5b77,0x1e74f3a,0x08dc654,0x019d485 } },
|
|
/* 65 */
|
|
{ { 0x140f5e5,0x0f747da,0x145ff86,0x1e09cd1,0x06d2a52,0x1ee438c,
|
|
0x036c2b6,0x191a464,0x0d03a7f,0x01d6ad4,0x12e45aa,0x078e117,
|
|
0x0054bf8,0x1728f42,0x084cfa8,0x1bbbe12,0x024cb52,0x1de71c2,
|
|
0x0418d60,0x0f7c806,0x1176d5c,0x0fa2c71,0x107aee7,0x09b577f,
|
|
0x19639bc,0x0d457d8,0x13015c9,0x0c6a1fc,0x01cd243,0x031a427,
|
|
0x17ab128,0x1828b71,0x1f73154,0x0191bd6,0x167acd2,0x00154db,
|
|
0x0bff272,0x1a2e1ee,0x14ec28c,0x0d969c8,0x01b3ace },
|
|
{ 0x0a8bdc5,0x1f2f4c8,0x02240d0,0x1ac60d4,0x0203bf9,0x0429075,
|
|
0x068d639,0x00d3091,0x0de7d1d,0x08bef5f,0x0574fef,0x0daebef,
|
|
0x1f8fafa,0x1c3d851,0x13ad8c0,0x1d5f549,0x132ffdd,0x1700b35,
|
|
0x19d9380,0x1c40a8f,0x1304a2f,0x127438f,0x156ae60,0x05d88bc,
|
|
0x136bb95,0x065515e,0x12a4348,0x1698290,0x1cfb537,0x19c3bad,
|
|
0x1954c67,0x0d30589,0x0238a4a,0x1490e9a,0x071e840,0x1d4576c,
|
|
0x1b3ab17,0x030db26,0x0285078,0x07c325e,0x0538ec3 } },
|
|
/* 66 */
|
|
{ { 0x19b56cf,0x04b7f50,0x0b3464d,0x08f7733,0x063d77f,0x085440b,
|
|
0x0bea15f,0x1fb1e09,0x0082835,0x0769ed1,0x0b3b1f3,0x15dabb0,
|
|
0x057e21f,0x1c004e4,0x05d6e67,0x1460edc,0x11b2d05,0x16ce371,
|
|
0x0521f60,0x091a950,0x0655969,0x196a37b,0x01baf4f,0x0799893,
|
|
0x11aa877,0x0534342,0x0a2c590,0x1c441e4,0x020b753,0x11d420d,
|
|
0x1be7c1b,0x1215814,0x0fffe5e,0x159fd96,0x076a3af,0x13eb536,
|
|
0x0e08e2c,0x03eccbb,0x1d00496,0x13007d3,0x06fd602 },
|
|
{ 0x0b7516a,0x04fc6c7,0x02ad51c,0x097b8b3,0x03058a7,0x1400e74,
|
|
0x176621f,0x12da469,0x0d17b8a,0x087cec8,0x03daaff,0x093edd2,
|
|
0x1baa1e5,0x0d3f6aa,0x05bfe01,0x0983249,0x17a6c25,0x086cfb2,
|
|
0x025895d,0x1d49397,0x07de3cd,0x1816ff9,0x0da168f,0x1178097,
|
|
0x0e7fddb,0x1581e28,0x1e61c8d,0x009fe1f,0x0d50559,0x0c7edd8,
|
|
0x141250a,0x1c297d1,0x0b3386d,0x0986b1a,0x1a71f0f,0x12f5a69,
|
|
0x0159fdd,0x15995ef,0x197007c,0x0798ec3,0x084cfa2 } },
|
|
/* 67 */
|
|
{ { 0x199b964,0x008f5c5,0x111c4ef,0x14b1c5f,0x0e280c0,0x04d2a5c,
|
|
0x0f12753,0x1f50e1f,0x0bf6e20,0x1d19a51,0x0233e8d,0x1a1baf9,
|
|
0x1aee583,0x17a578e,0x180a6a3,0x1f14c0b,0x0340c2e,0x136aaf1,
|
|
0x027a6d8,0x0dfbfc4,0x080f61b,0x135dc70,0x0ec76b4,0x125f834,
|
|
0x1c16293,0x1a72d6d,0x182ab8f,0x05581fc,0x1f4d5b0,0x000d615,
|
|
0x14a3666,0x18505fd,0x133f93f,0x0d99f91,0x0432d4b,0x0e2db96,
|
|
0x055752e,0x1c87c26,0x0363827,0x0a39094,0x0287d4c },
|
|
{ 0x09867da,0x0c10087,0x13697e9,0x06350e9,0x014589b,0x0f71173,
|
|
0x09f17ef,0x15000bc,0x1e612bd,0x1abff7a,0x18d7e78,0x1dbe5a6,
|
|
0x064e0db,0x17892d4,0x0f9c391,0x145cac5,0x0840d94,0x0d04dcc,
|
|
0x02d7974,0x13342a5,0x08b57eb,0x173a881,0x086e505,0x0da5988,
|
|
0x17fd7e0,0x0228d89,0x1ffa826,0x1f43ea2,0x0ecbd76,0x14b37fe,
|
|
0x0f8ee87,0x1065e8a,0x0c89a4a,0x147d0ea,0x0abfb29,0x060f63c,
|
|
0x0bd395a,0x1da229a,0x0784f43,0x1b9b1df,0x00132a3 } },
|
|
/* 68 */
|
|
{ { 0x16374c2,0x03bc2ab,0x010394f,0x0308e4e,0x060526d,0x0650227,
|
|
0x1b7208a,0x027140c,0x0f1ce13,0x1f0e0d9,0x0c31747,0x10659bd,
|
|
0x0f2aeec,0x0e5fc13,0x1659a66,0x14b134e,0x081de77,0x0668c47,
|
|
0x0634495,0x1c1fc02,0x186ae5c,0x0203c85,0x0850aa6,0x158519d,
|
|
0x1043f39,0x0027147,0x021f796,0x1ddf052,0x19a8c54,0x0d997b1,
|
|
0x13e0f0c,0x0b10ef2,0x10454a7,0x0d9c8eb,0x154062c,0x0b94c6b,
|
|
0x11d9c79,0x1f503b1,0x0a8973b,0x0ed6df1,0x013cbee },
|
|
{ 0x13f34f3,0x15f07c6,0x1f8de72,0x1946c2f,0x1da9c31,0x0a1350d,
|
|
0x1b88f76,0x00964db,0x1f29c91,0x0eecb13,0x1b34efa,0x02d3c58,
|
|
0x16033eb,0x1e5d10c,0x1cfd24b,0x1907914,0x00bb858,0x1c971bf,
|
|
0x0ecfeed,0x05594c4,0x00a2e4f,0x0f325f0,0x00407ec,0x11ec891,
|
|
0x1826a94,0x073c8d3,0x1241c98,0x0280cf6,0x0bb8354,0x1528718,
|
|
0x1bbddd2,0x1933380,0x122ca80,0x04288fc,0x16e42e8,0x00d70c6,
|
|
0x05fa04f,0x09b5ae1,0x0259efe,0x1b5c05d,0x04e0a1a } },
|
|
/* 69 */
|
|
{ { 0x1a29c4d,0x1333845,0x0250032,0x1c45310,0x008240c,0x0ed3a96,
|
|
0x1299c5b,0x068438b,0x1abbbfa,0x04e0722,0x0a2dc9a,0x0bfa7da,
|
|
0x141d754,0x0be2b55,0x0884663,0x13acabe,0x1743875,0x0a59ec7,
|
|
0x1f942e2,0x121bf71,0x1a16934,0x0bf4075,0x0d907d7,0x1596a6f,
|
|
0x1a5eb79,0x12f3d86,0x1c30757,0x16d6292,0x1a429aa,0x1346d2e,
|
|
0x0948ce3,0x05eda5e,0x010c437,0x079d3f0,0x1b4994c,0x1844de2,
|
|
0x0bef08b,0x187bdb6,0x12667be,0x1b33f33,0x0733e30 },
|
|
{ 0x02a38f9,0x10ac152,0x1403b3f,0x1c8e616,0x0ec2d58,0x0bb5965,
|
|
0x1ca9f7a,0x1765dc5,0x1a969c1,0x029ceda,0x136d2bc,0x02d1f9d,
|
|
0x0231954,0x13d4748,0x1dcd22b,0x0a83fe5,0x1cc3121,0x10eac6b,
|
|
0x080ab94,0x0b6eb84,0x15a75d2,0x0d7a041,0x17aa659,0x1369c8d,
|
|
0x16a4152,0x0cd9ff5,0x1ef49eb,0x192ff6d,0x1f900b5,0x0a60130,
|
|
0x07b61d5,0x009ab63,0x03031d9,0x0cdce5a,0x06e32c8,0x1e67abd,
|
|
0x1ee00bc,0x01ea491,0x17031e9,0x0736f34,0x056facb } },
|
|
/* 70 */
|
|
{ { 0x1018bfa,0x0b2d151,0x0610064,0x093ff5b,0x100c6b2,0x1a0d4d8,
|
|
0x0c7d954,0x19377e3,0x125dc4c,0x15e8ecb,0x1ff9839,0x1daa57f,
|
|
0x0b52850,0x1f2a84d,0x1a64b31,0x0b3e249,0x02e4ceb,0x07fb628,
|
|
0x0a9f452,0x166ae63,0x0a462f0,0x0ef3f1d,0x1a43077,0x0285101,
|
|
0x09f45d1,0x0eadd76,0x1996f97,0x0eb9fa4,0x0bce134,0x18a70ff,
|
|
0x0c20eae,0x101285a,0x0ba4829,0x1416435,0x0d74a5f,0x1a3c364,
|
|
0x10d8218,0x18e6df2,0x1b2eedd,0x0cdb29a,0x0885992 },
|
|
{ 0x15ccaf2,0x039480a,0x1cf8221,0x0ef8b6e,0x0679ebc,0x0e8476c,
|
|
0x0b746cb,0x1b75116,0x087d475,0x1050c07,0x1340aa5,0x0d6ecd2,
|
|
0x1680fdb,0x1f9fcf4,0x01d6324,0x06d887d,0x0fa4ad8,0x0ded1fb,
|
|
0x0bece1f,0x018b026,0x000f940,0x0112a81,0x0969e15,0x0dd9e30,
|
|
0x1c35177,0x0cd154b,0x1959b6d,0x07d7e8d,0x145eda0,0x1140132,
|
|
0x1111d0e,0x19ee956,0x1169d84,0x19fb4f6,0x0c76232,0x0d75572,
|
|
0x1825719,0x1749966,0x05c65c2,0x14d4181,0x0797224 } },
|
|
/* 71 */
|
|
{ { 0x01f3567,0x091fc22,0x1c758ca,0x105c497,0x011c316,0x138fffe,
|
|
0x1c9aedd,0x044972e,0x17a5e1a,0x00ba353,0x16d05d8,0x1d4075b,
|
|
0x0653ddd,0x1facdc2,0x019e8f1,0x0ffeeaf,0x18756cd,0x0580954,
|
|
0x066ea6a,0x0bfd93e,0x07481bd,0x117c183,0x1d40de6,0x1180ba2,
|
|
0x1445dab,0x0153bb1,0x0de40fd,0x1afe883,0x03e46d5,0x13a6d48,
|
|
0x1070045,0x15ba24d,0x11d3c4d,0x0ada00d,0x0ab1851,0x1d44ea5,
|
|
0x155c356,0x1215342,0x014b136,0x02bb041,0x03ff09c },
|
|
{ 0x1cb7784,0x10de77c,0x0c15302,0x184845e,0x0ec539b,0x00a553d,
|
|
0x1e7f431,0x188be81,0x0ffd42b,0x1d518b6,0x1638574,0x09865e6,
|
|
0x0242f5a,0x0b713b4,0x0f7367b,0x1d9dc01,0x09ff8a5,0x0834fbc,
|
|
0x17853d7,0x10031c0,0x0741807,0x09c5a06,0x0aecf92,0x02fee5a,
|
|
0x08c1d79,0x0862ede,0x13315c5,0x01dd4cc,0x1a8920e,0x062d61f,
|
|
0x192897b,0x038f2e2,0x021b0f5,0x168b59e,0x0bc98d2,0x151e134,
|
|
0x18391d9,0x1987e2a,0x0b93239,0x00a9fbf,0x047ef18 } },
|
|
/* 72 */
|
|
{ { 0x1a285e4,0x0f9e89e,0x0fd2659,0x147403c,0x1a7d4db,0x10a5685,
|
|
0x104e984,0x0928e70,0x1223975,0x1dbea9a,0x0c2e4b4,0x1b9eb4e,
|
|
0x1da53db,0x19968b2,0x0c364ac,0x0fde862,0x14182f9,0x1225142,
|
|
0x137386d,0x0444388,0x0ec9bf6,0x0c3f150,0x0ee84e1,0x1f5b331,
|
|
0x12c8dcb,0x02599f9,0x1ed7fb5,0x013cbe7,0x0217bb4,0x0632e33,
|
|
0x0a570ca,0x1f9bee3,0x00db69f,0x103c458,0x0886e24,0x1744785,
|
|
0x1ae6464,0x1594731,0x02187e2,0x13971bc,0x01a6b6e },
|
|
{ 0x0af77aa,0x1615b03,0x0196bdb,0x1b510fe,0x0e60f5c,0x04c62b1,
|
|
0x050027d,0x0970fa4,0x1fcbaaf,0x1acadac,0x0ae1576,0x05424e3,
|
|
0x0c0fb59,0x0a1a4d8,0x1384397,0x1193941,0x1d8887d,0x1ceb0c3,
|
|
0x152f5b6,0x1d2bf22,0x099903e,0x09ae836,0x03f94c8,0x0d4c9a1,
|
|
0x1bc30fb,0x1b07a53,0x159a932,0x1a455e1,0x17367c3,0x1677ae9,
|
|
0x1545a54,0x132fb1c,0x10ea734,0x1996837,0x1c3dcc5,0x05688f8,
|
|
0x09cb394,0x15981a5,0x03f4002,0x10050a2,0x079dd01 } },
|
|
/* 73 */
|
|
{ { 0x0c7424e,0x0019d1d,0x1340138,0x10c1fb4,0x1b06b68,0x1bb97de,
|
|
0x05d9af2,0x14846d5,0x1f297cd,0x0a54715,0x04f1b8a,0x170bb60,
|
|
0x0d4b0aa,0x0391d1d,0x0abb262,0x094d67a,0x0cd13c8,0x1065719,
|
|
0x03b05a7,0x111ebce,0x0262218,0x1ea1544,0x1ce58ce,0x0c1b370,
|
|
0x0792e7b,0x1f0b456,0x0841da7,0x13e56e4,0x0bed348,0x07f3692,
|
|
0x0aa3cff,0x147d649,0x15efb88,0x03835e9,0x08fd213,0x1bbbd9f,
|
|
0x129ece0,0x008cd4c,0x150d9f3,0x08b1a80,0x087e5ad },
|
|
{ 0x11000a7,0x0d54ebe,0x00ceea6,0x195d047,0x0b94aff,0x1c1ee2c,
|
|
0x058a37e,0x11b9045,0x1845a41,0x1acff08,0x05c150b,0x01f0ba8,
|
|
0x01a8b97,0x195b8ac,0x0630995,0x1ba2f12,0x17dc0d1,0x07277a3,
|
|
0x0beb5f0,0x1699e67,0x0a5bb50,0x1c80c38,0x086eba9,0x07450d0,
|
|
0x087f9bb,0x0e6e3b8,0x1849296,0x10aea63,0x1432397,0x0137abf,
|
|
0x12bb5d3,0x002c992,0x1f5ae25,0x05fba6a,0x1f8bc25,0x04cc116,
|
|
0x1dceea3,0x06dadd7,0x10117d3,0x0333219,0x00b7125 } },
|
|
/* 74 */
|
|
{ { 0x0d5c64d,0x08650c4,0x14d168a,0x134e924,0x0596d74,0x0074928,
|
|
0x034f4a8,0x0d74096,0x0caf7b6,0x0166816,0x17b60c2,0x0185d9b,
|
|
0x0e912b5,0x1f98b23,0x0f3a77b,0x1ff2b02,0x0c7c75f,0x0b15738,
|
|
0x18a9185,0x10a5c0f,0x0fd16f6,0x0801c02,0x0c83f5f,0x031d1b2,
|
|
0x0a4dd82,0x0ebd8d1,0x0ebf191,0x12314df,0x19fdbe4,0x07d0f46,
|
|
0x1bbec20,0x088e16d,0x1d4d08a,0x1a77b99,0x01ddb65,0x05a5744,
|
|
0x09dae5d,0x05cad3b,0x165b63b,0x074fad2,0x07a3f42 },
|
|
{ 0x0929387,0x096534d,0x1ffcd8b,0x0396383,0x0bdb758,0x08db65d,
|
|
0x1b27df9,0x03fb125,0x03a4e13,0x146c319,0x01d587b,0x07e2b7b,
|
|
0x124680e,0x0a73f39,0x0965f87,0x1fdfdc7,0x17c5581,0x19e6395,
|
|
0x0a32b82,0x0eff159,0x14aff3e,0x0e2f17e,0x1f31f5f,0x06ab6f3,
|
|
0x0455221,0x0bbee9d,0x0a8b01c,0x08d649e,0x09621f5,0x0996834,
|
|
0x0f9056d,0x07ef02c,0x1e9af51,0x1f69095,0x0e6ccf5,0x064fac7,
|
|
0x1680294,0x00cf794,0x1ebd2ac,0x0aa2c47,0x02da5fc } },
|
|
/* 75 */
|
|
{ { 0x0a5c600,0x14e79e4,0x19f1890,0x047fc67,0x07a80c2,0x0beee5d,
|
|
0x09d0029,0x0e93ffb,0x1925b0c,0x0d70ab6,0x003ac34,0x07f2d62,
|
|
0x01097a4,0x17ca1e4,0x07a5173,0x19e482d,0x0e51128,0x1d0fb9a,
|
|
0x067c04c,0x10f8948,0x0024043,0x0580822,0x1001e1a,0x06b39e5,
|
|
0x16abf90,0x071f2a0,0x191e355,0x138edfd,0x02173ef,0x0ed3215,
|
|
0x1059886,0x13fc602,0x1e03156,0x1923f30,0x138e4fb,0x0541feb,
|
|
0x072b659,0x0bc95d0,0x1534e04,0x032e190,0x0855f02 },
|
|
{ 0x07314c4,0x1fdb642,0x05a987e,0x0bd68b7,0x1790615,0x1157d64,
|
|
0x18519ae,0x102e205,0x1ab9497,0x0a8fcba,0x0313fbb,0x162f822,
|
|
0x079d2f5,0x17fabb3,0x12339c2,0x089cef5,0x0216eb2,0x1f39b35,
|
|
0x1471971,0x1779d8a,0x19dedd1,0x0570d42,0x0d49418,0x14fa5cf,
|
|
0x081748b,0x0623d02,0x06ae3aa,0x03458a8,0x1ff078e,0x1261b7e,
|
|
0x011b9e0,0x0290e96,0x1b49fc7,0x0fb99bc,0x0dfc1ac,0x1e455c6,
|
|
0x0f8fe6c,0x1a90c93,0x01e5c70,0x19ea4ba,0x0292236 } },
|
|
/* 76 */
|
|
{ { 0x18b29dc,0x06c053e,0x122b36e,0x0811d4c,0x117a202,0x095f48e,
|
|
0x0b17aba,0x178fb62,0x0fda72f,0x19a3e8c,0x1831bc7,0x16813ce,
|
|
0x1111374,0x0c71c6c,0x187a3c7,0x183e8e6,0x09d739a,0x13b8a5f,
|
|
0x137d713,0x12e0396,0x0ae1c1f,0x0c37b96,0x1644e3b,0x1a30189,
|
|
0x1e1f76a,0x1ce0e3f,0x1a78b6f,0x11830b7,0x10c44df,0x1934be3,
|
|
0x17e0d76,0x161a2b6,0x197cfea,0x12a2f7c,0x1169879,0x1ca2028,
|
|
0x05184e5,0x1834421,0x19ea85a,0x0b2ea43,0x07cfac3 },
|
|
{ 0x00bc53a,0x010b39e,0x0d9e046,0x06fcea2,0x04b5ede,0x12bd0c4,
|
|
0x157f68d,0x1307944,0x0ba1fdd,0x0b55dfa,0x09df602,0x0d3f8bb,
|
|
0x059ce83,0x1559a16,0x1ee6b9e,0x0b3e3e4,0x1d69720,0x083648d,
|
|
0x053b3fa,0x1b56612,0x1f12ee0,0x1dc9fa9,0x0ed91fe,0x14afc1d,
|
|
0x18a7aff,0x1039861,0x1e7cab5,0x02fa0dd,0x19dcc95,0x06c3ddc,
|
|
0x08525ca,0x088c101,0x0034af1,0x0e0bed8,0x10fc4ae,0x0199021,
|
|
0x172a22a,0x12f8a7b,0x00af5c8,0x0fe3bbf,0x06ce3dc } },
|
|
/* 77 */
|
|
{ { 0x0397830,0x06c1ad2,0x0c1b01f,0x19e8e66,0x0dd9290,0x0c4f462,
|
|
0x14ea0a6,0x0a5ba6b,0x1563d81,0x0c812ac,0x17986de,0x1223d0f,
|
|
0x1cf278d,0x081271a,0x1cd031c,0x01cb338,0x0614a0d,0x096a222,
|
|
0x0c989a8,0x0ec11fe,0x1aa963e,0x14e264d,0x189e8df,0x1fffa4a,
|
|
0x0dc5176,0x0e6862b,0x033bca8,0x16dbdf9,0x0559d9c,0x06ab77e,
|
|
0x04b2f30,0x008396d,0x05f3fc5,0x10f04f2,0x08e7945,0x199a0b8,
|
|
0x1c3b559,0x198f74a,0x085b4a9,0x04547a1,0x0851511 },
|
|
{ 0x0ff19e2,0x0819ac3,0x180de0b,0x143b450,0x02c60da,0x1e3f76e,
|
|
0x033f955,0x16165cf,0x01bc4e8,0x07b7cc2,0x0d719ea,0x16967be,
|
|
0x0acc1f9,0x03b2231,0x184d80d,0x1c1612d,0x1977c7a,0x15fc885,
|
|
0x050d655,0x0fe60aa,0x0ae527c,0x0e7b18f,0x10536c5,0x0d36699,
|
|
0x161427e,0x1f9528e,0x057f04b,0x1d9050a,0x087162d,0x1709fdc,
|
|
0x0f7f33a,0x1bc2911,0x0332ac1,0x1f3a66d,0x1388bb8,0x194406e,
|
|
0x10ae069,0x1f50d0f,0x1b01165,0x1e4ef7b,0x08b1159 } },
|
|
/* 78 */
|
|
{ { 0x1961d30,0x18d2217,0x123d2bd,0x10f58e4,0x1df968a,0x148366d,
|
|
0x1e1f2c6,0x04ba65b,0x004abf9,0x0608713,0x0135300,0x0eb373e,
|
|
0x1ab8711,0x09cb82e,0x1553982,0x0109201,0x033c9f8,0x0fbac3a,
|
|
0x09e88dd,0x1575bcd,0x17ac2e9,0x1c4a560,0x159db51,0x005b338,
|
|
0x0525bc2,0x19ea650,0x16afeb9,0x0b71795,0x05991b9,0x169c1a0,
|
|
0x10c8dc7,0x08b1533,0x169e47a,0x0643315,0x0c60ade,0x18f9581,
|
|
0x00232c7,0x1553cdf,0x1d165b3,0x066b11e,0x00bd864 },
|
|
{ 0x0734189,0x0d45a3f,0x085f7a8,0x119fcbf,0x12c5ac8,0x01bb322,
|
|
0x1353845,0x0a08894,0x0af9e97,0x1291184,0x11acef0,0x0187a61,
|
|
0x1778b1d,0x0636fa3,0x16b97c1,0x11bae5d,0x19a2ee8,0x029898e,
|
|
0x1324f8d,0x0701dd5,0x0e8ec4e,0x16546d8,0x15266c6,0x0ba93af,
|
|
0x08c167f,0x06bbb9a,0x1c555b3,0x12cc64a,0x11d13dc,0x0746130,
|
|
0x1319738,0x16b45fb,0x095fe66,0x07d5096,0x00ca196,0x104cd31,
|
|
0x11c32c9,0x03e8fa1,0x0641f6a,0x131f9b2,0x0466505 } },
|
|
/* 79 */
|
|
{ { 0x14a5efa,0x009e635,0x099531b,0x163a0f6,0x0481989,0x0e34e06,
|
|
0x19b3a2f,0x1a82172,0x02c2531,0x0a67d51,0x028403d,0x101195a,
|
|
0x09cb5f1,0x172ed22,0x0d494e3,0x107997d,0x085bedd,0x0531200,
|
|
0x189571e,0x05b59fa,0x058fe79,0x0310310,0x020dc64,0x02cb183,
|
|
0x15e83ed,0x0a14b30,0x1df4a35,0x16a9364,0x175df34,0x13edc1d,
|
|
0x10babc4,0x02ff772,0x160df6d,0x1e49827,0x076fdbd,0x1fa10c6,
|
|
0x0018789,0x01c7cc3,0x0a0305f,0x0957352,0x00c4357 },
|
|
{ 0x120cad0,0x199260e,0x0229dba,0x1318c22,0x10decb0,0x0369b6c,
|
|
0x14e71bc,0x12f4dd3,0x0bc0da1,0x06cbc5d,0x0b1739b,0x0380a0f,
|
|
0x155948b,0x02a4bf5,0x151c593,0x029c657,0x00f4d59,0x0154e26,
|
|
0x1d67c0f,0x18a08d4,0x047e772,0x0534d64,0x19f5cca,0x0916661,
|
|
0x17d0c30,0x167546a,0x0103dee,0x0c0069c,0x1f1790e,0x08c9d42,
|
|
0x0da08f6,0x0b90b2e,0x0e9b66c,0x1081153,0x11e99e7,0x0845945,
|
|
0x09023fa,0x13d0ce0,0x156e403,0x1e24e4d,0x0324999 } },
|
|
/* 80 */
|
|
{ { 0x0834915,0x1576b3e,0x193599f,0x1578bd6,0x1f77aa6,0x0b1008c,
|
|
0x0f2d897,0x184e53d,0x0699fd9,0x1771279,0x153db02,0x10e8571,
|
|
0x16e1eb5,0x0a64bb6,0x049c430,0x1d4cafe,0x135f6d9,0x0489c81,
|
|
0x1ad4019,0x16e0920,0x0e4f668,0x07043b7,0x1965a68,0x13b26c0,
|
|
0x1bf3f2f,0x1e77c80,0x06d2678,0x16350ca,0x1bcaaaf,0x09fdf96,
|
|
0x0da02e5,0x12e760d,0x12cc566,0x1b63218,0x070cebc,0x0a6a69b,
|
|
0x10ffd81,0x031d290,0x0ae4791,0x097e318,0x057ea2b },
|
|
{ 0x0a0f2f2,0x0f0b145,0x12a803d,0x0a1c8d7,0x0c7e75c,0x116216c,
|
|
0x11e6a92,0x0052f56,0x014baa2,0x0798475,0x0f30bad,0x1a28d28,
|
|
0x04a901b,0x176ac40,0x0497fbb,0x01ef976,0x0f99d18,0x0328164,
|
|
0x1603187,0x0a72322,0x1ee3e53,0x1493880,0x1f89e01,0x14e4e2e,
|
|
0x040a1fa,0x0a9bd05,0x0931d6c,0x05db9c0,0x0f1c223,0x1305a9c,
|
|
0x0bb688d,0x17c60fa,0x1511e98,0x1705a26,0x19026eb,0x0e484ed,
|
|
0x1ff1f30,0x061c93b,0x0d7269e,0x08dd4f2,0x060480b } },
|
|
/* 81 */
|
|
{ { 0x072ece3,0x03eb31c,0x03e0c42,0x1b2ab6e,0x1f29be7,0x1caddc2,
|
|
0x13f1e73,0x0436a16,0x1dbffa6,0x171dac6,0x0ae976e,0x0501c04,
|
|
0x1c0e61d,0x00c0a24,0x0b9445d,0x0a90af1,0x040cf55,0x1058994,
|
|
0x03382c3,0x1da36d7,0x1e3d800,0x0abc6ae,0x0d77ff7,0x14ad68e,
|
|
0x0237469,0x173fbf2,0x0636442,0x0bc646d,0x13c7c7d,0x0950318,
|
|
0x196dbfd,0x1525bd3,0x02fe20d,0x0885dad,0x1f4f448,0x0683668,
|
|
0x00c16f2,0x082f6da,0x0233316,0x1a7351f,0x00774a0 },
|
|
{ 0x1b6c106,0x0c0d5f1,0x02dceb8,0x1f1bc2a,0x0ebe163,0x1aa41b2,
|
|
0x0e0bdbc,0x02d9eeb,0x13ac7ac,0x1069031,0x1c8abea,0x0cd0522,
|
|
0x135c680,0x08aa2aa,0x0507984,0x1c7eee7,0x038bf5d,0x10b893f,
|
|
0x0bed076,0x1fbe063,0x066332c,0x08c3de4,0x11a24f2,0x0593933,
|
|
0x06744a6,0x0a3ba82,0x1658b06,0x0d0cdc5,0x0cdf4c9,0x046f9bc,
|
|
0x0c9227b,0x0680ff4,0x060709b,0x148689d,0x0565544,0x07a6fa4,
|
|
0x1ab9227,0x11e981d,0x0052e58,0x0a84864,0x0081519 } },
|
|
/* 82 */
|
|
{ { 0x17b2108,0x1b6c4fd,0x06abe48,0x195aebf,0x1ecc83c,0x10ed089,
|
|
0x0ac56d3,0x0c5ef8e,0x10315c3,0x0957577,0x0bf8fd5,0x01dbe4e,
|
|
0x0811e14,0x03c21f7,0x15e6fda,0x164b733,0x0fd1d9b,0x06735aa,
|
|
0x0c6eb5d,0x161c42b,0x090db20,0x07adc26,0x1528085,0x14d9d92,
|
|
0x1bf52fc,0x1b7a2cd,0x167937d,0x06c7891,0x0cf17ee,0x1c276b2,
|
|
0x120c117,0x1ec55b4,0x002a167,0x06500c2,0x0fcda9d,0x1a593c3,
|
|
0x1691c42,0x07cea0f,0x0e1d3a3,0x0f18589,0x05abf21 },
|
|
{ 0x1b3bccd,0x1cb35f9,0x12a91dd,0x017c7c1,0x0047e0f,0x1ea8218,
|
|
0x00ece31,0x1f99707,0x1946fd5,0x1bf1dd7,0x103a1f9,0x0f0bd3d,
|
|
0x0579baa,0x0450c69,0x0f155f3,0x1f9fdb0,0x1af25be,0x0cdcb72,
|
|
0x031c6d8,0x0ba2bd3,0x0da14f0,0x0d3bf31,0x0207e64,0x1547042,
|
|
0x0c781cb,0x1fd8e37,0x1795366,0x0a45ecb,0x0d14307,0x0ab9a27,
|
|
0x16bd741,0x12b95fb,0x035b31f,0x07adf98,0x1d0d8de,0x128fccf,
|
|
0x1270b9d,0x0fbe56a,0x1a9200a,0x10e9b22,0x015ad15 } },
|
|
/* 83 */
|
|
{ { 0x0588ae4,0x1176755,0x08c8037,0x1146e34,0x152ebc5,0x1182222,
|
|
0x0a4d1c4,0x05ba01d,0x1e4b183,0x1dfd33e,0x07a10eb,0x06836d1,
|
|
0x0829216,0x10fa717,0x05aeef5,0x13b8a3f,0x08404c2,0x0caa103,
|
|
0x08c5ff4,0x1c704e8,0x1162c7f,0x0331a41,0x18282bb,0x000309f,
|
|
0x194d107,0x0c2fe15,0x0ff87ef,0x0e4332e,0x0743520,0x1558fd8,
|
|
0x049922d,0x188dca7,0x1bbdaad,0x12b7f91,0x147c03e,0x0c1b71b,
|
|
0x066725f,0x040af5c,0x0658c41,0x194a5d0,0x03f9c4c },
|
|
{ 0x0ce637e,0x1594b99,0x1377fcd,0x1beba4b,0x01a15f2,0x0156cbc,
|
|
0x014b62c,0x1d2343a,0x0cfbab3,0x12f9dde,0x1badd4b,0x17aec29,
|
|
0x1a60d2c,0x06ad3c9,0x124610f,0x04289a8,0x175cdba,0x1112167,
|
|
0x02e65d9,0x0e0bcf1,0x0132a20,0x00763bf,0x19384b3,0x035360a,
|
|
0x14df6b6,0x1ad58e0,0x11d2096,0x1fb2fe0,0x0312238,0x04109ed,
|
|
0x0365581,0x09a618e,0x0486727,0x17734ef,0x1c54704,0x1b79571,
|
|
0x068d893,0x031c5a3,0x15d2d77,0x1ac447e,0x06479da } },
|
|
/* 84 */
|
|
{ { 0x05f2b26,0x02279d8,0x1db15a4,0x150173e,0x135a294,0x087b575,
|
|
0x1f8a10a,0x0ef1073,0x1026a58,0x10e7d91,0x1fe70dd,0x0d6c5cb,
|
|
0x1676892,0x0588e2b,0x19b3480,0x07dfd75,0x15672a0,0x16e42bb,
|
|
0x06eb58e,0x1c0e95c,0x199c0ca,0x10eb84e,0x0ff9246,0x003b382,
|
|
0x1ded665,0x1fbbb62,0x070cabb,0x1b4dd94,0x1683e81,0x0eaae2b,
|
|
0x11d4212,0x1bf31b0,0x0392e9c,0x0d2b24f,0x00bd936,0x05f5af3,
|
|
0x037b98b,0x01dedbd,0x0125fdf,0x129e10c,0x01fe09f },
|
|
{ 0x048cc63,0x1f5573b,0x1c51269,0x02cf9f4,0x13ea251,0x1fa2ac8,
|
|
0x048f194,0x10df917,0x181a16e,0x0abb0cd,0x1919d36,0x0096790,
|
|
0x1a0c7e8,0x0b0b2cc,0x0204d28,0x04651f9,0x1690a65,0x11b3754,
|
|
0x0f240a7,0x0652c09,0x0d2b415,0x0a57155,0x1be7866,0x0217deb,
|
|
0x08c527f,0x0304f15,0x1b19efe,0x07b96b0,0x0cc25d7,0x01fd422,
|
|
0x14fd869,0x0e9d66c,0x14e7eea,0x007816b,0x1c1b749,0x09e66ac,
|
|
0x1d83bcb,0x03b4a67,0x149abbb,0x10db6c4,0x04de957 } },
|
|
/* 85 */
|
|
{ { 0x1eac2f7,0x1e98a9e,0x0a39219,0x156c3b3,0x0084778,0x1bd96ad,
|
|
0x1be582a,0x0f3e76e,0x0cfdf4f,0x059802b,0x0e3d2c0,0x1c2a635,
|
|
0x01d0701,0x0e3bce8,0x1e52356,0x0a6e20f,0x0bc8267,0x03e4ca7,
|
|
0x02eb530,0x09a9dc9,0x1058110,0x1adfe4e,0x1e63382,0x13f5016,
|
|
0x0898d30,0x157e3e5,0x16b2ccf,0x0489e44,0x0f31750,0x06fe2d9,
|
|
0x0d3547a,0x149af7c,0x049ba6b,0x015a19f,0x131ef68,0x142ec1e,
|
|
0x0435275,0x11b53f2,0x06030df,0x117cc6d,0x01c9441 },
|
|
{ 0x1dc1414,0x1098984,0x14dd0e8,0x1887926,0x060765f,0x0fbce70,
|
|
0x081eb7d,0x194dfe6,0x085d4cf,0x18c58fd,0x0656adb,0x0e5cc7d,
|
|
0x02f5c42,0x1415980,0x0682792,0x0fe2c24,0x11b9714,0x1415b2e,
|
|
0x029ff89,0x0784184,0x0726499,0x0c7338b,0x067272e,0x1688141,
|
|
0x0d673fe,0x1e2ad01,0x04946d2,0x1e7f53c,0x1338ea3,0x023a502,
|
|
0x12dd76f,0x0f613ed,0x0b4044b,0x1a3049e,0x0862010,0x04cecfb,
|
|
0x098ceac,0x028a110,0x0d6ea5e,0x1656aa4,0x0611bfb } },
|
|
/* 86 */
|
|
{ { 0x00ad2a1,0x152af78,0x035ef6e,0x1c29452,0x09efa85,0x158b4a1,
|
|
0x11da3a4,0x0607694,0x111ec81,0x1888de6,0x149ec99,0x0e05117,
|
|
0x060e425,0x0cd01e0,0x033ca8f,0x11095e5,0x12df318,0x05dbe46,
|
|
0x0eabac8,0x1428c5c,0x1d77e2e,0x0221dc2,0x0cd4d60,0x09dd37a,
|
|
0x0448255,0x0c7c0f7,0x1b9aa86,0x165ddd3,0x0c5944e,0x1402613,
|
|
0x1f1e96a,0x105562c,0x0ef2da5,0x110d2d0,0x11d80bf,0x1cb4556,
|
|
0x1370298,0x0e59dc1,0x0aa345a,0x0881d67,0x086e6c5 },
|
|
{ 0x1793d9b,0x0199085,0x1b3bb78,0x023bb6b,0x179fade,0x0985b27,
|
|
0x16a49a2,0x165ee7f,0x1fe4fd1,0x1556cbe,0x1372201,0x163b254,
|
|
0x15073a5,0x1e4bb6b,0x1e32f62,0x04d8115,0x1b163ce,0x1305a55,
|
|
0x12c7ec1,0x060153b,0x13d39c8,0x066d4ad,0x0cd6965,0x0fd590e,
|
|
0x1d7d4b3,0x1558fcb,0x0883bbe,0x07a5d74,0x0828c8a,0x048379f,
|
|
0x004c963,0x10b56ef,0x032616f,0x05b0be4,0x064a30a,0x1ae4b2e,
|
|
0x1233b82,0x18cb5e1,0x049b735,0x17233f4,0x083867e } },
|
|
/* 87 */
|
|
{ { 0x0474edb,0x1f39f11,0x06b9dd3,0x083509c,0x0a76639,0x16eb719,
|
|
0x0a6b671,0x0ba4e06,0x114f8bf,0x062520a,0x19ee400,0x146fa44,
|
|
0x0e3ce2e,0x08e927d,0x1d4c054,0x036f024,0x054263a,0x13e0a6c,
|
|
0x0b82c81,0x1080363,0x09fc20c,0x0d840fa,0x1cca804,0x138dbf1,
|
|
0x123fb95,0x0830f40,0x1200387,0x0651b8f,0x059a9aa,0x11bc121,
|
|
0x0dd61da,0x16fded8,0x1ada8b5,0x0a64f91,0x0dbaa4f,0x1e047ed,
|
|
0x1fb6389,0x1aa0a6f,0x0ce7a27,0x145cc51,0x04b26bb },
|
|
{ 0x1318454,0x18e5a2e,0x12db4c2,0x1fae86d,0x123b749,0x053a308,
|
|
0x11c995a,0x03c6221,0x11c84fd,0x02ef091,0x00f5572,0x0dcc108,
|
|
0x18a5f8d,0x0d8fd5f,0x16db84e,0x1b9c072,0x0c33cfe,0x07f36b4,
|
|
0x12e4444,0x00703f2,0x0eb71d9,0x0096e63,0x1c2a3aa,0x1219457,
|
|
0x004137e,0x02d2cf4,0x1f22897,0x1d6bf80,0x04663cb,0x129d2ec,
|
|
0x1f00270,0x12216d4,0x0b15073,0x07c6a80,0x0931042,0x0b0c0fb,
|
|
0x0b901e6,0x01ece1e,0x057180b,0x18a592c,0x04d697b } },
|
|
/* 88 */
|
|
{ { 0x1a8fb40,0x18f7877,0x0273836,0x16b7473,0x09021c5,0x0e8cef9,
|
|
0x1ec5602,0x1c351ad,0x14c1219,0x1bc3db9,0x1c1789a,0x02d029d,
|
|
0x026417e,0x07cbcb7,0x04d0b6e,0x0843689,0x05ebf84,0x117c3c5,
|
|
0x052914d,0x122dafd,0x1693e71,0x11d708c,0x06062ee,0x0d1009d,
|
|
0x14be957,0x1c57633,0x13e1093,0x144c0e9,0x0ce6ab0,0x1dcea33,
|
|
0x02f6f24,0x192400f,0x1f15a98,0x078d1d9,0x1434e1c,0x0f3a21f,
|
|
0x04e785a,0x0920ecf,0x1360298,0x143cd91,0x076ca87 },
|
|
{ 0x02e48b7,0x1fdab70,0x07190d5,0x079813d,0x1bd14b1,0x034e787,
|
|
0x090d490,0x153b6be,0x02c3b01,0x03c0b2e,0x15b6b7e,0x0f89cd2,
|
|
0x08e549e,0x1deb05b,0x1fa54e2,0x18ca7e5,0x16b059d,0x1ca97c2,
|
|
0x0ddffa6,0x0c044b6,0x08c4d3f,0x145ff48,0x1a831cc,0x11ebe5a,
|
|
0x0a2d3bc,0x0286735,0x0c91094,0x0e42688,0x1b3ce5f,0x13351e9,
|
|
0x0485f84,0x182ceea,0x1b5e43f,0x1c4a53a,0x0188dfe,0x0a2b24e,
|
|
0x0be3e37,0x1303a99,0x0def854,0x18cdb47,0x027e7f2 } },
|
|
/* 89 */
|
|
{ { 0x0a15883,0x1b2d6f3,0x0ccd8e3,0x18cd5fb,0x14a7e68,0x1896f2e,
|
|
0x0daaf4f,0x020c40f,0x037b878,0x037fca8,0x13db4c7,0x1964c95,
|
|
0x02c0d44,0x195f3c6,0x0eb1807,0x1301c2c,0x05a1636,0x18e31e6,
|
|
0x1724d26,0x059fd12,0x12203e9,0x0c20f63,0x1dce383,0x0bf52c2,
|
|
0x1d7642d,0x074b0b4,0x070f80a,0x154eed8,0x0d54092,0x0b2358b,
|
|
0x1664f71,0x0e0dbe9,0x0b27fb5,0x035cbd0,0x05c33a7,0x013d322,
|
|
0x13c85f4,0x07215f2,0x194a3aa,0x06f0648,0x002e964 },
|
|
{ 0x078ea1f,0x0056ed7,0x1a5a455,0x1af6ce1,0x11a1b74,0x0034132,
|
|
0x19107dc,0x18ff326,0x07d7520,0x1cbeb75,0x184b863,0x1404d39,
|
|
0x020faa6,0x1c9041a,0x042b2a1,0x0886c4b,0x0637561,0x1bd241c,
|
|
0x0e05023,0x0c293de,0x140607c,0x026bc29,0x1ccefd6,0x1776dee,
|
|
0x1b0109a,0x04d43b0,0x1fd4a28,0x09d6493,0x00ae3ce,0x0f6c170,
|
|
0x1e821e0,0x042f1df,0x04c1b25,0x09d3f43,0x0a8a754,0x1f983cc,
|
|
0x1919062,0x1c5ca70,0x149f7b6,0x1b49e2c,0x0739f53 } },
|
|
/* 90 */
|
|
{ { 0x04adc5f,0x1a54449,0x15b5e97,0x0d5031e,0x15646c1,0x0afcaa4,
|
|
0x044a5de,0x0001d89,0x1d19c54,0x1a43a9e,0x044ad0a,0x06d640b,
|
|
0x0616fa2,0x143d24a,0x0f597cf,0x1a0ccd6,0x001045f,0x0538ba5,
|
|
0x0a97850,0x0a06262,0x0623b63,0x0254b5c,0x09e712d,0x16007ab,
|
|
0x19d659a,0x18d3d19,0x18e09bc,0x0e5e618,0x1090cdc,0x1c8637b,
|
|
0x092d39c,0x120dd7c,0x1ac6c36,0x0282d2c,0x01b6ee9,0x14734fe,
|
|
0x058c413,0x0cc8f0e,0x03a120e,0x1ff441c,0x0020c23 },
|
|
{ 0x1c74661,0x1256d57,0x0194483,0x064eff8,0x17bbcf6,0x0e73cc9,
|
|
0x073dadb,0x1428209,0x17b161b,0x1c6b5a9,0x043ec96,0x086352c,
|
|
0x0922218,0x0feef3b,0x07b2747,0x00c61bd,0x04d42d8,0x1e995fd,
|
|
0x09137d2,0x0ae054c,0x0dfb388,0x16a2ac9,0x137b747,0x09c0371,
|
|
0x1f45bfb,0x0d8070e,0x0a1b885,0x1e97bda,0x137e6a8,0x0a43b54,
|
|
0x08e024d,0x10261ee,0x15278ba,0x010fc20,0x1a48e2a,0x158db88,
|
|
0x1d8b4f8,0x03d88cf,0x073bc88,0x0a7f24d,0x076e7bf } },
|
|
/* 91 */
|
|
{ { 0x1ebd187,0x1421413,0x16ed7c4,0x176cb55,0x0d3320a,0x12c34ac,
|
|
0x1d969c8,0x1576084,0x18f0986,0x11f99fc,0x1fd40f6,0x0f4f5d7,
|
|
0x0541180,0x012fb8d,0x11ddb2a,0x1e4964b,0x1edff7d,0x0606f3d,
|
|
0x197c7ed,0x161e842,0x1ae3da8,0x1bb98f9,0x17cffdc,0x07c14a4,
|
|
0x1d7e719,0x1232668,0x0edacee,0x1bf0954,0x1f37828,0x1c4bd50,
|
|
0x11eea12,0x1cee675,0x07960cc,0x00d10b7,0x1aad426,0x1a9a8da,
|
|
0x1cbb80e,0x009612b,0x1bc247b,0x04e572d,0x079e7ad },
|
|
{ 0x130caae,0x0b86e47,0x1bd0f36,0x0214dd7,0x05cabcf,0x0a30b6c,
|
|
0x018fb1c,0x130c783,0x1519e3a,0x0286d85,0x0c4f587,0x12c6c99,
|
|
0x09f39b8,0x112a3db,0x19f607c,0x16199be,0x1b9d67d,0x1b8abd5,
|
|
0x025246d,0x144b751,0x00dcccc,0x1e3d13f,0x1da2481,0x1a86503,
|
|
0x08fbe0f,0x0049a57,0x0d5c83b,0x0bb23ee,0x1d7beda,0x0c84e6f,
|
|
0x0cacbd8,0x094073c,0x0c10232,0x0c7ee0f,0x197b6c3,0x1ba787a,
|
|
0x0fe5005,0x048b642,0x1aa50cb,0x1589817,0x07f8c37 } },
|
|
/* 92 */
|
|
{ { 0x1ac05e5,0x00f2a21,0x0094cfb,0x099b1a7,0x1a4a4da,0x1fcf15e,
|
|
0x0302e22,0x1b90db1,0x0b53811,0x06b8ee8,0x0eae90d,0x01a5478,
|
|
0x1e65504,0x1b0b08d,0x1102526,0x09f4057,0x06e279a,0x18e16a1,
|
|
0x0c196b0,0x14b5447,0x0890535,0x17e2975,0x16aa28c,0x1bb5a45,
|
|
0x1eca79f,0x137ad2e,0x14aacec,0x023e0bf,0x1cd81e9,0x13edf9b,
|
|
0x03176b3,0x121a2d7,0x00e44e7,0x0c4a707,0x0bb793d,0x1e2bcd1,
|
|
0x1c92a74,0x1024ccf,0x1f0bebf,0x1552e1c,0x01d7703 },
|
|
{ 0x10062a9,0x0640e9f,0x02eaa29,0x11b2d44,0x031eb2b,0x05e880f,
|
|
0x0637e19,0x028cdbb,0x04413b6,0x102fac9,0x1557e2e,0x141bd34,
|
|
0x1151a67,0x1725a96,0x10bc25c,0x1564759,0x0ec7184,0x1d5aed5,
|
|
0x11fda46,0x11687cf,0x07f4ce0,0x05bb621,0x148394c,0x047d7b8,
|
|
0x12069e4,0x0673e9a,0x00d37c5,0x16bc73d,0x0305ac6,0x194aa23,
|
|
0x104f72f,0x1fc699b,0x02cb2e1,0x1ad7db4,0x1744447,0x13a9588,
|
|
0x07f296f,0x17b1e6a,0x021c717,0x1d92784,0x00a2c40 } },
|
|
/* 93 */
|
|
{ { 0x15747db,0x01c27d7,0x01ac26f,0x0d80d57,0x1bad608,0x1e0aa39,
|
|
0x020ba79,0x17f480d,0x155977a,0x0a99368,0x077ac0b,0x140bb50,
|
|
0x11063a9,0x0925b08,0x01b929d,0x1d72135,0x07a4ab2,0x10a017c,
|
|
0x171802e,0x0e43a9a,0x1dbf7d0,0x14f944f,0x068bf66,0x1bcde0e,
|
|
0x0e66dec,0x139faee,0x1f6ae7e,0x042e24e,0x074bab6,0x024fb62,
|
|
0x0cdb4b7,0x0eddda0,0x0017e1f,0x012e9ee,0x170136a,0x0772e2e,
|
|
0x14b05e4,0x14bf1ea,0x121f9b0,0x08cad93,0x02efb45 },
|
|
{ 0x121c064,0x0958045,0x0a7a91c,0x0494e0c,0x1186fe4,0x1a7857e,
|
|
0x0cd026d,0x052c86b,0x17ec9e6,0x0b2d521,0x183421a,0x0ce7898,
|
|
0x0adda14,0x1f982bd,0x19599c2,0x0dec016,0x0403ce8,0x13f82f4,
|
|
0x1100685,0x00e7520,0x007ec05,0x1c14a73,0x05ac798,0x19ee08c,
|
|
0x0325269,0x09d103c,0x0fa339f,0x1282283,0x17053d2,0x0c69bab,
|
|
0x0374e2b,0x1954cc6,0x1a68fb3,0x021a86d,0x1fc7a54,0x17d97d5,
|
|
0x1d2d760,0x08b36a8,0x047927d,0x19c8c51,0x0337532 } },
|
|
/* 94 */
|
|
{ { 0x000bb9b,0x08c299d,0x1a14fc4,0x1c8becc,0x0d2ffba,0x1771269,
|
|
0x06a1752,0x0dd35c2,0x1034185,0x05d0f0d,0x04d27c6,0x02f04e6,
|
|
0x15a9ac8,0x0a2b8ad,0x0f7f529,0x1a5d582,0x03c5daa,0x1d2fba1,
|
|
0x0d6dda9,0x090772a,0x1e9b30a,0x127fc39,0x04ba6b6,0x07420ab,
|
|
0x02d8472,0x0700ab3,0x0e3b6b1,0x126a92f,0x18fa70b,0x020d1ce,
|
|
0x07d86d9,0x081a2b1,0x141d756,0x02f850a,0x08dfc28,0x10c5328,
|
|
0x0bb2890,0x05801a3,0x0cafff6,0x0bba99a,0x0192a2b },
|
|
{ 0x05ced07,0x1b3141b,0x147d8d5,0x160bbc3,0x029f32f,0x0053d50,
|
|
0x0e6f2fd,0x08eda2f,0x09bb50a,0x18d9504,0x0989e06,0x1776f2b,
|
|
0x1b9389a,0x19a7e0c,0x13fd83e,0x10e72a5,0x092387d,0x179d5ca,
|
|
0x0483335,0x00a7ccd,0x14f0a8f,0x05b1d4d,0x0fbcb75,0x1d04252,
|
|
0x0ede151,0x1d0cd58,0x0c20e2f,0x1f74181,0x1c11bea,0x13d64ff,
|
|
0x1e0af56,0x12b9810,0x18bfd95,0x1786302,0x028fe30,0x14d0da9,
|
|
0x1d9b31b,0x1d5d578,0x109a30c,0x1127781,0x0632e22 } },
|
|
/* 95 */
|
|
{ { 0x1a1ccca,0x08e900a,0x0f0c721,0x18fca45,0x0efe290,0x155829a,
|
|
0x0755463,0x02e16e8,0x1bc85e2,0x132b0cb,0x1e2ca6b,0x083c039,
|
|
0x18ae131,0x134a423,0x0b2d64d,0x1b15c5c,0x10fc31b,0x075abdd,
|
|
0x09939e2,0x1debad8,0x0d86dec,0x064e5cb,0x1bea15b,0x12307b4,
|
|
0x1681327,0x0b516d8,0x00e0f5e,0x007e704,0x0c6fedf,0x0b7f8e8,
|
|
0x06d6291,0x114d57b,0x1589805,0x0b78c92,0x0b160fe,0x0e673ea,
|
|
0x1a7e9ea,0x16f6c7e,0x135173d,0x182ba39,0x068c3d9 },
|
|
{ 0x0b392b7,0x13132f3,0x14259f8,0x1eeebb2,0x0ec1d9b,0x128a7be,
|
|
0x0f3535d,0x039c2d5,0x00de72e,0x037acd9,0x1ec0cf6,0x079a35b,
|
|
0x0ca66e4,0x02f22be,0x0d10d00,0x1b545b6,0x1165681,0x0db3d3c,
|
|
0x00451cc,0x1cf757e,0x0961c32,0x1769d8f,0x019bf85,0x07a4dcc,
|
|
0x0298ef6,0x0b6c927,0x01506b7,0x17d41bb,0x02f9719,0x006fccc,
|
|
0x0b3be54,0x18be0ed,0x0876e63,0x09cb5ae,0x0b96c8f,0x14abc25,
|
|
0x0ec6747,0x17dd9b1,0x01a9427,0x1dc4665,0x08f2055 } },
|
|
/* 96 */
|
|
{ { 0x02c1af0,0x15cf1dc,0x0991292,0x0fe595c,0x1c65e9e,0x0c3ea37,
|
|
0x0b02980,0x0c69fd5,0x1e393b3,0x1e9f99a,0x0eb3389,0x1801033,
|
|
0x119c9f7,0x1c55330,0x1d062d6,0x15d2a7e,0x157372a,0x0ffd4a2,
|
|
0x16ce162,0x1af0091,0x1c1c937,0x0fb78fd,0x144321b,0x1e1419d,
|
|
0x0bd89a2,0x0f5a457,0x08d9d0e,0x1cbabf4,0x17d2d8a,0x15059f8,
|
|
0x05040e9,0x0823b31,0x033f68a,0x1b3d179,0x02cc862,0x0cffd9d,
|
|
0x0319bf0,0x112a079,0x0c8b810,0x192681a,0x01292c8 },
|
|
{ 0x186463d,0x1aac381,0x05ffd7a,0x0406e3b,0x14bbc2b,0x00ce2d6,
|
|
0x115c42e,0x082366c,0x0cf04ad,0x05da16b,0x0e7b043,0x18eccd2,
|
|
0x075d819,0x100c23f,0x116b04e,0x065c90e,0x1021c72,0x027b825,
|
|
0x12c15e0,0x1cb1415,0x02952c9,0x19dab0f,0x0548ee2,0x1f3746b,
|
|
0x0df0079,0x11419c2,0x087aaa5,0x10463f8,0x0a2b907,0x02a7c57,
|
|
0x18e8bab,0x061a384,0x075ed77,0x1c80040,0x1b57ecc,0x1559689,
|
|
0x1011293,0x0a35617,0x05d9249,0x057d704,0x07c7876 } },
|
|
/* 97 */
|
|
{ { 0x07902b6,0x1eb7d83,0x0602e3d,0x07a2e6b,0x12823a4,0x1a0eeed,
|
|
0x1ec4965,0x0b80c59,0x14033f9,0x11c8d83,0x026e31b,0x0146d0b,
|
|
0x123831d,0x0911487,0x11d3525,0x03e75c6,0x0d6222e,0x0a6d58a,
|
|
0x0fc234e,0x01f9bca,0x08f58f0,0x17383f9,0x156645e,0x11cc0f8,
|
|
0x0a0ba06,0x0120b35,0x1f5f87e,0x004e27c,0x0a328f6,0x0aa026b,
|
|
0x0a9f095,0x131219a,0x12e3264,0x0590506,0x0513b28,0x19e440f,
|
|
0x12f4e09,0x0c6e03a,0x1a07572,0x009b09b,0x0694035 },
|
|
{ 0x1407206,0x1d9b372,0x0a33e2d,0x1e1b11f,0x1ecf54c,0x1397378,
|
|
0x19523dc,0x0d0dfdf,0x081ab44,0x12989b9,0x1d10235,0x1e1c9c8,
|
|
0x1f52cb5,0x124839b,0x109ace9,0x1a0e33c,0x19b4980,0x192bb60,
|
|
0x1c9cb2b,0x068c501,0x11c991f,0x07a3479,0x1e39829,0x1089b12,
|
|
0x0a32990,0x015c3bb,0x12e5456,0x14aae01,0x11adbf8,0x19b28a5,
|
|
0x1beac6b,0x1f7a687,0x0ebff92,0x00f9a11,0x0c06df6,0x0265f3f,
|
|
0x1a6b30e,0x0287035,0x0551ab6,0x04f78bf,0x06da9e0 } },
|
|
/* 98 */
|
|
{ { 0x09490ce,0x172612e,0x0e0487b,0x061bed0,0x096ec4a,0x149b475,
|
|
0x01f8292,0x1e7cd8c,0x04bc262,0x0582495,0x10d3ff6,0x04208c1,
|
|
0x0d0846a,0x146f99e,0x1fde990,0x0ec25ef,0x0442182,0x08862a8,
|
|
0x126f340,0x0bf9d22,0x13dc9d2,0x06e7e30,0x1c95847,0x1ea39ca,
|
|
0x17e8897,0x05a8acf,0x053a302,0x1f477e6,0x07538f3,0x108abaf,
|
|
0x083a855,0x1239080,0x1e0a951,0x1568568,0x02eb3c0,0x1e1a44d,
|
|
0x058b8e5,0x0635620,0x1644a81,0x17366a2,0x0773b40 },
|
|
{ 0x031cfd2,0x1966e1b,0x1ef003f,0x0700ee6,0x14c4c2d,0x0529380,
|
|
0x185a8ce,0x1bdac00,0x1b32cab,0x0719836,0x0c5f2b4,0x11d54e1,
|
|
0x0e33673,0x1cf9a9f,0x1d2aa35,0x075a7e5,0x0d9576f,0x03897b5,
|
|
0x06caf38,0x0f30a51,0x0a30e42,0x06ed496,0x01763e5,0x0925bb2,
|
|
0x1d475d8,0x05ecc48,0x0934579,0x1c0d4b9,0x0eabbd3,0x0a7592a,
|
|
0x0f11c97,0x181daa2,0x1394ace,0x1573618,0x0166efe,0x0efc1f3,
|
|
0x033fd13,0x092aa34,0x13dd770,0x10b8ad8,0x012b463 } },
|
|
/* 99 */
|
|
{ { 0x12951de,0x0df5ec9,0x1252043,0x04b54d3,0x16959d4,0x197846c,
|
|
0x07013b2,0x058bf89,0x02250b8,0x03a7866,0x113876b,0x134a75d,
|
|
0x0d96a43,0x0824cd6,0x0f2ae6a,0x1675f86,0x06654d9,0x197e66f,
|
|
0x018eba2,0x1e50b87,0x1f88f4a,0x1f237f5,0x08dccdc,0x1356fda,
|
|
0x1672c3c,0x1063a8e,0x03f8480,0x038a226,0x13e56ec,0x0017a97,
|
|
0x006b609,0x1494c95,0x089ab7a,0x0b1f91a,0x198767c,0x0e143f6,
|
|
0x0e55331,0x034df08,0x1505c5f,0x0bcfb11,0x061c193 },
|
|
{ 0x092ae43,0x116cd9a,0x0168b9c,0x0a0a71e,0x1ef89d9,0x0555b18,
|
|
0x1962080,0x02f5cef,0x0eba4b1,0x0396090,0x1872e0a,0x0590748,
|
|
0x065c243,0x05c9c79,0x16cd0d3,0x0fb8062,0x0c58c4c,0x082df95,
|
|
0x05acde3,0x0a03bab,0x0c30d2e,0x0fe5c48,0x0a141b2,0x06c3e19,
|
|
0x0f4617c,0x1d71e85,0x0168d72,0x03ef6e3,0x1c01382,0x1af8f9f,
|
|
0x17ef440,0x116491d,0x0628af5,0x0e5703a,0x0741232,0x071ac84,
|
|
0x0ca1877,0x11ed1c9,0x16e51d7,0x1e4e3a7,0x027ad0d } },
|
|
/* 100 */
|
|
{ { 0x05b5aed,0x1ed3c98,0x1a9e78e,0x08b331a,0x0c67d4a,0x1f5b801,
|
|
0x1874c3d,0x08990ab,0x0147d1c,0x0c53f4f,0x1503b70,0x0c31912,
|
|
0x003ea99,0x1f35fe9,0x0ef8829,0x0886f4a,0x064ecc1,0x164a43f,
|
|
0x13be171,0x0f240e6,0x0bd5729,0x18eaf0f,0x1e83539,0x091ad6d,
|
|
0x0b1e64d,0x06a7ed1,0x159b880,0x10543c0,0x1366a17,0x186d2d2,
|
|
0x0e0a8f1,0x0348e6e,0x03fbd2b,0x010747f,0x1019ff8,0x0bafdf1,
|
|
0x0acfb66,0x1437ef7,0x150bfb1,0x04edba2,0x05d9b5e },
|
|
{ 0x13e472e,0x1e2d2e5,0x0178d8d,0x0e61428,0x0153d92,0x04c2ac1,
|
|
0x04b96d1,0x0a20133,0x1f39a08,0x0780666,0x1b15806,0x18236b8,
|
|
0x0e26237,0x09a1aa0,0x03b5020,0x0630883,0x1f07e7f,0x1ff7be5,
|
|
0x1d215da,0x1246cd7,0x091aecd,0x0d5e4a6,0x06dd6f8,0x02c44ec,
|
|
0x178de4a,0x05c470b,0x0f171af,0x0a5cafa,0x171858c,0x0163ad5,
|
|
0x1e5730e,0x07edc73,0x12c2c28,0x19afe70,0x1bcb589,0x0c98fc1,
|
|
0x035a599,0x18ef58c,0x11d9b81,0x19b9771,0x024f891 } },
|
|
/* 101 */
|
|
{ { 0x178c1e2,0x1b05fb3,0x197093b,0x1a01ab7,0x1f49c03,0x00d04ff,
|
|
0x061b8bc,0x0b1d823,0x0ae096e,0x0d39452,0x1e61316,0x1db6e0e,
|
|
0x05aabbc,0x038652d,0x11cef4a,0x01c7bf6,0x0614de3,0x1464946,
|
|
0x1d9eaf2,0x1cff349,0x09cf3fa,0x15f610d,0x00f0acb,0x1b36bbd,
|
|
0x10d629c,0x06fd7d3,0x07182c6,0x1bd5d4b,0x09b54ca,0x1bdf202,
|
|
0x18f57fb,0x0dba621,0x0eebc76,0x190e67e,0x1f8e3d8,0x0aee91d,
|
|
0x18ee8af,0x0e19588,0x1d84bfa,0x19fa85b,0x0863ac3 },
|
|
{ 0x05a2fe2,0x17e53dc,0x171828d,0x11dc853,0x13e70d0,0x0e1ca27,
|
|
0x0882450,0x0151937,0x067272a,0x0354083,0x02f418c,0x0aabf2d,
|
|
0x1de69a1,0x0a9e301,0x1bdf91c,0x1c9f570,0x14aef56,0x04b8330,
|
|
0x01e02d3,0x186d713,0x1263c0d,0x111d0e9,0x10d95ff,0x0aa4592,
|
|
0x17a8643,0x13c80fc,0x1bb7fbd,0x12312fe,0x0a17a0d,0x18ea36d,
|
|
0x0f7aef8,0x10b599f,0x1179100,0x1e0ef37,0x18ca3e7,0x19c1b4d,
|
|
0x01e7142,0x0ea9edf,0x1c96872,0x03d170c,0x03e3f1b } },
|
|
/* 102 */
|
|
{ { 0x17fbf05,0x10ae03d,0x020adfa,0x0c3e347,0x192f11b,0x0e68de4,
|
|
0x1656b47,0x11793bb,0x0ad0f7e,0x0fadbfd,0x1eade4c,0x0bd7f94,
|
|
0x062936e,0x0cd2adf,0x1d05f70,0x1caa861,0x04343cd,0x18fb7a7,
|
|
0x0bc112f,0x1ebccb0,0x0408971,0x1221446,0x1cf0ee3,0x00feaea,
|
|
0x0c59fb8,0x07830d5,0x16062d6,0x0c9dc5b,0x03b0d3a,0x05304bd,
|
|
0x161bde8,0x0072960,0x185ecc8,0x1a8bec5,0x11d2fec,0x0d340b2,
|
|
0x079c3f0,0x16acbbd,0x0009626,0x1b0e015,0x081208e },
|
|
{ 0x0c4ce37,0x1a84c8a,0x0298424,0x0743549,0x134bb84,0x06ac747,
|
|
0x1c09160,0x1750c00,0x1b375b8,0x0da1624,0x0f7a0db,0x0a49da7,
|
|
0x16ac365,0x124919d,0x08786d1,0x128deaa,0x1d564dd,0x15e3e62,
|
|
0x1ed6dab,0x09606b7,0x01a39c1,0x0c00a36,0x1fc8ae8,0x04429ea,
|
|
0x0fbbc87,0x1b205b1,0x1ed2485,0x159fafe,0x0d6df13,0x06d0e5a,
|
|
0x0457fc4,0x0c4c015,0x00e2620,0x08b3fb3,0x0a76076,0x12f58fb,
|
|
0x16e7a19,0x0713065,0x0cf09ba,0x17101bd,0x044383f } },
|
|
/* 103 */
|
|
{ { 0x04f9af6,0x1f80ef2,0x0873841,0x1b1963f,0x16381a4,0x1eea499,
|
|
0x18fb3ed,0x13fccb7,0x026a883,0x05c21ad,0x1e27634,0x122a7d8,
|
|
0x1fee60f,0x15e62f0,0x17fa940,0x15039c4,0x0c57e44,0x0023be0,
|
|
0x0c2e96e,0x1d3f064,0x0dd9349,0x17ef0c0,0x1750bcc,0x147a239,
|
|
0x19eaf64,0x01d4581,0x1afadc2,0x01df109,0x0742cb8,0x1062789,
|
|
0x188a239,0x0e41404,0x0156cc5,0x1dbbfa2,0x1799c94,0x139aa8f,
|
|
0x06013a5,0x14d3765,0x0111660,0x11e1aa9,0x08aee70 },
|
|
{ 0x0c54409,0x116ce19,0x0b1063c,0x0cebd75,0x09ebfa4,0x1424c0d,
|
|
0x1a4a218,0x01921c5,0x16b3a8e,0x0100fb7,0x1d907b4,0x02d97ae,
|
|
0x15c9730,0x180b82b,0x09bcbc1,0x19c03f2,0x08ffec0,0x024c202,
|
|
0x0c674c1,0x12c423e,0x08c4bf6,0x02648d4,0x1d2d721,0x0061504,
|
|
0x0fbcee0,0x090a620,0x1793db5,0x1dacea4,0x167d1eb,0x03e614e,
|
|
0x0dabdf9,0x1843a6a,0x0307db8,0x14a02fd,0x11aaeec,0x1ead6d8,
|
|
0x033e805,0x0cd3f18,0x09683c1,0x1fcc12d,0x0970f61 } },
|
|
/* 104 */
|
|
{ { 0x1ec8e4a,0x09e918d,0x0d306f1,0x086b4c0,0x0809ac1,0x0f2326c,
|
|
0x0076942,0x06a9dc1,0x18a4882,0x0b570fe,0x0192d92,0x10c664b,
|
|
0x1fa1ae9,0x1a66834,0x1284fa5,0x14d6975,0x058b1d8,0x01b9c66,
|
|
0x1dae769,0x0e3eb1c,0x16fb5fa,0x0463f58,0x12466fa,0x09c853b,
|
|
0x0f13fad,0x0f6fae4,0x049267e,0x0b076ce,0x0d8bd74,0x008ad08,
|
|
0x1faf388,0x0af2176,0x06d7605,0x1bc6efb,0x1b7920a,0x15262d5,
|
|
0x15f855f,0x0c7d96b,0x1329f83,0x128b4fb,0x0404b5b },
|
|
{ 0x17a15c7,0x1341528,0x080be7b,0x19df100,0x0ae4cfb,0x0351aa5,
|
|
0x104e544,0x1cf9dc5,0x0170feb,0x0f300c9,0x03152d7,0x13fae7a,
|
|
0x17589e3,0x0648495,0x171c4d6,0x1fcbe32,0x13f0a7b,0x0e5bf6a,
|
|
0x187325e,0x124855e,0x17d92bd,0x1629caf,0x034bbc5,0x1665e13,
|
|
0x0c1ca70,0x0e086a5,0x154b461,0x0b0ea4d,0x0d6195a,0x18254a1,
|
|
0x0b0a4ca,0x14a0161,0x025a979,0x1e9187f,0x12b958b,0x18bf43e,
|
|
0x00da253,0x1aad791,0x1800983,0x16b0628,0x07faa11 } },
|
|
/* 105 */
|
|
{ { 0x0402149,0x1278637,0x0466c2e,0x1b2c798,0x1584cc1,0x093a3b1,
|
|
0x1706a99,0x1e4ee81,0x1c95715,0x1bbffba,0x07ec38f,0x095a7f1,
|
|
0x1fb2f23,0x17cdf1f,0x05640cb,0x0fd04aa,0x01d0423,0x1fe4fd9,
|
|
0x054fb64,0x1dfe714,0x1d13eb2,0x1008020,0x02754eb,0x037b051,
|
|
0x0545b7f,0x152e797,0x190e54f,0x1a944f9,0x1e75c8d,0x12ea6c2,
|
|
0x10c034b,0x04837c3,0x193ed62,0x10196f5,0x097c090,0x023ca7e,
|
|
0x03a4e70,0x0abb1b6,0x1fafee6,0x0a5db31,0x014b63a },
|
|
{ 0x1c43336,0x05aa9b8,0x092dd84,0x0c47490,0x19dfd4a,0x03028d8,
|
|
0x08b800a,0x1b6f72f,0x08f5f1e,0x155ddce,0x1f6ab61,0x1aef36c,
|
|
0x1b67a57,0x06affd7,0x13941b7,0x078c715,0x19589ac,0x042ed4f,
|
|
0x168f454,0x197550e,0x0ed2081,0x07f49a3,0x00cd4f6,0x1f3405a,
|
|
0x161f1a1,0x038d955,0x1ce9967,0x0196126,0x1df8a1b,0x1185a7a,
|
|
0x076df83,0x1d6fab4,0x1c4c741,0x12e783b,0x1271ca3,0x191e08d,
|
|
0x17c171a,0x0e85e3f,0x09954cb,0x0e706da,0x0024858 } },
|
|
/* 106 */
|
|
{ { 0x1a4cd8d,0x06e91ba,0x09e3350,0x072f797,0x132ca43,0x06b0fa8,
|
|
0x1361096,0x0d0618b,0x1da1e8e,0x13f602c,0x1750282,0x02e23ac,
|
|
0x1607a8f,0x1a1a86b,0x079957b,0x15c850d,0x0f05983,0x05cc673,
|
|
0x162faf4,0x02723b3,0x1d497b6,0x12d8dd2,0x0e94a78,0x0d659ec,
|
|
0x132e91f,0x114a37b,0x08fe8ed,0x1acdd8d,0x0f0ed2b,0x087661f,
|
|
0x1d8e5e5,0x0be1168,0x09008cb,0x1071777,0x1096596,0x0ffad7c,
|
|
0x1177bc8,0x16a89e0,0x0b6b9e3,0x1bffca2,0x06798ce },
|
|
{ 0x197c5c6,0x1fc7e8d,0x0cfd278,0x1cf1876,0x19fbab3,0x1acadd1,
|
|
0x1104903,0x0ec884e,0x15d7d43,0x1a112dc,0x111ddc5,0x1f98f38,
|
|
0x05880b3,0x194b592,0x0eb2a0c,0x1c309b8,0x1f71734,0x12ac89e,
|
|
0x124d11c,0x1647a73,0x0a11a4d,0x19e8a10,0x13aecdc,0x0c117b9,
|
|
0x00cf9f3,0x09fdce9,0x18c33f8,0x0c3159e,0x10874ca,0x1598af9,
|
|
0x095d7c1,0x13e000b,0x06efe7f,0x1e4eda8,0x1e3006f,0x03155d4,
|
|
0x178e7c4,0x0bc92af,0x18e57e4,0x1a4a5d2,0x03ea7ae } },
|
|
/* 107 */
|
|
{ { 0x106ae25,0x0bf022d,0x03be618,0x1b96aea,0x1cac148,0x0615d15,
|
|
0x0bc3981,0x0eb23d4,0x176b789,0x060cfb5,0x1686040,0x0da0ca3,
|
|
0x1b79b9b,0x04a2b82,0x0896faf,0x0b7e3e6,0x1f35c00,0x0985a1a,
|
|
0x109361b,0x1689057,0x1777440,0x0b6b1b9,0x0ae3c26,0x08969b8,
|
|
0x16c561c,0x0ccb2fe,0x18c241a,0x1280bdc,0x0a1ec1e,0x0492045,
|
|
0x05467fc,0x07a5e51,0x0f3246a,0x033cbf7,0x1d96f1d,0x1c02d86,
|
|
0x10705f7,0x092b4fe,0x001118b,0x1380a4a,0x06a8ad3 },
|
|
{ 0x0be7282,0x18106a3,0x1c4b917,0x1a42701,0x1405afe,0x0d35684,
|
|
0x096f757,0x03c99b9,0x07f8be6,0x16b78c2,0x0e05e30,0x12a6b2d,
|
|
0x1420132,0x1d46fca,0x0ec79ed,0x0569b1a,0x1bb3957,0x13abe30,
|
|
0x0330ed5,0x136af70,0x1fecd74,0x099bd9f,0x05643fe,0x0bb929b,
|
|
0x1b65314,0x0b99cdd,0x188cd79,0x01838c0,0x03feba7,0x196bfbb,
|
|
0x0ca70b9,0x198c36e,0x168e424,0x1f96523,0x1e9aa9c,0x1aeefa5,
|
|
0x05cb58c,0x126dd56,0x186ab7b,0x0f339f5,0x01a1811 } },
|
|
/* 108 */
|
|
{ { 0x1575ed0,0x1fb17bb,0x066dbdb,0x12fa3b5,0x18f14fa,0x17ebfb0,
|
|
0x0bbeda7,0x0665ce5,0x1ddc286,0x02d5a65,0x1160d31,0x1a90b0d,
|
|
0x18b0e20,0x1cbbaee,0x05c0468,0x08931a7,0x008f413,0x0009864,
|
|
0x14457b6,0x011d75e,0x1ed92d4,0x0e01306,0x1141a81,0x1957223,
|
|
0x1736219,0x1434f2d,0x1ba1a4e,0x19ea118,0x1736174,0x122fe63,
|
|
0x08d39c4,0x12bb139,0x171aa1f,0x1de4c17,0x11a981e,0x049774f,
|
|
0x012b7fd,0x128af39,0x1d6a3ce,0x0eb2461,0x07d2ddc },
|
|
{ 0x0d2cae8,0x0c0b6a7,0x0ddcf41,0x1b73800,0x0cf6bc7,0x15846a2,
|
|
0x0639991,0x101847d,0x14b9c01,0x0f73630,0x05e707e,0x1427df2,
|
|
0x0ae11c9,0x076cb44,0x0d851fa,0x0e14f4b,0x048d066,0x0bd7f5b,
|
|
0x1da149d,0x0066782,0x08f2d67,0x14bafcf,0x0a27765,0x14d15bd,
|
|
0x1228d37,0x0c35dab,0x191532c,0x0340bab,0x1dd5502,0x0ac7831,
|
|
0x1cd2040,0x0996d95,0x0dd4f08,0x055f3c9,0x0149e15,0x0ce189b,
|
|
0x0e729d7,0x0cb4ee3,0x102ea11,0x0f5637e,0x05a52f8 } },
|
|
/* 109 */
|
|
{ { 0x1ecacbd,0x0cf4884,0x17abb40,0x1af7137,0x0544023,0x039b8f3,
|
|
0x07c2d5c,0x02ef98a,0x016c8e2,0x0419582,0x166ad45,0x0d05024,
|
|
0x14b1aa6,0x11f1b0e,0x0403e48,0x0b854dc,0x0e9e3a9,0x172c9f7,
|
|
0x1b04389,0x16d77a2,0x013f699,0x19ca39d,0x0b521e1,0x0e930f9,
|
|
0x14dc5b2,0x174f8e0,0x1495678,0x0fb800e,0x147ad25,0x024ee1e,
|
|
0x04e1126,0x1baa4ef,0x1df278a,0x0adccc1,0x1b23bbf,0x00ee1c7,
|
|
0x16bd02a,0x12c2233,0x17ff8ab,0x0c87ce0,0x017f027 },
|
|
{ 0x1abea1f,0x0008694,0x1133769,0x0a480f5,0x036b969,0x1990c5b,
|
|
0x004a410,0x0952d4c,0x1163d53,0x110fe1d,0x081597c,0x0b7d998,
|
|
0x1705ba1,0x0b142ab,0x0e39536,0x009a624,0x0578788,0x00d8a21,
|
|
0x026a7f9,0x17e6095,0x02b196f,0x1625f32,0x1229fc1,0x05610bd,
|
|
0x020e86e,0x08eee8d,0x0bfd296,0x1efe4f8,0x0343b88,0x03a9d25,
|
|
0x13705ec,0x1762e7a,0x04b1e88,0x03ddf34,0x0910f70,0x0e7599d,
|
|
0x0c441d7,0x0ae446a,0x055fb6c,0x134a7cb,0x00ef030 } },
|
|
/* 110 */
|
|
{ { 0x08e5b60,0x12b90fd,0x0ec93f0,0x1ad2381,0x046938a,0x0511243,
|
|
0x12dd82c,0x0efc8da,0x07de168,0x11fcd61,0x0718c21,0x0dde4e4,
|
|
0x02503bb,0x05b3fd8,0x106677c,0x17a73f1,0x172e07a,0x13c60f6,
|
|
0x0cbc376,0x1bd6f76,0x09f3cf9,0x18361e4,0x0bfdc9b,0x0e444b5,
|
|
0x08b2d19,0x1ae5b80,0x1d3c517,0x1eb4c22,0x1c4f378,0x17c622b,
|
|
0x1913839,0x0388a78,0x1bdaa44,0x0964045,0x09b69ba,0x02af7c6,
|
|
0x1d77356,0x1e1feca,0x0dcaaa6,0x18d766f,0x03d3b6c },
|
|
{ 0x122c880,0x189664b,0x0225b9b,0x0e50d6d,0x1a1b6ae,0x17d7f61,
|
|
0x1026eb4,0x1df7439,0x043bb8b,0x0b256bd,0x0fd30eb,0x14012f8,
|
|
0x1ba5af6,0x01a9d48,0x1f2c367,0x17ed655,0x0ab69cc,0x06509fe,
|
|
0x0aaf064,0x142723e,0x07e5699,0x0111d12,0x0b6f555,0x0911b34,
|
|
0x0180f95,0x01e7103,0x1c49133,0x153cf7f,0x13a365b,0x1d5f43e,
|
|
0x188a4a5,0x1f4994b,0x054fa38,0x10db620,0x08f59ef,0x096720c,
|
|
0x18f41a4,0x133e2bb,0x1139c7e,0x0878f6a,0x02e946e } },
|
|
/* 111 */
|
|
{ { 0x00934ae,0x07eefe3,0x1b44a60,0x1e2c840,0x0c3e7ef,0x176bad1,
|
|
0x1fe5905,0x1b9eebc,0x15cd0b2,0x1630679,0x0b61efe,0x1d9c3f5,
|
|
0x1dddc4b,0x0c24f2e,0x0fea1f2,0x1e35cea,0x0a32c1b,0x1e2ea8b,
|
|
0x11ccad2,0x1b7d502,0x096b565,0x1d67243,0x001faf8,0x172ed28,
|
|
0x074d6cd,0x1df2065,0x0197939,0x1eb9a4e,0x0c4ebc3,0x1e009d5,
|
|
0x085d211,0x087ad87,0x162e034,0x103b533,0x125519e,0x1ad21b1,
|
|
0x1eda677,0x06bc6b0,0x16309da,0x0aa0303,0x00997ce },
|
|
{ 0x05a0b81,0x1ba364b,0x17ea4a5,0x0dcbc25,0x08b58be,0x0fa1bfa,
|
|
0x0cf11c5,0x0b2aae7,0x1b565c4,0x012f483,0x09e5f39,0x0a242b0,
|
|
0x0f4f43f,0x0752a3a,0x16be9be,0x00959cb,0x1be13de,0x19575c7,
|
|
0x0281f20,0x1f2be1d,0x09feed7,0x1733160,0x0f804a9,0x0859e2e,
|
|
0x0e9b8c7,0x022dfcb,0x0b8a287,0x1d4aeb3,0x14e2f38,0x00da2e7,
|
|
0x0651d65,0x1f20340,0x1d3c02d,0x0b5973e,0x1ba9c24,0x11cf49b,
|
|
0x0fa9b98,0x19395a9,0x1ff9942,0x13fa122,0x096f9f0 } },
|
|
/* 112 */
|
|
{ { 0x0310a96,0x0556216,0x1cd1e3a,0x07ef454,0x12a9830,0x0b11039,
|
|
0x0a0f48e,0x10188d9,0x0d95412,0x0898f37,0x0fa446b,0x18bc595,
|
|
0x085791f,0x020db63,0x12ddfae,0x110f0a1,0x1ea3d3c,0x157fc9e,
|
|
0x0401ef3,0x083e3be,0x11fd065,0x012ae6f,0x13b9ca7,0x07c72e4,
|
|
0x1131732,0x060f07b,0x06b5342,0x05bcf48,0x1e22bfa,0x155fd1a,
|
|
0x096a644,0x1136066,0x050122b,0x0a6a750,0x07d0194,0x17173ca,
|
|
0x19d3e0a,0x1e3d56b,0x1fa9508,0x04c8171,0x071998e },
|
|
{ 0x0b6ed78,0x007e6e7,0x1459005,0x0e30a68,0x053cf37,0x0b06e63,
|
|
0x0d96ba3,0x1f008a1,0x09dac55,0x1360d3b,0x15a1b33,0x125b5c0,
|
|
0x028a96a,0x093892b,0x1911d88,0x1284a5f,0x150a4f3,0x13a3de5,
|
|
0x114c7f0,0x18dfe5f,0x1ff0f0e,0x03887f4,0x125f0d1,0x0f259ff,
|
|
0x087839c,0x00cfda4,0x0009bec,0x0a58a49,0x04c2905,0x114e6c0,
|
|
0x1cd0006,0x06b9194,0x02b5ad8,0x0efd03a,0x1c5dbb9,0x0386f03,
|
|
0x1dfa4ab,0x15c2f81,0x0cab329,0x034161a,0x0838994 } },
|
|
/* 113 */
|
|
{ { 0x0067dff,0x031516f,0x058b03c,0x0179700,0x14f3269,0x03d15ee,
|
|
0x064341c,0x123319b,0x0fae4a3,0x17e31dc,0x0b60516,0x16f7665,
|
|
0x11684f1,0x18ccefd,0x08b738b,0x0b09161,0x17f48f2,0x1113070,
|
|
0x0b57a18,0x07b6018,0x1171739,0x0a19c67,0x07a23e1,0x159ea45,
|
|
0x1942902,0x19e8033,0x01a0d6b,0x122af97,0x02614c1,0x17c95c5,
|
|
0x1b0bea9,0x0269d88,0x0ff95f5,0x1409a82,0x09bbede,0x099e00c,
|
|
0x137a470,0x059e82d,0x1b09515,0x0624d29,0x01fbfda },
|
|
{ 0x0f69c77,0x1db2be4,0x03ebf7a,0x1747bf1,0x12a8278,0x1dbc5a4,
|
|
0x155c707,0x0668c76,0x011c71a,0x103350d,0x0562c34,0x0286113,
|
|
0x0610c88,0x07ceb3d,0x1d71f83,0x0f71f72,0x0087303,0x0ed52e9,
|
|
0x02fd618,0x0a00ba8,0x09a95ee,0x13bedd3,0x0c039b3,0x0c598e8,
|
|
0x03cb3c9,0x02ac49e,0x0533e10,0x15930c5,0x1c9d700,0x1b1d112,
|
|
0x1a029fb,0x1723c8f,0x0184869,0x1c25f7f,0x17ae30b,0x1e373af,
|
|
0x00e278b,0x1c448ae,0x1c6799d,0x195884d,0x04f9488 } },
|
|
/* 114 */
|
|
{ { 0x151b8ce,0x0fe6a6e,0x1a01843,0x106c461,0x0857927,0x0ccab10,
|
|
0x1fc70d9,0x0efdb8f,0x1e2cae8,0x02f56a5,0x19d8224,0x0bb3cf2,
|
|
0x0ca1c32,0x1e9c493,0x0e7b776,0x0149c7c,0x0685f6f,0x06d4964,
|
|
0x11e83e9,0x1f0015e,0x0aabe16,0x0df2fb0,0x142d36d,0x070a7a6,
|
|
0x1412f98,0x04e1b32,0x026de5e,0x096c44a,0x0e72b26,0x002c270,
|
|
0x0efa958,0x1caab85,0x1bd4901,0x09708d5,0x069c5ca,0x1e6f083,
|
|
0x0174218,0x05ad557,0x1ae49b8,0x1091ef2,0x0688e06 },
|
|
{ 0x13b8f64,0x17b2098,0x118b37f,0x172858e,0x0ef11b7,0x06c55ed,
|
|
0x1eddd70,0x1520cf9,0x0af4041,0x04752f8,0x14843d8,0x1b04d26,
|
|
0x0823d5b,0x13c8bd0,0x0e413f0,0x05a42b5,0x1fe45d2,0x1c2edd8,
|
|
0x14d8567,0x0bca129,0x18f2c3d,0x070e9cd,0x0baed4a,0x0959de1,
|
|
0x0a828f4,0x12a6eae,0x1c8315e,0x084135b,0x195f442,0x1a19bc7,
|
|
0x0dd5d0a,0x15266fa,0x11fa7d9,0x07edbe8,0x1027193,0x19acd41,
|
|
0x1bb817e,0x12adc7c,0x049955b,0x1c7c988,0x01723c7 } },
|
|
/* 115 */
|
|
{ { 0x08b43f3,0x0436c6e,0x19a2699,0x024c813,0x1c3e0e6,0x1a3001f,
|
|
0x110df66,0x0f63113,0x16284ec,0x142819a,0x16eba8e,0x0b88d53,
|
|
0x1c5a366,0x14bc499,0x1da5077,0x02920f7,0x1106934,0x08f6ad2,
|
|
0x12e000b,0x14f6f51,0x0a59664,0x1230768,0x180fddb,0x09d7e4e,
|
|
0x06ba31f,0x13fe1f0,0x07cb0e2,0x12d9da8,0x1db08a2,0x07bce78,
|
|
0x0d8ab06,0x19bcf47,0x119e882,0x1458364,0x14a76fd,0x0a2bcef,
|
|
0x0e947cb,0x0bc5d52,0x064e886,0x056ec61,0x084bf54 },
|
|
{ 0x164f21e,0x166d4f1,0x15fb077,0x0a025ca,0x0d6cf34,0x07c8708,
|
|
0x1a12162,0x1717448,0x1e3b104,0x1b6ed25,0x1bd5ea7,0x068dc75,
|
|
0x096bf7a,0x14193f5,0x00a67fb,0x1cd8e42,0x087da95,0x0d54cfa,
|
|
0x0b37d91,0x1f027da,0x14b824f,0x0945ea0,0x1476ecb,0x1f434c3,
|
|
0x101afca,0x0d20328,0x0a737af,0x1b3e973,0x1039e47,0x19caf20,
|
|
0x10abd06,0x18a15be,0x1e9e6ba,0x14f24f1,0x0eb8d07,0x069e426,
|
|
0x0b157f2,0x146079e,0x0054d25,0x0f7b40d,0x0383f82 } },
|
|
/* 116 */
|
|
{ { 0x183ff4c,0x03510b2,0x079cbb1,0x1295ae1,0x0e645a2,0x0650952,
|
|
0x1a73f01,0x1cbb8cd,0x09160a7,0x178947a,0x11d8ba0,0x0f62ad3,
|
|
0x07bfb22,0x0176dc7,0x031e58f,0x1ed11f0,0x00649a0,0x053ed7f,
|
|
0x1452e33,0x082ea85,0x00beb7e,0x09c36f2,0x0e83171,0x16f2662,
|
|
0x052861d,0x18df868,0x07eff81,0x12059cd,0x0e9903b,0x14ab108,
|
|
0x0e18791,0x1ee07d7,0x0ef874e,0x1bc5b7d,0x11fb757,0x15ecd12,
|
|
0x1af5ea3,0x1432a3a,0x11895bf,0x02a87f2,0x03b121f },
|
|
{ 0x19275e9,0x17423b2,0x19416c9,0x1ada1f9,0x07581cf,0x11f8f7a,
|
|
0x12ff62a,0x01cabeb,0x1e484e6,0x13df18a,0x1a63907,0x041ffd2,
|
|
0x04d8f1a,0x1d5823c,0x151b6a5,0x1b67c4b,0x175834c,0x0d2936d,
|
|
0x1422802,0x0811b31,0x08161fd,0x102dae5,0x1f0012c,0x1c977d1,
|
|
0x03bb365,0x177ad9f,0x15d66ed,0x0a19824,0x1ac737f,0x140be17,
|
|
0x06bc17e,0x1a4e72a,0x0e102d2,0x199b3cf,0x102ffb2,0x1e551ca,
|
|
0x0a6a515,0x1a237d9,0x0320d9c,0x1a26e52,0x05505e1 } },
|
|
/* 117 */
|
|
{ { 0x15e68a6,0x00a50e8,0x179430c,0x0cc9ba6,0x0f9f0b2,0x16b3fcb,
|
|
0x1d0b40e,0x1083186,0x0d2c144,0x040c607,0x068f2dd,0x02d21a8,
|
|
0x1ec5181,0x024f9f4,0x12320ff,0x1270ccb,0x0612c27,0x04d9306,
|
|
0x1b413a7,0x10df5d9,0x0758f60,0x15febe2,0x09ecb33,0x052ffb1,
|
|
0x0313390,0x164259e,0x0025c06,0x1504c9d,0x0b3762c,0x1543a84,
|
|
0x1fa7e5d,0x130751b,0x1582714,0x0cc74ae,0x19a7675,0x106a1a4,
|
|
0x0f6fd34,0x05c4e58,0x0c5f217,0x1a94ae8,0x0617d80 },
|
|
{ 0x0022b67,0x1933f38,0x052933b,0x0a6ed17,0x00536bb,0x1c22314,
|
|
0x0959b49,0x03262a7,0x0382439,0x082a6a2,0x1e31292,0x02e4bbe,
|
|
0x1a8d11e,0x0ad0f1a,0x094a9c7,0x1c63b36,0x0808171,0x103c336,
|
|
0x0ce2803,0x0a03b63,0x02360a8,0x1c673b8,0x0bb64ca,0x1b5efa0,
|
|
0x176098e,0x174d16b,0x0ee4c01,0x15dcbb5,0x1eb0363,0x04625df,
|
|
0x02febff,0x09c4367,0x17b9678,0x0703483,0x167f72a,0x02923f8,
|
|
0x0e93847,0x1127aa8,0x1e02cfd,0x010f9a2,0x05156f5 } },
|
|
/* 118 */
|
|
{ { 0x006e8d0,0x1a71101,0x1cc9608,0x08fe2b5,0x15f6f5d,0x1c4a87f,
|
|
0x1ca2758,0x1e95f56,0x17d4495,0x1762684,0x0a02a59,0x18bad1b,
|
|
0x0bad890,0x127c51b,0x0a82481,0x0b8bfc9,0x17e0f4d,0x0bccf12,
|
|
0x112578c,0x0cef5c4,0x035244c,0x19d2dc7,0x1c80e1e,0x1450f72,
|
|
0x190f475,0x17bb81b,0x170f07c,0x0912b98,0x07fa415,0x07cda0d,
|
|
0x02ee1a0,0x1601601,0x0d47458,0x039e5fe,0x00e2e99,0x1429399,
|
|
0x0c9be19,0x16afbd5,0x196e9e3,0x139666e,0x0525459 },
|
|
{ 0x01b54c4,0x1cb3cd1,0x167421c,0x156c92f,0x029ece2,0x0443200,
|
|
0x06a4b21,0x1b3e29e,0x1e9fa79,0x1246e7f,0x08236eb,0x03848d8,
|
|
0x1e14b91,0x0d71fb4,0x0c3efcb,0x17070b5,0x07ed1ed,0x18c0564,
|
|
0x02161ae,0x1fae303,0x0bd0146,0x0a2a33e,0x0843ad9,0x0cf9fdc,
|
|
0x1940816,0x1305511,0x0adcf46,0x1624b83,0x1c1cbed,0x0980440,
|
|
0x0cb79a1,0x06f8604,0x034c713,0x0468c7f,0x1c39bcf,0x078d8c0,
|
|
0x14af4e8,0x11b2dd5,0x0ad141f,0x1dbb9f0,0x022f0a7 } },
|
|
/* 119 */
|
|
{ { 0x07f1b7f,0x13c8ff5,0x0753898,0x1bb9fe1,0x1c3d8c5,0x03ee2c4,
|
|
0x0a70ce7,0x1810d85,0x14276e8,0x0d6a00b,0x1875593,0x1eb3d3f,
|
|
0x090a918,0x1554086,0x15e59c0,0x19b8971,0x0364aa5,0x175bd44,
|
|
0x1ebe9cb,0x184777c,0x0908fc4,0x0f25643,0x136ed72,0x018fcde,
|
|
0x190136a,0x0691bf1,0x0527086,0x0abae00,0x1324a28,0x1e33ca5,
|
|
0x1c791d6,0x0c50f40,0x18a8dc6,0x0191e64,0x066d7ed,0x1272b45,
|
|
0x0c0389e,0x0361f70,0x1311b86,0x0de2ce6,0x079f81e },
|
|
{ 0x04f3c4e,0x160f99b,0x052e0fc,0x0a26cfc,0x136b2ac,0x19f21ea,
|
|
0x173f164,0x1fc894d,0x110d961,0x072ca3a,0x1caab8d,0x1d9cfc7,
|
|
0x0508234,0x1ef53f9,0x04b802a,0x1424997,0x0f0a791,0x10f7dd2,
|
|
0x064b54e,0x10dfa42,0x0af6c20,0x1e5a8e4,0x1fb0343,0x01e36bf,
|
|
0x1b2cadc,0x10ca468,0x1e04b6f,0x00f4711,0x1bdd45b,0x1d356f6,
|
|
0x069021c,0x1ae04b1,0x02a1268,0x13db25e,0x0ea05f8,0x0b77edc,
|
|
0x0d386e8,0x172b31b,0x10001cf,0x06f3bcf,0x0442ecd } },
|
|
/* 120 */
|
|
{ { 0x02f90a6,0x08d7345,0x0332d33,0x1adeb5a,0x1277d41,0x0ea5c77,
|
|
0x0a31100,0x062d470,0x0d83766,0x00bd09a,0x04492fa,0x0b1bebc,
|
|
0x04142b7,0x1eb5caf,0x1ef1a77,0x13c7c4b,0x15fd74a,0x151864f,
|
|
0x02598f3,0x01e2c7b,0x186d5ac,0x1b86731,0x0caa7bb,0x1daaa88,
|
|
0x10ea5d8,0x13d3d34,0x0262250,0x1bc47fe,0x0ced585,0x1b52f55,
|
|
0x195d6b4,0x1a7c308,0x114a6c1,0x09c881a,0x0b0dfc2,0x107b22c,
|
|
0x033d56e,0x0856ecf,0x1a47970,0x0e60d54,0x085176b },
|
|
{ 0x0a21e38,0x0887d14,0x14e28c8,0x1aaee7a,0x17b6379,0x0106e24,
|
|
0x1eefcb4,0x19ba6d2,0x1961833,0x08bbac9,0x0a14596,0x0bf5cbf,
|
|
0x126d704,0x1c355ae,0x043ca69,0x0b6e067,0x030dc4f,0x15605ed,
|
|
0x1318571,0x004815b,0x0d91cca,0x01628a3,0x0387c5c,0x059df0f,
|
|
0x072d0a7,0x1d0e75a,0x002d9a6,0x09080e1,0x01aa0a8,0x07cebf3,
|
|
0x02de6c2,0x08cd2ac,0x08160be,0x15b8f1c,0x10b6523,0x184726b,
|
|
0x1431590,0x1ec1e04,0x1a2cf5f,0x176dcae,0x08ab154 } },
|
|
/* 121 */
|
|
{ { 0x13c4a96,0x030019a,0x00d4a1a,0x1120b9b,0x0e5c60e,0x137c662,
|
|
0x04d923d,0x13d7ab2,0x09faccf,0x15c05cc,0x18e796d,0x1f5dc64,
|
|
0x0bbc1c1,0x13c556f,0x18e5b48,0x0405a5e,0x0d01898,0x08053cb,
|
|
0x091d20d,0x16a91e7,0x0e3e18a,0x01d98d8,0x0b3415b,0x0c8a25b,
|
|
0x068dd01,0x1de0add,0x052c0fc,0x00706db,0x1206c52,0x0535ec7,
|
|
0x0db593b,0x13e2ef3,0x11a361e,0x19a5449,0x03f14aa,0x05b04d2,
|
|
0x12922e2,0x15dc704,0x00aa4d0,0x109c016,0x01bfcdd },
|
|
{ 0x1a365d9,0x1cd21ba,0x0c0cc42,0x1c11b1f,0x14ade15,0x016fc1e,
|
|
0x14f5f5d,0x085392e,0x0de3187,0x1b984ea,0x02b3833,0x042466c,
|
|
0x031228e,0x1bb34b2,0x10f48e3,0x0b4a620,0x1edf90f,0x1fe156d,
|
|
0x0d7e4e5,0x0c996ef,0x101041d,0x0562236,0x14802cc,0x02e41fc,
|
|
0x0642d23,0x03ae1e4,0x16e6a88,0x1980245,0x1eae47f,0x1d89020,
|
|
0x09215b8,0x0d190ed,0x1864455,0x10358a2,0x01088cd,0x1e3438f,
|
|
0x027757b,0x1b368f9,0x153c66d,0x077ef73,0x025b78a } },
|
|
/* 122 */
|
|
{ { 0x16707ce,0x1ab8c0a,0x042a420,0x108629f,0x1bdc239,0x12bedec,
|
|
0x0216a2f,0x17002f9,0x1ad63a4,0x05dd112,0x0b3ff75,0x170c2b5,
|
|
0x025ce71,0x194aa39,0x09991d5,0x1a7babe,0x1f74f0a,0x1854078,
|
|
0x10d4bb5,0x0a7147f,0x06ca010,0x02a101e,0x1e29901,0x018e769,
|
|
0x07a8833,0x00d9596,0x180b72b,0x06867dc,0x0b17c7b,0x0ce7f69,
|
|
0x11cb812,0x17ac653,0x18681a4,0x16e1bcf,0x0518dbe,0x16712f3,
|
|
0x12b7895,0x0b28644,0x073c371,0x0e0cb4a,0x070ab95 },
|
|
{ 0x1585d93,0x1c7623d,0x193919d,0x014c67f,0x0a6d361,0x10188d6,
|
|
0x055393a,0x05e43b4,0x1bd6400,0x1910c85,0x12dea6b,0x158fb23,
|
|
0x179e633,0x17341be,0x04f0c7f,0x1dd15da,0x1d71616,0x16d2503,
|
|
0x0bf3585,0x144e647,0x1694d78,0x12dd0a6,0x1019a5b,0x1eb0841,
|
|
0x154d74d,0x1e4b99b,0x189de38,0x10bca09,0x15a5c2e,0x15062ad,
|
|
0x170c156,0x1147596,0x13df538,0x0476d18,0x12d4a82,0x1cb12d5,
|
|
0x04c85dd,0x0421504,0x19afbf2,0x0f2a3bb,0x05fec9f } },
|
|
/* 123 */
|
|
{ { 0x0519f99,0x0163e7f,0x0d4d7af,0x01ca820,0x0396bd8,0x1cc479f,
|
|
0x0500a28,0x1435bdb,0x1d601bd,0x001db9a,0x1992b07,0x006c299,
|
|
0x10fd302,0x0092014,0x0dfafa4,0x012fab0,0x1a3a554,0x0e55750,
|
|
0x02e204e,0x0e7a4b6,0x10b9dce,0x15f6584,0x0d7b504,0x07b5678,
|
|
0x09ff7d6,0x038cc81,0x0418b6c,0x0aa86fb,0x04c11d5,0x17ab215,
|
|
0x0249df4,0x049f922,0x17fa645,0x092a6a3,0x06dc9e6,0x18f625d,
|
|
0x184c618,0x0957116,0x14655eb,0x0c79d1d,0x00a8d56 },
|
|
{ 0x021fde1,0x028b185,0x01250eb,0x0cd207b,0x0fcf5dd,0x0eb140e,
|
|
0x067b97f,0x068da49,0x077a49a,0x0f6e378,0x1701bd3,0x058050e,
|
|
0x0646bda,0x1a3dc02,0x18383d8,0x106dfa1,0x09b5e67,0x1082c0b,
|
|
0x1a2a010,0x032255b,0x1d32c96,0x05549d9,0x17cffa8,0x0aed78b,
|
|
0x18edb0c,0x123cf89,0x1b634df,0x12e35ad,0x05e7cb7,0x0b9ce67,
|
|
0x103aae1,0x03a4056,0x0a4b434,0x0fe9344,0x155f8e8,0x02bb084,
|
|
0x13a86f9,0x17d5ead,0x18a7e1c,0x126d548,0x095b934 } },
|
|
/* 124 */
|
|
{ { 0x1f951de,0x05380cc,0x0d16666,0x0de0b1b,0x0fade59,0x081ee9c,
|
|
0x0707bcf,0x1a69a8f,0x133b141,0x14946ae,0x1a2901b,0x100159f,
|
|
0x1d9a465,0x00e77d1,0x022b4bf,0x0e4dda2,0x121e013,0x1b25cb4,
|
|
0x1a0eee7,0x0d4d6d1,0x0544b9b,0x0e09217,0x0a7c79b,0x0cb2cd6,
|
|
0x0f6762f,0x1a0e9fc,0x1978416,0x069ba12,0x011e1ca,0x09cd0b0,
|
|
0x06f53a4,0x04a2aa8,0x0a4dc68,0x10b36f7,0x02b3208,0x08df006,
|
|
0x11d1612,0x03d70e9,0x1e9f6f7,0x0a2c435,0x02e25ef },
|
|
{ 0x18e7357,0x1e7c7ee,0x16e094c,0x11d59db,0x133ba21,0x0269561,
|
|
0x18c741e,0x1c4d1c7,0x0f2804a,0x0493f9b,0x1eb5f87,0x1a44efc,
|
|
0x0001433,0x0c3fbc5,0x10073c1,0x04f5c16,0x036aa00,0x0cefe78,
|
|
0x16691ad,0x08d9163,0x0d32c9e,0x030f944,0x0a9b792,0x114087b,
|
|
0x0da2f1b,0x1ab6eab,0x17cb42e,0x08c461c,0x1efb563,0x1b720ce,
|
|
0x1d067c2,0x043a590,0x1ec37cd,0x122d9aa,0x0e5edc3,0x047b7e0,
|
|
0x0c7ce85,0x031546d,0x1cf5bc2,0x14fc283,0x087979e } },
|
|
/* 125 */
|
|
{ { 0x11c747f,0x13d9fbf,0x0da66df,0x1b8dcc6,0x151a4c1,0x196dd00,
|
|
0x1fdc2cd,0x1fc84e7,0x0d3ee54,0x136911a,0x12b83f2,0x1c19a67,
|
|
0x0c12fc8,0x0eeb788,0x0ca14e1,0x139f24e,0x1bdf01a,0x0e4379f,
|
|
0x0db2ba4,0x04ceffc,0x0a44532,0x1997f7f,0x0e69c00,0x115e42e,
|
|
0x0a328ce,0x0fa164e,0x1bda9cc,0x004acee,0x096813c,0x19efb35,
|
|
0x0a31a1e,0x11b65db,0x14aab12,0x07f5e8c,0x116bbb1,0x05bc61b,
|
|
0x179241b,0x0911b54,0x1305b01,0x005847a,0x03ec988 },
|
|
{ 0x072f74d,0x13b0620,0x01643e7,0x1d56b28,0x078eb0d,0x1804e17,
|
|
0x1a90326,0x1cbb67b,0x038b59a,0x1f43af8,0x16a8191,0x086c569,
|
|
0x08f40eb,0x04879bc,0x1a93e48,0x15f1734,0x1afedbf,0x177f5f4,
|
|
0x019f895,0x1f2d4b3,0x0aebf87,0x11bad5b,0x079bfb4,0x1b62796,
|
|
0x0782a3f,0x1108bf9,0x19c3e89,0x02058e3,0x0c0dbe5,0x03767ea,
|
|
0x05d74ac,0x06068e5,0x17cc268,0x1f3c029,0x18acad9,0x051b7eb,
|
|
0x1a25da3,0x119f9d5,0x12450bd,0x1d1df5d,0x03e9315 } },
|
|
/* 126 */
|
|
{ { 0x19a9ea9,0x0e7d291,0x098a495,0x0017c67,0x00f3c69,0x1b215e9,
|
|
0x1ad2e72,0x030eb3d,0x000bae7,0x18b62a3,0x043e10c,0x0dabe68,
|
|
0x16874a7,0x087894d,0x0ed40ba,0x03e3824,0x1a81285,0x056e47c,
|
|
0x0d89023,0x16ec943,0x177bf57,0x0f8d403,0x045bb00,0x01bb8b8,
|
|
0x0cef21f,0x0d3ba37,0x13969a9,0x1893a8f,0x0955ba3,0x0df3837,
|
|
0x0c07857,0x168baf3,0x09c0c79,0x08843b1,0x0c21de3,0x0e224f0,
|
|
0x0c6a22d,0x0c2ee3c,0x09e4489,0x01a14d0,0x02ed02a },
|
|
{ 0x1aa2682,0x01a0b26,0x18954c1,0x16026b2,0x0e26d32,0x03384b8,
|
|
0x00d2af6,0x05c8939,0x1ee77ae,0x0d0ce95,0x1b05a44,0x053475e,
|
|
0x1439bd5,0x0e6b082,0x1329701,0x01fc26d,0x19bdc6c,0x0b1b852,
|
|
0x04f544d,0x041a4f7,0x051aca4,0x02aaa62,0x161cc35,0x19bd7e5,
|
|
0x058c996,0x102f5e9,0x02943e6,0x1963732,0x0f01510,0x04bd3d8,
|
|
0x185a6a3,0x023a42f,0x0c36d34,0x1baf416,0x0229d4b,0x03e22ed,
|
|
0x009b2a6,0x1809ca5,0x15f7476,0x08953df,0x0146278 } },
|
|
/* 127 */
|
|
{ { 0x12803cf,0x11d7691,0x1cd1af2,0x17352df,0x01e4398,0x15bc45e,
|
|
0x1d5fdd2,0x09b95ec,0x07e68c0,0x1d29f00,0x1f34830,0x1832b96,
|
|
0x0a5f969,0x0e0345e,0x02d969b,0x06065e5,0x1d31d86,0x071e500,
|
|
0x1e02385,0x0677030,0x18be9b7,0x0cf7f30,0x0d75c13,0x03728db,
|
|
0x13542b0,0x0df93b7,0x1befb77,0x00afc33,0x1275cee,0x1795c81,
|
|
0x119f460,0x1101ef7,0x0dc5f77,0x1b60a1e,0x14fde11,0x05ade07,
|
|
0x09ba507,0x0faaabd,0x058a00d,0x16d6805,0x07acb57 },
|
|
{ 0x0e6b07c,0x09ab4a2,0x1177490,0x13c38e6,0x051c4cc,0x19dcfda,
|
|
0x1136389,0x1f880e8,0x1b88e34,0x124b03c,0x09ddb7f,0x099fe2a,
|
|
0x1c77d18,0x03a114c,0x040cee7,0x0512eda,0x08477bf,0x014d053,
|
|
0x1a3c108,0x1fbe21d,0x16d659f,0x16225da,0x1385c51,0x135d0aa,
|
|
0x106c2fb,0x06ac18e,0x0f64f9f,0x059705b,0x16b607b,0x0e231e4,
|
|
0x0a20ce0,0x0ea93c5,0x0aed251,0x110ea03,0x0471dd2,0x1bdf2f1,
|
|
0x0675fbd,0x0c03e3c,0x145b2ba,0x172c6c6,0x06a5a05 } },
|
|
/* 128 */
|
|
{ { 0x08f4f33,0x18f5335,0x1d2a4b9,0x0c9bd51,0x12fc6fc,0x144230f,
|
|
0x094b3fb,0x011a6ac,0x008954d,0x0d8541f,0x0add996,0x18468d1,
|
|
0x045bd68,0x0807c68,0x0a04d5e,0x0cf5c80,0x1c052b8,0x08c0e0c,
|
|
0x01d9310,0x14a2d23,0x1d24986,0x1709aba,0x12c077e,0x06cef6f,
|
|
0x09ae559,0x18c8b93,0x151b726,0x0da2e04,0x0097c8f,0x024ce20,
|
|
0x1ee379a,0x04b3880,0x0df0032,0x14ec5bb,0x0b645f4,0x0c81235,
|
|
0x0a7ab5f,0x1a3690a,0x192329f,0x168e1d9,0x0688054 },
|
|
{ 0x1a5b86c,0x0b45528,0x091fc34,0x112aeee,0x0437e4d,0x1901949,
|
|
0x101dbc5,0x09d5d08,0x19647a5,0x13d643e,0x1588b02,0x1496080,
|
|
0x0f1e597,0x1853cf9,0x1bf971b,0x02adbdb,0x0c24d55,0x1579f78,
|
|
0x1c11f3d,0x1f609dd,0x0137917,0x0faa5b1,0x0de49e6,0x097c170,
|
|
0x0a32f31,0x18643af,0x0c3119a,0x02af8cb,0x018978e,0x08673f1,
|
|
0x0bf4a32,0x19bcb0f,0x10fc3ba,0x1bdf6dc,0x1c722e1,0x1bba65a,
|
|
0x0a8e10c,0x0191006,0x1b94ced,0x033b29e,0x00021f4 } },
|
|
/* 129 */
|
|
{ { 0x1519d26,0x0891621,0x0114864,0x1a814a3,0x1dafac1,0x05dc4fd,
|
|
0x1c7a552,0x1f398de,0x016844b,0x1799bae,0x1a35567,0x1ef22f1,
|
|
0x05e7789,0x0fc5f0e,0x1d666d8,0x1bc8009,0x19a2cbb,0x0c04464,
|
|
0x04c81b2,0x1344c11,0x0851893,0x1ffe698,0x086b92f,0x11fd5fd,
|
|
0x0b3fee0,0x15e3326,0x07fc52a,0x03e7013,0x041ef96,0x0a66154,
|
|
0x0d8360e,0x02fe03b,0x1fad8ad,0x1dbb9ba,0x15d9b7a,0x04df868,
|
|
0x0425251,0x18b582d,0x1b67c79,0x10053c3,0x0798558 },
|
|
{ 0x1106473,0x19d554a,0x08128b2,0x02b4c3b,0x15fafa4,0x0ab1e04,
|
|
0x04d894e,0x10ffa79,0x195312b,0x1524048,0x0171dae,0x0b057f1,
|
|
0x156c7e7,0x11863c6,0x1db6ad8,0x0881ae1,0x11c7747,0x1467182,
|
|
0x1f6d861,0x1d7a29f,0x00966db,0x1d0c872,0x0c38107,0x1cc5c55,
|
|
0x0c4666e,0x1eb5d08,0x09d3ccc,0x07aafc5,0x1b9b669,0x16e27f3,
|
|
0x1f401aa,0x00da506,0x0f72f6c,0x1a0f57d,0x179a441,0x0e63198,
|
|
0x0569247,0x081304b,0x0c23671,0x1863a1f,0x095d823 } },
|
|
/* 130 */
|
|
{ { 0x00528a5,0x15ec30a,0x0f21abb,0x14a72f3,0x1268c2b,0x00a255f,
|
|
0x06e293b,0x1db6379,0x182a7d7,0x17d5d86,0x0463607,0x01a29c0,
|
|
0x0ef12c7,0x10e0aac,0x181c5a2,0x1ce7c62,0x0b7e4b7,0x099f214,
|
|
0x0ebb277,0x0ecc6f0,0x035c631,0x1f70956,0x145cbfe,0x02f6548,
|
|
0x10bfbbc,0x0951bef,0x01d07e0,0x0425f0e,0x088f9c4,0x05edf14,
|
|
0x174f73b,0x0ead94a,0x1dc15aa,0x14720d4,0x03b2e40,0x07e6323,
|
|
0x0aeadb0,0x0f0142b,0x13d51fb,0x1aaf0ca,0x00e2708 },
|
|
{ 0x1e20f88,0x06629e6,0x00e489c,0x18beb62,0x1338272,0x058edfc,
|
|
0x1867977,0x182a085,0x1b72d74,0x19ef10c,0x0aa9552,0x1516555,
|
|
0x0616c49,0x1dd435d,0x0110f96,0x02d2a01,0x17220cf,0x0f735e6,
|
|
0x026af44,0x1f58d75,0x039d59f,0x1df88ab,0x0a0c485,0x09974a4,
|
|
0x08af2f3,0x0837269,0x1c1c9ea,0x04fe07c,0x017766f,0x03cfb48,
|
|
0x0f9a10b,0x0f50224,0x13469bd,0x0b9dc65,0x0d1a90a,0x1a9181e,
|
|
0x03990db,0x0bc2531,0x059e3f1,0x077f653,0x00d3dab } },
|
|
/* 131 */
|
|
{ { 0x029c3cc,0x1bb7367,0x0f1a3e0,0x19e02d9,0x0b0507e,0x1ca670e,
|
|
0x1e65978,0x083bd7f,0x173c50d,0x07e2937,0x1b38f49,0x14a85a2,
|
|
0x014edd5,0x08e098a,0x0def766,0x10c0d76,0x0f2e33a,0x071a217,
|
|
0x018a76a,0x12066f8,0x13312ae,0x122c955,0x15febb1,0x0570af6,
|
|
0x18997d8,0x0bb0d49,0x068cdcc,0x1ad9197,0x06751fa,0x0ef1484,
|
|
0x05a0965,0x03182e3,0x01e97fb,0x0b9abd4,0x084efda,0x13c9e91,
|
|
0x1cb89f6,0x1c3e172,0x0d09a84,0x1d6b0e9,0x0530b4e },
|
|
{ 0x0b7b5ae,0x13ad0dd,0x0fd3a7c,0x1a074af,0x1b69dc4,0x0e282dd,
|
|
0x1712a91,0x00592e9,0x1416ac4,0x131b4f9,0x061771c,0x1cf15db,
|
|
0x01735e4,0x06ea235,0x12361e7,0x160540a,0x0699e16,0x1426758,
|
|
0x026c469,0x1edf48f,0x0784f73,0x0fd9527,0x1aa8310,0x1536d2e,
|
|
0x1690293,0x15958fb,0x03c0ea2,0x02999c0,0x0d66c18,0x12adc22,
|
|
0x005932c,0x0612a44,0x194e7d6,0x19138db,0x1390f68,0x13c0a5a,
|
|
0x08b6a4d,0x1c59738,0x15dfd49,0x0a5018c,0x0909425 } },
|
|
/* 132 */
|
|
{ { 0x15b4c2f,0x0d0a686,0x127349a,0x16b914c,0x0b8fc59,0x11bea51,
|
|
0x12ceac3,0x0fd2b7d,0x0911103,0x0d0d3b4,0x0d4c8bf,0x00b529c,
|
|
0x1c5810e,0x10bc7d7,0x137304a,0x19cc544,0x1b28e3d,0x02e1631,
|
|
0x114b111,0x187e2f2,0x1161995,0x01a16a2,0x0d4cc3b,0x1df0252,
|
|
0x1a60ab4,0x009d012,0x0a2eba7,0x0a9264a,0x03caf88,0x1303717,
|
|
0x11c9746,0x06c937e,0x04091ab,0x162f8ea,0x1efdc13,0x078fa15,
|
|
0x1d8b333,0x1e8eb15,0x05bd49e,0x0239fcc,0x0505701 },
|
|
{ 0x134356b,0x025677a,0x1ef3402,0x0a96961,0x1df1de0,0x1026e0c,
|
|
0x1f8173b,0x1c20435,0x0361b78,0x05ef344,0x034e2d9,0x198fdef,
|
|
0x0ea324f,0x15852f2,0x0cdcb3b,0x0332dfd,0x0b36581,0x177827e,
|
|
0x1ac2ad3,0x1cbaa0b,0x186e7dc,0x0411c62,0x078a6d6,0x1b0006e,
|
|
0x03197bc,0x0e7ef2f,0x05201ae,0x17ebc8a,0x0e67ab8,0x0b45e8c,
|
|
0x0b50cc2,0x1f3ec7f,0x0a7d04e,0x0c5da13,0x048ed70,0x19438fe,
|
|
0x05dce22,0x0dc2411,0x19e7d21,0x0dfaa81,0x08ff0b3 } },
|
|
/* 133 */
|
|
{ { 0x1f42cff,0x1717a1f,0x05f267c,0x1a386a6,0x03c19f9,0x10daa2d,
|
|
0x04e4aae,0x065b6e9,0x14afa9a,0x0119582,0x1350da1,0x1a8dafb,
|
|
0x150b855,0x02e7cc8,0x10d7881,0x1443115,0x0c7f001,0x0ebe791,
|
|
0x15020c1,0x1a6b5dd,0x0fcd057,0x0caa9e6,0x0969294,0x1c57272,
|
|
0x0579393,0x013af2b,0x00d08bb,0x0406656,0x053958a,0x002f1d6,
|
|
0x18e6c24,0x0f3d362,0x08051a3,0x10c6b31,0x1027f19,0x1f6941b,
|
|
0x0748e7a,0x0742bfb,0x158fa78,0x1dd8aef,0x071b28e },
|
|
{ 0x1726bf8,0x15866cc,0x1cf1250,0x1238411,0x1290a3b,0x0cc7550,
|
|
0x0439ec1,0x051fae5,0x1a25a91,0x153bc8f,0x1f5f6b1,0x1649806,
|
|
0x1b2d33d,0x187141b,0x07bfac1,0x1c54184,0x16ee3da,0x1dfb86c,
|
|
0x141d809,0x1b03230,0x17e343e,0x1426a56,0x12bac2a,0x18b6e98,
|
|
0x1101fe8,0x1eede3a,0x1ab49ba,0x17f654d,0x18aa4ed,0x103435b,
|
|
0x122ea04,0x1c22b30,0x14aa8f2,0x12e2764,0x076cfae,0x141a21b,
|
|
0x0318295,0x1ff623b,0x0496b39,0x034661b,0x0729471 } },
|
|
/* 134 */
|
|
{ { 0x0bbd495,0x02c8219,0x1cfff39,0x037ca92,0x130f4dd,0x0e1fa71,
|
|
0x1b87576,0x00800d7,0x059ba72,0x077303c,0x0b1da10,0x1a7e858,
|
|
0x1ec194f,0x14ff445,0x19dac4b,0x0042141,0x1dbec2b,0x18be6ee,
|
|
0x02047b1,0x1a86d60,0x09e4689,0x1b9425f,0x09a9ae8,0x0fa8229,
|
|
0x195b200,0x1a255e1,0x0c3c479,0x119bf3e,0x196402f,0x1f64749,
|
|
0x01717fa,0x1dd68c5,0x0751743,0x0689bc5,0x1e0b1b8,0x07337f0,
|
|
0x1eb292e,0x12f0b85,0x1f57ce5,0x1b0b003,0x0001c39 },
|
|
{ 0x04a0912,0x02e5ced,0x1293d20,0x1488217,0x127cb76,0x18eb2de,
|
|
0x12e3bb1,0x135de7b,0x1481684,0x007dd95,0x0918d5e,0x004d516,
|
|
0x08ef6a7,0x0962273,0x1897220,0x0e9502a,0x12c4d7a,0x0312611,
|
|
0x0c58c79,0x0ee06e9,0x1c2e81a,0x18edc8b,0x01393df,0x0c3db2a,
|
|
0x065fd1f,0x11e8e82,0x072f79b,0x0209009,0x131fcfb,0x1060eb8,
|
|
0x0558df3,0x115b48e,0x0e4dbc2,0x0cb9311,0x1172b3a,0x01eea61,
|
|
0x0e28745,0x0b06e67,0x0bc4e80,0x0e17723,0x09132e6 } },
|
|
/* 135 */
|
|
{ { 0x196099d,0x1f7f13c,0x0232015,0x1740dcc,0x172344d,0x0ac2c45,
|
|
0x01d0342,0x1d3d695,0x079e5ae,0x09ed783,0x08beb79,0x1535211,
|
|
0x0ac9560,0x083f383,0x12f84c4,0x048d4fe,0x19b2830,0x136af9e,
|
|
0x1f328f9,0x11d1b44,0x1292a5f,0x1326147,0x1ad4772,0x03bfaf1,
|
|
0x0310ef3,0x1f2a67d,0x08b281c,0x05c18f8,0x0da6839,0x0b4a520,
|
|
0x1f040bc,0x0ea1a71,0x0bb07cc,0x1701a8b,0x0f8aeb6,0x1ae07d0,
|
|
0x14d3c9d,0x09e0335,0x03b47aa,0x1caf328,0x07d0b03 },
|
|
{ 0x1d94c63,0x1f51826,0x0ce97f9,0x0ae7161,0x17ef01c,0x0735a5a,
|
|
0x09e3285,0x0ed2a69,0x0a53532,0x1b1166f,0x0b40181,0x140ef84,
|
|
0x09af696,0x1ea3590,0x0f06219,0x05694e6,0x0bb626c,0x04b2a66,
|
|
0x013cf13,0x11a7435,0x0b74a09,0x1696b9a,0x0d65be7,0x0aa3920,
|
|
0x1021a5d,0x11fefe9,0x1c7b144,0x0574fa5,0x01aa39e,0x1492d96,
|
|
0x09fe5c9,0x1f1d652,0x0e75d0e,0x09537e9,0x04b8646,0x1df574e,
|
|
0x1b83e50,0x035a1d4,0x1798298,0x05fb56b,0x031b178 } },
|
|
/* 136 */
|
|
{ { 0x034db92,0x0dd22a0,0x11361e3,0x031e69b,0x0397790,0x1aa619d,
|
|
0x13cbb7d,0x1111a00,0x0cd563a,0x152caa5,0x1feb47a,0x191376b,
|
|
0x18a29d6,0x186c5ed,0x0b7d956,0x1b68f51,0x02d8cdb,0x1fbfdc2,
|
|
0x034c816,0x1c74070,0x1ca9b72,0x193e563,0x10cd6c2,0x14a8ebb,
|
|
0x00bcbd8,0x12fffe3,0x07ae934,0x06deee3,0x10fca67,0x0e1c062,
|
|
0x000f640,0x1018032,0x1dacf7b,0x0fc268f,0x163d5a0,0x02eb9ec,
|
|
0x1cefbbc,0x13f31a2,0x1b47d5e,0x1ca7c0f,0x06fc0fb },
|
|
{ 0x01b0e5f,0x088b5dc,0x0ee125b,0x0a5590a,0x182dd2a,0x19c3f86,
|
|
0x08b50c9,0x0b26afc,0x0ba912c,0x1199542,0x177304f,0x0c8693a,
|
|
0x138b71c,0x01c6c2e,0x060bba5,0x19a9c19,0x13cbf7f,0x1c85caa,
|
|
0x03fb578,0x0737787,0x09032cb,0x0e2d621,0x08b19f2,0x00fb4ab,
|
|
0x01217bf,0x07775f9,0x1682e79,0x0b580b5,0x09e0c65,0x0961477,
|
|
0x0fc42ec,0x09176dc,0x0f3aee5,0x03748ae,0x1a722c1,0x1e95ce4,
|
|
0x0a0e553,0x1330095,0x03f232c,0x1435299,0x0701935 } },
|
|
/* 137 */
|
|
{ { 0x0626dea,0x06a0ed2,0x0e7f796,0x142b720,0x05ef66c,0x12732d9,
|
|
0x04290c5,0x19f3350,0x1748cfc,0x1f36d56,0x10bea67,0x0d7a5e2,
|
|
0x167ab9a,0x0ea38bc,0x12e85a1,0x1473749,0x1366bc3,0x1096985,
|
|
0x0fd141d,0x0d4bb91,0x0c0e1f4,0x148a10d,0x0e1a394,0x1774389,
|
|
0x0620659,0x1c83d34,0x1b69a62,0x1696aa5,0x0537072,0x0e6a72a,
|
|
0x17d40e7,0x13d202c,0x0a07a9e,0x02efe21,0x1fcf5f5,0x015071f,
|
|
0x1b5ceb3,0x0c8f2d1,0x0980106,0x1912d39,0x06c961e },
|
|
{ 0x0e7eb46,0x1ee0de2,0x0d21c0e,0x0eb2d8f,0x16bac55,0x17eba6e,
|
|
0x05f359a,0x1e69f32,0x1656ce6,0x11aa882,0x05c5d55,0x0a18649,
|
|
0x0d3d1fb,0x11f7fd9,0x099e0f9,0x1457bfb,0x1f3eefa,0x1debcf8,
|
|
0x1ebe7bd,0x1f7ca82,0x17a4a4e,0x112d2ad,0x1b3bd91,0x0e26608,
|
|
0x132381a,0x0d188b7,0x1ee5589,0x165454f,0x027e96d,0x121d058,
|
|
0x0f1a82a,0x0906567,0x18fe5d2,0x1d56022,0x037d6b7,0x14a4683,
|
|
0x049e7f9,0x0d44e5e,0x12d4f01,0x1b0d3c4,0x0830883 } },
|
|
/* 138 */
|
|
{ { 0x0557389,0x18e3101,0x02f2566,0x0f5bdf8,0x1fe5ce9,0x1879c1a,
|
|
0x0f9fe0c,0x03d1277,0x116cfb8,0x1f06357,0x10a3f49,0x0cb7a08,
|
|
0x026f64e,0x1bcf30c,0x17a4916,0x02394a7,0x1c1487e,0x1845189,
|
|
0x116f3a4,0x1d87728,0x149e65c,0x0a6b3f6,0x0cef00c,0x0f046a4,
|
|
0x16b2430,0x0e934f9,0x1e4eb4c,0x0f1cbb5,0x00890cd,0x15b863c,
|
|
0x1a7c9a0,0x13c8bdf,0x015c34f,0x1d7f538,0x0e939b2,0x1826ba9,
|
|
0x1e3fcc6,0x11bc523,0x03e310e,0x0ff2cc7,0x02376f9 },
|
|
{ 0x0575b99,0x10f6057,0x037029b,0x1f0372e,0x1e14cb4,0x139ca3b,
|
|
0x0e0934e,0x13be014,0x1fb235a,0x1a5ce40,0x18a5102,0x02beb7e,
|
|
0x1a8d151,0x0f0b2eb,0x14d6d0c,0x07c779f,0x0a2b2ee,0x1ae897f,
|
|
0x1460b9e,0x13094de,0x108e629,0x19e1b2e,0x1390f8b,0x1e6dce4,
|
|
0x0709130,0x000cc99,0x03f4d15,0x1316940,0x196dce6,0x1e875d7,
|
|
0x1508f13,0x046ceaa,0x00ba0ae,0x12bc253,0x10b6c0c,0x02a37b5,
|
|
0x015464a,0x1a0c851,0x00a5a2a,0x0c2d7e2,0x08c4616 } },
|
|
/* 139 */
|
|
{ { 0x11f36a5,0x0512c16,0x1cb7bff,0x051298b,0x0eded2b,0x076c278,
|
|
0x136e10f,0x1366b4b,0x0db0e3b,0x087c4c1,0x068448a,0x15e00e3,
|
|
0x16cce0e,0x1cd1b16,0x1995f90,0x0fc8fa1,0x15d6269,0x02a8b52,
|
|
0x198d945,0x1c3eef1,0x09bc269,0x05ea813,0x178f7b7,0x038af8a,
|
|
0x0230044,0x1c6f676,0x131c155,0x1707e63,0x089eabd,0x1db98f2,
|
|
0x0d06f7b,0x072bf9b,0x0b678cf,0x0d80090,0x0473fe7,0x112119f,
|
|
0x15f52cc,0x15e37a2,0x0458b2f,0x045698c,0x0155ea6 },
|
|
{ 0x16fa42e,0x1178fc3,0x1b9e52f,0x12ff5bd,0x0b5e874,0x0432d7d,
|
|
0x1c3d4e3,0x160d25c,0x0df8059,0x174cdc2,0x09eb245,0x00dd16b,
|
|
0x0b0ceb6,0x16a31e9,0x148cd5c,0x013419d,0x0232a9a,0x1968793,
|
|
0x0187ef7,0x1333187,0x110b252,0x13e0df1,0x1c46222,0x1155bc6,
|
|
0x029c50d,0x19ecd89,0x00ec4d4,0x179f36f,0x029708d,0x037c7f8,
|
|
0x020f29d,0x1b507df,0x1a013a1,0x1422252,0x14612ac,0x151d209,
|
|
0x1cbd4ab,0x14259ed,0x1630cbf,0x0484b20,0x08f570f } },
|
|
/* 140 */
|
|
{ { 0x0a9c508,0x1364516,0x1e037ad,0x04d3ad6,0x0dc5bec,0x156b001,
|
|
0x0499a23,0x0282dac,0x149d726,0x0c20dcb,0x1cb9bd8,0x1cd99c8,
|
|
0x1641e40,0x0fd3d43,0x0890990,0x12f415b,0x133cc39,0x022dcfe,
|
|
0x105773d,0x1d1f52f,0x029db25,0x190974b,0x004933a,0x167b2ac,
|
|
0x072c67d,0x0221d46,0x0df069e,0x1c5bda5,0x1027ff8,0x04e336e,
|
|
0x11a52ac,0x0fcf457,0x09a057d,0x063b1fc,0x089b3dc,0x055b17e,
|
|
0x08a2621,0x193473e,0x1307532,0x10f6588,0x03d171e },
|
|
{ 0x0e49820,0x160b746,0x1724e0a,0x0581889,0x04ee45e,0x142c621,
|
|
0x1e449cf,0x1f21d8c,0x046327c,0x0c6592e,0x16707e4,0x0ed78c2,
|
|
0x1343e38,0x1baa2e5,0x0db8380,0x068fd6d,0x1ab5d12,0x0b25c1c,
|
|
0x0c03550,0x0124e94,0x116972e,0x13440e0,0x09aaca3,0x0eb5086,
|
|
0x00fffeb,0x06fa52c,0x08d6448,0x14b0059,0x09f4a30,0x0168190,
|
|
0x001ffba,0x11cd527,0x118016b,0x108e55a,0x11c30bb,0x0f7338d,
|
|
0x0b9d4ec,0x082d78d,0x0401058,0x1f0699b,0x0234e98 } },
|
|
/* 141 */
|
|
{ { 0x0db9cda,0x1a9040a,0x1243fd0,0x0f2d5bd,0x19cfdc4,0x02c5b6c,
|
|
0x0a9bebd,0x0630875,0x1743eaa,0x18fba0a,0x0d7604f,0x125cc2e,
|
|
0x15915e1,0x0562cae,0x10688b4,0x1791a68,0x167c044,0x13825df,
|
|
0x188e88d,0x0c08e37,0x15572f9,0x040ae8e,0x130c98e,0x163bb29,
|
|
0x0230b76,0x133ca08,0x1c30722,0x05ca873,0x1c910df,0x00d6419,
|
|
0x17d5ac5,0x10cb709,0x07c999f,0x015bda3,0x07e887c,0x003604a,
|
|
0x1621695,0x0da9304,0x07a4f79,0x1c79c74,0x06a2130 },
|
|
{ 0x13ca1a7,0x1b3d025,0x1a03486,0x0601819,0x0f42ed5,0x16783d5,
|
|
0x14da24c,0x0b44599,0x15c25c3,0x1291d40,0x013418d,0x12b11ba,
|
|
0x1becdd3,0x197c9d1,0x168d40a,0x16a60e7,0x03cd5e5,0x1a62f06,
|
|
0x0c9a1dd,0x1ea90c2,0x0292ef9,0x1e0f3a1,0x1b61ffb,0x09cbdbd,
|
|
0x0c29ea2,0x18d36cd,0x00ce127,0x115793e,0x1239050,0x1149207,
|
|
0x14ec26c,0x0ff2686,0x191072c,0x15aa833,0x0e079ab,0x002054c,
|
|
0x16feb87,0x103a04c,0x0a0c0fb,0x155389a,0x034f06f } },
|
|
/* 142 */
|
|
{ { 0x148f005,0x0e3cf91,0x02c61a7,0x03be924,0x1b5c5d7,0x1732524,
|
|
0x15f29b7,0x169fa36,0x0e82a4f,0x0dbfb9a,0x1e0d988,0x106972a,
|
|
0x16637cb,0x1e943ec,0x0d0406d,0x1d95792,0x0ac0392,0x18ac87c,
|
|
0x1dd7d38,0x1b86e6f,0x0c62280,0x07b530d,0x02cdbd4,0x0aad1b5,
|
|
0x18304a6,0x1853a7a,0x0764c21,0x01af255,0x0895cc8,0x18c97e4,
|
|
0x07db45e,0x0922927,0x18392fa,0x0adcf24,0x09f7507,0x0b5e6c0,
|
|
0x1caa82b,0x16bcf12,0x1746914,0x163e822,0x0764d47 },
|
|
{ 0x0ee8b9c,0x11181d1,0x152177c,0x070bbf9,0x1b9f72d,0x009d1b8,
|
|
0x0e60c42,0x1ead685,0x13de741,0x146291d,0x0eed6f8,0x04b5e60,
|
|
0x0f08576,0x164dfcd,0x1bca66a,0x0b66924,0x0080d44,0x110df56,
|
|
0x1ae8b03,0x047405a,0x08646a5,0x18bfe71,0x18c0a86,0x00183d5,
|
|
0x0a235e3,0x188a28b,0x09ed2a4,0x0a86e6d,0x0c89f74,0x1cf4606,
|
|
0x17b4f02,0x081db11,0x081904f,0x1fe3802,0x0d58f2d,0x109e4d3,
|
|
0x121b973,0x10ea9d1,0x0e04026,0x1864614,0x01c0dd9 } },
|
|
/* 143 */
|
|
{ { 0x06a7d9a,0x10fb3e2,0x0733fea,0x097dbf2,0x0474333,0x1217973,
|
|
0x0e9d11e,0x1528b06,0x1241ffa,0x1cc0028,0x1bf9ad9,0x150866b,
|
|
0x0370979,0x1845920,0x0184fd7,0x023b8be,0x1cd64f2,0x035d917,
|
|
0x015cb3f,0x1165474,0x014ae1b,0x00bca85,0x06783ad,0x16d9a98,
|
|
0x0bb293e,0x0fff31a,0x151c289,0x0340964,0x115a0a3,0x1d64d1e,
|
|
0x1a6907d,0x17e5fdb,0x1ed85ec,0x0a50077,0x1d7e06e,0x183eb03,
|
|
0x1ef4a15,0x1ccb584,0x106f2a8,0x07360c0,0x052d8be },
|
|
{ 0x1631a2f,0x09b7b7e,0x0372f45,0x0166a35,0x11fae7f,0x0931094,
|
|
0x0431e6c,0x06ba34b,0x12bd0f4,0x16a43af,0x03a9c14,0x0da7256,
|
|
0x1e9aedb,0x1c1d5c4,0x142af72,0x0325817,0x06289fe,0x1413d08,
|
|
0x00a82f6,0x0d52c02,0x0814656,0x1be701b,0x16820c0,0x0c7280b,
|
|
0x0d79f58,0x0fc985f,0x1b6f2a3,0x0e40336,0x1aa3f59,0x094377e,
|
|
0x04a2480,0x0a46d71,0x137b996,0x01739d9,0x0e38a3f,0x0623a7c,
|
|
0x080e8da,0x1c3fa0c,0x09175c1,0x0cfb5c9,0x06cff63 } },
|
|
/* 144 */
|
|
{ { 0x09a8bb4,0x08219fc,0x1dc6f4f,0x0727731,0x02144c3,0x038516a,
|
|
0x05b200d,0x13d056c,0x1e5da08,0x07e63ab,0x17f69a6,0x09def7e,
|
|
0x0c54235,0x0f5e9a6,0x017094e,0x1ba1a31,0x085bec5,0x1171059,
|
|
0x00a86f2,0x1777c2f,0x0ef0e71,0x184dc2a,0x05677b4,0x12ff4d5,
|
|
0x0997989,0x0228b92,0x03607cf,0x019f1f5,0x0111525,0x1a8bb06,
|
|
0x1aaa68e,0x1d9f08b,0x1b0ef7d,0x1688de4,0x188ee7f,0x0192673,
|
|
0x0825608,0x1f4e2e1,0x1079f24,0x02ec27d,0x01d2c82 },
|
|
{ 0x07cfc93,0x09a3ecc,0x0041ce0,0x17e30ff,0x047603b,0x0865188,
|
|
0x0f27449,0x1e67f4d,0x0bb055b,0x00048f0,0x0be1f12,0x1e34747,
|
|
0x0bbdf95,0x0a02a05,0x1a1ddc0,0x008b7c4,0x130d7fe,0x0ccc6fb,
|
|
0x1c8ef0b,0x1026bf6,0x0c46b39,0x060af5f,0x0b08c3e,0x0aac381,
|
|
0x018305f,0x03ff047,0x1369829,0x181f7e9,0x0d4bfc7,0x0e1270b,
|
|
0x0481ba5,0x0e8c2fd,0x0163495,0x061073a,0x01a52b8,0x0c72e33,
|
|
0x0131e2b,0x1349891,0x1dc8bf8,0x06c14a6,0x025486e } },
|
|
/* 145 */
|
|
{ { 0x1572806,0x1cae529,0x0385861,0x12cad2d,0x12c8944,0x1991d75,
|
|
0x0b25cfe,0x1ac2938,0x0409bc7,0x18aef13,0x0486cfe,0x14e58f2,
|
|
0x1ba90cd,0x102655d,0x0be8538,0x0824ada,0x0f79160,0x1e5e6d3,
|
|
0x10d7e51,0x10c4c36,0x0b10250,0x1c61417,0x16da1b0,0x14f2397,
|
|
0x16d62f1,0x1362880,0x0586889,0x1638fda,0x1d74a66,0x0333138,
|
|
0x09099e0,0x104850f,0x1ffeda1,0x07879da,0x0ffeef9,0x0997ca0,
|
|
0x19482a7,0x1bf85f5,0x04fc75f,0x0b01109,0x0751b23 },
|
|
{ 0x1c9be68,0x1dceb74,0x11b3565,0x08cfa21,0x1794b5c,0x11597a0,
|
|
0x170f5dd,0x0235119,0x0a1b44e,0x0ca531d,0x03b2a1b,0x1773555,
|
|
0x1ffb0bb,0x04b1ec3,0x0c3cb43,0x00ebbe9,0x02c5dc7,0x0dba983,
|
|
0x064ce62,0x0e4d589,0x0cdefed,0x1c2bfce,0x1769818,0x1f18ecc,
|
|
0x0392a75,0x165110e,0x157719c,0x1a4c9b2,0x0ecc8dc,0x1f915b3,
|
|
0x0e9c013,0x03148b1,0x11aa9ae,0x1eb29fd,0x137e2ea,0x19d52c8,
|
|
0x0ba0de7,0x1bc7401,0x1b1d6a4,0x05b9458,0x0144cc1 } },
|
|
/* 146 */
|
|
{ { 0x189aa3a,0x1050e94,0x193564e,0x06b3cdc,0x183f228,0x1739976,
|
|
0x0c32f4c,0x093d271,0x13c3cb2,0x0623262,0x1a9ab3d,0x0bf1f13,
|
|
0x129750a,0x1a367e1,0x1f96efc,0x170128c,0x19d37b2,0x0e4dfd5,
|
|
0x0cce71b,0x16e8a67,0x0deef8e,0x1f1dbb3,0x0ff807e,0x0d5d44e,
|
|
0x14254ef,0x188598a,0x09ef986,0x0ab87be,0x0184885,0x16c0eec,
|
|
0x1e5c3ed,0x177ce29,0x01af3a4,0x07b49ed,0x005e746,0x12aebe4,
|
|
0x0465b83,0x047e359,0x0a54770,0x066d709,0x0874ecf },
|
|
{ 0x1b3f6be,0x17c1f5d,0x08f5892,0x1211768,0x1578fbb,0x039a93f,
|
|
0x0c2eb5e,0x084ac47,0x0a62e04,0x1b2cdec,0x0dbde70,0x02cffc4,
|
|
0x062903b,0x129f935,0x090c31b,0x0259eab,0x1ae3ad7,0x19112a3,
|
|
0x1bac9ca,0x1121aee,0x0df9b73,0x059eb14,0x056d3dc,0x1d5c959,
|
|
0x013b053,0x1a74f87,0x039fc85,0x169ea27,0x1bae175,0x167ccc6,
|
|
0x001d520,0x088a309,0x169bbde,0x178ae15,0x194b2bf,0x129e4f2,
|
|
0x16bcaf1,0x11f795d,0x18d3e82,0x1039c98,0x031fb85 } },
|
|
/* 147 */
|
|
{ { 0x15cd607,0x18368b0,0x0e98e60,0x1554658,0x080c9fa,0x1c898eb,
|
|
0x1c16ddd,0x001d0f4,0x036708b,0x018809d,0x14a5fc4,0x01c3288,
|
|
0x16814fa,0x1353cda,0x11560ea,0x17da8e1,0x0bf4b16,0x18181ce,
|
|
0x0aabe34,0x0f951b5,0x08a518a,0x13ae6db,0x1ccc567,0x07029f5,
|
|
0x0e738d2,0x1cfef50,0x02343d3,0x166a4e3,0x1ff032e,0x1304ee6,
|
|
0x02ec2dd,0x07a9067,0x1ba8ea9,0x0a83d32,0x1609577,0x0830089,
|
|
0x0a4a50b,0x05111f2,0x0795211,0x00031c3,0x0983230 },
|
|
{ 0x1f3d5a6,0x10813ab,0x1734a28,0x10dd195,0x1fce564,0x0a8f9df,
|
|
0x0e06c09,0x1e32b20,0x1935ebd,0x1366327,0x0ea9bac,0x0523810,
|
|
0x0160611,0x047267a,0x062299a,0x1636b9b,0x173dd53,0x0ac0e1f,
|
|
0x1ff1887,0x100952e,0x02fa78c,0x187d6e5,0x0c61d0c,0x0799e04,
|
|
0x08da4c8,0x183fb80,0x169e691,0x0824543,0x115eb5c,0x069fa54,
|
|
0x1826a38,0x1a0246c,0x0de157d,0x1695051,0x0ec997a,0x0a8bde8,
|
|
0x188db28,0x11156f0,0x032ab42,0x13d245c,0x08abbe3 } },
|
|
/* 148 */
|
|
{ { 0x02d2f01,0x034829d,0x0172d11,0x06bb8cd,0x127c319,0x1a5013e,
|
|
0x02efc75,0x03ad521,0x15b50ec,0x0ed1a87,0x10b8980,0x08bc7e7,
|
|
0x121d3dd,0x1c1b774,0x1b84742,0x12f39ec,0x08f474b,0x03f01c8,
|
|
0x02e1e0d,0x0f8b733,0x1de919e,0x1f5e9e8,0x09d074f,0x1ec0b37,
|
|
0x08e8d1e,0x123b1e3,0x04d9d38,0x173ff27,0x1e67f69,0x09f39f3,
|
|
0x12075f5,0x15dd3c4,0x18dc326,0x0cc2634,0x1b6acef,0x0ea5e47,
|
|
0x0f8fe8a,0x0f18d83,0x0ea57e5,0x1a187a1,0x00f15b4 },
|
|
{ 0x10a8d85,0x1b31abc,0x0bc63cb,0x1dc4b2b,0x11bffba,0x1a8943a,
|
|
0x1fb1892,0x0bba2b6,0x1323471,0x11cdb55,0x151075d,0x0532578,
|
|
0x130cdd5,0x1b682c1,0x0003a93,0x1c6c0a9,0x152f6d6,0x190f7eb,
|
|
0x04a4184,0x0fffca3,0x18cdc0b,0x12f7544,0x0da2960,0x13044cd,
|
|
0x1ba9222,0x1d97676,0x02ef41a,0x0f15236,0x16b0cb6,0x16e025d,
|
|
0x062c90d,0x195f1d5,0x17a99e7,0x102dde7,0x19b9c6a,0x03725a1,
|
|
0x15993eb,0x068238f,0x1776efe,0x0f04070,0x0515db3 } },
|
|
/* 149 */
|
|
{ { 0x15bef22,0x1f55537,0x1c4bb90,0x1040690,0x152d269,0x1d7b634,
|
|
0x12139e8,0x0063c98,0x09a8c94,0x06a1a63,0x0626686,0x0e82a00,
|
|
0x0c63e5d,0x1f47520,0x0e36ef3,0x10e42a4,0x0d29679,0x0653664,
|
|
0x12b2f7a,0x16d5dc0,0x13ce73d,0x06dbfcc,0x0fda4ca,0x08bc669,
|
|
0x19bbfad,0x11851fb,0x0df07c5,0x18a3d92,0x00a6de8,0x192fcd8,
|
|
0x10d241c,0x025b057,0x1e6acb4,0x0cfe4a4,0x0db43b1,0x16b2036,
|
|
0x1cf34e3,0x04db884,0x1300b2c,0x0fc357e,0x02de048 },
|
|
{ 0x1d9d484,0x19179c6,0x0b3062d,0x06f8ef7,0x0334939,0x0c95c54,
|
|
0x0e3c64f,0x04ab1b7,0x08e3fac,0x06bc6a8,0x1d29f60,0x1302e8b,
|
|
0x1df0500,0x03be614,0x1caffb6,0x113f1a0,0x0f2c30a,0x1b3d5fc,
|
|
0x0820835,0x0acfd53,0x173892c,0x17451d2,0x1096ac4,0x0aaa436,
|
|
0x0faebf0,0x0f4e0b1,0x1ae53a9,0x1c389e4,0x11e546e,0x04ca1eb,
|
|
0x0747905,0x087d17c,0x18183b8,0x1570592,0x120bbe7,0x008922f,
|
|
0x13874a3,0x09d22bb,0x1e1b9a0,0x0e39885,0x06f6ac0 } },
|
|
/* 150 */
|
|
{ { 0x1d6e3b1,0x01156a6,0x01a74e2,0x195ac41,0x1c78e1c,0x166f407,
|
|
0x0e114b2,0x1c7cf08,0x0a8469f,0x10e60a5,0x1a3bc84,0x1b4fccf,
|
|
0x088e8f3,0x069a3a2,0x00f45b9,0x063e9b7,0x1987986,0x19dd0ee,
|
|
0x0931305,0x16b2ee1,0x101fdfa,0x031f6e3,0x07c284c,0x1b1fe50,
|
|
0x1d6016c,0x1e4a324,0x0ef3156,0x04ce461,0x00412a2,0x0e302bb,
|
|
0x1d80a86,0x0651f5d,0x119d5f1,0x1556ce3,0x1a7bd9f,0x0a4f972,
|
|
0x119bafb,0x0129873,0x00b2fcd,0x199feb5,0x06e2c24 },
|
|
{ 0x1af8793,0x18125d6,0x12398c4,0x0206b92,0x144bccf,0x1a805fc,
|
|
0x19ade54,0x0cbd340,0x01d1167,0x0c8d4a3,0x04f1e1e,0x165d3fb,
|
|
0x1595add,0x14972a4,0x14b00df,0x1cb9e0b,0x1189f03,0x1658a2d,
|
|
0x16a87dc,0x1c91952,0x0e4f81a,0x0109ad3,0x080fc9c,0x1654faa,
|
|
0x0f5a249,0x15195e7,0x000b5fc,0x0d0f520,0x0745b00,0x1914363,
|
|
0x014bdf4,0x10ca0e6,0x1a8a875,0x0e2c79e,0x0210ba3,0x0b7c717,
|
|
0x1bf1118,0x045f9a6,0x03e45ad,0x01b2f81,0x05af7fd } },
|
|
/* 151 */
|
|
{ { 0x0a224a5,0x0dca87a,0x1ce957e,0x0998a04,0x0190457,0x1f8feaa,
|
|
0x04cc190,0x10669f0,0x10e50f7,0x0b400dd,0x005c4a6,0x080712b,
|
|
0x16866d7,0x12048e9,0x0690176,0x0dfcfb7,0x1df16a4,0x078f1bc,
|
|
0x0efe45a,0x09527f0,0x0bca8d0,0x1a99590,0x0b9320c,0x0543821,
|
|
0x134b1f7,0x0da4ce9,0x1f60657,0x1f7932e,0x014b5d8,0x1efffdd,
|
|
0x1db2bac,0x0edb5e8,0x0fef022,0x1b97a30,0x17fb6d6,0x0497291,
|
|
0x16dfb06,0x02e492d,0x152b946,0x1032c13,0x027a9c3 },
|
|
{ 0x12a93af,0x1b9a378,0x0d35cf0,0x18aa6cc,0x028b707,0x00c9e88,
|
|
0x1635526,0x13b1df4,0x0ef21b6,0x1c1d2e6,0x0283893,0x01474f1,
|
|
0x1805cbb,0x12d89e4,0x00c5e05,0x0f09802,0x0582b73,0x17f5107,
|
|
0x140d87c,0x0e2741c,0x02d9df9,0x07e8661,0x0c51268,0x0bc5c36,
|
|
0x152e77c,0x0678c1b,0x16d9c11,0x1c89ad7,0x1e177a6,0x0f4ab99,
|
|
0x08c04b7,0x011dc58,0x0b49669,0x18ca4b4,0x15047d7,0x1fb3760,
|
|
0x0acd886,0x0c1638b,0x0491254,0x129f7bd,0x01c6906 } },
|
|
/* 152 */
|
|
{ { 0x0880026,0x13e8b9d,0x17c976d,0x0024bb2,0x09c4f0a,0x165bd24,
|
|
0x01544fd,0x14a520a,0x15cbbdc,0x15918e8,0x0f2f4cf,0x19332e5,
|
|
0x1af8cff,0x16aad01,0x13bd352,0x0f85f96,0x1ca2286,0x0ca26a3,
|
|
0x1ab46a9,0x110a901,0x104596d,0x1c65e45,0x1da95f3,0x0bcab40,
|
|
0x1844b00,0x04beff2,0x0474628,0x1d3cfc3,0x123c745,0x1374294,
|
|
0x0e655e8,0x0febb66,0x0867b79,0x1686468,0x02398ef,0x184aa68,
|
|
0x089ad23,0x0b72eab,0x10ce456,0x1ad4a09,0x07b8c13 },
|
|
{ 0x0fb6901,0x01d56a9,0x14ecbf1,0x122d944,0x1c0313f,0x0d56e30,
|
|
0x00c2945,0x18428eb,0x07f577d,0x09e8c93,0x0f03772,0x1d1dee4,
|
|
0x1a26e52,0x1f5cfb6,0x0783ae0,0x06eda5e,0x082f180,0x0ccbcef,
|
|
0x020d24e,0x051d976,0x18e743e,0x0e51ce1,0x068b547,0x1c7ed6b,
|
|
0x063a9a8,0x1383730,0x092e6cc,0x19e3b47,0x18915d4,0x0451697,
|
|
0x049b94d,0x0a0a0f2,0x075e3e0,0x1c1fd2f,0x195c834,0x135dff9,
|
|
0x0fd2fb2,0x16a9e64,0x1334075,0x1ecd2de,0x00e3c3e } },
|
|
/* 153 */
|
|
{ { 0x1ee1d83,0x19be090,0x1e20ef0,0x1af0f6e,0x17e08f6,0x07d2674,
|
|
0x07f304e,0x0b17ee1,0x1a0348e,0x17bbb23,0x199cb6e,0x15794ab,
|
|
0x1d04f8b,0x1eaf62e,0x14a4675,0x124301d,0x1ff33e9,0x1c67325,
|
|
0x12c166b,0x13f8ae4,0x12baac0,0x1cee2f1,0x141a0c7,0x0b5ed52,
|
|
0x0267746,0x1fc1351,0x1b25fc7,0x18bdfcc,0x0087fd3,0x106b5e3,
|
|
0x1ac5457,0x1551db8,0x1a39c5e,0x0f694d8,0x1aec39e,0x107bb02,
|
|
0x1c3788b,0x009bb4d,0x09471b3,0x1c78125,0x0463098 },
|
|
{ 0x0bd0fa7,0x00463e4,0x1924e99,0x039cd7b,0x1176431,0x1f7bdf6,
|
|
0x18420a0,0x071c62b,0x199b5d9,0x109e63b,0x1269ae0,0x0b028b4,
|
|
0x11af7f1,0x1294f26,0x03f6c3f,0x193ada0,0x177ce66,0x12ae9c7,
|
|
0x0f52e54,0x0f99803,0x1986b4f,0x04d7b8f,0x0365d6d,0x0c9a015,
|
|
0x19fcbcd,0x16b895a,0x12968ee,0x10c1ca0,0x1c89f11,0x102215a,
|
|
0x07db65d,0x0f47c46,0x0d0c659,0x05d497f,0x10cc5e3,0x1cb0229,
|
|
0x0698e11,0x13a6033,0x0e16b8b,0x1274691,0x07f8fd0 } },
|
|
/* 154 */
|
|
{ { 0x19428af,0x0c96560,0x1997c91,0x0274610,0x192a1c8,0x05debf8,
|
|
0x0604b8c,0x17284b1,0x1836c6b,0x06d8391,0x19261c4,0x03d2b31,
|
|
0x0b9c7a4,0x1756b7a,0x1fc5e79,0x0588915,0x1b97586,0x1387c7c,
|
|
0x1c8660f,0x16046ed,0x11526b3,0x0dcc732,0x09760fa,0x0a24314,
|
|
0x126a8d7,0x0d31d96,0x0a75bc7,0x0a10503,0x081f749,0x0682d2d,
|
|
0x1c637de,0x1c8d0e8,0x19ee559,0x1ec666b,0x095d9e1,0x0a40c19,
|
|
0x08476c9,0x1d427fd,0x144c509,0x0a3cc86,0x087b64c },
|
|
{ 0x130d3c4,0x037b2a5,0x1c521fd,0x184769d,0x0dec4c5,0x0526b46,
|
|
0x11d998f,0x0db676e,0x1cf3fb5,0x0f9a134,0x1f51a87,0x13881fa,
|
|
0x1dd4f13,0x1534d45,0x0df1f1d,0x1afa547,0x0c9cbad,0x0772b5a,
|
|
0x12508cd,0x1fe6855,0x1da3b28,0x1d3c378,0x0011bf7,0x001905c,
|
|
0x1149cb7,0x0cbe72e,0x0542599,0x1461df0,0x1f4bddc,0x0304fe7,
|
|
0x1a11288,0x08924a4,0x12f65e7,0x10f9c07,0x14b3500,0x01cb6ca,
|
|
0x042dbbd,0x154e150,0x18bd5df,0x0f9b380,0x08c9526 } },
|
|
/* 155 */
|
|
{ { 0x1c1abb1,0x081972f,0x1d0d995,0x0825fc8,0x0215af5,0x182f7a9,
|
|
0x1d580a7,0x1d3faca,0x1dc191b,0x0739992,0x18e6c2c,0x0cbd810,
|
|
0x137ab3c,0x0e1f333,0x141fd44,0x0aaaace,0x1c3c861,0x0b1c5f7,
|
|
0x0bc312b,0x03119e8,0x186d5d0,0x0e6c4b0,0x010e8c0,0x18ce83d,
|
|
0x003f7b2,0x0e8022b,0x13e8f34,0x0ea8b81,0x00672ef,0x17fea52,
|
|
0x177d84a,0x08b73d1,0x0197c9f,0x116ba2b,0x0df61e4,0x1f68a64,
|
|
0x0b2d59b,0x09971d2,0x1a85afc,0x0e77094,0x08afa1b },
|
|
{ 0x193ac70,0x0cb7573,0x1441acd,0x1dddedb,0x0c94ef8,0x0117202,
|
|
0x13e89c1,0x0c724d6,0x0e9e5d7,0x0638ee7,0x0aab7f2,0x16e1ea2,
|
|
0x1f352fc,0x1441cba,0x1ee84e2,0x0762636,0x190058c,0x0abcc89,
|
|
0x1dd03f4,0x0412552,0x0697969,0x0d8b058,0x066b651,0x106f564,
|
|
0x1438810,0x1b8de31,0x13c5d2e,0x0ddc238,0x1b80eb7,0x1fe0d58,
|
|
0x0298446,0x0e1d88b,0x082bac8,0x09992de,0x049cc4b,0x11ddcc0,
|
|
0x1240adc,0x08c58d5,0x024f2d0,0x12256b4,0x0672111 } },
|
|
/* 156 */
|
|
{ { 0x15cf9bf,0x0c9837a,0x1b6647a,0x1148d72,0x1b04530,0x1d32efc,
|
|
0x0787679,0x1775c78,0x1c731bc,0x09e58a8,0x1629851,0x044f49a,
|
|
0x0214be5,0x0be3a66,0x16b248a,0x001ac73,0x045822e,0x1a687bd,
|
|
0x18ac0f7,0x163aa38,0x0b2dafe,0x125d50c,0x0ec770e,0x056e9e1,
|
|
0x07178df,0x119bf9e,0x1a25ada,0x19a6514,0x0e055ff,0x0a2a0ee,
|
|
0x01fa57b,0x0d49c57,0x1fbc76b,0x0ee74cb,0x1fc7e96,0x03cbd8c,
|
|
0x0c0367c,0x11b4566,0x08ff814,0x02ca9c9,0x07c8639 },
|
|
{ 0x07388cf,0x0a5af65,0x14e157a,0x018066b,0x17cc0a6,0x17c2dd0,
|
|
0x0de2d85,0x10136d3,0x1101229,0x02e8177,0x1429e5c,0x1d0039f,
|
|
0x12565a6,0x1e8f71a,0x1d2a5b5,0x13b5bd6,0x0ed427b,0x1ae4419,
|
|
0x1b54cc3,0x150a51c,0x0ee896e,0x158c692,0x0c36218,0x1f273ee,
|
|
0x18ed59f,0x1294e69,0x0804180,0x121f934,0x03b3ff6,0x045c118,
|
|
0x1a718b6,0x1baa568,0x042d7a4,0x096c9fe,0x1e8a32b,0x100df1b,
|
|
0x0092043,0x11b0483,0x156b540,0x0b1f9d0,0x0325827 } },
|
|
/* 157 */
|
|
{ { 0x19e8c60,0x0722f9a,0x061bac8,0x0a6c994,0x071bb8a,0x1c70886,
|
|
0x141c77f,0x0f00562,0x14c93e5,0x1a748e9,0x0743601,0x1c01705,
|
|
0x1ac0326,0x113541f,0x0648961,0x1413c78,0x0d5fb29,0x11c3d32,
|
|
0x16b1720,0x147a69c,0x1a29caa,0x12d6d16,0x03b5a17,0x052ca1d,
|
|
0x00267eb,0x179c939,0x05d8e00,0x0e30963,0x0b1aeaf,0x0e876fb,
|
|
0x1748fd7,0x04bcc24,0x01fa347,0x1950d5f,0x1e74321,0x1fac50f,
|
|
0x0c57c3a,0x1549e95,0x1d95926,0x0e2b7b4,0x01a4e6a },
|
|
{ 0x14d1267,0x1376f2a,0x0d20684,0x0639a05,0x17f9453,0x18fd8e9,
|
|
0x1c13338,0x025ae15,0x1097dc0,0x1a08585,0x1edb173,0x1a2e6d8,
|
|
0x05930e1,0x0344884,0x0bfb907,0x0c71f20,0x0a779fb,0x19a4dd2,
|
|
0x135be37,0x18b0435,0x0acea16,0x009703b,0x1ecee0f,0x003a29b,
|
|
0x1033be5,0x16d35c6,0x0883cb4,0x0b27a8a,0x1f18800,0x0936cce,
|
|
0x098dd49,0x13fd667,0x032351c,0x17a2b65,0x0ef07db,0x15b2268,
|
|
0x15b9dc8,0x042bed9,0x1a0cb1d,0x1270b69,0x0856a7c } },
|
|
/* 158 */
|
|
{ { 0x10a5583,0x1e80106,0x162a801,0x1bdb48c,0x0f1301d,0x0c9cdf1,
|
|
0x1e590d3,0x06d2380,0x0a70c08,0x065b3c0,0x0795028,0x1f2b7d0,
|
|
0x18c0b4d,0x0ea5645,0x0ef34d1,0x0c472d9,0x0d05475,0x12be297,
|
|
0x00173ad,0x05b9483,0x0255cac,0x15bc9a2,0x0457b9a,0x193454d,
|
|
0x1ef3124,0x13a1b36,0x1e304b1,0x1a772c5,0x1b7c3bb,0x078dbed,
|
|
0x16eaad9,0x1c45772,0x00e4553,0x11dba1e,0x1aeb131,0x024811f,
|
|
0x0a4da63,0x13b9891,0x16900f2,0x1098c6d,0x0628890 },
|
|
{ 0x0b8d208,0x1fea9c6,0x1b52915,0x12a87e0,0x1a8f800,0x17f955b,
|
|
0x18553cb,0x1cf6cdb,0x1f72517,0x0ed9475,0x0274b3f,0x1ccdf27,
|
|
0x0e0149f,0x0c2dc46,0x1a1dcff,0x087eef3,0x10b0ba5,0x0229704,
|
|
0x02c0ff0,0x136b9f6,0x177bdeb,0x05362f6,0x0c44d12,0x1f806e4,
|
|
0x1f3cf8f,0x0251b04,0x15706d3,0x179388d,0x059be92,0x1df9c7d,
|
|
0x04799bc,0x19b604d,0x196bf5f,0x1c47c89,0x0750027,0x07e3d8b,
|
|
0x0ad9dfe,0x081a2b1,0x135630a,0x058b5b4,0x079d812 } },
|
|
/* 159 */
|
|
{ { 0x0529507,0x0726755,0x1400535,0x08e8cab,0x056a081,0x07e23a0,
|
|
0x028e13c,0x11d81a6,0x03443cb,0x14101f5,0x05ca362,0x1f612fe,
|
|
0x1233c62,0x1a9077a,0x0e373f6,0x13a7d14,0x15d7cac,0x0507c86,
|
|
0x1cf3a94,0x0f617f0,0x01cb28a,0x1d36362,0x14456b8,0x0702583,
|
|
0x171daa1,0x03f51a8,0x1589354,0x0ba9774,0x18f42f2,0x0944bf4,
|
|
0x1c6476b,0x12d4826,0x1d6b1e9,0x12dbbff,0x0496da7,0x0fa8d84,
|
|
0x00c4f70,0x095a121,0x155eb1f,0x12b0284,0x02ab3af },
|
|
{ 0x05372a6,0x103a635,0x0e9e1b2,0x1cac525,0x128fb83,0x1a0e7ab,
|
|
0x05b71dd,0x13ae8ab,0x1520ef4,0x05a6750,0x1191c9c,0x1c68c3c,
|
|
0x1d1472f,0x1fdc562,0x15af598,0x180e3e9,0x0c9c10b,0x0a37296,
|
|
0x1c68d18,0x129dfc6,0x0877287,0x0c13b7f,0x092141c,0x1deb569,
|
|
0x157739b,0x00af6d6,0x1cfc572,0x0985b3f,0x0395c32,0x0872c7c,
|
|
0x1546225,0x1016d50,0x0e40996,0x001f0dd,0x08b22a2,0x1c9ea7c,
|
|
0x039d25e,0x119fb08,0x0272abc,0x06a4a08,0x007db2c } },
|
|
/* 160 */
|
|
{ { 0x17d4703,0x1dc6d81,0x02e71fc,0x1f8be91,0x083708d,0x18ea017,
|
|
0x00c3e11,0x1d23f75,0x05a2faa,0x0af7469,0x13f07a9,0x1e20a80,
|
|
0x11c2e5b,0x1516ab2,0x1f5409e,0x1ebf2c8,0x00c7eba,0x19bd29e,
|
|
0x16cc2af,0x1e17652,0x13ba7ad,0x1f6b264,0x1698b87,0x1de94f0,
|
|
0x018c0e2,0x027bffe,0x0534b34,0x073bb3b,0x00af021,0x1d5baf5,
|
|
0x13c94fe,0x01fdf35,0x08100ea,0x0ad53be,0x0137218,0x12e98a7,
|
|
0x1fe5206,0x143416c,0x15d672c,0x11f9efb,0x008b6ca },
|
|
{ 0x16c3b5a,0x12df501,0x0d2f813,0x04ff3e5,0x1872610,0x1cbe079,
|
|
0x095c0a5,0x14753f9,0x182879e,0x12b0c05,0x1c377c5,0x1376c0f,
|
|
0x0715338,0x13d8704,0x08488f1,0x0ff8f33,0x0ec9d89,0x0868c04,
|
|
0x05bb7c6,0x00e2352,0x1118947,0x158390b,0x1e3d4bc,0x111116d,
|
|
0x129ffd1,0x0802ec5,0x15331be,0x1e3c458,0x04877fe,0x10b2f59,
|
|
0x097100d,0x06a8f2a,0x1a95233,0x0a3457e,0x1085a18,0x11ac454,
|
|
0x14faba0,0x021d83b,0x09f4974,0x0041a63,0x02c337b } },
|
|
/* 161 */
|
|
{ { 0x022fa65,0x182de75,0x18e9ec8,0x09a2b3e,0x1e183ef,0x1ac91fd,
|
|
0x161f4fc,0x0a668e7,0x0c11d77,0x13fd983,0x1533fec,0x1cd6540,
|
|
0x19702e7,0x178c2b0,0x1a7e5f2,0x0a38a79,0x0434e7d,0x1c1aa81,
|
|
0x0d5ab16,0x1c7b05e,0x1131a63,0x156bb22,0x019edf2,0x0e3f93b,
|
|
0x1e6afa6,0x0bbf742,0x18ac1f3,0x1730bdb,0x1a51933,0x0c587fe,
|
|
0x0d81f56,0x15285b8,0x10eca39,0x10c54d8,0x13b9418,0x142fe7b,
|
|
0x06b7d5c,0x0a74688,0x0c724f6,0x069db10,0x0509b26 },
|
|
{ 0x0caed54,0x0a0a724,0x1a5ec6e,0x1997ea3,0x17a78c6,0x14d92c3,
|
|
0x0323537,0x0f148d1,0x091ee3d,0x01209be,0x1b99300,0x0469c61,
|
|
0x18a68f9,0x040c86b,0x0c956f2,0x0d216ae,0x05fba80,0x020f470,
|
|
0x10d53d3,0x071b09d,0x0816500,0x0b6fd29,0x0c63c0b,0x16c7fb5,
|
|
0x19007cc,0x02ae23f,0x0fa62b9,0x13a901f,0x0e319d2,0x0e912e8,
|
|
0x0652b11,0x004db6e,0x06f3575,0x0c3dce8,0x1880b0d,0x0ee6773,
|
|
0x0c31772,0x041cc91,0x01d4889,0x14ea977,0x01592d5 } },
|
|
/* 162 */
|
|
{ { 0x17453f0,0x06cd167,0x07c15de,0x15db078,0x0ffb899,0x1415d3d,
|
|
0x01b4f82,0x1035cca,0x0ea3d50,0x164270d,0x0a8e2cc,0x1181021,
|
|
0x019ad52,0x1e9be82,0x1f6c082,0x1c83f63,0x1e1d06c,0x13c6b65,
|
|
0x19d2dfd,0x0fe1e05,0x1022d28,0x1ae21dd,0x1d73495,0x034e367,
|
|
0x0f2f3f8,0x1fa3694,0x1718cf9,0x0cb763e,0x1c580ee,0x1e0e627,
|
|
0x094cb97,0x176f60f,0x155539f,0x1579d66,0x11c70f2,0x1b6b528,
|
|
0x0cc22d2,0x0c5efa2,0x1ddf2e5,0x17aef44,0x01614bd },
|
|
{ 0x10ab04d,0x1811876,0x0ba9307,0x00dc410,0x0e347b0,0x162dafd,
|
|
0x0f18f10,0x06b3e21,0x1de0199,0x029cf37,0x142096c,0x09cecbb,
|
|
0x16d89bd,0x1de76d0,0x0983fbe,0x1946524,0x15ce62a,0x1c5553a,
|
|
0x1b20b17,0x0c5f52b,0x0768ed7,0x008c328,0x0679930,0x05c6919,
|
|
0x16245c9,0x0b42bee,0x1cc7a9b,0x1b7114e,0x1447360,0x095583d,
|
|
0x1fbbc00,0x02e3ae1,0x1356b94,0x048d85c,0x18a00fe,0x05cd160,
|
|
0x179c20a,0x0a529d5,0x01ca0e9,0x18f6016,0x0489656 } },
|
|
/* 163 */
|
|
{ { 0x1353c25,0x124dd38,0x189390d,0x0227ecf,0x117f27a,0x0f5cf1a,
|
|
0x0cce870,0x1f2217a,0x078e29b,0x070e02e,0x0fc5765,0x1b2e8e8,
|
|
0x1084fe7,0x086d16f,0x01d2422,0x077c339,0x1a75367,0x0c1201f,
|
|
0x0eba86c,0x1ebb683,0x0ead7eb,0x1a920c0,0x13f82b8,0x1ea187f,
|
|
0x1873fc2,0x06c8e8a,0x19c1987,0x0d0a35a,0x1e8c2c1,0x146cd28,
|
|
0x06600a5,0x1c02c21,0x1d1a9cd,0x1f52b73,0x1226a29,0x10562a7,
|
|
0x06e3c49,0x00dbc48,0x0772db5,0x1d3aced,0x0082bb2 },
|
|
{ 0x0d6615f,0x077a362,0x0a71860,0x0203730,0x1c629dc,0x1932657,
|
|
0x0bb003e,0x189bc44,0x010ecc2,0x0a2bf03,0x08b1371,0x133e3dd,
|
|
0x0c95ce5,0x07ce2d9,0x0cfe9ca,0x021f208,0x062cd63,0x1f701aa,
|
|
0x18b8894,0x0af8779,0x1e4484c,0x0d4b6c3,0x1b23b0c,0x0a58b4e,
|
|
0x1e393a4,0x11a985f,0x02811ec,0x0b25628,0x18545ec,0x1f0c600,
|
|
0x119ef62,0x0b82f18,0x14e0107,0x1802dbc,0x0518b88,0x06908e3,
|
|
0x022a54f,0x12f11bb,0x0410899,0x08d2039,0x036451a } },
|
|
/* 164 */
|
|
{ { 0x1893e71,0x0168c0c,0x02085e0,0x16a7344,0x01765d8,0x01767e5,
|
|
0x1a8048c,0x13bf8d5,0x1365bf5,0x0a67a8d,0x0caa023,0x1ae41a4,
|
|
0x0787741,0x0c74021,0x0d0facc,0x073d958,0x12fe747,0x12a9f65,
|
|
0x0a2c1f2,0x14f3503,0x0b3aaec,0x112b7a5,0x0227fcc,0x143a3ee,
|
|
0x1d7293f,0x10b2f4a,0x1bd8aa6,0x0c0ad35,0x08ddc22,0x1119550,
|
|
0x12979dd,0x036f76a,0x1fabec3,0x0ab73c9,0x0559d0f,0x1e91441,
|
|
0x0b0ebef,0x0e6d897,0x1f3c5d2,0x148d371,0x0705307 },
|
|
{ 0x088310b,0x1260272,0x15edea3,0x04a64b9,0x12726e3,0x01f7d60,
|
|
0x162c126,0x026ba1f,0x002ddb9,0x0b72a96,0x05a171e,0x07eeef7,
|
|
0x030eeca,0x18af925,0x1d9ba26,0x192f336,0x0d648ef,0x03e139b,
|
|
0x000871b,0x032d0b5,0x11ea3d6,0x1c50597,0x1f8cf89,0x0edad61,
|
|
0x09879b6,0x05f4ae3,0x046bd38,0x00e8e63,0x04ee55a,0x1af89b6,
|
|
0x0e68bea,0x0b3cbe7,0x138b8ff,0x17f3734,0x1690e72,0x003c229,
|
|
0x0a6ad12,0x0caf61b,0x0abb325,0x1a0afcc,0x080f79b } },
|
|
/* 165 */
|
|
{ { 0x0af09b3,0x1a153b0,0x1850f3b,0x1b267bf,0x1c016eb,0x02f5541,
|
|
0x1c783b6,0x192e419,0x1ceaa3b,0x07af4cf,0x01be5f5,0x13a56e2,
|
|
0x127216b,0x04b3456,0x1cd30db,0x0ca3ecb,0x0bc5b0c,0x1547dc1,
|
|
0x0bf6937,0x085e39e,0x059e20f,0x16690fb,0x1acc6ac,0x07a2c31,
|
|
0x176c7a1,0x1f2dbd3,0x08e198a,0x1888204,0x108e0be,0x0d38656,
|
|
0x0032097,0x0045803,0x1299079,0x1cffecc,0x1680abb,0x00ec477,
|
|
0x15c58b5,0x027a79f,0x1fc677a,0x149b049,0x05f5a5d },
|
|
{ 0x08311dc,0x192bf3f,0x04d95cd,0x028cd9e,0x1ef94f5,0x0e510d6,
|
|
0x05916c1,0x06f4e7c,0x002e4ab,0x0754d9e,0x04596ce,0x15930af,
|
|
0x047760e,0x012580d,0x1f7411f,0x0ab09bf,0x1d13fb9,0x10c46a7,
|
|
0x15522f6,0x1871704,0x1cacfaa,0x182cf4e,0x069e69b,0x144e01e,
|
|
0x1720f09,0x1244c1f,0x13ee29f,0x19774aa,0x01fad58,0x0cb423d,
|
|
0x178e286,0x0b57ad6,0x1856547,0x0b76108,0x14c7cdc,0x16ea227,
|
|
0x0212907,0x08f3c0a,0x162244e,0x0021b82,0x05319c8 } },
|
|
/* 166 */
|
|
{ { 0x161c3af,0x009b735,0x0da08c8,0x1c0f697,0x1d40f2d,0x064bf80,
|
|
0x1b9fce0,0x074ca3b,0x06a8c31,0x0bc5d38,0x072842a,0x0fac402,
|
|
0x1b22c58,0x158fa22,0x0ee8862,0x089cc91,0x107e504,0x0c62f57,
|
|
0x10bf33e,0x13e0548,0x093d554,0x179ec02,0x09591d1,0x1808b22,
|
|
0x04f6179,0x043a169,0x02af722,0x0c01f43,0x138f8f1,0x10056f6,
|
|
0x11972e1,0x12475d6,0x0bf9b90,0x02bc552,0x18d4787,0x09ac7fd,
|
|
0x0bb9ea1,0x04e2d67,0x13fc3cf,0x09be234,0x03d1331 },
|
|
{ 0x0513d1e,0x03316da,0x0af7973,0x0baab2a,0x1e78a8c,0x1c36856,
|
|
0x1e8ff9f,0x18bd146,0x07a04f0,0x1168952,0x1741b32,0x0dc85c4,
|
|
0x114c669,0x1909b03,0x1851a62,0x1c396a4,0x01b89f6,0x17a6938,
|
|
0x03bf657,0x1ac2ef0,0x0907aaf,0x0262ddb,0x19b5ceb,0x01b66b5,
|
|
0x074ac42,0x1d024f4,0x13c9d47,0x02c63bc,0x1a2edd1,0x199b50f,
|
|
0x136ca7d,0x16ffaf2,0x0406864,0x1c95326,0x074f88b,0x0ce7964,
|
|
0x0043cc7,0x1482731,0x11ab7ab,0x13f6645,0x067f28a } },
|
|
/* 167 */
|
|
{ { 0x0148ab5,0x1d92c65,0x0145f05,0x1f678c0,0x19a1976,0x1946fcd,
|
|
0x01a6323,0x02fd44c,0x0e8d450,0x1d9663a,0x02908a1,0x06520af,
|
|
0x1237257,0x0bdf639,0x157b894,0x1778903,0x1cf1d48,0x16ba08f,
|
|
0x01fd73f,0x02fcd69,0x0e1b462,0x02a0f5c,0x12c01eb,0x0b40191,
|
|
0x057a6e0,0x14ce20e,0x0f4be7e,0x1f2a9a5,0x141cad1,0x0aeda04,
|
|
0x074dc2f,0x07052a1,0x087879c,0x052f772,0x154973b,0x1c9826e,
|
|
0x1d3efb9,0x17bfd27,0x0f6cba3,0x0e837a3,0x05ff091 },
|
|
{ 0x19c6632,0x089522b,0x0055e46,0x1f71441,0x1b19a44,0x0b1ce9d,
|
|
0x1ee114d,0x19de9f2,0x1bc3c9b,0x0bf15e5,0x1990439,0x1e57e33,
|
|
0x0d122b3,0x09abecd,0x0062768,0x1fecc3e,0x1bb79e5,0x033aab9,
|
|
0x1cbcf13,0x1cb931d,0x0731444,0x1002688,0x15bd878,0x0ebac6b,
|
|
0x0366fac,0x19186fd,0x18b2153,0x1f88f90,0x10850b9,0x121f056,
|
|
0x0cb012b,0x05ee418,0x0e94f64,0x1de4eae,0x19969d4,0x06cfdf5,
|
|
0x10373a6,0x1e9869d,0x0591b09,0x07452e4,0x0668101 } },
|
|
/* 168 */
|
|
{ { 0x04509df,0x0ec89f4,0x0dd84e1,0x1b9e672,0x0978bed,0x11d0a47,
|
|
0x0974cd0,0x0f25be8,0x1ee8cb5,0x1fd0571,0x1154f10,0x0d3a638,
|
|
0x08f0153,0x0fdf8ea,0x13c22ef,0x048940b,0x1e69444,0x1d6ffa5,
|
|
0x0d7768c,0x06bf034,0x0b7c016,0x04f3b7d,0x0217225,0x0e6ef06,
|
|
0x1fcde16,0x06925eb,0x128953e,0x1b196a5,0x1ec985f,0x0533209,
|
|
0x131885a,0x0f5204d,0x0db9741,0x0f0dbf9,0x1959438,0x1c72c5d,
|
|
0x13beffd,0x1051a36,0x0ac7efb,0x05e17bf,0x03b35b7 },
|
|
{ 0x15c3749,0x06f4fa9,0x1122ffe,0x1f15bb3,0x03c1f20,0x1c7b319,
|
|
0x0cdef23,0x09352eb,0x1e8f3ae,0x094f23a,0x1898a09,0x01aa3ab,
|
|
0x1dc32f1,0x13c3178,0x1034a5d,0x17c6cb5,0x138854c,0x109e3c9,
|
|
0x0d9f918,0x0009de9,0x0ee148f,0x0872e88,0x1e8de85,0x1051141,
|
|
0x0778dd2,0x1a6a4ba,0x1b3edcf,0x0d0614c,0x0049529,0x000983c,
|
|
0x0527d11,0x12ec16d,0x033c709,0x1ae4cc1,0x129496d,0x1906819,
|
|
0x0771f99,0x117205e,0x11a14fd,0x1d79b2b,0x047d0a1 } },
|
|
/* 169 */
|
|
{ { 0x12811f1,0x1a7ffb2,0x000899b,0x06c5de6,0x0aacaa9,0x05d0657,
|
|
0x1e95543,0x0ced870,0x0007f54,0x1a80a15,0x1c99ce8,0x0054405,
|
|
0x05c7fd1,0x19ee373,0x0bb95c0,0x0c7b2bb,0x0c3064a,0x1303417,
|
|
0x18ac947,0x1e17608,0x16e746c,0x12aed49,0x0380c32,0x084cb6a,
|
|
0x060f243,0x07ae43d,0x0da6d3a,0x0c6f657,0x17770a9,0x1ac63d6,
|
|
0x099807e,0x1da742b,0x12147f6,0x0f4b08f,0x1578a65,0x0c0b68f,
|
|
0x03213a1,0x0654d9c,0x0a1732c,0x094932b,0x08f4b61 },
|
|
{ 0x14eb3c1,0x0760ca5,0x09c16aa,0x0840647,0x0c549ac,0x1663554,
|
|
0x04c893d,0x14601a9,0x145f9a5,0x129dcdd,0x1eaeec3,0x0220112,
|
|
0x10e46ef,0x0bd66be,0x01cf95f,0x16b11fd,0x1e50f7c,0x0be7e67,
|
|
0x01555f4,0x0a7acb9,0x12e20ea,0x0239447,0x1f767ad,0x1d6d151,
|
|
0x1edfac0,0x1065596,0x002180e,0x104428e,0x1eb06c5,0x0344807,
|
|
0x0b1a519,0x04bcb95,0x04cf5bf,0x08d74c0,0x01627f2,0x1db0ab3,
|
|
0x13c45ea,0x09bc58b,0x06007b6,0x004a499,0x08f942d } },
|
|
/* 170 */
|
|
{ { 0x0845808,0x1618147,0x1f147c7,0x156ef57,0x0302bff,0x0cbee3e,
|
|
0x152e7e3,0x0964d5f,0x03aac59,0x09d41e2,0x165370f,0x17a2ce9,
|
|
0x1ce3b74,0x0552c88,0x192dcdf,0x059a488,0x173871c,0x131492b,
|
|
0x0d1103f,0x1e490a7,0x0d7d419,0x19f0295,0x1769a83,0x0d90d81,
|
|
0x080d684,0x1a13229,0x0be0c93,0x04ad13f,0x0f117aa,0x08f403e,
|
|
0x0df1d2b,0x11bb93b,0x026dea0,0x1e42eab,0x0dce59b,0x06a4c40,
|
|
0x13b1eb5,0x16abe1f,0x06b2f82,0x0a52938,0x0383002 },
|
|
{ 0x0744723,0x1ad202f,0x120683b,0x0a35c10,0x1b5bcf7,0x00fbb7e,
|
|
0x16333fb,0x18d57f5,0x1fab37f,0x1d2ec18,0x1b6de3e,0x049191f,
|
|
0x10be39e,0x16c9f98,0x13eb57e,0x0b8494b,0x11e913d,0x0ba3fed,
|
|
0x1462dfd,0x148f928,0x0327052,0x163e7da,0x0788235,0x1ca717d,
|
|
0x1cb9c70,0x08b589a,0x056ec5e,0x0c6a4eb,0x1106c73,0x1c402d9,
|
|
0x01a8b01,0x1841376,0x0d42a06,0x08256e9,0x11c74f1,0x096a4b6,
|
|
0x022ce03,0x1a59b44,0x0169727,0x12dd683,0x015f187 } },
|
|
/* 171 */
|
|
{ { 0x0ee4684,0x0f50305,0x0f20253,0x0cf9b7b,0x02b21f0,0x09898ca,
|
|
0x18526c6,0x14d4873,0x181a7db,0x125eea0,0x0ba03fa,0x0e0c785,
|
|
0x02c6213,0x09411ee,0x02c259c,0x023636b,0x1158326,0x03a21ea,
|
|
0x0f080e1,0x0df0622,0x12d22e1,0x0b15ecc,0x0338813,0x0327116,
|
|
0x1bcd6f4,0x063a4ce,0x1474dde,0x125bda3,0x1dae734,0x0ba7e2e,
|
|
0x166756f,0x13296c4,0x0813d52,0x165346a,0x13d83a1,0x18323b3,
|
|
0x13e9c2a,0x10bcf57,0x048e158,0x1e73fdc,0x06146f1 },
|
|
{ 0x18e2aa6,0x1699f03,0x0996f41,0x0f3bdd2,0x093af7f,0x1207423,
|
|
0x03e076a,0x0fdaadc,0x09b9a40,0x0fdddc4,0x0654641,0x15b9dbd,
|
|
0x19dcf44,0x0496dd1,0x1c7e34c,0x0ee96fe,0x1a54231,0x1b3adae,
|
|
0x17d817a,0x0d44a34,0x1a9e745,0x17c3d1c,0x040c752,0x168e97b,
|
|
0x1000605,0x148eda1,0x0ad996a,0x1b4bb7e,0x11eeb4b,0x1efab31,
|
|
0x1617468,0x0c46ef8,0x08149ef,0x085ff81,0x13a5a17,0x1c5c35e,
|
|
0x02a465d,0x15043ac,0x0014383,0x13c0d7a,0x095543f } },
|
|
/* 172 */
|
|
{ { 0x1d7c6ef,0x1e37a42,0x1093df2,0x1ac7637,0x0ad8084,0x065d316,
|
|
0x13a22fe,0x125bf21,0x0b455c1,0x0725b43,0x1f1bb66,0x11aaee9,
|
|
0x176146b,0x1d71003,0x188e279,0x04a52e1,0x07961c2,0x0a920e2,
|
|
0x021397d,0x042a207,0x02737d2,0x110bf14,0x15b4833,0x04ce9f1,
|
|
0x19f514f,0x0edf188,0x15c3004,0x0a8b20a,0x1b760e8,0x1aecfe7,
|
|
0x0677ead,0x13d1854,0x146362a,0x0a593ca,0x1e2929f,0x1896da7,
|
|
0x0e5d698,0x0438827,0x05bfe97,0x0f05745,0x06db434 },
|
|
{ 0x03f0d95,0x03249ae,0x0254192,0x049ce91,0x0917db8,0x179f224,
|
|
0x17d89ac,0x097ee7f,0x02b7f57,0x1076e2a,0x0c9c8f1,0x13455ee,
|
|
0x0cbe1c0,0x1e5688a,0x0d19a75,0x15ff2fa,0x00a321a,0x04b2330,
|
|
0x1433587,0x1c5775d,0x150eb94,0x00ef623,0x019b869,0x1513eb1,
|
|
0x0990db1,0x149d0df,0x13c9d65,0x073c9ad,0x00dddfc,0x1bc0607,
|
|
0x104473e,0x1b33914,0x0afcd7f,0x0182878,0x0b6db87,0x099d7ff,
|
|
0x16d2c6e,0x1cc0d84,0x1ea513c,0x1ce55c4,0x007a791 } },
|
|
/* 173 */
|
|
{ { 0x09f0300,0x148238f,0x04139c3,0x13799bf,0x00253ad,0x02983c7,
|
|
0x0a277fc,0x0c4a380,0x0ae8934,0x0f78497,0x11a117c,0x1235490,
|
|
0x142c90a,0x18ed6a5,0x11bb683,0x0cf6432,0x0f333df,0x0783b28,
|
|
0x0c56805,0x1311b61,0x10f9c6e,0x175aa17,0x1cb8319,0x1806f1e,
|
|
0x16311e0,0x086aea5,0x0aba1a5,0x09175b5,0x1f1c8f5,0x11c6d9a,
|
|
0x151a005,0x1289a35,0x09e3216,0x18e9909,0x0b21011,0x1d32a37,
|
|
0x05e94dd,0x0614f9c,0x1b2b00f,0x05c8a87,0x06d6acc },
|
|
{ 0x1b2d299,0x0cf4aab,0x0737ae6,0x17c7ae4,0x1a2bcd9,0x065a221,
|
|
0x0e13eed,0x1545cc0,0x1dc060f,0x10bbb84,0x01f37ab,0x0da7193,
|
|
0x0d74f0e,0x083b7df,0x08df3e0,0x1f7ff34,0x1137983,0x034d78a,
|
|
0x08fe561,0x1ef43a6,0x03986c3,0x07b6db2,0x0f8872b,0x0e07b24,
|
|
0x0134f96,0x1bb3e6c,0x1ee0e4f,0x0eab131,0x0252220,0x145e174,
|
|
0x1f06d6c,0x0f24954,0x18799c1,0x13d455b,0x03ca050,0x043b66f,
|
|
0x1f28949,0x1228d8f,0x11bbb56,0x0247a78,0x079d182 } },
|
|
/* 174 */
|
|
{ { 0x09d5589,0x16ffc88,0x126468f,0x0805368,0x1ed52eb,0x1aa56fe,
|
|
0x074c2d2,0x0ce27d7,0x1a27bff,0x1c90a60,0x03d1813,0x1dcecfe,
|
|
0x084c817,0x01d2871,0x17e360f,0x0c46f75,0x1c99402,0x0e2ee01,
|
|
0x19991f0,0x12b0372,0x07f35f2,0x04c5034,0x042da82,0x0c68a2e,
|
|
0x07cec31,0x0c4573c,0x158b9d4,0x0003b74,0x02c3fb2,0x10d3a2f,
|
|
0x0555753,0x16cfa67,0x1cacdeb,0x021775f,0x1e72f1a,0x1743415,
|
|
0x1e88580,0x0c85159,0x1372141,0x1234f09,0x0731044 },
|
|
{ 0x048d676,0x1166f93,0x0ac5132,0x0a9e362,0x1a85eca,0x0070f5c,
|
|
0x0b250a6,0x112373b,0x11ac8aa,0x1869b84,0x078657c,0x156f8e3,
|
|
0x1773072,0x17b81bc,0x1463208,0x0cfed74,0x014ac00,0x1d60487,
|
|
0x1734a49,0x19f8e11,0x1a630e6,0x1110f3e,0x13d6227,0x0e38f8c,
|
|
0x0a40b83,0x064da55,0x0a3de1e,0x1f3b57c,0x0caf3f1,0x16b5ec2,
|
|
0x04bde2b,0x13c1c3b,0x039dd07,0x0126e1e,0x17ec489,0x12d017c,
|
|
0x0bdc009,0x0d90a68,0x1153fd0,0x192a301,0x06a8f8f } },
|
|
/* 175 */
|
|
{ { 0x1235132,0x0f6b1a9,0x022d8a8,0x02b3b75,0x1db233f,0x0f7eec0,
|
|
0x15148a4,0x15d0ac4,0x1b25111,0x1a8294b,0x006f631,0x15f23ae,
|
|
0x1db5921,0x0bba7a2,0x14175ca,0x0e7ff69,0x05ef18e,0x0371ea6,
|
|
0x066cc0e,0x1b30bf1,0x1558897,0x1de44d8,0x02a70c3,0x0263039,
|
|
0x0d1a34d,0x1071e49,0x08888cc,0x125d0d7,0x0eed022,0x0a6100e,
|
|
0x07f3c91,0x0b07e61,0x1a45f74,0x1e8d193,0x00b2b43,0x10eb4c2,
|
|
0x0b9c753,0x07a2e96,0x0ff5f6d,0x183b650,0x04752d8 },
|
|
{ 0x1dff4d5,0x0b6756a,0x1fd1453,0x168b504,0x14cd5fd,0x0389af3,
|
|
0x098313f,0x11c20e1,0x01be577,0x1605dbc,0x11ac237,0x059ab1b,
|
|
0x16271e1,0x0a5e124,0x194226d,0x131596e,0x0636190,0x136ef96,
|
|
0x1d4a20c,0x1d758cc,0x0af1fd6,0x12e1284,0x1aa8b40,0x19f83e1,
|
|
0x0cda84d,0x1f009e1,0x0115442,0x18f06d5,0x0868011,0x14468d4,
|
|
0x114e411,0x15f5e4a,0x03132aa,0x05446b2,0x15dca0c,0x0092d0a,
|
|
0x0744b47,0x0a48e54,0x015495a,0x1e6ebf7,0x03a6518 } },
|
|
/* 176 */
|
|
{ { 0x04042a0,0x076a811,0x079aaaa,0x0048a5e,0x0cb4e3b,0x0108ec3,
|
|
0x17d31da,0x07fdb94,0x1ef4d5d,0x107f1fc,0x151b953,0x0548a45,
|
|
0x1533a8e,0x18a233b,0x063887f,0x1a036b3,0x10ef592,0x08a4b62,
|
|
0x0e99dce,0x00985f0,0x1f00691,0x05a395d,0x0a19c2f,0x062ef7a,
|
|
0x083b250,0x1514754,0x15f49c4,0x0bb1780,0x19c994c,0x098bda1,
|
|
0x1fd07be,0x1b9b435,0x001d3a8,0x07b7dcc,0x1ad5c0e,0x01ad0dd,
|
|
0x1bfbf82,0x062e687,0x1605fa0,0x0c7db84,0x0540ac3 },
|
|
{ 0x07f43df,0x0b4d4ff,0x19329c6,0x1058373,0x0665380,0x0e148bf,
|
|
0x1df6216,0x0095b2c,0x196aa44,0x1654aa2,0x0a5f6ae,0x0abffe2,
|
|
0x1e0e9d8,0x115753e,0x18625ec,0x07f1c3e,0x0fd36f1,0x1cb76e6,
|
|
0x1b88037,0x1a60e02,0x08a4627,0x1b64c4c,0x1ca7c1c,0x1e463a4,
|
|
0x05e6097,0x1a94af1,0x0fd8121,0x1efe443,0x19b299a,0x1304a00,
|
|
0x16759a0,0x04d6963,0x199de09,0x0ebd18e,0x1d986b3,0x13d88f9,
|
|
0x0ebe15e,0x14f959b,0x05d3d37,0x1d9f42d,0x017db32 } },
|
|
/* 177 */
|
|
{ { 0x0f40599,0x1b48cb6,0x03a9d7b,0x1601804,0x1ea10df,0x157b3cb,
|
|
0x0b9eff2,0x0f07b4b,0x188ddd6,0x0b31e51,0x0f3f343,0x11fc4ab,
|
|
0x1e5a21f,0x11a25e3,0x10fd4e3,0x00c65d3,0x11d548e,0x09afb15,
|
|
0x0f1b993,0x1e484a8,0x1627654,0x13134c9,0x11d569e,0x1e82649,
|
|
0x1c5f7b0,0x079d1db,0x04e8860,0x0ad2fef,0x01675b0,0x0fd88f4,
|
|
0x1d5b3e1,0x1ca6851,0x13cdb35,0x1458136,0x16454b4,0x11c7542,
|
|
0x17a3fb7,0x03812af,0x11176a1,0x0374328,0x0460bd0 },
|
|
{ 0x04d8077,0x06e11e1,0x14b2f0d,0x0098e41,0x02f4b58,0x0e8fff4,
|
|
0x0a445bd,0x1c5453b,0x092783c,0x1c57a90,0x012bcd5,0x03576b2,
|
|
0x10e29f5,0x1bd508c,0x115c35f,0x1bbe08d,0x1ba571b,0x0a52917,
|
|
0x1a26ed4,0x1c540d5,0x044dbf4,0x062cf9a,0x1e66cd7,0x1984aae,
|
|
0x0836726,0x0bbe181,0x16bf3b0,0x0949d30,0x16cbd09,0x1ee5be1,
|
|
0x1deb6bd,0x0eba720,0x131b787,0x1125e76,0x013cb4f,0x16a5ad2,
|
|
0x1f95421,0x0513348,0x01e3717,0x0782e69,0x07d342c } },
|
|
/* 178 */
|
|
{ { 0x1fd127f,0x1960508,0x117b973,0x10233c9,0x06d36bb,0x1ab561b,
|
|
0x0c949bb,0x0eac435,0x0e54306,0x067f577,0x1a5864c,0x0fa5587,
|
|
0x112ede2,0x1c7e733,0x04d44eb,0x0987ac8,0x01b075f,0x030ace3,
|
|
0x041a766,0x0fdfd2b,0x0ea9d44,0x14753b5,0x0be35bd,0x0b7a2c9,
|
|
0x1c61b0f,0x1cc562e,0x187a22e,0x175688d,0x092320d,0x058b0dd,
|
|
0x195862e,0x0f13130,0x0eafb3c,0x1bf4150,0x130b022,0x1618f57,
|
|
0x00d160b,0x184db71,0x18e9c43,0x14d1c98,0x05be0af },
|
|
{ 0x1bbf49c,0x1b69c0d,0x0ffa0aa,0x13180e0,0x1e09ce4,0x07a1319,
|
|
0x02d7784,0x065d94b,0x1da5a45,0x0e632c0,0x03dedf6,0x10edec3,
|
|
0x0707e18,0x1287bff,0x066978c,0x10d7c08,0x090de6b,0x0dd8d4f,
|
|
0x1cd645a,0x14fbd66,0x1b2c584,0x04a8a4e,0x0e3acd2,0x1d75770,
|
|
0x06a33b0,0x1490a2a,0x030be22,0x00cfe16,0x0db0190,0x0ff3851,
|
|
0x0faf783,0x18c7cde,0x051b06c,0x037d6dd,0x1ee7a48,0x1543224,
|
|
0x1e80dc0,0x15af43f,0x0c2bb93,0x1eba9bc,0x01e6fcc } },
|
|
/* 179 */
|
|
{ { 0x08ac924,0x0ffb355,0x0fa2d5f,0x0385316,0x06e9ad3,0x1d84060,
|
|
0x18ca597,0x07fa281,0x11d95c9,0x0d5908e,0x0032a9f,0x1085143,
|
|
0x096d68d,0x1106f6b,0x04a5022,0x08c3e35,0x15338df,0x1540a8b,
|
|
0x03aba4c,0x0c095cc,0x0c0bff5,0x04bed72,0x0406e79,0x04c5d13,
|
|
0x1a97fde,0x0c1a2b9,0x13c4212,0x1ad3b34,0x124f1de,0x0117b23,
|
|
0x17e3fe8,0x1d50b42,0x1f1c2e4,0x09bca6a,0x13a4051,0x1a98c4d,
|
|
0x1f0907d,0x02066b5,0x0a0de01,0x0c2bbb5,0x04522d4 },
|
|
{ 0x1fbe7c5,0x0f83cf5,0x111a225,0x1b09de6,0x10ea1de,0x10d5cb1,
|
|
0x07adb52,0x0d0e2d5,0x050a30c,0x1252e91,0x0eeea86,0x0638008,
|
|
0x155a166,0x080872f,0x041d409,0x00aad7a,0x09d3d8c,0x0dfff1f,
|
|
0x1ddc906,0x0616300,0x029731b,0x18425c1,0x043fdfb,0x0343187,
|
|
0x17d75f2,0x07c0061,0x15596ee,0x11a14c6,0x03bceb1,0x0d1522f,
|
|
0x036eb07,0x047e161,0x038e90c,0x02d628e,0x0a897ef,0x0de3743,
|
|
0x1da71fc,0x0a92b5e,0x102e827,0x152dafc,0x0346501 } },
|
|
/* 180 */
|
|
{ { 0x02b0f1d,0x1224666,0x1c0e1af,0x1358986,0x03eb45c,0x04b5dff,
|
|
0x1d9767f,0x1b4a70f,0x15ae27f,0x179e274,0x0602273,0x0eec378,
|
|
0x01a008f,0x11650c5,0x1d28210,0x066e3e6,0x04253b7,0x0774414,
|
|
0x13024d5,0x1f8db0f,0x0d6bcb6,0x0db0a4b,0x01227b0,0x1c64b89,
|
|
0x029b949,0x0b35496,0x09ef7b0,0x0b8d94a,0x0a28131,0x07776e7,
|
|
0x13e5511,0x074422a,0x0683eb3,0x030e79a,0x1e634e4,0x171f64d,
|
|
0x06c940b,0x1845540,0x125b70e,0x19fcaa9,0x07c1d42 },
|
|
{ 0x0110aa7,0x1381fee,0x0de1d9b,0x0fe6c5c,0x0b7b79d,0x16e51e5,
|
|
0x11d756a,0x0e7a4b3,0x160be33,0x137653c,0x13a3fca,0x14960d8,
|
|
0x1ff4744,0x19db82d,0x010b33b,0x096a765,0x1aaae30,0x00d1d7a,
|
|
0x0cb4c6e,0x1f44023,0x08d97bb,0x1d25f74,0x112e9ba,0x0b97073,
|
|
0x165ce56,0x074169a,0x1b6bdfb,0x09010d2,0x1597452,0x0673f34,
|
|
0x0dcb1f3,0x1d29f30,0x1d6eb3c,0x0d19377,0x133ce04,0x0c14676,
|
|
0x1ffa93a,0x101fa1f,0x0764050,0x050e786,0x0031e98 } },
|
|
/* 181 */
|
|
{ { 0x05a17ff,0x1f67e3b,0x09953fb,0x11a2521,0x009f388,0x06d01c5,
|
|
0x1711a4e,0x08d7e4c,0x1a169ad,0x1db0a2e,0x18bfa12,0x0428474,
|
|
0x0533cf8,0x15e4305,0x0b7d5c6,0x07188ac,0x0fa815c,0x0df9548,
|
|
0x1fb6a1d,0x143adc2,0x05e145b,0x0d4a37d,0x1e67620,0x01eb476,
|
|
0x1e784b9,0x095360d,0x12c43fd,0x122146f,0x14fd360,0x0ff2527,
|
|
0x0830e30,0x11c5a77,0x1180fc5,0x130c3e1,0x0142c5e,0x047c5fe,
|
|
0x143a35c,0x0002cdc,0x11470e8,0x08b4519,0x0494d36 },
|
|
{ 0x1a021f8,0x0135b25,0x0db0e61,0x06f2dbd,0x114c908,0x1b63b16,
|
|
0x14e55f8,0x02cda5c,0x0751cf2,0x1aab765,0x0928663,0x1c00336,
|
|
0x0edaca1,0x0590615,0x021f691,0x14e668f,0x0cdff41,0x1c9f6a6,
|
|
0x11f0335,0x02f888b,0x10098d7,0x0548dfb,0x131218d,0x0b3775f,
|
|
0x146f93b,0x18ad0f8,0x0795893,0x1a71767,0x1f8443d,0x0d56981,
|
|
0x1f25b50,0x097e209,0x1670f03,0x032c135,0x07b4a5c,0x0a0a07f,
|
|
0x134200f,0x070fa3d,0x11bcdda,0x0bd77a9,0x03cfdcc } },
|
|
/* 182 */
|
|
{ { 0x123e13d,0x015435a,0x02814db,0x105241a,0x1014a45,0x0b894b0,
|
|
0x0d1e39d,0x1d47aa5,0x07eb51b,0x0ba3033,0x03a4641,0x10c30f6,
|
|
0x08709f7,0x1434447,0x02bb621,0x1f9a805,0x1d7d94a,0x1bcd404,
|
|
0x084a6bc,0x0c065fc,0x008250c,0x194c1e2,0x1d792f9,0x1677d1c,
|
|
0x11bbb7a,0x1944c19,0x12d8631,0x0634065,0x19c4a4d,0x02d09fa,
|
|
0x188db76,0x1da9ec3,0x1ece345,0x18b8aed,0x1334795,0x0f74f55,
|
|
0x04a1ebd,0x062c6d3,0x1ba844e,0x01e7a35,0x089296d },
|
|
{ 0x0a82c97,0x09447e6,0x0372c59,0x1a284fd,0x06c6c12,0x1f6ed49,
|
|
0x13c1d30,0x17ccd52,0x0eaa01e,0x030070f,0x17a1b65,0x1cf861e,
|
|
0x1114abc,0x05a2b51,0x075c083,0x08584e8,0x013279f,0x05582d5,
|
|
0x108e11a,0x0c1f5fa,0x19e670b,0x0098c69,0x0863bfb,0x0416631,
|
|
0x1f1ac89,0x101f583,0x0360e67,0x03c7975,0x01a3010,0x09971e4,
|
|
0x16197e2,0x1998ccf,0x08bca7d,0x0303e57,0x19e689a,0x199dc35,
|
|
0x0ac0a12,0x0173266,0x13150c6,0x1ee5634,0x09233a2 } },
|
|
/* 183 */
|
|
{ { 0x0cbee17,0x146fb05,0x1371c5f,0x04b849f,0x0f0959c,0x07fe580,
|
|
0x0621f95,0x0d68de1,0x0d28511,0x0c9ef65,0x07e946e,0x09f1774,
|
|
0x1e0bfaa,0x08790c1,0x04927bf,0x0eef339,0x1589684,0x0fc9e59,
|
|
0x0c8b508,0x17f6fe4,0x1009284,0x0d6a157,0x10331c2,0x163ac2a,
|
|
0x122749b,0x035634f,0x09c5f0f,0x0dea167,0x1c5eeb7,0x14c2ddc,
|
|
0x17e2c87,0x148f076,0x0fb19ae,0x0e1f3ac,0x0e6d4b8,0x100990d,
|
|
0x12971ac,0x12c8497,0x00a46b2,0x0d243db,0x02bb26a },
|
|
{ 0x1f81416,0x1a21a8a,0x0ed2628,0x0f55feb,0x086e72e,0x0b930e0,
|
|
0x193780c,0x1fc7a3e,0x05c0a1c,0x0e03c36,0x00d004c,0x09b166d,
|
|
0x0d542ea,0x0d1cda6,0x1dc9ce8,0x04fe25e,0x0e1cbef,0x00a7f3f,
|
|
0x1aec9f7,0x1f813c2,0x1dc7ee7,0x0ba0872,0x1037330,0x08767bb,
|
|
0x0674219,0x0dbd1a3,0x00fcc70,0x052696c,0x0c10709,0x0f6ce11,
|
|
0x1ac061b,0x0f33f2c,0x17ee8ba,0x18449d1,0x12d0926,0x1c1e77f,
|
|
0x0e92d4d,0x130a239,0x1ac22eb,0x1f1c32d,0x0937cb3 } },
|
|
/* 184 */
|
|
{ { 0x0fbfdce,0x073be0b,0x13015f0,0x13931a9,0x0a034cc,0x0b96907,
|
|
0x1b5c909,0x079cec0,0x00019a8,0x030daae,0x05c58a6,0x1007e2b,
|
|
0x1b80ba2,0x02d07eb,0x1050774,0x155441e,0x13b4b0d,0x04432c8,
|
|
0x08e123b,0x10ae8d5,0x05d2e66,0x0d1f024,0x05b4569,0x0d20bba,
|
|
0x0c7743b,0x15d40e0,0x16062bc,0x1d8636f,0x174b78c,0x18ca695,
|
|
0x0a20363,0x0a87c5e,0x0659db2,0x03e0e65,0x09f67ec,0x0063707,
|
|
0x1f1048c,0x09bfee0,0x1a84619,0x00ef0b0,0x04d57bb },
|
|
{ 0x1b396b6,0x1bb4529,0x16b2f12,0x09276a3,0x1c8b24c,0x0570d9d,
|
|
0x047ae8c,0x18a67ca,0x1945147,0x09ddeca,0x1f8f3a2,0x00622f3,
|
|
0x146cc86,0x1fc905e,0x0c2859c,0x0c2c069,0x0eb6b25,0x1d99489,
|
|
0x145a360,0x1345493,0x1128bc6,0x1d7786e,0x0d25279,0x04d33c3,
|
|
0x1419a87,0x1b59309,0x1efc84d,0x0d8b08e,0x1971470,0x0c84d27,
|
|
0x17f956c,0x0f736e8,0x1d6eb75,0x19e42b1,0x0ca4237,0x076a6cb,
|
|
0x15fcfae,0x12bf21a,0x0aaa038,0x0312f3e,0x01067c1 } },
|
|
/* 185 */
|
|
{ { 0x0bf8883,0x0a84219,0x199f211,0x14dfa0c,0x0755286,0x0119aea,
|
|
0x03e3ddf,0x129ae16,0x02f4a2c,0x1c7306d,0x02b3d59,0x1159a23,
|
|
0x19a468d,0x1fadc86,0x04e0c2e,0x122099d,0x074ed4e,0x075258e,
|
|
0x1dddba9,0x0e62da4,0x0b12ac6,0x0e1b0dd,0x0e62b5d,0x02448a3,
|
|
0x1d48299,0x1d76191,0x014c290,0x0c88044,0x12d5a52,0x0997194,
|
|
0x0f0e911,0x0bfd9e3,0x148694b,0x1dc5c6d,0x05bb199,0x1dc9c0a,
|
|
0x04306ad,0x152cafd,0x05c96ce,0x123e69d,0x07e4f70 },
|
|
{ 0x1f70919,0x00b74db,0x0fd4fce,0x1a2d600,0x165216e,0x064cf2b,
|
|
0x13fd1de,0x0208d8d,0x030a518,0x152d5f4,0x1ca36f9,0x13cc8bc,
|
|
0x16ef6f4,0x056677e,0x175cfab,0x1e7eedf,0x06f8c37,0x1f61ca7,
|
|
0x1901ff0,0x0410056,0x1cbd733,0x1d4b312,0x0623a3d,0x157f601,
|
|
0x123637c,0x0cd4194,0x1d01fcd,0x0b1753b,0x1fae502,0x1772e65,
|
|
0x04ffc06,0x1fc4a30,0x1eaeace,0x0e5d0fd,0x05860fc,0x0b38d3e,
|
|
0x1eadcdb,0x162c56c,0x1a2f544,0x1a8d999,0x02ae49c } },
|
|
/* 186 */
|
|
{ { 0x00849f2,0x0d871e2,0x063048e,0x1b48821,0x1136a4c,0x03fb24a,
|
|
0x16a6795,0x18cc2a6,0x07a9bba,0x1725ee2,0x11ebda4,0x0c8ca6a,
|
|
0x0a195a1,0x05a3d3a,0x1b2cc66,0x145650b,0x1fc9de6,0x093c2a9,
|
|
0x18ae94b,0x1807141,0x1a93471,0x041ade5,0x04ae86e,0x063d944,
|
|
0x150da6f,0x1636a5f,0x1a00acc,0x028dc7e,0x04c8c4d,0x00989e3,
|
|
0x05c3270,0x1dda425,0x130f12d,0x02987d6,0x1fee71a,0x0336eb7,
|
|
0x0918de5,0x00569f4,0x1c6dc8f,0x0a54e6e,0x0180e9d },
|
|
{ 0x1ab77b0,0x12a1794,0x18a30c5,0x19ef5dc,0x1d411d9,0x1e17a06,
|
|
0x01a14d4,0x19e0898,0x04b0ae4,0x1c6e3f2,0x1099bd8,0x030b2bf,
|
|
0x1da0924,0x1e97f5b,0x07699c7,0x12f30c7,0x0d55ea3,0x12b42c7,
|
|
0x03ce0ca,0x129e62b,0x18317a6,0x03698b6,0x0a508cf,0x146b4f7,
|
|
0x0cb2630,0x09d97e5,0x17c7fdc,0x1df1efb,0x0ee2f3f,0x0292acf,
|
|
0x12a2e6d,0x02ada0c,0x1b4f91b,0x07e7e68,0x1b08bd7,0x022ef0c,
|
|
0x1777eb4,0x1e12b31,0x016d04a,0x079b157,0x021ca6f } },
|
|
/* 187 */
|
|
{ { 0x1e66635,0x11589d1,0x1abc385,0x16553ee,0x1ef20a2,0x0d99ab0,
|
|
0x0e8c11b,0x11b568e,0x17802bb,0x0205ebb,0x06d1302,0x1ebd4d3,
|
|
0x115b6ba,0x0d9103f,0x1846400,0x0020b8d,0x0a9790b,0x072ef0b,
|
|
0x0d9fc01,0x025e2bb,0x1d2522b,0x02c5012,0x0617eb5,0x0142284,
|
|
0x16953df,0x0605e67,0x0fd140d,0x1884253,0x077bff4,0x02000e1,
|
|
0x0603dd0,0x050153c,0x0440b4c,0x1515a37,0x03d610a,0x1eecfbd,
|
|
0x05e8d94,0x11055c0,0x1d8d4f7,0x0b24044,0x05aff58 },
|
|
{ 0x0458e40,0x1669054,0x0af6016,0x10292e6,0x1a5557d,0x0e5396a,
|
|
0x104c57c,0x0478e0e,0x0952b53,0x197134e,0x13eb7df,0x0aacc92,
|
|
0x065c592,0x0d3e933,0x0edeb34,0x050ca2a,0x03d86fe,0x1d36f83,
|
|
0x1f54eda,0x03b626a,0x0d011e9,0x04f49f5,0x04656ee,0x0c77fcd,
|
|
0x1e1af29,0x0431eb8,0x0a209e2,0x1565738,0x059b6ff,0x13491dc,
|
|
0x145de0d,0x1ee053b,0x0695174,0x022b0b7,0x01d9ee6,0x138f30f,
|
|
0x1907d84,0x1da78ea,0x0a5dd93,0x03911b1,0x03eab7e } },
|
|
/* 188 */
|
|
{ { 0x0e5718b,0x14a5b29,0x07a71ce,0x09e99dc,0x03aefa5,0x1f76f57,
|
|
0x0798d54,0x034ca9d,0x15f3aca,0x12a0f0d,0x00cc5bc,0x09121a1,
|
|
0x0ed7129,0x1dbfca8,0x196bd8f,0x07c94f2,0x00dc74e,0x06c7e4f,
|
|
0x0bde7af,0x1c91a5d,0x07e6b4e,0x1545bbc,0x09162a1,0x199d5e1,
|
|
0x1621ff7,0x006ec63,0x1f7d9e6,0x0451ddf,0x1067278,0x03a17c8,
|
|
0x0a48435,0x160fc6c,0x1f63501,0x0f14ec8,0x0719e5c,0x0a882ec,
|
|
0x03a3b8a,0x06632f8,0x0551303,0x09e71c1,0x03491da },
|
|
{ 0x1062eae,0x1682365,0x1db59c1,0x0aba10e,0x0e7db73,0x118ae97,
|
|
0x00148a4,0x1b701bd,0x0c402bb,0x03c2b31,0x14ccdd0,0x04b84dd,
|
|
0x135f935,0x1eab476,0x1a85359,0x1163cd9,0x1896688,0x0c8b508,
|
|
0x171c59d,0x1aa40ab,0x1df20fb,0x1bf22ba,0x00cf441,0x012466b,
|
|
0x1100aec,0x1c4a749,0x05b3614,0x1f3c3a0,0x0263682,0x1b92a19,
|
|
0x15fbaf4,0x037499f,0x01d172b,0x02c1c20,0x0e755d3,0x1c6efb5,
|
|
0x00d517d,0x1534ac4,0x16862ba,0x1fad5a2,0x00c843d } },
|
|
/* 189 */
|
|
{ { 0x1373300,0x008ffe4,0x0c01156,0x1533fb8,0x1c39332,0x1e5b2a8,
|
|
0x0e070d4,0x04fc337,0x096a83d,0x1a5c925,0x18fc69d,0x1f9765d,
|
|
0x07cbfc8,0x0086ab6,0x09e3b10,0x15ef35e,0x02fe0ab,0x1b7ef34,
|
|
0x0ce6baf,0x0da0e4e,0x1db6756,0x0eb8902,0x0f4d6b5,0x0a393a1,
|
|
0x1e69470,0x13e5add,0x034e8c1,0x0efb690,0x0d75305,0x1faa2b9,
|
|
0x0f4b1c3,0x1c0db0a,0x0615aec,0x1fdaef4,0x132c16a,0x0ee3333,
|
|
0x0a0a8ed,0x17e4b5f,0x17da7bb,0x13a6bed,0x02dcc46 },
|
|
{ 0x05f0e77,0x1668363,0x052b329,0x017ae36,0x1dcc798,0x09e6006,
|
|
0x07e2cf2,0x0af6c44,0x1ae8cbf,0x0fe6ad9,0x0398ff7,0x0e7eedf,
|
|
0x17bc929,0x0370995,0x01228d0,0x193c5d3,0x003d51e,0x12662cd,
|
|
0x08cc206,0x1a65767,0x066b9c9,0x0940742,0x0004841,0x17ce52a,
|
|
0x0032a1b,0x0246158,0x08924e1,0x17f8cae,0x1ba0ffd,0x10675b5,
|
|
0x00ba5ca,0x1815290,0x00c0a4f,0x0c5e3fb,0x0731667,0x11ec588,
|
|
0x112da0b,0x064b771,0x1e7f208,0x1b79b7b,0x05a1a65 } },
|
|
/* 190 */
|
|
{ { 0x0485684,0x1348d21,0x0326fee,0x125388e,0x013116b,0x15028cb,
|
|
0x065c798,0x1b56960,0x05ff499,0x1922d53,0x0e3bffc,0x0fe94a4,
|
|
0x15c2ef8,0x064eaa8,0x1b71aeb,0x1595982,0x07e2dbd,0x1ad3f91,
|
|
0x06eebb2,0x1b55895,0x18858de,0x16973e4,0x1fcc229,0x112ab27,
|
|
0x12fc2e6,0x108a637,0x145df81,0x0cabe50,0x0b1bee3,0x0683180,
|
|
0x15298fa,0x02782f6,0x0d0ce79,0x1a1315f,0x18d7125,0x0f94957,
|
|
0x1c4e403,0x1a250bd,0x1ef67d2,0x133dfcb,0x05ae950 },
|
|
{ 0x04f7455,0x12f73c0,0x1a0848b,0x0e440cc,0x141a499,0x0af1999,
|
|
0x130c5de,0x1db2fa4,0x0e48efc,0x17a091e,0x0f08704,0x1b2433f,
|
|
0x0ee8738,0x0331d1d,0x0ef7184,0x14db776,0x0c28593,0x09b01ec,
|
|
0x0f06b1d,0x044fe5c,0x0519926,0x002f557,0x1faa4ab,0x0d02559,
|
|
0x16f0bfd,0x16e2dac,0x13f0aa0,0x19cfd08,0x122b273,0x040d31a,
|
|
0x054e101,0x0a50cf1,0x16088b1,0x0434441,0x1f30996,0x1843ff6,
|
|
0x0f4a7ca,0x1198b09,0x14a6032,0x0fd47db,0x0411066 } },
|
|
/* 191 */
|
|
{ { 0x0d04b63,0x181abe1,0x0862060,0x1be9253,0x1fc5a34,0x08caef9,
|
|
0x1db688b,0x0e78e77,0x1cb4324,0x06f97c4,0x1fc4e05,0x1cb9d32,
|
|
0x14345af,0x05cb027,0x18fd7e6,0x015cbb1,0x0e950c1,0x1d6bca1,
|
|
0x1b497fc,0x1aa88fd,0x00cccef,0x0f0739e,0x0fda394,0x0a9f499,
|
|
0x0d591ab,0x0462d8d,0x144ad87,0x1778220,0x0bf7608,0x1489dad,
|
|
0x126ee4c,0x003cf2c,0x11231be,0x065f3ed,0x1a44103,0x13a1507,
|
|
0x10a96db,0x0f2137c,0x047a8f7,0x08a69be,0x01cceb6 },
|
|
{ 0x06d0f55,0x0862786,0x1274b48,0x1738ce7,0x0cadf61,0x071fddb,
|
|
0x06466a7,0x1c9baff,0x093b063,0x1afa4a6,0x0a4ef84,0x167828b,
|
|
0x1c580bd,0x07a977b,0x01c8cc8,0x176d49b,0x0e88814,0x13a6c3b,
|
|
0x1ea5f7b,0x1ee4758,0x18334f6,0x181f1e6,0x1f78ae3,0x0e404e0,
|
|
0x0f082ae,0x03730b1,0x1377e92,0x111d85a,0x1a17c6e,0x042cc69,
|
|
0x06b6597,0x073002e,0x0e59e54,0x1b59131,0x0176efb,0x06156c5,
|
|
0x0d48b20,0x1a28caa,0x17a8cf3,0x0669d44,0x01f1752 } },
|
|
/* 192 */
|
|
{ { 0x067ea91,0x13b2d9a,0x1116022,0x1dfa5b3,0x1f4632e,0x195e379,
|
|
0x171b673,0x15cf6eb,0x0359813,0x1e46920,0x12f637b,0x0413c89,
|
|
0x0223ecb,0x10a92b1,0x0e8438c,0x1c334b3,0x1343f1e,0x1fd0a6c,
|
|
0x0c3123d,0x0f8437f,0x1437df9,0x0875186,0x11398a2,0x028eb85,
|
|
0x0e2a465,0x152d943,0x104999c,0x123e03c,0x0ab3b82,0x0d2e18d,
|
|
0x1b271bf,0x1c2fa45,0x1277a5a,0x185d6db,0x160e453,0x037b11d,
|
|
0x0a2392e,0x182e8db,0x0f0af42,0x120cb12,0x04cb8af },
|
|
{ 0x14b1953,0x0102bdd,0x1bba8ac,0x09eb2fe,0x0ce08b4,0x1209642,
|
|
0x1766d79,0x0330a9e,0x1b3cd49,0x0899316,0x0aed746,0x05c8dc8,
|
|
0x0090276,0x0bc73fb,0x157239b,0x182d906,0x02438b6,0x0477d54,
|
|
0x1543d86,0x0e6f21c,0x178ed01,0x1172beb,0x0462bd1,0x0b68e28,
|
|
0x0d5e871,0x07cd0b5,0x0d077a9,0x000b2d8,0x0ca6109,0x1e19140,
|
|
0x084aa55,0x06e98cb,0x1aee800,0x0020a17,0x049d402,0x03b620a,
|
|
0x1f080fa,0x0edc98f,0x1e3f230,0x04baf30,0x0486a5c } },
|
|
/* 193 */
|
|
{ { 0x01b4f36,0x0f109ca,0x13e4148,0x09f0076,0x1aacfb1,0x12a5d45,
|
|
0x188b94a,0x0d9fbe3,0x08fe479,0x07d5ddd,0x0eb2dab,0x11b6b1b,
|
|
0x11ae078,0x00cefd2,0x0635cdb,0x02dddbf,0x06a35a7,0x18aae14,
|
|
0x1219186,0x1a8ced3,0x0a5ebe7,0x07b1d32,0x142d8e0,0x0c124c4,
|
|
0x019149f,0x0d98a5a,0x028b7f1,0x12334fa,0x1466ac0,0x0d2ae77,
|
|
0x1b31153,0x0d30d55,0x1fa4a24,0x04e76c9,0x05c5c69,0x1aa1216,
|
|
0x01fa75a,0x178eb66,0x1015180,0x112f1c9,0x05d269f },
|
|
{ 0x0920419,0x001860a,0x1ce4e9d,0x11212d0,0x0845d86,0x1b87d30,
|
|
0x05313ba,0x1970373,0x1d9fc5b,0x1e55036,0x1e3cb6a,0x084feb1,
|
|
0x0a06539,0x18ee295,0x1217d9e,0x037546b,0x1722c91,0x02d3ec6,
|
|
0x1b0b60d,0x0200b95,0x1347404,0x023d472,0x0d61a29,0x1ca2587,
|
|
0x0180b8d,0x0758277,0x148445a,0x1b54cdc,0x17cd8a4,0x0ed5918,
|
|
0x1db02f5,0x0c22c9b,0x1d4185d,0x16be4d0,0x089876e,0x0759db9,
|
|
0x09b0268,0x125ad60,0x1543c3f,0x0b44db2,0x08ac999 } },
|
|
/* 194 */
|
|
{ { 0x040a39d,0x06e4d93,0x07e6cb2,0x11dbc19,0x01ff0b3,0x165d051,
|
|
0x1a6f687,0x02ee9e8,0x1080d04,0x1481666,0x0518122,0x1465e93,
|
|
0x15e956f,0x0bbb558,0x03e173e,0x1e92469,0x0ee0066,0x1e10fe3,
|
|
0x1bbbcd9,0x03d7fdf,0x05ed35b,0x0e2309f,0x1e01160,0x0d740e2,
|
|
0x1e8e6ea,0x1f6e5ef,0x0a5435c,0x1bf9546,0x048889d,0x1c9b0ed,
|
|
0x14725d1,0x1b75ff7,0x0867c8c,0x17573e7,0x0c7c72e,0x11a4ce8,
|
|
0x097912c,0x12a822c,0x07935a0,0x1b9afd4,0x00c7c1d },
|
|
{ 0x0e963a7,0x118660e,0x0b794ea,0x19898bf,0x1352f64,0x1457dfb,
|
|
0x08be0a0,0x00e5735,0x0ca2121,0x0139e2b,0x15db719,0x0ca90b4,
|
|
0x1caadd7,0x085ae3b,0x05ab0fa,0x1e736c3,0x09fd1aa,0x0106a1f,
|
|
0x14172f1,0x1240c59,0x12fdfc3,0x192607f,0x05058e1,0x1d043cc,
|
|
0x0b8d82a,0x1f86799,0x0cfe9e8,0x1eb1f28,0x04ca925,0x0e96fb2,
|
|
0x17ebafc,0x032314e,0x0061563,0x1b08c06,0x17b5ae1,0x02f3136,
|
|
0x0d41244,0x1a1222d,0x0ceaefc,0x15c3bec,0x024ffc9 } },
|
|
/* 195 */
|
|
{ { 0x1c7cb2b,0x06e02c9,0x0fee27f,0x0ab200a,0x01243b9,0x011a1e6,
|
|
0x1af3d86,0x0c6c03b,0x166c18a,0x122a377,0x04ca1cd,0x0e03d92,
|
|
0x11a5290,0x1cbc461,0x16e009b,0x1efaf86,0x02a92d1,0x04295c3,
|
|
0x0a9e5ca,0x13960a1,0x0005180,0x1e51e59,0x025f519,0x1eb728d,
|
|
0x077c09e,0x0c27906,0x0bc8906,0x066e588,0x1bb206c,0x1f06f9a,
|
|
0x0d76814,0x1538281,0x026c6d0,0x17d99de,0x10332d5,0x10c39f9,
|
|
0x099b396,0x1e7cf79,0x06e9070,0x1a280c4,0x089e4d3 },
|
|
{ 0x05a9be3,0x14073d2,0x1ef74d7,0x100e6ad,0x04daa57,0x13de17e,
|
|
0x158bae5,0x1c6030d,0x047cd16,0x18133cf,0x033a6e9,0x1804be6,
|
|
0x10ca2f1,0x0fc327a,0x0816d18,0x03acde2,0x1978506,0x13feb6b,
|
|
0x0822027,0x1b89ed1,0x1ae247e,0x04cd269,0x176b011,0x03f3b50,
|
|
0x0664a6d,0x138fc22,0x135ea0e,0x1e619d0,0x0c33f19,0x15d6755,
|
|
0x0afa4e0,0x1290c45,0x1033831,0x00f590f,0x12ebdda,0x0f606f4,
|
|
0x19a1b5c,0x0b54844,0x143ef45,0x0dfcde3,0x0675d3e } },
|
|
/* 196 */
|
|
{ { 0x07193e5,0x13ffeb8,0x039765d,0x030206b,0x0478aa9,0x06c77bf,
|
|
0x1e7fcca,0x14eac69,0x06dbbd9,0x09d0774,0x055a1a4,0x12d0fc4,
|
|
0x18379b2,0x04eced1,0x0fd042a,0x069a520,0x1b91b13,0x0ecfc6b,
|
|
0x160bbed,0x0e84537,0x07789fe,0x111c01e,0x16d5a2d,0x1a4a689,
|
|
0x1a350d3,0x1f449f4,0x01c9125,0x0b386b6,0x09e23b5,0x0a1b50b,
|
|
0x1a711cb,0x198b698,0x1864632,0x1fa9884,0x16760f1,0x113edae,
|
|
0x1e49788,0x0e78ed8,0x0692ea4,0x1fcc15e,0x05f7f92 },
|
|
{ 0x145167e,0x10e6302,0x0383c62,0x055ff51,0x15ee2e0,0x153de7a,
|
|
0x1fd450c,0x0cc499b,0x0a75108,0x1c16d21,0x046bddc,0x023e80a,
|
|
0x03e894c,0x15578a1,0x13938c4,0x1a55d54,0x0f0f63d,0x0c61e9b,
|
|
0x1d9818d,0x192aa1a,0x1eabfc5,0x189bf53,0x00494dc,0x172a1ec,
|
|
0x0d59839,0x021152e,0x050398d,0x0b41ec0,0x0c70459,0x11c7795,
|
|
0x1ce4178,0x088d61e,0x0bacc0e,0x02bc522,0x01bb112,0x0699a84,
|
|
0x05bd780,0x1d8d555,0x11634d9,0x1b21456,0x025bece } },
|
|
/* 197 */
|
|
{ { 0x033a8fb,0x139c106,0x10741e6,0x021e4bb,0x0fbf6cd,0x0a415b6,
|
|
0x1cfe31b,0x0949ff8,0x007bf84,0x128f8c6,0x058bc0f,0x046cb32,
|
|
0x11a7651,0x0a009c0,0x1669d38,0x0314158,0x065e550,0x0cabd34,
|
|
0x0f2826c,0x18a37bc,0x053fe1e,0x19d4b01,0x0f031fa,0x1c07f09,
|
|
0x1fd147d,0x184f41d,0x054bef6,0x00a81da,0x015ec1c,0x176ee75,
|
|
0x01dae94,0x0964c26,0x1d30ed5,0x0b90379,0x0ba3a0e,0x1537af7,
|
|
0x096373a,0x06c3490,0x0fd8fc8,0x0978761,0x00a616a },
|
|
{ 0x01339c9,0x0f9f6b7,0x029881d,0x057f160,0x1afaa07,0x06cda3b,
|
|
0x1b20af3,0x18fbf5f,0x100ca54,0x1898ac7,0x10c6b91,0x05e2717,
|
|
0x0a44910,0x1886fe4,0x063c560,0x0a9a95f,0x07559e9,0x064f790,
|
|
0x149e831,0x0435f38,0x0023e80,0x1bbd0c9,0x1ba0049,0x16046ee,
|
|
0x1538c7f,0x0a8b1af,0x1fa327a,0x1be32e9,0x0c90975,0x1d768ae,
|
|
0x1700a1f,0x1ef4a22,0x00728f0,0x0311efd,0x0f983eb,0x1321b7f,
|
|
0x0311ba0,0x0a07ea0,0x11932a3,0x09c0f8c,0x0876d15 } },
|
|
/* 198 */
|
|
{ { 0x0d3ea8a,0x06b6961,0x003b4e9,0x175084c,0x16be681,0x0383391,
|
|
0x0403790,0x0f78a7e,0x06a7d7a,0x1f2db7f,0x186a0f8,0x09f2bab,
|
|
0x0a6e699,0x1b04be1,0x12b3489,0x020220f,0x1baa679,0x0096cc6,
|
|
0x00b8389,0x1888c22,0x072addf,0x016a499,0x120576f,0x086cd2c,
|
|
0x0e64ba9,0x1c83f1c,0x08cacaf,0x12c1d63,0x08e28b4,0x1a92ec9,
|
|
0x07b6915,0x0540ef9,0x0f75b39,0x10e8039,0x12edff5,0x0c4eec1,
|
|
0x0f4b145,0x11ae8d8,0x05c02bc,0x077ceda,0x03040c2 },
|
|
{ 0x0fa9a70,0x0e2ada7,0x1842c43,0x1ea7d0c,0x14de414,0x1c513fe,
|
|
0x1044c27,0x0787b2b,0x106661d,0x02884d2,0x0d44f94,0x1294c1d,
|
|
0x0bcaa29,0x0f3e99c,0x19054dc,0x1ce3e7d,0x1fc4651,0x027e8a2,
|
|
0x0f0c4ed,0x17f0719,0x015051b,0x1c0f5c9,0x0c0e781,0x17eb58f,
|
|
0x16b4414,0x0467434,0x022f835,0x1acce31,0x0f2b6f2,0x197aeec,
|
|
0x02afa4e,0x1d714ff,0x1dfd1e7,0x1a8e2e0,0x176643d,0x1d0c567,
|
|
0x032a74b,0x18d6ac5,0x126887a,0x1343d77,0x05486d7 } },
|
|
/* 199 */
|
|
{ { 0x1359e13,0x11a7fd0,0x01472cb,0x1e5032c,0x002d8db,0x0b25af1,
|
|
0x008f48d,0x025d2bc,0x042f6ac,0x189a05b,0x0dc977e,0x10a56ca,
|
|
0x0d543ba,0x0692335,0x0bb735a,0x0e51703,0x024547c,0x0dfbc01,
|
|
0x15a7ed9,0x1f14232,0x0ec9559,0x116fd91,0x1416de9,0x1dabca4,
|
|
0x075409e,0x1888388,0x00a67db,0x1913251,0x16f8c79,0x09309ed,
|
|
0x0a69f5a,0x16794f3,0x0eb7fb3,0x0b05818,0x0ee3ec8,0x1595733,
|
|
0x128b409,0x0092b46,0x17e2f48,0x01eb588,0x0380f1b },
|
|
{ 0x0a0068f,0x0cf35f3,0x1d4f02e,0x15914e6,0x0b67cf2,0x1d75be2,
|
|
0x09522cb,0x1874d93,0x1340260,0x1a0bfcc,0x1dce79f,0x10ab981,
|
|
0x1a8ee56,0x1c04a4e,0x02d443d,0x0ddffe1,0x1c28d5c,0x1d8bb87,
|
|
0x165a9ee,0x0b57ddf,0x1a2ab4f,0x1b79332,0x081ec44,0x003b9f3,
|
|
0x180a4b6,0x06317d9,0x1058afb,0x19006c2,0x0b83b3c,0x1dcb773,
|
|
0x1acd263,0x15182fd,0x09b0fd6,0x1f7e175,0x16ea85d,0x1cb0696,
|
|
0x1b110b3,0x08227aa,0x0a17a4a,0x1dbd7ae,0x04abedd } },
|
|
/* 200 */
|
|
{ { 0x00ef376,0x0f0dcb8,0x0ffccd5,0x14cd9b5,0x156e5d9,0x143b236,
|
|
0x095d51f,0x0d367b8,0x000f793,0x07a25c5,0x14b8a4a,0x163d418,
|
|
0x1208c32,0x1b94d9c,0x1e37848,0x0473ab4,0x19ab26d,0x1a0c228,
|
|
0x033929a,0x0d696fc,0x09f923f,0x0556595,0x08d7dbe,0x00c94b2,
|
|
0x1c454e2,0x1175dc5,0x106fcc1,0x0fdfa06,0x1ff6f93,0x141dca6,
|
|
0x019aeb1,0x1154ff4,0x1364b1e,0x19ba2e1,0x1cab382,0x1e0c2ce,
|
|
0x11e3fb0,0x1846846,0x0cb4d1b,0x16631c2,0x06a20ab },
|
|
{ 0x085cbc7,0x1880b35,0x0a9faa0,0x0d269f3,0x1099094,0x1c78d9e,
|
|
0x042239d,0x1338442,0x12247b7,0x1527fc7,0x121339f,0x1ae28a8,
|
|
0x04b3171,0x07cc61b,0x100e525,0x028b052,0x1f397df,0x12ed488,
|
|
0x050e445,0x0b01261,0x18bca6b,0x0d0ba11,0x1d7e542,0x012eb1a,
|
|
0x1182182,0x0e87f5a,0x0691e49,0x1c18c04,0x0a315ea,0x134a57c,
|
|
0x0dc3a51,0x0d75a09,0x07af8a3,0x1223ed7,0x19ffc1c,0x1c8982b,
|
|
0x05456ff,0x0233455,0x0e5dd46,0x14f7e6d,0x045e353 } },
|
|
/* 201 */
|
|
{ { 0x1092f71,0x0b3b249,0x15c5d81,0x05eb725,0x0b66b6c,0x045b62f,
|
|
0x0526f8b,0x07d3b66,0x020c036,0x117ac1d,0x15c25fd,0x1a66079,
|
|
0x0c688ac,0x15dc8b5,0x14303e3,0x1361d0b,0x02c84c1,0x08dfba3,
|
|
0x1129ab4,0x1dabf2f,0x1369c76,0x1d688cf,0x1b22e22,0x1ca1707,
|
|
0x0371beb,0x1532cdc,0x02199c1,0x198d2a1,0x173d2c0,0x1ad1fc1,
|
|
0x1ed4c71,0x054b405,0x01cd3a3,0x0d0e827,0x1de368e,0x1dd04e8,
|
|
0x15da333,0x1e2dddb,0x0f4dbb7,0x04994f3,0x015941f },
|
|
{ 0x17dd512,0x0607c53,0x17d90ba,0x0e3b86c,0x091b59a,0x1a9c315,
|
|
0x0533421,0x195d01a,0x1d272fa,0x1121186,0x1f2d685,0x182c804,
|
|
0x03eea3e,0x00f7cf8,0x1c02d67,0x0291b82,0x1270da3,0x0ea08e0,
|
|
0x10606bc,0x1dc8918,0x100b801,0x0ccf1d4,0x1b7ca15,0x0135ffb,
|
|
0x1b0bd0d,0x0122eb3,0x1a2cdc0,0x1073bf2,0x1836b8d,0x03f0737,
|
|
0x124ed8c,0x17a6403,0x182e588,0x0815da9,0x09ade87,0x12c6db1,
|
|
0x168641e,0x1bedbb4,0x0b40dc2,0x094231f,0x06d17c3 } },
|
|
/* 202 */
|
|
{ { 0x181c99b,0x04420e0,0x12bf3d8,0x0390f7b,0x165dc90,0x106d5f5,
|
|
0x0d11cdc,0x0b768c1,0x0537751,0x03ce1cb,0x1b09dd3,0x045c152,
|
|
0x00d447f,0x15607a2,0x05484c0,0x1075a1b,0x06bc905,0x0419859,
|
|
0x0a24128,0x1d2ef52,0x0b18e25,0x0cc2e28,0x077abff,0x15abed4,
|
|
0x1bcb7a5,0x16ae7a6,0x07228df,0x179a003,0x1850b6c,0x0ec80f4,
|
|
0x015e11b,0x16171cc,0x0c8194a,0x197c80d,0x15c4d04,0x1772e50,
|
|
0x156ee28,0x14f8a4f,0x0753933,0x1487d3c,0x01ab9b5 },
|
|
{ 0x14fa7a3,0x0d5c918,0x058c81b,0x008f1ff,0x0c4af0f,0x06cfede,
|
|
0x05c4e41,0x1fc999c,0x112c045,0x0105175,0x1db5f6b,0x08f1fb1,
|
|
0x1a44fc5,0x053db7f,0x1b9cb17,0x1eeb110,0x09b6fd6,0x0bfd229,
|
|
0x0aa0835,0x03a3632,0x11494df,0x0f93c4f,0x0f604be,0x176a7a4,
|
|
0x0f083aa,0x1994c21,0x0ca80ea,0x0c90a73,0x1125022,0x104858a,
|
|
0x1558c73,0x0e63ed7,0x1294d15,0x1731a70,0x187650d,0x1f64526,
|
|
0x1ca966a,0x0140e21,0x0cfb631,0x0ad8435,0x024b349 } },
|
|
/* 203 */
|
|
{ { 0x19824e2,0x0e5c332,0x1d3126f,0x109c27c,0x0dc4ce4,0x1f0f753,
|
|
0x06899ae,0x0af4980,0x11e3ec4,0x1d95c73,0x0a392d1,0x0bc05eb,
|
|
0x0d7e8b1,0x1199a98,0x07adb9b,0x0a405d0,0x09e17a4,0x1d65d1b,
|
|
0x1c39327,0x082863a,0x1eb8812,0x059f095,0x10642bd,0x1e90dfb,
|
|
0x1052311,0x1e72993,0x04a7eca,0x1ed883c,0x0f6c089,0x03f5db8,
|
|
0x1def98a,0x07fd688,0x079850a,0x18c5d8a,0x0c466f3,0x01f9fbf,
|
|
0x1a80d04,0x0e1497e,0x16fe649,0x1cafc78,0x0212d65 },
|
|
{ 0x015cf08,0x0d9c365,0x0bac8eb,0x0903c2e,0x0dfa4ac,0x0168602,
|
|
0x0fe4d35,0x18f3a3b,0x174404d,0x0e7b039,0x0aff376,0x0883d26,
|
|
0x1860508,0x0e34154,0x1a44328,0x0398135,0x01841ac,0x04a947e,
|
|
0x0efb58c,0x02415db,0x1250e6a,0x1618667,0x0538387,0x1177e5f,
|
|
0x0ba54e5,0x00aff42,0x1e7ea91,0x0cda169,0x0e7ce5c,0x18f3f67,
|
|
0x0e83163,0x0df4d0e,0x01d43eb,0x189a43d,0x1680e67,0x0f2d8d8,
|
|
0x06727ab,0x17cd557,0x0911f9b,0x0a934b8,0x066afa5 } },
|
|
/* 204 */
|
|
{ { 0x180e91d,0x155d464,0x1beb696,0x12d5931,0x093cf50,0x1193315,
|
|
0x0382a36,0x07d6132,0x0008145,0x0e90a98,0x077a100,0x067c7ae,
|
|
0x122bb0d,0x1f0cd00,0x17db600,0x071ce8c,0x14c78a8,0x02c817f,
|
|
0x04c4d23,0x055f6e3,0x057b74e,0x0bce7d8,0x0924c9d,0x1a07f1f,
|
|
0x0a6423a,0x0053b0f,0x1563fe9,0x0fa9848,0x087e30b,0x006cbbd,
|
|
0x09ad7a7,0x193909a,0x1c5edba,0x0b1d068,0x0e68f46,0x1bd9510,
|
|
0x0bf6bf0,0x17979af,0x0af7ef1,0x0621ab1,0x001ef06 },
|
|
{ 0x0cdcbb0,0x0818b1f,0x0554afe,0x104f839,0x19e2d72,0x1ae4980,
|
|
0x1c0c255,0x0613ca4,0x1969839,0x0e0e2d4,0x020b7c3,0x01fef9a,
|
|
0x11ef9f8,0x0fcbf02,0x04541d7,0x036ab9b,0x1fe9cc6,0x079437f,
|
|
0x03c9331,0x1b671f0,0x1ae3352,0x161b291,0x1b66e67,0x1620953,
|
|
0x08ca810,0x1d6884d,0x1cc1480,0x04e01fc,0x1400f5c,0x11273b4,
|
|
0x0b0a8bb,0x1dc188a,0x195d399,0x01520ea,0x15abdfc,0x0e156eb,
|
|
0x0db730b,0x08404c8,0x04808d0,0x1fabd1a,0x00e4f5f } },
|
|
/* 205 */
|
|
{ { 0x1f14c38,0x0322207,0x07caf47,0x155d9c2,0x1a5b59f,0x17b1984,
|
|
0x0169c8a,0x1dd548c,0x082af24,0x0e4fb2d,0x0845677,0x17fdd73,
|
|
0x0ff4ee4,0x1a74275,0x18f41d9,0x1559c48,0x1e00e0b,0x1c465f0,
|
|
0x17eaf72,0x0ad1d5a,0x199d7ca,0x1262bf5,0x0f60354,0x17d30e7,
|
|
0x0572ce9,0x02f4e23,0x15cc02e,0x03143b9,0x1541769,0x0989207,
|
|
0x0d92488,0x16b6284,0x1e324ff,0x078b57b,0x140490d,0x1881bb4,
|
|
0x0133d97,0x019a10d,0x1c08022,0x0c210ed,0x033d411 },
|
|
{ 0x078e5ec,0x0d1b5cc,0x08c9d4c,0x028d230,0x1de3e32,0x1182322,
|
|
0x068cf42,0x0b3a2bf,0x1aa1736,0x1a60dc3,0x1753f9c,0x0945f24,
|
|
0x14ac209,0x0131587,0x1259687,0x0b97887,0x03e447d,0x03ace48,
|
|
0x148e4c0,0x1e42bc0,0x1f3492a,0x0f8fac9,0x1ffedb5,0x19bb6bf,
|
|
0x03b4bc3,0x00432ca,0x12ff755,0x1a07453,0x0d76c09,0x0d358cc,
|
|
0x1663df3,0x181e4f6,0x0790a22,0x0c667e0,0x0a1232d,0x1974aaf,
|
|
0x16c54fd,0x110296b,0x0d19964,0x1548f6d,0x02d3de7 } },
|
|
/* 206 */
|
|
{ { 0x1add3b7,0x13a3132,0x10aaab7,0x0b57e49,0x05888f3,0x12bec9f,
|
|
0x1272b86,0x17fa82a,0x02c76f7,0x11170c7,0x080acc3,0x11d57c6,
|
|
0x0a67f28,0x0e8e878,0x0699ae8,0x15a316f,0x1492881,0x087055b,
|
|
0x1eb6c3a,0x04810d8,0x132f7d4,0x0294210,0x01c30cb,0x1f3413d,
|
|
0x077f158,0x0c4c2c2,0x0bb0095,0x045526e,0x0987774,0x062e528,
|
|
0x162f90a,0x0aecc00,0x1b79564,0x19be7a2,0x18c655f,0x12d8ff8,
|
|
0x1631628,0x1811eee,0x04a9a2d,0x16cb638,0x047003b },
|
|
{ 0x11c1c96,0x000e0e4,0x05c3665,0x124f425,0x0a5dcdf,0x014883d,
|
|
0x0b85f0f,0x0207572,0x1a3fe47,0x17e747b,0x0663b89,0x1abc9dd,
|
|
0x18b0d09,0x071d20f,0x0988812,0x14a0d5f,0x0a5a26c,0x158e009,
|
|
0x06d5c94,0x1ee6993,0x1fe12c6,0x0fa897b,0x0424f5e,0x1dc334c,
|
|
0x0906eac,0x1531798,0x0415b47,0x17ff070,0x135f216,0x0c2b77f,
|
|
0x091871d,0x1835a44,0x007e978,0x07ef437,0x1285ac8,0x165994d,
|
|
0x033fe81,0x06b696b,0x0b39aad,0x00960d4,0x073dff5 } },
|
|
/* 207 */
|
|
{ { 0x0e20fb8,0x0ac02ec,0x0fc22d8,0x09056a6,0x1c6873e,0x142a653,
|
|
0x1c0055a,0x022a40b,0x0cb3692,0x1ff6356,0x024ade1,0x01d98fe,
|
|
0x0c1fa3c,0x1422ff2,0x0d991fb,0x1e224b6,0x085f8b1,0x1ea3c0f,
|
|
0x0c3c69b,0x04d0731,0x0b92c65,0x166e5c7,0x13bae31,0x0bedaa5,
|
|
0x10ead8e,0x06e099f,0x0f2364d,0x03107c4,0x0ac45a3,0x0adea14,
|
|
0x014853b,0x1b77f95,0x17ca492,0x0d709fb,0x0ff81f9,0x17be822,
|
|
0x12ab05f,0x1250693,0x1d4d58f,0x16ee291,0x07544d0 },
|
|
{ 0x0797ace,0x0689a40,0x05f93fa,0x015f0db,0x016d6aa,0x0d347e1,
|
|
0x09a23bd,0x109b7e1,0x19f9b26,0x05937a2,0x074bf06,0x19f5133,
|
|
0x1552fef,0x11211ca,0x0be3609,0x06f01ab,0x069f63a,0x1c7891a,
|
|
0x1353fab,0x068a9fb,0x1d09293,0x1bd39da,0x0ea0062,0x0aa5831,
|
|
0x1f276e5,0x18e4d78,0x17fc9ae,0x0ba8ee7,0x1d4f44c,0x0a08036,
|
|
0x1267bd2,0x0be7374,0x18f12f9,0x0527956,0x1b73d9b,0x14aecfe,
|
|
0x1922f59,0x03b9f8b,0x0b526ea,0x1d583c8,0x0220081 } },
|
|
/* 208 */
|
|
{ { 0x037a0ba,0x1eab9dd,0x17d8c10,0x19ba2ed,0x05a431b,0x10387b8,
|
|
0x0b3f310,0x0120664,0x067c2d1,0x055e987,0x02f3e97,0x0bbd97f,
|
|
0x0b362c9,0x1bc3d88,0x19f49dd,0x0bcc9ae,0x15e6ec0,0x1309648,
|
|
0x19a70c3,0x0d2c639,0x06359e6,0x07b4171,0x09f2776,0x1ff9870,
|
|
0x01f1295,0x0513c81,0x0628ab7,0x0d51dcf,0x1d500a0,0x13c225a,
|
|
0x1163803,0x11b01ad,0x1746fc7,0x1886643,0x0efa457,0x1048c0a,
|
|
0x019f6fd,0x0719459,0x0dcce11,0x158237a,0x0620541 },
|
|
{ 0x09e5a29,0x1e9c128,0x0c783df,0x016864a,0x0748d7d,0x1c41dcc,
|
|
0x04d5334,0x0f51ee9,0x08bfbb1,0x15c563a,0x0b4b171,0x14cc0be,
|
|
0x03a4616,0x0de58dc,0x1659894,0x04cb567,0x1042fee,0x067ba98,
|
|
0x0c89416,0x1ae7f7b,0x1556c70,0x1a78616,0x0484750,0x164b366,
|
|
0x061d854,0x1bec310,0x1710acf,0x1fc8c0d,0x0a4949f,0x02c2f43,
|
|
0x0b13172,0x02c1ddb,0x0ddcc8b,0x1121002,0x199d5a3,0x0c30099,
|
|
0x0214165,0x19c2ad2,0x0fa5e47,0x131f265,0x07f3781 } },
|
|
/* 209 */
|
|
{ { 0x1a6639a,0x1a5ed6f,0x0e4668d,0x080556e,0x0cbd48d,0x018f168,
|
|
0x1c8d91c,0x03eb8bd,0x0d0599d,0x04f715e,0x0e110ed,0x16c1c1a,
|
|
0x08d285e,0x1349c97,0x0faa4bc,0x0a71fb7,0x1bfb8bc,0x048a2af,
|
|
0x11a6dda,0x0b3fe3c,0x1682ae2,0x0fa0ef2,0x1073b2c,0x0a5a35d,
|
|
0x0f07199,0x023643b,0x079efdd,0x19c4a30,0x0ad2f11,0x16c3141,
|
|
0x19f2e4e,0x0d749de,0x1a3cd31,0x1d51f47,0x0813941,0x11f9cd1,
|
|
0x061bb60,0x0ba0b85,0x043433b,0x167ed58,0x06de716 },
|
|
{ 0x12d6dc5,0x0c6820b,0x1973539,0x0cc72f8,0x1ed2cde,0x0f5a745,
|
|
0x1f86032,0x1b6f5ce,0x075fa2e,0x113aa34,0x199ce15,0x049d523,
|
|
0x0e4b303,0x11ae459,0x08ea158,0x0510ec0,0x0c2a8f9,0x0cefb6b,
|
|
0x1bd7a2d,0x1830bfe,0x148aec2,0x159d6ab,0x1e24b84,0x095df78,
|
|
0x1b4f2d5,0x010bd75,0x03ba1a2,0x0922a89,0x19bd5b1,0x0fb8d8e,
|
|
0x1de89b1,0x05fe01b,0x1ccd166,0x18ef772,0x1c5ee56,0x09d7933,
|
|
0x1fe1f77,0x0c1b0b1,0x096c242,0x061767a,0x051f908 } },
|
|
/* 210 */
|
|
{ { 0x0922461,0x1b7d0f9,0x034524d,0x062ca1a,0x1bb1b1c,0x0c3046e,
|
|
0x070cc37,0x00d2572,0x136b899,0x1309625,0x180148f,0x1617bea,
|
|
0x05e1977,0x11b512a,0x0bffdc1,0x07b1df1,0x0781172,0x166d3e9,
|
|
0x06f79ee,0x1789770,0x178e0b0,0x1976952,0x0f2c202,0x0365c04,
|
|
0x00d0d17,0x0d72ded,0x1e506ee,0x0dbe719,0x0a65c5f,0x00ede0a,
|
|
0x03a1776,0x1833bb3,0x198c82d,0x037c9bf,0x11fd488,0x118c26e,
|
|
0x1f5bbe7,0x09d1612,0x12f9e78,0x11c1546,0x05eed21 },
|
|
{ 0x1d4dc0b,0x12baa00,0x0c1f855,0x0feacd7,0x01ae5f2,0x1112ead,
|
|
0x1afaee0,0x0d7d30b,0x01189ec,0x19d690e,0x1936757,0x0319d99,
|
|
0x1917da5,0x0b5b2da,0x128b4fb,0x0ee3990,0x1758ffa,0x13fcc40,
|
|
0x0b1a69e,0x0d5c245,0x046d50d,0x18e3734,0x12dfcc2,0x1a17627,
|
|
0x03a605b,0x003c601,0x175cfc9,0x1421fd9,0x10a9969,0x0c6672f,
|
|
0x01a3145,0x17b1eb0,0x06bf615,0x12370e9,0x0a1e456,0x115e65d,
|
|
0x0287d30,0x1ba7408,0x10953ab,0x00d4c4c,0x08c14ba } },
|
|
/* 211 */
|
|
{ { 0x17ee201,0x1bc4ad8,0x09dc321,0x0311caf,0x005aa47,0x01122b6,
|
|
0x19d8e5e,0x03a3387,0x0c9c3ba,0x1f37c60,0x027af82,0x09ff687,
|
|
0x16fe85f,0x0673fdd,0x02f3338,0x0d8c8a7,0x12a6526,0x143b755,
|
|
0x1e68e10,0x158d219,0x19815c9,0x18e6647,0x07d73ce,0x1ed0fbd,
|
|
0x1be6a9c,0x00afd0b,0x120e0d7,0x19f821f,0x0ef2ebf,0x07ed8a8,
|
|
0x19821ac,0x11094a5,0x197ecd9,0x08f5c4f,0x1e8ac33,0x1482dcd,
|
|
0x1ecc03b,0x1e8acc9,0x0597b8a,0x0bbd576,0x0645c0a },
|
|
{ 0x0aa7e31,0x02102a8,0x1697653,0x185f0a3,0x0ec8df0,0x1937355,
|
|
0x1a424f1,0x13532c8,0x02619bf,0x16dee1b,0x0fef55c,0x01c1c4a,
|
|
0x061b426,0x06384f0,0x10967ee,0x1d8b72f,0x0bbcdda,0x0fd5fbe,
|
|
0x12dc0fa,0x0bd163c,0x0fddb4d,0x17039a7,0x06c1b95,0x0abf14a,
|
|
0x0a4f91f,0x046816a,0x08fd597,0x1f0c117,0x0d1d947,0x03e940b,
|
|
0x0da08bd,0x0b9cf62,0x0c36156,0x0212106,0x17bcc74,0x0dc8ddc,
|
|
0x083567f,0x132fb83,0x1b246ca,0x081a5f4,0x027e9ff } },
|
|
/* 212 */
|
|
{ { 0x1e952e7,0x08c49eb,0x1c61d49,0x078e6b7,0x15b3058,0x1f02488,
|
|
0x1664a5b,0x194e656,0x0806d2f,0x1a28c2c,0x017b649,0x0d40371,
|
|
0x0c71ab7,0x16cfaaf,0x13a765d,0x175397b,0x12048f2,0x19ed305,
|
|
0x04ac4ca,0x0f810cb,0x11d7697,0x0584c82,0x0db72a7,0x1115c4b,
|
|
0x0ab23d1,0x19eece1,0x1f882ab,0x1e8d3e7,0x0d74d09,0x1be7ad5,
|
|
0x0ef6f47,0x04553d6,0x15efe5c,0x008621e,0x1e884dc,0x0118bdb,
|
|
0x1787026,0x1110bda,0x05ddab6,0x0ce7b59,0x04feee5 },
|
|
{ 0x1d3d780,0x0c6a95a,0x1d10c38,0x060e2cc,0x0dadb5d,0x1a10ab2,
|
|
0x0e1b969,0x10c641a,0x08d6bbb,0x0c61487,0x18f7457,0x06465a4,
|
|
0x16981a4,0x0c4c231,0x1439f2a,0x1596267,0x04da519,0x1a89c3c,
|
|
0x177207f,0x1c7f57b,0x043a832,0x0a18ccd,0x1f09e16,0x0e862c7,
|
|
0x0abcf32,0x1d3ada6,0x15d3e53,0x1f40217,0x14a6279,0x1a1eab4,
|
|
0x0930a29,0x196caf4,0x1d2a888,0x112f560,0x140fa1a,0x1efdde4,
|
|
0x04c561f,0x08d2e98,0x1783bb4,0x1cf393d,0x04fe818 } },
|
|
/* 213 */
|
|
{ { 0x1c1c7ff,0x0964ebf,0x0b44009,0x1b3f513,0x09bd419,0x1274e65,
|
|
0x0492901,0x1999274,0x043942e,0x0265e5c,0x05a56ce,0x03fb0e9,
|
|
0x1f004c2,0x0108b2d,0x120767d,0x02204d3,0x028dde0,0x0f1192b,
|
|
0x0a6c013,0x06e8aeb,0x1c21ec9,0x1ffb6e7,0x1eccd1a,0x06e58fb,
|
|
0x1a64b4d,0x0715626,0x0fc8125,0x1d96f5a,0x07c150c,0x00daf43,
|
|
0x16158b1,0x1856e47,0x19395ce,0x0991894,0x1f15fb9,0x0f9235b,
|
|
0x110b659,0x1788b0f,0x0fff381,0x0536e9a,0x0819155 },
|
|
{ 0x0d9d4ee,0x09218b7,0x1c063b0,0x08d135f,0x1dffa15,0x04d1fa1,
|
|
0x0d27caa,0x1649574,0x0d467ef,0x0d8f471,0x040b88b,0x06a8072,
|
|
0x0b18dea,0x1297841,0x0aae14f,0x1ba8e84,0x0c1ed36,0x1389851,
|
|
0x0a5747b,0x01d0da0,0x1ad3ca6,0x043e3fa,0x19ab1a0,0x10c8cb1,
|
|
0x1cecfde,0x13287c1,0x0518744,0x05ccd84,0x1850997,0x00a85e9,
|
|
0x027fbbd,0x14cc645,0x1183f3a,0x0e3ca87,0x12f9e4b,0x044ea8a,
|
|
0x1136770,0x02608d8,0x1bbcc9d,0x18fd1d4,0x07d06bc } },
|
|
/* 214 */
|
|
{ { 0x090212f,0x02ca138,0x011224a,0x18aa43d,0x091b7d4,0x16ddc93,
|
|
0x0108af8,0x1009807,0x1bd81f8,0x0bb90f6,0x06f0d8c,0x17dd591,
|
|
0x0dc136c,0x1dc7802,0x1c6d82d,0x115709e,0x0d04e21,0x0934899,
|
|
0x1b32053,0x0492ddc,0x1c15b0e,0x0bbafd6,0x02cb38c,0x1a4478a,
|
|
0x1c08466,0x1c5c171,0x193184b,0x0e43954,0x1653559,0x08f5d25,
|
|
0x145669d,0x18fa7b3,0x033aad5,0x0a1231a,0x074ba03,0x143cc37,
|
|
0x1c673ca,0x0fb2aff,0x12e4852,0x133a1f3,0x048b52b },
|
|
{ 0x1dc05be,0x0a9ccf7,0x17a68e4,0x1027c12,0x1e70db1,0x0d9fed6,
|
|
0x18ba737,0x0a288f0,0x01a0094,0x15818b1,0x083a8e8,0x1018472,
|
|
0x0b4b279,0x111dc7f,0x14e53c6,0x02da958,0x0563e56,0x10b1fb9,
|
|
0x1c50866,0x1ff27f6,0x0474aa0,0x0949eb1,0x149be5b,0x19fc4ed,
|
|
0x12ea87d,0x08aee90,0x1d1c0e3,0x164f7e5,0x18168ea,0x0192fa0,
|
|
0x06b9632,0x1665531,0x1704222,0x0f89df1,0x0e42ff2,0x1b46d28,
|
|
0x0d0684a,0x1713030,0x1dbb3c5,0x10f3b18,0x017c0de } },
|
|
/* 215 */
|
|
{ { 0x0c01958,0x0fa29ee,0x0e4ef29,0x0839d10,0x1d94595,0x0fadb6b,
|
|
0x1428558,0x178bcc6,0x07e2d36,0x08e1e43,0x10e9b0a,0x1b094b5,
|
|
0x0df6c7e,0x0cc0036,0x04f102f,0x1d876f2,0x0875671,0x0fbc5d8,
|
|
0x10fa26a,0x051edd6,0x01ed1c9,0x19d70f5,0x1f7ca37,0x049656b,
|
|
0x1a5b1b9,0x102b15d,0x146845b,0x123a4e0,0x1ed3e34,0x015b8b3,
|
|
0x11823b0,0x0b78160,0x091cf7b,0x0bfacf1,0x05a6317,0x0e61ca0,
|
|
0x15c799b,0x1e1a86f,0x1875c31,0x1c4158d,0x06862b9 },
|
|
{ 0x1fa1f64,0x17a73cf,0x0d255b1,0x1543c48,0x1ed6a91,0x1ba9197,
|
|
0x1b83336,0x00fd341,0x10322d6,0x1e4859b,0x1fbe1ef,0x15a48c5,
|
|
0x1429480,0x015fe79,0x08525a7,0x1c71ff8,0x1e0a539,0x0372908,
|
|
0x0a94527,0x13d84c2,0x15322a5,0x096b835,0x0657f88,0x1390852,
|
|
0x1b108e9,0x0417bbf,0x0d77201,0x099d5d4,0x12d2987,0x0185dec,
|
|
0x1ba9698,0x155d42b,0x142dca5,0x1884e56,0x0f1d261,0x13ad587,
|
|
0x090af64,0x070e201,0x179b319,0x05aa3f1,0x05093fa } },
|
|
/* 216 */
|
|
{ { 0x02d553b,0x1994026,0x10a7133,0x04772cd,0x1c1abe2,0x0b48a56,
|
|
0x152708a,0x192aad4,0x1999976,0x064fc5a,0x1a0fcf6,0x0f7aeed,
|
|
0x17c22c5,0x1e42f62,0x0a50aad,0x0c3ea9e,0x1e56e2c,0x0779a03,
|
|
0x084f6d2,0x0bd195e,0x18c7f00,0x1ef9934,0x11c3214,0x1814a96,
|
|
0x088d7ca,0x00f737a,0x1582dd4,0x0d7ad7d,0x0a4bd9b,0x188338a,
|
|
0x053c040,0x0dc1311,0x085bc3b,0x0950029,0x106bd7e,0x15d80ce,
|
|
0x0f7ef24,0x18b2137,0x090e0cb,0x09ad8ef,0x012f9c4 },
|
|
{ 0x1313a1c,0x0f4b241,0x0cdc654,0x14678b1,0x18edd3d,0x1620224,
|
|
0x0fd4b1e,0x1d09db7,0x10dcb5e,0x136537b,0x108be21,0x11eadba,
|
|
0x0eec0ae,0x0330f61,0x1def150,0x0a47820,0x13ad422,0x1369cc8,
|
|
0x039f2cf,0x0bc3d0b,0x1b45d10,0x1fe4bcd,0x11f24e5,0x12f6b24,
|
|
0x1d4a909,0x1f39910,0x0fa254b,0x1dec514,0x1462410,0x0c13a74,
|
|
0x1034235,0x0b2f01e,0x0cbed0f,0x0887632,0x089c238,0x0627af8,
|
|
0x1679b1a,0x036c333,0x0746346,0x09c4d5c,0x002f75e } },
|
|
/* 217 */
|
|
{ { 0x1f307d7,0x1bf5fa3,0x11dc6d8,0x15a0282,0x0b644a6,0x02d4063,
|
|
0x0f594b8,0x0630546,0x1fed07b,0x078d079,0x1b965f2,0x0ff26d2,
|
|
0x1ec09ee,0x03ffe00,0x0a9fb0f,0x0e7739b,0x0fef8f3,0x0aa4fc4,
|
|
0x0eee262,0x1a32c38,0x07b7c88,0x14efe55,0x164a93f,0x1c95641,
|
|
0x19ee23a,0x0d2897f,0x07d7b2c,0x0b5d4c8,0x0fb47df,0x11bff19,
|
|
0x1039da4,0x04ba10b,0x0a5c420,0x1aad14b,0x15609b1,0x07b9224,
|
|
0x1bce972,0x05cc2fc,0x0650560,0x0ccc72c,0x072b1b5 },
|
|
{ 0x10e5558,0x045043c,0x1e0275c,0x020d135,0x1853604,0x189dafc,
|
|
0x1ee2908,0x035d0bc,0x055a49d,0x15d0949,0x1c6c2f9,0x0961586,
|
|
0x195e76c,0x09c7370,0x1413ce6,0x13442b0,0x02260ae,0x146ea0a,
|
|
0x1a12173,0x009d372,0x1e43d8b,0x12c43f7,0x1e5312e,0x038bce7,
|
|
0x08e67f1,0x0e20893,0x033dae6,0x04c47c5,0x0a96629,0x15543d0,
|
|
0x14fcb42,0x099405d,0x066772a,0x1daa8d9,0x1938b58,0x0ad1dd1,
|
|
0x0e78b5b,0x15d94c9,0x096b737,0x02dc2e4,0x05df192 } },
|
|
/* 218 */
|
|
{ { 0x1f2e7e3,0x13f0f46,0x1f78800,0x11b1b40,0x1183cc6,0x05734a5,
|
|
0x0e9a52d,0x1119c6b,0x13ca62e,0x0b6cbef,0x1fb4b22,0x0276a5d,
|
|
0x0f3de47,0x135e842,0x01b1038,0x12477a0,0x1bbfc81,0x00f4db8,
|
|
0x0ab31ac,0x038f6c3,0x0840999,0x1247b2b,0x194324d,0x1e8ea48,
|
|
0x161d187,0x05109c2,0x06fff4f,0x021e562,0x1914186,0x0fd7fd0,
|
|
0x0265a45,0x12abca6,0x11236de,0x196bcc7,0x1baa861,0x16c2797,
|
|
0x06a2a48,0x1da2753,0x070c9fd,0x185c151,0x0452265 },
|
|
{ 0x1430010,0x0f63c92,0x03012b5,0x1fd7a12,0x0ac786f,0x14e9fae,
|
|
0x1d3fc82,0x0bf4bf3,0x0a3edc6,0x05fa089,0x0fac47f,0x073819e,
|
|
0x0088248,0x0552db8,0x175b53a,0x1157171,0x1fdb756,0x171138e,
|
|
0x1d11583,0x1d86e76,0x1296e43,0x130e7ba,0x1e3abe4,0x152db36,
|
|
0x1ae0e3f,0x1ea8c04,0x1770977,0x16625a5,0x0b77110,0x1c5a35d,
|
|
0x191ae3d,0x16bd9e3,0x09efc8d,0x1f65503,0x0eb9827,0x03832a5,
|
|
0x1f4dbde,0x118176a,0x015550f,0x1f23c0f,0x014b02b } },
|
|
/* 219 */
|
|
{ { 0x07e5b57,0x0e3b45c,0x155cb1c,0x0fea634,0x0bcc78f,0x0cbee40,
|
|
0x0fe2fdd,0x0be9ff2,0x1139e17,0x1470136,0x1329b2c,0x0e4f972,
|
|
0x1c6b83b,0x003cfbf,0x0bf8ec8,0x1a2e05d,0x0decf3b,0x015652a,
|
|
0x0bc371b,0x082678d,0x035e17c,0x12e67af,0x0fa8799,0x0aa0b8d,
|
|
0x11a4834,0x1c4d334,0x0398402,0x0c6757a,0x1d03882,0x138360b,
|
|
0x03259b1,0x03419f2,0x0efffbe,0x0eb263d,0x0f9f42b,0x0c9b08f,
|
|
0x0ea2aa4,0x0de6fdd,0x1429752,0x0e8598f,0x085e07e },
|
|
{ 0x1c25bca,0x1705305,0x13b08ea,0x03c89ec,0x0e8e55f,0x03dbb9b,
|
|
0x05b62d8,0x013c3cd,0x0d30059,0x14853a3,0x112642a,0x199a597,
|
|
0x1d072b1,0x034717a,0x03f9b1b,0x11d921a,0x1f053e2,0x0c90762,
|
|
0x0010330,0x043f69e,0x02c779b,0x09fe625,0x09cdd6f,0x1758fbb,
|
|
0x1def9e1,0x069fafa,0x04d703e,0x1862baf,0x0cd318d,0x00b8165,
|
|
0x071c45f,0x1d24dee,0x12823c4,0x179cd37,0x02efb40,0x0671b6b,
|
|
0x1db6932,0x1a4918b,0x1d0c396,0x13f1a93,0x0096403 } },
|
|
/* 220 */
|
|
{ { 0x0999eba,0x1a78b2b,0x0c1485d,0x0f63bcc,0x1d8ee28,0x0593349,
|
|
0x1dc9b78,0x143b035,0x13f8942,0x1a2349c,0x0f84f0d,0x0c2bd40,
|
|
0x0fbcf6b,0x0a7139e,0x03030d6,0x0b8ada6,0x056c672,0x127e99d,
|
|
0x02fa5e8,0x0a695b5,0x0251a57,0x133e115,0x1e6490a,0x018b892,
|
|
0x1bdb59d,0x1b42728,0x131a909,0x0f9aed9,0x06bf59d,0x0bd66a1,
|
|
0x0ca4502,0x0cdd37d,0x1404a2c,0x171f4ac,0x1a61725,0x008e71f,
|
|
0x0ad666d,0x1d9f075,0x1795af2,0x1a4c778,0x0626b0f },
|
|
{ 0x1a1ec42,0x0bedd70,0x11411c8,0x1756b59,0x0a6ae7d,0x0998e8d,
|
|
0x0ac7a19,0x0df6fc3,0x03d3012,0x0229838,0x186146e,0x13c1bdc,
|
|
0x0428064,0x15344aa,0x01bd28f,0x1ec6510,0x1adcb56,0x1a5df21,
|
|
0x12bfe53,0x1737b57,0x17be036,0x12de831,0x0365079,0x0de7576,
|
|
0x19d4468,0x1eb410b,0x12ab5ab,0x090d225,0x1e15341,0x048f7fb,
|
|
0x05a68ee,0x1d70dfb,0x0c426ce,0x09461c4,0x0a0445e,0x016adcd,
|
|
0x16399e0,0x1f389ac,0x1ab064c,0x1b342f6,0x009bbdd } },
|
|
/* 221 */
|
|
{ { 0x0fd3673,0x1ce0ef2,0x181dd78,0x034cb91,0x1880d9d,0x04e3ff7,
|
|
0x10771ca,0x0008e4b,0x03529d2,0x1b39af7,0x11ebcd6,0x05da78e,
|
|
0x15c1f8f,0x08977ef,0x1ce663e,0x13872b9,0x0184985,0x0f6b913,
|
|
0x19a5e57,0x12745e1,0x12a7237,0x0b4358e,0x029aae3,0x15105c9,
|
|
0x015de22,0x0bf0064,0x13e76e3,0x1cefadf,0x067547b,0x1d99011,
|
|
0x170221b,0x093821d,0x02687d4,0x1f6a65b,0x185df20,0x153e387,
|
|
0x1af366e,0x0aebf82,0x0b4939b,0x171a3df,0x02eaa01 },
|
|
{ 0x1357c74,0x1fdb80f,0x1e51791,0x1553c76,0x13085c4,0x02d482c,
|
|
0x01ccdba,0x1929e13,0x1be0244,0x09c047f,0x159837d,0x1f27476,
|
|
0x1691ddd,0x19dcaf6,0x1d8ddef,0x041a916,0x1b7bb39,0x1c8dc88,
|
|
0x1a84f3c,0x1e117f0,0x0e587cc,0x0bf500c,0x14fb63e,0x18aa328,
|
|
0x0434378,0x0d358f5,0x07834b5,0x1cd5bbd,0x16259a8,0x1247cdc,
|
|
0x177f0ac,0x1dde2fb,0x0ebceae,0x1ce42cb,0x110d55f,0x11ed296,
|
|
0x07d5bba,0x068a878,0x061ad23,0x1d36983,0x002d31d } },
|
|
/* 222 */
|
|
{ { 0x079499d,0x1cf0f6f,0x0ab69ae,0x11fa1f8,0x16ca8ff,0x1ec9ab7,
|
|
0x1e3a069,0x04f7d81,0x1e8f063,0x01e8e4f,0x002faef,0x042e766,
|
|
0x1b805c7,0x009e0c0,0x1082821,0x13a0200,0x07ef0ca,0x14f4d0b,
|
|
0x0bbb775,0x19213a3,0x0a72076,0x1fc71d4,0x1928665,0x0f6853c,
|
|
0x1f7a7a7,0x1f49e73,0x1172534,0x1581f7e,0x148407a,0x0a53f36,
|
|
0x19fcdda,0x1523243,0x16679e2,0x0ddeb7a,0x03cfb87,0x13e47fc,
|
|
0x0bf9fa9,0x08bab36,0x15d971e,0x1e5c1e9,0x0965860 },
|
|
{ 0x1a5f79c,0x03815bf,0x09b79cd,0x0cb5e5a,0x130bd42,0x19f0674,
|
|
0x02e61b1,0x05a8b7b,0x14ee44a,0x0df3df6,0x122869f,0x00492ad,
|
|
0x0ec129e,0x1be6fc0,0x17016b1,0x14b36df,0x02b589c,0x1b8535d,
|
|
0x066096b,0x1080433,0x10b6fc4,0x0a3d11f,0x074a12d,0x141515e,
|
|
0x010a428,0x16c58ed,0x04acabd,0x03d6366,0x135ee3b,0x021d19c,
|
|
0x1b3c145,0x11dff4d,0x007eb26,0x132a63d,0x021b598,0x182ddc8,
|
|
0x0549ee4,0x1de280a,0x02949e9,0x0643f53,0x0650810 } },
|
|
/* 223 */
|
|
{ { 0x07ed9b2,0x072305b,0x0f4927c,0x0186db2,0x0cda0fd,0x03af0e0,
|
|
0x18fa623,0x19376b2,0x1614bc0,0x0bddf49,0x1a1815d,0x100334e,
|
|
0x049a9b8,0x0476e2a,0x0df8abd,0x0b30b51,0x19eb51a,0x04f3bf6,
|
|
0x0efc093,0x04a4e9d,0x0636dd0,0x040aa2e,0x1662d8a,0x001b740,
|
|
0x1aed048,0x11d1cde,0x06078a8,0x1f84027,0x0cb4f27,0x1eae2a8,
|
|
0x11f719b,0x16a40d1,0x127032f,0x0fd0ad6,0x12ba05a,0x0593417,
|
|
0x1a7ca8a,0x1037909,0x194bd81,0x08d30c4,0x0982950 },
|
|
{ 0x011c128,0x1a30017,0x09f8f8d,0x1a1cdb9,0x00dfae5,0x0a91324,
|
|
0x05b8b65,0x087c880,0x0880b71,0x12fc479,0x0e2073d,0x11a8a4d,
|
|
0x1eca3d2,0x0fdc357,0x1167747,0x1f2b1f3,0x0c24c74,0x1aa4430,
|
|
0x12da7d3,0x1d48793,0x0cecd06,0x17399a7,0x14d0f26,0x0652e26,
|
|
0x0ccd635,0x0062e61,0x0d7ce9b,0x12bfe80,0x12653ba,0x10e659b,
|
|
0x0f4b806,0x144a0a4,0x1510fdf,0x13f5918,0x038a988,0x01ddca7,
|
|
0x0a23cd1,0x0fe4506,0x1d52fab,0x0367cf1,0x04b7e6e } },
|
|
/* 224 */
|
|
{ { 0x15f928b,0x083b7ed,0x13b1e72,0x0d6e68f,0x06250bb,0x007620f,
|
|
0x1de62b0,0x18ea96c,0x09d9619,0x006905d,0x10d0fe4,0x01a0b3c,
|
|
0x17ed42c,0x028c9ae,0x1ce7a15,0x0039c7b,0x18264f7,0x0131c88,
|
|
0x07e1eab,0x1e4aa9c,0x1aaace8,0x04b2fc8,0x1f7759e,0x048a73f,
|
|
0x1163fa3,0x0cacb66,0x112eb3a,0x1902be5,0x0f9ea55,0x061554a,
|
|
0x1575e32,0x1de49c8,0x0b2aff4,0x0e1353d,0x1024737,0x05e1dac,
|
|
0x00ca282,0x0521058,0x1d96255,0x18ba652,0x00611c4 },
|
|
{ 0x1e81829,0x1000e54,0x0b33c64,0x0011450,0x1ed3332,0x0ef6cde,
|
|
0x1f7863e,0x00617fa,0x1b78890,0x1c9d606,0x1e97759,0x123a6ae,
|
|
0x0bbb00d,0x00169e1,0x1e88e9e,0x12029c2,0x08cfb54,0x1ffcafc,
|
|
0x1c6db81,0x037e978,0x0c8b7cd,0x1011ac4,0x0b8ec92,0x02240ec,
|
|
0x135b8a4,0x0984da9,0x1b1015b,0x090380b,0x16a1b52,0x0086748,
|
|
0x1d1571d,0x10a02f3,0x1e03271,0x089045d,0x05decf3,0x002bcd8,
|
|
0x10cbfe5,0x0d12604,0x0159942,0x0523821,0x0820795 } },
|
|
/* 225 */
|
|
{ { 0x07d353e,0x09e7f8e,0x18ed74b,0x1afbc19,0x15e7ecc,0x143b1ae,
|
|
0x01d7db2,0x07d6962,0x025f9ad,0x1420270,0x12d6bb6,0x1d1240b,
|
|
0x016b963,0x04f910d,0x17b8360,0x159493c,0x1d9ea41,0x06b2642,
|
|
0x1110a8d,0x0d89d26,0x15a46a4,0x1f1e7b2,0x0b1bfe5,0x082faf9,
|
|
0x05c1ee5,0x0263b2b,0x07bafe7,0x1020135,0x1a63886,0x0e9cc46,
|
|
0x11a56d8,0x1ed68e5,0x002b46a,0x188b8b2,0x05942df,0x063fbca,
|
|
0x1e0c05e,0x1c7939d,0x1129e53,0x06d5106,0x07487b0 },
|
|
{ 0x03e2370,0x072bace,0x1c66a18,0x07f0090,0x19d5819,0x117cd50,
|
|
0x0fcf29b,0x136741b,0x1614471,0x163f4ac,0x1fb086d,0x18e9bdf,
|
|
0x1fa9049,0x1fa8675,0x08192c8,0x1bc2b17,0x0c049a1,0x1589411,
|
|
0x07549fc,0x096fb36,0x0430b65,0x0e87fe8,0x111c216,0x00a88d7,
|
|
0x14a674f,0x0ca9be3,0x0e8eb76,0x0aa64a3,0x1533b5e,0x0b65f19,
|
|
0x13928fb,0x04fc833,0x12f44d0,0x0dcbc97,0x1a0a974,0x1e5b09d,
|
|
0x1b6fa69,0x1b5891e,0x0ef7731,0x18a43f4,0x0834f85 } },
|
|
/* 226 */
|
|
{ { 0x0e9b31a,0x1a3e096,0x0edcca4,0x15fc7f6,0x1d88522,0x1fc87e8,
|
|
0x1ed354b,0x03a979d,0x02b1a08,0x1d8b9c3,0x047c214,0x0374548,
|
|
0x1a538c1,0x0a0db01,0x056e4f0,0x1ae82f1,0x1aab10b,0x114c9dc,
|
|
0x0644a61,0x17a08c1,0x0ba5ccb,0x1877505,0x19a7ebe,0x0cc312e,
|
|
0x0462235,0x12a6a42,0x10d9ffe,0x14c7713,0x1478da4,0x0e8e8e1,
|
|
0x1df2eb5,0x154c069,0x1339227,0x189c8e2,0x017f986,0x0a1cdae,
|
|
0x174ff51,0x0a5b307,0x0d53374,0x014a665,0x0639d8b },
|
|
{ 0x02217cd,0x118b10b,0x039be90,0x1502385,0x0e0e4a2,0x1b36e01,
|
|
0x1386085,0x1ded1b3,0x1046a06,0x0931b9c,0x0484054,0x0463bbd,
|
|
0x1344eea,0x08a14c6,0x01f23c8,0x0afd20c,0x0ba63d9,0x093f939,
|
|
0x17a32b8,0x1d01994,0x063fe7c,0x11127bd,0x1605baf,0x0ce7c68,
|
|
0x0e5a789,0x1ea26f6,0x094daea,0x06ead44,0x1f77af1,0x10d771d,
|
|
0x0f19135,0x0579f31,0x0b2bf6e,0x14b1630,0x07cca7e,0x067616b,
|
|
0x0bb5002,0x1b4d0d5,0x100b2c1,0x06c18ea,0x0409031 } },
|
|
/* 227 */
|
|
{ { 0x070433f,0x1439d0b,0x17f2134,0x0c4a927,0x09394df,0x1e7c4f6,
|
|
0x0866a03,0x02dd60b,0x0db2976,0x1cf2188,0x18c11b8,0x1b93b3c,
|
|
0x1e50742,0x0ef4e54,0x06b6320,0x03a1be6,0x194fb7b,0x0c3555f,
|
|
0x0cf20b4,0x1b44f43,0x0d8436c,0x1a1cb81,0x1ec68bb,0x0102533,
|
|
0x1fddc46,0x11c1405,0x1748e58,0x0965691,0x1c9353e,0x0179bd9,
|
|
0x1a4b6cb,0x025f714,0x1b5b317,0x0023a6a,0x08ec206,0x11f370f,
|
|
0x1e95257,0x0c84c30,0x0af2361,0x1dbe6f4,0x080668e },
|
|
{ 0x19a0249,0x0e69ad9,0x1abb8bb,0x0965f15,0x0f230cd,0x11ef82d,
|
|
0x05791c8,0x1e852b6,0x0e0e937,0x1b34c15,0x12458ae,0x16e5197,
|
|
0x01019d2,0x07a4ee5,0x144aba7,0x00f68b8,0x1a7630f,0x088da48,
|
|
0x00e1d3a,0x09e6994,0x143348d,0x132265b,0x107f43a,0x0b66187,
|
|
0x19ae1f9,0x05609fb,0x17b62d8,0x006c5a9,0x0ad81c4,0x0a7fb0f,
|
|
0x0a27a0c,0x093187a,0x1600dd4,0x10b8176,0x1067094,0x06bf963,
|
|
0x1a9c1f3,0x1194fe1,0x1b3a564,0x09037bc,0x0046775 } },
|
|
/* 228 */
|
|
{ { 0x1233c96,0x0f2b71c,0x1abfb8f,0x1900e6f,0x068c409,0x0d5e344,
|
|
0x046f480,0x00b595c,0x12b4862,0x196754d,0x0415b03,0x0fc2de3,
|
|
0x01e3238,0x12ee152,0x1d4d96a,0x17d0dd4,0x0cc12b4,0x0bb614d,
|
|
0x158ca53,0x1f956f1,0x1f24a01,0x058655c,0x0076fa2,0x02980a9,
|
|
0x06e5bf4,0x1d53b32,0x0f2e5ad,0x1c22312,0x04e097f,0x1ad8bb3,
|
|
0x0a6d927,0x0a7f9eb,0x196422e,0x1fb1a50,0x06f42df,0x0ab2f19,
|
|
0x1c22989,0x1f59c71,0x1115ad7,0x1f61067,0x0038a49 },
|
|
{ 0x1e93257,0x1c0c609,0x106cd78,0x1b4c24e,0x14cebc9,0x1560358,
|
|
0x04925f2,0x02c9edd,0x13daa11,0x113c719,0x080d2a0,0x0cbc9bc,
|
|
0x10e7cc5,0x050dd31,0x1f7257c,0x0df7b76,0x1236695,0x140eecf,
|
|
0x0c4cb75,0x1cc6337,0x1337c63,0x117e120,0x1b88ac0,0x117d638,
|
|
0x081937e,0x05611c2,0x176324e,0x0763329,0x1b56448,0x1d65535,
|
|
0x01ed533,0x00df230,0x07cd44e,0x06cf98d,0x06eea3e,0x0c3ba87,
|
|
0x1f74a8e,0x06153c3,0x1598198,0x0442436,0x04bb76e } },
|
|
/* 229 */
|
|
{ { 0x0354817,0x08f4573,0x10e1e85,0x15e0716,0x13d494e,0x0ac4c31,
|
|
0x11a2216,0x024990d,0x11dcbac,0x10a9c13,0x16b419c,0x1f1981d,
|
|
0x16f487a,0x128072e,0x0cc147f,0x0feab5a,0x11bd6e4,0x085388d,
|
|
0x11d1ab5,0x0e134f1,0x135ea68,0x1132017,0x09fc5c9,0x0618260,
|
|
0x08efafb,0x04be368,0x0701b1d,0x1de3808,0x03e2da9,0x07676e6,
|
|
0x1cf431d,0x0125c20,0x0c5f96e,0x095ba18,0x0f3caa8,0x041e272,
|
|
0x0107eb0,0x0c200b1,0x1e62c91,0x0bef6ed,0x08843d2 },
|
|
{ 0x1b2a83e,0x080ee76,0x1c91385,0x005771a,0x1cfe8fb,0x12efb15,
|
|
0x0196764,0x1861204,0x142ab6f,0x038aee7,0x0277f4f,0x00ab41e,
|
|
0x0a73c05,0x11ac857,0x19d1763,0x0e93c24,0x0d876ff,0x1a9c17a,
|
|
0x0483198,0x13fddf5,0x11cafc6,0x08cfeb8,0x1785808,0x0eb89ab,
|
|
0x1c3bd90,0x1f9210c,0x04f7b5a,0x100197a,0x03a1163,0x1075b13,
|
|
0x0de31fa,0x0fa4c98,0x1bd7958,0x0e4c61a,0x1915c56,0x0aadc45,
|
|
0x1a7373b,0x1f9516f,0x12525c6,0x073126b,0x00503f9 } },
|
|
/* 230 */
|
|
{ { 0x1dad4f6,0x0ee3338,0x086d96b,0x120497d,0x038e488,0x02e9ee9,
|
|
0x1238bd8,0x113f6ed,0x0b0d96b,0x1eafaef,0x06cb2c4,0x146acc0,
|
|
0x14e0b5b,0x01f1e92,0x1f52476,0x11d4fc6,0x023240c,0x1744302,
|
|
0x047266e,0x0305e7d,0x1919374,0x1cd43d6,0x09b0b2b,0x0e9e52a,
|
|
0x1040af5,0x051a589,0x0651000,0x17379da,0x1f42e75,0x0bdf036,
|
|
0x0753331,0x097a211,0x0e8ec50,0x1da8011,0x1deb776,0x1618a62,
|
|
0x1ecfead,0x0698e94,0x1a3e5a4,0x1fc2ecc,0x0735778 },
|
|
{ 0x03c1137,0x1771f42,0x0f343e1,0x147e16e,0x1c1c42f,0x19071d1,
|
|
0x19e762a,0x15c1cea,0x016242f,0x1caf8fa,0x024b91b,0x0238736,
|
|
0x007b88e,0x0611b56,0x0a500f9,0x005cc2c,0x1412dac,0x133082f,
|
|
0x18b818c,0x18514f0,0x1c8d74d,0x1979d91,0x08463fe,0x08bff7e,
|
|
0x0417c07,0x08f08c1,0x113015c,0x136ab40,0x1be4de4,0x0dba677,
|
|
0x01cb199,0x12f7ee2,0x0c4c01d,0x1833b0e,0x1b6b153,0x1165940,
|
|
0x1450d0f,0x0cced53,0x00a87f1,0x14c3463,0x052e637 } },
|
|
/* 231 */
|
|
{ { 0x1ebc6db,0x18078b5,0x1649205,0x17f2a07,0x0a6b45d,0x0a9c8ca,
|
|
0x134f174,0x1798e2b,0x1e5ad2a,0x0150e02,0x0d19be5,0x086756f,
|
|
0x0b36a82,0x1d09c8c,0x104efb6,0x1cd9d74,0x02490f4,0x134c52b,
|
|
0x0fc7cf2,0x041b4de,0x1ab3bb7,0x0eb1a38,0x0845b50,0x07a6c12,
|
|
0x1222730,0x14f7006,0x0118ee9,0x1fa9980,0x045fd17,0x0f26b14,
|
|
0x11eb182,0x1015b93,0x1603b2c,0x17de531,0x126917e,0x177e2df,
|
|
0x04bc94a,0x003fbfe,0x05a6104,0x09f4e96,0x07c916b },
|
|
{ 0x0bac2d4,0x137c8bc,0x01d7040,0x104c035,0x0a2e809,0x19eb204,
|
|
0x09db801,0x1115a5e,0x0fcc1fb,0x01b0862,0x0ca47d1,0x104594d,
|
|
0x1c5727b,0x0476307,0x1154cb2,0x1a9160c,0x099ed9a,0x1a8f244,
|
|
0x150fc40,0x16916be,0x0eeb841,0x1f6ac8e,0x09b32c6,0x19eb517,
|
|
0x0df0f9d,0x0da7e25,0x02cd1f7,0x14f9404,0x04c5213,0x066165a,
|
|
0x112a86b,0x00a4f81,0x13b6828,0x1e7a83b,0x1041c08,0x0d546e9,
|
|
0x0b74c92,0x1e88003,0x141f1cc,0x0deef51,0x01ff391 } },
|
|
/* 232 */
|
|
{ { 0x197939d,0x0c7f27c,0x0ecea88,0x16f22b0,0x1d4dfbb,0x1bab059,
|
|
0x0d76a1f,0x131674f,0x15da92c,0x0e01400,0x19bd2aa,0x155a8cc,
|
|
0x17e1eb4,0x0a674ee,0x0c5e944,0x060ec5d,0x0a4ef8f,0x17a3533,
|
|
0x043951b,0x168b8d0,0x04dd900,0x0c25d78,0x1debc89,0x109a85f,
|
|
0x1c8725c,0x1ef1e60,0x1639320,0x0127e44,0x0d88b23,0x0f208b8,
|
|
0x1118beb,0x1580edc,0x19612e4,0x08a0df0,0x0d18cb7,0x15e91ae,
|
|
0x125e34d,0x18fbacc,0x0432706,0x0ac0e57,0x019ed1a },
|
|
{ 0x0735473,0x1fe6f36,0x10fa73d,0x0ec0077,0x0ab88e6,0x0ccddc5,
|
|
0x1f2f3ec,0x17a2430,0x19acccc,0x1b98220,0x195166e,0x1e7961e,
|
|
0x02214af,0x17c9314,0x1b2068d,0x04170d5,0x1329f9d,0x0554165,
|
|
0x1dcf324,0x07f21ea,0x17e182f,0x15fb112,0x12bd839,0x08ec5be,
|
|
0x144bfbd,0x1a9f8c5,0x076e5c1,0x1291625,0x02c18e3,0x1074be1,
|
|
0x0b71ba4,0x0af7d2f,0x13d6208,0x11bfc9c,0x00b11ad,0x0bd1ae7,
|
|
0x11fed1d,0x112e65f,0x05667d9,0x1f2d0d0,0x06f31e0 } },
|
|
/* 233 */
|
|
{ { 0x0b8f204,0x17f2ac1,0x152b116,0x0da6b16,0x0c0441b,0x0afaf6d,
|
|
0x19efeb3,0x126e427,0x1139bcd,0x08a6385,0x0f2ec06,0x0b032db,
|
|
0x01714b4,0x0f69ae9,0x0a5f4d4,0x03e41d2,0x0376a3e,0x0c7b204,
|
|
0x1cf35c1,0x15153a5,0x1f6d150,0x00ee6ec,0x1ecdba0,0x1eadb05,
|
|
0x0eb655c,0x110ad2a,0x124aa96,0x0c20a01,0x089f037,0x05711d8,
|
|
0x1a34434,0x18856cd,0x11b2079,0x146a424,0x18f43bb,0x0a95e35,
|
|
0x01556f4,0x1f26142,0x09f984d,0x010c7b1,0x0875e33 },
|
|
{ 0x16c0acc,0x07eee57,0x1023720,0x0d763cf,0x15ad1e6,0x02c2d6e,
|
|
0x1eb860a,0x14db8e2,0x0275c7d,0x0e2a1a0,0x0e7856f,0x10a5a4d,
|
|
0x10f4b4c,0x1502fd2,0x0287efd,0x19664be,0x047817b,0x0e37c0f,
|
|
0x03fcb87,0x1a8650e,0x17fc2cb,0x0b33e3f,0x0289240,0x10b4d89,
|
|
0x1acb7b5,0x02be822,0x11199b0,0x1d2e55a,0x17d63d2,0x03e7f36,
|
|
0x1131d36,0x01c4e82,0x1067d87,0x0c2577b,0x15ea2c9,0x1765942,
|
|
0x15f0fde,0x0e2dfdb,0x1802525,0x103e70d,0x05abb05 } },
|
|
/* 234 */
|
|
{ { 0x0c97f57,0x11695f8,0x031e2f9,0x032c5e5,0x0fe0487,0x1a855d8,
|
|
0x0919d1e,0x1db8a91,0x144fa09,0x1593701,0x16a5bbd,0x0dc7560,
|
|
0x02fd44c,0x1873574,0x0c00cb1,0x1133bdb,0x02bd7e4,0x1145ea0,
|
|
0x0df0470,0x05d2c73,0x171643f,0x0767489,0x03b0ff0,0x1fa1f18,
|
|
0x18bc902,0x1d63b4d,0x09f2af0,0x1b39675,0x124cc99,0x0449034,
|
|
0x053a22a,0x084c120,0x11461aa,0x13cf052,0x0a2e58b,0x018fe95,
|
|
0x0b1b3e8,0x1810854,0x192f13b,0x10037fd,0x0705446 },
|
|
{ 0x01901c1,0x1eb8989,0x12abeac,0x0ffd5aa,0x090a262,0x045d11f,
|
|
0x14a16f0,0x0fcc9ed,0x136ec22,0x0cc980a,0x0646ae3,0x15720d8,
|
|
0x0c99a16,0x1b24e71,0x0c73d6f,0x075010d,0x15966be,0x02c9033,
|
|
0x12e8b3c,0x06c4f39,0x1486188,0x03f7fa9,0x0b055ee,0x04475e4,
|
|
0x098964b,0x12bdfd6,0x002ab9e,0x1a1fa9e,0x018a80c,0x1ca0319,
|
|
0x13b6b76,0x1bf11e2,0x044bb79,0x16cfe9c,0x0f52dc7,0x0d8367c,
|
|
0x1620503,0x11a509e,0x029adb1,0x19f70d0,0x06f56ae } },
|
|
/* 235 */
|
|
{ { 0x1205c5d,0x0e401ec,0x04a6c07,0x1ace247,0x08955f7,0x0db2b2b,
|
|
0x0fff676,0x1fc7bd7,0x0d3b1ac,0x0221caf,0x13bbfee,0x1642c12,
|
|
0x0b04328,0x114c8ff,0x0c7fea0,0x1a0eacc,0x0e6190d,0x086ef33,
|
|
0x015df01,0x0078abd,0x040775b,0x0fc8b91,0x1b24739,0x176747e,
|
|
0x08a408e,0x1cb4d14,0x0816284,0x1a6edf1,0x0e06761,0x0a2bcd3,
|
|
0x023ce96,0x0f6e3a5,0x03029c5,0x0186008,0x10a2d13,0x181087e,
|
|
0x130e0b9,0x1357fc3,0x112b763,0x0229dac,0x07b6be8 },
|
|
{ 0x13aa54e,0x1c7251e,0x0268fb0,0x07b07aa,0x1023394,0x1caaf10,
|
|
0x0988490,0x089f095,0x1f51d3d,0x088238b,0x0938dca,0x0858fd9,
|
|
0x1e62d24,0x02fd2ae,0x16948f6,0x1436b18,0x0da851d,0x0637ae6,
|
|
0x000051a,0x1795504,0x02e0044,0x14700b8,0x1dd4079,0x14159d9,
|
|
0x19359e6,0x0597840,0x16b03bc,0x07bb4d5,0x164f013,0x16e47ec,
|
|
0x1625ebb,0x0a61721,0x0dacd0e,0x09175a4,0x15bee10,0x1c98bf5,
|
|
0x1700a1d,0x02760f6,0x151d08a,0x06bb794,0x086f9a8 } },
|
|
/* 236 */
|
|
{ { 0x10cc69f,0x0c82aa2,0x063c387,0x1993dbf,0x10eb14b,0x1f5d00a,
|
|
0x139dfb9,0x0a63772,0x1998f8e,0x1bd339b,0x1bbbc17,0x09c6362,
|
|
0x1558838,0x0c2e2f0,0x04a1c8f,0x0a55577,0x145cbd9,0x07f28f1,
|
|
0x189059d,0x01dc50f,0x02f0c5d,0x178800c,0x1f7051b,0x1eb7c59,
|
|
0x19e92e7,0x09f07b9,0x1ed95af,0x0035675,0x08e2895,0x16ef28b,
|
|
0x12ac554,0x171dc20,0x00dfe31,0x0223aca,0x180f10c,0x0685246,
|
|
0x0460a91,0x03788a6,0x07e1a4c,0x15e076a,0x05bfa9f },
|
|
{ 0x07b258e,0x1fa9608,0x0770a88,0x17acc68,0x189e82b,0x1e7f8d4,
|
|
0x13b6208,0x03ea947,0x0719b49,0x02dbbca,0x0f7ee3d,0x0430486,
|
|
0x0e898c2,0x0249287,0x0776473,0x0ecaa1f,0x0ae4fa1,0x0a86151,
|
|
0x10c9fd1,0x1439c85,0x1e41f7a,0x0b2c1d8,0x04e856b,0x17f5b3c,
|
|
0x0d5a5a1,0x0e6cd50,0x02387ef,0x1639545,0x1f7f879,0x01db48a,
|
|
0x07abe4a,0x10fd034,0x10e4e0c,0x0694b60,0x0958420,0x1009fb9,
|
|
0x12755bd,0x064b0b0,0x1bb69ab,0x155051f,0x01b1266 } },
|
|
/* 237 */
|
|
{ { 0x14ee49c,0x005003b,0x1f5d3af,0x0596c46,0x176f685,0x1c9c51b,
|
|
0x112b177,0x17bf80a,0x0b6fbfb,0x19c4764,0x1cbabb0,0x179ae8b,
|
|
0x1784ac8,0x18f6749,0x1159826,0x1f42753,0x0ac7de8,0x0b2b7db,
|
|
0x14cae1c,0x1bdae94,0x1f095f8,0x05d5444,0x0ac350a,0x16f5d85,
|
|
0x07f2810,0x1a621d9,0x1bfbb2c,0x0c84dc3,0x09c2db2,0x0db5cf4,
|
|
0x041110c,0x0724221,0x0c4bc5d,0x0082c55,0x0da13f6,0x1d24dee,
|
|
0x071ef60,0x17d348a,0x1e88d14,0x1b6431a,0x033517f },
|
|
{ 0x13c4a36,0x19fa32c,0x07baa70,0x106d635,0x0c69d71,0x1bdf765,
|
|
0x0307509,0x138ab44,0x07e4f17,0x1465127,0x162288f,0x06d3a8d,
|
|
0x1857373,0x1983817,0x13ac731,0x1aae8e3,0x19735ee,0x1458c26,
|
|
0x1c133b0,0x0a2f440,0x0a537f4,0x0c6b831,0x1fc4a74,0x1aefc38,
|
|
0x0571bb1,0x05903d2,0x060d436,0x0e95861,0x1ab8ef7,0x08cfb0f,
|
|
0x06c9eca,0x16bbb00,0x1c4cc13,0x02c8fd3,0x156c50d,0x07cfcc4,
|
|
0x1a3592b,0x0c9bdc2,0x1d524d2,0x07a618e,0x031fac6 } },
|
|
/* 238 */
|
|
{ { 0x0913fb6,0x0678d82,0x1accbba,0x002ed34,0x1e40135,0x1f30f83,
|
|
0x0edc5e0,0x1fcf21d,0x1e27f2f,0x12883fc,0x1e26fc7,0x0cffdb5,
|
|
0x0d124ba,0x12c6f34,0x0480387,0x157dc31,0x0a36df5,0x14b1399,
|
|
0x12fad2a,0x186f9f5,0x1a7672c,0x0b749e2,0x0c317ea,0x0c67277,
|
|
0x0317cde,0x0b62615,0x1e0c2cb,0x0fecbcc,0x05b96a9,0x1a820df,
|
|
0x1b52bf0,0x0e619cc,0x1f40a60,0x06c2785,0x09e64d0,0x112d437,
|
|
0x07626b0,0x10c12a0,0x12fd4fb,0x1b6f561,0x001db35 },
|
|
{ 0x00efee2,0x1de16d6,0x0d15b83,0x1bae3b7,0x0406ebc,0x1b4d5f4,
|
|
0x178f866,0x045ce57,0x137e018,0x0e5bf30,0x162d312,0x0038228,
|
|
0x03cbb8c,0x143e2eb,0x02d211d,0x0ceec84,0x1a1454c,0x00c23ef,
|
|
0x060e746,0x1d223ba,0x1046bed,0x0493c6f,0x06e7727,0x03466d8,
|
|
0x1d62b88,0x16e14a5,0x064f9de,0x1e12d0f,0x0e3ba77,0x0332a1e,
|
|
0x1f1eb24,0x0eec9dd,0x08695fd,0x032e78a,0x1c2e6b1,0x03c1841,
|
|
0x06e2cdb,0x1746945,0x0d0758d,0x119aeaa,0x07b6ba9 } },
|
|
/* 239 */
|
|
{ { 0x1881ab4,0x0cf01e0,0x12232c7,0x0b662d1,0x19c25d5,0x11b2670,
|
|
0x0f51ca0,0x049505a,0x0f161aa,0x0cca1c8,0x0ecb265,0x1801c3d,
|
|
0x157838b,0x1ef63d3,0x1577f32,0x044151f,0x1c24ff7,0x026e901,
|
|
0x1bfbfd2,0x02e7661,0x0b355ec,0x198b214,0x067c74a,0x0dd027f,
|
|
0x1d9e505,0x0f8e035,0x0b02cc6,0x0522e57,0x023b159,0x11c27e9,
|
|
0x1b5ab83,0x131a123,0x101059e,0x032475e,0x0392995,0x10d662d,
|
|
0x1375e79,0x08a23f9,0x1142088,0x032e3d6,0x047e810 },
|
|
{ 0x08c290d,0x0ea2d5e,0x0ce9c11,0x0b021f6,0x033d135,0x1ddf97d,
|
|
0x002491b,0x1b2575e,0x1385c7c,0x07f9f8d,0x066172b,0x01d9c2c,
|
|
0x08c5b15,0x154443a,0x1b829fc,0x1b9918d,0x08e5e88,0x1cec446,
|
|
0x12e1910,0x0e6be59,0x16f24dd,0x1b9e207,0x130784e,0x1fdad23,
|
|
0x025fff3,0x0e3fe1d,0x1c95fb9,0x1968762,0x0db1354,0x07c9f99,
|
|
0x14ea995,0x005bfe5,0x0f58d0a,0x131ca22,0x0622a32,0x0ef1c7e,
|
|
0x13e8669,0x1236677,0x1a1ece5,0x005c1b9,0x0785b19 } },
|
|
/* 240 */
|
|
{ { 0x12f9a20,0x111b0d4,0x103bf33,0x0f3ac8a,0x17bdca8,0x006be2d,
|
|
0x06a1474,0x04da8e7,0x02e97c9,0x13d646e,0x09aa2c1,0x1ffcf1b,
|
|
0x092aea3,0x11e28db,0x0a2fd51,0x02834d0,0x0797155,0x03b78e2,
|
|
0x05df604,0x197dec7,0x0e7af4b,0x04aa0de,0x1d6f125,0x0e0834a,
|
|
0x14066d1,0x157f00f,0x161dd57,0x0505ab7,0x07ae80d,0x03eeacf,
|
|
0x1bdb884,0x0705566,0x056e166,0x0eb1a55,0x1bdae74,0x08cbdd1,
|
|
0x0e4ed84,0x110b056,0x0b09e66,0x0cf6ee2,0x06557c3 },
|
|
{ 0x15b6e52,0x181346b,0x1a25586,0x00231a1,0x1081364,0x1758d75,
|
|
0x0ccc1a8,0x1299fea,0x06d0908,0x1231113,0x1075213,0x044f6bf,
|
|
0x0dbb351,0x0bd1831,0x197a81d,0x05b8b26,0x17bd66e,0x1a65651,
|
|
0x0425621,0x1afa477,0x13bf220,0x09c6223,0x0703f4e,0x10fb49f,
|
|
0x1370a67,0x05c56ff,0x13415fd,0x1e15d79,0x13f33ae,0x1a2608b,
|
|
0x0d08179,0x124b44d,0x0d1f0a5,0x1ddfedc,0x1d25c8b,0x09526c9,
|
|
0x0227d28,0x08d73bc,0x02ad322,0x00941c1,0x015c40d } },
|
|
/* 241 */
|
|
{ { 0x00e18d1,0x18b4d15,0x1f0a6eb,0x0e98064,0x1971c01,0x0131674,
|
|
0x0c8fdef,0x0f3b034,0x1818ff3,0x04cedc6,0x0f0cc08,0x0c7a99a,
|
|
0x13663f6,0x008d02a,0x14c970c,0x148e1de,0x1dcf980,0x04e6b85,
|
|
0x127b41c,0x08a5a23,0x0e13e64,0x1a5633b,0x0befd0f,0x10b854b,
|
|
0x0c0a6ae,0x0624bdf,0x011c124,0x1f55caa,0x1e6ba92,0x1d43a48,
|
|
0x0502ae5,0x155f532,0x055f537,0x132aba0,0x16ecd9c,0x1ff92b5,
|
|
0x1119d6b,0x11a1dce,0x078dd91,0x1413a68,0x0788e94 },
|
|
{ 0x053461a,0x137f2ce,0x1bb414e,0x1c11c76,0x15ec897,0x146c9cb,
|
|
0x14bcc1d,0x09f51eb,0x0cc213d,0x1eb5ffb,0x0051f26,0x16820b6,
|
|
0x09590c7,0x1e3dc0b,0x08d8a2d,0x0f1d241,0x06e5bce,0x1e33504,
|
|
0x17b0763,0x09a5049,0x0ce93dd,0x0260cee,0x0242b3d,0x086b4fd,
|
|
0x0d875d8,0x0d93319,0x07a98e0,0x1202cf8,0x1cc1285,0x0bcbf86,
|
|
0x18ec896,0x08df1a8,0x1a612b4,0x17d1cc8,0x15e3057,0x108430b,
|
|
0x119f678,0x0af61b8,0x1aa4f7d,0x18cf01b,0x091b19c } },
|
|
/* 242 */
|
|
{ { 0x15d8b80,0x1384ee5,0x183bafc,0x05f86ac,0x03b9618,0x0f7cb48,
|
|
0x1664415,0x08570e7,0x1e47c43,0x0f525a6,0x1e219f4,0x0489aa9,
|
|
0x0fcc4b9,0x1ec6bbf,0x0c68b2b,0x1eac727,0x0e7e8c1,0x1034692,
|
|
0x065cc15,0x1f576c9,0x174f5f5,0x0802a11,0x00c9231,0x071d227,
|
|
0x1e2b53f,0x05f61b6,0x0deeda0,0x1a0fd1d,0x1313b5e,0x09ebec7,
|
|
0x04a5920,0x15fa5a7,0x1b6a069,0x0518d3d,0x1238212,0x0b80db0,
|
|
0x04f0c32,0x13fd97f,0x10ebda1,0x0680ce6,0x03c2ba8 },
|
|
{ 0x13ad63b,0x16bbace,0x0c7ead8,0x0eb3c1d,0x1f9cab9,0x02f08b9,
|
|
0x0a98ce2,0x13ce066,0x0e20b2f,0x11657e7,0x12a51fc,0x14fc93d,
|
|
0x0db529b,0x11146c4,0x0550859,0x12ac249,0x1ec3923,0x0407511,
|
|
0x10dc191,0x120fcfa,0x0e441b8,0x0aab1f2,0x12dfe91,0x14961f4,
|
|
0x1829eb2,0x1c96654,0x1120181,0x014e414,0x0991ced,0x0d06123,
|
|
0x1ae3337,0x0691a10,0x1a2325b,0x177099b,0x1427d82,0x1eacdda,
|
|
0x147f253,0x1870488,0x0ef60f4,0x14b820e,0x01fa627 } },
|
|
/* 243 */
|
|
{ { 0x0478fd4,0x1115121,0x0002844,0x02ce164,0x0cf4c6f,0x0ce36f5,
|
|
0x0c13e0d,0x179ee37,0x17b93cd,0x0c71414,0x16d82d8,0x15c6461,
|
|
0x0996e1b,0x0b2d9d9,0x1ff4ed2,0x0abbbe2,0x1c6bc70,0x1d2c31c,
|
|
0x0e05f5f,0x1525da9,0x08a4c3e,0x13691d8,0x0420aca,0x02e021d,
|
|
0x1228adc,0x0cbc238,0x1883a27,0x0a773c8,0x1f77c97,0x07cb81f,
|
|
0x1973df9,0x0577cc1,0x03f8245,0x100beb6,0x12f2e03,0x173c865,
|
|
0x00a45ed,0x052d66e,0x1d0f854,0x00a8f30,0x067b8bd },
|
|
{ 0x0797cf7,0x03cda7a,0x180b998,0x15a07fb,0x031c998,0x055778f,
|
|
0x1d8e953,0x022b546,0x0f76497,0x06cd0ff,0x06c69d9,0x18e75e5,
|
|
0x137ce0d,0x1db3654,0x186c20f,0x0d4f0cc,0x0fe32fb,0x0dfa6ba,
|
|
0x1c02958,0x0dde13b,0x115925f,0x1fc18e8,0x0af10e0,0x0d7bc6e,
|
|
0x0c10c53,0x12db6ae,0x1e20b31,0x0928bf3,0x1a99b8d,0x0789a28,
|
|
0x09207d2,0x0d75823,0x00161cd,0x125050a,0x13b7c62,0x093b29a,
|
|
0x0467a82,0x1b18b2d,0x0bb7d94,0x1534993,0x074297a } },
|
|
/* 244 */
|
|
{ { 0x01124ba,0x1ac5271,0x0f4b125,0x1150fff,0x19bd819,0x131c544,
|
|
0x13744f5,0x0ec8bf7,0x015f7bf,0x0322ffc,0x1b55fa5,0x06df89c,
|
|
0x195fa67,0x09730ed,0x0b991d6,0x128943d,0x00ccbdf,0x03cabae,
|
|
0x16cc75d,0x02608e4,0x1ae6a3d,0x112655a,0x1e2077c,0x0510fe4,
|
|
0x1d2991a,0x02cc6df,0x0289ab1,0x07a0eb2,0x061d4a2,0x0c296c3,
|
|
0x1dcb962,0x1140281,0x1b5c13b,0x1bc151b,0x0678fec,0x001f283,
|
|
0x1bc14e9,0x15502c8,0x0ec49c8,0x175aab7,0x089aab7 },
|
|
{ 0x056bdc7,0x02d4b6b,0x14ee2cd,0x1fc2ed9,0x03bdc8a,0x0b2621a,
|
|
0x062d8cb,0x083ad2a,0x179b82b,0x079b253,0x033e0bf,0x089dff6,
|
|
0x1b907b3,0x0880943,0x14320f1,0x121dfe7,0x05934cd,0x074f935,
|
|
0x1c20ad7,0x0b55e40,0x0165e5f,0x1af673e,0x13adcb1,0x130d9ac,
|
|
0x10a81be,0x15574ac,0x1ffc54d,0x1dde931,0x063d5ef,0x0121d41,
|
|
0x0ac1158,0x0a95d0e,0x00be14f,0x03b434a,0x13278c8,0x157dcf7,
|
|
0x01bc4d7,0x0b513ee,0x0ad1b52,0x12eb281,0x0002dc2 } },
|
|
/* 245 */
|
|
{ { 0x09d60c3,0x19c9bdb,0x1d57b94,0x05fd2e4,0x060be55,0x0392d31,
|
|
0x0de3703,0x185623f,0x0cab2e7,0x0c1613f,0x0c8b2da,0x1bb3dc4,
|
|
0x174bcee,0x0913827,0x0ac67b4,0x0c2cb2a,0x085854a,0x096fa61,
|
|
0x0c64921,0x016b7ef,0x152aba4,0x08008cf,0x1f2f2a5,0x15bb0df,
|
|
0x1d1cbe5,0x160ba33,0x0f6743c,0x17ea6df,0x14ebc99,0x171a5c6,
|
|
0x05cf0a5,0x00b5026,0x095f8f4,0x1afbb02,0x0359ccc,0x0518b3d,
|
|
0x0054212,0x09e9927,0x169cc2d,0x06a7877,0x04d5645 },
|
|
{ 0x05c0877,0x17c003f,0x1d91cc8,0x0c19534,0x081b43e,0x00938b2,
|
|
0x13d2e8b,0x184463e,0x1ed3136,0x0acb42b,0x0cc3782,0x064471b,
|
|
0x1cae826,0x0cc8475,0x0beb502,0x0463cca,0x014af0d,0x085c68c,
|
|
0x072f0d2,0x018a961,0x1f8e268,0x19a5f9d,0x1f5158b,0x056b2bf,
|
|
0x1090b09,0x01a14c2,0x117857f,0x0de7394,0x178168e,0x08c8de1,
|
|
0x01dc05d,0x108b495,0x06944b3,0x0aa0d48,0x1d2a0a8,0x09598da,
|
|
0x1155c8b,0x04dd59d,0x1b18ab7,0x19cee60,0x01f2f89 } },
|
|
/* 246 */
|
|
{ { 0x0ffefdf,0x1f7a0cd,0x15ae094,0x0a99f24,0x05d7ece,0x0272418,
|
|
0x00bcad1,0x03e6ee0,0x1cba547,0x0c4baaf,0x0f8056c,0x0797ab9,
|
|
0x09c8848,0x1505c21,0x13df1a5,0x1ec3a4a,0x1d461f3,0x18c4285,
|
|
0x0891c55,0x0421121,0x0b0d7ba,0x176c977,0x0d6aef0,0x0bbd912,
|
|
0x0cabe96,0x0257dab,0x12f155a,0x1b446e4,0x1a74929,0x1cb7b53,
|
|
0x11b62e8,0x05de974,0x0b90db7,0x0d93d7e,0x1f82642,0x1dba469,
|
|
0x16f4366,0x19e0b23,0x0351ef7,0x0fe2fca,0x009c809 },
|
|
{ 0x0050c07,0x058a030,0x0df9a81,0x108751c,0x029e831,0x0af20fe,
|
|
0x0a6caed,0x0759728,0x02ce60e,0x097f52d,0x160bd3b,0x1fe7b73,
|
|
0x1adc7b1,0x143e9bf,0x1afb30d,0x0ea7291,0x032ecb0,0x13c8a9f,
|
|
0x1c1d5a4,0x000a9ea,0x19ba6a6,0x064003a,0x0e1c734,0x1245be2,
|
|
0x1386f30,0x1be0bd3,0x1a0cd5e,0x1d3f8b3,0x0151864,0x19d49ca,
|
|
0x024749a,0x1a69b71,0x12a0222,0x06db8c8,0x13d167f,0x0ccce5f,
|
|
0x04ff303,0x1f9346a,0x185b168,0x1a6d223,0x06f113e } },
|
|
/* 247 */
|
|
{ { 0x036f1c9,0x0efac8c,0x01f54aa,0x0a84646,0x1a6519f,0x16942d7,
|
|
0x11c0577,0x0eb080d,0x0af627f,0x10aa2e5,0x0105f42,0x03dd59c,
|
|
0x03ae111,0x13089a2,0x0a2f7da,0x19797f6,0x0ab52db,0x06f4f78,
|
|
0x004f996,0x183036f,0x1225e9d,0x0dcc893,0x02c76af,0x10298b2,
|
|
0x198e322,0x13f2f82,0x1b64d3b,0x18772cd,0x1ba4bf5,0x076d5cc,
|
|
0x19d3ae1,0x07836ab,0x0919a34,0x14307d9,0x0d2652a,0x0d535bb,
|
|
0x16811ff,0x19106ff,0x00f886d,0x077a343,0x06636a2 },
|
|
{ 0x0587283,0x0ad1690,0x11777d7,0x13de0ff,0x0b3822c,0x1b6f1c0,
|
|
0x0f5543b,0x03a2f0d,0x125d167,0x11e7c83,0x0c77bc5,0x0e3e39b,
|
|
0x0a74bf9,0x04217e2,0x127a0c0,0x0a9eeae,0x1c727f8,0x187176d,
|
|
0x13892b2,0x0f77b57,0x108dbb2,0x1602df6,0x106c673,0x1920979,
|
|
0x0123ef7,0x16dd56d,0x0f62660,0x04853e3,0x16e6320,0x10b732f,
|
|
0x0c9274d,0x1dcb3fa,0x1789fa8,0x194fad1,0x0eebfa7,0x002c174,
|
|
0x0f5378a,0x169db0d,0x09be03c,0x0ece785,0x07aeecc } },
|
|
/* 248 */
|
|
{ { 0x043b0db,0x03abe6e,0x12b7ce9,0x0b30233,0x1d8a4e8,0x0b60ab1,
|
|
0x16fd918,0x12ff012,0x04f533e,0x11503de,0x1f16b4f,0x06ce739,
|
|
0x0ca9824,0x06b4029,0x09ae8eb,0x1d8cc31,0x1908a1c,0x0deb072,
|
|
0x0ac6da5,0x10834a0,0x195bae3,0x090c850,0x061b7fc,0x063fb37,
|
|
0x0beacad,0x1bd96f9,0x1331ca3,0x1b12644,0x10a9927,0x139c067,
|
|
0x1ab0e3a,0x0b0d489,0x0439a80,0x0f81e54,0x1fc0585,0x0bdbcfe,
|
|
0x07a1f88,0x124c841,0x1d91520,0x00d6f14,0x028ec40 },
|
|
{ 0x0fe0009,0x1061751,0x13a7860,0x05e270e,0x011ba5d,0x126da97,
|
|
0x0915314,0x0532ea4,0x07fede5,0x0a3ba13,0x1403513,0x0335364,
|
|
0x0b01d34,0x0c34922,0x0229248,0x1c3739c,0x023dd1b,0x05d0b48,
|
|
0x0a8c078,0x187ca86,0x0788242,0x1d38483,0x06d5bde,0x0951989,
|
|
0x12a09c7,0x01cf856,0x075dbe5,0x139a308,0x1fb60e9,0x1f05b10,
|
|
0x0d3b76b,0x17872ec,0x16bee54,0x1854202,0x0183fdf,0x1e8ca7f,
|
|
0x0011c0a,0x0a43b79,0x0970daf,0x18e192a,0x0134f4c } },
|
|
/* 249 */
|
|
{ { 0x138dff4,0x0d1f674,0x068e588,0x1690d4f,0x1d101a7,0x0a829bb,
|
|
0x1be5f7a,0x1b7e589,0x1e65d87,0x18c204c,0x0e33ebc,0x1ff66e7,
|
|
0x0eb89c7,0x142148b,0x0ea9417,0x14ec8d1,0x1094ebe,0x1d3c87e,
|
|
0x164a24a,0x1beda9c,0x1741679,0x0e7e7f6,0x0808ccc,0x101fe42,
|
|
0x0efd298,0x08085fa,0x1740d11,0x194f1bb,0x0858c87,0x0f659a1,
|
|
0x1e8b2c2,0x04aea90,0x05eb6dc,0x18248cf,0x0857af2,0x02a0ceb,
|
|
0x1381d47,0x0973a7b,0x15bd027,0x05307a7,0x06ea378 },
|
|
{ 0x05cc40a,0x004a5a7,0x17ef197,0x1435e6f,0x1a2e3f6,0x0137223,
|
|
0x1fa77e4,0x0a7dece,0x193880f,0x1c3c64a,0x112aa6d,0x160efec,
|
|
0x1c4aa30,0x1790461,0x1145a0c,0x0cc7741,0x1ae658d,0x03e013b,
|
|
0x187644c,0x1678715,0x1ea4ef0,0x13b4ae1,0x0c0bcde,0x018bc1a,
|
|
0x0c1c56a,0x1cff002,0x10832f3,0x1fa92b8,0x0a0e7c9,0x0dceab4,
|
|
0x151c1b5,0x0b250c8,0x1225dff,0x1384e45,0x1196366,0x10a4fa8,
|
|
0x07c08d6,0x02ac6d4,0x1c1f51f,0x1cd769d,0x0606ee6 } },
|
|
/* 250 */
|
|
{ { 0x1c621f6,0x0cfe3ab,0x15200b6,0x02ffd07,0x092e40c,0x18ccd81,
|
|
0x11e867b,0x0cc37bf,0x0e62c76,0x0502081,0x0e1d4de,0x06e1cce,
|
|
0x0f16cda,0x0f1d32d,0x0065d34,0x1c41379,0x048f78f,0x10cba10,
|
|
0x1d66071,0x140b157,0x102dc83,0x1a4e44b,0x1c9ac90,0x034cf15,
|
|
0x12f1e9d,0x114cc45,0x03fca6b,0x0e57f36,0x1cf5ec4,0x11cc0eb,
|
|
0x162850f,0x164d1bb,0x09d7e45,0x07fbb4e,0x09557f1,0x062cd9b,
|
|
0x04aa767,0x0266f85,0x01c1d81,0x1efd229,0x049dba6 },
|
|
{ 0x158e37a,0x03fd953,0x1d98839,0x0e5b1d5,0x0f6b31d,0x0e11085,
|
|
0x157e5be,0x0566a55,0x190efc3,0x049fb93,0x12c9900,0x13b883c,
|
|
0x15435c9,0x02d8abc,0x0a1e380,0x06aeb7f,0x0a40e67,0x0cce290,
|
|
0x1fba9d6,0x104b290,0x148bca6,0x00f8951,0x00a7dee,0x1459c6a,
|
|
0x1cc182a,0x162d2a3,0x0fab578,0x023b0e9,0x082cdfa,0x1a4daab,
|
|
0x19a6bc0,0x1177d1c,0x06ebfea,0x1ca55fc,0x1e0bd54,0x1e7b570,
|
|
0x0bc8eb8,0x05fbcbf,0x19e3116,0x14936fb,0x04890a7 } },
|
|
/* 251 */
|
|
{ { 0x1a995f6,0x0cb44c6,0x1bbf5ca,0x0fd8c2a,0x139eaae,0x15416ae,
|
|
0x01030d5,0x1fcd2b2,0x1c135bc,0x1023590,0x0571e2c,0x16c81eb,
|
|
0x00ea720,0x13e2fda,0x0093beb,0x077f805,0x14c0edb,0x14bec7e,
|
|
0x07c93af,0x00520af,0x06b912f,0x078c3f5,0x05bf11f,0x13ab846,
|
|
0x1fd2778,0x166610c,0x122498f,0x0674d6d,0x0d30a62,0x1a5945b,
|
|
0x00208d8,0x193666d,0x0352e25,0x1ba2b65,0x1b29031,0x172711a,
|
|
0x1c92065,0x12ad859,0x069dbe3,0x0960487,0x05c1747 },
|
|
{ 0x0accab5,0x073e145,0x016f622,0x0d559da,0x1802783,0x1607b28,
|
|
0x01df733,0x10430b7,0x0125c28,0x1e56e0e,0x1715324,0x0814cff,
|
|
0x1345df5,0x013c451,0x0f21b8b,0x1f4589e,0x069e3a0,0x19f43a2,
|
|
0x1ce60f3,0x1b548e4,0x18a5c59,0x05a54b6,0x0c18f12,0x1cb122a,
|
|
0x12bcfc2,0x061e1c6,0x1e1390a,0x01cf170,0x04fd539,0x1496786,
|
|
0x0164028,0x1283cc0,0x1f92db7,0x09d0e5b,0x0905b29,0x0f2acf2,
|
|
0x11ab0fa,0x1b798ed,0x10230d7,0x168f6b0,0x05d675e } },
|
|
/* 252 */
|
|
{ { 0x10c6025,0x10d3bc3,0x1f2abbb,0x0f2345b,0x1c4a23b,0x15b2627,
|
|
0x18310e1,0x162f61c,0x1e5ae72,0x0ead8be,0x1e884b5,0x11593dd,
|
|
0x166dfc8,0x0a01c5c,0x1abbefb,0x05d989f,0x1568e2d,0x184cd61,
|
|
0x04abc81,0x1d4c240,0x1218548,0x0dc4e18,0x13ffb67,0x1cce662,
|
|
0x091c4e0,0x0700e0f,0x1ebe0c0,0x01376c9,0x13c3be0,0x080e33b,
|
|
0x1ea1e01,0x1810433,0x0cd6ede,0x1837ff0,0x181fe06,0x1ef80ab,
|
|
0x0080b36,0x1b1fce7,0x1b28e0a,0x15e153f,0x002fccb },
|
|
{ 0x07cac61,0x0ea68da,0x04b2664,0x0f570dc,0x0e9d168,0x0a78211,
|
|
0x157b0ae,0x1cb18d0,0x148e648,0x120028c,0x06b15f2,0x1f65df1,
|
|
0x0d9ba91,0x0df3c96,0x1064818,0x03c2a9e,0x1cbbd0f,0x0c16910,
|
|
0x1111006,0x1d6277f,0x0fdc062,0x194cbc8,0x1cea5f0,0x0cf4c97,
|
|
0x16d9460,0x1ad273c,0x01b48dd,0x08dba60,0x1f0f23c,0x026af6b,
|
|
0x15e19cb,0x0769ec7,0x01851dc,0x139f941,0x1833498,0x1ea1475,
|
|
0x0ac60f6,0x072c7e7,0x1551600,0x0ac2708,0x056f1e4 } },
|
|
/* 253 */
|
|
{ { 0x0c24f3b,0x059fb19,0x1f98073,0x1e0db02,0x19eb1c7,0x1133bb4,
|
|
0x102edaa,0x1c11b8c,0x00845d5,0x01c57ff,0x09e6a1e,0x1963f03,
|
|
0x10f34fe,0x1f340cd,0x0b8a0b4,0x14970d4,0x1ce8237,0x0e25cbb,
|
|
0x1d8d90e,0x0d67b70,0x04970f4,0x004bcb8,0x09197d5,0x1237c87,
|
|
0x0876287,0x1636bf0,0x10d0663,0x004416d,0x1d94bb0,0x031b849,
|
|
0x0c95ece,0x053ad21,0x0012e16,0x168d242,0x16d482a,0x0605d93,
|
|
0x05dc34e,0x1717e34,0x033e2bf,0x06c4aa0,0x0911d19 },
|
|
{ 0x1e5af5b,0x0deac7a,0x0a9c4ec,0x16f6d44,0x07ca263,0x17956e5,
|
|
0x1b137ce,0x17b56d7,0x1a04420,0x1328f2c,0x0db0445,0x1676974,
|
|
0x103b448,0x1fa1218,0x18aff37,0x0d97678,0x0a5f1a9,0x06f0ae2,
|
|
0x1347e60,0x15b143c,0x1a3abe0,0x071b339,0x004af45,0x02559bb,
|
|
0x03af692,0x0e72018,0x115d825,0x1edb573,0x1f5ca58,0x0415083,
|
|
0x0c1f7c6,0x1112d47,0x103e63c,0x1d9f85c,0x1513618,0x1dea090,
|
|
0x009887d,0x080cdce,0x0e19579,0x1fd41ea,0x02be744 } },
|
|
/* 254 */
|
|
{ { 0x150f324,0x0682fad,0x1e88153,0x083d478,0x19b1eb2,0x1c735bd,
|
|
0x02971ff,0x104950b,0x0ec0408,0x01c817f,0x0ea6f76,0x0929a19,
|
|
0x1e72b26,0x194e4f0,0x05dbe42,0x1b703a0,0x102ceba,0x002ea75,
|
|
0x1cae2ff,0x080b626,0x1190874,0x00bcf56,0x17104a2,0x056919a,
|
|
0x03dd3ec,0x019ea25,0x1cfd354,0x089334e,0x0c3a098,0x1c66ab2,
|
|
0x0eecdec,0x1e85d00,0x0e99497,0x08c5940,0x1e82e3d,0x0980f68,
|
|
0x1568fde,0x0871e29,0x039eb1c,0x05f9d5a,0x0735f54 },
|
|
{ 0x0380039,0x0d0b89c,0x07232aa,0x0fee9a3,0x0dfafe1,0x1e0d45d,
|
|
0x0e4fb32,0x00b25a8,0x1fe0297,0x02edf9c,0x1a6cd8f,0x0b57261,
|
|
0x0a4552b,0x157ea4a,0x198c0c8,0x15886fd,0x0d73f02,0x041354d,
|
|
0x04d58a6,0x0a6ac53,0x1b3998c,0x03b9a15,0x0321a7e,0x1f36f34,
|
|
0x10020e4,0x0d4eba8,0x134d1e2,0x06c3a34,0x0856376,0x0add67d,
|
|
0x193c37b,0x111580f,0x07ee73f,0x18e5ea0,0x00fc27b,0x1bf58fa,
|
|
0x0d475ba,0x0b4be5a,0x0e67897,0x13a297a,0x01e984c } },
|
|
/* 255 */
|
|
{ { 0x050c817,0x082b0a4,0x04b71db,0x1269130,0x108a5b1,0x0c65df5,
|
|
0x1455179,0x0b4e4e7,0x04be61e,0x0805afd,0x1ae3862,0x0d23af5,
|
|
0x0baa088,0x09ad1ea,0x1999abf,0x0fa7bcc,0x19957ec,0x01c5160,
|
|
0x1a35bd7,0x091d1ec,0x1746a06,0x163d6e0,0x07e7f24,0x060cb86,
|
|
0x116c084,0x13491d0,0x01879ab,0x0c6e144,0x047e733,0x1b9b155,
|
|
0x01189b0,0x1bdfedb,0x00c25f2,0x1696a2a,0x093336f,0x0530090,
|
|
0x039a949,0x0dfe700,0x0b8052d,0x0aced28,0x06c474a },
|
|
{ 0x188e3a1,0x1cd20be,0x10a8eba,0x118908e,0x105d3c8,0x1308988,
|
|
0x1a344ff,0x117cb3b,0x11a869e,0x047adb5,0x1764285,0x18b354e,
|
|
0x137a8ab,0x110a300,0x0326f1d,0x099b25e,0x147c382,0x121fd53,
|
|
0x09742e4,0x0c7430d,0x0ebc817,0x1e4de5d,0x0ef0d06,0x08ba3bb,
|
|
0x13160f7,0x0fa70c0,0x16dd739,0x0a79ca5,0x0de4c2a,0x13366a8,
|
|
0x1b457ab,0x0ebaeca,0x0d8996c,0x12a952f,0x1c47132,0x09c9fea,
|
|
0x1c5305b,0x0f4c2d1,0x08b3885,0x0a9f437,0x06b2589 } },
|
|
};
|
|
|
|
/* Multiply the base point of P1024 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* Stripe implementation.
|
|
* Pre-generated: 2^0, 2^128, ...
|
|
* Pre-generated: products of all combinations of above.
|
|
* 8 doubles and adds (with qz=1)
|
|
*
|
|
* r Resulting point.
|
|
* k Scalar to multiply by.
|
|
* map Indicates whether to convert result to affine.
|
|
* ct Constant time required.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
static int sp_1024_ecc_mulmod_base_42(sp_point_1024* r, const sp_digit* k,
|
|
int map, int ct, void* heap)
|
|
{
|
|
return sp_1024_ecc_mulmod_stripe_42(r, &p1024_base, p1024_table,
|
|
k, map, ct, heap);
|
|
}
|
|
|
|
#endif
|
|
|
|
/* Multiply the base point of P1024 by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_1024(const mp_int* km, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_1024 point[1];
|
|
sp_digit k[42];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_from_mp(k, 42, km);
|
|
|
|
err = sp_1024_ecc_mulmod_base_42(point, k, map, 1, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_to_ecc_point_42(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply the base point of P1024 by the scalar, add point a and return
|
|
* the result. If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* am Point to add to scalar mulitply result.
|
|
* inMont Point to add is in montgomery form.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_base_add_1024(const mp_int* km, const ecc_point* am,
|
|
int inMont, ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_1024 point[2];
|
|
sp_digit k[42 + 42 * 2 * 37];
|
|
#endif
|
|
sp_point_1024* addP = NULL;
|
|
sp_digit* tmp = NULL;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(
|
|
sizeof(sp_digit) * (42 + 42 * 2 * 37),
|
|
heap, DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
addP = point + 1;
|
|
tmp = k + 42;
|
|
|
|
sp_1024_from_mp(k, 42, km);
|
|
sp_1024_point_from_ecc_point_42(addP, am);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_1024_mod_mul_norm_42(addP->x, addP->x, p1024_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_1024_mod_mul_norm_42(addP->y, addP->y, p1024_mod);
|
|
}
|
|
if ((err == MP_OKAY) && (!inMont)) {
|
|
err = sp_1024_mod_mul_norm_42(addP->z, addP->z, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_ecc_mulmod_base_42(point, k, 0, 0, heap);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
sp_1024_proj_point_add_42(point, point, addP, tmp);
|
|
|
|
if (map) {
|
|
sp_1024_map_42(point, point, tmp);
|
|
}
|
|
|
|
err = sp_1024_point_to_ecc_point_42(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/* Generate a pre-computation table for the point.
|
|
*
|
|
* gm Point to generate table for.
|
|
* table Buffer to hold pre-computed points table.
|
|
* len Length of table.
|
|
* heap Heap to use for allocation.
|
|
* returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is
|
|
* NULL and length is returned, BUFFER_E if length is too small and 0 otherwise.
|
|
*/
|
|
int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len,
|
|
void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* point = NULL;
|
|
sp_digit* t = NULL;
|
|
#else
|
|
sp_point_1024 point[1];
|
|
sp_digit t[38 * 2 * 42];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
if ((gm == NULL) || (len == NULL)) {
|
|
err = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if ((err == MP_OKAY) && (table == NULL)) {
|
|
*len = sizeof(sp_table_entry_1024) * 256;
|
|
err = LENGTH_ONLY_E;
|
|
}
|
|
if ((err == MP_OKAY) && (*len < (int)(sizeof(sp_table_entry_1024) * 256))) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 38 * 2 * 42, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (t == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_point_from_ecc_point_42(point, gm);
|
|
err = sp_1024_gen_stripe_table_42(point,
|
|
(sp_table_entry_1024*)table, t, heap);
|
|
}
|
|
if (err == 0) {
|
|
*len = sizeof(sp_table_entry_1024) * 256;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t != NULL)
|
|
XFREE(t, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#else
|
|
/* Generate a pre-computation table for the point.
|
|
*
|
|
* gm Point to generate table for.
|
|
* table Buffer to hold pre-computed points table.
|
|
* len Length of table.
|
|
* heap Heap to use for allocation.
|
|
* returns BAD_FUNC_ARG when gm or len is NULL, LENGTH_ONLY_E when table is
|
|
* NULL and length is returned, BUFFER_E if length is too small and 0 otherwise.
|
|
*/
|
|
int sp_ecc_gen_table_1024(const ecc_point* gm, byte* table, word32* len,
|
|
void* heap)
|
|
{
|
|
int err = 0;
|
|
|
|
if ((gm == NULL) || (len == NULL)) {
|
|
err = BAD_FUNC_ARG;
|
|
}
|
|
|
|
if ((err == 0) && (table == NULL)) {
|
|
*len = 0;
|
|
err = LENGTH_ONLY_E;
|
|
}
|
|
if ((err == 0) && (*len != 0)) {
|
|
err = BUFFER_E;
|
|
}
|
|
if (err == 0) {
|
|
*len = 0;
|
|
}
|
|
|
|
(void)heap;
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
/* Multiply the point by the scalar and return the result.
|
|
* If map is true then convert result to affine coordinates.
|
|
*
|
|
* km Scalar to multiply by.
|
|
* gm Point to multiply.
|
|
* table Pre-computed points.
|
|
* r Resulting point.
|
|
* map Indicates whether to convert result to affine.
|
|
* heap Heap to use for allocation.
|
|
* returns MEMORY_E when memory allocation fails and MP_OKAY on success.
|
|
*/
|
|
int sp_ecc_mulmod_table_1024(const mp_int* km, const ecc_point* gm, byte* table,
|
|
ecc_point* r, int map, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* point = NULL;
|
|
sp_digit* k = NULL;
|
|
#else
|
|
sp_point_1024 point[1];
|
|
sp_digit k[42];
|
|
#endif
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
point = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (point == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY) {
|
|
k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap, DYNAMIC_TYPE_ECC);
|
|
if (k == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_from_mp(k, 42, km);
|
|
sp_1024_point_from_ecc_point_42(point, gm);
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
err = sp_1024_ecc_mulmod_stripe_42(point, point,
|
|
(const sp_table_entry_1024*)table, k, map, 0, heap);
|
|
#else
|
|
(void)table;
|
|
err = sp_1024_ecc_mulmod_42(point, point, k, map, 0, heap);
|
|
#endif
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_to_ecc_point_42(point, r);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (k != NULL)
|
|
XFREE(k, heap, DYNAMIC_TYPE_ECC);
|
|
if (point != NULL)
|
|
XFREE(point, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Multiply p* in projective co-ordinates by q*.
|
|
*
|
|
* r.x = p.x - (p.y * q.y)
|
|
* r.y = (p.x * q.y) + p.y
|
|
*
|
|
* px [in,out] A single precision integer - X ordinate of number to multiply.
|
|
* py [in,out] A single precision integer - Y ordinate of number to multiply.
|
|
* q [in] A single precision integer - multiplier.
|
|
* t [in] Two single precision integers - temps.
|
|
*/
|
|
static void sp_1024_proj_mul_qx1_42(sp_digit* px, sp_digit* py,
|
|
const sp_digit* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
|
|
/* t1 = p.x * q.y */
|
|
sp_1024_mont_mul_42(t1, px, q, p1024_mod, p1024_mp_mod);
|
|
/* t2 = p.y * q.y */
|
|
sp_1024_mont_mul_42(t2, py, q, p1024_mod, p1024_mp_mod);
|
|
/* r.x = p.x - (p.y * q.y) */
|
|
sp_1024_mont_sub_42(px, px, t2, p1024_mod);
|
|
/* r.y = (p.x * q.y) + p.y */
|
|
sp_1024_mont_add_42(py, t1, py, p1024_mod);
|
|
}
|
|
|
|
/* Square p* in projective co-ordinates.
|
|
*
|
|
* px' = (p.x + p.y) * (p.x - p.y) = p.x^2 - p.y^2
|
|
* py' = 2 * p.x * p.y
|
|
*
|
|
* px [in,out] A single precision integer - X ordinate of number to square.
|
|
* py [in,out] A single precision integer - Y ordinate of number to square.
|
|
* t [in] Two single precision integers - temps.
|
|
*/
|
|
static void sp_1024_proj_sqr_42(sp_digit* px, sp_digit* py, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
|
|
/* t1 = p.x + p.y */
|
|
sp_1024_mont_add_42(t1, px, py, p1024_mod);
|
|
/* t2 = p.x - p.y */
|
|
sp_1024_mont_sub_42(t2, px, py, p1024_mod);
|
|
/* r.y = p.x * p.y */
|
|
sp_1024_mont_mul_42(py, px, py, p1024_mod, p1024_mp_mod);
|
|
/* r.x = (p.x + p.y) * (p.x - p.y) */
|
|
sp_1024_mont_mul_42(px, t1, t2, p1024_mod, p1024_mp_mod);
|
|
/* r.y = (p.x * p.y) * 2 */
|
|
sp_1024_mont_dbl_42(py, py, p1024_mod);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/* Perform the modular exponentiation in Fp* for SAKKE.
|
|
*
|
|
* Simple square and multiply when expontent bit is one algorithm.
|
|
* Square and multiply performed in Fp*.
|
|
*
|
|
* base [in] Base. MP integer.
|
|
* exp [in] Exponent. MP integer.
|
|
* res [out] Result. MP integer.
|
|
* returns 0 on success and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res)
|
|
{
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
sp_digit* td;
|
|
sp_digit* t;
|
|
sp_digit* tx;
|
|
sp_digit* ty;
|
|
sp_digit* b;
|
|
sp_digit* e;
|
|
#else
|
|
sp_digit t[36 * 2 * 42];
|
|
sp_digit tx[2 * 42];
|
|
sp_digit ty[2 * 42];
|
|
sp_digit b[2 * 42];
|
|
sp_digit e[2 * 42];
|
|
#endif
|
|
sp_digit* r;
|
|
int err = MP_OKAY;
|
|
int bits;
|
|
int i;
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 40 * 42 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
t = td;
|
|
tx = td + 36 * 42 * 2;
|
|
ty = td + 37 * 42 * 2;
|
|
b = td + 38 * 42 * 2;
|
|
e = td + 39 * 42 * 2;
|
|
#endif
|
|
r = ty;
|
|
|
|
bits = mp_count_bits(exp);
|
|
sp_1024_from_mp(b, 42, base);
|
|
sp_1024_from_mp(e, 42, exp);
|
|
|
|
XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 42);
|
|
sp_1024_mul_42(b, b, p1024_norm_mod);
|
|
err = sp_1024_mod_42(b, b, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(ty, b, sizeof(sp_digit) * 42);
|
|
|
|
for (i = bits - 2; i >= 0; i--) {
|
|
sp_1024_proj_sqr_42(tx, ty, t);
|
|
if ((e[i / 25] >> (i % 25)) & 1) {
|
|
sp_1024_proj_mul_qx1_42(tx, ty, b, t);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_mont_inv_42(tx, tx, t);
|
|
|
|
XMEMSET(tx + 42, 0, sizeof(sp_digit) * 42);
|
|
sp_1024_mont_reduce_42(tx, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(ty + 42, 0, sizeof(sp_digit) * 42);
|
|
sp_1024_mont_reduce_42(ty, p1024_mod, p1024_mp_mod);
|
|
|
|
sp_1024_mul_42(r, tx, ty);
|
|
err = sp_1024_mod_42(r, r, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_to_mp(r, res);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (td != NULL) {
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif
|
|
return err;
|
|
}
|
|
|
|
#else
|
|
/* Pre-computed table for exponentiating g.
|
|
* Striping: 8 points at a distance of (128 combined for
|
|
* a total of 256 points.
|
|
*/
|
|
static const sp_digit sp_1024_g_table[256][42] = {
|
|
{ 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
|
|
0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
|
|
0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
|
|
0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
|
|
0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
|
|
0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000,
|
|
0x0000000, 0x0000000, 0x0000000, 0x0000000, 0x0000000 },
|
|
{ 0x15c1685, 0x1236919, 0x09605c2, 0x03c200f, 0x0ac9e97, 0x052539f,
|
|
0x1cf7d0f, 0x0ea81d1, 0x1826424, 0x1237c0a, 0x15db449, 0x176966c,
|
|
0x1b3af49, 0x195f8d7, 0x078b451, 0x0a3cdb1, 0x02c2fd1, 0x013df44,
|
|
0x1e21c5f, 0x1db90b1, 0x0c6fadd, 0x1f8b563, 0x15b6166, 0x11d5cb1,
|
|
0x01a1b2d, 0x186873a, 0x018707c, 0x1f5ef40, 0x07e0966, 0x084d4db,
|
|
0x1f59b6f, 0x0fa769e, 0x1f11c06, 0x1e4c710, 0x080b1c9, 0x02c2a57,
|
|
0x086cb22, 0x0ac448f, 0x0ebd2bf, 0x0d4d7a7, 0x059e93c },
|
|
{ 0x1dd4594, 0x0e9b7b8, 0x079b953, 0x1e015de, 0x1bc9cc9, 0x0fb2985,
|
|
0x0913a86, 0x0513d4b, 0x13f5209, 0x0c4554c, 0x1050621, 0x12991eb,
|
|
0x1a97537, 0x0089ccf, 0x02f5e4b, 0x0d56a23, 0x0fdf5cb, 0x15cde9d,
|
|
0x1b2e594, 0x1a39645, 0x1813813, 0x13a01c4, 0x1f51589, 0x1908639,
|
|
0x1119b4a, 0x15b28fb, 0x0428603, 0x1b3ed52, 0x1bfa2ed, 0x168bcfb,
|
|
0x1644e51, 0x0a153a1, 0x0f18631, 0x1b9e98b, 0x0835be0, 0x12be338,
|
|
0x1b6a52b, 0x02d6354, 0x0b80efa, 0x0f6e9ec, 0x063ef18 },
|
|
{ 0x16f45e7, 0x1b5bf80, 0x0be1f0d, 0x0e57d90, 0x1c1bdb5, 0x014db00,
|
|
0x1dd0739, 0x03ae725, 0x0c7afd8, 0x1edf851, 0x04262db, 0x163ee48,
|
|
0x0fbda41, 0x1db07c6, 0x101d1d2, 0x1789ab6, 0x141b330, 0x1499f06,
|
|
0x0cfe8ef, 0x105060e, 0x0cd1ae1, 0x0d87ae3, 0x083b4a6, 0x130c191,
|
|
0x1354e3f, 0x020bff9, 0x1855567, 0x026c130, 0x1f85cbb, 0x1b1e094,
|
|
0x0faac32, 0x08ed0bf, 0x02ecc49, 0x0cb19b4, 0x1b0bac6, 0x14a0bd1,
|
|
0x1dac2cd, 0x0e63ca6, 0x1688e43, 0x039e325, 0x04fe679 },
|
|
{ 0x1e8733c, 0x011ea82, 0x1f06529, 0x0a3aae2, 0x0c845e6, 0x10d9916,
|
|
0x1fa23a5, 0x19846f8, 0x0db4181, 0x02238e3, 0x0f5c843, 0x0bc4e27,
|
|
0x0900c87, 0x1960bd8, 0x1f7a7b6, 0x1d5ed3b, 0x1e5e88c, 0x1218536,
|
|
0x0e073a9, 0x0f4c34f, 0x18d5aaa, 0x13119fc, 0x1a94b40, 0x0d13535,
|
|
0x0fdd060, 0x155daaf, 0x1972b12, 0x019f4f9, 0x1507613, 0x188a474,
|
|
0x14be936, 0x09d343c, 0x09570c4, 0x000b818, 0x1d84681, 0x0431843,
|
|
0x1e78d9d, 0x0e8fff5, 0x0ca5d55, 0x030ac3b, 0x004482a },
|
|
{ 0x1d486d8, 0x0c56139, 0x079f9dd, 0x0cc39b8, 0x0169f94, 0x0455a7c,
|
|
0x067f086, 0x060e479, 0x0f33736, 0x072a781, 0x1089828, 0x1c4b7b1,
|
|
0x00560be, 0x0298de3, 0x1f0c1f1, 0x1fd6a51, 0x11a7e44, 0x1eb790f,
|
|
0x1c4a34d, 0x089338a, 0x0a45c8e, 0x1f6bd97, 0x058ec14, 0x147a445,
|
|
0x07a0432, 0x1342061, 0x14d5165, 0x16a30a9, 0x1557e95, 0x124feb9,
|
|
0x1e99b86, 0x10d240e, 0x1267fd9, 0x0138106, 0x034f9cd, 0x09f426a,
|
|
0x08ccdb4, 0x0e1f92b, 0x1e27c6a, 0x1f1bdb7, 0x0833a0f },
|
|
{ 0x1376b76, 0x00ce3d5, 0x0332a31, 0x064fa1e, 0x1b7294f, 0x0628a69,
|
|
0x0e78aa4, 0x14dcad7, 0x0a62575, 0x18dd28f, 0x102a224, 0x00f6131,
|
|
0x0a56fee, 0x1a60b51, 0x0f96bba, 0x04c1609, 0x10be6eb, 0x072899a,
|
|
0x075709c, 0x1db5ad4, 0x0dd1339, 0x0cf4edd, 0x1cd9bb5, 0x1a0dd81,
|
|
0x1be882d, 0x1eda109, 0x032c461, 0x05ac739, 0x01058a2, 0x0af0ec5,
|
|
0x1c47fb2, 0x1456e89, 0x1f73ea6, 0x02e0601, 0x146bd3c, 0x00e83fa,
|
|
0x05f811a, 0x16fcad4, 0x0597cb8, 0x1c7d649, 0x0692b3c },
|
|
{ 0x0a127b4, 0x165b969, 0x05bc339, 0x0b1f250, 0x06a46ea, 0x11bb0b3,
|
|
0x1d18d1e, 0x1dc87d9, 0x1e0ab96, 0x11ecd00, 0x16fa305, 0x18db65d,
|
|
0x05c8145, 0x06f2733, 0x109b2b9, 0x0a5f25e, 0x14074e2, 0x08ba685,
|
|
0x14abe0c, 0x0481aef, 0x093654c, 0x0b9eb29, 0x1607e8e, 0x13a8d2a,
|
|
0x1491ca0, 0x01e02dc, 0x0d51499, 0x189d0a6, 0x1283278, 0x0198ea0,
|
|
0x094cb59, 0x0e06c3e, 0x0479038, 0x184f932, 0x06c627b, 0x00ee832,
|
|
0x01de5fe, 0x078557c, 0x10b5b03, 0x015e800, 0x0333e43 },
|
|
{ 0x126d3b7, 0x026f267, 0x06f977c, 0x0d6a7ef, 0x17a7730, 0x045b322,
|
|
0x0f17c60, 0x0c14802, 0x0850373, 0x1948f52, 0x1840dfb, 0x1afa160,
|
|
0x1b1ffc9, 0x12e489d, 0x1413765, 0x10b0fb3, 0x1aff13b, 0x0ca451b,
|
|
0x18fb9d5, 0x086907f, 0x1386b54, 0x1a02318, 0x0ff0879, 0x1bd6b18,
|
|
0x104e5cd, 0x0a959d0, 0x0995cb3, 0x09fc30c, 0x0aa4089, 0x18d08ad,
|
|
0x18bae69, 0x08b3d48, 0x0dc6fe5, 0x18151c5, 0x05d52ba, 0x037631a,
|
|
0x0f7791d, 0x093b1b1, 0x15c22b8, 0x03bad77, 0x010e8b3 },
|
|
{ 0x0d9f1af, 0x181f29f, 0x059ae1f, 0x0eaccec, 0x03ad247, 0x070adc0,
|
|
0x158c1d3, 0x0b671b9, 0x026b1e8, 0x03bf158, 0x0670546, 0x1a2e35f,
|
|
0x1ab1654, 0x09c12a3, 0x00ba792, 0x0bdeb2f, 0x07c26d5, 0x036e3fe,
|
|
0x1efad53, 0x11f2ba5, 0x0357903, 0x1f01b60, 0x1f96437, 0x1b87eff,
|
|
0x16eae4f, 0x14467e5, 0x13cd786, 0x163f78a, 0x0a5568c, 0x0ed96d0,
|
|
0x15cf238, 0x0b6deaa, 0x087393f, 0x005034d, 0x0ccb9eb, 0x1670c8d,
|
|
0x0a8495a, 0x130e419, 0x112f3f4, 0x09819b9, 0x0648552 },
|
|
{ 0x0a6ff2a, 0x1d9f162, 0x0a286af, 0x146b4c8, 0x0aa03fb, 0x17fba11,
|
|
0x09fc226, 0x1271084, 0x0ba5dbd, 0x19bc41d, 0x060b2c8, 0x15d3a54,
|
|
0x0538186, 0x04d00f8, 0x1c1d935, 0x03cf573, 0x1eb917b, 0x1c9208f,
|
|
0x1c32ed6, 0x163206a, 0x1e7c700, 0x0adc8a5, 0x1754607, 0x102305a,
|
|
0x0443719, 0x0cb89ae, 0x115d2e6, 0x04eb1a4, 0x0d28b23, 0x147ab19,
|
|
0x0269942, 0x1f4707e, 0x0078bac, 0x19ec012, 0x1830028, 0x12ca8d4,
|
|
0x0df8b44, 0x030e3d1, 0x158f290, 0x1e5e468, 0x01f76f3 },
|
|
{ 0x0c436b0, 0x160a1a2, 0x01ea6a8, 0x0c3ed39, 0x1907055, 0x16d96fb,
|
|
0x045ed7d, 0x1046be6, 0x1ed56ba, 0x0bb0fa0, 0x0be9221, 0x0c9efa1,
|
|
0x1ef8314, 0x1d6e738, 0x07ca454, 0x0e91153, 0x093116b, 0x1593dfb,
|
|
0x0ee510e, 0x14b5193, 0x1de8a98, 0x131772f, 0x1fe1e00, 0x025596e,
|
|
0x193dd18, 0x0491d37, 0x137212f, 0x1f25499, 0x14995aa, 0x1157f8e,
|
|
0x074f095, 0x009db13, 0x19fc33c, 0x1529c7e, 0x0a513b4, 0x0d80519,
|
|
0x049ea72, 0x19b3dd8, 0x0381743, 0x1f67a21, 0x004924f },
|
|
{ 0x073562f, 0x0471ee3, 0x1230195, 0x0bc5d5c, 0x13b3302, 0x0e34bbe,
|
|
0x14cad78, 0x0f7cc3f, 0x06ebe55, 0x1271032, 0x1b86390, 0x038083a,
|
|
0x1b76739, 0x0a6bf4a, 0x03aee38, 0x0371897, 0x1d42099, 0x1a5745b,
|
|
0x004a434, 0x01becdc, 0x1f4ef8a, 0x11c92f2, 0x125f892, 0x0104e55,
|
|
0x1b2cb15, 0x130bcd3, 0x18941c9, 0x08160e5, 0x02fa49b, 0x10c1483,
|
|
0x13b6b67, 0x1e78a77, 0x180a784, 0x013ccc3, 0x0dda7c5, 0x0cb1505,
|
|
0x0146842, 0x06c24e6, 0x0b8d423, 0x0138701, 0x04dfce8 },
|
|
{ 0x127b780, 0x14e596a, 0x0375141, 0x0b2ef26, 0x152da01, 0x1e8131e,
|
|
0x1802f89, 0x0562198, 0x0bb2d1b, 0x0081613, 0x0b7cf0d, 0x0c46aa9,
|
|
0x074c652, 0x02f87fa, 0x0244e09, 0x0dcf9ad, 0x0c5ca91, 0x141fd46,
|
|
0x0572362, 0x01e273a, 0x16b31e1, 0x1740ee2, 0x1c5cf70, 0x09db375,
|
|
0x0cb045c, 0x1143fe7, 0x011f404, 0x00ffafb, 0x1a532f3, 0x18a9cf9,
|
|
0x0889295, 0x1c42a78, 0x1e9e81d, 0x052042c, 0x057790a, 0x078ac4b,
|
|
0x1339bd2, 0x1ed7fc4, 0x1a00b71, 0x0117140, 0x00d0759 },
|
|
{ 0x0085f2a, 0x17953ef, 0x0b961c2, 0x1f7d336, 0x08fcd24, 0x05209dc,
|
|
0x1498567, 0x0a31181, 0x08559f8, 0x1815172, 0x0b68347, 0x0043ec4,
|
|
0x1583b96, 0x16e51b0, 0x0170bd5, 0x18d04b8, 0x11c7910, 0x100a467,
|
|
0x1c9a56f, 0x1e512c4, 0x0ef6392, 0x1ad46b2, 0x020f42e, 0x1f978a5,
|
|
0x122441c, 0x1f2f786, 0x1149845, 0x0bb5f9d, 0x0928e9f, 0x095cf82,
|
|
0x0aada18, 0x0727e5c, 0x03f744d, 0x008a894, 0x1fb5c03, 0x1df7dda,
|
|
0x04360df, 0x06f10ad, 0x14d6bcb, 0x0385e10, 0x024fa96 },
|
|
{ 0x16df7f6, 0x1ed9fb0, 0x0c981d9, 0x11f7b20, 0x043057d, 0x016aa23,
|
|
0x0aa41ba, 0x1b62e9b, 0x1689643, 0x14279a2, 0x0681808, 0x03bf991,
|
|
0x1218b19, 0x0b613e8, 0x0d1abd3, 0x0a28b75, 0x086c989, 0x12d2bfa,
|
|
0x1250be7, 0x0429d39, 0x0158c03, 0x07a0ca8, 0x09cf872, 0x15a8756,
|
|
0x1759f39, 0x0b9c675, 0x1f943b8, 0x1c3716f, 0x0d7d4e5, 0x18fe47a,
|
|
0x1cfd8d6, 0x0eaac07, 0x0ff77e3, 0x17d3047, 0x0745dd4, 0x02403ec,
|
|
0x0a6fb6e, 0x0bd01ea, 0x0045253, 0x07bf89e, 0x0371cc2 },
|
|
{ 0x090c351, 0x188aeed, 0x1018a26, 0x1e6c9b3, 0x0d196eb, 0x08598db,
|
|
0x0480bd9, 0x05eef51, 0x06f5764, 0x01460b2, 0x00049f3, 0x1c6c102,
|
|
0x1bdc4f7, 0x0e26403, 0x0db3423, 0x081e510, 0x156e002, 0x1894078,
|
|
0x072ce54, 0x14daf13, 0x00383f9, 0x099d401, 0x1029253, 0x0fa68e8,
|
|
0x17e91e8, 0x12522b4, 0x1c9b778, 0x01b2fa0, 0x00c30e7, 0x12c6bb2,
|
|
0x1181bda, 0x0b74dcd, 0x1c2c0e8, 0x009f401, 0x09ebc6f, 0x1e661ed,
|
|
0x09f4d78, 0x101727e, 0x1edfcf9, 0x1401901, 0x092b6bc },
|
|
{ 0x100822e, 0x0ae41af, 0x1c48b8f, 0x057162d, 0x0e82571, 0x1851980,
|
|
0x0a7124a, 0x0a90386, 0x1a7cc19, 0x1a71956, 0x0504fda, 0x19dc376,
|
|
0x070bee9, 0x0549651, 0x1edeea9, 0x122a7db, 0x0faea3b, 0x0e6a395,
|
|
0x03c303e, 0x013cfc0, 0x1b70e8f, 0x192e6f5, 0x0938761, 0x136c76d,
|
|
0x1ae084a, 0x1b2ff15, 0x00ff563, 0x0802837, 0x162759f, 0x0f6d51d,
|
|
0x0235fb1, 0x0f21c61, 0x0af6e67, 0x1bf18cd, 0x00c07c9, 0x1842b5b,
|
|
0x0f33871, 0x0da5cc6, 0x1e2779f, 0x1929e05, 0x071ff62 },
|
|
{ 0x04a84d9, 0x0388115, 0x079aa93, 0x1abd78e, 0x02ee4ac, 0x06b2bc7,
|
|
0x0a297c7, 0x14a7623, 0x1fff120, 0x1faf7cf, 0x1940ce0, 0x11c213c,
|
|
0x00a4c59, 0x050220c, 0x1a7e643, 0x05183c3, 0x146f598, 0x1c5c196,
|
|
0x0ebd4da, 0x1e51406, 0x168a753, 0x18db6a7, 0x04bb712, 0x199a3e1,
|
|
0x0692a72, 0x01976ef, 0x1748899, 0x07541ef, 0x12661cd, 0x1b1f51e,
|
|
0x168e36e, 0x1fb86fb, 0x1e19fc6, 0x1b5a678, 0x0d4213b, 0x12d8316,
|
|
0x1f1bba6, 0x141ff4e, 0x009cf9a, 0x1cebf2b, 0x040fd47 },
|
|
{ 0x07140a4, 0x05ba313, 0x0bed6e2, 0x1dd56de, 0x0dbbfc1, 0x0312a43,
|
|
0x12239a6, 0x185bb3d, 0x12eb6ef, 0x0df75d0, 0x03fe21a, 0x0295159,
|
|
0x10cfc22, 0x1ad10ca, 0x15725ba, 0x1f6d32b, 0x0054171, 0x1c99c4e,
|
|
0x0d1a0cd, 0x0ba8a43, 0x025c2d8, 0x042089a, 0x0535a28, 0x0d842e8,
|
|
0x00139ec, 0x026f296, 0x1fdcc02, 0x019e172, 0x178aa32, 0x15130fa,
|
|
0x10c6b05, 0x1f36d5c, 0x0b9fab3, 0x0534a8c, 0x0447615, 0x0cd1b04,
|
|
0x1ffbe28, 0x19a6cc6, 0x0ce302c, 0x0afcc72, 0x05b1c11 },
|
|
{ 0x0b6bb8f, 0x0d558b9, 0x0b0a43b, 0x0405f92, 0x0dc64ed, 0x14a639c,
|
|
0x08f17f9, 0x1c9e857, 0x1cb54dc, 0x0b6e32f, 0x108370c, 0x0d46c64,
|
|
0x14cb2d6, 0x02b6e7c, 0x19c1b9c, 0x0593a2d, 0x164a4f3, 0x01404e3,
|
|
0x09bb72a, 0x11b061d, 0x1f57ab1, 0x1340e32, 0x13f46b3, 0x1425820,
|
|
0x1651c7d, 0x1240fc8, 0x1b1de46, 0x15877ac, 0x1e67a30, 0x0e7a3c2,
|
|
0x046dab4, 0x1b41fab, 0x0d3fc44, 0x031a272, 0x0005b87, 0x079c2c9,
|
|
0x13e50ab, 0x0f4e5c1, 0x1bbd213, 0x0754ead, 0x0963ab8 },
|
|
{ 0x14ea5a3, 0x1a3ec6f, 0x17fa512, 0x0ab9fc8, 0x1656881, 0x1e1ab24,
|
|
0x1f56228, 0x02ba2dc, 0x0e7c99e, 0x072ad9f, 0x01c6f21, 0x009beaa,
|
|
0x0e3fee2, 0x0202bee, 0x001bca4, 0x0aae0e2, 0x10dbba7, 0x07f461c,
|
|
0x0c66b6b, 0x0b796c6, 0x1fd8364, 0x183e105, 0x00627a2, 0x0fb2af1,
|
|
0x109697d, 0x11dc72a, 0x06e67d3, 0x06fa264, 0x0cfb6a0, 0x1290d30,
|
|
0x168046c, 0x106e705, 0x0594aaa, 0x0ee03b3, 0x07f60f0, 0x0991372,
|
|
0x076b988, 0x015c4c8, 0x11561ae, 0x1f97c8b, 0x0443480 },
|
|
{ 0x114221a, 0x1ffda48, 0x09ebe3f, 0x1c7d0af, 0x0aec4f2, 0x12a3c3a,
|
|
0x143903e, 0x0a485c5, 0x1d6f961, 0x19f3598, 0x1a6ddfb, 0x0a6ff7f,
|
|
0x0ab2296, 0x1da1d43, 0x0a743cb, 0x0558d85, 0x0ed2457, 0x1920942,
|
|
0x1c86e9e, 0x0d122fc, 0x078da38, 0x00608bd, 0x16fbdf0, 0x02c0b59,
|
|
0x09071d3, 0x1749c0a, 0x18196a3, 0x05b5b53, 0x02be82c, 0x1c6c622,
|
|
0x16356c4, 0x1edae56, 0x16c224b, 0x01f36cd, 0x173e3ac, 0x0373a6a,
|
|
0x0170037, 0x168f585, 0x09faead, 0x1119ff5, 0x097118a },
|
|
{ 0x1ecb5d8, 0x02cd166, 0x019afe7, 0x175274d, 0x0083c81, 0x1ba7dfc,
|
|
0x1760411, 0x16849c1, 0x0a02070, 0x1bcd1e5, 0x1ede079, 0x1f761f7,
|
|
0x049d352, 0x1f7950e, 0x0c36080, 0x1ca0351, 0x17b14b3, 0x15c2c31,
|
|
0x0a20bfc, 0x0e14931, 0x0fa55ba, 0x019d837, 0x089cc02, 0x05fdc55,
|
|
0x002f410, 0x1d2d216, 0x0628088, 0x09cec53, 0x03fc72e, 0x1d1342e,
|
|
0x19f6e8a, 0x1fca5d5, 0x14fe763, 0x1a2fb2a, 0x01689c3, 0x18616a8,
|
|
0x0573387, 0x150bbd5, 0x1ea0b55, 0x11a96e3, 0x017c077 },
|
|
{ 0x135e37b, 0x0ff8e93, 0x15c839b, 0x0ccadd8, 0x09884e5, 0x1dd4bc6,
|
|
0x0b2767a, 0x18945eb, 0x0ba09f3, 0x07d228c, 0x010ddd0, 0x02efeb6,
|
|
0x0a8c3fa, 0x0b3d176, 0x0877b36, 0x17a8143, 0x0700528, 0x13b45e5,
|
|
0x01a4712, 0x092a563, 0x1fd5f22, 0x02f436a, 0x05b84b1, 0x10b34d4,
|
|
0x1915737, 0x1073d06, 0x0683ff3, 0x047e861, 0x0cc9a37, 0x1bcdd4b,
|
|
0x0e16a36, 0x035a474, 0x1d12ae0, 0x1aec236, 0x0e878af, 0x0d3ffd8,
|
|
0x0452ed6, 0x074270d, 0x1931b5b, 0x190ae3f, 0x01219d5 },
|
|
{ 0x02969eb, 0x1533f93, 0x1dcd0fa, 0x1a5e07c, 0x1a3ab39, 0x1d84849,
|
|
0x1f9455e, 0x0e9cc24, 0x18d1502, 0x1c15876, 0x02f6f43, 0x15b1cb0,
|
|
0x0bffffc, 0x14ba1f3, 0x14f41d6, 0x023aca3, 0x1b18bac, 0x00a425e,
|
|
0x0c930e2, 0x1b3321d, 0x07c695c, 0x083fd63, 0x085a987, 0x09cd70e,
|
|
0x0f762a0, 0x0642184, 0x072e95f, 0x10cbbac, 0x14a07a2, 0x1586e91,
|
|
0x1e4f0a5, 0x0740f27, 0x0f92839, 0x14f673b, 0x187c2f8, 0x04e16af,
|
|
0x1e626f4, 0x0a5417b, 0x1c8c04c, 0x165acaf, 0x02c8d7a },
|
|
{ 0x025e4d6, 0x1ac4904, 0x0d119f3, 0x0addf07, 0x1f51eaa, 0x080846e,
|
|
0x197604c, 0x07ec7cc, 0x18dd096, 0x14fc4fa, 0x190da88, 0x09bb3be,
|
|
0x078c4b1, 0x0a2f5dd, 0x16b91a7, 0x1e70333, 0x1775a4d, 0x188c555,
|
|
0x078dffa, 0x12f17a5, 0x17efda8, 0x1556516, 0x1a73b56, 0x0fad514,
|
|
0x0d05dc6, 0x11a364c, 0x15dfe12, 0x08e97e1, 0x0cd59a7, 0x059776c,
|
|
0x1ef510a, 0x1a3a731, 0x0fd1cd5, 0x10588d8, 0x0f6e528, 0x08b2c02,
|
|
0x1b404c4, 0x15b82d0, 0x165625b, 0x0ee9613, 0x02299d2 },
|
|
{ 0x04397e6, 0x06ac6e3, 0x0c796e7, 0x1d7edba, 0x0c198f1, 0x0f8ed95,
|
|
0x16384fa, 0x118b0cd, 0x18fcdc6, 0x02d7143, 0x1007f50, 0x019bca7,
|
|
0x16a4b28, 0x008edaf, 0x058fcb5, 0x1f141b9, 0x189bec4, 0x1f6aea8,
|
|
0x05bba62, 0x1fa27b2, 0x148e336, 0x198216f, 0x1a496c6, 0x1c00e9c,
|
|
0x16291ac, 0x14a867a, 0x0094c5f, 0x11a7169, 0x1c446be, 0x0e95c10,
|
|
0x0d31eb4, 0x1e16cb2, 0x1c44135, 0x106a838, 0x0dbd4b2, 0x0d2e36e,
|
|
0x07b46c2, 0x0ffd2b9, 0x1863abe, 0x0f2326c, 0x021ac67 },
|
|
{ 0x17fbcd2, 0x1071f96, 0x1062ad0, 0x072f7bf, 0x1272247, 0x1aea5a0,
|
|
0x0cfe137, 0x1a69240, 0x03807b7, 0x1e6a11b, 0x10d895b, 0x1613667,
|
|
0x14dfc19, 0x1079140, 0x15bcdd6, 0x0337027, 0x059037c, 0x0384bc5,
|
|
0x1fc9ee7, 0x13132e1, 0x03894f3, 0x02b0ad2, 0x1f03869, 0x0c05ee9,
|
|
0x1496a3e, 0x10e7fd1, 0x06c9872, 0x07e3886, 0x0164cdc, 0x08edf70,
|
|
0x07d8488, 0x1cfef7d, 0x0463ee4, 0x170dd98, 0x19e24b0, 0x0c02bef,
|
|
0x04483a5, 0x1ec46b1, 0x1676198, 0x1ce1cc5, 0x00e8ec1 },
|
|
{ 0x00878dd, 0x06614c5, 0x1c6aa23, 0x1acc800, 0x19ac175, 0x0b9b0bc,
|
|
0x1208294, 0x02b2068, 0x0dd58a3, 0x0b6811f, 0x088684c, 0x17a911a,
|
|
0x0330785, 0x0ace247, 0x12cf79e, 0x14ee36e, 0x1824c67, 0x1a17701,
|
|
0x02e4514, 0x1ed9bbc, 0x1e9159e, 0x144d91b, 0x1e0c2b8, 0x0bb064a,
|
|
0x07a4c49, 0x13370c2, 0x1b41dcd, 0x0f6242f, 0x14a3256, 0x1643514,
|
|
0x0996064, 0x10c9b06, 0x0aa0f56, 0x09f2dbb, 0x144bd2c, 0x1bc5457,
|
|
0x1b6b73f, 0x0860e00, 0x0d8d761, 0x0beba20, 0x0653a79 },
|
|
{ 0x0dcb199, 0x144c2a8, 0x0d833f8, 0x1cff405, 0x135b8e5, 0x1b01e85,
|
|
0x15f0f25, 0x16b794f, 0x127f131, 0x0729446, 0x04b54ac, 0x09bdc56,
|
|
0x073aa70, 0x0edb92e, 0x01ac760, 0x16227c4, 0x19ac5d1, 0x1858941,
|
|
0x0d175d8, 0x12e197b, 0x1e8e14f, 0x1f59092, 0x1265fe4, 0x0fb544d,
|
|
0x1739cee, 0x074deba, 0x1c7fbc8, 0x0dd97a7, 0x0a42b14, 0x108a3e3,
|
|
0x147e652, 0x04ff61f, 0x089eb4f, 0x06d25e9, 0x14c6690, 0x0c2230d,
|
|
0x1b9d797, 0x1fb2d2f, 0x19d7820, 0x0f7a888, 0x030dfc4 },
|
|
{ 0x0aadfe8, 0x02d714f, 0x004af3f, 0x0969a9d, 0x05027e5, 0x099ab09,
|
|
0x00b7e2d, 0x029560e, 0x056a6a2, 0x15ce102, 0x041a3a8, 0x1ef460b,
|
|
0x0fb1a3d, 0x0c41888, 0x1452c86, 0x11c3946, 0x136c4b7, 0x05bdf11,
|
|
0x18bda61, 0x0e79cc7, 0x1ac6170, 0x1316efb, 0x01b8452, 0x1af8791,
|
|
0x192bf07, 0x14493b0, 0x0fac6b8, 0x1b4d3c1, 0x1849395, 0x18ba928,
|
|
0x08260eb, 0x080f475, 0x0c52a4d, 0x1f10c4d, 0x1f6ab83, 0x022a6b8,
|
|
0x197f250, 0x17f4391, 0x04b3f85, 0x03ea984, 0x0572a59 },
|
|
{ 0x1a5553a, 0x1420c84, 0x0ef1259, 0x1064ee6, 0x1f05431, 0x17eb481,
|
|
0x0d2c8fb, 0x1a9f39d, 0x1f22126, 0x09e5fcd, 0x1655e2f, 0x03805fd,
|
|
0x186d967, 0x0501836, 0x0965f3b, 0x09fcb77, 0x1613d67, 0x15b82f6,
|
|
0x1fccfdd, 0x06c456c, 0x0c31f1d, 0x0308e5c, 0x056f3cf, 0x07a3552,
|
|
0x067dce5, 0x1a1d1c2, 0x07e422a, 0x005fd25, 0x15767a9, 0x04cec68,
|
|
0x1edb8f9, 0x1215fa0, 0x142db5c, 0x18c8740, 0x1ef1b22, 0x1c2418d,
|
|
0x04919a4, 0x0432a99, 0x0b0f203, 0x1c3b190, 0x065c2cb },
|
|
{ 0x060bb63, 0x06d1053, 0x0915a13, 0x150dd0c, 0x07dc3b0, 0x10776b9,
|
|
0x0b3d9ae, 0x0b0ec8e, 0x1679dd1, 0x0e0b172, 0x14b511e, 0x04ee108,
|
|
0x1eb6884, 0x009fabc, 0x06f1acd, 0x02ee105, 0x1ec9501, 0x1c9750a,
|
|
0x1dce060, 0x09c6008, 0x12f15e3, 0x04b9f0e, 0x030f28d, 0x137a7bd,
|
|
0x0f1dc22, 0x169d2e2, 0x0e53bdf, 0x107dfe3, 0x0e7a1a7, 0x19c6efd,
|
|
0x1491b6d, 0x0341330, 0x153d72e, 0x07a55a1, 0x1562837, 0x124a675,
|
|
0x0e7888b, 0x02a80b0, 0x1fd9b60, 0x1aa774e, 0x0831440 },
|
|
{ 0x011b2da, 0x117197b, 0x1ab3d0f, 0x13a1f48, 0x1d066e2, 0x059e06a,
|
|
0x1cfa208, 0x1e1d12f, 0x01d3e44, 0x02e1473, 0x09e99b1, 0x1ecdbfa,
|
|
0x17929d7, 0x080f428, 0x16e1828, 0x0f1bae6, 0x0983de0, 0x1751fe7,
|
|
0x0e33846, 0x0efb6ac, 0x0b3bc99, 0x17a429b, 0x01220e0, 0x195bf8c,
|
|
0x07a3c64, 0x1b8bf06, 0x1e0851e, 0x19a2fef, 0x011e3e3, 0x11e60da,
|
|
0x1b7a559, 0x130bf68, 0x139ac8f, 0x08ce52b, 0x0736f3c, 0x0a70a73,
|
|
0x015a281, 0x0c2d387, 0x115992a, 0x114dabe, 0x0504c3a },
|
|
{ 0x0fa53c7, 0x0a941dc, 0x138c02d, 0x10a128e, 0x185cff3, 0x1e712fc,
|
|
0x090710d, 0x1da469a, 0x0e5a129, 0x0c19218, 0x1319d0a, 0x12ad557,
|
|
0x016ad38, 0x1f740f7, 0x1700075, 0x04e0545, 0x0b6670b, 0x1a611e3,
|
|
0x1ba28ee, 0x1cacfd4, 0x13eab35, 0x07534b3, 0x0f1c2cf, 0x1c51d59,
|
|
0x1a9c3e6, 0x1ed42d3, 0x1954ded, 0x15cd09b, 0x0937dc2, 0x01f2b6f,
|
|
0x0897b2b, 0x1f08608, 0x12ea6c9, 0x0e2905f, 0x1f41dff, 0x1a7195e,
|
|
0x09f56ad, 0x1d7858b, 0x0874b09, 0x1338e3a, 0x0496e46 },
|
|
{ 0x1a93467, 0x07e414f, 0x1852e85, 0x081d654, 0x02e3768, 0x19f04de,
|
|
0x13ebd20, 0x198cb37, 0x03686bd, 0x042cba9, 0x0c85aaf, 0x010103e,
|
|
0x1840bfd, 0x0be040d, 0x18ef698, 0x0f27788, 0x086bb04, 0x0de80fd,
|
|
0x1359031, 0x03d9cc5, 0x15c45a2, 0x0a1101e, 0x05efda9, 0x022cf6f,
|
|
0x00edc95, 0x134675a, 0x1dd96e8, 0x0cf5595, 0x0b51f9d, 0x0cf4d75,
|
|
0x0ea2e83, 0x161ad0c, 0x14b215e, 0x034a960, 0x136f97c, 0x0a6a99b,
|
|
0x0b3744b, 0x15ae67e, 0x1ffa13c, 0x0e62606, 0x0133891 },
|
|
{ 0x1003cd1, 0x0032022, 0x0b1bb9a, 0x18895c5, 0x1dac17b, 0x07298a7,
|
|
0x1067f7a, 0x0b8979a, 0x1c7cea9, 0x0f1a75c, 0x0df8060, 0x0c5a71e,
|
|
0x08bb577, 0x1304c86, 0x1133ec0, 0x094f7d9, 0x1f950a3, 0x185e249,
|
|
0x10cc13b, 0x0e82e4a, 0x0a2a680, 0x1935e45, 0x0bb03f2, 0x08bfd4b,
|
|
0x09b463b, 0x1d64f3d, 0x1957ef6, 0x17652a5, 0x05dff44, 0x0053024,
|
|
0x05943c3, 0x09bd48f, 0x0c5104d, 0x11d0101, 0x0825a57, 0x0ba59df,
|
|
0x0da1f34, 0x00815a3, 0x0fef532, 0x0e7e706, 0x0422eb5 },
|
|
{ 0x0ad3f47, 0x0975b53, 0x083ab16, 0x1b2e297, 0x10861f6, 0x140a2cd,
|
|
0x1a4641c, 0x006af83, 0x064ea58, 0x1be4a71, 0x049c8f3, 0x0d58a96,
|
|
0x0a72537, 0x0d7db9b, 0x09ae907, 0x079b9e5, 0x120cba0, 0x0e44f44,
|
|
0x0c3f4eb, 0x041968b, 0x19fef2e, 0x0a6b302, 0x09ba969, 0x13bf178,
|
|
0x1fa8b88, 0x15ff731, 0x059a8fc, 0x01e38fc, 0x1312e14, 0x1e4e3a3,
|
|
0x1fc27fa, 0x0e4f333, 0x119b9c2, 0x09582be, 0x0d32dff, 0x0d53f77,
|
|
0x00da2dc, 0x1d13ebd, 0x0960b3e, 0x19e584a, 0x0368541 },
|
|
{ 0x0799d37, 0x09e4f11, 0x0ce9443, 0x0b59f46, 0x1b677de, 0x07bcad8,
|
|
0x1863c20, 0x1849cd5, 0x0afc8df, 0x0da9e15, 0x10b709a, 0x036c1d0,
|
|
0x0879754, 0x16033ff, 0x09bcabe, 0x1b0efab, 0x003bd07, 0x1681045,
|
|
0x152f8bc, 0x08e7e0c, 0x023e34b, 0x157a8af, 0x199f040, 0x1835e91,
|
|
0x1bf9d2a, 0x0805806, 0x06da84f, 0x04c9f48, 0x094c11e, 0x1c354bf,
|
|
0x1d059a5, 0x10d4b0d, 0x1d8cf2d, 0x093f484, 0x01a71fe, 0x0c0e77f,
|
|
0x0241a56, 0x0bbc401, 0x04cd2e2, 0x0b2444c, 0x059a5bf },
|
|
{ 0x1347191, 0x0e48f40, 0x05cba74, 0x19d72d3, 0x186c1ab, 0x0a353f8,
|
|
0x01d9ea7, 0x12e0f11, 0x0daa7d3, 0x149e7e6, 0x0e6a836, 0x13e3b23,
|
|
0x0c08bee, 0x1c6e9e3, 0x19ff5e3, 0x1020104, 0x0d09422, 0x1fc9c30,
|
|
0x0b6d1fe, 0x14e355b, 0x0f8a6a6, 0x1bd30ab, 0x072a81a, 0x1091793,
|
|
0x105e039, 0x09ad50d, 0x1caaaa4, 0x0dbb846, 0x1f3bd13, 0x103cd89,
|
|
0x135df9f, 0x09598be, 0x10b5cbe, 0x07e9b46, 0x17e2613, 0x1009b48,
|
|
0x13d3e0f, 0x077b0c6, 0x1e673c5, 0x18287d6, 0x0467564 },
|
|
{ 0x0fff5d7, 0x12c825b, 0x1d4a35c, 0x1f25b88, 0x037f33a, 0x105c550,
|
|
0x155d5b4, 0x073212b, 0x143baec, 0x111afe0, 0x0ae6c0c, 0x095ed14,
|
|
0x01a2feb, 0x0a69ae3, 0x1140c62, 0x0e90cc3, 0x0a2ea87, 0x1d6495b,
|
|
0x046f1bc, 0x09162a0, 0x1cb28eb, 0x1463cf6, 0x08a3f84, 0x1a5400d,
|
|
0x1bc0ca5, 0x0284fb8, 0x08bc56e, 0x062cee6, 0x036218f, 0x19463d0,
|
|
0x07bfa35, 0x09f03c1, 0x08f39cb, 0x0286c83, 0x0059edf, 0x062ee7e,
|
|
0x0d6a1e0, 0x07bd6df, 0x0135434, 0x02c9dd3, 0x08a0dee },
|
|
{ 0x1366e6f, 0x0c8dfa3, 0x0015412, 0x1fd0d86, 0x18084d9, 0x06671b5,
|
|
0x11d4690, 0x1c42989, 0x03f1961, 0x1da3553, 0x11790ee, 0x0bf2808,
|
|
0x1f56a78, 0x048f10a, 0x0346d5f, 0x1011bb7, 0x13ec7ee, 0x0354722,
|
|
0x0ea87a3, 0x0cfdf17, 0x0109c03, 0x18f1f0c, 0x0c43647, 0x0414586,
|
|
0x0fd0e7e, 0x13bfcbe, 0x1155330, 0x03d0190, 0x028403f, 0x1e0ebdb,
|
|
0x1f3a26e, 0x07fc142, 0x178a966, 0x00039bb, 0x067f07c, 0x053d3b6,
|
|
0x16f6bed, 0x13ff3ed, 0x1388cb3, 0x1a5dd2f, 0x07b04b5 },
|
|
{ 0x0c5faf8, 0x035e3c1, 0x025d6d5, 0x1d1d702, 0x1a734c5, 0x1c28f00,
|
|
0x1a1879d, 0x03e7aac, 0x1e956d5, 0x19d0809, 0x0f0df20, 0x0e63878,
|
|
0x0cc7351, 0x1060a47, 0x1dce3ef, 0x1de82c0, 0x0bbe1bb, 0x1976378,
|
|
0x1e94615, 0x0558dd9, 0x0df00aa, 0x0bb371d, 0x01ca40b, 0x045adc6,
|
|
0x15089c6, 0x017e6a6, 0x0e9b760, 0x15c4364, 0x0863723, 0x0d2a99c,
|
|
0x08b9519, 0x151b030, 0x05119a0, 0x14bbd6c, 0x00c8de1, 0x189e29a,
|
|
0x1c7b272, 0x0d840e4, 0x18c7145, 0x1499337, 0x01c6a95 },
|
|
{ 0x0821363, 0x0a56ae1, 0x18729ac, 0x069a2fb, 0x029c182, 0x16f4244,
|
|
0x14b1332, 0x04f5deb, 0x182489e, 0x009559c, 0x07649fd, 0x0131e10,
|
|
0x1f92c9c, 0x1ae5d68, 0x01ef7d1, 0x13f62df, 0x0b81a1d, 0x17a556d,
|
|
0x1d7cedd, 0x14f2476, 0x08fe475, 0x0b6dddd, 0x067742b, 0x0e1568b,
|
|
0x161644b, 0x178c1b7, 0x04d2f66, 0x148c910, 0x1abda32, 0x11375d4,
|
|
0x1ed7244, 0x1ccac4b, 0x0ec8709, 0x0725f26, 0x0678206, 0x19a9672,
|
|
0x14f6879, 0x004e420, 0x1932697, 0x0046150, 0x072708a },
|
|
{ 0x14a466c, 0x1e058f9, 0x16e93cc, 0x18ff3a8, 0x01bae09, 0x143c2e5,
|
|
0x03fb838, 0x103ae1e, 0x0908808, 0x12638a3, 0x10f68e0, 0x1855760,
|
|
0x12e2416, 0x07637a1, 0x0f69c4f, 0x07c38e6, 0x049c979, 0x095ac83,
|
|
0x0d724d9, 0x05ab616, 0x1b2adb6, 0x111f2e0, 0x0d57adb, 0x02d6a2a,
|
|
0x0b5cebb, 0x08e67f4, 0x07dc25a, 0x1c1030d, 0x085bd59, 0x1cfdb0d,
|
|
0x1df2197, 0x1f5c207, 0x169d3cc, 0x13f4ef8, 0x11cdcd1, 0x072a4b8,
|
|
0x0369511, 0x1aae05a, 0x17485f6, 0x098e64c, 0x07491c7 },
|
|
{ 0x0d2b94d, 0x16adfc0, 0x182cc4b, 0x0774964, 0x1b8ac63, 0x110cd08,
|
|
0x1163358, 0x11d590d, 0x1aeb82c, 0x0be67b5, 0x1e73b4c, 0x13dcb3d,
|
|
0x1a2dfb2, 0x1215e6a, 0x09f6263, 0x16403b5, 0x1c85974, 0x049f14a,
|
|
0x07f16b7, 0x0eaf09b, 0x03ba69e, 0x0f80955, 0x15b11c2, 0x0ba7973,
|
|
0x09f37c8, 0x15e8fed, 0x174f752, 0x0a90fc4, 0x1ba22ee, 0x0580859,
|
|
0x0ec03f5, 0x18dd1b9, 0x1591493, 0x1433265, 0x1eaef39, 0x0d6e653,
|
|
0x08906b7, 0x14e8e13, 0x1a105a0, 0x1cae82e, 0x08bcfd3 },
|
|
{ 0x1c8c314, 0x0139a69, 0x00cc1a2, 0x02230e1, 0x15f0b2f, 0x145d0b4,
|
|
0x1df0f01, 0x10f726f, 0x0779247, 0x1b2f06c, 0x04889d4, 0x1cbc3f3,
|
|
0x0f15527, 0x13effea, 0x01a5920, 0x0c71214, 0x1f22f58, 0x0eac59e,
|
|
0x0bc83ab, 0x08d712d, 0x0257834, 0x05a83a3, 0x0275e5c, 0x0454d22,
|
|
0x0d20640, 0x1bcecf4, 0x1d9c7b0, 0x03cbf15, 0x1fe91ed, 0x128482b,
|
|
0x061bd50, 0x0a51208, 0x14dda81, 0x09956f8, 0x043876e, 0x117af00,
|
|
0x105a937, 0x0c68f24, 0x0ad24f8, 0x1ef7a6f, 0x053cadc },
|
|
{ 0x053d0ff, 0x0f6fbaf, 0x1d9c6ed, 0x1911157, 0x1886606, 0x10368ae,
|
|
0x0c3e048, 0x066c923, 0x1e22b6a, 0x180c1a2, 0x0ecc5ec, 0x129762e,
|
|
0x15aba67, 0x1ee4f2c, 0x079619d, 0x049a318, 0x0822396, 0x1a70832,
|
|
0x0957754, 0x0a5cb3b, 0x079c617, 0x15cf214, 0x0062d3a, 0x03e57da,
|
|
0x0784b49, 0x14f657b, 0x0879e50, 0x1b9b73a, 0x1262243, 0x0a42887,
|
|
0x170da50, 0x14ca1d8, 0x06f190a, 0x14bb008, 0x16bada6, 0x0cea854,
|
|
0x032d104, 0x1ebaf4e, 0x18ac5a6, 0x0c97f18, 0x0908499 },
|
|
{ 0x093c661, 0x0867b2d, 0x015ac4e, 0x093b6be, 0x1848626, 0x0d0bc40,
|
|
0x0ea7694, 0x1352552, 0x16772de, 0x1865dc7, 0x0521f06, 0x1d7af8e,
|
|
0x1e6e67f, 0x0731211, 0x0d0e0b5, 0x085f1f3, 0x10ebb5a, 0x14b7ed2,
|
|
0x022693c, 0x03666ec, 0x0516c92, 0x1dc3af6, 0x1274cb5, 0x0202496,
|
|
0x0d2cac4, 0x1bd5ec3, 0x071087e, 0x0d0c441, 0x17de33f, 0x04d5fb5,
|
|
0x1a0f865, 0x1d27924, 0x1ee18f0, 0x0266066, 0x1578237, 0x05a9db7,
|
|
0x13580d2, 0x1badf23, 0x15fa30a, 0x1f48d19, 0x03d7f6f },
|
|
{ 0x1fbd5d1, 0x194866f, 0x037fa9e, 0x0d2e067, 0x1d759da, 0x1f76e4c,
|
|
0x02c2243, 0x11cacd0, 0x142dce6, 0x034857a, 0x19360af, 0x1e57655,
|
|
0x008519d, 0x1f8cadb, 0x04919fd, 0x043e8ac, 0x02cd83c, 0x1b2cd1a,
|
|
0x159458c, 0x0e37eaa, 0x0562557, 0x1aaa45d, 0x17f1a24, 0x125e474,
|
|
0x1920394, 0x00bdaa0, 0x0e72718, 0x0cea51c, 0x1e60195, 0x076a288,
|
|
0x154fc19, 0x03a2d4a, 0x03f9eb9, 0x055f718, 0x13f4895, 0x187c318,
|
|
0x1d434e7, 0x0ca6b7f, 0x1d39902, 0x07edbbc, 0x08fb12d },
|
|
{ 0x13cb7a4, 0x1c0d114, 0x1935b18, 0x0170f6f, 0x053e09f, 0x0561f7a,
|
|
0x0a08c1e, 0x1229e42, 0x0578cae, 0x04ffd68, 0x0e9377a, 0x12d4e2d,
|
|
0x004a2b6, 0x1b7ac05, 0x1a06853, 0x0260e28, 0x17b4c2f, 0x089ac7c,
|
|
0x04cbee2, 0x12d32c5, 0x1af7878, 0x0513452, 0x0a77614, 0x0473f06,
|
|
0x11f6dfe, 0x0ced7bb, 0x193d1d2, 0x1e41fa5, 0x1ca0e95, 0x1f3bc33,
|
|
0x1b26d90, 0x06eb303, 0x1858ecd, 0x18e4bf3, 0x096466a, 0x077d28d,
|
|
0x06ff345, 0x0981d10, 0x0dec53e, 0x062eba4, 0x03fcc67 },
|
|
{ 0x121f920, 0x0f5eaef, 0x0e41427, 0x1f82803, 0x1af70e1, 0x132557f,
|
|
0x12ff656, 0x0444853, 0x12c37a1, 0x109042a, 0x0e49afc, 0x07e8fbd,
|
|
0x1c1d4c9, 0x0fd9f8e, 0x1cf9302, 0x1788c25, 0x0595b51, 0x12b042d,
|
|
0x043f6f4, 0x1ebac5e, 0x13c22a2, 0x07ef865, 0x183758b, 0x01e4a96,
|
|
0x024a36b, 0x15b8aa2, 0x1559184, 0x074b40b, 0x15249cc, 0x1867d0f,
|
|
0x022faf8, 0x0fcc543, 0x0ec6903, 0x14c9c92, 0x0eb2bd0, 0x0aebe1f,
|
|
0x13fa868, 0x09a2ee5, 0x070d350, 0x1fb8e2a, 0x0645146 },
|
|
{ 0x01924f9, 0x0319d5d, 0x1b87b3b, 0x0c00c64, 0x1ba6f13, 0x087e0bd,
|
|
0x15eb1f9, 0x000406e, 0x1ef3d8e, 0x1298c8c, 0x1169d32, 0x0d54a3b,
|
|
0x189545a, 0x098a095, 0x087563f, 0x1a000dc, 0x0057bb1, 0x180de18,
|
|
0x1b46a70, 0x1138d2d, 0x1a48f17, 0x0fcc2c7, 0x1ebcb4d, 0x12f7d0a,
|
|
0x109b981, 0x12ea1a6, 0x14a6a89, 0x1b80eea, 0x18fa801, 0x1df3e02,
|
|
0x13b2b40, 0x0a97429, 0x0d70a9f, 0x0853a49, 0x1415b01, 0x14db8f0,
|
|
0x0d005dd, 0x1e5254a, 0x07cb8a9, 0x0e557f7, 0x0448d3d },
|
|
{ 0x1b33989, 0x178a294, 0x056b715, 0x19535d0, 0x068351b, 0x03a20a4,
|
|
0x1584d2c, 0x07767e8, 0x03cd9f3, 0x0ae7215, 0x1b928e5, 0x09d8bfe,
|
|
0x1113ade, 0x1287554, 0x0ab1c56, 0x1dfbfa7, 0x0995666, 0x10630f6,
|
|
0x1a911c2, 0x145171e, 0x04c9108, 0x0272a42, 0x100bbd6, 0x1c5e66e,
|
|
0x1b162d0, 0x05e5c12, 0x1ed1bdf, 0x1b9a263, 0x12fd893, 0x1c764b7,
|
|
0x1e08205, 0x04b2518, 0x18c5d67, 0x1e22ca6, 0x0f7e658, 0x1e50b46,
|
|
0x192a309, 0x04b8bae, 0x06695c9, 0x0f396e0, 0x0768814 },
|
|
{ 0x1767eed, 0x1d08a48, 0x176ee90, 0x1b257ec, 0x1e11b9a, 0x12f10d2,
|
|
0x0b3800e, 0x02bd144, 0x12a3354, 0x1b02210, 0x1ab5898, 0x0768953,
|
|
0x05c2c56, 0x1059577, 0x1018992, 0x1c3ae97, 0x1758bf2, 0x0badc6a,
|
|
0x0228997, 0x1e1dcfa, 0x12a71cf, 0x0ed85b8, 0x05e4538, 0x030d25a,
|
|
0x125d04b, 0x00ae1ac, 0x115b33a, 0x1c4a7e9, 0x1f0e3ad, 0x120e4ff,
|
|
0x06691e4, 0x1bb57da, 0x0b9d06e, 0x1728328, 0x098167e, 0x00ce26a,
|
|
0x132ce18, 0x1b007da, 0x0189bcd, 0x038bcb5, 0x0670eb0 },
|
|
{ 0x1cdbb43, 0x1e057b9, 0x06b77dc, 0x0afe486, 0x0f08ecc, 0x0d1c22e,
|
|
0x01504a8, 0x1e322f0, 0x09224dd, 0x0d08279, 0x11fbfda, 0x071b7d5,
|
|
0x024352f, 0x1e16899, 0x0eced39, 0x168edf8, 0x030b5e4, 0x0534f4a,
|
|
0x1d691bc, 0x0646812, 0x0ece7d9, 0x0f2eb27, 0x0024e26, 0x0468bd3,
|
|
0x01250db, 0x0b5bdc1, 0x09fd2de, 0x06aa526, 0x190b1f2, 0x060aa5d,
|
|
0x158bba7, 0x12225ef, 0x1a9c8f5, 0x157190f, 0x1e6072e, 0x145a1e5,
|
|
0x0075166, 0x1f81b30, 0x1fc9edd, 0x1cec6bb, 0x0504852 },
|
|
{ 0x0f392fa, 0x19e72d1, 0x01e0bc3, 0x15d8d92, 0x126c076, 0x1d557b1,
|
|
0x17a4a12, 0x1275a03, 0x1cbe8e9, 0x00d8b69, 0x142422c, 0x18485b2,
|
|
0x1871305, 0x1c29d79, 0x1bf585c, 0x053418c, 0x00ed3c4, 0x1bb9a8a,
|
|
0x1eafc09, 0x0362543, 0x11778a3, 0x0102c59, 0x0814c00, 0x18fbd73,
|
|
0x1d9fca9, 0x09855ff, 0x0fa199f, 0x00bded3, 0x09e13fd, 0x198474d,
|
|
0x070bce9, 0x1723d5d, 0x14c9a19, 0x073621f, 0x1b9d863, 0x00a1a19,
|
|
0x1240f8b, 0x126e202, 0x03313ec, 0x0a3efd2, 0x0992fe1 },
|
|
{ 0x0f197aa, 0x06d989c, 0x1e61115, 0x1b0f0e5, 0x04ded69, 0x1854145,
|
|
0x09ec113, 0x18d2f68, 0x0a31e48, 0x010f0d7, 0x03bfb26, 0x013fbb3,
|
|
0x0ee38cb, 0x040659d, 0x0e13ea1, 0x0aae641, 0x0a84747, 0x1dd2dda,
|
|
0x1543a5a, 0x1c10159, 0x1550a9b, 0x0e77881, 0x111147a, 0x08264b9,
|
|
0x0e75fc4, 0x19eb137, 0x00e2978, 0x1dd4bd3, 0x10abd26, 0x1f5cd15,
|
|
0x0a5cc86, 0x136c105, 0x092e484, 0x1e61565, 0x1a2a64a, 0x163b902,
|
|
0x1c8eb9f, 0x0767a5c, 0x1c7804d, 0x15098b6, 0x05a68bf },
|
|
{ 0x10a2bfb, 0x19da2ff, 0x02c2d3f, 0x12aa05f, 0x1105fff, 0x0e06136,
|
|
0x162156c, 0x00829bc, 0x10d3b9d, 0x08b432d, 0x14e45fb, 0x08a604d,
|
|
0x0e2f5a2, 0x1a6d9e0, 0x08bd24f, 0x11e5cd4, 0x08ae241, 0x0a438aa,
|
|
0x026fbd8, 0x06c750a, 0x1bec6ab, 0x1d5c65d, 0x0472878, 0x023472d,
|
|
0x0dc9840, 0x0bbb8f0, 0x0835729, 0x1f305c1, 0x097bc1f, 0x1822c0c,
|
|
0x19fad02, 0x010b5ab, 0x1c24a46, 0x1bdbe25, 0x1e8298c, 0x1fa2b91,
|
|
0x1ef1628, 0x07377bd, 0x1d0e55b, 0x1f33ebd, 0x078acfd },
|
|
{ 0x0520189, 0x1bf8afc, 0x071116f, 0x018efec, 0x154202a, 0x11170dc,
|
|
0x11ae77e, 0x10e73db, 0x11f4a34, 0x16b0133, 0x13314b4, 0x1252902,
|
|
0x03cd933, 0x02f4f89, 0x1da8490, 0x16defbc, 0x0a0ae36, 0x0711837,
|
|
0x00e9638, 0x02a4317, 0x031a538, 0x1b50209, 0x0618aed, 0x0637ce3,
|
|
0x0253cbf, 0x10ff46d, 0x08df7a1, 0x1bf8a66, 0x0e48902, 0x09fb485,
|
|
0x14bc972, 0x11754dd, 0x0bcb8f0, 0x1a514b3, 0x183e422, 0x12de215,
|
|
0x1061c94, 0x1a5a465, 0x08d9a32, 0x0e7a0eb, 0x00ad92d },
|
|
{ 0x0ca548a, 0x0aff6e1, 0x06aefee, 0x01019b1, 0x0778c62, 0x1361402,
|
|
0x0552cd1, 0x0057d32, 0x1d4be89, 0x11df049, 0x1a07b7a, 0x132a27c,
|
|
0x01847b7, 0x017a00b, 0x0aa3d2c, 0x0ffd1e4, 0x14d4aeb, 0x11f7965,
|
|
0x0ebb57d, 0x18a2a36, 0x11639ad, 0x08cc618, 0x1b0733f, 0x1afb11f,
|
|
0x0c17ba3, 0x04bee15, 0x0d19084, 0x11f4c9a, 0x190bcf0, 0x005bca5,
|
|
0x1ad7afe, 0x016a153, 0x178b4ba, 0x153358d, 0x04d09e6, 0x1a349fd,
|
|
0x075b3ce, 0x1a6e578, 0x1a6ba3b, 0x140e14d, 0x095bbd8 },
|
|
{ 0x014bbd0, 0x0924af3, 0x0d8d67e, 0x0f7047c, 0x1567a88, 0x0deb53b,
|
|
0x127b3f0, 0x085c48f, 0x18e835c, 0x1fd57a3, 0x1819a8a, 0x09c155b,
|
|
0x16314ef, 0x0e0b699, 0x0aea98d, 0x1c7120e, 0x071e2f0, 0x1fd214e,
|
|
0x141f643, 0x03cba17, 0x1c04cac, 0x1528a7a, 0x1a7fcd7, 0x0aa9d82,
|
|
0x053fcc0, 0x03fc498, 0x1ca8d65, 0x163b0d6, 0x0be487a, 0x1830157,
|
|
0x0878a7e, 0x1bf739e, 0x0a10d6d, 0x0fe7ad0, 0x0167c83, 0x155a28e,
|
|
0x18867a2, 0x06e337d, 0x0a46520, 0x09f824b, 0x0375a88 },
|
|
{ 0x017f7ea, 0x05f1709, 0x16ac5e3, 0x150eb8d, 0x1a161e2, 0x0d8d2a0,
|
|
0x1fb006f, 0x195eee0, 0x0e4fd73, 0x1c43250, 0x0836199, 0x0cc9a27,
|
|
0x08baebc, 0x0469833, 0x0c97e67, 0x0b2a080, 0x1c92f1c, 0x1dc9f6c,
|
|
0x1078199, 0x06cec6a, 0x0763fdf, 0x185c8d3, 0x1f65fee, 0x0f39341,
|
|
0x069ea60, 0x0239355, 0x007aaa3, 0x0e60790, 0x063c55c, 0x0e40d7d,
|
|
0x16f7b1d, 0x09fa255, 0x1cdcde2, 0x041c500, 0x169c65a, 0x133fc1b,
|
|
0x1841537, 0x1d849d9, 0x013b19a, 0x1161197, 0x0268d81 },
|
|
{ 0x1580555, 0x171ac20, 0x00edcf6, 0x0e8e7a2, 0x0fc32e6, 0x0660d5a,
|
|
0x0404efb, 0x1bc4818, 0x0b24ee9, 0x1204cf9, 0x03819b6, 0x16b73f5,
|
|
0x0e37b0c, 0x121c6bf, 0x0b81391, 0x002816b, 0x1642b72, 0x03fbe98,
|
|
0x0e7929e, 0x1e9db66, 0x037586e, 0x169d3ec, 0x0979dfb, 0x0e0f85d,
|
|
0x1ad37bd, 0x0c4c41f, 0x083e5e4, 0x02d6c67, 0x1a208e8, 0x0145173,
|
|
0x1ab8930, 0x0886aa2, 0x171fe3c, 0x195fa88, 0x0ccd3d7, 0x0c7d727,
|
|
0x01b53a5, 0x0cf6a58, 0x0912e10, 0x0b80ad9, 0x08b0273 },
|
|
{ 0x1019195, 0x1da3270, 0x0306e26, 0x0de7f85, 0x1de4c02, 0x1e1d908,
|
|
0x039b8af, 0x05f5824, 0x091bdf9, 0x038de2d, 0x056f27b, 0x15681b3,
|
|
0x1e485d7, 0x13248ff, 0x119da3b, 0x1c4cb2f, 0x119afbc, 0x16caa96,
|
|
0x186ddb0, 0x0d8ffd1, 0x0d1bbae, 0x00ebf1d, 0x059f60a, 0x1312e68,
|
|
0x09af95e, 0x0c11f0a, 0x1228320, 0x03e0049, 0x006c0dd, 0x1fede18,
|
|
0x133d5c7, 0x0b0ee7a, 0x12ecf7e, 0x0a06c59, 0x1e0bf4d, 0x04b0454,
|
|
0x0436504, 0x1a2e1f8, 0x017f96a, 0x140969b, 0x0400e3a },
|
|
{ 0x046e4a2, 0x10b24af, 0x01d11cc, 0x084826c, 0x17a2ed6, 0x0763be9,
|
|
0x08ec718, 0x05ccb24, 0x1e5e0ac, 0x109d561, 0x01eadd7, 0x08378a2,
|
|
0x1bda17c, 0x19e129e, 0x0c8bb25, 0x0452ccb, 0x1b8a501, 0x1ff9c33,
|
|
0x1886a66, 0x0cc1aa0, 0x03f5fed, 0x03644fe, 0x08f0a14, 0x0c8a34f,
|
|
0x150b9f1, 0x0379f69, 0x099f2d6, 0x0f87c06, 0x1185b12, 0x03bccb3,
|
|
0x06f201f, 0x0942601, 0x1c157d4, 0x18fa684, 0x191eb6b, 0x106c5ee,
|
|
0x13a6a19, 0x015cd67, 0x180e529, 0x1451b4d, 0x0131c3d },
|
|
{ 0x1da83ba, 0x02ff8d3, 0x10d929e, 0x0ba09e8, 0x1415b42, 0x01fc097,
|
|
0x066f7b0, 0x144f811, 0x080f5f4, 0x0c6a08d, 0x0946e71, 0x0c21fb4,
|
|
0x123d32d, 0x069d979, 0x0ed1413, 0x0107933, 0x04bf4c2, 0x08cc622,
|
|
0x0c3a0ff, 0x04c35ee, 0x1b9060c, 0x0fe5816, 0x0183293, 0x1e3cf90,
|
|
0x1838b9d, 0x06487fb, 0x1f131a4, 0x16f39f2, 0x15f1546, 0x0a6baeb,
|
|
0x1fc4c54, 0x03961d1, 0x1c074f1, 0x0bb0ad3, 0x0b06cb0, 0x0172415,
|
|
0x04aa0ff, 0x004c56a, 0x173a77a, 0x0d468a8, 0x071d1a4 },
|
|
{ 0x01b382e, 0x1c7bb7d, 0x0835d85, 0x06ee5bb, 0x00d8ecc, 0x0a68985,
|
|
0x0acab17, 0x05954b5, 0x08d7262, 0x1e9c5d2, 0x0fb4189, 0x1b6d947,
|
|
0x0fc5410, 0x1c9e766, 0x0de9621, 0x1c7afec, 0x0fd6e65, 0x08fb2ed,
|
|
0x0291590, 0x08950ac, 0x140bc3b, 0x1427bc2, 0x03d1ece, 0x09ac1ec,
|
|
0x1dadd5e, 0x16ac127, 0x105f4ed, 0x1199f21, 0x1fc13ad, 0x15ef992,
|
|
0x0e4023a, 0x06c91f5, 0x090d716, 0x096a59f, 0x1ce8931, 0x1672c9f,
|
|
0x133d0ac, 0x0e620b2, 0x1d486e5, 0x13e22cf, 0x06cd269 },
|
|
{ 0x0f4f3ac, 0x0059d89, 0x17ecb63, 0x0533a37, 0x103dcfe, 0x19b9935,
|
|
0x0d3e0c3, 0x104a800, 0x17c5a8c, 0x16eb449, 0x1c51088, 0x07a19b1,
|
|
0x12eb709, 0x0c2ba17, 0x09e569d, 0x1b5bb12, 0x02c087a, 0x170af94,
|
|
0x1aaded7, 0x1b8e922, 0x0bb47bb, 0x05d2c56, 0x14c3f90, 0x1758737,
|
|
0x017ebe2, 0x05e06f2, 0x1b18681, 0x1696334, 0x1355694, 0x01a6f93,
|
|
0x1be4ce3, 0x0615632, 0x0f03742, 0x064b2f4, 0x12e1b22, 0x0df45df,
|
|
0x07eeb82, 0x17713a6, 0x1770867, 0x07fb468, 0x0327c06 },
|
|
{ 0x147cd53, 0x0cf7fad, 0x1bfaace, 0x1a32875, 0x1be9869, 0x0154335,
|
|
0x131ec50, 0x02dcc9d, 0x0b1c25a, 0x1f3e155, 0x1789c70, 0x16f2045,
|
|
0x1fc4216, 0x1b36b52, 0x037f320, 0x0666dcb, 0x09eda81, 0x068aca8,
|
|
0x0c2fedf, 0x0801e42, 0x0780370, 0x0cc9da4, 0x06f9381, 0x1e79a44,
|
|
0x1a1fe39, 0x1c38311, 0x0bbb2d3, 0x0554456, 0x07b83b7, 0x024b361,
|
|
0x0fc6bd3, 0x1b4bf4b, 0x042a94b, 0x00d793d, 0x008922c, 0x1935f75,
|
|
0x1670112, 0x15ce951, 0x1a15bad, 0x1a381be, 0x0020f19 },
|
|
{ 0x0dbba20, 0x08d4352, 0x1714dc1, 0x0db63bc, 0x1618ebc, 0x092c205,
|
|
0x0286799, 0x09b34f0, 0x1d2bccc, 0x0201816, 0x0168925, 0x047a205,
|
|
0x08e9ff0, 0x1d24313, 0x04dfb8c, 0x0228e77, 0x0f24cd6, 0x1f1bf71,
|
|
0x0f415f3, 0x177fa74, 0x0fce79f, 0x09e66ef, 0x17ee85b, 0x0462e4e,
|
|
0x058ec5b, 0x16dc8b0, 0x19c830e, 0x0ed33d7, 0x0f6bba4, 0x01c345a,
|
|
0x1c0989d, 0x1e3140e, 0x0b0092a, 0x108b02a, 0x03aeb32, 0x0133a12,
|
|
0x0c888f6, 0x0bf0ff8, 0x01513dd, 0x041600a, 0x079e727 },
|
|
{ 0x020a239, 0x1679294, 0x0c418ca, 0x1d55cd6, 0x11a3974, 0x0050efd,
|
|
0x15ae923, 0x155ac3f, 0x15a3ee7, 0x1229e1c, 0x0111b74, 0x0b41730,
|
|
0x0f54845, 0x0f0b33b, 0x0a765ef, 0x0eb433e, 0x00c7893, 0x0f92965,
|
|
0x1d0ea61, 0x035e7ce, 0x1d8de96, 0x0b3366d, 0x1c31e71, 0x18a71f2,
|
|
0x1854ecb, 0x08e0a51, 0x0a849a1, 0x11b54e7, 0x1f558c5, 0x1da2954,
|
|
0x017a6d6, 0x1f7a2bc, 0x1af7f83, 0x0c9ce9b, 0x049ce28, 0x0d4890f,
|
|
0x1511a05, 0x14595ac, 0x011b790, 0x1c6e02b, 0x0001d3c },
|
|
{ 0x145b1d7, 0x11b5cf0, 0x19935af, 0x140138a, 0x13e3938, 0x007b6df,
|
|
0x0b9f79f, 0x0725cac, 0x0c343f5, 0x0882273, 0x025ec65, 0x0571b21,
|
|
0x1ca5ab6, 0x0897bcb, 0x087dc2d, 0x051c963, 0x154750f, 0x0c8e6eb,
|
|
0x1ee0597, 0x101c5ff, 0x02b3b4c, 0x03aca68, 0x197b4e7, 0x1067db8,
|
|
0x0a49d56, 0x10c6609, 0x13cda4e, 0x0e6d297, 0x12c404e, 0x09a57e6,
|
|
0x050d330, 0x023a803, 0x11bd5fc, 0x02f2303, 0x011ff16, 0x080aeb2,
|
|
0x190b7a0, 0x1401b03, 0x11a12cc, 0x1f8815f, 0x04bb8c6 },
|
|
{ 0x10f8796, 0x0716efe, 0x0778c48, 0x1b62679, 0x0968a40, 0x1b4e373,
|
|
0x19b02a4, 0x077fd46, 0x0600727, 0x1f2db6b, 0x0050e4d, 0x19e1197,
|
|
0x0539e4e, 0x0ff5e00, 0x1ffa736, 0x16a7890, 0x0440199, 0x1f5c57a,
|
|
0x04d467a, 0x049c765, 0x1c162f1, 0x0564164, 0x0183086, 0x13b8b21,
|
|
0x1d6f270, 0x094d668, 0x14db541, 0x0d2daa8, 0x120bfc5, 0x0efcac8,
|
|
0x04300fd, 0x021ff4d, 0x1a3e88d, 0x19413cc, 0x1e95b10, 0x13a9f39,
|
|
0x1a135d8, 0x07f54f4, 0x1f9e0ba, 0x1036d4e, 0x03699a8 },
|
|
{ 0x0b1c64d, 0x119b90f, 0x05516f2, 0x1be3a50, 0x09cf3a2, 0x1b8837f,
|
|
0x1a6cd94, 0x09b6fc5, 0x14f7cbf, 0x160b8a8, 0x02cdfc1, 0x02dc40b,
|
|
0x05cbde4, 0x041a74e, 0x114e9fa, 0x074eb05, 0x1e2e9ac, 0x14a6def,
|
|
0x1799f00, 0x1d8d978, 0x080d795, 0x0f8a135, 0x0308f09, 0x11a9f3f,
|
|
0x0d20d6a, 0x11af716, 0x134edf0, 0x071b54a, 0x1a4d528, 0x07601eb,
|
|
0x1cee782, 0x0f03968, 0x09475e9, 0x18e5565, 0x0e797b0, 0x0ee4e3e,
|
|
0x0253518, 0x18474fc, 0x1fe2c77, 0x0064115, 0x04f3a4b },
|
|
{ 0x0d095f8, 0x1c0838f, 0x15383de, 0x0db444d, 0x03e37fa, 0x19b68e9,
|
|
0x0614abe, 0x023161f, 0x007d8e3, 0x08a31a7, 0x03c5bac, 0x152fc7c,
|
|
0x17b9634, 0x010f761, 0x152ee71, 0x0438248, 0x1dbd72b, 0x05a766a,
|
|
0x17c835f, 0x0070d0d, 0x00a2f96, 0x1eefc37, 0x07d4d67, 0x1891155,
|
|
0x154fa5a, 0x0fa621e, 0x0f44127, 0x0dae295, 0x00607a5, 0x159f581,
|
|
0x1784c54, 0x0f40464, 0x1be1c18, 0x1426da4, 0x1d294ab, 0x0089e49,
|
|
0x0b5a7b8, 0x092e018, 0x1e7f679, 0x08d4da2, 0x06d8744 },
|
|
{ 0x09a42f5, 0x083d55f, 0x13234a7, 0x186f039, 0x1fd5316, 0x034f508,
|
|
0x169b677, 0x034e34e, 0x188fee9, 0x10cf06f, 0x113c493, 0x09b9f1a,
|
|
0x0499c2b, 0x18d74a7, 0x1db7e48, 0x199840b, 0x076cf28, 0x193fdd4,
|
|
0x15fdf3a, 0x141e03e, 0x1b746e1, 0x1a79fe9, 0x180fc7c, 0x183a427,
|
|
0x1c4a742, 0x0c05076, 0x01f7ae1, 0x195584e, 0x0848bc5, 0x1c8fd78,
|
|
0x0743d75, 0x00f58eb, 0x1f514ad, 0x1e2988b, 0x1cd2413, 0x1b2b472,
|
|
0x1bb70f3, 0x125654b, 0x1582656, 0x193ff38, 0x03cf384 },
|
|
{ 0x01fc9e3, 0x0835d67, 0x0e65c01, 0x04ced60, 0x0972174, 0x15fbd9a,
|
|
0x06e379c, 0x1ee5694, 0x079b209, 0x1430154, 0x1aa3872, 0x17219c4,
|
|
0x1a90580, 0x1f1279c, 0x1cce6df, 0x0c5c23d, 0x1916293, 0x05b62ec,
|
|
0x1dec93d, 0x0e9c34a, 0x11e9511, 0x1a82f22, 0x1ce03f2, 0x106437b,
|
|
0x17afb14, 0x0957a6c, 0x0dd1f97, 0x13300d7, 0x19a6080, 0x0eb2df4,
|
|
0x0821549, 0x1a8abd0, 0x04828d9, 0x1053293, 0x1017615, 0x011918a,
|
|
0x1103077, 0x13f39e3, 0x17c98f1, 0x0a1dce7, 0x02b2488 },
|
|
{ 0x141159f, 0x1e6f342, 0x02c885c, 0x109f682, 0x18224c1, 0x1650e3b,
|
|
0x018647c, 0x0800f45, 0x0a8b23e, 0x16103eb, 0x08d1294, 0x04214d6,
|
|
0x05071a0, 0x1af694a, 0x03961f2, 0x198d9b6, 0x0ef810f, 0x0b62b5c,
|
|
0x0b610ee, 0x118b1ec, 0x0975124, 0x1eba633, 0x12e40d8, 0x0d8cdec,
|
|
0x0f7f2e6, 0x05f31a4, 0x07049af, 0x05f3a88, 0x0e49e8b, 0x1951b9e,
|
|
0x1c2b01f, 0x1d0361b, 0x0486758, 0x110e8a9, 0x1534751, 0x1942116,
|
|
0x14414a1, 0x130f673, 0x108545c, 0x198d475, 0x0938b3b },
|
|
{ 0x0ded340, 0x050b5f2, 0x00daa79, 0x1501d10, 0x0e65fb2, 0x0b9d65c,
|
|
0x0581b73, 0x1532e11, 0x0aaa657, 0x01d021a, 0x006c187, 0x18b0922,
|
|
0x0cf304f, 0x0d05db2, 0x03ed86b, 0x05bebcc, 0x0ecf554, 0x1c0c615,
|
|
0x1bddb57, 0x040aeca, 0x1d97740, 0x0849299, 0x0d59ade, 0x1add6bf,
|
|
0x055e574, 0x05bd723, 0x16956d1, 0x01ef436, 0x147ea56, 0x0bcdc9b,
|
|
0x159e5c0, 0x1e5b59c, 0x0e7e0e8, 0x01e0345, 0x181e13a, 0x03308e8,
|
|
0x1530734, 0x1464f68, 0x075ac93, 0x14bb3d1, 0x06cff58 },
|
|
{ 0x1e51f68, 0x000d801, 0x1f59423, 0x0a3a5fc, 0x01d1f22, 0x1ec402f,
|
|
0x0342c26, 0x16fef33, 0x003e415, 0x0af483d, 0x165e609, 0x0cfac0f,
|
|
0x16d1484, 0x0da29c4, 0x170ec7a, 0x0a1e80a, 0x013809f, 0x01a8008,
|
|
0x008cff7, 0x165f4da, 0x00b8fbb, 0x057f8c1, 0x02da02c, 0x1a62fc0,
|
|
0x004dc38, 0x1efd8ea, 0x1333231, 0x067aa88, 0x013f841, 0x03f3376,
|
|
0x121fea1, 0x008dc5c, 0x13f83d8, 0x1d9d661, 0x1f15218, 0x0e78c4f,
|
|
0x0b936af, 0x13fc557, 0x04c9d7d, 0x11e636f, 0x05fe4ac },
|
|
{ 0x16f401e, 0x1525fc5, 0x1b51606, 0x075ab8f, 0x05db12a, 0x183da50,
|
|
0x01c99be, 0x1a8f603, 0x09c22bc, 0x0e88f82, 0x1c7257f, 0x0fa8d26,
|
|
0x0f5454a, 0x0cd2375, 0x1b157ee, 0x12da00c, 0x07c7fef, 0x00c31be,
|
|
0x0e0fa57, 0x183a68d, 0x02dcbaf, 0x09805da, 0x1570e16, 0x1cfce24,
|
|
0x1ec2b34, 0x1746ec6, 0x02c6133, 0x13939f6, 0x0278646, 0x062124d,
|
|
0x19e3730, 0x04021e5, 0x10d95f2, 0x1d21014, 0x1325a5d, 0x1b0dc4a,
|
|
0x0b2abda, 0x098e44f, 0x0152082, 0x0c82438, 0x0813771 },
|
|
{ 0x05a8edf, 0x1592f4e, 0x1eb5899, 0x0420f14, 0x0e1388c, 0x1b776fb,
|
|
0x1cdf521, 0x02ebe04, 0x1627446, 0x017d3fc, 0x14e0a89, 0x17b3670,
|
|
0x0f3e2cf, 0x017b8df, 0x16b5ec4, 0x0152575, 0x0fa677d, 0x02b155e,
|
|
0x07f7fcd, 0x1d7a2ea, 0x0c78573, 0x093e128, 0x15fd961, 0x0f9512d,
|
|
0x116eec4, 0x04f7067, 0x019d88b, 0x199af36, 0x12c0758, 0x0c417c7,
|
|
0x054c7f1, 0x14c010a, 0x032b37e, 0x062dd49, 0x0d860ba, 0x1c9af76,
|
|
0x12f146f, 0x1239ae6, 0x16e62fc, 0x1dd39a5, 0x079c280 },
|
|
{ 0x0b48122, 0x04101f9, 0x123af73, 0x0d60958, 0x08c0491, 0x02442f5,
|
|
0x193727f, 0x03959e0, 0x182c100, 0x1c1c4cb, 0x178942a, 0x0e42ced,
|
|
0x007339e, 0x070d5c1, 0x0a96baa, 0x0965c2f, 0x0a06bc1, 0x0126946,
|
|
0x05ad88c, 0x18b76f0, 0x1606570, 0x0e67735, 0x1b1448d, 0x07d5c84,
|
|
0x1f89f18, 0x1a58d95, 0x1a71989, 0x1c75e78, 0x1e38bc3, 0x02135a8,
|
|
0x0ef82c1, 0x0e7c81c, 0x0dbc58e, 0x12df213, 0x15e2d6f, 0x107f3ba,
|
|
0x12c8f40, 0x0cfbc8a, 0x1fd3e7f, 0x14953c7, 0x0758073 },
|
|
{ 0x091ca22, 0x1d82bc3, 0x06d9f49, 0x0c27454, 0x1206bfd, 0x1caa09f,
|
|
0x14e16b1, 0x00fd097, 0x0755366, 0x0e8c515, 0x0389331, 0x1bcf914,
|
|
0x1d2e166, 0x1e23a6d, 0x155d430, 0x10874ad, 0x0c11366, 0x16f7a22,
|
|
0x1d2e10c, 0x08dca79, 0x1783146, 0x1854fec, 0x12f0340, 0x0fdc406,
|
|
0x0c82429, 0x163ded2, 0x1ff5ef9, 0x1a16217, 0x07f3ff3, 0x123b046,
|
|
0x114b485, 0x169fa98, 0x0e52599, 0x0f08203, 0x1e8527a, 0x1bf7573,
|
|
0x0661d32, 0x0153fd4, 0x1aaa24d, 0x0b1f5ec, 0x03f3e34 },
|
|
{ 0x11597aa, 0x01ad7ca, 0x13ad47b, 0x1893bec, 0x1677d4a, 0x1a77fad,
|
|
0x136726f, 0x06a04ed, 0x1515a29, 0x11f6524, 0x0ee70d0, 0x0aa7fb3,
|
|
0x1c8a696, 0x16f0f84, 0x07ba77f, 0x0bf31f3, 0x156199e, 0x15c7d14,
|
|
0x14a4b0c, 0x070eb06, 0x081bb76, 0x0e7e207, 0x01cd3b7, 0x08afb2b,
|
|
0x15e9f65, 0x095ec16, 0x18c31e3, 0x11dc647, 0x033d67c, 0x172660a,
|
|
0x0bb9dec, 0x0790629, 0x0d9f807, 0x117b1ab, 0x1788a83, 0x1c883dd,
|
|
0x0c48295, 0x0f0bf6b, 0x053bc7a, 0x1886985, 0x0640d20 },
|
|
{ 0x084d513, 0x105c719, 0x14e93a6, 0x0be62a0, 0x074c354, 0x166a950,
|
|
0x1d01d16, 0x16f66dc, 0x01de50d, 0x005ee7e, 0x07f11b6, 0x0fb84a9,
|
|
0x088d9d4, 0x181f83d, 0x0dbbc4c, 0x1a98453, 0x0ca6d4a, 0x1a7230d,
|
|
0x127c6dc, 0x1c6a3bf, 0x0e65ca8, 0x06aba30, 0x02f1025, 0x065a6cf,
|
|
0x02b330f, 0x1745b18, 0x18a15d0, 0x1340e96, 0x0c29c36, 0x1588c3b,
|
|
0x1eb7f94, 0x12257a2, 0x19e4609, 0x1531cf9, 0x1598d26, 0x031dc81,
|
|
0x072e05c, 0x1448156, 0x0a05ae5, 0x15181b2, 0x00f9c1c },
|
|
{ 0x1433df3, 0x1d559b3, 0x0a307ae, 0x0e2ba6c, 0x16aa534, 0x1862e65,
|
|
0x083625f, 0x1f22746, 0x165e408, 0x1648c65, 0x1cd145c, 0x10a9aa6,
|
|
0x094b638, 0x05a6e50, 0x04e668c, 0x0264ce6, 0x1300a3b, 0x06792b3,
|
|
0x1822ce2, 0x0c1bf4c, 0x0dfd5ea, 0x183d948, 0x162b5d2, 0x0d29f36,
|
|
0x02789d7, 0x1d8c190, 0x02d98c3, 0x10b27b7, 0x1e3eaf4, 0x1fb8632,
|
|
0x1e0f6d1, 0x07ce4c7, 0x1949c91, 0x17f99b1, 0x1b1b9b9, 0x0137359,
|
|
0x098a824, 0x1ecdd38, 0x1bb14d2, 0x05e8ba6, 0x07e31c1 },
|
|
{ 0x1fd2dd7, 0x00eb406, 0x0762f8a, 0x004956c, 0x1efacb0, 0x018fcb8,
|
|
0x0017e51, 0x1797386, 0x0959cb3, 0x10646fd, 0x0ed0199, 0x18619ff,
|
|
0x0dfdd5f, 0x1cb4d08, 0x118c6f9, 0x1fa36f4, 0x09ede13, 0x119b718,
|
|
0x1251c1d, 0x077f5bf, 0x022376b, 0x0eee639, 0x1ea4649, 0x0d89dc3,
|
|
0x10d7315, 0x1a3ba0f, 0x0438acd, 0x1ec9dc8, 0x04d93c4, 0x0969f7e,
|
|
0x0ba1afa, 0x1f89f76, 0x13b7e03, 0x050dde2, 0x13d4cdf, 0x015832d,
|
|
0x1e23ba6, 0x120d183, 0x14d5d37, 0x08a64da, 0x01a219c },
|
|
{ 0x04db0bc, 0x1bf7c55, 0x058ff73, 0x0cf6d93, 0x0e23180, 0x050c979,
|
|
0x0419cf6, 0x0e384c7, 0x0ffdc77, 0x0676171, 0x103b6f0, 0x1c6b45f,
|
|
0x03997c8, 0x0166302, 0x1843b06, 0x10240f1, 0x0cb2b0c, 0x17e86f1,
|
|
0x0795fe3, 0x188afed, 0x11c34d6, 0x192da9f, 0x054f9a6, 0x1f13971,
|
|
0x0330ac4, 0x1f32115, 0x065559a, 0x05fe465, 0x1442d19, 0x0816a1b,
|
|
0x00dcf35, 0x17d4d28, 0x04ce590, 0x1833178, 0x0dfbe00, 0x06d582a,
|
|
0x16d0bf9, 0x15e7bbd, 0x064bf80, 0x1337920, 0x017aaa9 },
|
|
{ 0x055db2e, 0x0ab21c7, 0x014434f, 0x067728d, 0x035dee4, 0x042317c,
|
|
0x103956e, 0x0f83428, 0x1ea17e2, 0x17f9d9a, 0x17dea69, 0x186dbb2,
|
|
0x0f23f99, 0x1eeb396, 0x05ff766, 0x08b80e4, 0x01edd20, 0x0fa0056,
|
|
0x1fc1ac9, 0x0ab90e9, 0x09be94b, 0x1287252, 0x0291283, 0x076d026,
|
|
0x05e91b4, 0x162f449, 0x04853e5, 0x117dbbc, 0x17fa977, 0x152607c,
|
|
0x19c3d15, 0x14b7fa4, 0x08fd86b, 0x10477d1, 0x163ef9d, 0x1876965,
|
|
0x026474b, 0x0affc61, 0x0c92bef, 0x1e14be7, 0x06b282a },
|
|
{ 0x141a595, 0x0012fb1, 0x0a31e3f, 0x0d488bc, 0x191c38d, 0x0234212,
|
|
0x1b8f7ad, 0x066e57a, 0x1755478, 0x1ca3369, 0x185b10f, 0x09a6107,
|
|
0x1491141, 0x0ad3d65, 0x176519a, 0x1f6c828, 0x1098fd2, 0x08816ef,
|
|
0x0ff61ec, 0x165a5a1, 0x10882a2, 0x0e2ca2a, 0x1a7a6f9, 0x0048bbc,
|
|
0x18bf4a8, 0x187771b, 0x02c8c1a, 0x01617ad, 0x1e9f3d8, 0x02e3615,
|
|
0x115da95, 0x0900584, 0x09d167b, 0x096fda1, 0x109cad0, 0x0427cc8,
|
|
0x0e8d976, 0x127a94f, 0x1bafed9, 0x046a8e0, 0x06d4f5d },
|
|
{ 0x0ba9f88, 0x0795b00, 0x02fcd72, 0x00f76da, 0x1dc807e, 0x1c0f2df,
|
|
0x1b50ace, 0x03c1424, 0x0a7ac78, 0x1ae7367, 0x172e98c, 0x1cdfe6f,
|
|
0x073e308, 0x11e4b24, 0x0372989, 0x0869a05, 0x17e8818, 0x13975d2,
|
|
0x06de289, 0x07ab3ef, 0x0ea3a9e, 0x0e9783d, 0x14bc29f, 0x1a0bee9,
|
|
0x0467824, 0x15b707f, 0x00045b7, 0x0410a2e, 0x137580b, 0x0f492c7,
|
|
0x0ce70a9, 0x0e80e17, 0x18bd7a5, 0x1bec873, 0x01cae65, 0x08aa3f9,
|
|
0x00db81b, 0x0d49e22, 0x0d2b5bb, 0x09facba, 0x04aaf0b },
|
|
{ 0x114c7af, 0x192831a, 0x1ab66fb, 0x1b78303, 0x109e7da, 0x11f62c5,
|
|
0x0ba1e3e, 0x10bde79, 0x1173b86, 0x06dfd5a, 0x14cb776, 0x1f81243,
|
|
0x06b2490, 0x05ece23, 0x1bce1ae, 0x1b7b69d, 0x12fa061, 0x1e0e6ea,
|
|
0x16f0136, 0x1d31344, 0x063664d, 0x15c2b94, 0x01be60d, 0x1c89540,
|
|
0x1a8048b, 0x06388d2, 0x1825c06, 0x0dbdbc9, 0x011fb11, 0x02bbd96,
|
|
0x165cabb, 0x14e43d9, 0x04dade1, 0x1f9d48a, 0x09af5ba, 0x0ff338a,
|
|
0x1c2e14d, 0x0a0b2d8, 0x18cde87, 0x0730578, 0x08b2cbd },
|
|
{ 0x052e991, 0x00df945, 0x0bb0a3b, 0x0d9f3a8, 0x0ba202f, 0x1a75228,
|
|
0x144c318, 0x139060f, 0x1c5762b, 0x1e12bd9, 0x10a8b4f, 0x11a290f,
|
|
0x0abd329, 0x118ca44, 0x053c69e, 0x00da594, 0x13b06ba, 0x0e38654,
|
|
0x19017a2, 0x07e967d, 0x0ae79aa, 0x199aef7, 0x13193ba, 0x17e3a99,
|
|
0x1f57803, 0x1fee8aa, 0x151585a, 0x083d816, 0x0e33f60, 0x0073043,
|
|
0x1d48f7e, 0x1e04879, 0x19a79c8, 0x066ac1c, 0x093a1d3, 0x030d850,
|
|
0x0fc5c83, 0x0775764, 0x0d9c088, 0x008fb7c, 0x057e283 },
|
|
{ 0x1cdf666, 0x05b4c7d, 0x0749b98, 0x1317d76, 0x1dd06a9, 0x04c21b5,
|
|
0x0b6ea01, 0x11a8089, 0x0522bc8, 0x1b5fbaf, 0x08ec835, 0x1736508,
|
|
0x12655c4, 0x099cc53, 0x103d249, 0x0ec02cb, 0x0b70ca3, 0x13b6a79,
|
|
0x00c3e96, 0x11324a4, 0x0705469, 0x03db02a, 0x05acdfa, 0x1bc365f,
|
|
0x0f73153, 0x182f7cb, 0x12b553b, 0x1d97791, 0x1617b05, 0x0e85549,
|
|
0x1f7aca2, 0x0f97442, 0x0c0fbd5, 0x0516b9d, 0x0d58675, 0x07a1a79,
|
|
0x091d606, 0x1f74ea6, 0x1f69ba2, 0x06ed2df, 0x04f12e0 },
|
|
{ 0x1f1a610, 0x1d2110a, 0x0669333, 0x0a6f0ca, 0x004a5c5, 0x01c09a4,
|
|
0x09151ce, 0x054248d, 0x04b284e, 0x10ada42, 0x144c83e, 0x18ca28d,
|
|
0x1a36464, 0x1854507, 0x1aea231, 0x1009df6, 0x0e793c4, 0x13a73e7,
|
|
0x056b85a, 0x09a4597, 0x14dd8c3, 0x0ffce0e, 0x0767b62, 0x004a6e3,
|
|
0x0866d32, 0x02530d0, 0x0a6f591, 0x0b64656, 0x17bab14, 0x1496793,
|
|
0x00be223, 0x1528916, 0x1e69c6e, 0x10f65b9, 0x1aa56d4, 0x043492d,
|
|
0x1858afb, 0x1bc753a, 0x1be46a3, 0x07d624c, 0x083d233 },
|
|
{ 0x1b478d7, 0x1994433, 0x1270718, 0x02a145f, 0x01ee1ae, 0x09120dd,
|
|
0x0acc063, 0x12c0b6d, 0x0893cd6, 0x0f8f944, 0x05ea1da, 0x0cc1502,
|
|
0x17159d6, 0x18739eb, 0x0480465, 0x0be15d0, 0x10093f5, 0x12947f7,
|
|
0x01537ec, 0x0f1b71b, 0x1fbbb39, 0x1b7a2ec, 0x15ad0fb, 0x17dc72f,
|
|
0x04bfed5, 0x0d68bef, 0x05afddb, 0x003c1eb, 0x00754ca, 0x14071ea,
|
|
0x1cca2c8, 0x1f1d0dd, 0x0db6122, 0x0f2c347, 0x1abedf4, 0x17044d6,
|
|
0x0f40a55, 0x1a990a9, 0x0588518, 0x07d8b46, 0x07362f1 },
|
|
{ 0x1c0c430, 0x1593e39, 0x195de4b, 0x1f4a386, 0x0cc0a65, 0x0ca78dc,
|
|
0x13b3b48, 0x08ea14b, 0x0814b49, 0x04a2b44, 0x1eefd06, 0x103496d,
|
|
0x08bbf0a, 0x1855430, 0x1bd3d63, 0x0f2bc6e, 0x1683987, 0x0ec9b0e,
|
|
0x0ea3435, 0x0219b1c, 0x0455b65, 0x1fdb60d, 0x18f8bf6, 0x19123f2,
|
|
0x1154eae, 0x1b21648, 0x17fd5a3, 0x1d63ce2, 0x0b399e0, 0x0e6b979,
|
|
0x02f9ebe, 0x113e17e, 0x1c39bac, 0x01b4a8f, 0x164a426, 0x11e10c3,
|
|
0x1a0a20a, 0x18b7816, 0x03ab766, 0x07f4718, 0x02f1069 },
|
|
{ 0x006ded2, 0x1674886, 0x01ec1e9, 0x1e5fb21, 0x1974842, 0x1b1ad37,
|
|
0x0ff5aa7, 0x04dc8d1, 0x11ed606, 0x05b0c48, 0x1b95201, 0x113e6d3,
|
|
0x011fb2f, 0x0e4b510, 0x0f4444f, 0x0675939, 0x0fe10d6, 0x133acd6,
|
|
0x1ea98a7, 0x14cdf91, 0x028364b, 0x04a3f9c, 0x09a1ab9, 0x139b533,
|
|
0x03a05d5, 0x1b74146, 0x1023a8b, 0x18f5f62, 0x1953c87, 0x0472579,
|
|
0x13c9547, 0x13b553c, 0x153d279, 0x18ca02d, 0x0352b5b, 0x163dfed,
|
|
0x16437cd, 0x1aedeec, 0x0810c9d, 0x1c89fcf, 0x0985f83 },
|
|
{ 0x0f45294, 0x01e0b75, 0x1d46258, 0x018496a, 0x1013116, 0x0b5a96b,
|
|
0x08060e7, 0x0809822, 0x0ed9433, 0x03ce781, 0x106da1c, 0x0516e9e,
|
|
0x010c5b0, 0x0e4560f, 0x10fc1da, 0x09e1c7b, 0x0a3f8b2, 0x12d62f7,
|
|
0x0d31708, 0x0d0975c, 0x052aee6, 0x11cd5e2, 0x0949679, 0x1be8b99,
|
|
0x12cd1e9, 0x07d583e, 0x0c6910f, 0x0e03392, 0x0003b30, 0x0d54c96,
|
|
0x0b9a3f7, 0x01b1978, 0x19f179c, 0x00e5396, 0x09bc79e, 0x1377e2b,
|
|
0x10dcc79, 0x0bbceaa, 0x18bc553, 0x0801fd2, 0x00c88e5 },
|
|
{ 0x0f44357, 0x18d3574, 0x0daa13d, 0x0c74795, 0x175b4bf, 0x15e3407,
|
|
0x076796b, 0x1e46699, 0x08a753e, 0x1657842, 0x18f23b3, 0x09820eb,
|
|
0x1ae2801, 0x1ba7c69, 0x07568e3, 0x0655d77, 0x064b80e, 0x13acc42,
|
|
0x0af0de4, 0x051cdfe, 0x01977b3, 0x17f7687, 0x1aeec7e, 0x0660cb5,
|
|
0x0ac955a, 0x07433a7, 0x1e48b6f, 0x1833fb1, 0x1b907a8, 0x1742cc3,
|
|
0x15e305e, 0x0767459, 0x1f33627, 0x1bb97c4, 0x0067ea1, 0x0dd75d4,
|
|
0x1a25ced, 0x0ef24c9, 0x01c5539, 0x1715e22, 0x08e2560 },
|
|
{ 0x141aba6, 0x1ba3618, 0x1e795b4, 0x1f75659, 0x05a1079, 0x0e93e3a,
|
|
0x0a0c673, 0x01d6c70, 0x09dfd95, 0x111bb19, 0x1023fc8, 0x0b9a752,
|
|
0x181e0b1, 0x188b008, 0x0a00802, 0x1774e93, 0x15da383, 0x0938ced,
|
|
0x14411b5, 0x106814c, 0x1b1f607, 0x0f4ba91, 0x024a753, 0x0145157,
|
|
0x0345c8e, 0x0e3a020, 0x082b7c2, 0x024eb58, 0x11d6116, 0x1932919,
|
|
0x142d06a, 0x0a72394, 0x10cc77c, 0x1118a91, 0x124a3e4, 0x13117c1,
|
|
0x12fd9a2, 0x19ec95c, 0x1cb97fb, 0x0450649, 0x059005f },
|
|
{ 0x04c1c74, 0x0ba861e, 0x0de5aec, 0x01d2cdf, 0x1e73aac, 0x02cb9fd,
|
|
0x176499b, 0x16d0b4e, 0x03a8656, 0x04bfc99, 0x11b37a3, 0x0762a08,
|
|
0x1f2b704, 0x1ff9c4b, 0x0245bdc, 0x0e564a9, 0x01cb18b, 0x1489ee8,
|
|
0x0230379, 0x0ea3e29, 0x0a58d0a, 0x0a42ac6, 0x0645d5c, 0x14cc7b4,
|
|
0x1430144, 0x10c4bb8, 0x12c3821, 0x1be3215, 0x1ead9c2, 0x1e0679c,
|
|
0x0840203, 0x02e705b, 0x085ac6e, 0x1519c00, 0x0144c98, 0x1bd2f23,
|
|
0x143bae8, 0x04ac9b5, 0x17dbb91, 0x04daf07, 0x057a78e },
|
|
{ 0x0dbddd8, 0x19a37a0, 0x0eb0586, 0x0f28218, 0x0b49a92, 0x03679d9,
|
|
0x09e0c62, 0x1d718a8, 0x033b93d, 0x16f9919, 0x1d5e75c, 0x13ea81b,
|
|
0x009c8d5, 0x01077a8, 0x15e99f7, 0x10c87cb, 0x11867f0, 0x1e2359c,
|
|
0x165ab70, 0x14488b5, 0x04d0ecf, 0x0d8622a, 0x1963d62, 0x1082fae,
|
|
0x09301e0, 0x1447376, 0x0b11538, 0x194bded, 0x0f462d6, 0x0247d60,
|
|
0x0d90644, 0x011b140, 0x12407d8, 0x1adbf42, 0x0e9fdb4, 0x0f698a6,
|
|
0x0f6ada8, 0x08f2094, 0x1cba0c9, 0x18b0388, 0x01ca370 },
|
|
{ 0x001b68a, 0x0a8b8d4, 0x02ce52f, 0x19fa333, 0x1312879, 0x0b19013,
|
|
0x0aafd04, 0x1b6920b, 0x0f5b01f, 0x0ff43fa, 0x084a2ed, 0x047539b,
|
|
0x1778de5, 0x03de98f, 0x1c58687, 0x0986a17, 0x1d02390, 0x0daef67,
|
|
0x0623c4b, 0x165105c, 0x0e74224, 0x0efcced, 0x0374a00, 0x19a39a4,
|
|
0x067b508, 0x11ce56a, 0x170219f, 0x1862387, 0x0250726, 0x0b9015a,
|
|
0x00dc684, 0x05dfb20, 0x1bf464e, 0x09d81c1, 0x122876f, 0x14a7a08,
|
|
0x06265ba, 0x0da97a7, 0x0b1e4cb, 0x0989867, 0x02584b3 },
|
|
{ 0x0eec688, 0x031c495, 0x148cf2e, 0x148bf7c, 0x05e740b, 0x105afc5,
|
|
0x1c7dff5, 0x07a845c, 0x0487491, 0x0ae8c2e, 0x1f60351, 0x166df42,
|
|
0x0404c2b, 0x1602a29, 0x09c6152, 0x14cae7e, 0x045a8b9, 0x03b6e98,
|
|
0x0bb9f32, 0x0587c2c, 0x07d02e4, 0x0326fb6, 0x000999c, 0x0f96910,
|
|
0x1dd51dc, 0x1f02c93, 0x1861e25, 0x167f557, 0x15737c6, 0x0917796,
|
|
0x1fff9ab, 0x1fea353, 0x1b60269, 0x03dd557, 0x1515a60, 0x15c3906,
|
|
0x151ca49, 0x0edb7fc, 0x0c216b3, 0x0e87f35, 0x07e8113 },
|
|
{ 0x10a88b1, 0x11545c1, 0x1f86b5c, 0x119c222, 0x11918ea, 0x04da3ec,
|
|
0x142e010, 0x1a67c05, 0x16c46d1, 0x09c0969, 0x059a72d, 0x1b61cb1,
|
|
0x1e2fd09, 0x0ad866a, 0x1173418, 0x188a730, 0x15a2386, 0x1860e0a,
|
|
0x17fd0f2, 0x0e9bcbe, 0x00cdda7, 0x0c71c8e, 0x0ec1dae, 0x009e50d,
|
|
0x11eff50, 0x1ff4beb, 0x12bbb02, 0x07c168d, 0x01ad942, 0x0333995,
|
|
0x08b914e, 0x072db48, 0x00c9f81, 0x195ff7f, 0x06898f6, 0x02c6ed8,
|
|
0x1a56fa9, 0x0e3c8c5, 0x0169800, 0x0c9bf09, 0x0436b8c },
|
|
{ 0x0b764bc, 0x0bf4ec5, 0x1e12204, 0x0940efb, 0x1fa61e9, 0x0c775ee,
|
|
0x1974c30, 0x1b8b4ee, 0x1fc9451, 0x0448b57, 0x08d1e95, 0x1c660e3,
|
|
0x1f01a52, 0x191da0e, 0x0ee577a, 0x1850cc6, 0x0c943c8, 0x06ebeb4,
|
|
0x0365c1a, 0x13a83c3, 0x199de4f, 0x0846493, 0x1e6422e, 0x0e72946,
|
|
0x0148ed4, 0x09ff30a, 0x1f35479, 0x0a030a2, 0x03dcb6e, 0x03af012,
|
|
0x0154180, 0x02f2a88, 0x1dcde62, 0x0d2fff2, 0x03854df, 0x0cdef92,
|
|
0x0768cb6, 0x1bd5720, 0x0578477, 0x13cdb7d, 0x05266ca },
|
|
{ 0x186b3db, 0x0f73689, 0x1502137, 0x14f871c, 0x19e4af5, 0x027a4ef,
|
|
0x01103ac, 0x1fb6683, 0x0fde5a4, 0x09c50f4, 0x15f3f08, 0x1248604,
|
|
0x013e6e6, 0x0cfeb86, 0x0671b8c, 0x03fe06a, 0x17486c3, 0x0479a70,
|
|
0x103387a, 0x0531fb2, 0x0d7cf1e, 0x0e8a4b0, 0x1bee32c, 0x05e77fe,
|
|
0x013472b, 0x07f903e, 0x1051bbe, 0x1334416, 0x13e2208, 0x1b15bde,
|
|
0x09df7b0, 0x0c4d7d4, 0x175044e, 0x065b3d4, 0x11253ed, 0x141e656,
|
|
0x1fc6703, 0x1d04900, 0x128af05, 0x17339b0, 0x041f325 },
|
|
{ 0x02843a4, 0x16a89e7, 0x0bf0c4b, 0x1c00e51, 0x0748498, 0x032672f,
|
|
0x0a08936, 0x07751de, 0x0a62008, 0x0032382, 0x14ce34d, 0x03b297d,
|
|
0x185905e, 0x031f3d9, 0x15e32d4, 0x0f77254, 0x196289e, 0x0cc13b6,
|
|
0x05edcd0, 0x05b88fe, 0x0944dfe, 0x0f8ed64, 0x1648d48, 0x080154e,
|
|
0x0d28d23, 0x1219edb, 0x1a9d86e, 0x0c8ee0b, 0x1d07ddc, 0x1d36cdf,
|
|
0x1f6251e, 0x0485951, 0x0f2e3ac, 0x01a3400, 0x19c3ae3, 0x1a93de8,
|
|
0x19aa18f, 0x19e9bde, 0x1aa79f6, 0x16dcb19, 0x056b30f },
|
|
{ 0x180a428, 0x06e5566, 0x02441fb, 0x190e659, 0x1af922d, 0x0d220fb,
|
|
0x01e60eb, 0x11441b1, 0x0924b00, 0x1f6cd22, 0x0070e8e, 0x067965d,
|
|
0x1321235, 0x12fc03e, 0x13901d5, 0x15d9786, 0x1a51f2f, 0x085fd77,
|
|
0x17a2a23, 0x0c694b5, 0x0a9178b, 0x1c4a1c9, 0x11382df, 0x17639b1,
|
|
0x0237790, 0x0571849, 0x0be1c81, 0x1d5369f, 0x13cd83d, 0x00fac2e,
|
|
0x1e4fb7e, 0x18ca474, 0x0f88c51, 0x06cb4ac, 0x0e2c5f0, 0x0fc8e5f,
|
|
0x1ccf7f0, 0x0840f2e, 0x1451a26, 0x0aeb17b, 0x01353cc },
|
|
{ 0x1bf6e18, 0x0b24b9c, 0x071ca29, 0x04c9371, 0x19e8b5a, 0x145c73a,
|
|
0x0d28373, 0x0191b28, 0x1204704, 0x09adfa8, 0x0e3a0b6, 0x02c8d4f,
|
|
0x142ab3a, 0x13fc094, 0x160fb58, 0x0e52fe2, 0x1e072d6, 0x1c20b53,
|
|
0x14e790a, 0x10bb0d9, 0x1bad496, 0x03cac6e, 0x029e5ff, 0x0b9cdbd,
|
|
0x0f92815, 0x11ad2ac, 0x03e28d8, 0x0be9cae, 0x077ae57, 0x07e0294,
|
|
0x0f6f1a7, 0x14d62dd, 0x14193a9, 0x060f8c7, 0x10f2ec7, 0x131a3be,
|
|
0x1a21e78, 0x1d41872, 0x17d61c8, 0x0bbe8a3, 0x03ec218 },
|
|
{ 0x10bc2d7, 0x063eb8f, 0x104ae75, 0x18dca3a, 0x0982c6c, 0x0fc07b3,
|
|
0x0b64e82, 0x13925c0, 0x1047ae0, 0x1ee9692, 0x0d47e6d, 0x093e6fe,
|
|
0x1e35031, 0x03bc285, 0x1527387, 0x1a590d3, 0x0cb12f0, 0x0b01215,
|
|
0x0f0a2e7, 0x1118acf, 0x0550ba1, 0x10835e0, 0x0390184, 0x0fa8653,
|
|
0x04b1f8d, 0x0f0586c, 0x1f4e254, 0x094cf5c, 0x097607b, 0x02bdc5e,
|
|
0x1cad49f, 0x0a92f54, 0x093c5f3, 0x0eb335e, 0x0330e6f, 0x06be3bd,
|
|
0x09d447a, 0x03ee2e7, 0x0af94c2, 0x16d4423, 0x089b356 },
|
|
{ 0x1dcc837, 0x0d857ef, 0x1ea7b5b, 0x1550e36, 0x0fb80ba, 0x0ea5b90,
|
|
0x0ff2470, 0x0b88275, 0x1adac9e, 0x0dab5fb, 0x195e8fd, 0x05b5170,
|
|
0x0e5664a, 0x0720eca, 0x0c13dc8, 0x06cb023, 0x1263743, 0x131f08e,
|
|
0x109b6ba, 0x051d9de, 0x0dc2ee6, 0x04e58b1, 0x0045867, 0x0c90c86,
|
|
0x1817f87, 0x0434e7a, 0x095612f, 0x03772e0, 0x1f7928e, 0x1e77805,
|
|
0x194b309, 0x1b8c1dd, 0x0f3a80e, 0x0e17ca7, 0x0afa1eb, 0x04fc240,
|
|
0x0a0d4f5, 0x178c704, 0x1449995, 0x01aaf8b, 0x039c4f1 },
|
|
{ 0x08aecd3, 0x0db4674, 0x0a76cea, 0x114a315, 0x155b091, 0x0a772a2,
|
|
0x136b52f, 0x109db83, 0x102068d, 0x0db45b3, 0x0b1cb5e, 0x01a1023,
|
|
0x187dac8, 0x140d053, 0x079b4d6, 0x0c506da, 0x1ea3bd1, 0x06420f4,
|
|
0x0531111, 0x182eeb1, 0x1202a7b, 0x12f8d50, 0x1cad8dc, 0x1a98aad,
|
|
0x1767ec7, 0x08ddf63, 0x0f51bfd, 0x102fd76, 0x17e3392, 0x1f46b9f,
|
|
0x113f796, 0x0b5da49, 0x0c6c977, 0x0bce7a2, 0x1c1edb9, 0x1817342,
|
|
0x1069fbc, 0x18b23c4, 0x0ac033f, 0x05a922a, 0x0414b54 },
|
|
{ 0x06e173b, 0x18f2c30, 0x04e8cf0, 0x1721cce, 0x1b7f4e1, 0x1d9057a,
|
|
0x0d44b7a, 0x0e084bf, 0x105120e, 0x1c4630b, 0x0f93b31, 0x0c05202,
|
|
0x173ef05, 0x00e3736, 0x074d6b2, 0x0d2153f, 0x08f9450, 0x17098f4,
|
|
0x12bc20b, 0x1f36648, 0x0ea9708, 0x160dd15, 0x0cb9359, 0x01b6539,
|
|
0x14a6e74, 0x003d78f, 0x034610c, 0x0957249, 0x156a6c7, 0x077c76a,
|
|
0x0984cce, 0x04e1a2f, 0x08e623e, 0x07adffa, 0x0bea582, 0x0a78e6c,
|
|
0x044e851, 0x0bbc3a2, 0x02ca90e, 0x0d5c017, 0x052678d },
|
|
{ 0x136aeb4, 0x18e2cef, 0x02ad77f, 0x1952578, 0x12d6653, 0x1d2fc0a,
|
|
0x1d25a49, 0x03e1c07, 0x02dfd49, 0x084ea0a, 0x07e26e1, 0x18a54ae,
|
|
0x05258c2, 0x0999a24, 0x1586012, 0x13c1257, 0x14f3f7d, 0x10d19f4,
|
|
0x106fe41, 0x0831a65, 0x095cfab, 0x072d52b, 0x1ce7124, 0x1a5afff,
|
|
0x1196ef6, 0x0548720, 0x143de52, 0x1d9a80e, 0x053b4f3, 0x1cd9698,
|
|
0x1252d63, 0x0bb32e9, 0x0ee842a, 0x17b415c, 0x1076fc8, 0x0c474b3,
|
|
0x08efcea, 0x0d630a6, 0x1bb7411, 0x0b78219, 0x07040ba },
|
|
{ 0x15a1a96, 0x127c0a8, 0x1f80b0d, 0x0630864, 0x11a6350, 0x0c9ea79,
|
|
0x199406b, 0x0e61412, 0x1273b61, 0x0bb4a78, 0x16a74a7, 0x10eda59,
|
|
0x178886d, 0x140a60b, 0x0069d08, 0x0d2d63c, 0x16b8667, 0x11a4913,
|
|
0x0c97c01, 0x09e18cb, 0x0c4a2fd, 0x0ffd94a, 0x1949cd2, 0x03a66de,
|
|
0x00d8ade, 0x10760ff, 0x039f8e1, 0x1f3447d, 0x14c31ea, 0x1b90dbb,
|
|
0x12a5f4a, 0x086caf0, 0x0c3e582, 0x07551fd, 0x1d39c3d, 0x11fe5bf,
|
|
0x1e87324, 0x140f0d7, 0x12704f4, 0x1ac17a3, 0x09043a6 },
|
|
{ 0x06c7937, 0x0d07f3b, 0x0f8c544, 0x1957787, 0x1b2ded5, 0x0444560,
|
|
0x1833380, 0x1e65582, 0x1616200, 0x143aa5e, 0x0ba81a4, 0x107a694,
|
|
0x0fb801c, 0x0e5f083, 0x15e80ea, 0x19b2915, 0x022cedf, 0x04cb584,
|
|
0x101a620, 0x068c75c, 0x1663c3c, 0x06facbf, 0x1ec4ba9, 0x19255f3,
|
|
0x1383440, 0x0aa1646, 0x193a368, 0x13790b8, 0x0e801a7, 0x0fd16da,
|
|
0x0ca55dc, 0x03c6af3, 0x1d2c138, 0x1683c3d, 0x177ffea, 0x0dc8b8e,
|
|
0x173eac4, 0x1b051e5, 0x17cd6c1, 0x0907424, 0x026362b },
|
|
{ 0x0fc3e89, 0x1469477, 0x19c4971, 0x0ed3d3d, 0x0d0ee87, 0x0f25ba9,
|
|
0x0ee1abd, 0x067160f, 0x0cb86b3, 0x1b84839, 0x14aeb36, 0x01d5fea,
|
|
0x09fd3d2, 0x0606d0f, 0x1bacac5, 0x0e28b4b, 0x08a44f9, 0x09c8fb4,
|
|
0x181b521, 0x17a6203, 0x0d4921f, 0x12df54e, 0x11793ca, 0x17e43b4,
|
|
0x0d464a7, 0x038bdb0, 0x0015355, 0x127f119, 0x00f2e91, 0x09e8df7,
|
|
0x1cd6b39, 0x1828724, 0x0c26563, 0x15af749, 0x02ca5b1, 0x15390dc,
|
|
0x09ff59b, 0x17f1188, 0x04d7914, 0x040aab9, 0x02e952b },
|
|
{ 0x15f886e, 0x035e56b, 0x1160aa1, 0x1da87bf, 0x068a5db, 0x1d8dc37,
|
|
0x116d801, 0x16a207c, 0x1355ff2, 0x0071764, 0x0fb3256, 0x1e4d44c,
|
|
0x13bc702, 0x0c0f2f1, 0x0d6ce18, 0x040ec50, 0x1ec6c12, 0x0812889,
|
|
0x1ef615b, 0x04dc74f, 0x1cb1a5c, 0x19ceb75, 0x03be0fe, 0x09a5f51,
|
|
0x053f2a4, 0x14bbd55, 0x0d4ec7e, 0x1829de6, 0x159a307, 0x05088ba,
|
|
0x183fd81, 0x16126ef, 0x1cd96b0, 0x1813995, 0x025b6cb, 0x0d4b829,
|
|
0x0b53ef0, 0x054264f, 0x0392c70, 0x02e606f, 0x01236d0 },
|
|
{ 0x084373b, 0x00e47e0, 0x1ebb5d2, 0x10c8c12, 0x09ae476, 0x1de1a59,
|
|
0x17e8184, 0x1602601, 0x0934bc2, 0x18938a6, 0x0f9f88d, 0x0c521c5,
|
|
0x0086524, 0x1680840, 0x13eee7f, 0x08aecaa, 0x1384231, 0x1787605,
|
|
0x0c28ca0, 0x15eb286, 0x181765b, 0x1438377, 0x0ef7786, 0x0ea61d2,
|
|
0x0727dba, 0x0e5be96, 0x19d3325, 0x1618bac, 0x18906db, 0x09b2921,
|
|
0x1cecff3, 0x1a28cb1, 0x1881941, 0x1f8748c, 0x1555b25, 0x15cc2de,
|
|
0x0b9ec7e, 0x1e16c2a, 0x0d5b8d4, 0x028c419, 0x002a480 },
|
|
{ 0x06ccd38, 0x1691ea8, 0x0a98475, 0x0920b37, 0x029a1c5, 0x0808e29,
|
|
0x0709da7, 0x0fae2f9, 0x0d82893, 0x03f0da3, 0x0d420fa, 0x1777070,
|
|
0x18f5d63, 0x156d612, 0x09ed09e, 0x09a3fe1, 0x0bd9f15, 0x0ccd593,
|
|
0x1b2557f, 0x01ff7f1, 0x1880dec, 0x13a4fe5, 0x1ba55f1, 0x00229bd,
|
|
0x15dee1e, 0x163991c, 0x1cda7d1, 0x1254c96, 0x0b25991, 0x033048f,
|
|
0x1690c11, 0x145d187, 0x02da887, 0x0b68c5f, 0x10970d5, 0x07489c5,
|
|
0x155f75f, 0x1c820a5, 0x1ff80c4, 0x0df1e42, 0x01d8bde },
|
|
{ 0x0028924, 0x09cfc51, 0x0e7c0f3, 0x1960dd9, 0x0e54f19, 0x182c233,
|
|
0x0f2df5b, 0x0ed0c57, 0x05a0607, 0x1f0338b, 0x1fb0436, 0x12f5621,
|
|
0x1c9397c, 0x178ddb2, 0x084e099, 0x17471e8, 0x0cba672, 0x120a6f6,
|
|
0x022c179, 0x1a9a87f, 0x14d1594, 0x1d564a6, 0x1e64fd5, 0x162ec70,
|
|
0x02a6abf, 0x0ad3a7e, 0x0edbf19, 0x1032d6b, 0x0d2139d, 0x0e42774,
|
|
0x09b70dd, 0x06c1a74, 0x1b00a02, 0x09dc3dc, 0x0d737ae, 0x1d66dda,
|
|
0x0c83209, 0x12d945e, 0x04f07d5, 0x0878c20, 0x0349c69 },
|
|
{ 0x1e6c88a, 0x1ca2226, 0x01fb46c, 0x028e004, 0x15c2c47, 0x015bc06,
|
|
0x1628887, 0x07d6de8, 0x0085099, 0x04fbab2, 0x1c3061d, 0x0af375d,
|
|
0x10400ba, 0x19be387, 0x1d0a4e1, 0x0fd7e5a, 0x0ec2146, 0x1e2d471,
|
|
0x0cdfd14, 0x14ccdca, 0x150a243, 0x03f685e, 0x12647c7, 0x17a3f23,
|
|
0x13e90f4, 0x14d9d3f, 0x097c384, 0x0c113d1, 0x1896359, 0x10bb839,
|
|
0x127434e, 0x04e3055, 0x0f842d5, 0x1e2e14e, 0x0a64205, 0x124232a,
|
|
0x0725576, 0x17993f4, 0x163ea8c, 0x1571385, 0x0056587 },
|
|
{ 0x0e4733d, 0x0b1768e, 0x1110021, 0x1731ca2, 0x1faff7c, 0x15a35ca,
|
|
0x0087ea6, 0x026be06, 0x0b61a8c, 0x0a4a62f, 0x0d65da2, 0x006c6d6,
|
|
0x1657c95, 0x1561697, 0x1a1323c, 0x0e07cd7, 0x0d89bd2, 0x1872d9a,
|
|
0x1a1caae, 0x1b231ef, 0x0ee1c4a, 0x0fe2029, 0x10aa27a, 0x1216a3d,
|
|
0x0ee3f31, 0x0a7e165, 0x1dbffc9, 0x11fa286, 0x1e09725, 0x06b4441,
|
|
0x0e1bcf0, 0x01f62a8, 0x1d0a0e9, 0x1570031, 0x192fdb2, 0x198870e,
|
|
0x1f1d0f6, 0x0f8ab29, 0x16f7a05, 0x1db70d9, 0x01b87f2 },
|
|
{ 0x10b15b1, 0x095dd95, 0x1de4d5e, 0x0f9cd74, 0x03e4b5a, 0x079bbcd,
|
|
0x1ff6776, 0x1dff759, 0x1c298d1, 0x02a285e, 0x00c7180, 0x0aad88e,
|
|
0x060e3f5, 0x0aeb403, 0x1c3c1ea, 0x0a5840e, 0x0e02d10, 0x0671f42,
|
|
0x0aa3315, 0x00f23cf, 0x03a3b05, 0x19dd191, 0x1358879, 0x0c65320,
|
|
0x1b94d39, 0x0b6c3dc, 0x1dfae01, 0x1bf3968, 0x1ca0cc8, 0x06f476f,
|
|
0x12b890c, 0x12e2541, 0x14bf416, 0x0454c9b, 0x11de221, 0x1d7c7e7,
|
|
0x04a3e59, 0x15c3d8e, 0x0f08ec8, 0x1887d2b, 0x08e0227 },
|
|
{ 0x010964d, 0x1115419, 0x1bac003, 0x0bfe0ad, 0x1ccd5df, 0x18f56be,
|
|
0x0e87f6b, 0x1c6042e, 0x067cdca, 0x01419f0, 0x1324334, 0x099717b,
|
|
0x151cc57, 0x19125a7, 0x1b29c50, 0x105310d, 0x03abb3f, 0x1e80730,
|
|
0x106a37a, 0x1d9c361, 0x061db98, 0x121bc61, 0x08a291b, 0x02cbcba,
|
|
0x1dd0da6, 0x071637c, 0x052dfbc, 0x075c713, 0x09f306b, 0x0b59ded,
|
|
0x16ce8f0, 0x0714109, 0x09a26d3, 0x074a82f, 0x064d4e5, 0x18a51cb,
|
|
0x0ea206b, 0x076588a, 0x175ba12, 0x16a80a8, 0x014b15a },
|
|
{ 0x04c59a2, 0x0c364b3, 0x0a943db, 0x02c1faf, 0x1dfe2be, 0x1965c71,
|
|
0x0d5a641, 0x1c067f3, 0x18176a7, 0x19192ec, 0x1c202d7, 0x09ce8b0,
|
|
0x0579a0d, 0x06aea70, 0x1b837bc, 0x051c349, 0x1fac87b, 0x16056cf,
|
|
0x1c26d3b, 0x031a5e7, 0x1d87d6f, 0x1394974, 0x13225ab, 0x128ec79,
|
|
0x0953d60, 0x0fd6544, 0x0063efe, 0x17dd2f5, 0x03d701d, 0x1074a5b,
|
|
0x0bf7c83, 0x08fd4e4, 0x1ba6e30, 0x1ab8fe5, 0x072984a, 0x0b9cafc,
|
|
0x009a55f, 0x0b563b0, 0x078b878, 0x1b18871, 0x0742bbe },
|
|
{ 0x1dc2c73, 0x1436e60, 0x0afc8fa, 0x1782c87, 0x0bbbfd5, 0x0c650fa,
|
|
0x1e87c93, 0x18e0ff1, 0x08cb5ca, 0x1345370, 0x19a9f77, 0x0c96a9c,
|
|
0x187d54c, 0x14dbd6b, 0x076e88a, 0x15728f1, 0x140e364, 0x0a6c46a,
|
|
0x1dcb804, 0x05c05a3, 0x0278c8c, 0x0ba3715, 0x1320981, 0x030f8fa,
|
|
0x15bb34b, 0x064f361, 0x1bae3f8, 0x1b167bf, 0x11e415e, 0x1a743e8,
|
|
0x1e6daf0, 0x170cb8f, 0x1908bbf, 0x060be59, 0x139b87b, 0x16e2fa3,
|
|
0x17cdd69, 0x0f19847, 0x1049054, 0x0296b92, 0x097bd5a },
|
|
{ 0x1e82861, 0x0317f40, 0x103b807, 0x1bba858, 0x103d4b6, 0x0f48f2b,
|
|
0x1956f99, 0x1bafca5, 0x05abbbf, 0x05a49ba, 0x0917d2e, 0x1ea58e5,
|
|
0x18b4f15, 0x0a8794e, 0x010d6a1, 0x1cebf9d, 0x19b582d, 0x14efbb5,
|
|
0x08322e5, 0x1098bf4, 0x0af452e, 0x0885450, 0x0bddf4b, 0x0c02787,
|
|
0x1bbd8ca, 0x02f81c4, 0x089be0c, 0x01b3737, 0x0c8b9ab, 0x1424067,
|
|
0x063c14f, 0x1ff57b4, 0x163367a, 0x1261526, 0x0f92990, 0x1ca1ea7,
|
|
0x064fba2, 0x0962c64, 0x151a7e2, 0x0629198, 0x0317c6d },
|
|
{ 0x0b7d42b, 0x092d816, 0x12b830d, 0x12621f5, 0x15240bc, 0x102047a,
|
|
0x0808bfc, 0x1411aba, 0x1e0c10e, 0x180a017, 0x1ac8f5a, 0x0d14e31,
|
|
0x197fbef, 0x0092950, 0x051ad69, 0x01add40, 0x048110e, 0x0acd7e7,
|
|
0x08b7860, 0x03a4fe0, 0x09dae9a, 0x0b6e1fa, 0x1b6e5b4, 0x17c8010,
|
|
0x0e3f5ef, 0x08e7e0d, 0x07b32f0, 0x13ae0c8, 0x1f8636f, 0x113ca92,
|
|
0x0c12408, 0x184ec78, 0x169796a, 0x031859b, 0x00f0764, 0x0f39869,
|
|
0x0e3d3f1, 0x0b28f87, 0x0e3f514, 0x0733b41, 0x06ae597 },
|
|
{ 0x1f4d2ee, 0x09de3df, 0x0f615ec, 0x126162e, 0x0075422, 0x0a49b61,
|
|
0x12f541e, 0x17d6c4a, 0x05efd55, 0x0af9195, 0x10ce247, 0x150a9c1,
|
|
0x04c06f4, 0x0730fca, 0x0b16d66, 0x10f6f9e, 0x01ffd5f, 0x062b243,
|
|
0x08abe93, 0x0c3f62b, 0x0774ee2, 0x1316cbd, 0x0c3fdc8, 0x19e00f5,
|
|
0x1ae22d6, 0x10a0d44, 0x134d1bc, 0x11100a6, 0x16497e2, 0x1dffcbd,
|
|
0x1f23f9c, 0x1f455ff, 0x08595b2, 0x0d39345, 0x1cfbc54, 0x173df39,
|
|
0x0744b82, 0x0772f8f, 0x1f9caa1, 0x11b78c7, 0x0664904 },
|
|
{ 0x08b760d, 0x1ddbc0f, 0x0a8246d, 0x104b55b, 0x147b0bd, 0x1a9137e,
|
|
0x0f67fea, 0x11d0292, 0x0bffc14, 0x136e913, 0x0f8f6d2, 0x1f15453,
|
|
0x0b5a032, 0x1a58558, 0x036f1c0, 0x090d063, 0x1b57d65, 0x16e665f,
|
|
0x1160791, 0x0d566f3, 0x0ce2850, 0x1714187, 0x0244da9, 0x0d9018e,
|
|
0x19356cf, 0x143245b, 0x1fbdac7, 0x142ec6e, 0x10f1c9f, 0x0e60c1f,
|
|
0x174b270, 0x02d57db, 0x0f0526d, 0x186f24b, 0x038aa4e, 0x147c1d3,
|
|
0x0f13873, 0x16bd6d0, 0x127b1bc, 0x0b9e7f4, 0x04eb93b },
|
|
{ 0x11fae32, 0x0fbf2f0, 0x1d46f62, 0x0b88047, 0x113d74f, 0x0e1fb7e,
|
|
0x0537d24, 0x16e3600, 0x1555279, 0x0c24d2b, 0x0801a07, 0x112e0b7,
|
|
0x0abb9e8, 0x009e516, 0x0889067, 0x0cedf04, 0x085fd33, 0x157dddb,
|
|
0x161e28a, 0x187ea4e, 0x1173931, 0x17f79ea, 0x04abbbf, 0x114d0f0,
|
|
0x05cc8bd, 0x00b0c4d, 0x0f667c3, 0x059ffb6, 0x1d48b68, 0x0a0350c,
|
|
0x182fd59, 0x1d38d89, 0x005e223, 0x020b92b, 0x077a1a0, 0x10a7cf0,
|
|
0x07001cc, 0x1ae485e, 0x0fda337, 0x126f808, 0x02b582d },
|
|
{ 0x1abc2ae, 0x12e4140, 0x1b2a845, 0x0bc56d3, 0x073380f, 0x1ffb37d,
|
|
0x0cf481f, 0x00d812f, 0x0547765, 0x0b01c13, 0x1e88717, 0x13e76af,
|
|
0x15dcbac, 0x04c6dee, 0x1d436d3, 0x1e654f0, 0x103d9ef, 0x042f108,
|
|
0x1c47107, 0x1a2e585, 0x0c09cee, 0x124f1a4, 0x0a38e49, 0x03dbbf7,
|
|
0x1936b83, 0x051b8e5, 0x1bd4219, 0x02b87a0, 0x1acfcd9, 0x19e6f49,
|
|
0x0abfa38, 0x167e5ef, 0x1ee10d7, 0x0774d25, 0x0d23adf, 0x1b83b1d,
|
|
0x1a574af, 0x124e71f, 0x0d3013e, 0x0130c5b, 0x0786151 },
|
|
{ 0x0e72c21, 0x1fa403d, 0x1694ff8, 0x09fa1e1, 0x031aa14, 0x01d22a3,
|
|
0x187a3e3, 0x1578edd, 0x051b4f1, 0x1cd704a, 0x16ec90d, 0x072faf9,
|
|
0x0d2a3a4, 0x015eafe, 0x0533ffa, 0x1deb4f4, 0x112f427, 0x1ddf276,
|
|
0x0134f33, 0x1487dc5, 0x0e1e9b0, 0x09c7763, 0x15ede2e, 0x171d0f6,
|
|
0x004e467, 0x0100c6a, 0x14d0dd3, 0x1915b80, 0x08deb50, 0x1b02aa1,
|
|
0x13d90dc, 0x1875f45, 0x0d80ec0, 0x0ab7cda, 0x04f0eaa, 0x10daa3f,
|
|
0x04161c6, 0x0d1455c, 0x100967e, 0x16ed793, 0x0540b6b },
|
|
{ 0x01d315d, 0x0b9a619, 0x1740138, 0x05b0dc0, 0x0ef5661, 0x1466c0a,
|
|
0x18516ee, 0x135d5f5, 0x1acdc78, 0x1d83d24, 0x1d5c3c7, 0x135ab0e,
|
|
0x1e6a21e, 0x1cde29e, 0x12a0dfa, 0x131d65c, 0x0931d62, 0x0a1b6d9,
|
|
0x08d8bd1, 0x1f78f1d, 0x058543a, 0x0bd55fb, 0x0aa5cf6, 0x1249ac0,
|
|
0x1dabe0c, 0x074ee73, 0x01f2b7c, 0x0d3b31e, 0x020538f, 0x02d0ba8,
|
|
0x0a782d4, 0x088c39a, 0x1b7d1a3, 0x0740c1e, 0x1dd9788, 0x0dc3850,
|
|
0x12dd50f, 0x112c33a, 0x0e230b2, 0x02925c0, 0x0897cab },
|
|
{ 0x18bab8a, 0x09c0986, 0x002967b, 0x1948704, 0x011d364, 0x0c0a0ae,
|
|
0x0fcb101, 0x0e80d0f, 0x07ac896, 0x156869d, 0x1046821, 0x020b72e,
|
|
0x1c44928, 0x19c19b8, 0x0612c47, 0x1063ce9, 0x1840d1a, 0x0386976,
|
|
0x1244bf8, 0x06c516d, 0x08d2d88, 0x1d8a7d4, 0x113e3df, 0x015927c,
|
|
0x12a4dcf, 0x1d32b27, 0x0a9b093, 0x05ec535, 0x0cd9498, 0x15d1dfb,
|
|
0x0b6ae41, 0x0414a30, 0x0822e67, 0x1c9d296, 0x16b0c3a, 0x145fe8f,
|
|
0x1ff673a, 0x1162527, 0x03b1771, 0x0c68ed6, 0x064b007 },
|
|
{ 0x1c9a404, 0x1a99f59, 0x054878f, 0x076fdf3, 0x11db7f7, 0x129b49d,
|
|
0x0f8a5b0, 0x1a98fe2, 0x00738ee, 0x073fa62, 0x1b2b41f, 0x16679c4,
|
|
0x11ccfd3, 0x00f62e7, 0x1e124d4, 0x09c03b0, 0x09ddc08, 0x19fc7e0,
|
|
0x0e6d6b3, 0x1956658, 0x151c217, 0x1dcf7aa, 0x10b6bc2, 0x042f52a,
|
|
0x16f56e1, 0x0157de3, 0x0b08dc0, 0x002f162, 0x10a2938, 0x01cfd83,
|
|
0x1902d4b, 0x0aed952, 0x1925153, 0x1471b71, 0x1090675, 0x084aab2,
|
|
0x09e50e8, 0x0fdc160, 0x1b630a4, 0x14ccc31, 0x07dd22e },
|
|
{ 0x1cbb3bf, 0x14225a4, 0x0c95fff, 0x08aac5f, 0x1e0cc70, 0x0d422d6,
|
|
0x194de7d, 0x1f83cdd, 0x0e51277, 0x0b6bf93, 0x0d5c625, 0x097260c,
|
|
0x142c75d, 0x0b4abf9, 0x085224a, 0x0e85673, 0x13282e5, 0x1467a75,
|
|
0x0c91edc, 0x1a7bbb0, 0x02376b0, 0x19900d2, 0x19ea7d8, 0x029490a,
|
|
0x003c114, 0x08b20b2, 0x1edbdaa, 0x015fa88, 0x06f7906, 0x04986d6,
|
|
0x00a57e5, 0x17a773b, 0x05ff94b, 0x16f87b4, 0x03f1472, 0x12b91f3,
|
|
0x113b748, 0x0ce4455, 0x1f32255, 0x0ccbe31, 0x031377c },
|
|
{ 0x1cfb35f, 0x0ef04be, 0x1be0d71, 0x1e03986, 0x0dccca9, 0x1b65b19,
|
|
0x1a175d5, 0x0eafd27, 0x0f7b4b3, 0x016ea45, 0x0866d43, 0x1a9f613,
|
|
0x079d95c, 0x18dff30, 0x0bb4565, 0x1b5a4ea, 0x0cf2596, 0x1a1cc40,
|
|
0x07a429b, 0x1df6a6d, 0x060ae52, 0x1181e9f, 0x11025d9, 0x0a0e1c0,
|
|
0x164faa9, 0x0e97e79, 0x1815893, 0x11f3276, 0x15e467d, 0x0c12006,
|
|
0x092cd6a, 0x0191e8a, 0x089d024, 0x100bcf1, 0x08f1922, 0x1bde8a8,
|
|
0x187edab, 0x0feb4aa, 0x149c4e9, 0x019423c, 0x03dacc5 },
|
|
{ 0x099ae4c, 0x127ca32, 0x149f2cf, 0x02e0a78, 0x046dcbe, 0x1c17455,
|
|
0x173a6f9, 0x08b00fe, 0x0d8481e, 0x1632694, 0x01bf42d, 0x0a31545,
|
|
0x09f35e4, 0x0f8e6da, 0x0dee6eb, 0x07d5fef, 0x010aec2, 0x1f9fdb1,
|
|
0x06ff4be, 0x17470b7, 0x13a00a9, 0x09c403f, 0x1946835, 0x0f65085,
|
|
0x04404b1, 0x1853d59, 0x1fe7767, 0x1faaed0, 0x09df646, 0x1eda79f,
|
|
0x137347b, 0x0c1be32, 0x1d2df7a, 0x0ef82ae, 0x0b0f81a, 0x037da7e,
|
|
0x03248a3, 0x0dbab09, 0x113dd1a, 0x1c2d28e, 0x0866949 },
|
|
{ 0x14ab07a, 0x106d29f, 0x1efcea6, 0x07ea94d, 0x0cd6f33, 0x1e79481,
|
|
0x1a486c8, 0x0b01925, 0x0848e3d, 0x0ac0e1f, 0x0862af2, 0x1f7ba76,
|
|
0x1793af1, 0x03365a6, 0x1663a84, 0x0074070, 0x14e990c, 0x0a8009c,
|
|
0x1421ded, 0x0c963cf, 0x10913b6, 0x1deba63, 0x15e76c6, 0x05abba1,
|
|
0x144354e, 0x1c14296, 0x0ccca76, 0x1a57083, 0x16d4800, 0x07583dc,
|
|
0x11bea11, 0x1852bb8, 0x1a50569, 0x1f6271b, 0x0dce53d, 0x0f85a70,
|
|
0x1b08317, 0x1c427fa, 0x0966370, 0x171163f, 0x0574352 },
|
|
{ 0x15d7ce9, 0x0c9fb86, 0x1abfb48, 0x0c1690f, 0x1c19fd2, 0x132fe81,
|
|
0x0ad65ef, 0x0acf889, 0x078270d, 0x0ced430, 0x1c06637, 0x1801754,
|
|
0x1f8a84e, 0x142cc2e, 0x109f924, 0x051b05d, 0x0f0de20, 0x0ccb665,
|
|
0x0708807, 0x0c918ec, 0x19eb4e7, 0x1e048e0, 0x0a58cd6, 0x1acf057,
|
|
0x03a69f0, 0x049929d, 0x034a519, 0x1e40868, 0x1f68733, 0x10d084c,
|
|
0x0691114, 0x0d32c02, 0x1cbcc09, 0x1d4a72f, 0x1763e14, 0x027109a,
|
|
0x13b6a3a, 0x0c63126, 0x0f13c90, 0x1e40d5c, 0x03e431a },
|
|
{ 0x1d381f1, 0x1ec9cc1, 0x0f0fe59, 0x1da1806, 0x16501aa, 0x0083b41,
|
|
0x1d34151, 0x1a77e75, 0x05093a6, 0x0368acc, 0x1ca402a, 0x0e83b25,
|
|
0x1543ae0, 0x1b785ba, 0x0cabe98, 0x0dadffd, 0x0a3aa45, 0x1684853,
|
|
0x1bf6d91, 0x149fb55, 0x0f7d336, 0x020d4a1, 0x1f46ff9, 0x03dc83d,
|
|
0x0a3ed85, 0x0e2bfe1, 0x1847a4d, 0x1e392d0, 0x1bb3434, 0x1b3329d,
|
|
0x0ab355d, 0x15b12d8, 0x06931ba, 0x1fd20f9, 0x0f461ae, 0x03141f7,
|
|
0x0203cef, 0x1ebec15, 0x134d470, 0x02bc4cc, 0x06dad3f },
|
|
{ 0x0ec35a1, 0x005be89, 0x04a3465, 0x0dcfbf6, 0x0219c5b, 0x1990eab,
|
|
0x1e31bc4, 0x16c5984, 0x033c58e, 0x13b4825, 0x00f10d7, 0x1eabb32,
|
|
0x1915090, 0x01ecb50, 0x06f249b, 0x1974e0c, 0x1038c0a, 0x1cba54f,
|
|
0x0662c86, 0x028042e, 0x0c6f7a4, 0x0efc4ac, 0x0c1a566, 0x17a0253,
|
|
0x12f1dbe, 0x0e1a8bf, 0x0f7cea3, 0x02134c2, 0x0375c51, 0x0224339,
|
|
0x14c2396, 0x12707a5, 0x0590ba4, 0x1c1be2b, 0x1f182ff, 0x1ff87dc,
|
|
0x07d2d55, 0x1d29c81, 0x1e8ff21, 0x1a8bea2, 0x02438e9 },
|
|
{ 0x015af3c, 0x0298444, 0x1b57129, 0x05e7937, 0x055f1a3, 0x1b2eeff,
|
|
0x137265e, 0x16b5de3, 0x012e51e, 0x0e30eca, 0x1c92418, 0x18a9cc7,
|
|
0x11bd0da, 0x0859f11, 0x0510a73, 0x0c020de, 0x1c2f1da, 0x0fb9be1,
|
|
0x0ef13ec, 0x01c096d, 0x01cb715, 0x048df14, 0x0816d32, 0x0e03eb6,
|
|
0x0633cd7, 0x04878da, 0x18a944d, 0x1667de8, 0x11f7f28, 0x1e39b47,
|
|
0x19f76d1, 0x17a82d6, 0x0ada511, 0x0add9fa, 0x1f37fde, 0x0f3a552,
|
|
0x16200e6, 0x145bd94, 0x0380402, 0x0235fc6, 0x013f390 },
|
|
{ 0x1d0c827, 0x14b77bd, 0x1d18f74, 0x069453f, 0x106110f, 0x0d28ad2,
|
|
0x0c1a072, 0x0eff0f2, 0x1268bca, 0x146c022, 0x01177f7, 0x0049330,
|
|
0x04cbb83, 0x146072c, 0x0435c41, 0x0c0c47f, 0x0a8263b, 0x19541c6,
|
|
0x0d71742, 0x176bcea, 0x1110293, 0x0aab20a, 0x13baa67, 0x17b400b,
|
|
0x11ad01b, 0x00c7f18, 0x1e93634, 0x092fc17, 0x12b8662, 0x1bd00e7,
|
|
0x02ccf75, 0x1b18975, 0x0075b73, 0x1bde4de, 0x1b51c8a, 0x165308c,
|
|
0x0bda1b0, 0x13e7126, 0x00ed85e, 0x0d6d00e, 0x0458d4b },
|
|
{ 0x154d8b2, 0x1510726, 0x0836289, 0x1c9a641, 0x05a5696, 0x0a7b800,
|
|
0x16163e6, 0x150d316, 0x02f6549, 0x1256e1e, 0x134035e, 0x10326d2,
|
|
0x1d1812e, 0x1982015, 0x0e6c001, 0x0c8208d, 0x049a1b3, 0x070850a,
|
|
0x048c088, 0x12bd4b3, 0x00c3eae, 0x0d8da41, 0x0fbf0ba, 0x193d714,
|
|
0x15cb585, 0x0327f2d, 0x065e11c, 0x035c063, 0x07d49f2, 0x05b8479,
|
|
0x1ada3bc, 0x05ee4aa, 0x059ef18, 0x0d80d19, 0x115d893, 0x18015c0,
|
|
0x1668f95, 0x071d832, 0x0fe458a, 0x1f56df7, 0x05f13f5 },
|
|
{ 0x09b0dc6, 0x16cd71d, 0x1b21f1b, 0x12df107, 0x0ea1bde, 0x059b3bd,
|
|
0x0fe23aa, 0x157d4cd, 0x09a66e3, 0x17d355e, 0x05fff77, 0x02f6d04,
|
|
0x1cc4d33, 0x1486f82, 0x10723c8, 0x0ce9dee, 0x1177d11, 0x10f87ef,
|
|
0x0d66272, 0x01d9cf8, 0x082dfdf, 0x0fb5ce2, 0x03bb64b, 0x17e394e,
|
|
0x13e6655, 0x0ce39b8, 0x00973b2, 0x0159652, 0x03e69c9, 0x11d1740,
|
|
0x068df27, 0x02ee274, 0x00a3c53, 0x10ba6be, 0x1595bd6, 0x0c6a1b8,
|
|
0x05f802f, 0x112d220, 0x0928845, 0x0bb46f7, 0x0219649 },
|
|
{ 0x1142680, 0x197e989, 0x13d0032, 0x0ecba29, 0x0b9e91d, 0x11334f5,
|
|
0x13aaf7f, 0x18b8d41, 0x00ae22b, 0x177e72c, 0x1b0942f, 0x130d96d,
|
|
0x1f3c2b7, 0x0b9c78f, 0x0b6c68b, 0x191d909, 0x028516e, 0x0cb84de,
|
|
0x1a3df6d, 0x1262531, 0x17f9f36, 0x15cad8c, 0x1123bf1, 0x1554809,
|
|
0x109529a, 0x0584ff8, 0x1451055, 0x1879197, 0x1f34352, 0x1de1a13,
|
|
0x104cfbd, 0x1a4312f, 0x0a17940, 0x0a45002, 0x11f5b39, 0x04b5418,
|
|
0x1d56fa6, 0x18e7539, 0x17c20a5, 0x160088e, 0x093ad0e },
|
|
{ 0x08a9963, 0x1b4b3cc, 0x0375e82, 0x0eca2bd, 0x01e477f, 0x15a8793,
|
|
0x18e18ed, 0x1bcc4e9, 0x1d33922, 0x1d4dc6a, 0x096cf58, 0x07f6d0f,
|
|
0x033c38d, 0x0981719, 0x1dbc270, 0x1999e31, 0x1c3e02f, 0x192a602,
|
|
0x1b998bd, 0x1da16e4, 0x0079c04, 0x1c0a1ff, 0x075591a, 0x002d918,
|
|
0x09448c9, 0x1cbf7c5, 0x0fe08f5, 0x0ace989, 0x0de451e, 0x1b97de6,
|
|
0x178161b, 0x0882fd5, 0x1fc88d5, 0x12c46e2, 0x08255db, 0x12572a4,
|
|
0x1844d1f, 0x046ea12, 0x100d110, 0x1e1d483, 0x073f8c3 },
|
|
{ 0x1f763dd, 0x1a7e42e, 0x00da254, 0x06758e3, 0x1b1427f, 0x078ad01,
|
|
0x0f85dba, 0x11c1b6b, 0x0cb2088, 0x09c84a2, 0x12ba987, 0x135b0af,
|
|
0x137804c, 0x08cfbdf, 0x16110a1, 0x1519f54, 0x0f1293a, 0x0b13776,
|
|
0x08da805, 0x1c1b31d, 0x0dcd749, 0x171990f, 0x1bffdb6, 0x16f2399,
|
|
0x1eea628, 0x1b0cb1e, 0x08b45b8, 0x029c0aa, 0x1ae206a, 0x0c7e58a,
|
|
0x1928b81, 0x1f9464b, 0x1268745, 0x00d4507, 0x101c84d, 0x10f9f3a,
|
|
0x1caa51b, 0x1692ecb, 0x175d77f, 0x0735b7d, 0x00108ae },
|
|
{ 0x1e88f63, 0x0bc79d4, 0x0c95534, 0x1d5618e, 0x0a05b11, 0x10ec535,
|
|
0x14f9b89, 0x190ee74, 0x08d0b91, 0x06dbed7, 0x0c01349, 0x00e7d37,
|
|
0x0bde10b, 0x0a71848, 0x02fbf9d, 0x13913f9, 0x1990cc6, 0x10b5782,
|
|
0x1565446, 0x1070073, 0x1afcddc, 0x0ca362e, 0x10fd96e, 0x1c14b33,
|
|
0x04be81e, 0x18bfddf, 0x1becea6, 0x11123c6, 0x1dad008, 0x16baa22,
|
|
0x07c326a, 0x1aa12fc, 0x1fc46ab, 0x0d270ef, 0x026eb21, 0x0710901,
|
|
0x00c4523, 0x05da17d, 0x1077cd2, 0x1b1d627, 0x0807c06 },
|
|
{ 0x0ee0ef6, 0x0b4f64c, 0x1ebc02a, 0x07176f6, 0x1a9d548, 0x17c7edd,
|
|
0x1324a80, 0x0f84890, 0x08b7055, 0x1ed900d, 0x146bc9e, 0x07c8c15,
|
|
0x1be5934, 0x0cc64af, 0x0a6a50a, 0x03a76a7, 0x1deda86, 0x14ba6d9,
|
|
0x14e6703, 0x0a4b93d, 0x09bdce1, 0x00fb908, 0x026d5a2, 0x1042349,
|
|
0x17d1599, 0x1ad047f, 0x0bbc3c9, 0x1beed67, 0x0f358b5, 0x007bfd1,
|
|
0x0d24fc6, 0x187360c, 0x0c4ffcf, 0x01da9d5, 0x18985d6, 0x184d258,
|
|
0x155399f, 0x1efd1b5, 0x1e986cb, 0x0d932c0, 0x016424c },
|
|
{ 0x12744a9, 0x12e2aee, 0x1061775, 0x05fc75e, 0x0544c1c, 0x1458449,
|
|
0x0ba67bf, 0x0346590, 0x1a9df69, 0x05bd592, 0x0659d0c, 0x0aa137d,
|
|
0x0298384, 0x0579689, 0x1b34963, 0x0e4e579, 0x098bcc7, 0x0445720,
|
|
0x0e3be83, 0x12c2829, 0x112cd43, 0x1cf6b26, 0x113fd9e, 0x0fe6808,
|
|
0x055e42e, 0x0f5d4f3, 0x1516c3a, 0x1a2df88, 0x1ded283, 0x1f0a781,
|
|
0x1711d28, 0x1599970, 0x1c9adff, 0x1d28dd1, 0x0f05c94, 0x027bfcd,
|
|
0x1b5831b, 0x0d7a5cf, 0x11e2b77, 0x00549e8, 0x05544e6 },
|
|
{ 0x0a80b4f, 0x02989dd, 0x03be25f, 0x1ec77b9, 0x0122716, 0x0162d40,
|
|
0x10b6ded, 0x1195c4e, 0x1088330, 0x0ecf0f4, 0x106ac7a, 0x187e5a6,
|
|
0x10352c8, 0x16ca2c3, 0x0f41403, 0x1b3b02c, 0x173c290, 0x0c1a4ee,
|
|
0x1db1f4a, 0x078bc03, 0x033c205, 0x0365a10, 0x00c41d1, 0x1a135e3,
|
|
0x08bd209, 0x140bb64, 0x1ac9e51, 0x01ee1cd, 0x11b540d, 0x0cef0cd,
|
|
0x10dc82d, 0x0453296, 0x0b7ecdc, 0x029e7c0, 0x1738b7b, 0x0583499,
|
|
0x1ed60f4, 0x1e9f6e8, 0x1498775, 0x0b9c483, 0x0573599 },
|
|
{ 0x0237056, 0x1d1fdd0, 0x0e23712, 0x0867566, 0x0856c16, 0x0f63093,
|
|
0x1aef49c, 0x1d9803d, 0x1e3031b, 0x1ef5819, 0x0287d6a, 0x0832c23,
|
|
0x134eee4, 0x0db0079, 0x125d085, 0x10ee7d8, 0x1cf0886, 0x08db8c2,
|
|
0x106df7f, 0x188d9af, 0x1e897b0, 0x0d25262, 0x1450ecb, 0x03ff29b,
|
|
0x05984bb, 0x032edcd, 0x13273cd, 0x187209c, 0x0e64c9a, 0x0de0756,
|
|
0x06be1ca, 0x0ed15b3, 0x0c22821, 0x0a0612e, 0x02062a5, 0x0f77a76,
|
|
0x049a691, 0x1476af8, 0x17bc391, 0x1be7d88, 0x0885486 },
|
|
{ 0x1dff464, 0x01649a5, 0x1145aa5, 0x1e4b4f6, 0x1db2719, 0x0df1921,
|
|
0x01c2cc9, 0x0739960, 0x119fe33, 0x02ad18d, 0x1ba3fc8, 0x15d0483,
|
|
0x0faca69, 0x0af7c6f, 0x01f7421, 0x0e78cec, 0x00f1a1b, 0x04f124b,
|
|
0x074da04, 0x01d144e, 0x06b9bcb, 0x113442f, 0x0a7846a, 0x0bd5c32,
|
|
0x1d0ab18, 0x08e4c5a, 0x103e07e, 0x14172dc, 0x0fc5031, 0x05e7cca,
|
|
0x181343a, 0x1e233ad, 0x1d81697, 0x0670619, 0x0a1eaa9, 0x0e52106,
|
|
0x091ff9d, 0x0ea69f6, 0x058b717, 0x1d1a957, 0x031cecf },
|
|
{ 0x08b21e8, 0x1fecd7e, 0x1b7d0de, 0x0763286, 0x05dd32b, 0x0e1b507,
|
|
0x00b5248, 0x121fcb2, 0x1a3d0fa, 0x14ef426, 0x148ef63, 0x0d5ab76,
|
|
0x159663e, 0x1766b4b, 0x00288fe, 0x16b3930, 0x0d9b4fb, 0x08804e0,
|
|
0x07483fc, 0x154f7b9, 0x1a3d839, 0x16f66b7, 0x1d40bd9, 0x0a2d953,
|
|
0x0d4fbc5, 0x1622407, 0x19b1d0a, 0x0bff4be, 0x1252f86, 0x1ca2ff9,
|
|
0x0f4adf1, 0x0ebb396, 0x0fefc05, 0x178e939, 0x18ef5b5, 0x0623610,
|
|
0x1a6a4ec, 0x079e784, 0x11ecd76, 0x0d5b44a, 0x06961b4 },
|
|
{ 0x135e2ac, 0x1ac3f65, 0x136741e, 0x16af5e2, 0x1ed5546, 0x1450260,
|
|
0x1e96f6c, 0x1e1d942, 0x0709d54, 0x0fc8ea2, 0x1d003a8, 0x13fb38d,
|
|
0x10a6e71, 0x1dc670c, 0x12e23b7, 0x07fa49c, 0x0dd246e, 0x0fcbc0f,
|
|
0x1956bd7, 0x0241cd6, 0x1ca7d67, 0x0ec9a09, 0x169e0b4, 0x00ff443,
|
|
0x020a297, 0x091b4bf, 0x0953a10, 0x1d6a3e6, 0x051f9f1, 0x06cf1b0,
|
|
0x1a4b895, 0x0e79cb7, 0x1aec42b, 0x1bca7ee, 0x0cbb34f, 0x1313534,
|
|
0x0781aad, 0x1271178, 0x1484865, 0x018a6ea, 0x06a63a9 },
|
|
{ 0x17acbbb, 0x0a7001e, 0x0421d95, 0x156e9ec, 0x0c01668, 0x0628cd9,
|
|
0x059c8e2, 0x09fc945, 0x03eb94d, 0x0b33b8a, 0x1b4bd80, 0x19be19a,
|
|
0x1f086a3, 0x1d9b87b, 0x1960085, 0x07cf9f0, 0x0c15a4d, 0x0b2c440,
|
|
0x0e8fd28, 0x1ab02cb, 0x11ddd6e, 0x09ae523, 0x0af31e0, 0x0894aed,
|
|
0x1f074e8, 0x175404d, 0x0dba940, 0x0a75036, 0x021ed3a, 0x0983870,
|
|
0x197082e, 0x10c2fe2, 0x027f892, 0x0e685c6, 0x111a08d, 0x034a8ec,
|
|
0x0255296, 0x044ffec, 0x1643bff, 0x045a2a3, 0x051ed4a },
|
|
{ 0x09701b4, 0x14b1d22, 0x0bc8df5, 0x07764f9, 0x0a8d91a, 0x194b2ff,
|
|
0x0f856d5, 0x0fa7df3, 0x1db50bf, 0x0d3d02a, 0x10ee6dd, 0x101d9cc,
|
|
0x1efd674, 0x1675aea, 0x09834b5, 0x1912fe5, 0x00c5ed7, 0x1b47e19,
|
|
0x0339a17, 0x0a79ec5, 0x015e41c, 0x0fb8833, 0x038a5c4, 0x0a01d98,
|
|
0x1213823, 0x1243d43, 0x01b0a7f, 0x1e1524c, 0x0f9712a, 0x1f9570f,
|
|
0x0fe4f7c, 0x1a5a2d3, 0x15f6fb1, 0x0bc9e06, 0x1899d2a, 0x0dd6f5f,
|
|
0x09f4925, 0x19eca57, 0x1739505, 0x1785716, 0x02d6951 },
|
|
{ 0x04e222e, 0x03ecfc8, 0x0427740, 0x1f0de9c, 0x133f248, 0x014f771,
|
|
0x13a2e3d, 0x031a932, 0x1cfc775, 0x0ab9a0a, 0x1d0bc4a, 0x1474161,
|
|
0x196e7fe, 0x013a1a8, 0x0572df7, 0x0e3418f, 0x166711e, 0x0c10547,
|
|
0x0e1d3d5, 0x12bb385, 0x162783d, 0x1c73870, 0x152d935, 0x1254e85,
|
|
0x153f58b, 0x136c921, 0x0511ed7, 0x0440916, 0x1931a03, 0x19865e7,
|
|
0x1a02eb5, 0x14f5e44, 0x1c4d089, 0x1c9fcba, 0x1306e0e, 0x1c8c920,
|
|
0x165b3ae, 0x075d010, 0x117c289, 0x0f1c119, 0x065c48e },
|
|
{ 0x0222c22, 0x039e76f, 0x0ed0687, 0x1bf9d44, 0x1683d8c, 0x0a1d832,
|
|
0x12c52c8, 0x0ee0603, 0x159fcec, 0x0256fc7, 0x0133bca, 0x1038624,
|
|
0x07fb1c5, 0x0a39a88, 0x134fbba, 0x11181ea, 0x10b4d31, 0x16dfb3f,
|
|
0x03c6344, 0x07e5a22, 0x001376a, 0x1403e9f, 0x0e027e8, 0x1cfd9c0,
|
|
0x10a4625, 0x0977837, 0x16ca257, 0x1050cfd, 0x10553ad, 0x1a44845,
|
|
0x117841b, 0x1de48a8, 0x0280fa6, 0x0d1e5f1, 0x1e16a36, 0x1a805aa,
|
|
0x1438ba2, 0x1eecffe, 0x089bfd8, 0x058f4d6, 0x036b5cd },
|
|
{ 0x05679a7, 0x1a7102a, 0x1d421ff, 0x028a418, 0x04d80b4, 0x02ce6c3,
|
|
0x15fea6d, 0x1472146, 0x1c85af1, 0x0cf579c, 0x0d697a8, 0x1af31b2,
|
|
0x0a0d475, 0x1c0d33c, 0x140660d, 0x1d020e8, 0x1790cc2, 0x03a41cb,
|
|
0x1d04891, 0x043a225, 0x1a37c6a, 0x1c9b528, 0x0343a17, 0x14e9bf1,
|
|
0x0151eea, 0x0e27fa8, 0x1e4f3e6, 0x09c3054, 0x0a9ab61, 0x1ef89bb,
|
|
0x1fd1564, 0x0a44713, 0x0f73caf, 0x02f450c, 0x0583dd1, 0x11a4f99,
|
|
0x19a51dc, 0x097a629, 0x0ff601a, 0x089b673, 0x008d7c1 },
|
|
{ 0x0cca773, 0x006cb1f, 0x055a027, 0x05a9184, 0x07ea919, 0x15eb20c,
|
|
0x135d36d, 0x1bfe1d9, 0x02a678c, 0x19891ba, 0x01edf9d, 0x1b17a2b,
|
|
0x067a966, 0x1098526, 0x1068405, 0x02f7be7, 0x0385fce, 0x03e6374,
|
|
0x0379ea9, 0x12b7715, 0x08e395e, 0x1ac4c18, 0x0ff87a2, 0x08ed294,
|
|
0x1243ee3, 0x15f80cb, 0x0aec334, 0x07fd388, 0x1b2b49f, 0x093207c,
|
|
0x07ed641, 0x18e6cfa, 0x0385e8b, 0x10a3da6, 0x02bad7b, 0x123a60a,
|
|
0x04004ad, 0x161c3c8, 0x0080a38, 0x1dd756e, 0x05f2aa8 },
|
|
{ 0x066524b, 0x06a3209, 0x1d9b882, 0x01a1433, 0x17bf388, 0x08375fd,
|
|
0x1a17b68, 0x08d4b54, 0x1e642dd, 0x134f469, 0x0b93582, 0x18c38d0,
|
|
0x0cef349, 0x07e5a9a, 0x1dbb8ec, 0x0cf704d, 0x12705eb, 0x13ed5d0,
|
|
0x02f817d, 0x1764fc3, 0x05d12ba, 0x1d4716c, 0x0566bf2, 0x1b3a70d,
|
|
0x12d1ae2, 0x03776e7, 0x187a9bc, 0x13b8a5c, 0x0e5ae85, 0x1c5a433,
|
|
0x11f0a09, 0x00579a7, 0x1ff0340, 0x1f417ec, 0x11d9e12, 0x09d1095,
|
|
0x03c9f22, 0x0b24c04, 0x1e5268c, 0x13168df, 0x062501a },
|
|
{ 0x1264086, 0x1becd56, 0x12f558f, 0x174bc1c, 0x0a6a33d, 0x069eb3e,
|
|
0x0c00a32, 0x033d04a, 0x046e64b, 0x1446d64, 0x0914da8, 0x032e415,
|
|
0x0cfa3c9, 0x16aa9f5, 0x0c326c3, 0x157a702, 0x0e02ea8, 0x1b11403,
|
|
0x1b33f9d, 0x17ea9b9, 0x1b7052f, 0x18a7868, 0x0f66a38, 0x1362e83,
|
|
0x12133d5, 0x14528ce, 0x1269bfa, 0x1ae8203, 0x04eb10f, 0x1bd05ae,
|
|
0x17b46b3, 0x123f3b4, 0x0499b73, 0x152c33c, 0x1127037, 0x1557549,
|
|
0x01f3531, 0x0e2fb9d, 0x1199732, 0x1fdfa7f, 0x0497b15 },
|
|
{ 0x05568e9, 0x165d57a, 0x09be295, 0x1d8e325, 0x1491a0f, 0x1929cd7,
|
|
0x0f74e6a, 0x153b760, 0x04ac37d, 0x032917c, 0x03d6d32, 0x1744054,
|
|
0x1f8c8cd, 0x114e29c, 0x027f1d6, 0x1e05d02, 0x131ca90, 0x1ce6836,
|
|
0x1885b6f, 0x03e0887, 0x1d918f3, 0x165d1f5, 0x066a9a2, 0x1800fe9,
|
|
0x0d0d242, 0x1e71540, 0x1e1aa6d, 0x1b1bff7, 0x108edcd, 0x1f426b1,
|
|
0x1290174, 0x00d0025, 0x0fa33fe, 0x10838ed, 0x144fb7a, 0x0d85dd7,
|
|
0x0ff637e, 0x173f2e1, 0x132dede, 0x0d93ca2, 0x018d46a },
|
|
{ 0x18b7802, 0x05d9153, 0x0bd21a3, 0x0492f97, 0x0745ddb, 0x17456e8,
|
|
0x0bcf90a, 0x1c989d6, 0x0b4ceb4, 0x0055e6d, 0x17f502b, 0x064b464,
|
|
0x052e0d8, 0x09d639a, 0x1f815c4, 0x0e372d9, 0x188b141, 0x1ba03d3,
|
|
0x169e94a, 0x160c06d, 0x16ac70e, 0x1cec28b, 0x0ac2cdb, 0x052a9e7,
|
|
0x09d297c, 0x0d68a08, 0x03735c1, 0x0e1bd39, 0x15e7513, 0x1ae6bdd,
|
|
0x030fc36, 0x140dce1, 0x1f93d41, 0x18286a2, 0x1e29fa4, 0x1221aa9,
|
|
0x1a38fef, 0x137c722, 0x0b901a7, 0x003a7ec, 0x0550446 },
|
|
{ 0x0cb9cc9, 0x0e48803, 0x0053471, 0x0e83a00, 0x142074d, 0x11b7dc2,
|
|
0x198f844, 0x104f9b0, 0x029ad5f, 0x0b90fff, 0x07f20ce, 0x17f452a,
|
|
0x0f1d21f, 0x00068a2, 0x1781b9d, 0x05cd639, 0x16b9179, 0x148212c,
|
|
0x06b5459, 0x0b91ca5, 0x1e98336, 0x02cd777, 0x188883a, 0x1855dc7,
|
|
0x1318970, 0x05e5e5a, 0x0e7fc40, 0x0ef947b, 0x12973f4, 0x00bb7a9,
|
|
0x06c9c1d, 0x13457a0, 0x12118ac, 0x1cfc9d0, 0x0824f75, 0x17e684a,
|
|
0x06f5d7d, 0x1d47fbe, 0x1b13d58, 0x1f9af61, 0x00da313 },
|
|
{ 0x1aa2557, 0x12d460a, 0x1a70dc4, 0x1801127, 0x0a21d70, 0x1c5411e,
|
|
0x0e6519e, 0x05490e2, 0x07cb004, 0x09f4d3a, 0x0b38603, 0x09ff93c,
|
|
0x022d2bf, 0x024d756, 0x14c6834, 0x00cc1aa, 0x016f03d, 0x02694d3,
|
|
0x1c6dfc0, 0x1aa1ac3, 0x050c473, 0x1de51ef, 0x0ebc3b2, 0x1851e4e,
|
|
0x19bea09, 0x132714a, 0x03e1c11, 0x1af85d4, 0x1083ef6, 0x1270b98,
|
|
0x152b7eb, 0x128384a, 0x0940c26, 0x11681a8, 0x1042845, 0x1c882ce,
|
|
0x1e82290, 0x01186c0, 0x12b3188, 0x1d1b682, 0x063630b },
|
|
{ 0x07d2e41, 0x0a91145, 0x01e6fe3, 0x07d6c5f, 0x09e7582, 0x0016c4a,
|
|
0x0cf75b1, 0x15a369a, 0x0de2c59, 0x01f026b, 0x0770e22, 0x11e8937,
|
|
0x0cbf3f3, 0x1a5b862, 0x065f462, 0x1408b3b, 0x00c13ce, 0x08fb4d9,
|
|
0x038981b, 0x1ae04ab, 0x1b79ca3, 0x1b930e8, 0x0f53f65, 0x0286df4,
|
|
0x0afa85a, 0x003ab57, 0x02ed10f, 0x0d367d3, 0x18f6be3, 0x0c3672a,
|
|
0x027f394, 0x1f1591f, 0x10cd478, 0x0d53975, 0x1cdf579, 0x00d00e9,
|
|
0x08544eb, 0x0c22e03, 0x023b4a5, 0x0e3e2cd, 0x0306a98 },
|
|
{ 0x14ec136, 0x08f4eb1, 0x163ef11, 0x141cdec, 0x1edf27c, 0x0da0900,
|
|
0x0054b03, 0x0cf537c, 0x0c5bfee, 0x1db7790, 0x15808e1, 0x0471345,
|
|
0x1935283, 0x03d7dc4, 0x1959363, 0x185bcc1, 0x1c00ac9, 0x1a57915,
|
|
0x0aa748a, 0x0dec630, 0x101b28e, 0x00fa993, 0x101d71c, 0x00ebf23,
|
|
0x018f882, 0x088fb6a, 0x146faa9, 0x13f4c51, 0x12a13df, 0x1d0bb73,
|
|
0x0715479, 0x0efe980, 0x106215b, 0x0eac449, 0x1cc64f2, 0x08e3574,
|
|
0x18e57cd, 0x01f5f02, 0x0f8dd91, 0x083d020, 0x02833ac },
|
|
{ 0x1a5ec5c, 0x125c346, 0x0c91f95, 0x103811b, 0x0c3d9da, 0x0bd3945,
|
|
0x07c2e31, 0x1853af8, 0x19d343d, 0x08957f3, 0x180ce4d, 0x099ffb8,
|
|
0x01b438e, 0x0e7d0ca, 0x1689c03, 0x00892fa, 0x1f82732, 0x16af991,
|
|
0x0e4f1b9, 0x0f4b1c2, 0x04311b8, 0x08825d5, 0x1b2da2f, 0x04569af,
|
|
0x01c5a47, 0x1d5604e, 0x1c81ad7, 0x085f552, 0x16327ef, 0x1e6b4cb,
|
|
0x1678772, 0x010ef0f, 0x15ba9e4, 0x000c8b2, 0x1d5f797, 0x117ab38,
|
|
0x0bcf353, 0x1810768, 0x18c0d9c, 0x0a9493a, 0x0120cd4 },
|
|
{ 0x0b0f9ee, 0x0dc7a65, 0x03bbaff, 0x00599cb, 0x1c003ef, 0x068332d,
|
|
0x1a1056a, 0x0e936d4, 0x09b9577, 0x01769d3, 0x06ad719, 0x0fe08e4,
|
|
0x133de48, 0x10d2786, 0x0bfce00, 0x1bb9bde, 0x15829db, 0x15e8b7a,
|
|
0x1a4f7fc, 0x00b6961, 0x0ec12ef, 0x0905e4d, 0x1787ea8, 0x0cff525,
|
|
0x0e2c2d4, 0x11a336d, 0x117accf, 0x0b1b5ec, 0x0103cb7, 0x0cfb478,
|
|
0x0c299eb, 0x137c048, 0x11f693a, 0x02a5e0a, 0x125bad0, 0x1daad30,
|
|
0x1019336, 0x18b3bf3, 0x1a8fa3b, 0x02cffbd, 0x0021cfd },
|
|
{ 0x15c36f3, 0x1b8afef, 0x095171c, 0x0fac95a, 0x103bde3, 0x07bb89b,
|
|
0x03443cb, 0x190aa6d, 0x10f3993, 0x12f63db, 0x0b93287, 0x0eec609,
|
|
0x0bfdb16, 0x1e9dd8c, 0x03dc5f8, 0x07ab41b, 0x13f6634, 0x0a93383,
|
|
0x158022d, 0x16a5de2, 0x070ffae, 0x1c91252, 0x0e5eb57, 0x0556a35,
|
|
0x0e391ed, 0x01657c3, 0x1e65d0c, 0x1818fca, 0x0ae28ad, 0x140bfe8,
|
|
0x073223e, 0x17f1dab, 0x07c22df, 0x145db40, 0x08c7ac4, 0x06bbdb8,
|
|
0x020595a, 0x16e6ce5, 0x1de39c7, 0x08d8e79, 0x007265b },
|
|
{ 0x166232f, 0x0ccf85e, 0x1c59cf7, 0x138804e, 0x059aaf8, 0x0307e26,
|
|
0x1b7e96e, 0x0775f04, 0x07a943f, 0x1cf5455, 0x110a348, 0x1634a47,
|
|
0x1a0e0e1, 0x14b9dca, 0x1a838e9, 0x0ea76ab, 0x0aa2557, 0x1f51cce,
|
|
0x1a55ec7, 0x1bee5e0, 0x0302f8a, 0x009de9a, 0x00e27cd, 0x148752e,
|
|
0x127d0f8, 0x0b7999f, 0x02b6bde, 0x1b38181, 0x012aa2c, 0x124da4e,
|
|
0x1a5b732, 0x0f4158d, 0x188deee, 0x004076e, 0x1d74191, 0x1b1e8ea,
|
|
0x0cc2f4b, 0x0eb33e8, 0x125b1ba, 0x09663a2, 0x036c575 },
|
|
{ 0x123d84b, 0x0023779, 0x113e448, 0x04fcf13, 0x0699112, 0x0dc02ad,
|
|
0x0bd3a48, 0x09c961d, 0x0807997, 0x19cc225, 0x1e31e58, 0x0cd4e81,
|
|
0x09c9054, 0x06b6f7a, 0x06343df, 0x1c97438, 0x06b4b23, 0x0a94bed,
|
|
0x1060031, 0x13bfe78, 0x07771c0, 0x0d9bf7b, 0x1b1241d, 0x0a27bda,
|
|
0x03a4050, 0x182d4a6, 0x05ac2c5, 0x1ace85d, 0x0af5ae3, 0x024a624,
|
|
0x17b01e1, 0x192b045, 0x0c01532, 0x06ca7a0, 0x1797059, 0x0b45bb5,
|
|
0x02975eb, 0x054564d, 0x0513bf2, 0x0c2328d, 0x006fbf8 },
|
|
{ 0x145aa97, 0x099c71f, 0x1facb59, 0x103a081, 0x183b58c, 0x0f7c5ce,
|
|
0x1d66c3f, 0x0f80bfd, 0x0e4d741, 0x1f5838d, 0x08688de, 0x03eb661,
|
|
0x03982b6, 0x1db2de8, 0x17ca8ab, 0x0d7e698, 0x09d5cbf, 0x0f2055e,
|
|
0x01984a9, 0x1864dbe, 0x0e28422, 0x0ecab8d, 0x124879a, 0x1a6869d,
|
|
0x0b10b23, 0x099be44, 0x1e7681e, 0x0da5d2a, 0x19cf4d9, 0x03509b0,
|
|
0x0860cf5, 0x1b2bddf, 0x1d19653, 0x147876c, 0x104680f, 0x0254fb0,
|
|
0x04bb5ab, 0x1214a98, 0x0a7a979, 0x1fa3e1f, 0x05e9ca0 },
|
|
{ 0x17c5dc4, 0x0a2b88c, 0x16896f5, 0x1fcf152, 0x02da40b, 0x0d87597,
|
|
0x07bf3ff, 0x0f8cbf7, 0x00d1746, 0x0a96e16, 0x031a8fa, 0x18f78eb,
|
|
0x1ac1fc9, 0x0a01a54, 0x1e558b3, 0x096adf8, 0x1be61f6, 0x19371b7,
|
|
0x1a11ca2, 0x18973c3, 0x0c8a6ad, 0x09d47cd, 0x1fc597f, 0x1c7c026,
|
|
0x13a4503, 0x071bde4, 0x0d9591e, 0x1598aa2, 0x0ddc77e, 0x0b8b832,
|
|
0x0534ce4, 0x0ed26d2, 0x1b318dc, 0x012533a, 0x071cd89, 0x08d363e,
|
|
0x09955f3, 0x01022da, 0x1abe233, 0x1678d06, 0x0940622 },
|
|
{ 0x1997973, 0x0665b86, 0x04551c4, 0x1ba7f1e, 0x1b29625, 0x0bd5ea9,
|
|
0x113556e, 0x14b19e1, 0x0673e14, 0x1190f05, 0x18891b1, 0x1f3a7a4,
|
|
0x110541a, 0x17e41d8, 0x1b61d51, 0x0a549bc, 0x1a8f016, 0x123f4be,
|
|
0x16600ad, 0x05674d5, 0x04b20f8, 0x1ad74e2, 0x1a6a901, 0x1a57eee,
|
|
0x15de2ce, 0x06d579f, 0x0925e90, 0x1de3d51, 0x03ba9c1, 0x03041e1,
|
|
0x120b83e, 0x1e32145, 0x0a998a4, 0x119b46c, 0x12333f7, 0x03c5693,
|
|
0x1de6bd7, 0x1a4c125, 0x1b6dae7, 0x0c8f0b7, 0x080bb16 },
|
|
{ 0x1145cb5, 0x0baff7e, 0x020c179, 0x0358bcd, 0x155ee56, 0x09d9398,
|
|
0x1c33e1e, 0x0708c3c, 0x0133b23, 0x18aa9ef, 0x1ee81e7, 0x0187454,
|
|
0x1a2fb9e, 0x1f38437, 0x0ff5aa0, 0x1972787, 0x1008bb4, 0x0db5d42,
|
|
0x1be0b6f, 0x0daf12e, 0x09ff0b6, 0x1b2a75a, 0x1f569bf, 0x0416644,
|
|
0x1d2371f, 0x06e66b2, 0x09538a7, 0x13d4938, 0x118ff97, 0x0cb1e58,
|
|
0x02d925d, 0x198b000, 0x09598dd, 0x03bce4b, 0x0460443, 0x0b2a20f,
|
|
0x03b85a3, 0x1e0aa43, 0x08d43b7, 0x1d48242, 0x0077ba5 },
|
|
{ 0x1d86f61, 0x11c69e6, 0x02ac2ce, 0x0a0a054, 0x0312144, 0x1681392,
|
|
0x1b71601, 0x01e3225, 0x08a32f1, 0x0ee0fcc, 0x031d800, 0x03a21d0,
|
|
0x13bb1d3, 0x1a32745, 0x1bb1f97, 0x093dda8, 0x1369abf, 0x1eab4d7,
|
|
0x136b79d, 0x10dd4e5, 0x19209d2, 0x06a2d6a, 0x0af9c08, 0x1335cfe,
|
|
0x1236e62, 0x003d5f2, 0x174fd57, 0x1262f37, 0x150e80c, 0x0cad291,
|
|
0x01a04e2, 0x15fe0eb, 0x101265c, 0x1cb2984, 0x06cbd1c, 0x02b6790,
|
|
0x1bc77d2, 0x1bac0ec, 0x08b8aeb, 0x1be8b23, 0x06b2006 },
|
|
{ 0x05b1bc1, 0x128544b, 0x13f6cbf, 0x152c576, 0x131f536, 0x073fccc,
|
|
0x034cc00, 0x0bdaae3, 0x153d512, 0x0394792, 0x0972be1, 0x0309a42,
|
|
0x1e4f8a6, 0x1abfb3c, 0x1c69c04, 0x180b4a9, 0x00c1531, 0x0b854fa,
|
|
0x1ea2ddd, 0x01972ed, 0x0ce910d, 0x0f4ee09, 0x0d1dbd0, 0x0abf129,
|
|
0x17a7527, 0x0d22e46, 0x01895d0, 0x0d825c2, 0x17b16cd, 0x17dc648,
|
|
0x08098a9, 0x071ad61, 0x0d116e6, 0x1c74192, 0x0300cb0, 0x19092a8,
|
|
0x06868af, 0x0dc88e3, 0x0d54215, 0x14d7a4d, 0x053217e },
|
|
{ 0x19f52b4, 0x0023992, 0x11b3f21, 0x17cc422, 0x168da9c, 0x05e9374,
|
|
0x0e17b2b, 0x0892c9d, 0x1e4a543, 0x1bed516, 0x093fdea, 0x1090703,
|
|
0x0f6dc3b, 0x00e40af, 0x1ea5acd, 0x163c340, 0x1e8c3d4, 0x0627d74,
|
|
0x0b3a7aa, 0x071a3c8, 0x052f0f9, 0x061ae60, 0x09c9f6b, 0x140de0f,
|
|
0x001c9e9, 0x0d0e40f, 0x0d29b59, 0x13c11b9, 0x04a9a6a, 0x08b9b02,
|
|
0x16fe38b, 0x1e57a52, 0x1893dd0, 0x00d894c, 0x0de7e5e, 0x05411a6,
|
|
0x01830ac, 0x1eb000b, 0x0fbbd92, 0x03db35b, 0x0038693 },
|
|
{ 0x09885a5, 0x1d5d9e8, 0x0c1f435, 0x0fc6ab7, 0x0d9d2b6, 0x175d76f,
|
|
0x0e33d4d, 0x1ac7784, 0x0699ce4, 0x0e5173c, 0x1653358, 0x088e222,
|
|
0x12354ff, 0x0198b56, 0x12f9c24, 0x1eb88ab, 0x1fd49ff, 0x020c33c,
|
|
0x1e71b10, 0x159aea1, 0x121a75b, 0x0414b93, 0x19dfb72, 0x1dea05e,
|
|
0x16887e5, 0x107412c, 0x1efcc83, 0x0b3d26c, 0x1dccb24, 0x1b77c5d,
|
|
0x0f60738, 0x16ecd0c, 0x1a097fc, 0x036dc0d, 0x075b563, 0x179a744,
|
|
0x14a8748, 0x04b3e6d, 0x0708039, 0x0922a08, 0x02caaf7 },
|
|
{ 0x0d20424, 0x0c00337, 0x151513e, 0x06448e2, 0x13e4ea2, 0x0d46435,
|
|
0x14695e0, 0x0164d1d, 0x17ae5b7, 0x06855ba, 0x14e6092, 0x06406ad,
|
|
0x046ca8b, 0x16f98fd, 0x1a39a04, 0x1b9e539, 0x032d925, 0x15c84e9,
|
|
0x159c8f7, 0x191ef1e, 0x16f9302, 0x14d5d64, 0x045c975, 0x1a342e0,
|
|
0x047ca57, 0x1f3b2b5, 0x070628a, 0x176baa2, 0x10d9d96, 0x02f8d6a,
|
|
0x062d5b9, 0x0e160aa, 0x0e886e2, 0x07fc89b, 0x1cf4276, 0x1d8f8e3,
|
|
0x1350361, 0x10ddf14, 0x0ef6196, 0x0648bfc, 0x086d7f5 },
|
|
{ 0x0bf719a, 0x0b75b58, 0x044e67c, 0x111787b, 0x1697509, 0x0680da5,
|
|
0x039489b, 0x039f5ca, 0x090898d, 0x1f1d62a, 0x1b199b4, 0x13b710f,
|
|
0x184da3b, 0x1df522d, 0x0c01913, 0x160b0b0, 0x1d98355, 0x19b4f9d,
|
|
0x1e6f304, 0x047350a, 0x18110fb, 0x1cb715e, 0x13d6d14, 0x0331fa4,
|
|
0x13baf24, 0x08e803f, 0x0e20df5, 0x114cedb, 0x075b166, 0x1531757,
|
|
0x0f1a3bb, 0x07b6c10, 0x1fe5f94, 0x1b62d2f, 0x143df60, 0x0aa5929,
|
|
0x0bc1ff8, 0x061e37e, 0x0d37569, 0x1c70d81, 0x0682a55 },
|
|
{ 0x07495aa, 0x11ad22c, 0x117723c, 0x18698e4, 0x0276026, 0x0d23719,
|
|
0x03316dd, 0x1cfad5c, 0x1ecc3e5, 0x0869cb2, 0x0598a62, 0x085e285,
|
|
0x071b133, 0x0543b91, 0x0649f9a, 0x14d1791, 0x07e2324, 0x10aa1f9,
|
|
0x0737086, 0x08ed089, 0x10ac6c4, 0x078a296, 0x06f1ff5, 0x09608b9,
|
|
0x10a31ff, 0x1089661, 0x0214bdd, 0x02ba8d4, 0x1dd7a64, 0x1829637,
|
|
0x046b5cd, 0x0f698f9, 0x0ecc3ab, 0x06b866e, 0x006dda2, 0x0ba59be,
|
|
0x040d390, 0x0792a17, 0x1373415, 0x14dfdfc, 0x002227f },
|
|
{ 0x151948b, 0x0f7ecdb, 0x0974601, 0x0dfbfa4, 0x0efeed4, 0x1645914,
|
|
0x038253c, 0x1cb9625, 0x196f7c5, 0x088485f, 0x0fb2827, 0x0089699,
|
|
0x040959d, 0x0704658, 0x12557e6, 0x09f9c43, 0x19d68fa, 0x15e0f93,
|
|
0x1c42ba6, 0x03c29c0, 0x07f4b02, 0x0fc408b, 0x19345ba, 0x193e34a,
|
|
0x1c22ebb, 0x1757ad2, 0x1f8d083, 0x1e6e2db, 0x04e8435, 0x1c8aeae,
|
|
0x0065c7a, 0x051ff75, 0x0fc55fc, 0x1babc32, 0x1535f74, 0x00684fc,
|
|
0x15ebc7d, 0x1735310, 0x05de111, 0x134524d, 0x0547e24 },
|
|
{ 0x1ffda27, 0x1434550, 0x1d411c1, 0x18f2ab9, 0x14e6cdc, 0x11f9ec5,
|
|
0x1478429, 0x015eca2, 0x09de5e7, 0x1a093f5, 0x10a08d6, 0x1375f26,
|
|
0x113d2c0, 0x1517bea, 0x126760e, 0x1804a31, 0x11dddee, 0x15062dd,
|
|
0x0f73c73, 0x1bbf080, 0x1eda7ff, 0x14b0b7e, 0x195f934, 0x06543e1,
|
|
0x1656979, 0x071e922, 0x00c6475, 0x08ebc1d, 0x00218b7, 0x1f50e11,
|
|
0x014d1e6, 0x117964a, 0x0eb5c90, 0x099737e, 0x13a8f18, 0x1638d0b,
|
|
0x1fe6c1e, 0x16e3a2d, 0x03bab10, 0x181a561, 0x045a41c },
|
|
{ 0x1bbf0e1, 0x0d963a6, 0x1c38faa, 0x1f42f9e, 0x01ff962, 0x15a6332,
|
|
0x09d617b, 0x0fdb83d, 0x0a9beb1, 0x1aa0969, 0x15d0693, 0x1ea5450,
|
|
0x1f2c9e4, 0x0c27e88, 0x17df692, 0x0309d27, 0x1dc0df3, 0x0d957de,
|
|
0x10878dd, 0x047a4a4, 0x181e963, 0x1224efb, 0x121ef87, 0x0b137d5,
|
|
0x001ed3d, 0x16e8a2b, 0x14a3ffd, 0x1e17b37, 0x0f298c0, 0x0cea450,
|
|
0x110b4c9, 0x1b11cd2, 0x02d7a77, 0x0157b1b, 0x1adadab, 0x0550980,
|
|
0x1087da0, 0x028564e, 0x10322ea, 0x19285dc, 0x0128763 },
|
|
{ 0x0bac178, 0x00783d6, 0x1db8a6a, 0x0869611, 0x1cc2004, 0x1f6f693,
|
|
0x07451c3, 0x0cfd2c6, 0x1866157, 0x108aed1, 0x021522c, 0x0b89961,
|
|
0x037c75f, 0x0d17470, 0x0a7484e, 0x02ea4b6, 0x0668b88, 0x07f4fed,
|
|
0x0779faf, 0x1b1b118, 0x01233f1, 0x0f0190c, 0x0d1d959, 0x1932be7,
|
|
0x05561b1, 0x18d839b, 0x02c4fad, 0x02c1963, 0x13a0eb2, 0x1289ccd,
|
|
0x1d1fa36, 0x1641f9a, 0x08ca1f9, 0x136b92f, 0x019ed04, 0x1ed4fc0,
|
|
0x08bb637, 0x01025bb, 0x1d3487a, 0x199f89e, 0x075e96b },
|
|
{ 0x119716e, 0x08fee06, 0x1494627, 0x10f8708, 0x1f58505, 0x0c3e956,
|
|
0x11b47aa, 0x01ec950, 0x16c0715, 0x15b5fc1, 0x1f56dc4, 0x1a8c9ad,
|
|
0x1f91d85, 0x07a9faa, 0x1e220d9, 0x1225352, 0x1d88150, 0x030041d,
|
|
0x0a1dbd2, 0x0e4d07d, 0x0489a76, 0x1d60ad9, 0x1a02cb9, 0x1a3b325,
|
|
0x0f8d242, 0x0494c2f, 0x073cf79, 0x18af605, 0x0876279, 0x1c1e58a,
|
|
0x01ff80b, 0x115cb6d, 0x0ba4fe4, 0x1c0cb57, 0x026d75a, 0x1b150de,
|
|
0x016e523, 0x07ab35d, 0x0252762, 0x135744d, 0x0309a6e },
|
|
{ 0x1fbe97a, 0x1f7285e, 0x1137bc9, 0x1f718a1, 0x1a5fe70, 0x104fae0,
|
|
0x1ac05ff, 0x18b98f7, 0x1bed36c, 0x1d0ad42, 0x03b4ea3, 0x19b6eaa,
|
|
0x01c0c3a, 0x15c8434, 0x007be1f, 0x0b9978b, 0x162c49d, 0x050ad99,
|
|
0x1e8993a, 0x162e283, 0x0e880fb, 0x07c70f7, 0x099fe36, 0x1856c7a,
|
|
0x0cfd621, 0x17ee98e, 0x154ef9f, 0x049b7cf, 0x0a358a9, 0x03bfed9,
|
|
0x10750ba, 0x0ebad15, 0x19673c7, 0x1f52ae7, 0x03f5c53, 0x05c6b2f,
|
|
0x1769b20, 0x19b329a, 0x0de27ba, 0x115aeb2, 0x0045825 },
|
|
{ 0x042dbdf, 0x18d3a50, 0x1e8977d, 0x0eaef3b, 0x0d40585, 0x17332b9,
|
|
0x12e9c34, 0x05c1ccd, 0x1ca2e89, 0x02eb3a2, 0x19ad7ca, 0x1bde1e1,
|
|
0x03f56a8, 0x1183b3e, 0x1ba1476, 0x0d739c1, 0x0584334, 0x14c602b,
|
|
0x1acf1d0, 0x1f9c4da, 0x1e00b35, 0x1f9cbbb, 0x102256f, 0x16db10d,
|
|
0x0f6a6e7, 0x025c1e4, 0x0d3c0a4, 0x1dc2908, 0x04ec34b, 0x08ad974,
|
|
0x045fdd2, 0x12da213, 0x0af663c, 0x1d6605d, 0x1d5f907, 0x1200970,
|
|
0x0f86c02, 0x1c4072b, 0x1cd628a, 0x1c12b6e, 0x053f4a3 },
|
|
{ 0x1fc48e7, 0x1846744, 0x0bac46e, 0x0f5f56b, 0x1a60c57, 0x00e5ad5,
|
|
0x12fe283, 0x16de0d7, 0x079757c, 0x0977d75, 0x064581f, 0x0162ec6,
|
|
0x09e26d9, 0x15bbdbd, 0x0a86ad8, 0x1e57e85, 0x0cd285d, 0x01c7760,
|
|
0x0ea3dfc, 0x128febe, 0x15b5d35, 0x077e0e5, 0x05f2370, 0x0b08b9f,
|
|
0x0cca0c4, 0x1797f5c, 0x0492789, 0x0dd1b31, 0x1ed89a1, 0x0736a41,
|
|
0x1cdf099, 0x0a3b220, 0x1a3f145, 0x14cf809, 0x18b8c17, 0x070a02a,
|
|
0x0908d56, 0x1cc6ba3, 0x148daab, 0x0a7ae47, 0x00a99e6 },
|
|
{ 0x1bc0559, 0x1b7a355, 0x05808d4, 0x1735434, 0x0163067, 0x0b40dae,
|
|
0x148a430, 0x00e453f, 0x11378e9, 0x092a5f0, 0x04e8b58, 0x0af556f,
|
|
0x1bc60ff, 0x0332a96, 0x1cb7e2d, 0x0146d4d, 0x0938c17, 0x14d698c,
|
|
0x06dd366, 0x1b357c5, 0x0523c5c, 0x19fbc24, 0x13dd1c9, 0x01c60c7,
|
|
0x0a93a0d, 0x1ec6093, 0x0d09238, 0x1c4043c, 0x03ddfaf, 0x01f7419,
|
|
0x19f65cd, 0x0664c73, 0x1768775, 0x12aa44f, 0x10c5d4c, 0x152ca1f,
|
|
0x1eebf7e, 0x0aede89, 0x12f02d6, 0x08a021f, 0x03a95cb },
|
|
{ 0x1d7ff2e, 0x134659c, 0x123e553, 0x1783ab8, 0x0dd1cb4, 0x14a1c54,
|
|
0x0b1ddc5, 0x19c0552, 0x091cad8, 0x0b2e058, 0x142349e, 0x1156659,
|
|
0x1a0c579, 0x134815e, 0x16f0f0e, 0x1a43034, 0x1255186, 0x1aa2e84,
|
|
0x09f9936, 0x0ef9b7a, 0x12daf00, 0x1246684, 0x0055f2a, 0x0a65566,
|
|
0x1a3a024, 0x1d19517, 0x0d0732a, 0x0bf6c73, 0x04aee6a, 0x16e0a3a,
|
|
0x16805c0, 0x19b7527, 0x05bb436, 0x1c278a4, 0x1d98ca5, 0x0726b2f,
|
|
0x1ad672c, 0x189e0ee, 0x1c91575, 0x05c0616, 0x0366d22 },
|
|
{ 0x13ea5b2, 0x1a43aab, 0x1137542, 0x17521b4, 0x0fce401, 0x0d01880,
|
|
0x1e995e8, 0x0c0f6a7, 0x1cf1144, 0x1154052, 0x02fd25c, 0x1e0b4a7,
|
|
0x010b8eb, 0x0995669, 0x050451f, 0x1a0fb5c, 0x12c7b5a, 0x1b34938,
|
|
0x1d23281, 0x0bfdce7, 0x18d86dc, 0x0c95c53, 0x063b452, 0x05e2eb3,
|
|
0x13145dd, 0x1c72745, 0x057e5c6, 0x06811bc, 0x11b3684, 0x136ed6f,
|
|
0x1f8157a, 0x1cb2656, 0x1b76e73, 0x049fea5, 0x054f4c2, 0x148850e,
|
|
0x0661bfd, 0x1ee6690, 0x1f4945c, 0x132f3bd, 0x09072ba },
|
|
{ 0x020ea39, 0x0f26ecb, 0x1ba11d3, 0x1f90639, 0x1bf1649, 0x1d4e21f,
|
|
0x02ec734, 0x1aa161d, 0x13f3df1, 0x11c1437, 0x1b26cda, 0x05671e1,
|
|
0x034ed07, 0x194e04f, 0x193261d, 0x044854d, 0x0c68ad1, 0x1751f45,
|
|
0x0f7e96e, 0x01c457f, 0x15926ae, 0x07d8507, 0x1585c7b, 0x10e3f1a,
|
|
0x0886d6b, 0x1ed19d9, 0x04d7846, 0x16337d5, 0x0f153f6, 0x0d203f8,
|
|
0x1b93605, 0x0fad805, 0x0608d97, 0x047a33f, 0x0f66daa, 0x08fd1e4,
|
|
0x039d165, 0x164b292, 0x1b0a49a, 0x17a6aa8, 0x08d92c6 },
|
|
{ 0x1eb0ff7, 0x06be755, 0x0be2cf8, 0x087c1c8, 0x1be3525, 0x00424cf,
|
|
0x0c89b7a, 0x186afa3, 0x11cd44b, 0x167170f, 0x13fb867, 0x1b7886b,
|
|
0x1c1245a, 0x1c9fac0, 0x13ba103, 0x1728f0e, 0x19cbda0, 0x148b53b,
|
|
0x095eb82, 0x1902b5f, 0x01b0abc, 0x16f8531, 0x05eb7b0, 0x1f217b9,
|
|
0x0502b81, 0x11edf35, 0x054ef79, 0x097f3bc, 0x084c255, 0x0d5fbc4,
|
|
0x1c2a23f, 0x19776a8, 0x0aa52b1, 0x09f7a98, 0x05b0a41, 0x15f00a7,
|
|
0x0dd827e, 0x01ec4c4, 0x1970235, 0x02eb835, 0x04e4bec },
|
|
{ 0x0c09676, 0x041d17e, 0x0a52fe1, 0x1e33d53, 0x057c4a3, 0x0152eea,
|
|
0x0bbcf5c, 0x1b14d0a, 0x0843fe7, 0x1c8afe9, 0x0d45639, 0x15302dc,
|
|
0x10644bb, 0x0f6ba37, 0x06e5742, 0x1e16b1a, 0x181b90a, 0x123b822,
|
|
0x13f44d7, 0x0978d7a, 0x13a50bd, 0x13da741, 0x09b7381, 0x0ad5343,
|
|
0x08f30ff, 0x1ff1607, 0x03b0b18, 0x1390100, 0x1508a8a, 0x1052cc7,
|
|
0x0e91270, 0x0652502, 0x0b94cb3, 0x140d101, 0x14a3b1f, 0x0ec8fc7,
|
|
0x1487767, 0x133e8d5, 0x1b491cb, 0x1eadf3b, 0x07a4aa3 },
|
|
{ 0x07a0045, 0x178dd71, 0x0d41567, 0x1f64859, 0x1c812d4, 0x07c6926,
|
|
0x1e390e7, 0x0a84748, 0x19b3f9c, 0x1aa27e2, 0x087f3e5, 0x02655ff,
|
|
0x1b5ac68, 0x1a51641, 0x1e3fb80, 0x0976ee9, 0x00fcd3f, 0x14b6632,
|
|
0x0144ba9, 0x1b9d3b6, 0x181e775, 0x0ee6e71, 0x19f7286, 0x1a7fcaa,
|
|
0x0b3f3a9, 0x1a7e0f7, 0x0868649, 0x11c17e8, 0x169b123, 0x17da146,
|
|
0x1e05664, 0x13fa13b, 0x0fcebde, 0x15aefa4, 0x093ed06, 0x0bb93bf,
|
|
0x00a269c, 0x1ebee46, 0x0b78432, 0x0f7efe1, 0x060282a },
|
|
{ 0x0eea2e7, 0x1f29c6e, 0x1875f01, 0x1078840, 0x18a322c, 0x0fb28b1,
|
|
0x0a3e53c, 0x020ced0, 0x1c7776a, 0x10db4fd, 0x1ad017c, 0x082f6bc,
|
|
0x02c63a3, 0x08d3db2, 0x067c962, 0x0288099, 0x0a82cad, 0x09c3496,
|
|
0x021a6f3, 0x105ffc0, 0x066af1e, 0x070b7f2, 0x10c2dc5, 0x0032271,
|
|
0x142f919, 0x1572fdb, 0x003e945, 0x1202cda, 0x073a43e, 0x1bd66c6,
|
|
0x1c95543, 0x1f78b86, 0x16a407d, 0x01cf696, 0x14e5a33, 0x01c8f4e,
|
|
0x0a5fbe7, 0x09436ca, 0x0e508ff, 0x18e478d, 0x05f4ae9 },
|
|
{ 0x1f4d561, 0x116ed29, 0x064b65a, 0x002db43, 0x086d45d, 0x0a58289,
|
|
0x007eff7, 0x1d48934, 0x19f2195, 0x0a44506, 0x1986cc9, 0x161546e,
|
|
0x02c4151, 0x1cf2f70, 0x0311c7b, 0x1102f73, 0x06ea865, 0x1525e54,
|
|
0x09a3f02, 0x15b70ef, 0x06a9bbc, 0x04b5b9b, 0x022cd19, 0x0cc385b,
|
|
0x098d415, 0x1061977, 0x1b24050, 0x0b67698, 0x0752aff, 0x139a979,
|
|
0x07288d4, 0x0a21c9b, 0x164ce73, 0x0554017, 0x1c9ab29, 0x072734f,
|
|
0x001aa50, 0x09f148a, 0x0bf4a73, 0x047b88d, 0x092a014 },
|
|
{ 0x02f7dbd, 0x125f08e, 0x1feba7c, 0x1f6faa4, 0x1a8c900, 0x0478946,
|
|
0x096ee19, 0x0832c7c, 0x0481419, 0x15b89f1, 0x1d5bee6, 0x1a02f4c,
|
|
0x1de87f7, 0x02c6c85, 0x1376178, 0x0d57a4e, 0x07a8256, 0x0c11ff7,
|
|
0x1090065, 0x0461aee, 0x046e9f6, 0x16565af, 0x0115e7c, 0x14990fc,
|
|
0x0626316, 0x02b9511, 0x0f666c2, 0x1943348, 0x08789e9, 0x15d1f24,
|
|
0x0f61b70, 0x1280d87, 0x160b5b9, 0x04abf7c, 0x0a2e258, 0x16de588,
|
|
0x161c515, 0x1a43830, 0x12e6e41, 0x03d5511, 0x00fc8fe },
|
|
{ 0x0b90f2d, 0x10df6ff, 0x1565a2b, 0x1949162, 0x1393bb3, 0x074b1af,
|
|
0x0be73d9, 0x18457cc, 0x0f8be75, 0x0a61208, 0x1dd4a4d, 0x0e06bcd,
|
|
0x11bd7ea, 0x0b16559, 0x1921a38, 0x1e7ff84, 0x070c860, 0x1589c8f,
|
|
0x16260df, 0x0cf8ea3, 0x0941df3, 0x1a15f99, 0x18542da, 0x182631f,
|
|
0x0f46e78, 0x0b04af4, 0x0e8b12c, 0x167e3b5, 0x1afbf32, 0x1ae7380,
|
|
0x1171b33, 0x0bd10e9, 0x0d27530, 0x16e5f1d, 0x1945771, 0x1a7250b,
|
|
0x199892d, 0x0aa6c36, 0x1e27cf2, 0x0c5bfa6, 0x02d0ba8 },
|
|
{ 0x072e1af, 0x0c7745a, 0x0f33ab3, 0x1d6ed57, 0x0b354ea, 0x0c9fdef,
|
|
0x02fe343, 0x00d36a4, 0x1fe6fc7, 0x066b06b, 0x18bce7f, 0x1bbd49d,
|
|
0x1ea9353, 0x0d40f28, 0x0c2497a, 0x0ceeebd, 0x1a1d136, 0x0f719a6,
|
|
0x14d535a, 0x05193fa, 0x0d54c1d, 0x0ac952f, 0x0e5dc5d, 0x1ee1b03,
|
|
0x0367fb7, 0x13d2e9f, 0x0aa4ceb, 0x17cfdd9, 0x1cfbb77, 0x18fcf11,
|
|
0x0049933, 0x11292ed, 0x1129f4a, 0x111ad86, 0x169026d, 0x14e0a6e,
|
|
0x08a376d, 0x1b263aa, 0x16ff333, 0x0249a83, 0x0963c87 },
|
|
{ 0x036a814, 0x14865ef, 0x0ad6eb8, 0x0ae6762, 0x1bdb019, 0x1ff070c,
|
|
0x1619fdd, 0x1d41d75, 0x129720c, 0x13e8cfe, 0x07b1c82, 0x0ca3205,
|
|
0x1e434d7, 0x1da8c88, 0x1abfc5e, 0x0fec10a, 0x19ad80a, 0x168512e,
|
|
0x0123041, 0x150d5ff, 0x149cffc, 0x1ca1d6b, 0x14fa2f7, 0x1cd2d76,
|
|
0x00284e3, 0x10afdcf, 0x0bbbb90, 0x1d6cc61, 0x0f3c633, 0x1dcf176,
|
|
0x102763e, 0x09c0181, 0x1da4ffa, 0x1df5638, 0x1965755, 0x1f652d7,
|
|
0x08cec7e, 0x08fdd6d, 0x15ef45d, 0x079feab, 0x02d03eb },
|
|
{ 0x0f2ec1d, 0x1492f82, 0x1b8bac5, 0x0c1a28f, 0x0878f27, 0x0cecf05,
|
|
0x1d812ab, 0x0b6885b, 0x13f7103, 0x08efa25, 0x05756e2, 0x0567197,
|
|
0x03c2827, 0x0f74769, 0x053bed5, 0x1e7c6de, 0x00f13b0, 0x179e223,
|
|
0x0f5ccd7, 0x1f37aed, 0x1a6e889, 0x18fbaad, 0x0227b9d, 0x04336d9,
|
|
0x184feed, 0x008b134, 0x1fb0bb9, 0x1a898e6, 0x0fcd372, 0x02d131f,
|
|
0x1aee50e, 0x0cc6f04, 0x109321b, 0x15bd3ec, 0x09e4fb9, 0x0f849f1,
|
|
0x07cf61b, 0x0546925, 0x0b3668f, 0x1838a97, 0x0842e40 },
|
|
{ 0x061d843, 0x1476b53, 0x0335689, 0x149eb66, 0x02328cc, 0x08f0bb8,
|
|
0x1fb444c, 0x0ce2dcd, 0x0c66959, 0x086f65a, 0x0b8a01a, 0x17ecaf6,
|
|
0x10bdac5, 0x0f7f216, 0x1fe0b28, 0x1945f04, 0x00aca5f, 0x162aa76,
|
|
0x1791541, 0x04ed83b, 0x1513ac5, 0x047183b, 0x0dfd32c, 0x10f2f99,
|
|
0x16d9acc, 0x1694657, 0x10364cc, 0x0b2c902, 0x1a409fd, 0x114b942,
|
|
0x04f31ab, 0x0c447a1, 0x173c2a5, 0x07e04bb, 0x1ab144a, 0x185aa4c,
|
|
0x1c31fe6, 0x0b5be5d, 0x04ca296, 0x1359592, 0x00e6331 },
|
|
{ 0x0360ac2, 0x097d6f8, 0x016ad73, 0x1c50bcc, 0x06b660d, 0x0dcd8a4,
|
|
0x13c4389, 0x0a9058d, 0x1aa9ac5, 0x0afd1c6, 0x101c3a7, 0x0370a4d,
|
|
0x0d3dfcf, 0x1fe6629, 0x1e6a5ac, 0x18fea06, 0x0290bfc, 0x0f1b2ce,
|
|
0x074f9a8, 0x147b6ad, 0x02d55b1, 0x1acdbda, 0x0d054a2, 0x045400d,
|
|
0x1efa49c, 0x1db49a6, 0x026d338, 0x01e7003, 0x0baf329, 0x1e0259d,
|
|
0x18ac1ce, 0x1ff0713, 0x1a5a222, 0x0d1ad93, 0x1547fe9, 0x0416f53,
|
|
0x08e1a7c, 0x1cf6779, 0x1c16924, 0x14430e4, 0x088839d },
|
|
{ 0x01ce29a, 0x1361838, 0x15415ad, 0x0cb1303, 0x1acaf12, 0x0fcf909,
|
|
0x1f03041, 0x027a9b5, 0x0373e3d, 0x172b8f3, 0x1b8f2bf, 0x190df45,
|
|
0x1ae7269, 0x0e901c2, 0x132992b, 0x1d359eb, 0x1573000, 0x190bf93,
|
|
0x19c9cfb, 0x09b68e1, 0x0776c93, 0x1b9aadb, 0x10a53d3, 0x180a300,
|
|
0x036b96f, 0x0858fd5, 0x0ec1486, 0x1f1163b, 0x0aef528, 0x0dc874f,
|
|
0x040d5e4, 0x1b6d037, 0x17fb2eb, 0x0e1b4f9, 0x1475105, 0x1273a14,
|
|
0x1d2e21c, 0x0ce6538, 0x0309bf1, 0x1fd43ea, 0x064128c },
|
|
{ 0x0f5b0b5, 0x13c5174, 0x0167c0d, 0x19a681e, 0x1c7e249, 0x053e762,
|
|
0x011064f, 0x1308288, 0x0bc83af, 0x1ae51a3, 0x02eec01, 0x0067f55,
|
|
0x17f39f0, 0x19c1187, 0x063c3b7, 0x1e68a7a, 0x00cd448, 0x0bc6ff8,
|
|
0x146a91d, 0x045181a, 0x08d1849, 0x0418649, 0x175389c, 0x0259fa7,
|
|
0x1a6868f, 0x1036335, 0x0e22ce8, 0x122093b, 0x0dae010, 0x082c80b,
|
|
0x1f76197, 0x1c4a7c6, 0x199e905, 0x0c38da2, 0x0309f3a, 0x1c6459e,
|
|
0x174a132, 0x07aa6d0, 0x12f6805, 0x0137b57, 0x093634a },
|
|
{ 0x1a2e304, 0x13593d4, 0x04918a0, 0x0d83498, 0x057e186, 0x1c0b886,
|
|
0x0e0c888, 0x1fd2275, 0x1a9847c, 0x14db5c2, 0x1d1bf5f, 0x19e256b,
|
|
0x0d29655, 0x001c733, 0x0555cae, 0x0bd56e5, 0x0016fa9, 0x0f265d3,
|
|
0x077b6a0, 0x0220e37, 0x161ebbc, 0x0d1f8e7, 0x05fc002, 0x07c19f7,
|
|
0x0777b37, 0x11da9b9, 0x1344e75, 0x005f213, 0x07d78e3, 0x196d27c,
|
|
0x18c7b59, 0x168090e, 0x02077a3, 0x011591b, 0x0cb6773, 0x0f88118,
|
|
0x06deeee, 0x062df91, 0x0d5f92d, 0x0cf780c, 0x0266cb4 },
|
|
{ 0x16363e8, 0x120aa5a, 0x136dbea, 0x1078354, 0x0b4fd07, 0x0f32cba,
|
|
0x03778ae, 0x108286b, 0x0fa004b, 0x19a571f, 0x0446996, 0x05d9e33,
|
|
0x18cf44b, 0x129b5fb, 0x12aa0ce, 0x1b92aab, 0x0b98870, 0x0b0370f,
|
|
0x07cd447, 0x0650fa1, 0x1364e3c, 0x15ceae7, 0x1a2cbd3, 0x157193c,
|
|
0x0e89263, 0x108e0aa, 0x1b0daad, 0x0a91051, 0x17d1201, 0x1fe5d0d,
|
|
0x15c24ca, 0x0a62b71, 0x0e7b5bc, 0x19d60bf, 0x0347dd1, 0x06f05fa,
|
|
0x1c8f2af, 0x1814d41, 0x13b86f2, 0x036a48a, 0x04b1d5a },
|
|
{ 0x1d52c0c, 0x128ba31, 0x06744bf, 0x1c31181, 0x1735525, 0x071cab1,
|
|
0x0558cd8, 0x086b8c4, 0x0acfa5a, 0x059f8e5, 0x1a041e2, 0x1414f2f,
|
|
0x0a90123, 0x18af040, 0x0c7dad6, 0x1b5b574, 0x012fca3, 0x06bef2f,
|
|
0x17d4472, 0x0e6c361, 0x1d4e328, 0x0a32bab, 0x1f32003, 0x00fd922,
|
|
0x10f3d52, 0x0718840, 0x04c3ba8, 0x1a9cade, 0x05a2ec0, 0x17099f5,
|
|
0x142efdf, 0x17cd577, 0x1c07762, 0x1fb0cb7, 0x1738482, 0x159063f,
|
|
0x1622d42, 0x1a1cfd5, 0x12c9f81, 0x07ea11c, 0x08186b9 },
|
|
{ 0x1312867, 0x0e8aa04, 0x16d3186, 0x0b7f5ef, 0x1e042c0, 0x0faeed3,
|
|
0x059a07d, 0x105839e, 0x1a4fc3d, 0x055282b, 0x02e3f94, 0x1acb9cd,
|
|
0x04ed30e, 0x1f5a6b2, 0x0c0702e, 0x0092fd9, 0x044831c, 0x03daee2,
|
|
0x0df66c7, 0x1cd4013, 0x1c91351, 0x1ceca3b, 0x12ee18e, 0x1a82214,
|
|
0x0589105, 0x1bd55d3, 0x110d602, 0x0010d9e, 0x1e357e3, 0x003b485,
|
|
0x13ac4e7, 0x04f6a42, 0x0bfff1a, 0x1d5ab89, 0x1b5c8b0, 0x14f39f8,
|
|
0x134a9bf, 0x01ef2bf, 0x0aca91d, 0x12f93dc, 0x00bf97e },
|
|
{ 0x1a19e96, 0x027646e, 0x1a2e5bb, 0x14d860d, 0x14ce18e, 0x1b48c52,
|
|
0x184ad97, 0x132fd06, 0x10d9a0d, 0x1637b45, 0x1730246, 0x0f48c5f,
|
|
0x1398a69, 0x0ade1f0, 0x13897c6, 0x12e60cb, 0x0dab393, 0x10c4b76,
|
|
0x0bc4a01, 0x10341e6, 0x07df9eb, 0x170e96e, 0x14f5d05, 0x08e6b33,
|
|
0x07976ad, 0x01cf116, 0x0a7d7bd, 0x1bc6f53, 0x09d94e3, 0x0055cf3,
|
|
0x121adeb, 0x0153a17, 0x0bfa9e0, 0x1789073, 0x1c3559d, 0x1eaed50,
|
|
0x1eaac23, 0x0c8dda7, 0x0aaecef, 0x0587c81, 0x08fe548 },
|
|
{ 0x09a4d1e, 0x133e167, 0x00e216b, 0x069e3a4, 0x0c3eb80, 0x0830c92,
|
|
0x03ce897, 0x038b8d9, 0x1308fb4, 0x01ef056, 0x10a53a0, 0x0b79ce3,
|
|
0x1a9961f, 0x1817586, 0x1881e37, 0x1d16db8, 0x115b64a, 0x1e43f7a,
|
|
0x02d3463, 0x0f3e3ca, 0x1f43696, 0x10a90cc, 0x1170026, 0x0c814bf,
|
|
0x084be0f, 0x0b353ea, 0x048f6ad, 0x1923176, 0x075d2c4, 0x08a6321,
|
|
0x15a99f0, 0x195a5bd, 0x1a913b9, 0x1ae46ca, 0x062dad2, 0x0c313da,
|
|
0x142d3bf, 0x15b1035, 0x0f0fd2b, 0x0d37791, 0x03928c6 },
|
|
{ 0x0cb4b64, 0x1f5256d, 0x0687792, 0x09e4c2f, 0x03f62a4, 0x0889520,
|
|
0x12539ea, 0x03de755, 0x1d36f33, 0x02247de, 0x0e17124, 0x057880f,
|
|
0x1b42604, 0x1090dbb, 0x1629658, 0x1d308b5, 0x04f67ce, 0x098b3a5,
|
|
0x18ecbc3, 0x1d177c9, 0x10eb7fa, 0x0ed3e49, 0x1a077db, 0x0b3a1a8,
|
|
0x0fa98c2, 0x0fed6f7, 0x1afa870, 0x1629b3c, 0x1405d11, 0x0e4590e,
|
|
0x150eeab, 0x0e7124e, 0x01dff93, 0x0e6f278, 0x0cfbc1c, 0x130386b,
|
|
0x1150d0d, 0x026970c, 0x0d3d85c, 0x11e6aa2, 0x06ccc88 },
|
|
{ 0x0d7504c, 0x1b7873d, 0x1777e34, 0x1fef2b3, 0x1ca3265, 0x0f33d55,
|
|
0x07b7bfb, 0x05e1b9a, 0x0baebf3, 0x13b7a67, 0x1b73f04, 0x0dcc029,
|
|
0x176825a, 0x0cd6c75, 0x0306a0a, 0x19c3c17, 0x0a909b8, 0x1189012,
|
|
0x12f4d46, 0x1fb3173, 0x08becb8, 0x1c7d58f, 0x092104d, 0x0e7959f,
|
|
0x10f5d39, 0x12a0bf6, 0x1096754, 0x02fc290, 0x191393a, 0x1c21ba5,
|
|
0x1a54f56, 0x0359479, 0x1792b21, 0x07c0ac7, 0x0443230, 0x1a06bfe,
|
|
0x0d4ed7b, 0x1d31abd, 0x0bbe5ab, 0x10164df, 0x02f1519 },
|
|
{ 0x1d2d439, 0x118ed14, 0x0554321, 0x0578073, 0x121fbbc, 0x02dbad8,
|
|
0x05e49b0, 0x1d87cb5, 0x0b6ce47, 0x0b67a60, 0x031961b, 0x0ecf3b1,
|
|
0x17baaa1, 0x199aad0, 0x076e79f, 0x0b50a06, 0x1d80aef, 0x1c1c0f1,
|
|
0x168c6f7, 0x1b65202, 0x1d7dc71, 0x1a4a4c7, 0x18e3dad, 0x17dddec,
|
|
0x1f3f913, 0x1d9a276, 0x07d2ad9, 0x0c2e64e, 0x02df11e, 0x16387e9,
|
|
0x048e880, 0x040b89d, 0x1be0389, 0x1cc907b, 0x0216a3a, 0x1438432,
|
|
0x1eb54aa, 0x002e745, 0x03595b2, 0x16e158b, 0x0354b05 },
|
|
{ 0x09170e9, 0x0f11b3d, 0x0335c5c, 0x1a995aa, 0x01eec42, 0x0ee67d8,
|
|
0x0093cf3, 0x035ff7d, 0x1a66cae, 0x19f4671, 0x11f4069, 0x14ff2cb,
|
|
0x1eb7138, 0x0e1ecb8, 0x01638fd, 0x14e5600, 0x0c32ff0, 0x1a92c8d,
|
|
0x0ef39db, 0x1f6b797, 0x1a18a32, 0x1c54fc0, 0x1cc906a, 0x14d0c61,
|
|
0x13332ec, 0x09df98e, 0x11120bc, 0x08f5f3f, 0x081be28, 0x110bd23,
|
|
0x1e5865b, 0x1cabdf9, 0x138f932, 0x06382cc, 0x12e1c2b, 0x047cfb5,
|
|
0x0f09fac, 0x0df449e, 0x08e8750, 0x1895c6a, 0x048dc55 },
|
|
{ 0x1092193, 0x11c1352, 0x1c32398, 0x04d1312, 0x046ec36, 0x04f5a0f,
|
|
0x15abc97, 0x08a5e26, 0x083c7d2, 0x0bc0320, 0x0038e10, 0x1ecf2fa,
|
|
0x1c982de, 0x12890a8, 0x0badb9e, 0x110d270, 0x0778af5, 0x10aa708,
|
|
0x09473c0, 0x00e0eb1, 0x1c58187, 0x1bb8989, 0x137aea7, 0x02ab209,
|
|
0x1b973ba, 0x19d2eb3, 0x0c7435e, 0x0a393e9, 0x0af2cd8, 0x0eb8c5c,
|
|
0x18867ca, 0x130d71a, 0x194ccff, 0x1ce19e5, 0x092ee4e, 0x110e4bc,
|
|
0x06e38c6, 0x0e7262b, 0x1008501, 0x1ba16db, 0x05f6a8e },
|
|
{ 0x19a8690, 0x02652c7, 0x101e0dc, 0x0c5eed4, 0x1f36976, 0x1008141,
|
|
0x0b631a4, 0x19ff782, 0x0bce3a4, 0x06ac78b, 0x0ac9b53, 0x0c94095,
|
|
0x0878046, 0x07522bd, 0x173eee9, 0x12f2800, 0x1b3b8a5, 0x0a9bca8,
|
|
0x1f87dce, 0x0573c89, 0x17974ca, 0x06ef992, 0x1910a2b, 0x14487b7,
|
|
0x1a3420e, 0x00f3246, 0x0fd0f38, 0x19ccac5, 0x1db490c, 0x0210f93,
|
|
0x1c2103c, 0x117f6f9, 0x16ccb70, 0x1cbe98a, 0x00356a1, 0x1736669,
|
|
0x1eb814b, 0x09703d4, 0x01eb0b8, 0x0e594ff, 0x01ca650 },
|
|
{ 0x19d25a0, 0x190e795, 0x1b6feec, 0x14814e8, 0x06affdc, 0x11b45ab,
|
|
0x14c3967, 0x11f8382, 0x07d8006, 0x1768f52, 0x1f75a15, 0x11fcac8,
|
|
0x089b74d, 0x04dbc6d, 0x05ad41e, 0x067223b, 0x0438bbe, 0x19cdba9,
|
|
0x1616317, 0x1a887c1, 0x0a34ef8, 0x04cb235, 0x1374b6d, 0x0cea878,
|
|
0x13bd1e6, 0x0c2bfd6, 0x01a2602, 0x01ae218, 0x1acabad, 0x1f9924f,
|
|
0x04a7deb, 0x029f343, 0x15dec1c, 0x183d082, 0x0e647ec, 0x09594cc,
|
|
0x15ffff6, 0x027ec89, 0x0f3bab1, 0x16d975a, 0x0462caf },
|
|
{ 0x03237dd, 0x05323ef, 0x1010598, 0x190570e, 0x15f735c, 0x1d2afc4,
|
|
0x07d6777, 0x095ef0f, 0x0726b91, 0x0f7821f, 0x0f8a605, 0x127a392,
|
|
0x1118753, 0x1778c19, 0x08af9d1, 0x1425743, 0x1fc25a9, 0x1a73f46,
|
|
0x070e45f, 0x1f92fb5, 0x1e41dfe, 0x0185175, 0x0f21d74, 0x065a399,
|
|
0x1d235a7, 0x16987ba, 0x1b66ea9, 0x0dfdcff, 0x1485760, 0x07d5b2f,
|
|
0x102a9e1, 0x0a27f07, 0x1155e22, 0x1ce8991, 0x1c60fa3, 0x1ba5f6e,
|
|
0x1546eaf, 0x148a81d, 0x0d820a8, 0x118d9b2, 0x01293c9 },
|
|
{ 0x1d53b77, 0x00928a4, 0x0b1dc9e, 0x1b2dd5f, 0x06ab403, 0x1b5b88d,
|
|
0x11f6d28, 0x1836faf, 0x087e771, 0x11c6384, 0x0dd48a0, 0x157e676,
|
|
0x0d495f6, 0x0643a98, 0x0c0a272, 0x0223561, 0x186e77b, 0x16541e5,
|
|
0x06f4627, 0x181f714, 0x17c7be1, 0x1d8d74e, 0x1633ecb, 0x08187d0,
|
|
0x023c549, 0x083e82e, 0x05d2b64, 0x0dcf3c8, 0x0e71421, 0x1f82832,
|
|
0x13e8291, 0x1fbfac2, 0x0929cd4, 0x14c45e3, 0x0130e51, 0x03db64b,
|
|
0x046f8fb, 0x125af9f, 0x052e9cf, 0x142d1d5, 0x053b79a },
|
|
{ 0x0bbb6a1, 0x1d7e722, 0x1ca085b, 0x00cf042, 0x13a5bba, 0x0ec9cd6,
|
|
0x12cc2a7, 0x1fdde3c, 0x1f19efa, 0x117579e, 0x1b00500, 0x179cf69,
|
|
0x18fed5a, 0x0896339, 0x05a3b99, 0x11344c9, 0x06929fe, 0x09188cc,
|
|
0x1ce5f01, 0x073b1a8, 0x16c40d5, 0x0a11a2c, 0x19002f1, 0x08cc23a,
|
|
0x07f5853, 0x107dc94, 0x0f27576, 0x0813320, 0x1af2a80, 0x04cbe41,
|
|
0x18797bd, 0x06502a3, 0x09dc01b, 0x0088264, 0x12a5610, 0x1a2a1f6,
|
|
0x13872c9, 0x137beaf, 0x1a0cd02, 0x1a2ad85, 0x08290d6 },
|
|
{ 0x0546946, 0x11be36c, 0x1febe11, 0x12d3d8a, 0x1a134a3, 0x04803f6,
|
|
0x166935e, 0x013a846, 0x00dc7b8, 0x012abff, 0x1e12a6d, 0x0a5a5ac,
|
|
0x1fe62ae, 0x05e56da, 0x1c53298, 0x1f94b44, 0x1e633aa, 0x0e61046,
|
|
0x1659e04, 0x01dab9d, 0x1660238, 0x14ed990, 0x1b9ad57, 0x0ea46b4,
|
|
0x0d02ca6, 0x0708df5, 0x06ccfe8, 0x0398ddf, 0x0a2a085, 0x1f13783,
|
|
0x13ff488, 0x1d88f67, 0x0f332e1, 0x14c2700, 0x05ee82a, 0x088b3e5,
|
|
0x0e952e1, 0x10ecb4f, 0x0aec1be, 0x156609f, 0x0506ef1 },
|
|
{ 0x1bff163, 0x075939a, 0x061046d, 0x1fd53f5, 0x1130b96, 0x1593e73,
|
|
0x1acfe77, 0x1aacd59, 0x19dd1c3, 0x16d78d2, 0x01d6aa8, 0x14fd4e6,
|
|
0x18f5090, 0x11838da, 0x09abce7, 0x15b386d, 0x13ddf73, 0x15146b1,
|
|
0x1722685, 0x0a99597, 0x1c3cdd3, 0x11ea6e5, 0x17fa8d0, 0x13b25a3,
|
|
0x074d237, 0x1b2b776, 0x1e3bb59, 0x02948ad, 0x0feb1fe, 0x1ba1fd4,
|
|
0x11feaf9, 0x1731f97, 0x004ccf8, 0x138370a, 0x1effdc6, 0x10d99a5,
|
|
0x0d85c67, 0x179feda, 0x00d136a, 0x17e2a40, 0x0415b7d },
|
|
{ 0x18377a7, 0x082c33e, 0x09ca5c0, 0x1197006, 0x068a3d6, 0x1d26190,
|
|
0x14a27c0, 0x121facf, 0x193c8f2, 0x1e384ae, 0x168ae12, 0x0279d3c,
|
|
0x1b712fa, 0x07f5cf9, 0x1ab1b18, 0x0a985f8, 0x0d96e0e, 0x0866d1b,
|
|
0x18c8280, 0x132ea30, 0x0f11454, 0x08cbf80, 0x1e4c632, 0x126ca11,
|
|
0x04c3fe6, 0x05500ee, 0x0617c1a, 0x0d345df, 0x15511c7, 0x0778515,
|
|
0x014d48b, 0x168245c, 0x06965ed, 0x0ea1f80, 0x0bf305d, 0x13f9c1f,
|
|
0x0c831d5, 0x0ee4def, 0x01e7549, 0x1e35eb1, 0x01ec314 },
|
|
{ 0x08310c2, 0x1ff7796, 0x1dd0198, 0x148afc7, 0x0a7e14d, 0x1a3443d,
|
|
0x043f394, 0x18a7256, 0x1637ec2, 0x0f251c7, 0x0be37f3, 0x06416a8,
|
|
0x1150773, 0x1bef0b8, 0x04c0be7, 0x1378c68, 0x063ae4b, 0x180c58e,
|
|
0x14be79b, 0x0388ddb, 0x0fa0f00, 0x0b93766, 0x14eec2a, 0x08dc18f,
|
|
0x1b99d77, 0x1765498, 0x1fd61d6, 0x01916de, 0x139c82e, 0x18be4b4,
|
|
0x192eccb, 0x07bcb4c, 0x05135d2, 0x1fd35bb, 0x12d14aa, 0x1ce326d,
|
|
0x0dc105d, 0x0e60479, 0x15e22b5, 0x024fffe, 0x017e91d },
|
|
{ 0x1e051ca, 0x16769db, 0x1b52fa4, 0x1a338ee, 0x0644d4f, 0x033c25e,
|
|
0x12d4802, 0x0639156, 0x1ce9d6b, 0x1533113, 0x07a71cf, 0x1347a51,
|
|
0x0e39524, 0x08950cf, 0x1427997, 0x0b5d8a8, 0x0928c36, 0x153dea3,
|
|
0x1e58f83, 0x132fc8e, 0x132d354, 0x0bdaccb, 0x035d965, 0x1a9476c,
|
|
0x04aeb91, 0x1144cac, 0x1077acf, 0x1cca7d4, 0x0571df6, 0x0c76ab9,
|
|
0x1e729f2, 0x16315c3, 0x101a38f, 0x1dcbf79, 0x1f098fd, 0x0a2c53e,
|
|
0x0fc4a0d, 0x1211415, 0x030077c, 0x0967bba, 0x0118f3b },
|
|
{ 0x0d4762b, 0x050543d, 0x05d5d28, 0x1518b1a, 0x1aef84d, 0x1bb6c30,
|
|
0x1258133, 0x1162dfe, 0x07e60d9, 0x05f43c3, 0x1076eb0, 0x1ff67d9,
|
|
0x1a83637, 0x0eeb0a3, 0x1129825, 0x08dcb84, 0x0345b08, 0x0d1f0bc,
|
|
0x1de9301, 0x1d6d0dc, 0x0695735, 0x07efbac, 0x16f062d, 0x1bfca5e,
|
|
0x18d0b1b, 0x1d08ab0, 0x1401c56, 0x0f1d981, 0x1d617f8, 0x1e8d616,
|
|
0x04076f6, 0x0436c2e, 0x1d2b631, 0x0c9e110, 0x09e513d, 0x08459d1,
|
|
0x04f1702, 0x0da9b52, 0x19c9cee, 0x0f91a07, 0x001d0a6 },
|
|
{ 0x046533c, 0x1211b0f, 0x0ab9ee5, 0x01f7118, 0x0947799, 0x16250c7,
|
|
0x1745a90, 0x08a0336, 0x1d83c7a, 0x09af40e, 0x198f8dc, 0x17ba996,
|
|
0x0374a69, 0x13b606b, 0x19fb36f, 0x11b4cf6, 0x12111e6, 0x101eaa2,
|
|
0x0ba1942, 0x199d6ba, 0x1b37596, 0x1e95781, 0x1355cb7, 0x17ab2a5,
|
|
0x04ba1fa, 0x0b4a91b, 0x1ad3b61, 0x1e8fa8a, 0x10d5d47, 0x1ab964a,
|
|
0x0116b62, 0x090dc5f, 0x0dd2dfa, 0x1d82265, 0x0d0f15a, 0x0dbaa4f,
|
|
0x197c08e, 0x16dd124, 0x0c83f26, 0x00cfb4c, 0x01b625b },
|
|
{ 0x1d8446d, 0x1d53da7, 0x0fad137, 0x035edfd, 0x001b2f0, 0x041c5ae,
|
|
0x10e23fa, 0x1177e88, 0x1bba975, 0x19e21a7, 0x15af27c, 0x19750e2,
|
|
0x0b2b971, 0x0fa484c, 0x0917970, 0x18bbad6, 0x1342b41, 0x1c3ee5a,
|
|
0x13614b5, 0x1f018c6, 0x1a34db1, 0x0c1219e, 0x1b5b8c9, 0x0fbe184,
|
|
0x020653f, 0x1b2fb34, 0x10d832c, 0x0994acf, 0x06656ac, 0x15614c1,
|
|
0x1a0c87e, 0x17e0d2e, 0x1f5ca6f, 0x1b31c89, 0x04869c1, 0x1c2a72f,
|
|
0x0400736, 0x18a1944, 0x05236f7, 0x12c33f9, 0x0333eca },
|
|
{ 0x0775d81, 0x1bca456, 0x0f288cc, 0x1fa83b7, 0x18c2518, 0x1e74a41,
|
|
0x1e93ef3, 0x1cec478, 0x054703f, 0x169b11b, 0x0ced6ea, 0x074827f,
|
|
0x102b3a1, 0x1fae00f, 0x0cd5969, 0x12cc2bb, 0x0dc5235, 0x0eb9204,
|
|
0x1585ba4, 0x0ff1ca3, 0x19995a1, 0x15e592d, 0x04305bb, 0x126e87d,
|
|
0x08cf133, 0x053f9af, 0x0b952d9, 0x10fb4e9, 0x0d449d9, 0x191532e,
|
|
0x17555ec, 0x06fcf62, 0x05082a5, 0x089a7bb, 0x1d0bcb3, 0x0c9a4b8,
|
|
0x0ccf074, 0x0ece03a, 0x144d6ba, 0x0210e51, 0x072fc21 },
|
|
{ 0x16004c8, 0x15901fc, 0x17fea41, 0x1e8b00a, 0x183f95c, 0x19ac84e,
|
|
0x1619d57, 0x1ddaefa, 0x1e550c8, 0x14f537d, 0x0182052, 0x1952ab4,
|
|
0x0291c8c, 0x1e74103, 0x07fb9e2, 0x1f0bc94, 0x0069a3d, 0x175cd6f,
|
|
0x14f7999, 0x1b9e18f, 0x0d51fbb, 0x0dae99b, 0x08a28e4, 0x05ff878,
|
|
0x18d285c, 0x12dbb07, 0x0cbdec5, 0x1dc91bc, 0x1770401, 0x1ec22b0,
|
|
0x0800e00, 0x13bdff3, 0x173f648, 0x11ad272, 0x0e3a85f, 0x0dc344e,
|
|
0x0840a6c, 0x0778be4, 0x164b48e, 0x1f1623d, 0x0480946 },
|
|
{ 0x171f119, 0x1a3d47e, 0x1a56131, 0x1ca7d66, 0x19e65c5, 0x0c2c3d0,
|
|
0x19e198a, 0x1e81c5e, 0x1ab18d6, 0x052444c, 0x02e3012, 0x00498c6,
|
|
0x12a1a99, 0x16557c4, 0x05d4258, 0x1ac4909, 0x0bae20f, 0x064434d,
|
|
0x10adf75, 0x05609ad, 0x17d03b7, 0x1b04c97, 0x189dd7a, 0x00dcd09,
|
|
0x1c06e7d, 0x0038044, 0x0792ef4, 0x167686c, 0x0846e4c, 0x1335a5d,
|
|
0x07a86b9, 0x08c8c9b, 0x01c2eb2, 0x029cfe0, 0x0f9b07e, 0x0ff0de5,
|
|
0x0f68afc, 0x1474576, 0x1a4085b, 0x1fb8e70, 0x08dab61 },
|
|
{ 0x14d1d45, 0x0e481ea, 0x0e890a9, 0x1dfe9f3, 0x0cd4297, 0x0a3c5a5,
|
|
0x0d480d3, 0x0345b11, 0x108c462, 0x0d95d15, 0x195008d, 0x1376690,
|
|
0x06d3d23, 0x088f997, 0x19dabb6, 0x1fb843b, 0x1cf3f06, 0x143bfc5,
|
|
0x1b14540, 0x0e29833, 0x100d802, 0x15d2c83, 0x0841113, 0x1b992af,
|
|
0x0229f31, 0x1f6c34a, 0x0ee05a7, 0x1d9cef5, 0x0f080e5, 0x050a965,
|
|
0x1c556fa, 0x197af9d, 0x0b21b14, 0x0bf709f, 0x0b459ee, 0x193bdef,
|
|
0x118f690, 0x1e543c8, 0x0a79f80, 0x05bf336, 0x06f77e6 },
|
|
{ 0x00bbf59, 0x0def6f2, 0x0b5a89c, 0x06c8035, 0x177ba45, 0x0a0e688,
|
|
0x180d5cd, 0x05e2eab, 0x04b71b0, 0x032da33, 0x0cd67cd, 0x0227502,
|
|
0x0722eb7, 0x179c756, 0x04aa3f5, 0x1e76b2f, 0x12fff3b, 0x188d500,
|
|
0x0170fef, 0x15f57ff, 0x0c4299a, 0x1783606, 0x047828b, 0x076f675,
|
|
0x15d5777, 0x00518a6, 0x1b59a61, 0x1cbc5ce, 0x1a8be6a, 0x1039972,
|
|
0x002184d, 0x1839eab, 0x06d7578, 0x1688177, 0x003da2f, 0x164689c,
|
|
0x0184f0e, 0x0ebc434, 0x13e01e6, 0x12387a5, 0x063819c },
|
|
{ 0x084b073, 0x1c970bc, 0x1fab294, 0x19d624c, 0x1ec3a1f, 0x181c53c,
|
|
0x1d7c241, 0x0e07a0f, 0x0e4c47b, 0x195603e, 0x05ae472, 0x09dc37f,
|
|
0x1ff9666, 0x157527d, 0x1d5d624, 0x0ca01d7, 0x191fade, 0x02d55f9,
|
|
0x1c74481, 0x066ede2, 0x181ac5b, 0x08d069e, 0x07fd831, 0x0d50896,
|
|
0x0cfe797, 0x12d0859, 0x0af6984, 0x0263993, 0x1d453ee, 0x0b69a75,
|
|
0x10783f0, 0x0a096d7, 0x0d0319a, 0x1c655e0, 0x0f9c28b, 0x0fc8741,
|
|
0x15e49b4, 0x057f762, 0x15fbb20, 0x02504cb, 0x067d48d },
|
|
{ 0x02d56d6, 0x0acd3f5, 0x098c1a3, 0x1c4e901, 0x171abd0, 0x19b366e,
|
|
0x076c2b9, 0x178d7a2, 0x007204e, 0x1db1ce5, 0x198a4fe, 0x05cfeef,
|
|
0x1d89a24, 0x1add461, 0x19f28ad, 0x1f351bd, 0x03d64a2, 0x02396ee,
|
|
0x1586804, 0x053be8e, 0x09d4842, 0x02e2db2, 0x057d8b2, 0x1924f9b,
|
|
0x16b1b4d, 0x0cb7eea, 0x017b981, 0x1d17624, 0x129401f, 0x152855f,
|
|
0x010fbf2, 0x021a383, 0x0900d0f, 0x00efaea, 0x0ea4a2c, 0x0a59e22,
|
|
0x1f0e43f, 0x0bf5e18, 0x1371e8f, 0x071d070, 0x027950e },
|
|
{ 0x1d0fa79, 0x10ff870, 0x17a7aac, 0x060916b, 0x0b9fd03, 0x11ba65a,
|
|
0x11a24bf, 0x0d69926, 0x04eb21f, 0x1a413fd, 0x179f9ee, 0x1ef3524,
|
|
0x1146716, 0x1eea629, 0x10afcd9, 0x0dbbe28, 0x14cd2e9, 0x09039ca,
|
|
0x140aaa2, 0x02835d0, 0x0cc94e0, 0x0d4777b, 0x03b8038, 0x1019b5f,
|
|
0x0849158, 0x0232ae7, 0x11a58a0, 0x1e7574b, 0x15dfbff, 0x027c2e8,
|
|
0x094cd73, 0x13ed09e, 0x1f0440c, 0x12dec53, 0x14feec7, 0x175d008,
|
|
0x1f2225a, 0x04cc09f, 0x175c687, 0x108f364, 0x054ff78 },
|
|
{ 0x040b068, 0x177186f, 0x14789f1, 0x17cde74, 0x1226465, 0x1d90fb4,
|
|
0x11813e8, 0x02bc494, 0x1c04181, 0x052d2d6, 0x0434ad4, 0x08831bf,
|
|
0x0fe3285, 0x0e58600, 0x1d3963f, 0x011c776, 0x13b4a2c, 0x0e3478d,
|
|
0x13367b2, 0x1be1021, 0x0a9f339, 0x0e5bc37, 0x0454d8b, 0x0ab5d5b,
|
|
0x05e31c9, 0x035944a, 0x162da9b, 0x0d45803, 0x18a427d, 0x016e1b3,
|
|
0x0b01a7a, 0x0519260, 0x1875500, 0x080f30b, 0x05967e8, 0x0d159b5,
|
|
0x0e30b28, 0x0722b9f, 0x0c3f939, 0x10a7e30, 0x08adbad },
|
|
{ 0x169d524, 0x1708f84, 0x11e4182, 0x0fe7379, 0x142fdaf, 0x00fe617,
|
|
0x19d99f3, 0x09e79d8, 0x0e2336d, 0x0b5ce79, 0x103dfd1, 0x0bbd1c3,
|
|
0x0e6aa1f, 0x04c27d8, 0x0f0ab48, 0x096519b, 0x1a61b46, 0x1a04867,
|
|
0x090fcfb, 0x10de602, 0x07e740d, 0x0666af4, 0x056c5b3, 0x04d9a83,
|
|
0x1168c30, 0x198201f, 0x0e05b01, 0x17c70d9, 0x007a1dd, 0x0379ac2,
|
|
0x0bc53ae, 0x02e2fc3, 0x188b4f8, 0x1e4b67a, 0x06999b2, 0x036eb88,
|
|
0x027e71c, 0x0160d50, 0x1797fcd, 0x06d8128, 0x0739300 },
|
|
{ 0x0cdaf42, 0x1babe91, 0x0aae553, 0x1be8303, 0x188b591, 0x08a792b,
|
|
0x1a067d5, 0x1791730, 0x0f18fd5, 0x0b21704, 0x13ae45a, 0x0ba2045,
|
|
0x0592b30, 0x1527b4c, 0x05640f9, 0x1395c2e, 0x09d6117, 0x125ebeb,
|
|
0x0a7006a, 0x1bfabba, 0x08ccdac, 0x0d6c888, 0x1c17775, 0x1591e2a,
|
|
0x0c7b164, 0x197a1a5, 0x06d4918, 0x034a29c, 0x1fc4476, 0x130db98,
|
|
0x0c516e7, 0x1c12c36, 0x1561348, 0x17911e7, 0x059dcfa, 0x0738515,
|
|
0x0a7c99d, 0x0880c15, 0x197896f, 0x095c852, 0x08bc6ec },
|
|
{ 0x1f2a32b, 0x172e073, 0x08c3425, 0x1812711, 0x1f54800, 0x0f1b067,
|
|
0x10df100, 0x14c0dfc, 0x0bb6054, 0x12afe4e, 0x1ea9b99, 0x10c108a,
|
|
0x17510e1, 0x1594d95, 0x0b3f288, 0x1b4c341, 0x1e351b7, 0x1399241,
|
|
0x0f9b232, 0x08e3dcd, 0x09a1e31, 0x0e45b2e, 0x195950c, 0x1acb977,
|
|
0x0c3b948, 0x1547e4d, 0x06ba6ca, 0x0611f84, 0x00aa6ad, 0x0f86d53,
|
|
0x1535a9f, 0x1305f81, 0x044d96a, 0x1d26b94, 0x10b1611, 0x0b56025,
|
|
0x1ceb895, 0x1e47b8e, 0x1f854ac, 0x0fb7d38, 0x08e8543 },
|
|
};
|
|
|
|
/* Perform the modular exponentiation in Fp* for SAKKE.
|
|
*
|
|
* Base is fixed to be the g parameter - a precomputed table is used.
|
|
*
|
|
* Striping: 128 points at a distance of 8 combined.
|
|
* Total of 256 points in table.
|
|
* Square and multiply performed in Fp*.
|
|
*
|
|
* base [in] Base. MP integer.
|
|
* exp [in] Exponent. MP integer.
|
|
* res [out] Result. MP integer.
|
|
* returns 0 on success, MP_READ_E if there are too many bytes in an array
|
|
* and MEMORY_E if memory allocation fails.
|
|
*/
|
|
int sp_ModExp_Fp_star_1024(const mp_int* base, mp_int* exp, mp_int* res)
|
|
{
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
sp_digit* td;
|
|
sp_digit* t;
|
|
sp_digit* tx;
|
|
sp_digit* ty;
|
|
#else
|
|
sp_digit t[36 * 2 * 42];
|
|
sp_digit tx[2 * 42];
|
|
sp_digit ty[2 * 42];
|
|
#endif
|
|
sp_digit* r = NULL;
|
|
unsigned char e[128];
|
|
int err = MP_OKAY;
|
|
int i;
|
|
int y;
|
|
|
|
(void)base;
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 38 * 42 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
t = td;
|
|
tx = td + 36 * 42 * 2;
|
|
ty = td + 37 * 42 * 2;
|
|
#endif
|
|
r = ty;
|
|
|
|
(void)mp_to_unsigned_bin_len(exp, e, 128);
|
|
|
|
XMEMCPY(tx, p1024_norm_mod, sizeof(sp_digit) * 42);
|
|
y = e[112] >> 7;
|
|
y |= (e[96] >> 7) << 1;
|
|
y |= (e[80] >> 7) << 2;
|
|
y |= (e[64] >> 7) << 3;
|
|
y |= (e[48] >> 7) << 4;
|
|
y |= (e[32] >> 7) << 5;
|
|
y |= (e[16] >> 7) << 6;
|
|
y |= (e[0] >> 7) << 7;
|
|
XMEMCPY(ty, sp_1024_g_table[y], sizeof(sp_digit) * 42);
|
|
for (i = 126; i >= 0; i--) {
|
|
y = (e[127 - (i / 8)] >> (i & 0x7)) & 1;
|
|
y |= ((e[111 - (i / 8)] >> (i & 0x7)) & 1) << 1;
|
|
y |= ((e[95 - (i / 8)] >> (i & 0x7)) & 1) << 2;
|
|
y |= ((e[79 - (i / 8)] >> (i & 0x7)) & 1) << 3;
|
|
y |= ((e[63 - (i / 8)] >> (i & 0x7)) & 1) << 4;
|
|
y |= ((e[47 - (i / 8)] >> (i & 0x7)) & 1) << 5;
|
|
y |= ((e[31 - (i / 8)] >> (i & 0x7)) & 1) << 6;
|
|
y |= ((e[15 - (i / 8)] >> (i & 0x7)) & 1) << 7;
|
|
|
|
sp_1024_proj_sqr_42(tx, ty, t);
|
|
sp_1024_proj_mul_qx1_42(tx, ty, sp_1024_g_table[y], t);
|
|
}
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_mont_inv_42(tx, tx, t);
|
|
sp_1024_mont_mul_42(r, tx, ty, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
|
|
sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
|
|
|
|
err = sp_1024_to_mp(r, res);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (td != NULL) {
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/* Multiply p* by q* in projective co-ordinates.
|
|
*
|
|
* p.x' = (p.x * q.x) - (p.y * q.y)
|
|
* p.y' = (p.x * q.y) + (p.y * q.x)
|
|
* But applying Karatsuba:
|
|
* v0 = p.x * q.x
|
|
* v1 = p.y * q.y
|
|
* p.x' = v0 - v1
|
|
* p.y' = (px + py) * (qx + qy) - v0 - v1
|
|
*
|
|
* px [in,out] A single precision integer - X ordinate of number to multiply.
|
|
* py [in,out] A single precision integer - Y ordinate of number to multiply.
|
|
* qx [in] A single precision integer - X ordinate of number of
|
|
* multiplier.
|
|
* qy [in] A single precision integer - Y ordinate of number of
|
|
* multiplier.
|
|
* t [in] Two single precision integers - temps.
|
|
*/
|
|
static void sp_1024_proj_mul_42(sp_digit* px, sp_digit* py,
|
|
const sp_digit* qx, const sp_digit* qy, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
|
|
/* t1 = px + py */
|
|
sp_1024_mont_add_42(t1, px, py, p1024_mod);
|
|
/* t2 = qx + qy */
|
|
sp_1024_mont_add_42(t2, qx, qy, p1024_mod);
|
|
/* t2 = (px + py) * (qx + qy) */
|
|
sp_1024_mont_mul_42(t2, t1, t2, p1024_mod, p1024_mp_mod);
|
|
/* t1 = py * qy */
|
|
sp_1024_mont_mul_42(t1, py, qy, p1024_mod, p1024_mp_mod);
|
|
/* t2 = (px + py) * (qx + qy) - (py * qy) */
|
|
sp_1024_mont_sub_42(t2, t2, t1, p1024_mod);
|
|
/* px = px * qx */
|
|
sp_1024_mont_mul_42(px, px, qx, p1024_mod, p1024_mp_mod);
|
|
/* py = (px + py) * (qx + qy) - (py * qy) - (px * qx) */
|
|
sp_1024_mont_sub_42(py, t2, px, p1024_mod);
|
|
/* px = (px * qx) - (py * qy)*/
|
|
sp_1024_mont_sub_42(px, px, t1, p1024_mod);
|
|
}
|
|
|
|
#ifndef WOLFSSL_SP_SMALL
|
|
/*
|
|
* Convert point from projective to affine but keep in Montgomery form.
|
|
*
|
|
* p [in,out] Point to convert.
|
|
* t [in] Temporary numbers: 2.
|
|
*/
|
|
static void sp_1024_mont_map_42(sp_point_1024* p, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
|
|
sp_1024_mont_inv_42(t1, p->z, t2);
|
|
sp_1024_mont_sqr_42(t2, t1, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(t1, t2, t1, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(p->x, p->x, t2, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_mul_42(p->y, p->y, t1, p1024_mod, p1024_mp_mod);
|
|
XMEMCPY(p->z, p1024_norm_mod, sizeof(sp_digit) * 42);
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
/*
|
|
* Calculate gradient of line through P, P and [-2]P, accumulate line and
|
|
* double P.
|
|
*
|
|
* Calculations:
|
|
* l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
|
|
* r.x = l * (p.x + q.x * p.z^2) - 2 * p.y^2
|
|
* r.y = 2 * p.y * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
|
|
* v* = v*^2 * r*
|
|
* p'.x = l^2 - 8 * p.y^2 * p.x
|
|
* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4
|
|
* p'.z = 2 * p.y * p.z
|
|
*
|
|
* @param [in,out] vx X-ordinate of projective value in F*.
|
|
* @param [in,out] vy Y-ordinate of projective value in F*.
|
|
* @param [in,out] p ECC point - point on E(F_p^2) to double.
|
|
* @param [in] q ECC point - second point on E(F_P^2).
|
|
* @param [in] t SP temporaries (6 used).
|
|
*/
|
|
static void sp_1024_accumulate_line_dbl_42(sp_digit* vx, sp_digit* vy,
|
|
sp_point_1024* p, const sp_point_1024* q, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t + 0 * 42;
|
|
sp_digit* pz2 = t + 2 * 42;
|
|
sp_digit* rx = t + 4 * 42;
|
|
sp_digit* ry = t + 6 * 42;
|
|
sp_digit* l = t + 8 * 42;
|
|
sp_digit* ty = t + 10 * 42;
|
|
|
|
/* v = v^2 */
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
/* pz2 = p.z^2 */
|
|
sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod);
|
|
/* t1 = p.x + p.z^2 */
|
|
sp_1024_mont_add_42(ty, p->x, pz2, p1024_mod);
|
|
/* l = p.x - p.z^2 */
|
|
sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod);
|
|
/* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
|
|
sp_1024_mont_mul_42(t1, l, ty, p1024_mod, p1024_mp_mod);
|
|
/* l = 3 * (p.x^2 - p.z^4) */
|
|
sp_1024_mont_tpl_42(l, t1, p1024_mod);
|
|
/* t1 = q.x * p.z^2 */
|
|
sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
|
|
/* t1 = p.x + q.x * p.z^2 */
|
|
sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
|
|
/* r.x = l * (p.x + q.x * p.z^2) */
|
|
sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod);
|
|
/* r.y = 2 * p.y */
|
|
sp_1024_mont_dbl_42(ry, p->y, p1024_mod);
|
|
/* ty = 4 * p.y ^ 2 */
|
|
sp_1024_mont_sqr_42(ty, ry, p1024_mod, p1024_mp_mod);
|
|
/* t1 = 2 * p.y ^ 2 */
|
|
sp_1024_div2_42(t1, ty, p1024_mod);
|
|
/* r.x -= 2 * (p.y ^ 2) */
|
|
sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
|
|
/* p'.z = p.y * 2 * p.z */
|
|
sp_1024_mont_mul_42(p->z, p->z, ry, p1024_mod, p1024_mp_mod);
|
|
/* r.y = p'.z * p.z^2 */
|
|
sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
|
|
/* r.y = p'.z * p.z^2 * q.y */
|
|
sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod);
|
|
/* v = v^2 * r */
|
|
sp_1024_proj_mul_42(vx, vy, rx, ry, t);
|
|
|
|
/* Double point using previously calculated values
|
|
* l = 3 * (p.x - p.z^2).(p.x + p.z^2)
|
|
* ty = 4 * p.y^2
|
|
* p'.z = 2 * p.y * p.z
|
|
*/
|
|
/* t1 = (4 * p.y^2) ^ 2 = 16 * p.y^4 */
|
|
sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod);
|
|
/* t1 = 16 * p.y^4 / 2 = 8 * p.y^4 */
|
|
sp_1024_div2_42(t1, t1, p1024_mod);
|
|
/* p'.y = 4 * p.y^2 * p.x */
|
|
sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
|
|
/* p'.x = l^2 */
|
|
sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod);
|
|
/* p'.x = l^2 - 4 * p.y^2 * p.x */
|
|
sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
|
|
/* p'.x = l^2 - 8 * p.y^2 * p.x */
|
|
sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
|
|
/* p'.y = 4 * p.y^2 * p.x - p.x' */
|
|
sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod);
|
|
/* p'.y = (4 * p.y^2 * p.x - p'.x) * l */
|
|
sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod);
|
|
/* p'.y = (4 * p.y^2 * p.x - p'.x) * l - 8 * p.y^4 */
|
|
sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/*
|
|
* Calculate gradient of line through C, P and -C-P, accumulate line and
|
|
* add P to C.
|
|
*
|
|
* Calculations:
|
|
* r.x = (q.x + p.x) * c.y - (q.x * c.z^2 + c.x) * p.y * c.z
|
|
* r.y = (c.x - p.x * c.z^2) * q.y * c.z
|
|
* v* = v* * r*
|
|
* r = p.y * c.z^3 - c.y
|
|
* c'.x = r^2 + h^3 - 2 * c.x * h^2
|
|
* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3
|
|
* c'.z = (c.x - p.x * c.z^2) * c.z
|
|
*
|
|
* @param [in,out] vx X-ordinate of projective value in F*.
|
|
* @param [in,out] vy Y-ordinate of projective value in F*.
|
|
* @param [in,out] c ECC point - current point on E(F_p^2) to be added
|
|
* to.
|
|
* @param [in] p ECC point - point on E(F_p^2) to add.
|
|
* @param [in] q ECC point - second point on E(F_P^2).
|
|
* @param [in] qx_px SP that is a constant value across adds.
|
|
* @param [in] t SP temporaries (6 used).
|
|
*/
|
|
static void sp_1024_accumulate_line_add_one_42(sp_digit* vx, sp_digit* vy,
|
|
sp_point_1024* c, sp_point_1024* p, sp_point_1024* q, sp_digit* qx_px,
|
|
sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
sp_digit* rx = t + 4 * 42;
|
|
sp_digit* ry = t + 6 * 42;
|
|
sp_digit* h = t + 8 * 42;
|
|
sp_digit* r = t + 10 * 42;
|
|
|
|
/* r.x = (q.x + p.x) * c.y */
|
|
sp_1024_mont_mul_42(rx, qx_px, c->y, p1024_mod, p1024_mp_mod);
|
|
/* t2 = c.z^2 */
|
|
sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod);
|
|
/* t1 = q.x * c.z^2 */
|
|
sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod);
|
|
/* t1 = q.x * c.z^2 + c.x */
|
|
sp_1024_mont_add_42(h, t1, c->x, p1024_mod);
|
|
/* r = p.y * c.z */
|
|
sp_1024_mont_mul_42(ry, p->y, c->z, p1024_mod, p1024_mp_mod);
|
|
/* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
|
|
sp_1024_mont_mul_42(t1, h, ry, p1024_mod, p1024_mp_mod);
|
|
/* r = p.y * c.z * c.z^2 = p.y * c.z^3 */
|
|
sp_1024_mont_mul_42(r, ry, t2, p1024_mod, p1024_mp_mod);
|
|
/* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
|
|
sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
|
|
/* t1 = p.x * c.z^2 */
|
|
sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod);
|
|
/* h = c.x - p.x * c.z^2 */
|
|
sp_1024_mont_sub_42(h, c->x, t1, p1024_mod);
|
|
/* c'.z = (c.x - p.x * c.z^2) * c.z */
|
|
sp_1024_mont_mul_42(c->z, h, c->z, p1024_mod, p1024_mp_mod);
|
|
/* r.y = (c.x - p.x * c.z^2) * c.z * q.y */
|
|
sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
|
|
/* v = v * r */
|
|
sp_1024_proj_mul_42(vx, vy, rx, ry, t);
|
|
|
|
/* Add p to c using previously calculated values.
|
|
* h = c.x - p.x * c.z^2
|
|
* r = p.y * c.z^3
|
|
* c'.z = (c.x - p.x * c.z^2) * c.z
|
|
*/
|
|
|
|
/* r = p.y * c.z^3 - c.y */
|
|
sp_1024_mont_sub_42(r, r, c->y, p1024_mod);
|
|
/* t1 = r^2 */
|
|
sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod);
|
|
/* t2 = h^2 */
|
|
sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod);
|
|
/* ry = c.x * h^2 */
|
|
sp_1024_mont_mul_42(ry, c->x, rx, p1024_mod, p1024_mp_mod);
|
|
/* t2 = h^3 */
|
|
sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod);
|
|
/* c->x = r^2 + h^3 */
|
|
sp_1024_mont_add_42(c->x, t1, t2, p1024_mod);
|
|
/* t1 = 2 * c.x * h^2 */
|
|
sp_1024_mont_dbl_42(t1, ry, p1024_mod);
|
|
/* c'.x = r^2 + h^3 - 2 * c.x * h^2 */
|
|
sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod);
|
|
/* ry = c'.x - c.x * h^2 */
|
|
sp_1024_mont_sub_42(t1, c->x, ry, p1024_mod);
|
|
/* ry = r * (c'.x - c.x * h^2) */
|
|
sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
|
|
/* t2 = c.y * h^3 */
|
|
sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod);
|
|
/* c'.y = r * (c'.x - c.x * h^2) - c.y * h^3 */
|
|
sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod);
|
|
}
|
|
|
|
/*
|
|
* Calculate r = pairing <P, Q>.
|
|
*
|
|
* That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
|
|
*
|
|
* @param [in] key SAKKE key.
|
|
* @param [in] p First point on E(F_p)[q].
|
|
* @param [in] q Second point on E(F_p)[q].
|
|
* @param [in] r Result of calculation.
|
|
* @return 0 on success.
|
|
* @return MEMORY_E when dynamic memory allocation fails.
|
|
* @return Other -ve value on internal failure.
|
|
*/
|
|
int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
|
|
{
|
|
int err = MP_OKAY;
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
sp_digit* td = NULL;
|
|
sp_digit* t;
|
|
sp_digit* vx;
|
|
sp_digit* vy;
|
|
sp_digit* qx_px;
|
|
#else
|
|
sp_digit t[36 * 2 * 42];
|
|
sp_digit vx[2 * 42];
|
|
sp_digit vy[2 * 42];
|
|
sp_digit qx_px[2 * 42];
|
|
sp_point_1024 pd;
|
|
sp_point_1024 qd;
|
|
sp_point_1024 cd;
|
|
#endif
|
|
sp_point_1024* p = NULL;
|
|
sp_point_1024* q = NULL;
|
|
sp_point_1024* c = NULL;
|
|
sp_digit* r = NULL;
|
|
int i;
|
|
|
|
err = sp_1024_point_new_42(NULL, pd, p);
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, qd, q);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, cd, c);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 39 * 42 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
t = td;
|
|
vx = td + 36 * 42 * 2;
|
|
vy = td + 37 * 42 * 2;
|
|
qx_px = td + 38 * 42 * 2;
|
|
#endif
|
|
r = vy;
|
|
|
|
sp_1024_point_from_ecc_point_42(p, pm);
|
|
sp_1024_point_from_ecc_point_42(q, qm);
|
|
|
|
err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(c, p, sizeof(sp_point_1024));
|
|
XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
|
|
vx[0] = 1;
|
|
XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
|
|
|
|
sp_1024_mont_add_42(qx_px, q->x, p->x, p1024_mod);
|
|
|
|
for (i = 1020; i >= 0; i--) {
|
|
/* Accumulate line into v and double point. */
|
|
sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
|
|
|
|
if ((i > 0) && ((p1024_order[i / 25] >> (i % 25)) & 1)) {
|
|
/* Accumulate line into v and add P into C. */
|
|
sp_1024_accumulate_line_add_one_42(vx, vy, c, p, q, qx_px, t);
|
|
}
|
|
}
|
|
|
|
/* Final exponentiation */
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
|
|
/* Convert from PF_p[q] to F_p */
|
|
sp_1024_mont_inv_42(vx, vx, t);
|
|
sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
|
|
sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
|
|
|
|
err = sp_1024_to_mp(r, res);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (td != NULL) {
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif
|
|
sp_1024_point_free_42(c, 1, NULL);
|
|
sp_1024_point_free_42(q, 1, NULL);
|
|
sp_1024_point_free_42(p, 1, NULL);
|
|
return err;
|
|
}
|
|
|
|
#else
|
|
/*
|
|
* Calculate gradient of line through C, P and -C-P, accumulate line and
|
|
* add P to C.
|
|
*
|
|
* Both C and P have z ordinates to use in the calculation.
|
|
*
|
|
* Calculations:
|
|
* r.x = (q.x * c.z^2 + c.x) * p.y * c.z - (q.x * p.z^2 + p.x) * c.y * p.z
|
|
* r.y = (p.x * c.z^2 - c.x * p.z^2) * q.y * p.z * c.z
|
|
* v* = v* * r*
|
|
* h = p.x * c.z^2 - c.x * p.z^2
|
|
* r = p.y * c.z^3 - c.y * p.z^3
|
|
* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2
|
|
* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3
|
|
* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
|
|
*
|
|
* @param [in,out] vx X-ordinate of projective value in F*.
|
|
* @param [in,out] vy Y-ordinate of projective value in F*.
|
|
* @param [in,out] c ECC point - current point on E(F_p^2) to be added
|
|
* to.
|
|
* @param [in,out] p ECC point - point on E(F_p^2) to add.
|
|
* @param [in,out] q ECC point - second point on E(F_P^2).
|
|
* @param [in,out] t SP temporaries (6 used).
|
|
* @param [in,out] neg Indicates to use negative P.
|
|
* @return 0 on success.
|
|
* @return MEMORY_E when dynamic memory allocation fails.
|
|
* @return Other -ve value on internal failure.
|
|
*/
|
|
static void sp_1024_accumulate_line_add_n_42(sp_digit* vx, sp_digit* vy,
|
|
const sp_point_1024* p, const sp_point_1024* q,
|
|
sp_point_1024* c, sp_digit* t, int neg)
|
|
{
|
|
sp_digit* t1 = t;
|
|
sp_digit* t2 = t + 2 * 42;
|
|
sp_digit* rx = t + 4 * 42;
|
|
sp_digit* ry = t + 6 * 42;
|
|
sp_digit* h = t + 8 * 42;
|
|
sp_digit* r = t + 10 * 42;
|
|
|
|
/* h = p.z^2 */
|
|
sp_1024_mont_sqr_42(h, p->z, p1024_mod, p1024_mp_mod);
|
|
/* rx = q.x * p.z^2 */
|
|
sp_1024_mont_mul_42(rx, q->x, h, p1024_mod, p1024_mp_mod);
|
|
/* rx = q.x * p.z^2 + p.x */
|
|
sp_1024_mont_add_42(t2, rx, p->x, p1024_mod);
|
|
/* c.y = c.y * p.z */
|
|
sp_1024_mont_mul_42(t1, c->y, p->z, p1024_mod, p1024_mp_mod);
|
|
/* r.x = (q.x * p.z^2 + p.x) * c.y * p.z */
|
|
sp_1024_mont_mul_42(rx, t2, t1, p1024_mod, p1024_mp_mod);
|
|
/* c.y = c.y * p.z^3 */
|
|
sp_1024_mont_mul_42(c->y, t1, h, p1024_mod, p1024_mp_mod);
|
|
/* t2 = c.z^2 */
|
|
sp_1024_mont_sqr_42(t2, c->z, p1024_mod, p1024_mp_mod);
|
|
/* t1 = q.x * c.z^2 */
|
|
sp_1024_mont_mul_42(t1, q->x, t2, p1024_mod, p1024_mp_mod);
|
|
/* t1 = q.x * c.z^2 + c.x */
|
|
sp_1024_mont_add_42(t1, t1, c->x, p1024_mod);
|
|
/* c.x = c.x * p.z^2 */
|
|
sp_1024_mont_mul_42(c->x, c->x, h, p1024_mod, p1024_mp_mod);
|
|
/* r = p.y * c.z */
|
|
sp_1024_mont_mul_42(r, p->y, c->z, p1024_mod, p1024_mp_mod);
|
|
if (neg) {
|
|
/* r = -p.y * c.z */
|
|
sp_1024_mont_sub_42(r, p1024_mod, r, p1024_mod);
|
|
}
|
|
/* t1 = (q.x * c.z^2 + c.x) * p.y * c.z */
|
|
sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
|
|
/* r.x -= (q.x * c.z^2 + c.x) * p.y * c.z */
|
|
sp_1024_mont_sub_42(rx, ry, rx, p1024_mod);
|
|
/* t1 = p.x * c.z^2 */
|
|
sp_1024_mont_mul_42(t1, p->x, t2, p1024_mod, p1024_mp_mod);
|
|
/* h = p.x * c.z^2 - c.x * p.z^2 */
|
|
sp_1024_mont_sub_42(h, t1, c->x, p1024_mod);
|
|
/* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z */
|
|
sp_1024_mont_mul_42(t1, h, c->z, p1024_mod, p1024_mp_mod);
|
|
/* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z */
|
|
sp_1024_mont_mul_42(c->z, t1, p->z, p1024_mod, p1024_mp_mod);
|
|
/* r.y = (p.x * c.z^2 - c.x * p.z^2) * c.z * p.z * q.y */
|
|
sp_1024_mont_mul_42(ry, c->z, q->y, p1024_mod, p1024_mp_mod);
|
|
/* r = p.y * c.z^3 */
|
|
sp_1024_mont_mul_42(t1, r, t2, p1024_mod, p1024_mp_mod);
|
|
/* r = p.y * c.z^3 - c.y * p.z^3 */
|
|
sp_1024_mont_sub_42(r, t1, c->y, p1024_mod);
|
|
/* v = v * r */
|
|
sp_1024_proj_mul_42(vx, vy, rx, ry, t);
|
|
|
|
/* Add p to c using previously calculated values.
|
|
* h = p.x * c.z^2 - c.x * p.z^2
|
|
* r = p.y * c.z^3 - c.y * p.z^3
|
|
* c'.z = (p.x * c.z^2 - c.x * p.z^2) * c.z
|
|
*/
|
|
|
|
/* t1 = r^2 */
|
|
sp_1024_mont_sqr_42(t1, r, p1024_mod, p1024_mp_mod);
|
|
/* t2 = h^2 */
|
|
sp_1024_mont_sqr_42(rx, h, p1024_mod, p1024_mp_mod);
|
|
/* ry = c.x * p.z^2 * h^2 */
|
|
sp_1024_mont_mul_42(ry, rx, c->x, p1024_mod, p1024_mp_mod);
|
|
/* t2 = h^3 */
|
|
sp_1024_mont_mul_42(t2, rx, h, p1024_mod, p1024_mp_mod);
|
|
/* c'.x = r^2 - h^3 */
|
|
sp_1024_mont_sub_42(c->x, t1, t2, p1024_mod);
|
|
/* t1 = 2 * c.x * p.z^2 * h^2 */
|
|
sp_1024_mont_dbl_42(t1, ry, p1024_mod);
|
|
/* c'.x = r^2 - h^3 - 2 * c.x * p.z^2 * h^2 */
|
|
sp_1024_mont_sub_42(c->x, c->x, t1, p1024_mod);
|
|
/* ry = c.x * p.z^2 * h^2 - c'.x */
|
|
sp_1024_mont_sub_42(t1, ry, c->x, p1024_mod);
|
|
/* ry = r * (c.x * p.z^2 * h^2 - c'.x) */
|
|
sp_1024_mont_mul_42(ry, t1, r, p1024_mod, p1024_mp_mod);
|
|
/* t2 = c.y * p.z^3 * h^3 */
|
|
sp_1024_mont_mul_42(t1, t2, c->y, p1024_mod, p1024_mp_mod);
|
|
/* c'.y = r * (c.x * p.z^2 * h^2 - c'.x) - c.y * p.z^3 * h^3 */
|
|
sp_1024_mont_sub_42(c->y, ry, t1, p1024_mod);
|
|
}
|
|
|
|
/*
|
|
* Perform n accumulate doubles and doubles of P.
|
|
*
|
|
* py = 2 * p.y
|
|
*
|
|
* For each double:
|
|
* Calculate gradient of line through P, P and [-2]P, accumulate line and
|
|
* double P.
|
|
*
|
|
* Calculations:
|
|
* l = 3 * (p.x^2 - p.z^4) = 3 * (p.x - p.z^2) * (p.x + p.z^2)
|
|
* r.x = l * (p.x + q.x * p.z^2) - py^2 / 2
|
|
* r.y = py * p.z^3 * q.y (= p'.z * p.z^2 * q.y)
|
|
* v* = v*^2 * r*
|
|
* p'.x = l^2 - 2 * py^2 * p.x
|
|
* py' = (py^2 * p.x - p'.x) * l - py^4 (= 2 * p'.y)
|
|
* p'.z = py * p.z
|
|
*
|
|
* Finally:
|
|
* p'.y = py' / 2
|
|
*
|
|
* @param [in,out] vx X-ordinate of projective value in F*.
|
|
* @param [in,out] vy Y-ordinate of projective value in F*.
|
|
* @param [in,out] p ECC point - point on E(F_p^2) to double.
|
|
* @param [in] q ECC point - second point on E(F_P^2).
|
|
* @param [in] n Number of times to double.
|
|
* @param [in] t SP temporaries (6 used).
|
|
*/
|
|
static void sp_1024_accumulate_line_dbl_n_42(sp_digit* vx, sp_digit* vy,
|
|
sp_point_1024* p, const sp_point_1024* q, int n, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t + 0 * 42;
|
|
sp_digit* pz2 = t + 2 * 42;
|
|
sp_digit* rx = t + 4 * 42;
|
|
sp_digit* ry = t + 6 * 42;
|
|
sp_digit* l = t + 8 * 42;
|
|
sp_digit* ty = t + 10 * 42;
|
|
int i;
|
|
|
|
/* py = 2 * p.y */
|
|
sp_1024_mont_dbl_42(p->y, p->y, p1024_mod);
|
|
|
|
for (i = 0; i < n; i++) {
|
|
/* v = v^2 */
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
/* pz2 = p.z^2 */
|
|
sp_1024_mont_sqr_42(pz2, p->z, p1024_mod, p1024_mp_mod);
|
|
/* t1 = p.x + p.z^2 */
|
|
sp_1024_mont_add_42(t1, p->x, pz2, p1024_mod);
|
|
/* l = p.x - p.z^2 */
|
|
sp_1024_mont_sub_42(l, p->x, pz2, p1024_mod);
|
|
/* t1 = (p.x + p.z^2) * (p.x - p.z^2) = p.x^2 - p.z^4 */
|
|
sp_1024_mont_mul_42(ty, l, t1, p1024_mod, p1024_mp_mod);
|
|
/* l = 3 * (p.x^2 - p.z^4) */
|
|
sp_1024_mont_tpl_42(l, ty, p1024_mod);
|
|
/* t1 = q.x * p.z^2 */
|
|
sp_1024_mont_mul_42(t1, q->x, pz2, p1024_mod, p1024_mp_mod);
|
|
/* t1 = p.x + q.x * p.z^2 */
|
|
sp_1024_mont_add_42(t1, p->x, t1, p1024_mod);
|
|
/* r.x = l * (p.x + q.x * p.z^2) */
|
|
sp_1024_mont_mul_42(rx, l, t1, p1024_mod, p1024_mp_mod);
|
|
/* ty = py ^ 2 */
|
|
sp_1024_mont_sqr_42(ty, p->y, p1024_mod, p1024_mp_mod);
|
|
/* t1 = py ^ 2 / 2 */
|
|
sp_1024_div2_42(t1, ty, p1024_mod);
|
|
/* r.x -= py ^ 2 / 2 */
|
|
sp_1024_mont_sub_42(rx, rx, t1, p1024_mod);
|
|
/* p'.z = py * pz */
|
|
sp_1024_mont_mul_42(p->z, p->z, p->y, p1024_mod, p1024_mp_mod);
|
|
/* r.y = p'.z * p.z^2 */
|
|
sp_1024_mont_mul_42(t1, p->z, pz2, p1024_mod, p1024_mp_mod);
|
|
/* r.y = p'.z * p.z^2 * q.y */
|
|
sp_1024_mont_mul_42(ry, t1, q->y, p1024_mod, p1024_mp_mod);
|
|
/* v = v^2 * r */
|
|
sp_1024_proj_mul_42(vx, vy, rx, ry, t);
|
|
|
|
/* Double point using previously calculated values
|
|
* l = 3 * (p.x - p.z^2).(p.x + p.z^2)
|
|
* ty = py^2
|
|
* p'.z = py * p.z
|
|
*/
|
|
/* t1 = py^2 ^ 2 = py^4 */
|
|
sp_1024_mont_sqr_42(t1, ty, p1024_mod, p1024_mp_mod);
|
|
/* py' = py^2 * p. x */
|
|
sp_1024_mont_mul_42(p->y, ty, p->x, p1024_mod, p1024_mp_mod);
|
|
/* p'.x = l^2 */
|
|
sp_1024_mont_sqr_42(p->x, l, p1024_mod, p1024_mp_mod);
|
|
/* p'.x = l^2 - py^2 * p.x */
|
|
sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
|
|
/* p'.x = l^2 - 2 * p.y^2 * p.x */
|
|
sp_1024_mont_sub_42(p->x, p->x, p->y, p1024_mod);
|
|
/* py' = py^2 * p.x - p.x' */
|
|
sp_1024_mont_sub_42(ty, p->y, p->x, p1024_mod);
|
|
/* py' = (p.y^2 * p.x - p'.x) * l */
|
|
sp_1024_mont_mul_42(p->y, ty, l, p1024_mod, p1024_mp_mod);
|
|
/* py' = (p.y^2 * p.x - p'.x) * l * 2 */
|
|
sp_1024_mont_dbl_42(p->y, p->y, p1024_mod);
|
|
/* py' = (p.y^2 * p.x - p'.x) * l * 2 - p.y^4 */
|
|
sp_1024_mont_sub_42(p->y, p->y, t1, p1024_mod);
|
|
}
|
|
|
|
/* p'.y = py' / 2 */
|
|
sp_1024_div2_42(p->y, p->y, p1024_mod);
|
|
}
|
|
|
|
/* Operations to perform based on order - 1.
|
|
* Sliding window. Start at bottom and stop when bottom bit is one.
|
|
* Subtract if top bit in window is one.
|
|
* Width of 6 bits.
|
|
* Pairs: #dbls, add/subtract window value
|
|
*/
|
|
static const signed char sp_1024_order_op[] = {
|
|
5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
|
|
-1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
|
|
-19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
|
|
13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
|
|
-21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
|
|
-21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
|
|
-13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
|
|
-7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
|
|
-21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
|
|
17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
|
|
-19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
|
|
-13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
|
|
25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
|
|
-7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
|
|
27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
|
|
-7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
|
|
25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
|
|
-19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
|
|
-3, 1,
|
|
};
|
|
/*
|
|
* Calculate r = pairing <P, Q>.
|
|
*
|
|
* That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
|
|
*
|
|
* Sliding window. Start at bottom and stop when bottom bit is one.
|
|
* Subtract if top bit in window is one.
|
|
* Width of 6 bits.
|
|
*
|
|
* @param [in] pm First point on E(F_p)[q].
|
|
* @param [in] qm Second point on E(F_p)[q].
|
|
* @param [in] res Result of calculation.
|
|
* @return 0 on success.
|
|
* @return MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_Pairing_1024(const ecc_point* pm, const ecc_point* qm, mp_int* res)
|
|
{
|
|
int err;
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
sp_digit* td = NULL;
|
|
sp_digit* t;
|
|
sp_digit* vx;
|
|
sp_digit* vy;
|
|
sp_digit (*pre_vx)[84];
|
|
sp_digit (*pre_vy)[84];
|
|
sp_digit (*pre_nvy)[84];
|
|
sp_point_1024* pre_p;
|
|
#else
|
|
sp_digit t[36 * 2 * 42];
|
|
sp_digit vx[2 * 42];
|
|
sp_digit vy[2 * 42];
|
|
sp_digit pre_vx[16][84];
|
|
sp_digit pre_vy[16][84];
|
|
sp_digit pre_nvy[16][84];
|
|
sp_point_1024 pre_p[16];
|
|
sp_point_1024 pd;
|
|
sp_point_1024 qd;
|
|
sp_point_1024 cd;
|
|
#endif
|
|
sp_point_1024* p = NULL;
|
|
sp_point_1024* q = NULL;
|
|
sp_point_1024* c = NULL;
|
|
sp_digit* r = NULL;
|
|
int i;
|
|
int j;
|
|
|
|
err = sp_1024_point_new_42(NULL, pd, p);
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, qd, q);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, cd, c);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 42 * 2 + 16 * sizeof(sp_point_1024), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
t = td;
|
|
vx = td + 36 * 42 * 2;
|
|
vy = td + 37 * 42 * 2;
|
|
pre_vx = (sp_digit(*)[84])(td + 38 * 42 * 2);
|
|
pre_vy = (sp_digit(*)[84])(td + 54 * 42 * 2);
|
|
pre_nvy = (sp_digit(*)[84])(td + 70 * 42 * 2);
|
|
pre_p = (sp_point_1024*)(td + 86 * 42 * 2);
|
|
#endif
|
|
r = vy;
|
|
|
|
sp_1024_point_from_ecc_point_42(p, pm);
|
|
sp_1024_point_from_ecc_point_42(q, qm);
|
|
|
|
err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* Generate pre-computation table: 1, 3, ... , 31 */
|
|
XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
|
|
XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42);
|
|
pre_vx[0][0] = 1;
|
|
XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42);
|
|
sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
|
|
|
|
/* [2]P for adding */
|
|
XMEMCPY(c, p, sizeof(sp_point_1024));
|
|
XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
|
|
vx[0] = 1;
|
|
XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
|
|
sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
|
|
|
|
/* 3, 5, ... */
|
|
for (i = 1; i < 16; i++) {
|
|
XMEMCPY(&pre_p[i], &pre_p[i-1], sizeof(sp_point_1024));
|
|
XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42);
|
|
XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42);
|
|
sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t);
|
|
sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c,
|
|
q, &pre_p[i], t, 0);
|
|
sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i], p1024_mod);
|
|
}
|
|
|
|
j = sp_1024_order_op[0] / 2;
|
|
XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
|
|
XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42);
|
|
XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42);
|
|
|
|
/* Accumulate line into v and double point n times. */
|
|
sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q,
|
|
sp_1024_order_op[1], t);
|
|
|
|
for (i = 2; i < 290; i += 2) {
|
|
j = sp_1024_order_op[i];
|
|
if (j > 0) {
|
|
j /= 2;
|
|
/* Accumulate line into v and add P into C. */
|
|
sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t);
|
|
sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c,
|
|
t, 0);
|
|
}
|
|
else {
|
|
j = -j / 2;
|
|
/* Accumulate line into v and add P into C. */
|
|
sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t);
|
|
sp_1024_accumulate_line_add_n_42(vx, vy, &pre_p[j], q, c,
|
|
t, 1);
|
|
}
|
|
|
|
/* Accumulate line into v and double point n times. */
|
|
sp_1024_accumulate_line_dbl_n_42(vx, vy, c, q,
|
|
sp_1024_order_op[i + 1], t);
|
|
}
|
|
|
|
/* Final exponentiation */
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
|
|
/* Convert from PF_p[q] to F_p */
|
|
sp_1024_mont_inv_42(vx, vx, t);
|
|
sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
|
|
sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
|
|
|
|
err = sp_1024_to_mp(r, res);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (td != NULL) {
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif
|
|
sp_1024_point_free_42(c, 1, NULL);
|
|
sp_1024_point_free_42(q, 1, NULL);
|
|
sp_1024_point_free_42(p, 1, NULL);
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef WOLFSSL_SP_SMALL
|
|
/*
|
|
* Generate table for pairing.
|
|
*
|
|
* Small implementation does not use a table - returns 0 length.
|
|
*
|
|
* pm [in] Point to generate table for.
|
|
* table [in] Generated table.
|
|
* len [in,out] On in, the size of the buffer.
|
|
* On out, length of table generated.
|
|
* @return 0 on success.
|
|
* LENGTH_ONLY_E when table is NULL and only length returned.
|
|
* BUFFER_E when len is too small.
|
|
*/
|
|
int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
|
|
word32* len)
|
|
{
|
|
int err = 0;
|
|
|
|
if (table == NULL) {
|
|
*len = 0;
|
|
err = LENGTH_ONLY_E;
|
|
}
|
|
else if (*len != 0) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
(void)*pm;
|
|
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
* Calculate r = pairing <P, Q>.
|
|
*
|
|
* That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
|
|
*
|
|
* Small implementation does not use a table - use the normal implementation.
|
|
*
|
|
* @param [in] pm First point on E(F_p)[q].
|
|
* @param [in] qm Second point on E(F_p)[q].
|
|
* @param [in] res Result of calculation.
|
|
* @param [in] table Precomputed table of values.
|
|
* @param [in] len Length of precomputed table of values in bytes.
|
|
* @return 0 on success.
|
|
* @return MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
|
|
mp_int* res, const byte* table, word32 len)
|
|
{
|
|
(void)table;
|
|
(void)len;
|
|
return sp_Pairing_1024(pm, qm, res);
|
|
}
|
|
|
|
#else
|
|
/*
|
|
* Calc l and c for the point when doubling p.
|
|
*
|
|
* l = 3 * (p.x^2 - 1) / (2 * p.y)
|
|
* c = l * p.x - p.y
|
|
*
|
|
* @param [out] lr Gradient result - table entry.
|
|
* @param [out] cr Constant result - table entry.
|
|
* @param [in] px X-ordinate of point to double.
|
|
* @param [in] py Y-ordinate of point to double.
|
|
* @param [in] t SP temporaries (3 used).
|
|
*/
|
|
static void sp_1024_accum_dbl_calc_lc_42(sp_digit* lr, sp_digit* cr,
|
|
const sp_digit* px, const sp_digit* py, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t + 33 * 2 * 42;
|
|
sp_digit* t2 = t + 34 * 2 * 42;
|
|
sp_digit* l = t + 35 * 2 * 42;
|
|
|
|
/* l = 1 / 2 * p.y */
|
|
sp_1024_mont_dbl_42(l, py, p1024_mod);
|
|
sp_1024_mont_inv_42(l, l, t);
|
|
|
|
/* t1 = p.x^2 */
|
|
sp_1024_mont_sqr_42(t1, px, p1024_mod, p1024_mp_mod);
|
|
/* t1 = p.x - 1 */
|
|
sp_1024_mont_sub_42(t1, t1, p1024_norm_mod, p1024_mod);
|
|
/* t1 = 3 * (p.x^2 - 1) */
|
|
sp_1024_mont_dbl_42(t2, t1, p1024_mod);
|
|
sp_1024_mont_add_42(t1, t1, t2, p1024_mod);
|
|
/* t1 = 3 * (p.x^2 - 1) / (2 * p.y) */
|
|
sp_1024_mont_mul_42(l, l, t1, p1024_mod, p1024_mp_mod);
|
|
/* t2 = l * p.x */
|
|
sp_1024_mont_mul_42(t2, l, px, p1024_mod, p1024_mp_mod);
|
|
/* c = t2 = l * p.x - p.y */
|
|
sp_1024_mont_sub_42(t2, t2, py, p1024_mod);
|
|
|
|
XMEMCPY(lr, l, sizeof(sp_digit) * 42);
|
|
XMEMCPY(cr, t2, sizeof(sp_digit) * 42);
|
|
}
|
|
|
|
/*
|
|
* Calc l and c when adding p and c.
|
|
*
|
|
* l = (c.y - p.y) / (c.x - p.x)
|
|
* c = (p.x * c.y - cx * p.y) / (cx - p.x)
|
|
*
|
|
* @param [out] lr Gradient result - table entry.
|
|
* @param [out] cr Constant result - table entry.
|
|
* @param [in] px X-ordinate of point to add.
|
|
* @param [in] py Y-ordinate of point to add.
|
|
* @param [in] cx X-ordinate of current point.
|
|
* @param [in] cy Y-ordinate of current point.
|
|
* @param [in] t SP temporaries (3 used).
|
|
*/
|
|
static void sp_1024_accum_add_calc_lc_42(sp_digit* lr, sp_digit* cr,
|
|
const sp_digit* px, const sp_digit* py, const sp_digit* cx,
|
|
const sp_digit* cy, sp_digit* t)
|
|
{
|
|
sp_digit* t1 = t + 33 * 2 * 42;
|
|
sp_digit* c = t + 34 * 2 * 42;
|
|
sp_digit* l = t + 35 * 2 * 42;
|
|
|
|
/* l = 1 / (c.x - p.x) */
|
|
sp_1024_mont_sub_42(l, cx, px, p1024_mod);
|
|
sp_1024_mont_inv_42(l, l, t);
|
|
|
|
/* c = p.x * c.y */
|
|
sp_1024_mont_mul_42(c, px, cy, p1024_mod, p1024_mp_mod);
|
|
/* t1 = c.x * p.y */
|
|
sp_1024_mont_mul_42(t1, cx, py, p1024_mod, p1024_mp_mod);
|
|
/* c = (p.x * c.y) - (c.x * p.y) */
|
|
sp_1024_mont_sub_42(c, c, t1, p1024_mod);
|
|
/* c = ((p.x * c.y) - (c.x * p.y)) / (c.x - p.x) */
|
|
sp_1024_mont_mul_42(c, c, l, p1024_mod, p1024_mp_mod);
|
|
/* t1 = c.y - p.y */
|
|
sp_1024_mont_sub_42(t1, cy, py, p1024_mod);
|
|
/* l = (c.y - p.y) / (c.x - p.x) */
|
|
sp_1024_mont_mul_42(l, t1, l, p1024_mod, p1024_mp_mod);
|
|
|
|
XMEMCPY(lr, l, sizeof(sp_digit) * 42);
|
|
XMEMCPY(cr, c, sizeof(sp_digit) * 42);
|
|
}
|
|
|
|
/*
|
|
* Calculate vx and vy given gradient l and constant c and point q.
|
|
*
|
|
* l is a the gradient and is multiplied by q->x.
|
|
* c is a the constant that is added to the multiplicative result.
|
|
* q->y is the y-ordinate in result to multiply.
|
|
*
|
|
* if dbl
|
|
* v* = v*^2
|
|
* r.x = l * q.x + c
|
|
* r.y = q->y
|
|
* v* = v* * r*
|
|
*
|
|
* @param [in,out] vx X-ordinate of projective value in F*.
|
|
* @param [in,out] vy Y-ordinate of projective value in F*.
|
|
* @param [in] l Gradient to multiply with.
|
|
* @param [in] c Constant to add with.
|
|
* @param [in] q ECC point - second point on E(F_P^2).
|
|
* @param [in] t SP temporaries (3 used).
|
|
* @param [in] dbl Indicates whether this is for doubling. Otherwise
|
|
* adding.
|
|
*/
|
|
static void sp_1024_accumulate_line_lc_42(sp_digit* vx, sp_digit* vy,
|
|
const sp_digit* l, const sp_digit* c, const sp_point_1024* q,
|
|
sp_digit* t, int dbl)
|
|
{
|
|
sp_digit* rx = t + 4 * 2 * 42;
|
|
|
|
/* v = v^2 */
|
|
if (dbl) {
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
}
|
|
/* rx = l * q.x + c */
|
|
sp_1024_mont_mul_42(rx, l, q->x, p1024_mod, p1024_mp_mod);
|
|
sp_1024_mont_add_42(rx, rx, c, p1024_mod);
|
|
/* v = v^2 * r */
|
|
sp_1024_proj_mul_42(vx, vy, rx, q->y, t);
|
|
}
|
|
|
|
/* Operations to perform based on order - 1.
|
|
* Sliding window. Start at bottom and stop when bottom bit is one.
|
|
* Subtract if top bit in window is one.
|
|
* Width of 6 bits.
|
|
* Pairs: #dbls, add/subtract window value
|
|
*/
|
|
static const signed char sp_1024_order_op_pre[] = {
|
|
5, 6, -13, 9, -21, 6, -5, 8, 31, 6, 3, 6, -27, 6, 25, 9,
|
|
-1, 6, -11, 6, -13, 6, -7, 6, -15, 6, -29, 7, 25, 6, -9, 6,
|
|
-19, 7, 3, 6, 11, 9, -23, 6, 1, 6, 27, 6, 1, 7, -25, 8,
|
|
13, 7, -13, 7, -23, 10, 19, 7, 7, 7, -3, 7, 27, 6, -7, 7,
|
|
-21, 7, 11, 7, 31, 8, 1, 7, -23, 6, -17, 6, -3, 10, 11, 6,
|
|
-21, 7, -27, 11, -29, 6, -1, 10, 15, 8, 27, 7, 17, 6, 17, 7,
|
|
-13, 8, 13, 6, 21, 7, -29, 6, 19, 7, -25, 6, 11, 9, 29, 7,
|
|
-7, 8, 27, 7, 29, 10, -1, 8, -7, 8, 17, 6, 17, 7, -27, 7,
|
|
-21, 6, -9, 6, -27, 12, -23, 6, 19, 6, 13, 6, -11, 7, 27, 6,
|
|
17, 6, -7, 6, -25, 7, -29, 6, 9, 7, 7, 6, 13, 6, -25, 6,
|
|
-19, 6, 13, 6, -11, 6, 5, 8, 19, 6, -21, 8, 23, 7, 27, 6,
|
|
-13, 6, -19, 11, 29, 7, -15, 6, -9, 7, -21, 10, -3, 7, 21, 10,
|
|
25, 6, -15, 6, -23, 6, 21, 6, 1, 6, 21, 7, -3, 6, -3, 7,
|
|
-7, 6, -23, 7, 7, 8, 15, 9, 5, 6, -11, 6, 21, 11, -27, 7,
|
|
27, 6, -11, 6, 31, 6, -21, 6, 19, 6, -7, 8, -7, 13, -3, 6,
|
|
-7, 7, -3, 6, 1, 6, 7, 8, 19, 8, 11, 9, -9, 7, -31, 12,
|
|
25, 6, -17, 9, -15, 7, 5, 6, 25, 7, -5, 7, -25, 6, 17, 8,
|
|
-19, 6, -13, 6, 27, 8, 1, 7, -5, 7, -1, 6, 21, 6, 3, 10,
|
|
-3, 1,
|
|
};
|
|
|
|
/*
|
|
* Generate table for pairing.
|
|
*
|
|
* Calculate the graident (l) and constant (c) at each step of the way.
|
|
* Sliding window. Start at bottom and stop when bottom bit is one.
|
|
* Subtract if top bit in window is one.
|
|
* Width of 6 bits.
|
|
*
|
|
* pm [in] Point to generate table for.
|
|
* table [in] Generated table.
|
|
* len [in,out] On in, the size of the buffer.
|
|
* On out, length of table generated.
|
|
* @return 0 on success.
|
|
* LENGTH_ONLY_E when table is NULL and only length returned.
|
|
* BUFFER_E when len is too small.
|
|
* MEMORY_E when dynamic memory allocation fauls.
|
|
*/
|
|
int sp_Pairing_gen_precomp_1024(const ecc_point* pm, byte* table,
|
|
word32* len)
|
|
{
|
|
int err = 0;
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
sp_digit* td = NULL;
|
|
sp_digit* t;
|
|
sp_point_1024* pre_p;
|
|
#else
|
|
sp_digit t[36 * 2 * 42];
|
|
sp_point_1024 pre_p[16];
|
|
sp_point_1024 pd;
|
|
sp_point_1024 cd;
|
|
sp_point_1024 negd;
|
|
#endif
|
|
sp_point_1024* p = NULL;
|
|
sp_point_1024* c = NULL;
|
|
sp_point_1024* neg = NULL;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
sp_table_entry_1024* precomp = (sp_table_entry_1024*)table;
|
|
|
|
if (table == NULL) {
|
|
*len = sizeof(sp_table_entry_1024) * 1167;
|
|
err = LENGTH_ONLY_E;
|
|
}
|
|
|
|
if ((err == MP_OKAY) &&
|
|
(*len < (int)(sizeof(sp_table_entry_1024) * 1167))) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, pd, p);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, cd, c);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, negd, neg);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 42 * 2 + 16 *
|
|
sizeof(sp_point_1024), NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
t = td;
|
|
pre_p = (sp_point_1024*)(td + 36 * 42 * 2);
|
|
#endif
|
|
|
|
sp_1024_point_from_ecc_point_42(p, pm);
|
|
|
|
err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
XMEMCPY(p->z, p1024_norm_mod, sizeof(p1024_norm_mod));
|
|
neg->infinity = 0;
|
|
c->infinity = 0;
|
|
|
|
/* Generate pre-computation table: 1, 3, ... , 31 */
|
|
XMEMCPY(&pre_p[0], p, sizeof(sp_point_1024));
|
|
/* [2]P for adding */
|
|
sp_1024_proj_point_dbl_42(c, p, t);
|
|
|
|
/* 1, 3, ... */
|
|
for (i = 1; i < 16; i++) {
|
|
sp_1024_proj_point_add_42(&pre_p[i], &pre_p[i-1], c, t);
|
|
sp_1024_mont_map_42(&pre_p[i], t);
|
|
}
|
|
|
|
k = 0;
|
|
j = sp_1024_order_op_pre[0] / 2;
|
|
XMEMCPY(c, &pre_p[j], sizeof(sp_point_1024));
|
|
|
|
for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
|
|
sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x,
|
|
c->y, t);
|
|
k++;
|
|
sp_1024_proj_point_dbl_42(c, c, t);
|
|
sp_1024_mont_map_42(c, t);
|
|
}
|
|
|
|
for (i = 2; i < 290; i += 2) {
|
|
j = sp_1024_order_op_pre[i];
|
|
if (j > 0) {
|
|
sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y,
|
|
pre_p[j/2].x, pre_p[j/2].y, c->x, c->y, t);
|
|
k++;
|
|
sp_1024_proj_point_add_42(c, c, &pre_p[j/2], t);
|
|
sp_1024_mont_map_42(c, t);
|
|
}
|
|
else {
|
|
XMEMCPY(neg->x, pre_p[-j / 2].x, sizeof(pre_p->x));
|
|
sp_1024_mont_sub_42(neg->y, p1024_mod, pre_p[-j / 2].y,
|
|
p1024_mod);
|
|
XMEMCPY(neg->z, pre_p[-j / 2].z, sizeof(pre_p->z));
|
|
|
|
sp_1024_accum_add_calc_lc_42(precomp[k].x, precomp[k].y,
|
|
neg->x, neg->y, c->x, c->y, t);
|
|
k++;
|
|
sp_1024_proj_point_add_42(c, c, neg, t);
|
|
sp_1024_mont_map_42(c, t);
|
|
}
|
|
|
|
for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
|
|
sp_1024_accum_dbl_calc_lc_42(precomp[k].x, precomp[k].y, c->x,
|
|
c->y, t);
|
|
k++;
|
|
sp_1024_proj_point_dbl_42(c, c, t);
|
|
sp_1024_mont_map_42(c, t);
|
|
}
|
|
}
|
|
|
|
*len = sizeof(sp_table_entry_1024) * 1167;
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (td != NULL) {
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif
|
|
sp_1024_point_free_42(neg, 1, NULL);
|
|
sp_1024_point_free_42(c, 1, NULL);
|
|
sp_1024_point_free_42(p, 1, NULL);
|
|
return err;
|
|
}
|
|
|
|
/*
|
|
* Calculate r = pairing <P, Q>.
|
|
*
|
|
* That is, multiply base in PF_p[q] by the scalar s, such that s.P = Q.
|
|
*
|
|
* Sliding window. Start at bottom and stop when bottom bit is one.
|
|
* Subtract if top bit in window is one.
|
|
* Width of 6 bits.
|
|
* Pre-generate values in window (1, 3, ...) - only V.
|
|
* Table contains all gradient l and a constant for each point on the path.
|
|
*
|
|
* @param [in] pm First point on E(F_p)[q].
|
|
* @param [in] qm Second point on E(F_p)[q].
|
|
* @param [in] res Result of calculation.
|
|
* @param [in] table Precomputed table of values.
|
|
* @param [in] len Length of precomputed table of values in bytes.
|
|
* @return 0 on success.
|
|
* @return MEMORY_E when dynamic memory allocation fails.
|
|
*/
|
|
int sp_Pairing_precomp_1024(const ecc_point* pm, const ecc_point* qm,
|
|
mp_int* res, const byte* table, word32 len)
|
|
{
|
|
int err = 0;
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
sp_digit* td = NULL;
|
|
sp_digit* t;
|
|
sp_digit* vx;
|
|
sp_digit* vy;
|
|
sp_digit (*pre_vx)[84];
|
|
sp_digit (*pre_vy)[84];
|
|
sp_digit (*pre_nvy)[84];
|
|
#else
|
|
sp_digit t[36 * 2 * 42];
|
|
sp_digit vx[2 * 42];
|
|
sp_digit vy[2 * 42];
|
|
sp_digit pre_vx[16][84];
|
|
sp_digit pre_vy[16][84];
|
|
sp_digit pre_nvy[16][84];
|
|
sp_point_1024 pd;
|
|
sp_point_1024 qd;
|
|
sp_point_1024 cd;
|
|
#endif
|
|
sp_point_1024* p = NULL;
|
|
sp_point_1024* q = NULL;
|
|
sp_point_1024* c = NULL;
|
|
sp_digit* r = NULL;
|
|
int i;
|
|
int j;
|
|
int k;
|
|
const sp_table_entry_1024* precomp = (const sp_table_entry_1024*)table;
|
|
|
|
if (len < (int)(sizeof(sp_table_entry_1024) * 1167)) {
|
|
err = BUFFER_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, pd, p);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, qd, q);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_point_new_42(NULL, cd, c);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (err == MP_OKAY) {
|
|
td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 86 * 42 * 2, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (td == NULL) {
|
|
err = MEMORY_E;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
t = td;
|
|
vx = td + 36 * 42 * 2;
|
|
vy = td + 37 * 42 * 2;
|
|
pre_vx = (sp_digit(*)[84])(td + 38 * 42 * 2);
|
|
pre_vy = (sp_digit(*)[84])(td + 54 * 42 * 2);
|
|
pre_nvy = (sp_digit(*)[84])(td + 70 * 42 * 2);
|
|
#endif
|
|
r = vy;
|
|
|
|
sp_1024_point_from_ecc_point_42(p, pm);
|
|
sp_1024_point_from_ecc_point_42(q, qm);
|
|
|
|
err = sp_1024_mod_mul_norm_42(p->x, p->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->y, p->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(p->z, p->z, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(q->x, q->x, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
err = sp_1024_mod_mul_norm_42(q->y, q->y, p1024_mod);
|
|
}
|
|
if (err == MP_OKAY) {
|
|
/* Generate pre-computation table: 1, 3, ... , 31 */
|
|
XMEMSET(pre_vx[0], 0, sizeof(sp_digit) * 2 * 42);
|
|
pre_vx[0][0] = 1;
|
|
XMEMSET(pre_vy[0], 0, sizeof(sp_digit) * 2 * 42);
|
|
sp_1024_mont_sub_42(pre_nvy[0], p1024_mod, pre_vy[0], p1024_mod);
|
|
|
|
/* [2]P for adding */
|
|
XMEMCPY(c, p, sizeof(sp_point_1024));
|
|
XMEMSET(vx, 0, sizeof(sp_digit) * 2 * 42);
|
|
vx[0] = 1;
|
|
XMEMSET(vy, 0, sizeof(sp_digit) * 2 * 42);
|
|
sp_1024_accumulate_line_dbl_42(vx, vy, c, q, t);
|
|
|
|
/* 3, 5, ... */
|
|
for (i = 1; i < 16; i++) {
|
|
XMEMCPY(pre_vx[i], pre_vx[i-1], sizeof(sp_digit) * 2 * 42);
|
|
XMEMCPY(pre_vy[i], pre_vy[i-1], sizeof(sp_digit) * 2 * 42);
|
|
sp_1024_proj_mul_42(pre_vx[i], pre_vy[i], vx, vy, t);
|
|
sp_1024_accumulate_line_add_n_42(pre_vx[i], pre_vy[i], c,
|
|
q, p, t, 0);
|
|
sp_1024_mont_sub_42(pre_nvy[i], p1024_mod, pre_vy[i],
|
|
p1024_mod);
|
|
}
|
|
|
|
XMEMCPY(c->z, p1024_norm_mod, sizeof(sp_digit) * 42);
|
|
c->infinity = 0;
|
|
j = sp_1024_order_op_pre[0] / 2;
|
|
XMEMCPY(vx, pre_vx[j], sizeof(sp_digit) * 2 * 42);
|
|
XMEMCPY(vy, pre_vy[j], sizeof(sp_digit) * 2 * 42);
|
|
|
|
k = 0;
|
|
for (j = 0; j < sp_1024_order_op_pre[1]; j++) {
|
|
/* Accumulate line into v and double point. */
|
|
sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
|
|
precomp[k].y, q, t, 1);
|
|
k++;
|
|
}
|
|
|
|
for (i = 2; i < 290; i += 2) {
|
|
sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
|
|
precomp[k].y, q, t, 0);
|
|
k++;
|
|
|
|
j = sp_1024_order_op_pre[i];
|
|
if (j > 0) {
|
|
j /= 2;
|
|
/* Accumulate line into v. */
|
|
sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_vy[j], t);
|
|
}
|
|
else {
|
|
j = -j / 2;
|
|
/* Accumulate line into v. */
|
|
sp_1024_proj_mul_42(vx, vy, pre_vx[j], pre_nvy[j], t);
|
|
}
|
|
|
|
for (j = 0; j < sp_1024_order_op_pre[i + 1]; j++) {
|
|
/* Accumulate line into v and double point. */
|
|
sp_1024_accumulate_line_lc_42(vx, vy, precomp[k].x,
|
|
precomp[k].y, q, t, 1);
|
|
k++;
|
|
}
|
|
}
|
|
|
|
/* Final exponentiation */
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
sp_1024_proj_sqr_42(vx, vy, t);
|
|
|
|
/* Convert from PF_p[q] to F_p */
|
|
sp_1024_mont_inv_42(vx, vx, t);
|
|
sp_1024_mont_mul_42(r, vx, vy, p1024_mod, p1024_mp_mod);
|
|
XMEMSET(r + 42, 0, sizeof(sp_digit) * 42);
|
|
sp_1024_mont_reduce_42(r, p1024_mod, p1024_mp_mod);
|
|
|
|
err = sp_1024_to_mp(r, res);
|
|
}
|
|
|
|
#if (defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SP_NO_MALLOC)) || \
|
|
defined(WOLFSSL_SP_SMALL_STACK)
|
|
if (td != NULL) {
|
|
XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
}
|
|
#endif
|
|
sp_1024_point_free_42(c, 1, NULL);
|
|
sp_1024_point_free_42(q, 1, NULL);
|
|
sp_1024_point_free_42(p, 1, NULL);
|
|
return err;
|
|
}
|
|
|
|
#endif /* WOLFSSL_SP_SMALL */
|
|
#ifdef HAVE_ECC_CHECK_KEY
|
|
/* Read big endian unsigned byte array into r.
|
|
*
|
|
* r A single precision integer.
|
|
* size Maximum number of bytes to convert
|
|
* a Byte array.
|
|
* n Number of bytes in array to read.
|
|
*/
|
|
static void sp_1024_from_bin(sp_digit* r, int size, const byte* a, int n)
|
|
{
|
|
int i;
|
|
int j = 0;
|
|
word32 s = 0;
|
|
|
|
r[0] = 0;
|
|
for (i = n-1; i >= 0; i--) {
|
|
r[j] |= (((sp_digit)a[i]) << s);
|
|
if (s >= 17U) {
|
|
r[j] &= 0x1ffffff;
|
|
s = 25U - s;
|
|
if (j + 1 >= size) {
|
|
break;
|
|
}
|
|
r[++j] = (sp_digit)a[i] >> s;
|
|
s = 8U - s;
|
|
}
|
|
else {
|
|
s += 8U;
|
|
}
|
|
}
|
|
|
|
for (j++; j < size; j++) {
|
|
r[j] = 0;
|
|
}
|
|
}
|
|
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* point EC point.
|
|
* heap Heap to use if dynamically allocating.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
static int sp_1024_ecc_is_point_42(const sp_point_1024* point,
|
|
void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* t1 = NULL;
|
|
#else
|
|
sp_digit t1[42 * 4];
|
|
#endif
|
|
sp_digit* t2 = NULL;
|
|
sp_int32 n;
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
t1 = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42 * 4, heap, DYNAMIC_TYPE_ECC);
|
|
if (t1 == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
(void)heap;
|
|
|
|
if (err == MP_OKAY) {
|
|
t2 = t1 + 2 * 42;
|
|
|
|
sp_1024_sqr_42(t1, point->y);
|
|
(void)sp_1024_mod_42(t1, t1, p1024_mod);
|
|
sp_1024_sqr_42(t2, point->x);
|
|
(void)sp_1024_mod_42(t2, t2, p1024_mod);
|
|
sp_1024_mul_42(t2, t2, point->x);
|
|
(void)sp_1024_mod_42(t2, t2, p1024_mod);
|
|
(void)sp_1024_sub_42(t2, p1024_mod, t2);
|
|
sp_1024_mont_add_42(t1, t1, t2, p1024_mod);
|
|
|
|
sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
|
|
sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
|
|
sp_1024_mont_add_42(t1, t1, point->x, p1024_mod);
|
|
|
|
n = sp_1024_cmp_42(t1, p1024_mod);
|
|
sp_1024_cond_sub_42(t1, t1, p1024_mod, ~(n >> 24));
|
|
sp_1024_norm_42(t1);
|
|
if (!sp_1024_iszero_42(t1)) {
|
|
err = MP_VAL;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (t1 != NULL)
|
|
XFREE(t1, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the x and y oridinates are a valid point on the curve.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve and MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_is_point_1024(const mp_int* pX, const mp_int* pY)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_point_1024* pub = NULL;
|
|
#else
|
|
sp_point_1024 pub[1];
|
|
#endif
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024), NULL,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
sp_1024_from_mp(pub->x, 42, pX);
|
|
sp_1024_from_mp(pub->y, 42, pY);
|
|
sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one));
|
|
|
|
err = sp_1024_ecc_is_point_42(pub, NULL);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, NULL, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
|
|
/* Check that the private scalar generates the EC point (px, py), the point is
|
|
* on the curve and the point has the correct order.
|
|
*
|
|
* pX X ordinate of EC point.
|
|
* pY Y ordinate of EC point.
|
|
* privm Private scalar that generates EC point.
|
|
* returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is
|
|
* not on the curve, ECC_INF_E if the point does not have the correct order,
|
|
* ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and
|
|
* MP_OKAY otherwise.
|
|
*/
|
|
int sp_ecc_check_key_1024(const mp_int* pX, const mp_int* pY,
|
|
const mp_int* privm, void* heap)
|
|
{
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
sp_digit* priv = NULL;
|
|
sp_point_1024* pub = NULL;
|
|
#else
|
|
sp_digit priv[42];
|
|
sp_point_1024 pub[2];
|
|
#endif
|
|
sp_point_1024* p = NULL;
|
|
const byte one[1] = { 1 };
|
|
int err = MP_OKAY;
|
|
|
|
|
|
/* Quick check the lengs of public key ordinates and private key are in
|
|
* range. Proper check later.
|
|
*/
|
|
if (((mp_count_bits(pX) > 1024) ||
|
|
(mp_count_bits(pY) > 1024) ||
|
|
((privm != NULL) && (mp_count_bits(privm) > 1024)))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (err == MP_OKAY) {
|
|
pub = (sp_point_1024*)XMALLOC(sizeof(sp_point_1024) * 2, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (pub == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
if (err == MP_OKAY && privm) {
|
|
priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 42, heap,
|
|
DYNAMIC_TYPE_ECC);
|
|
if (priv == NULL)
|
|
err = MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
if (err == MP_OKAY) {
|
|
p = pub + 1;
|
|
|
|
sp_1024_from_mp(pub->x, 42, pX);
|
|
sp_1024_from_mp(pub->y, 42, pY);
|
|
sp_1024_from_bin(pub->z, 42, one, (int)sizeof(one));
|
|
if (privm)
|
|
sp_1024_from_mp(priv, 42, privm);
|
|
|
|
/* Check point at infinitiy. */
|
|
if ((sp_1024_iszero_42(pub->x) != 0) &&
|
|
(sp_1024_iszero_42(pub->y) != 0)) {
|
|
err = ECC_INF_E;
|
|
}
|
|
}
|
|
|
|
/* Check range of X and Y */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_1024_cmp_42(pub->x, p1024_mod) >= 0) ||
|
|
(sp_1024_cmp_42(pub->y, p1024_mod) >= 0))) {
|
|
err = ECC_OUT_OF_RANGE_E;
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Check point is on curve */
|
|
err = sp_1024_ecc_is_point_42(pub, heap);
|
|
}
|
|
|
|
if (err == MP_OKAY) {
|
|
/* Point * order = infinity */
|
|
err = sp_1024_ecc_mulmod_42(p, pub, p1024_order, 1, 1, heap);
|
|
}
|
|
/* Check result is infinity */
|
|
if ((err == MP_OKAY) && ((sp_1024_iszero_42(p->x) == 0) ||
|
|
(sp_1024_iszero_42(p->y) == 0))) {
|
|
err = ECC_INF_E;
|
|
}
|
|
|
|
if (privm) {
|
|
if (err == MP_OKAY) {
|
|
/* Base * private = point */
|
|
err = sp_1024_ecc_mulmod_base_42(p, priv, 1, 1, heap);
|
|
}
|
|
/* Check result is public key */
|
|
if ((err == MP_OKAY) &&
|
|
((sp_1024_cmp_42(p->x, pub->x) != 0) ||
|
|
(sp_1024_cmp_42(p->y, pub->y) != 0))) {
|
|
err = ECC_PRIV_KEY_E;
|
|
}
|
|
}
|
|
|
|
#ifdef WOLFSSL_SP_SMALL_STACK
|
|
if (pub != NULL)
|
|
XFREE(pub, heap, DYNAMIC_TYPE_ECC);
|
|
if (priv != NULL)
|
|
XFREE(priv, heap, DYNAMIC_TYPE_ECC);
|
|
#endif
|
|
|
|
return err;
|
|
}
|
|
#endif
|
|
#endif /* WOLFSSL_SP_1024 */
|
|
#endif /* WOLFCRYPT_HAVE_SAKKE */
|
|
#endif /* WOLFSSL_HAVE_SP_ECC */
|
|
#endif /* SP_WORD_SIZE == 32 */
|
|
#endif /* !WOLFSSL_SP_ASM */
|
|
#endif /* WOLFSSL_HAVE_SP_RSA | WOLFSSL_HAVE_SP_DH | WOLFSSL_HAVE_SP_ECC */
|