Xuyi Wang / wolfSSL

Dependents:   OS

Committer:
wolfSSL
Date:
Fri Jun 26 00:39:20 2015 +0000
Revision:
0:d92f9d21154c
Child:
3:6f956bdb3073
wolfSSL 3.6.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
wolfSSL 0:d92f9d21154c 1 /* ecc.c
wolfSSL 0:d92f9d21154c 2 *
wolfSSL 0:d92f9d21154c 3 * Copyright (C) 2006-2015 wolfSSL Inc.
wolfSSL 0:d92f9d21154c 4 *
wolfSSL 0:d92f9d21154c 5 * This file is part of wolfSSL. (formerly known as CyaSSL)
wolfSSL 0:d92f9d21154c 6 *
wolfSSL 0:d92f9d21154c 7 * wolfSSL is free software; you can redistribute it and/or modify
wolfSSL 0:d92f9d21154c 8 * it under the terms of the GNU General Public License as published by
wolfSSL 0:d92f9d21154c 9 * the Free Software Foundation; either version 2 of the License, or
wolfSSL 0:d92f9d21154c 10 * (at your option) any later version.
wolfSSL 0:d92f9d21154c 11 *
wolfSSL 0:d92f9d21154c 12 * wolfSSL is distributed in the hope that it will be useful,
wolfSSL 0:d92f9d21154c 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
wolfSSL 0:d92f9d21154c 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wolfSSL 0:d92f9d21154c 15 * GNU General Public License for more details.
wolfSSL 0:d92f9d21154c 16 *
wolfSSL 0:d92f9d21154c 17 * You should have received a copy of the GNU General Public License
wolfSSL 0:d92f9d21154c 18 * along with this program; if not, write to the Free Software
wolfSSL 0:d92f9d21154c 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
wolfSSL 0:d92f9d21154c 20 */
wolfSSL 0:d92f9d21154c 21
wolfSSL 0:d92f9d21154c 22
wolfSSL 0:d92f9d21154c 23 #ifdef HAVE_CONFIG_H
wolfSSL 0:d92f9d21154c 24 #include <config.h>
wolfSSL 0:d92f9d21154c 25 #endif
wolfSSL 0:d92f9d21154c 26
wolfSSL 0:d92f9d21154c 27 /* in case user set HAVE_ECC there */
wolfSSL 0:d92f9d21154c 28 #include <wolfssl/wolfcrypt/settings.h>
wolfSSL 0:d92f9d21154c 29
wolfSSL 0:d92f9d21154c 30 #ifdef HAVE_ECC
wolfSSL 0:d92f9d21154c 31
wolfSSL 0:d92f9d21154c 32 #include <wolfssl/wolfcrypt/ecc.h>
wolfSSL 0:d92f9d21154c 33 #include <wolfssl/wolfcrypt/asn.h>
wolfSSL 0:d92f9d21154c 34 #include <wolfssl/wolfcrypt/error-crypt.h>
wolfSSL 0:d92f9d21154c 35
wolfSSL 0:d92f9d21154c 36 #ifdef HAVE_ECC_ENCRYPT
wolfSSL 0:d92f9d21154c 37 #include <wolfssl/wolfcrypt/hmac.h>
wolfSSL 0:d92f9d21154c 38 #include <wolfssl/wolfcrypt/aes.h>
wolfSSL 0:d92f9d21154c 39 #endif
wolfSSL 0:d92f9d21154c 40
wolfSSL 0:d92f9d21154c 41 #ifdef NO_INLINE
wolfSSL 0:d92f9d21154c 42 #include <wolfssl/wolfcrypt/misc.h>
wolfSSL 0:d92f9d21154c 43 #else
wolfSSL 0:d92f9d21154c 44 #include <wolfcrypt/src/misc.c>
wolfSSL 0:d92f9d21154c 45 #endif
wolfSSL 0:d92f9d21154c 46
wolfSSL 0:d92f9d21154c 47 /* map
wolfSSL 0:d92f9d21154c 48
wolfSSL 0:d92f9d21154c 49 ptmul -> mulmod
wolfSSL 0:d92f9d21154c 50
wolfSSL 0:d92f9d21154c 51 */
wolfSSL 0:d92f9d21154c 52
wolfSSL 0:d92f9d21154c 53
wolfSSL 0:d92f9d21154c 54 /* p256 curve on by default whether user curves or not */
wolfSSL 0:d92f9d21154c 55 #if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 56 #define ECC112
wolfSSL 0:d92f9d21154c 57 #endif
wolfSSL 0:d92f9d21154c 58 #if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 59 #define ECC128
wolfSSL 0:d92f9d21154c 60 #endif
wolfSSL 0:d92f9d21154c 61 #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 62 #define ECC160
wolfSSL 0:d92f9d21154c 63 #endif
wolfSSL 0:d92f9d21154c 64 #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 65 #define ECC192
wolfSSL 0:d92f9d21154c 66 #endif
wolfSSL 0:d92f9d21154c 67 #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 68 #define ECC224
wolfSSL 0:d92f9d21154c 69 #endif
wolfSSL 0:d92f9d21154c 70 #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 71 #define ECC256
wolfSSL 0:d92f9d21154c 72 #endif
wolfSSL 0:d92f9d21154c 73 #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 74 #define ECC384
wolfSSL 0:d92f9d21154c 75 #endif
wolfSSL 0:d92f9d21154c 76 #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
wolfSSL 0:d92f9d21154c 77 #define ECC521
wolfSSL 0:d92f9d21154c 78 #endif
wolfSSL 0:d92f9d21154c 79
wolfSSL 0:d92f9d21154c 80
wolfSSL 0:d92f9d21154c 81
wolfSSL 0:d92f9d21154c 82 /* This holds the key settings. ***MUST*** be organized by size from
wolfSSL 0:d92f9d21154c 83 smallest to largest. */
wolfSSL 0:d92f9d21154c 84
wolfSSL 0:d92f9d21154c 85 const ecc_set_type ecc_sets[] = {
wolfSSL 0:d92f9d21154c 86 #ifdef ECC112
wolfSSL 0:d92f9d21154c 87 {
wolfSSL 0:d92f9d21154c 88 14,
wolfSSL 0:d92f9d21154c 89 "SECP112R1",
wolfSSL 0:d92f9d21154c 90 "DB7C2ABF62E35E668076BEAD208B",
wolfSSL 0:d92f9d21154c 91 "DB7C2ABF62E35E668076BEAD2088",
wolfSSL 0:d92f9d21154c 92 "659EF8BA043916EEDE8911702B22",
wolfSSL 0:d92f9d21154c 93 "DB7C2ABF62E35E7628DFAC6561C5",
wolfSSL 0:d92f9d21154c 94 "09487239995A5EE76B55F9C2F098",
wolfSSL 0:d92f9d21154c 95 "A89CE5AF8724C0A23E0E0FF77500"
wolfSSL 0:d92f9d21154c 96 },
wolfSSL 0:d92f9d21154c 97 #endif
wolfSSL 0:d92f9d21154c 98 #ifdef ECC128
wolfSSL 0:d92f9d21154c 99 {
wolfSSL 0:d92f9d21154c 100 16,
wolfSSL 0:d92f9d21154c 101 "SECP128R1",
wolfSSL 0:d92f9d21154c 102 "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
wolfSSL 0:d92f9d21154c 103 "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
wolfSSL 0:d92f9d21154c 104 "E87579C11079F43DD824993C2CEE5ED3",
wolfSSL 0:d92f9d21154c 105 "FFFFFFFE0000000075A30D1B9038A115",
wolfSSL 0:d92f9d21154c 106 "161FF7528B899B2D0C28607CA52C5B86",
wolfSSL 0:d92f9d21154c 107 "CF5AC8395BAFEB13C02DA292DDED7A83",
wolfSSL 0:d92f9d21154c 108 },
wolfSSL 0:d92f9d21154c 109 #endif
wolfSSL 0:d92f9d21154c 110 #ifdef ECC160
wolfSSL 0:d92f9d21154c 111 {
wolfSSL 0:d92f9d21154c 112 20,
wolfSSL 0:d92f9d21154c 113 "SECP160R1",
wolfSSL 0:d92f9d21154c 114 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
wolfSSL 0:d92f9d21154c 115 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
wolfSSL 0:d92f9d21154c 116 "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
wolfSSL 0:d92f9d21154c 117 "0100000000000000000001F4C8F927AED3CA752257",
wolfSSL 0:d92f9d21154c 118 "4A96B5688EF573284664698968C38BB913CBFC82",
wolfSSL 0:d92f9d21154c 119 "23A628553168947D59DCC912042351377AC5FB32",
wolfSSL 0:d92f9d21154c 120 },
wolfSSL 0:d92f9d21154c 121 #endif
wolfSSL 0:d92f9d21154c 122 #ifdef ECC192
wolfSSL 0:d92f9d21154c 123 {
wolfSSL 0:d92f9d21154c 124 24,
wolfSSL 0:d92f9d21154c 125 "ECC-192",
wolfSSL 0:d92f9d21154c 126 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
wolfSSL 0:d92f9d21154c 127 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
wolfSSL 0:d92f9d21154c 128 "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
wolfSSL 0:d92f9d21154c 129 "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
wolfSSL 0:d92f9d21154c 130 "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
wolfSSL 0:d92f9d21154c 131 "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
wolfSSL 0:d92f9d21154c 132 },
wolfSSL 0:d92f9d21154c 133 #endif
wolfSSL 0:d92f9d21154c 134 #ifdef ECC224
wolfSSL 0:d92f9d21154c 135 {
wolfSSL 0:d92f9d21154c 136 28,
wolfSSL 0:d92f9d21154c 137 "ECC-224",
wolfSSL 0:d92f9d21154c 138 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
wolfSSL 0:d92f9d21154c 139 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
wolfSSL 0:d92f9d21154c 140 "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
wolfSSL 0:d92f9d21154c 141 "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
wolfSSL 0:d92f9d21154c 142 "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
wolfSSL 0:d92f9d21154c 143 "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
wolfSSL 0:d92f9d21154c 144 },
wolfSSL 0:d92f9d21154c 145 #endif
wolfSSL 0:d92f9d21154c 146 #ifdef ECC256
wolfSSL 0:d92f9d21154c 147 {
wolfSSL 0:d92f9d21154c 148 32,
wolfSSL 0:d92f9d21154c 149 "ECC-256",
wolfSSL 0:d92f9d21154c 150 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
wolfSSL 0:d92f9d21154c 151 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
wolfSSL 0:d92f9d21154c 152 "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
wolfSSL 0:d92f9d21154c 153 "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
wolfSSL 0:d92f9d21154c 154 "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
wolfSSL 0:d92f9d21154c 155 "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
wolfSSL 0:d92f9d21154c 156 },
wolfSSL 0:d92f9d21154c 157 #endif
wolfSSL 0:d92f9d21154c 158 #ifdef ECC384
wolfSSL 0:d92f9d21154c 159 {
wolfSSL 0:d92f9d21154c 160 48,
wolfSSL 0:d92f9d21154c 161 "ECC-384",
wolfSSL 0:d92f9d21154c 162 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
wolfSSL 0:d92f9d21154c 163 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
wolfSSL 0:d92f9d21154c 164 "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
wolfSSL 0:d92f9d21154c 165 "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
wolfSSL 0:d92f9d21154c 166 "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
wolfSSL 0:d92f9d21154c 167 "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
wolfSSL 0:d92f9d21154c 168 },
wolfSSL 0:d92f9d21154c 169 #endif
wolfSSL 0:d92f9d21154c 170 #ifdef ECC521
wolfSSL 0:d92f9d21154c 171 {
wolfSSL 0:d92f9d21154c 172 66,
wolfSSL 0:d92f9d21154c 173 "ECC-521",
wolfSSL 0:d92f9d21154c 174 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
wolfSSL 0:d92f9d21154c 175 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
wolfSSL 0:d92f9d21154c 176 "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
wolfSSL 0:d92f9d21154c 177 "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
wolfSSL 0:d92f9d21154c 178 "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
wolfSSL 0:d92f9d21154c 179 "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
wolfSSL 0:d92f9d21154c 180 },
wolfSSL 0:d92f9d21154c 181 #endif
wolfSSL 0:d92f9d21154c 182 {
wolfSSL 0:d92f9d21154c 183 0,
wolfSSL 0:d92f9d21154c 184 NULL, NULL, NULL, NULL, NULL, NULL, NULL
wolfSSL 0:d92f9d21154c 185 }
wolfSSL 0:d92f9d21154c 186 };
wolfSSL 0:d92f9d21154c 187
wolfSSL 0:d92f9d21154c 188
wolfSSL 0:d92f9d21154c 189 ecc_point* ecc_new_point(void);
wolfSSL 0:d92f9d21154c 190 void ecc_del_point(ecc_point* p);
wolfSSL 0:d92f9d21154c 191 int ecc_map(ecc_point*, mp_int*, mp_digit*);
wolfSSL 0:d92f9d21154c 192 int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
wolfSSL 0:d92f9d21154c 193 mp_int* modulus, mp_digit* mp);
wolfSSL 0:d92f9d21154c 194 int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 195 mp_digit* mp);
wolfSSL 0:d92f9d21154c 196 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 197 int map);
wolfSSL 0:d92f9d21154c 198 static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order);
wolfSSL 0:d92f9d21154c 199 #ifdef ECC_SHAMIR
wolfSSL 0:d92f9d21154c 200 static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB,
wolfSSL 0:d92f9d21154c 201 ecc_point* C, mp_int* modulus);
wolfSSL 0:d92f9d21154c 202 #endif
wolfSSL 0:d92f9d21154c 203
wolfSSL 0:d92f9d21154c 204 int mp_jacobi(mp_int* a, mp_int* p, int* c);
wolfSSL 0:d92f9d21154c 205 int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
wolfSSL 0:d92f9d21154c 206 int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d);
wolfSSL 0:d92f9d21154c 207
wolfSSL 0:d92f9d21154c 208 #ifdef HAVE_COMP_KEY
wolfSSL 0:d92f9d21154c 209 static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
wolfSSL 0:d92f9d21154c 210 #endif
wolfSSL 0:d92f9d21154c 211
wolfSSL 0:d92f9d21154c 212 /* helper for either lib */
wolfSSL 0:d92f9d21154c 213 static int get_digit_count(mp_int* a)
wolfSSL 0:d92f9d21154c 214 {
wolfSSL 0:d92f9d21154c 215 if (a == NULL)
wolfSSL 0:d92f9d21154c 216 return 0;
wolfSSL 0:d92f9d21154c 217
wolfSSL 0:d92f9d21154c 218 return a->used;
wolfSSL 0:d92f9d21154c 219 }
wolfSSL 0:d92f9d21154c 220
wolfSSL 0:d92f9d21154c 221 /* helper for either lib */
wolfSSL 0:d92f9d21154c 222 static mp_digit get_digit(mp_int* a, int n)
wolfSSL 0:d92f9d21154c 223 {
wolfSSL 0:d92f9d21154c 224 if (a == NULL)
wolfSSL 0:d92f9d21154c 225 return 0;
wolfSSL 0:d92f9d21154c 226
wolfSSL 0:d92f9d21154c 227 return (n >= a->used || n < 0) ? 0 : a->dp[n];
wolfSSL 0:d92f9d21154c 228 }
wolfSSL 0:d92f9d21154c 229
wolfSSL 0:d92f9d21154c 230
wolfSSL 0:d92f9d21154c 231 #if defined(USE_FAST_MATH)
wolfSSL 0:d92f9d21154c 232
wolfSSL 0:d92f9d21154c 233 /* fast math accelerated version, but not for fp ecc yet */
wolfSSL 0:d92f9d21154c 234
wolfSSL 0:d92f9d21154c 235 /**
wolfSSL 0:d92f9d21154c 236 Add two ECC points
wolfSSL 0:d92f9d21154c 237 P The point to add
wolfSSL 0:d92f9d21154c 238 Q The point to add
wolfSSL 0:d92f9d21154c 239 R [out] The destination of the double
wolfSSL 0:d92f9d21154c 240 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 241 mp The "b" value from montgomery_setup()
wolfSSL 0:d92f9d21154c 242 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 243 */
wolfSSL 0:d92f9d21154c 244 int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R,
wolfSSL 0:d92f9d21154c 245 mp_int* modulus, mp_digit* mp)
wolfSSL 0:d92f9d21154c 246 {
wolfSSL 0:d92f9d21154c 247 fp_int t1, t2, x, y, z;
wolfSSL 0:d92f9d21154c 248 int err;
wolfSSL 0:d92f9d21154c 249
wolfSSL 0:d92f9d21154c 250 if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
wolfSSL 0:d92f9d21154c 251 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 252
wolfSSL 0:d92f9d21154c 253 if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 254 return err;
wolfSSL 0:d92f9d21154c 255 }
wolfSSL 0:d92f9d21154c 256
wolfSSL 0:d92f9d21154c 257 /* should we dbl instead? */
wolfSSL 0:d92f9d21154c 258 fp_sub(modulus, Q->y, &t1);
wolfSSL 0:d92f9d21154c 259 if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
wolfSSL 0:d92f9d21154c 260 (get_digit_count(Q->z) && fp_cmp(P->z, Q->z) == FP_EQ) &&
wolfSSL 0:d92f9d21154c 261 (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
wolfSSL 0:d92f9d21154c 262 return ecc_projective_dbl_point(P, R, modulus, mp);
wolfSSL 0:d92f9d21154c 263 }
wolfSSL 0:d92f9d21154c 264
wolfSSL 0:d92f9d21154c 265 fp_copy(P->x, &x);
wolfSSL 0:d92f9d21154c 266 fp_copy(P->y, &y);
wolfSSL 0:d92f9d21154c 267 fp_copy(P->z, &z);
wolfSSL 0:d92f9d21154c 268
wolfSSL 0:d92f9d21154c 269 /* if Z is one then these are no-operations */
wolfSSL 0:d92f9d21154c 270 if (get_digit_count(Q->z)) {
wolfSSL 0:d92f9d21154c 271 /* T1 = Z' * Z' */
wolfSSL 0:d92f9d21154c 272 fp_sqr(Q->z, &t1);
wolfSSL 0:d92f9d21154c 273 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 274 /* X = X * T1 */
wolfSSL 0:d92f9d21154c 275 fp_mul(&t1, &x, &x);
wolfSSL 0:d92f9d21154c 276 fp_montgomery_reduce(&x, modulus, *mp);
wolfSSL 0:d92f9d21154c 277 /* T1 = Z' * T1 */
wolfSSL 0:d92f9d21154c 278 fp_mul(Q->z, &t1, &t1);
wolfSSL 0:d92f9d21154c 279 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 280 /* Y = Y * T1 */
wolfSSL 0:d92f9d21154c 281 fp_mul(&t1, &y, &y);
wolfSSL 0:d92f9d21154c 282 fp_montgomery_reduce(&y, modulus, *mp);
wolfSSL 0:d92f9d21154c 283 }
wolfSSL 0:d92f9d21154c 284
wolfSSL 0:d92f9d21154c 285 /* T1 = Z*Z */
wolfSSL 0:d92f9d21154c 286 fp_sqr(&z, &t1);
wolfSSL 0:d92f9d21154c 287 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 288 /* T2 = X' * T1 */
wolfSSL 0:d92f9d21154c 289 fp_mul(Q->x, &t1, &t2);
wolfSSL 0:d92f9d21154c 290 fp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 291 /* T1 = Z * T1 */
wolfSSL 0:d92f9d21154c 292 fp_mul(&z, &t1, &t1);
wolfSSL 0:d92f9d21154c 293 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 294 /* T1 = Y' * T1 */
wolfSSL 0:d92f9d21154c 295 fp_mul(Q->y, &t1, &t1);
wolfSSL 0:d92f9d21154c 296 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 297
wolfSSL 0:d92f9d21154c 298 /* Y = Y - T1 */
wolfSSL 0:d92f9d21154c 299 fp_sub(&y, &t1, &y);
wolfSSL 0:d92f9d21154c 300 if (fp_cmp_d(&y, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 301 fp_add(&y, modulus, &y);
wolfSSL 0:d92f9d21154c 302 }
wolfSSL 0:d92f9d21154c 303 /* T1 = 2T1 */
wolfSSL 0:d92f9d21154c 304 fp_add(&t1, &t1, &t1);
wolfSSL 0:d92f9d21154c 305 if (fp_cmp(&t1, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 306 fp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 307 }
wolfSSL 0:d92f9d21154c 308 /* T1 = Y + T1 */
wolfSSL 0:d92f9d21154c 309 fp_add(&t1, &y, &t1);
wolfSSL 0:d92f9d21154c 310 if (fp_cmp(&t1, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 311 fp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 312 }
wolfSSL 0:d92f9d21154c 313 /* X = X - T2 */
wolfSSL 0:d92f9d21154c 314 fp_sub(&x, &t2, &x);
wolfSSL 0:d92f9d21154c 315 if (fp_cmp_d(&x, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 316 fp_add(&x, modulus, &x);
wolfSSL 0:d92f9d21154c 317 }
wolfSSL 0:d92f9d21154c 318 /* T2 = 2T2 */
wolfSSL 0:d92f9d21154c 319 fp_add(&t2, &t2, &t2);
wolfSSL 0:d92f9d21154c 320 if (fp_cmp(&t2, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 321 fp_sub(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 322 }
wolfSSL 0:d92f9d21154c 323 /* T2 = X + T2 */
wolfSSL 0:d92f9d21154c 324 fp_add(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 325 if (fp_cmp(&t2, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 326 fp_sub(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 327 }
wolfSSL 0:d92f9d21154c 328
wolfSSL 0:d92f9d21154c 329 /* if Z' != 1 */
wolfSSL 0:d92f9d21154c 330 if (get_digit_count(Q->z)) {
wolfSSL 0:d92f9d21154c 331 /* Z = Z * Z' */
wolfSSL 0:d92f9d21154c 332 fp_mul(&z, Q->z, &z);
wolfSSL 0:d92f9d21154c 333 fp_montgomery_reduce(&z, modulus, *mp);
wolfSSL 0:d92f9d21154c 334 }
wolfSSL 0:d92f9d21154c 335
wolfSSL 0:d92f9d21154c 336 /* Z = Z * X */
wolfSSL 0:d92f9d21154c 337 fp_mul(&z, &x, &z);
wolfSSL 0:d92f9d21154c 338 fp_montgomery_reduce(&z, modulus, *mp);
wolfSSL 0:d92f9d21154c 339
wolfSSL 0:d92f9d21154c 340 /* T1 = T1 * X */
wolfSSL 0:d92f9d21154c 341 fp_mul(&t1, &x, &t1);
wolfSSL 0:d92f9d21154c 342 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 343 /* X = X * X */
wolfSSL 0:d92f9d21154c 344 fp_sqr(&x, &x);
wolfSSL 0:d92f9d21154c 345 fp_montgomery_reduce(&x, modulus, *mp);
wolfSSL 0:d92f9d21154c 346 /* T2 = T2 * x */
wolfSSL 0:d92f9d21154c 347 fp_mul(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 348 fp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 349 /* T1 = T1 * X */
wolfSSL 0:d92f9d21154c 350 fp_mul(&t1, &x, &t1);
wolfSSL 0:d92f9d21154c 351 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 352
wolfSSL 0:d92f9d21154c 353 /* X = Y*Y */
wolfSSL 0:d92f9d21154c 354 fp_sqr(&y, &x);
wolfSSL 0:d92f9d21154c 355 fp_montgomery_reduce(&x, modulus, *mp);
wolfSSL 0:d92f9d21154c 356 /* X = X - T2 */
wolfSSL 0:d92f9d21154c 357 fp_sub(&x, &t2, &x);
wolfSSL 0:d92f9d21154c 358 if (fp_cmp_d(&x, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 359 fp_add(&x, modulus, &x);
wolfSSL 0:d92f9d21154c 360 }
wolfSSL 0:d92f9d21154c 361
wolfSSL 0:d92f9d21154c 362 /* T2 = T2 - X */
wolfSSL 0:d92f9d21154c 363 fp_sub(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 364 if (fp_cmp_d(&t2, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 365 fp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 366 }
wolfSSL 0:d92f9d21154c 367 /* T2 = T2 - X */
wolfSSL 0:d92f9d21154c 368 fp_sub(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 369 if (fp_cmp_d(&t2, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 370 fp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 371 }
wolfSSL 0:d92f9d21154c 372 /* T2 = T2 * Y */
wolfSSL 0:d92f9d21154c 373 fp_mul(&t2, &y, &t2);
wolfSSL 0:d92f9d21154c 374 fp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 375 /* Y = T2 - T1 */
wolfSSL 0:d92f9d21154c 376 fp_sub(&t2, &t1, &y);
wolfSSL 0:d92f9d21154c 377 if (fp_cmp_d(&y, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 378 fp_add(&y, modulus, &y);
wolfSSL 0:d92f9d21154c 379 }
wolfSSL 0:d92f9d21154c 380 /* Y = Y/2 */
wolfSSL 0:d92f9d21154c 381 if (fp_isodd(&y)) {
wolfSSL 0:d92f9d21154c 382 fp_add(&y, modulus, &y);
wolfSSL 0:d92f9d21154c 383 }
wolfSSL 0:d92f9d21154c 384 fp_div_2(&y, &y);
wolfSSL 0:d92f9d21154c 385
wolfSSL 0:d92f9d21154c 386 fp_copy(&x, R->x);
wolfSSL 0:d92f9d21154c 387 fp_copy(&y, R->y);
wolfSSL 0:d92f9d21154c 388 fp_copy(&z, R->z);
wolfSSL 0:d92f9d21154c 389
wolfSSL 0:d92f9d21154c 390 return MP_OKAY;
wolfSSL 0:d92f9d21154c 391 }
wolfSSL 0:d92f9d21154c 392
wolfSSL 0:d92f9d21154c 393
wolfSSL 0:d92f9d21154c 394 /**
wolfSSL 0:d92f9d21154c 395 Double an ECC point
wolfSSL 0:d92f9d21154c 396 P The point to double
wolfSSL 0:d92f9d21154c 397 R [out] The destination of the double
wolfSSL 0:d92f9d21154c 398 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 399 mp The "b" value from montgomery_setup()
wolfSSL 0:d92f9d21154c 400 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 401 */
wolfSSL 0:d92f9d21154c 402 int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 403 mp_digit* mp)
wolfSSL 0:d92f9d21154c 404 {
wolfSSL 0:d92f9d21154c 405 fp_int t1, t2;
wolfSSL 0:d92f9d21154c 406 int err;
wolfSSL 0:d92f9d21154c 407
wolfSSL 0:d92f9d21154c 408 if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
wolfSSL 0:d92f9d21154c 409 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 410
wolfSSL 0:d92f9d21154c 411 if (P != R) {
wolfSSL 0:d92f9d21154c 412 fp_copy(P->x, R->x);
wolfSSL 0:d92f9d21154c 413 fp_copy(P->y, R->y);
wolfSSL 0:d92f9d21154c 414 fp_copy(P->z, R->z);
wolfSSL 0:d92f9d21154c 415 }
wolfSSL 0:d92f9d21154c 416
wolfSSL 0:d92f9d21154c 417 if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 418 return err;
wolfSSL 0:d92f9d21154c 419 }
wolfSSL 0:d92f9d21154c 420
wolfSSL 0:d92f9d21154c 421 /* t1 = Z * Z */
wolfSSL 0:d92f9d21154c 422 fp_sqr(R->z, &t1);
wolfSSL 0:d92f9d21154c 423 fp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 424 /* Z = Y * Z */
wolfSSL 0:d92f9d21154c 425 fp_mul(R->z, R->y, R->z);
wolfSSL 0:d92f9d21154c 426 fp_montgomery_reduce(R->z, modulus, *mp);
wolfSSL 0:d92f9d21154c 427 /* Z = 2Z */
wolfSSL 0:d92f9d21154c 428 fp_add(R->z, R->z, R->z);
wolfSSL 0:d92f9d21154c 429 if (fp_cmp(R->z, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 430 fp_sub(R->z, modulus, R->z);
wolfSSL 0:d92f9d21154c 431 }
wolfSSL 0:d92f9d21154c 432
wolfSSL 0:d92f9d21154c 433 /* &t2 = X - T1 */
wolfSSL 0:d92f9d21154c 434 fp_sub(R->x, &t1, &t2);
wolfSSL 0:d92f9d21154c 435 if (fp_cmp_d(&t2, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 436 fp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 437 }
wolfSSL 0:d92f9d21154c 438 /* T1 = X + T1 */
wolfSSL 0:d92f9d21154c 439 fp_add(&t1, R->x, &t1);
wolfSSL 0:d92f9d21154c 440 if (fp_cmp(&t1, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 441 fp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 442 }
wolfSSL 0:d92f9d21154c 443 /* T2 = T1 * T2 */
wolfSSL 0:d92f9d21154c 444 fp_mul(&t1, &t2, &t2);
wolfSSL 0:d92f9d21154c 445 fp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 446 /* T1 = 2T2 */
wolfSSL 0:d92f9d21154c 447 fp_add(&t2, &t2, &t1);
wolfSSL 0:d92f9d21154c 448 if (fp_cmp(&t1, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 449 fp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 450 }
wolfSSL 0:d92f9d21154c 451 /* T1 = T1 + T2 */
wolfSSL 0:d92f9d21154c 452 fp_add(&t1, &t2, &t1);
wolfSSL 0:d92f9d21154c 453 if (fp_cmp(&t1, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 454 fp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 455 }
wolfSSL 0:d92f9d21154c 456
wolfSSL 0:d92f9d21154c 457 /* Y = 2Y */
wolfSSL 0:d92f9d21154c 458 fp_add(R->y, R->y, R->y);
wolfSSL 0:d92f9d21154c 459 if (fp_cmp(R->y, modulus) != FP_LT) {
wolfSSL 0:d92f9d21154c 460 fp_sub(R->y, modulus, R->y);
wolfSSL 0:d92f9d21154c 461 }
wolfSSL 0:d92f9d21154c 462 /* Y = Y * Y */
wolfSSL 0:d92f9d21154c 463 fp_sqr(R->y, R->y);
wolfSSL 0:d92f9d21154c 464 fp_montgomery_reduce(R->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 465 /* T2 = Y * Y */
wolfSSL 0:d92f9d21154c 466 fp_sqr(R->y, &t2);
wolfSSL 0:d92f9d21154c 467 fp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 468 /* T2 = T2/2 */
wolfSSL 0:d92f9d21154c 469 if (fp_isodd(&t2)) {
wolfSSL 0:d92f9d21154c 470 fp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 471 }
wolfSSL 0:d92f9d21154c 472 fp_div_2(&t2, &t2);
wolfSSL 0:d92f9d21154c 473 /* Y = Y * X */
wolfSSL 0:d92f9d21154c 474 fp_mul(R->y, R->x, R->y);
wolfSSL 0:d92f9d21154c 475 fp_montgomery_reduce(R->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 476
wolfSSL 0:d92f9d21154c 477 /* X = T1 * T1 */
wolfSSL 0:d92f9d21154c 478 fp_sqr(&t1, R->x);
wolfSSL 0:d92f9d21154c 479 fp_montgomery_reduce(R->x, modulus, *mp);
wolfSSL 0:d92f9d21154c 480 /* X = X - Y */
wolfSSL 0:d92f9d21154c 481 fp_sub(R->x, R->y, R->x);
wolfSSL 0:d92f9d21154c 482 if (fp_cmp_d(R->x, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 483 fp_add(R->x, modulus, R->x);
wolfSSL 0:d92f9d21154c 484 }
wolfSSL 0:d92f9d21154c 485 /* X = X - Y */
wolfSSL 0:d92f9d21154c 486 fp_sub(R->x, R->y, R->x);
wolfSSL 0:d92f9d21154c 487 if (fp_cmp_d(R->x, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 488 fp_add(R->x, modulus, R->x);
wolfSSL 0:d92f9d21154c 489 }
wolfSSL 0:d92f9d21154c 490
wolfSSL 0:d92f9d21154c 491 /* Y = Y - X */
wolfSSL 0:d92f9d21154c 492 fp_sub(R->y, R->x, R->y);
wolfSSL 0:d92f9d21154c 493 if (fp_cmp_d(R->y, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 494 fp_add(R->y, modulus, R->y);
wolfSSL 0:d92f9d21154c 495 }
wolfSSL 0:d92f9d21154c 496 /* Y = Y * T1 */
wolfSSL 0:d92f9d21154c 497 fp_mul(R->y, &t1, R->y);
wolfSSL 0:d92f9d21154c 498 fp_montgomery_reduce(R->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 499 /* Y = Y - T2 */
wolfSSL 0:d92f9d21154c 500 fp_sub(R->y, &t2, R->y);
wolfSSL 0:d92f9d21154c 501 if (fp_cmp_d(R->y, 0) == FP_LT) {
wolfSSL 0:d92f9d21154c 502 fp_add(R->y, modulus, R->y);
wolfSSL 0:d92f9d21154c 503 }
wolfSSL 0:d92f9d21154c 504
wolfSSL 0:d92f9d21154c 505 return MP_OKAY;
wolfSSL 0:d92f9d21154c 506 }
wolfSSL 0:d92f9d21154c 507
wolfSSL 0:d92f9d21154c 508 #else /* USE_FAST_MATH */
wolfSSL 0:d92f9d21154c 509
wolfSSL 0:d92f9d21154c 510 /**
wolfSSL 0:d92f9d21154c 511 Add two ECC points
wolfSSL 0:d92f9d21154c 512 P The point to add
wolfSSL 0:d92f9d21154c 513 Q The point to add
wolfSSL 0:d92f9d21154c 514 R [out] The destination of the double
wolfSSL 0:d92f9d21154c 515 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 516 mp The "b" value from montgomery_setup()
wolfSSL 0:d92f9d21154c 517 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 518 */
wolfSSL 0:d92f9d21154c 519 int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
wolfSSL 0:d92f9d21154c 520 mp_int* modulus, mp_digit* mp)
wolfSSL 0:d92f9d21154c 521 {
wolfSSL 0:d92f9d21154c 522 mp_int t1;
wolfSSL 0:d92f9d21154c 523 mp_int t2;
wolfSSL 0:d92f9d21154c 524 mp_int x;
wolfSSL 0:d92f9d21154c 525 mp_int y;
wolfSSL 0:d92f9d21154c 526 mp_int z;
wolfSSL 0:d92f9d21154c 527 int err;
wolfSSL 0:d92f9d21154c 528
wolfSSL 0:d92f9d21154c 529 if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
wolfSSL 0:d92f9d21154c 530 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 531
wolfSSL 0:d92f9d21154c 532 if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 533 return err;
wolfSSL 0:d92f9d21154c 534 }
wolfSSL 0:d92f9d21154c 535
wolfSSL 0:d92f9d21154c 536 /* should we dbl instead? */
wolfSSL 0:d92f9d21154c 537 err = mp_sub(modulus, Q->y, &t1);
wolfSSL 0:d92f9d21154c 538
wolfSSL 0:d92f9d21154c 539 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 540 if ( (mp_cmp(P->x, Q->x) == MP_EQ) &&
wolfSSL 0:d92f9d21154c 541 (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) &&
wolfSSL 0:d92f9d21154c 542 (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) {
wolfSSL 0:d92f9d21154c 543 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 544 mp_clear(&t2);
wolfSSL 0:d92f9d21154c 545 mp_clear(&x);
wolfSSL 0:d92f9d21154c 546 mp_clear(&y);
wolfSSL 0:d92f9d21154c 547 mp_clear(&z);
wolfSSL 0:d92f9d21154c 548
wolfSSL 0:d92f9d21154c 549 return ecc_projective_dbl_point(P, R, modulus, mp);
wolfSSL 0:d92f9d21154c 550 }
wolfSSL 0:d92f9d21154c 551 }
wolfSSL 0:d92f9d21154c 552
wolfSSL 0:d92f9d21154c 553 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 554 err = mp_copy(P->x, &x);
wolfSSL 0:d92f9d21154c 555 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 556 err = mp_copy(P->y, &y);
wolfSSL 0:d92f9d21154c 557 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 558 err = mp_copy(P->z, &z);
wolfSSL 0:d92f9d21154c 559
wolfSSL 0:d92f9d21154c 560 /* if Z is one then these are no-operations */
wolfSSL 0:d92f9d21154c 561 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 562 if (get_digit_count(Q->z)) {
wolfSSL 0:d92f9d21154c 563 /* T1 = Z' * Z' */
wolfSSL 0:d92f9d21154c 564 err = mp_sqr(Q->z, &t1);
wolfSSL 0:d92f9d21154c 565 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 566 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 567
wolfSSL 0:d92f9d21154c 568 /* X = X * T1 */
wolfSSL 0:d92f9d21154c 569 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 570 err = mp_mul(&t1, &x, &x);
wolfSSL 0:d92f9d21154c 571 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 572 err = mp_montgomery_reduce(&x, modulus, *mp);
wolfSSL 0:d92f9d21154c 573
wolfSSL 0:d92f9d21154c 574 /* T1 = Z' * T1 */
wolfSSL 0:d92f9d21154c 575 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 576 err = mp_mul(Q->z, &t1, &t1);
wolfSSL 0:d92f9d21154c 577 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 578 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 579
wolfSSL 0:d92f9d21154c 580 /* Y = Y * T1 */
wolfSSL 0:d92f9d21154c 581 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 582 err = mp_mul(&t1, &y, &y);
wolfSSL 0:d92f9d21154c 583 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 584 err = mp_montgomery_reduce(&y, modulus, *mp);
wolfSSL 0:d92f9d21154c 585 }
wolfSSL 0:d92f9d21154c 586 }
wolfSSL 0:d92f9d21154c 587
wolfSSL 0:d92f9d21154c 588 /* T1 = Z*Z */
wolfSSL 0:d92f9d21154c 589 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 590 err = mp_sqr(&z, &t1);
wolfSSL 0:d92f9d21154c 591 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 592 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 593
wolfSSL 0:d92f9d21154c 594 /* T2 = X' * T1 */
wolfSSL 0:d92f9d21154c 595 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 596 err = mp_mul(Q->x, &t1, &t2);
wolfSSL 0:d92f9d21154c 597 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 598 err = mp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 599
wolfSSL 0:d92f9d21154c 600 /* T1 = Z * T1 */
wolfSSL 0:d92f9d21154c 601 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 602 err = mp_mul(&z, &t1, &t1);
wolfSSL 0:d92f9d21154c 603 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 604 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 605
wolfSSL 0:d92f9d21154c 606 /* T1 = Y' * T1 */
wolfSSL 0:d92f9d21154c 607 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 608 err = mp_mul(Q->y, &t1, &t1);
wolfSSL 0:d92f9d21154c 609 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 610 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 611
wolfSSL 0:d92f9d21154c 612 /* Y = Y - T1 */
wolfSSL 0:d92f9d21154c 613 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 614 err = mp_sub(&y, &t1, &y);
wolfSSL 0:d92f9d21154c 615 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 616 if (mp_cmp_d(&y, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 617 err = mp_add(&y, modulus, &y);
wolfSSL 0:d92f9d21154c 618 }
wolfSSL 0:d92f9d21154c 619 /* T1 = 2T1 */
wolfSSL 0:d92f9d21154c 620 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 621 err = mp_add(&t1, &t1, &t1);
wolfSSL 0:d92f9d21154c 622 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 623 if (mp_cmp(&t1, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 624 err = mp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 625 }
wolfSSL 0:d92f9d21154c 626 /* T1 = Y + T1 */
wolfSSL 0:d92f9d21154c 627 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 628 err = mp_add(&t1, &y, &t1);
wolfSSL 0:d92f9d21154c 629 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 630 if (mp_cmp(&t1, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 631 err = mp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 632 }
wolfSSL 0:d92f9d21154c 633 /* X = X - T2 */
wolfSSL 0:d92f9d21154c 634 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 635 err = mp_sub(&x, &t2, &x);
wolfSSL 0:d92f9d21154c 636 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 637 if (mp_cmp_d(&x, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 638 err = mp_add(&x, modulus, &x);
wolfSSL 0:d92f9d21154c 639 }
wolfSSL 0:d92f9d21154c 640 /* T2 = 2T2 */
wolfSSL 0:d92f9d21154c 641 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 642 err = mp_add(&t2, &t2, &t2);
wolfSSL 0:d92f9d21154c 643 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 644 if (mp_cmp(&t2, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 645 err = mp_sub(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 646 }
wolfSSL 0:d92f9d21154c 647 /* T2 = X + T2 */
wolfSSL 0:d92f9d21154c 648 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 649 err = mp_add(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 650 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 651 if (mp_cmp(&t2, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 652 err = mp_sub(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 653 }
wolfSSL 0:d92f9d21154c 654
wolfSSL 0:d92f9d21154c 655 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 656 if (get_digit_count(Q->z)) {
wolfSSL 0:d92f9d21154c 657 /* Z = Z * Z' */
wolfSSL 0:d92f9d21154c 658 err = mp_mul(&z, Q->z, &z);
wolfSSL 0:d92f9d21154c 659 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 660 err = mp_montgomery_reduce(&z, modulus, *mp);
wolfSSL 0:d92f9d21154c 661 }
wolfSSL 0:d92f9d21154c 662 }
wolfSSL 0:d92f9d21154c 663
wolfSSL 0:d92f9d21154c 664 /* Z = Z * X */
wolfSSL 0:d92f9d21154c 665 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 666 err = mp_mul(&z, &x, &z);
wolfSSL 0:d92f9d21154c 667 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 668 err = mp_montgomery_reduce(&z, modulus, *mp);
wolfSSL 0:d92f9d21154c 669
wolfSSL 0:d92f9d21154c 670 /* T1 = T1 * X */
wolfSSL 0:d92f9d21154c 671 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 672 err = mp_mul(&t1, &x, &t1);
wolfSSL 0:d92f9d21154c 673 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 674 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 675
wolfSSL 0:d92f9d21154c 676 /* X = X * X */
wolfSSL 0:d92f9d21154c 677 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 678 err = mp_sqr(&x, &x);
wolfSSL 0:d92f9d21154c 679 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 680 err = mp_montgomery_reduce(&x, modulus, *mp);
wolfSSL 0:d92f9d21154c 681
wolfSSL 0:d92f9d21154c 682 /* T2 = T2 * x */
wolfSSL 0:d92f9d21154c 683 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 684 err = mp_mul(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 685 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 686 err = mp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 687
wolfSSL 0:d92f9d21154c 688 /* T1 = T1 * X */
wolfSSL 0:d92f9d21154c 689 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 690 err = mp_mul(&t1, &x, &t1);
wolfSSL 0:d92f9d21154c 691 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 692 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 693
wolfSSL 0:d92f9d21154c 694 /* X = Y*Y */
wolfSSL 0:d92f9d21154c 695 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 696 err = mp_sqr(&y, &x);
wolfSSL 0:d92f9d21154c 697 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 698 err = mp_montgomery_reduce(&x, modulus, *mp);
wolfSSL 0:d92f9d21154c 699
wolfSSL 0:d92f9d21154c 700 /* X = X - T2 */
wolfSSL 0:d92f9d21154c 701 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 702 err = mp_sub(&x, &t2, &x);
wolfSSL 0:d92f9d21154c 703 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 704 if (mp_cmp_d(&x, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 705 err = mp_add(&x, modulus, &x);
wolfSSL 0:d92f9d21154c 706 }
wolfSSL 0:d92f9d21154c 707 /* T2 = T2 - X */
wolfSSL 0:d92f9d21154c 708 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 709 err = mp_sub(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 710 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 711 if (mp_cmp_d(&t2, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 712 err = mp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 713 }
wolfSSL 0:d92f9d21154c 714 /* T2 = T2 - X */
wolfSSL 0:d92f9d21154c 715 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 716 err = mp_sub(&t2, &x, &t2);
wolfSSL 0:d92f9d21154c 717 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 718 if (mp_cmp_d(&t2, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 719 err = mp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 720 }
wolfSSL 0:d92f9d21154c 721 /* T2 = T2 * Y */
wolfSSL 0:d92f9d21154c 722 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 723 err = mp_mul(&t2, &y, &t2);
wolfSSL 0:d92f9d21154c 724 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 725 err = mp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 726
wolfSSL 0:d92f9d21154c 727 /* Y = T2 - T1 */
wolfSSL 0:d92f9d21154c 728 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 729 err = mp_sub(&t2, &t1, &y);
wolfSSL 0:d92f9d21154c 730 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 731 if (mp_cmp_d(&y, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 732 err = mp_add(&y, modulus, &y);
wolfSSL 0:d92f9d21154c 733 }
wolfSSL 0:d92f9d21154c 734 /* Y = Y/2 */
wolfSSL 0:d92f9d21154c 735 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 736 if (mp_isodd(&y))
wolfSSL 0:d92f9d21154c 737 err = mp_add(&y, modulus, &y);
wolfSSL 0:d92f9d21154c 738 }
wolfSSL 0:d92f9d21154c 739 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 740 err = mp_div_2(&y, &y);
wolfSSL 0:d92f9d21154c 741
wolfSSL 0:d92f9d21154c 742 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 743 err = mp_copy(&x, R->x);
wolfSSL 0:d92f9d21154c 744 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 745 err = mp_copy(&y, R->y);
wolfSSL 0:d92f9d21154c 746 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 747 err = mp_copy(&z, R->z);
wolfSSL 0:d92f9d21154c 748
wolfSSL 0:d92f9d21154c 749 /* clean up */
wolfSSL 0:d92f9d21154c 750 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 751 mp_clear(&t2);
wolfSSL 0:d92f9d21154c 752 mp_clear(&x);
wolfSSL 0:d92f9d21154c 753 mp_clear(&y);
wolfSSL 0:d92f9d21154c 754 mp_clear(&z);
wolfSSL 0:d92f9d21154c 755
wolfSSL 0:d92f9d21154c 756 return err;
wolfSSL 0:d92f9d21154c 757 }
wolfSSL 0:d92f9d21154c 758
wolfSSL 0:d92f9d21154c 759
wolfSSL 0:d92f9d21154c 760 /**
wolfSSL 0:d92f9d21154c 761 Double an ECC point
wolfSSL 0:d92f9d21154c 762 P The point to double
wolfSSL 0:d92f9d21154c 763 R [out] The destination of the double
wolfSSL 0:d92f9d21154c 764 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 765 mp The "b" value from montgomery_setup()
wolfSSL 0:d92f9d21154c 766 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 767 */
wolfSSL 0:d92f9d21154c 768 int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 769 mp_digit* mp)
wolfSSL 0:d92f9d21154c 770 {
wolfSSL 0:d92f9d21154c 771 mp_int t1;
wolfSSL 0:d92f9d21154c 772 mp_int t2;
wolfSSL 0:d92f9d21154c 773 int err;
wolfSSL 0:d92f9d21154c 774
wolfSSL 0:d92f9d21154c 775 if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
wolfSSL 0:d92f9d21154c 776 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 777
wolfSSL 0:d92f9d21154c 778 if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 779 return err;
wolfSSL 0:d92f9d21154c 780 }
wolfSSL 0:d92f9d21154c 781
wolfSSL 0:d92f9d21154c 782 if (P != R) {
wolfSSL 0:d92f9d21154c 783 err = mp_copy(P->x, R->x);
wolfSSL 0:d92f9d21154c 784 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 785 err = mp_copy(P->y, R->y);
wolfSSL 0:d92f9d21154c 786 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 787 err = mp_copy(P->z, R->z);
wolfSSL 0:d92f9d21154c 788 }
wolfSSL 0:d92f9d21154c 789
wolfSSL 0:d92f9d21154c 790 /* t1 = Z * Z */
wolfSSL 0:d92f9d21154c 791 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 792 err = mp_sqr(R->z, &t1);
wolfSSL 0:d92f9d21154c 793 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 794 err = mp_montgomery_reduce(&t1, modulus, *mp);
wolfSSL 0:d92f9d21154c 795
wolfSSL 0:d92f9d21154c 796 /* Z = Y * Z */
wolfSSL 0:d92f9d21154c 797 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 798 err = mp_mul(R->z, R->y, R->z);
wolfSSL 0:d92f9d21154c 799 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 800 err = mp_montgomery_reduce(R->z, modulus, *mp);
wolfSSL 0:d92f9d21154c 801
wolfSSL 0:d92f9d21154c 802 /* Z = 2Z */
wolfSSL 0:d92f9d21154c 803 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 804 err = mp_add(R->z, R->z, R->z);
wolfSSL 0:d92f9d21154c 805 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 806 if (mp_cmp(R->z, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 807 err = mp_sub(R->z, modulus, R->z);
wolfSSL 0:d92f9d21154c 808 }
wolfSSL 0:d92f9d21154c 809
wolfSSL 0:d92f9d21154c 810 /* T2 = X - T1 */
wolfSSL 0:d92f9d21154c 811 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 812 err = mp_sub(R->x, &t1, &t2);
wolfSSL 0:d92f9d21154c 813 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 814 if (mp_cmp_d(&t2, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 815 err = mp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 816 }
wolfSSL 0:d92f9d21154c 817 /* T1 = X + T1 */
wolfSSL 0:d92f9d21154c 818 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 819 err = mp_add(&t1, R->x, &t1);
wolfSSL 0:d92f9d21154c 820 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 821 if (mp_cmp(&t1, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 822 err = mp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 823 }
wolfSSL 0:d92f9d21154c 824 /* T2 = T1 * T2 */
wolfSSL 0:d92f9d21154c 825 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 826 err = mp_mul(&t1, &t2, &t2);
wolfSSL 0:d92f9d21154c 827 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 828 err = mp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 829
wolfSSL 0:d92f9d21154c 830 /* T1 = 2T2 */
wolfSSL 0:d92f9d21154c 831 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 832 err = mp_add(&t2, &t2, &t1);
wolfSSL 0:d92f9d21154c 833 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 834 if (mp_cmp(&t1, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 835 err = mp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 836 }
wolfSSL 0:d92f9d21154c 837 /* T1 = T1 + T2 */
wolfSSL 0:d92f9d21154c 838 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 839 err = mp_add(&t1, &t2, &t1);
wolfSSL 0:d92f9d21154c 840 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 841 if (mp_cmp(&t1, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 842 err = mp_sub(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 843 }
wolfSSL 0:d92f9d21154c 844 /* Y = 2Y */
wolfSSL 0:d92f9d21154c 845 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 846 err = mp_add(R->y, R->y, R->y);
wolfSSL 0:d92f9d21154c 847 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 848 if (mp_cmp(R->y, modulus) != MP_LT)
wolfSSL 0:d92f9d21154c 849 err = mp_sub(R->y, modulus, R->y);
wolfSSL 0:d92f9d21154c 850 }
wolfSSL 0:d92f9d21154c 851 /* Y = Y * Y */
wolfSSL 0:d92f9d21154c 852 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 853 err = mp_sqr(R->y, R->y);
wolfSSL 0:d92f9d21154c 854 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 855 err = mp_montgomery_reduce(R->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 856
wolfSSL 0:d92f9d21154c 857 /* T2 = Y * Y */
wolfSSL 0:d92f9d21154c 858 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 859 err = mp_sqr(R->y, &t2);
wolfSSL 0:d92f9d21154c 860 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 861 err = mp_montgomery_reduce(&t2, modulus, *mp);
wolfSSL 0:d92f9d21154c 862
wolfSSL 0:d92f9d21154c 863 /* T2 = T2/2 */
wolfSSL 0:d92f9d21154c 864 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 865 if (mp_isodd(&t2))
wolfSSL 0:d92f9d21154c 866 err = mp_add(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 867 }
wolfSSL 0:d92f9d21154c 868 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 869 err = mp_div_2(&t2, &t2);
wolfSSL 0:d92f9d21154c 870
wolfSSL 0:d92f9d21154c 871 /* Y = Y * X */
wolfSSL 0:d92f9d21154c 872 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 873 err = mp_mul(R->y, R->x, R->y);
wolfSSL 0:d92f9d21154c 874 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 875 err = mp_montgomery_reduce(R->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 876
wolfSSL 0:d92f9d21154c 877 /* X = T1 * T1 */
wolfSSL 0:d92f9d21154c 878 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 879 err = mp_sqr(&t1, R->x);
wolfSSL 0:d92f9d21154c 880 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 881 err = mp_montgomery_reduce(R->x, modulus, *mp);
wolfSSL 0:d92f9d21154c 882
wolfSSL 0:d92f9d21154c 883 /* X = X - Y */
wolfSSL 0:d92f9d21154c 884 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 885 err = mp_sub(R->x, R->y, R->x);
wolfSSL 0:d92f9d21154c 886 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 887 if (mp_cmp_d(R->x, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 888 err = mp_add(R->x, modulus, R->x);
wolfSSL 0:d92f9d21154c 889 }
wolfSSL 0:d92f9d21154c 890 /* X = X - Y */
wolfSSL 0:d92f9d21154c 891 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 892 err = mp_sub(R->x, R->y, R->x);
wolfSSL 0:d92f9d21154c 893 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 894 if (mp_cmp_d(R->x, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 895 err = mp_add(R->x, modulus, R->x);
wolfSSL 0:d92f9d21154c 896 }
wolfSSL 0:d92f9d21154c 897 /* Y = Y - X */
wolfSSL 0:d92f9d21154c 898 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 899 err = mp_sub(R->y, R->x, R->y);
wolfSSL 0:d92f9d21154c 900 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 901 if (mp_cmp_d(R->y, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 902 err = mp_add(R->y, modulus, R->y);
wolfSSL 0:d92f9d21154c 903 }
wolfSSL 0:d92f9d21154c 904 /* Y = Y * T1 */
wolfSSL 0:d92f9d21154c 905 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 906 err = mp_mul(R->y, &t1, R->y);
wolfSSL 0:d92f9d21154c 907 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 908 err = mp_montgomery_reduce(R->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 909
wolfSSL 0:d92f9d21154c 910 /* Y = Y - T2 */
wolfSSL 0:d92f9d21154c 911 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 912 err = mp_sub(R->y, &t2, R->y);
wolfSSL 0:d92f9d21154c 913 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 914 if (mp_cmp_d(R->y, 0) == MP_LT)
wolfSSL 0:d92f9d21154c 915 err = mp_add(R->y, modulus, R->y);
wolfSSL 0:d92f9d21154c 916 }
wolfSSL 0:d92f9d21154c 917
wolfSSL 0:d92f9d21154c 918 /* clean up */
wolfSSL 0:d92f9d21154c 919 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 920 mp_clear(&t2);
wolfSSL 0:d92f9d21154c 921
wolfSSL 0:d92f9d21154c 922 return err;
wolfSSL 0:d92f9d21154c 923 }
wolfSSL 0:d92f9d21154c 924
wolfSSL 0:d92f9d21154c 925 #endif /* USE_FAST_MATH */
wolfSSL 0:d92f9d21154c 926
wolfSSL 0:d92f9d21154c 927 /**
wolfSSL 0:d92f9d21154c 928 Map a projective jacbobian point back to affine space
wolfSSL 0:d92f9d21154c 929 P [in/out] The point to map
wolfSSL 0:d92f9d21154c 930 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 931 mp The "b" value from montgomery_setup()
wolfSSL 0:d92f9d21154c 932 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 933 */
wolfSSL 0:d92f9d21154c 934 int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp)
wolfSSL 0:d92f9d21154c 935 {
wolfSSL 0:d92f9d21154c 936 mp_int t1;
wolfSSL 0:d92f9d21154c 937 mp_int t2;
wolfSSL 0:d92f9d21154c 938 int err;
wolfSSL 0:d92f9d21154c 939
wolfSSL 0:d92f9d21154c 940 if (P == NULL || mp == NULL || modulus == NULL)
wolfSSL 0:d92f9d21154c 941 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 942
wolfSSL 0:d92f9d21154c 943 /* special case for point at infinity */
wolfSSL 0:d92f9d21154c 944 if (mp_cmp_d(P->z, 0) == MP_EQ) {
wolfSSL 0:d92f9d21154c 945 mp_set(P->x, 0);
wolfSSL 0:d92f9d21154c 946 mp_set(P->y, 0);
wolfSSL 0:d92f9d21154c 947 mp_set(P->z, 1);
wolfSSL 0:d92f9d21154c 948 return MP_OKAY;
wolfSSL 0:d92f9d21154c 949 }
wolfSSL 0:d92f9d21154c 950
wolfSSL 0:d92f9d21154c 951 if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 952 return MEMORY_E;
wolfSSL 0:d92f9d21154c 953 }
wolfSSL 0:d92f9d21154c 954
wolfSSL 0:d92f9d21154c 955 /* first map z back to normal */
wolfSSL 0:d92f9d21154c 956 err = mp_montgomery_reduce(P->z, modulus, *mp);
wolfSSL 0:d92f9d21154c 957
wolfSSL 0:d92f9d21154c 958 /* get 1/z */
wolfSSL 0:d92f9d21154c 959 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 960 err = mp_invmod(P->z, modulus, &t1);
wolfSSL 0:d92f9d21154c 961
wolfSSL 0:d92f9d21154c 962 /* get 1/z^2 and 1/z^3 */
wolfSSL 0:d92f9d21154c 963 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 964 err = mp_sqr(&t1, &t2);
wolfSSL 0:d92f9d21154c 965 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 966 err = mp_mod(&t2, modulus, &t2);
wolfSSL 0:d92f9d21154c 967 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 968 err = mp_mul(&t1, &t2, &t1);
wolfSSL 0:d92f9d21154c 969 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 970 err = mp_mod(&t1, modulus, &t1);
wolfSSL 0:d92f9d21154c 971
wolfSSL 0:d92f9d21154c 972 /* multiply against x/y */
wolfSSL 0:d92f9d21154c 973 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 974 err = mp_mul(P->x, &t2, P->x);
wolfSSL 0:d92f9d21154c 975 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 976 err = mp_montgomery_reduce(P->x, modulus, *mp);
wolfSSL 0:d92f9d21154c 977 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 978 err = mp_mul(P->y, &t1, P->y);
wolfSSL 0:d92f9d21154c 979 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 980 err = mp_montgomery_reduce(P->y, modulus, *mp);
wolfSSL 0:d92f9d21154c 981
wolfSSL 0:d92f9d21154c 982 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 983 mp_set(P->z, 1);
wolfSSL 0:d92f9d21154c 984
wolfSSL 0:d92f9d21154c 985 /* clean up */
wolfSSL 0:d92f9d21154c 986 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 987 mp_clear(&t2);
wolfSSL 0:d92f9d21154c 988
wolfSSL 0:d92f9d21154c 989 return err;
wolfSSL 0:d92f9d21154c 990 }
wolfSSL 0:d92f9d21154c 991
wolfSSL 0:d92f9d21154c 992
wolfSSL 0:d92f9d21154c 993 #ifndef ECC_TIMING_RESISTANT
wolfSSL 0:d92f9d21154c 994
wolfSSL 0:d92f9d21154c 995 /* size of sliding window, don't change this! */
wolfSSL 0:d92f9d21154c 996 #define WINSIZE 4
wolfSSL 0:d92f9d21154c 997
wolfSSL 0:d92f9d21154c 998 /**
wolfSSL 0:d92f9d21154c 999 Perform a point multiplication
wolfSSL 0:d92f9d21154c 1000 k The scalar to multiply by
wolfSSL 0:d92f9d21154c 1001 G The base point
wolfSSL 0:d92f9d21154c 1002 R [out] Destination for kG
wolfSSL 0:d92f9d21154c 1003 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 1004 map Boolean whether to map back to affine or not
wolfSSL 0:d92f9d21154c 1005 (1==map, 0 == leave in projective)
wolfSSL 0:d92f9d21154c 1006 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 1007 */
wolfSSL 0:d92f9d21154c 1008 #ifdef FP_ECC
wolfSSL 0:d92f9d21154c 1009 static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
wolfSSL 0:d92f9d21154c 1010 mp_int* modulus, int map)
wolfSSL 0:d92f9d21154c 1011 #else
wolfSSL 0:d92f9d21154c 1012 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 1013 int map)
wolfSSL 0:d92f9d21154c 1014 #endif
wolfSSL 0:d92f9d21154c 1015 {
wolfSSL 0:d92f9d21154c 1016 ecc_point *tG, *M[8];
wolfSSL 0:d92f9d21154c 1017 int i, j, err;
wolfSSL 0:d92f9d21154c 1018 mp_int mu;
wolfSSL 0:d92f9d21154c 1019 mp_digit mp;
wolfSSL 0:d92f9d21154c 1020 mp_digit buf;
wolfSSL 0:d92f9d21154c 1021 int first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0,
wolfSSL 0:d92f9d21154c 1022 digidx = 0;
wolfSSL 0:d92f9d21154c 1023
wolfSSL 0:d92f9d21154c 1024 if (k == NULL || G == NULL || R == NULL || modulus == NULL)
wolfSSL 0:d92f9d21154c 1025 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1026
wolfSSL 0:d92f9d21154c 1027 /* init montgomery reduction */
wolfSSL 0:d92f9d21154c 1028 if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1029 return err;
wolfSSL 0:d92f9d21154c 1030 }
wolfSSL 0:d92f9d21154c 1031 if ((err = mp_init(&mu)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1032 return err;
wolfSSL 0:d92f9d21154c 1033 }
wolfSSL 0:d92f9d21154c 1034 if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1035 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1036 return err;
wolfSSL 0:d92f9d21154c 1037 }
wolfSSL 0:d92f9d21154c 1038
wolfSSL 0:d92f9d21154c 1039 /* alloc ram for window temps */
wolfSSL 0:d92f9d21154c 1040 for (i = 0; i < 8; i++) {
wolfSSL 0:d92f9d21154c 1041 M[i] = ecc_new_point();
wolfSSL 0:d92f9d21154c 1042 if (M[i] == NULL) {
wolfSSL 0:d92f9d21154c 1043 for (j = 0; j < i; j++) {
wolfSSL 0:d92f9d21154c 1044 ecc_del_point(M[j]);
wolfSSL 0:d92f9d21154c 1045 }
wolfSSL 0:d92f9d21154c 1046 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1047 return MEMORY_E;
wolfSSL 0:d92f9d21154c 1048 }
wolfSSL 0:d92f9d21154c 1049 }
wolfSSL 0:d92f9d21154c 1050
wolfSSL 0:d92f9d21154c 1051 /* make a copy of G incase R==G */
wolfSSL 0:d92f9d21154c 1052 tG = ecc_new_point();
wolfSSL 0:d92f9d21154c 1053 if (tG == NULL)
wolfSSL 0:d92f9d21154c 1054 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 1055
wolfSSL 0:d92f9d21154c 1056 /* tG = G and convert to montgomery */
wolfSSL 0:d92f9d21154c 1057 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1058 if (mp_cmp_d(&mu, 1) == MP_EQ) {
wolfSSL 0:d92f9d21154c 1059 err = mp_copy(G->x, tG->x);
wolfSSL 0:d92f9d21154c 1060 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1061 err = mp_copy(G->y, tG->y);
wolfSSL 0:d92f9d21154c 1062 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1063 err = mp_copy(G->z, tG->z);
wolfSSL 0:d92f9d21154c 1064 } else {
wolfSSL 0:d92f9d21154c 1065 err = mp_mulmod(G->x, &mu, modulus, tG->x);
wolfSSL 0:d92f9d21154c 1066 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1067 err = mp_mulmod(G->y, &mu, modulus, tG->y);
wolfSSL 0:d92f9d21154c 1068 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1069 err = mp_mulmod(G->z, &mu, modulus, tG->z);
wolfSSL 0:d92f9d21154c 1070 }
wolfSSL 0:d92f9d21154c 1071 }
wolfSSL 0:d92f9d21154c 1072 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1073
wolfSSL 0:d92f9d21154c 1074 /* calc the M tab, which holds kG for k==8..15 */
wolfSSL 0:d92f9d21154c 1075 /* M[0] == 8G */
wolfSSL 0:d92f9d21154c 1076 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1077 err = ecc_projective_dbl_point(tG, M[0], modulus, &mp);
wolfSSL 0:d92f9d21154c 1078 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1079 err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
wolfSSL 0:d92f9d21154c 1080 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1081 err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
wolfSSL 0:d92f9d21154c 1082
wolfSSL 0:d92f9d21154c 1083 /* now find (8+k)G for k=1..7 */
wolfSSL 0:d92f9d21154c 1084 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1085 for (j = 9; j < 16; j++) {
wolfSSL 0:d92f9d21154c 1086 err = ecc_projective_add_point(M[j-9], tG, M[j-8], modulus, &mp);
wolfSSL 0:d92f9d21154c 1087 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1088 }
wolfSSL 0:d92f9d21154c 1089
wolfSSL 0:d92f9d21154c 1090 /* setup sliding window */
wolfSSL 0:d92f9d21154c 1091 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1092 mode = 0;
wolfSSL 0:d92f9d21154c 1093 bitcnt = 1;
wolfSSL 0:d92f9d21154c 1094 buf = 0;
wolfSSL 0:d92f9d21154c 1095 digidx = get_digit_count(k) - 1;
wolfSSL 0:d92f9d21154c 1096 bitcpy = bitbuf = 0;
wolfSSL 0:d92f9d21154c 1097 first = 1;
wolfSSL 0:d92f9d21154c 1098
wolfSSL 0:d92f9d21154c 1099 /* perform ops */
wolfSSL 0:d92f9d21154c 1100 for (;;) {
wolfSSL 0:d92f9d21154c 1101 /* grab next digit as required */
wolfSSL 0:d92f9d21154c 1102 if (--bitcnt == 0) {
wolfSSL 0:d92f9d21154c 1103 if (digidx == -1) {
wolfSSL 0:d92f9d21154c 1104 break;
wolfSSL 0:d92f9d21154c 1105 }
wolfSSL 0:d92f9d21154c 1106 buf = get_digit(k, digidx);
wolfSSL 0:d92f9d21154c 1107 bitcnt = (int) DIGIT_BIT;
wolfSSL 0:d92f9d21154c 1108 --digidx;
wolfSSL 0:d92f9d21154c 1109 }
wolfSSL 0:d92f9d21154c 1110
wolfSSL 0:d92f9d21154c 1111 /* grab the next msb from the ltiplicand */
wolfSSL 0:d92f9d21154c 1112 i = (int)(buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 0:d92f9d21154c 1113 buf <<= 1;
wolfSSL 0:d92f9d21154c 1114
wolfSSL 0:d92f9d21154c 1115 /* skip leading zero bits */
wolfSSL 0:d92f9d21154c 1116 if (mode == 0 && i == 0)
wolfSSL 0:d92f9d21154c 1117 continue;
wolfSSL 0:d92f9d21154c 1118
wolfSSL 0:d92f9d21154c 1119 /* if the bit is zero and mode == 1 then we double */
wolfSSL 0:d92f9d21154c 1120 if (mode == 1 && i == 0) {
wolfSSL 0:d92f9d21154c 1121 err = ecc_projective_dbl_point(R, R, modulus, &mp);
wolfSSL 0:d92f9d21154c 1122 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1123 continue;
wolfSSL 0:d92f9d21154c 1124 }
wolfSSL 0:d92f9d21154c 1125
wolfSSL 0:d92f9d21154c 1126 /* else we add it to the window */
wolfSSL 0:d92f9d21154c 1127 bitbuf |= (i << (WINSIZE - ++bitcpy));
wolfSSL 0:d92f9d21154c 1128 mode = 2;
wolfSSL 0:d92f9d21154c 1129
wolfSSL 0:d92f9d21154c 1130 if (bitcpy == WINSIZE) {
wolfSSL 0:d92f9d21154c 1131 /* if this is the first window we do a simple copy */
wolfSSL 0:d92f9d21154c 1132 if (first == 1) {
wolfSSL 0:d92f9d21154c 1133 /* R = kG [k = first window] */
wolfSSL 0:d92f9d21154c 1134 err = mp_copy(M[bitbuf-8]->x, R->x);
wolfSSL 0:d92f9d21154c 1135 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1136
wolfSSL 0:d92f9d21154c 1137 err = mp_copy(M[bitbuf-8]->y, R->y);
wolfSSL 0:d92f9d21154c 1138 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1139
wolfSSL 0:d92f9d21154c 1140 err = mp_copy(M[bitbuf-8]->z, R->z);
wolfSSL 0:d92f9d21154c 1141 first = 0;
wolfSSL 0:d92f9d21154c 1142 } else {
wolfSSL 0:d92f9d21154c 1143 /* normal window */
wolfSSL 0:d92f9d21154c 1144 /* ok window is filled so double as required and add */
wolfSSL 0:d92f9d21154c 1145 /* double first */
wolfSSL 0:d92f9d21154c 1146 for (j = 0; j < WINSIZE; j++) {
wolfSSL 0:d92f9d21154c 1147 err = ecc_projective_dbl_point(R, R, modulus, &mp);
wolfSSL 0:d92f9d21154c 1148 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1149 }
wolfSSL 0:d92f9d21154c 1150 if (err != MP_OKAY) break; /* out of first for(;;) */
wolfSSL 0:d92f9d21154c 1151
wolfSSL 0:d92f9d21154c 1152 /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranted */
wolfSSL 0:d92f9d21154c 1153 err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp);
wolfSSL 0:d92f9d21154c 1154 }
wolfSSL 0:d92f9d21154c 1155 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1156 /* empty window and reset */
wolfSSL 0:d92f9d21154c 1157 bitcpy = bitbuf = 0;
wolfSSL 0:d92f9d21154c 1158 mode = 1;
wolfSSL 0:d92f9d21154c 1159 }
wolfSSL 0:d92f9d21154c 1160 }
wolfSSL 0:d92f9d21154c 1161 }
wolfSSL 0:d92f9d21154c 1162
wolfSSL 0:d92f9d21154c 1163 /* if bits remain then double/add */
wolfSSL 0:d92f9d21154c 1164 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1165 if (mode == 2 && bitcpy > 0) {
wolfSSL 0:d92f9d21154c 1166 /* double then add */
wolfSSL 0:d92f9d21154c 1167 for (j = 0; j < bitcpy; j++) {
wolfSSL 0:d92f9d21154c 1168 /* only double if we have had at least one add first */
wolfSSL 0:d92f9d21154c 1169 if (first == 0) {
wolfSSL 0:d92f9d21154c 1170 err = ecc_projective_dbl_point(R, R, modulus, &mp);
wolfSSL 0:d92f9d21154c 1171 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1172 }
wolfSSL 0:d92f9d21154c 1173
wolfSSL 0:d92f9d21154c 1174 bitbuf <<= 1;
wolfSSL 0:d92f9d21154c 1175 if ((bitbuf & (1 << WINSIZE)) != 0) {
wolfSSL 0:d92f9d21154c 1176 if (first == 1) {
wolfSSL 0:d92f9d21154c 1177 /* first add, so copy */
wolfSSL 0:d92f9d21154c 1178 err = mp_copy(tG->x, R->x);
wolfSSL 0:d92f9d21154c 1179 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1180
wolfSSL 0:d92f9d21154c 1181 err = mp_copy(tG->y, R->y);
wolfSSL 0:d92f9d21154c 1182 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1183
wolfSSL 0:d92f9d21154c 1184 err = mp_copy(tG->z, R->z);
wolfSSL 0:d92f9d21154c 1185 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1186 first = 0;
wolfSSL 0:d92f9d21154c 1187 } else {
wolfSSL 0:d92f9d21154c 1188 /* then add */
wolfSSL 0:d92f9d21154c 1189 err = ecc_projective_add_point(R, tG, R, modulus, &mp);
wolfSSL 0:d92f9d21154c 1190 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1191 }
wolfSSL 0:d92f9d21154c 1192 }
wolfSSL 0:d92f9d21154c 1193 }
wolfSSL 0:d92f9d21154c 1194 }
wolfSSL 0:d92f9d21154c 1195 }
wolfSSL 0:d92f9d21154c 1196
wolfSSL 0:d92f9d21154c 1197 /* map R back from projective space */
wolfSSL 0:d92f9d21154c 1198 if (err == MP_OKAY && map)
wolfSSL 0:d92f9d21154c 1199 err = ecc_map(R, modulus, &mp);
wolfSSL 0:d92f9d21154c 1200
wolfSSL 0:d92f9d21154c 1201 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1202 ecc_del_point(tG);
wolfSSL 0:d92f9d21154c 1203 for (i = 0; i < 8; i++) {
wolfSSL 0:d92f9d21154c 1204 ecc_del_point(M[i]);
wolfSSL 0:d92f9d21154c 1205 }
wolfSSL 0:d92f9d21154c 1206 return err;
wolfSSL 0:d92f9d21154c 1207 }
wolfSSL 0:d92f9d21154c 1208
wolfSSL 0:d92f9d21154c 1209 #undef WINSIZE
wolfSSL 0:d92f9d21154c 1210
wolfSSL 0:d92f9d21154c 1211 #else /* ECC_TIMING_RESISTANT */
wolfSSL 0:d92f9d21154c 1212
wolfSSL 0:d92f9d21154c 1213 /**
wolfSSL 0:d92f9d21154c 1214 Perform a point multiplication (timing resistant)
wolfSSL 0:d92f9d21154c 1215 k The scalar to multiply by
wolfSSL 0:d92f9d21154c 1216 G The base point
wolfSSL 0:d92f9d21154c 1217 R [out] Destination for kG
wolfSSL 0:d92f9d21154c 1218 modulus The modulus of the field the ECC curve is in
wolfSSL 0:d92f9d21154c 1219 map Boolean whether to map back to affine or not
wolfSSL 0:d92f9d21154c 1220 (1==map, 0 == leave in projective)
wolfSSL 0:d92f9d21154c 1221 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 1222 */
wolfSSL 0:d92f9d21154c 1223 #ifdef FP_ECC
wolfSSL 0:d92f9d21154c 1224 static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
wolfSSL 0:d92f9d21154c 1225 mp_int* modulus, int map)
wolfSSL 0:d92f9d21154c 1226 #else
wolfSSL 0:d92f9d21154c 1227 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 1228 int map)
wolfSSL 0:d92f9d21154c 1229 #endif
wolfSSL 0:d92f9d21154c 1230 {
wolfSSL 0:d92f9d21154c 1231 ecc_point *tG, *M[3];
wolfSSL 0:d92f9d21154c 1232 int i, j, err;
wolfSSL 0:d92f9d21154c 1233 mp_int mu;
wolfSSL 0:d92f9d21154c 1234 mp_digit mp;
wolfSSL 0:d92f9d21154c 1235 mp_digit buf;
wolfSSL 0:d92f9d21154c 1236 int bitcnt = 0, mode = 0, digidx = 0;
wolfSSL 0:d92f9d21154c 1237
wolfSSL 0:d92f9d21154c 1238 if (k == NULL || G == NULL || R == NULL || modulus == NULL)
wolfSSL 0:d92f9d21154c 1239 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1240
wolfSSL 0:d92f9d21154c 1241 /* init montgomery reduction */
wolfSSL 0:d92f9d21154c 1242 if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1243 return err;
wolfSSL 0:d92f9d21154c 1244 }
wolfSSL 0:d92f9d21154c 1245 if ((err = mp_init(&mu)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1246 return err;
wolfSSL 0:d92f9d21154c 1247 }
wolfSSL 0:d92f9d21154c 1248 if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1249 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1250 return err;
wolfSSL 0:d92f9d21154c 1251 }
wolfSSL 0:d92f9d21154c 1252
wolfSSL 0:d92f9d21154c 1253 /* alloc ram for window temps */
wolfSSL 0:d92f9d21154c 1254 for (i = 0; i < 3; i++) {
wolfSSL 0:d92f9d21154c 1255 M[i] = ecc_new_point();
wolfSSL 0:d92f9d21154c 1256 if (M[i] == NULL) {
wolfSSL 0:d92f9d21154c 1257 for (j = 0; j < i; j++) {
wolfSSL 0:d92f9d21154c 1258 ecc_del_point(M[j]);
wolfSSL 0:d92f9d21154c 1259 }
wolfSSL 0:d92f9d21154c 1260 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1261 return MEMORY_E;
wolfSSL 0:d92f9d21154c 1262 }
wolfSSL 0:d92f9d21154c 1263 }
wolfSSL 0:d92f9d21154c 1264
wolfSSL 0:d92f9d21154c 1265 /* make a copy of G incase R==G */
wolfSSL 0:d92f9d21154c 1266 tG = ecc_new_point();
wolfSSL 0:d92f9d21154c 1267 if (tG == NULL)
wolfSSL 0:d92f9d21154c 1268 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 1269
wolfSSL 0:d92f9d21154c 1270 /* tG = G and convert to montgomery */
wolfSSL 0:d92f9d21154c 1271 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1272 err = mp_mulmod(G->x, &mu, modulus, tG->x);
wolfSSL 0:d92f9d21154c 1273 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1274 err = mp_mulmod(G->y, &mu, modulus, tG->y);
wolfSSL 0:d92f9d21154c 1275 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1276 err = mp_mulmod(G->z, &mu, modulus, tG->z);
wolfSSL 0:d92f9d21154c 1277 }
wolfSSL 0:d92f9d21154c 1278 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1279
wolfSSL 0:d92f9d21154c 1280 /* calc the M tab */
wolfSSL 0:d92f9d21154c 1281 /* M[0] == G */
wolfSSL 0:d92f9d21154c 1282 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1283 err = mp_copy(tG->x, M[0]->x);
wolfSSL 0:d92f9d21154c 1284 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1285 err = mp_copy(tG->y, M[0]->y);
wolfSSL 0:d92f9d21154c 1286 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1287 err = mp_copy(tG->z, M[0]->z);
wolfSSL 0:d92f9d21154c 1288
wolfSSL 0:d92f9d21154c 1289 /* M[1] == 2G */
wolfSSL 0:d92f9d21154c 1290 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1291 err = ecc_projective_dbl_point(tG, M[1], modulus, &mp);
wolfSSL 0:d92f9d21154c 1292
wolfSSL 0:d92f9d21154c 1293 /* setup sliding window */
wolfSSL 0:d92f9d21154c 1294 mode = 0;
wolfSSL 0:d92f9d21154c 1295 bitcnt = 1;
wolfSSL 0:d92f9d21154c 1296 buf = 0;
wolfSSL 0:d92f9d21154c 1297 digidx = get_digit_count(k) - 1;
wolfSSL 0:d92f9d21154c 1298
wolfSSL 0:d92f9d21154c 1299 /* perform ops */
wolfSSL 0:d92f9d21154c 1300 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1301 for (;;) {
wolfSSL 0:d92f9d21154c 1302 /* grab next digit as required */
wolfSSL 0:d92f9d21154c 1303 if (--bitcnt == 0) {
wolfSSL 0:d92f9d21154c 1304 if (digidx == -1) {
wolfSSL 0:d92f9d21154c 1305 break;
wolfSSL 0:d92f9d21154c 1306 }
wolfSSL 0:d92f9d21154c 1307 buf = get_digit(k, digidx);
wolfSSL 0:d92f9d21154c 1308 bitcnt = (int) DIGIT_BIT;
wolfSSL 0:d92f9d21154c 1309 --digidx;
wolfSSL 0:d92f9d21154c 1310 }
wolfSSL 0:d92f9d21154c 1311
wolfSSL 0:d92f9d21154c 1312 /* grab the next msb from the ltiplicand */
wolfSSL 0:d92f9d21154c 1313 i = (buf >> (DIGIT_BIT - 1)) & 1;
wolfSSL 0:d92f9d21154c 1314 buf <<= 1;
wolfSSL 0:d92f9d21154c 1315
wolfSSL 0:d92f9d21154c 1316 if (mode == 0 && i == 0) {
wolfSSL 0:d92f9d21154c 1317 /* dummy operations */
wolfSSL 0:d92f9d21154c 1318 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1319 err = ecc_projective_add_point(M[0], M[1], M[2], modulus,
wolfSSL 0:d92f9d21154c 1320 &mp);
wolfSSL 0:d92f9d21154c 1321 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1322 err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp);
wolfSSL 0:d92f9d21154c 1323 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1324 continue;
wolfSSL 0:d92f9d21154c 1325 }
wolfSSL 0:d92f9d21154c 1326
wolfSSL 0:d92f9d21154c 1327 if (mode == 0 && i == 1) {
wolfSSL 0:d92f9d21154c 1328 mode = 1;
wolfSSL 0:d92f9d21154c 1329 /* dummy operations */
wolfSSL 0:d92f9d21154c 1330 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1331 err = ecc_projective_add_point(M[0], M[1], M[2], modulus,
wolfSSL 0:d92f9d21154c 1332 &mp);
wolfSSL 0:d92f9d21154c 1333 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1334 err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp);
wolfSSL 0:d92f9d21154c 1335 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1336 continue;
wolfSSL 0:d92f9d21154c 1337 }
wolfSSL 0:d92f9d21154c 1338
wolfSSL 0:d92f9d21154c 1339 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1340 err = ecc_projective_add_point(M[0], M[1], M[i^1], modulus, &mp);
wolfSSL 0:d92f9d21154c 1341 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1342 err = ecc_projective_dbl_point(M[i], M[i], modulus, &mp);
wolfSSL 0:d92f9d21154c 1343 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 1344 break;
wolfSSL 0:d92f9d21154c 1345 } /* end for */
wolfSSL 0:d92f9d21154c 1346 }
wolfSSL 0:d92f9d21154c 1347
wolfSSL 0:d92f9d21154c 1348 /* copy result out */
wolfSSL 0:d92f9d21154c 1349 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1350 err = mp_copy(M[0]->x, R->x);
wolfSSL 0:d92f9d21154c 1351 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1352 err = mp_copy(M[0]->y, R->y);
wolfSSL 0:d92f9d21154c 1353 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1354 err = mp_copy(M[0]->z, R->z);
wolfSSL 0:d92f9d21154c 1355
wolfSSL 0:d92f9d21154c 1356 /* map R back from projective space */
wolfSSL 0:d92f9d21154c 1357 if (err == MP_OKAY && map)
wolfSSL 0:d92f9d21154c 1358 err = ecc_map(R, modulus, &mp);
wolfSSL 0:d92f9d21154c 1359
wolfSSL 0:d92f9d21154c 1360 /* done */
wolfSSL 0:d92f9d21154c 1361 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 1362 ecc_del_point(tG);
wolfSSL 0:d92f9d21154c 1363 for (i = 0; i < 3; i++) {
wolfSSL 0:d92f9d21154c 1364 ecc_del_point(M[i]);
wolfSSL 0:d92f9d21154c 1365 }
wolfSSL 0:d92f9d21154c 1366 return err;
wolfSSL 0:d92f9d21154c 1367 }
wolfSSL 0:d92f9d21154c 1368
wolfSSL 0:d92f9d21154c 1369 #endif /* ECC_TIMING_RESISTANT */
wolfSSL 0:d92f9d21154c 1370
wolfSSL 0:d92f9d21154c 1371
wolfSSL 0:d92f9d21154c 1372 #ifdef ALT_ECC_SIZE
wolfSSL 0:d92f9d21154c 1373
wolfSSL 0:d92f9d21154c 1374 static void alt_fp_init(fp_int* a)
wolfSSL 0:d92f9d21154c 1375 {
wolfSSL 0:d92f9d21154c 1376 a->size = FP_SIZE_ECC;
wolfSSL 0:d92f9d21154c 1377 fp_zero(a);
wolfSSL 0:d92f9d21154c 1378 }
wolfSSL 0:d92f9d21154c 1379
wolfSSL 0:d92f9d21154c 1380 #endif /* ALT_ECC_SIZE */
wolfSSL 0:d92f9d21154c 1381
wolfSSL 0:d92f9d21154c 1382
wolfSSL 0:d92f9d21154c 1383 /**
wolfSSL 0:d92f9d21154c 1384 Allocate a new ECC point
wolfSSL 0:d92f9d21154c 1385 return A newly allocated point or NULL on error
wolfSSL 0:d92f9d21154c 1386 */
wolfSSL 0:d92f9d21154c 1387 ecc_point* ecc_new_point(void)
wolfSSL 0:d92f9d21154c 1388 {
wolfSSL 0:d92f9d21154c 1389 ecc_point* p;
wolfSSL 0:d92f9d21154c 1390
wolfSSL 0:d92f9d21154c 1391 p = (ecc_point*)XMALLOC(sizeof(ecc_point), 0, DYNAMIC_TYPE_ECC);
wolfSSL 0:d92f9d21154c 1392 if (p == NULL) {
wolfSSL 0:d92f9d21154c 1393 return NULL;
wolfSSL 0:d92f9d21154c 1394 }
wolfSSL 0:d92f9d21154c 1395 XMEMSET(p, 0, sizeof(ecc_point));
wolfSSL 0:d92f9d21154c 1396
wolfSSL 0:d92f9d21154c 1397 #ifndef USE_FAST_MATH
wolfSSL 0:d92f9d21154c 1398 p->x->dp = NULL;
wolfSSL 0:d92f9d21154c 1399 p->y->dp = NULL;
wolfSSL 0:d92f9d21154c 1400 p->z->dp = NULL;
wolfSSL 0:d92f9d21154c 1401 #endif
wolfSSL 0:d92f9d21154c 1402
wolfSSL 0:d92f9d21154c 1403 #ifndef ALT_ECC_SIZE
wolfSSL 0:d92f9d21154c 1404 if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1405 XFREE(p, 0, DYNAMIC_TYPE_ECC);
wolfSSL 0:d92f9d21154c 1406 return NULL;
wolfSSL 0:d92f9d21154c 1407 }
wolfSSL 0:d92f9d21154c 1408 #else
wolfSSL 0:d92f9d21154c 1409 p->x = (mp_int*)&p->xyz[0];
wolfSSL 0:d92f9d21154c 1410 p->y = (mp_int*)&p->xyz[1];
wolfSSL 0:d92f9d21154c 1411 p->z = (mp_int*)&p->xyz[2];
wolfSSL 0:d92f9d21154c 1412 alt_fp_init(p->x);
wolfSSL 0:d92f9d21154c 1413 alt_fp_init(p->y);
wolfSSL 0:d92f9d21154c 1414 alt_fp_init(p->z);
wolfSSL 0:d92f9d21154c 1415 #endif
wolfSSL 0:d92f9d21154c 1416
wolfSSL 0:d92f9d21154c 1417 return p;
wolfSSL 0:d92f9d21154c 1418 }
wolfSSL 0:d92f9d21154c 1419
wolfSSL 0:d92f9d21154c 1420 /** Free an ECC point from memory
wolfSSL 0:d92f9d21154c 1421 p The point to free
wolfSSL 0:d92f9d21154c 1422 */
wolfSSL 0:d92f9d21154c 1423 void ecc_del_point(ecc_point* p)
wolfSSL 0:d92f9d21154c 1424 {
wolfSSL 0:d92f9d21154c 1425 /* prevents free'ing null arguments */
wolfSSL 0:d92f9d21154c 1426 if (p != NULL) {
wolfSSL 0:d92f9d21154c 1427 mp_clear(p->x);
wolfSSL 0:d92f9d21154c 1428 mp_clear(p->y);
wolfSSL 0:d92f9d21154c 1429 mp_clear(p->z);
wolfSSL 0:d92f9d21154c 1430 XFREE(p, 0, DYNAMIC_TYPE_ECC);
wolfSSL 0:d92f9d21154c 1431 }
wolfSSL 0:d92f9d21154c 1432 }
wolfSSL 0:d92f9d21154c 1433
wolfSSL 0:d92f9d21154c 1434
wolfSSL 0:d92f9d21154c 1435 /** Returns whether an ECC idx is valid or not
wolfSSL 0:d92f9d21154c 1436 n The idx number to check
wolfSSL 0:d92f9d21154c 1437 return 1 if valid, 0 if not
wolfSSL 0:d92f9d21154c 1438 */
wolfSSL 0:d92f9d21154c 1439 static int ecc_is_valid_idx(int n)
wolfSSL 0:d92f9d21154c 1440 {
wolfSSL 0:d92f9d21154c 1441 int x;
wolfSSL 0:d92f9d21154c 1442
wolfSSL 0:d92f9d21154c 1443 for (x = 0; ecc_sets[x].size != 0; x++)
wolfSSL 0:d92f9d21154c 1444 ;
wolfSSL 0:d92f9d21154c 1445 /* -1 is a valid index --- indicating that the domain params
wolfSSL 0:d92f9d21154c 1446 were supplied by the user */
wolfSSL 0:d92f9d21154c 1447 if ((n >= -1) && (n < x)) {
wolfSSL 0:d92f9d21154c 1448 return 1;
wolfSSL 0:d92f9d21154c 1449 }
wolfSSL 0:d92f9d21154c 1450 return 0;
wolfSSL 0:d92f9d21154c 1451 }
wolfSSL 0:d92f9d21154c 1452
wolfSSL 0:d92f9d21154c 1453
wolfSSL 0:d92f9d21154c 1454 /**
wolfSSL 0:d92f9d21154c 1455 Create an ECC shared secret between two keys
wolfSSL 0:d92f9d21154c 1456 private_key The private ECC key
wolfSSL 0:d92f9d21154c 1457 public_key The public key
wolfSSL 0:d92f9d21154c 1458 out [out] Destination of the shared secret
wolfSSL 0:d92f9d21154c 1459 Conforms to EC-DH from ANSI X9.63
wolfSSL 0:d92f9d21154c 1460 outlen [in/out] The max size and resulting size of the shared secret
wolfSSL 0:d92f9d21154c 1461 return MP_OKAY if successful
wolfSSL 0:d92f9d21154c 1462 */
wolfSSL 0:d92f9d21154c 1463 int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
wolfSSL 0:d92f9d21154c 1464 word32* outlen)
wolfSSL 0:d92f9d21154c 1465 {
wolfSSL 0:d92f9d21154c 1466 word32 x = 0;
wolfSSL 0:d92f9d21154c 1467 ecc_point* result;
wolfSSL 0:d92f9d21154c 1468 mp_int prime;
wolfSSL 0:d92f9d21154c 1469 int err;
wolfSSL 0:d92f9d21154c 1470
wolfSSL 0:d92f9d21154c 1471 if (private_key == NULL || public_key == NULL || out == NULL ||
wolfSSL 0:d92f9d21154c 1472 outlen == NULL)
wolfSSL 0:d92f9d21154c 1473 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 1474
wolfSSL 0:d92f9d21154c 1475 /* type valid? */
wolfSSL 0:d92f9d21154c 1476 if (private_key->type != ECC_PRIVATEKEY) {
wolfSSL 0:d92f9d21154c 1477 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1478 }
wolfSSL 0:d92f9d21154c 1479
wolfSSL 0:d92f9d21154c 1480 if (ecc_is_valid_idx(private_key->idx) == 0 ||
wolfSSL 0:d92f9d21154c 1481 ecc_is_valid_idx(public_key->idx) == 0)
wolfSSL 0:d92f9d21154c 1482 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1483
wolfSSL 0:d92f9d21154c 1484 if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0)
wolfSSL 0:d92f9d21154c 1485 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1486
wolfSSL 0:d92f9d21154c 1487 /* make new point */
wolfSSL 0:d92f9d21154c 1488 result = ecc_new_point();
wolfSSL 0:d92f9d21154c 1489 if (result == NULL) {
wolfSSL 0:d92f9d21154c 1490 return MEMORY_E;
wolfSSL 0:d92f9d21154c 1491 }
wolfSSL 0:d92f9d21154c 1492
wolfSSL 0:d92f9d21154c 1493 if ((err = mp_init(&prime)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1494 ecc_del_point(result);
wolfSSL 0:d92f9d21154c 1495 return err;
wolfSSL 0:d92f9d21154c 1496 }
wolfSSL 0:d92f9d21154c 1497
wolfSSL 0:d92f9d21154c 1498 err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16);
wolfSSL 0:d92f9d21154c 1499
wolfSSL 0:d92f9d21154c 1500 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1501 err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime,1);
wolfSSL 0:d92f9d21154c 1502
wolfSSL 0:d92f9d21154c 1503 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1504 x = mp_unsigned_bin_size(&prime);
wolfSSL 0:d92f9d21154c 1505 if (*outlen < x)
wolfSSL 0:d92f9d21154c 1506 err = BUFFER_E;
wolfSSL 0:d92f9d21154c 1507 }
wolfSSL 0:d92f9d21154c 1508
wolfSSL 0:d92f9d21154c 1509 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1510 XMEMSET(out, 0, x);
wolfSSL 0:d92f9d21154c 1511 err = mp_to_unsigned_bin(result->x,out + (x -
wolfSSL 0:d92f9d21154c 1512 mp_unsigned_bin_size(result->x)));
wolfSSL 0:d92f9d21154c 1513 *outlen = x;
wolfSSL 0:d92f9d21154c 1514 }
wolfSSL 0:d92f9d21154c 1515
wolfSSL 0:d92f9d21154c 1516 mp_clear(&prime);
wolfSSL 0:d92f9d21154c 1517 ecc_del_point(result);
wolfSSL 0:d92f9d21154c 1518
wolfSSL 0:d92f9d21154c 1519 return err;
wolfSSL 0:d92f9d21154c 1520 }
wolfSSL 0:d92f9d21154c 1521
wolfSSL 0:d92f9d21154c 1522
wolfSSL 0:d92f9d21154c 1523 /* return 1 if point is at infinity, 0 if not, < 0 on error */
wolfSSL 0:d92f9d21154c 1524 static int ecc_point_is_at_infinity(ecc_point* p)
wolfSSL 0:d92f9d21154c 1525 {
wolfSSL 0:d92f9d21154c 1526 if (p == NULL)
wolfSSL 0:d92f9d21154c 1527 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 1528
wolfSSL 0:d92f9d21154c 1529 if (get_digit_count(p->x) == 0 && get_digit_count(p->y) == 0)
wolfSSL 0:d92f9d21154c 1530 return 1;
wolfSSL 0:d92f9d21154c 1531
wolfSSL 0:d92f9d21154c 1532 return 0;
wolfSSL 0:d92f9d21154c 1533 }
wolfSSL 0:d92f9d21154c 1534
wolfSSL 0:d92f9d21154c 1535
wolfSSL 0:d92f9d21154c 1536 int wc_ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp);
wolfSSL 0:d92f9d21154c 1537
wolfSSL 0:d92f9d21154c 1538 /**
wolfSSL 0:d92f9d21154c 1539 Make a new ECC key
wolfSSL 0:d92f9d21154c 1540 rng An active RNG state
wolfSSL 0:d92f9d21154c 1541 keysize The keysize for the new key (in octets from 20 to 65 bytes)
wolfSSL 0:d92f9d21154c 1542 key [out] Destination of the newly created key
wolfSSL 0:d92f9d21154c 1543 return MP_OKAY if successful,
wolfSSL 0:d92f9d21154c 1544 upon error all allocated memory will be freed
wolfSSL 0:d92f9d21154c 1545 */
wolfSSL 0:d92f9d21154c 1546 int wc_ecc_make_key(RNG* rng, int keysize, ecc_key* key)
wolfSSL 0:d92f9d21154c 1547 {
wolfSSL 0:d92f9d21154c 1548 int x, err;
wolfSSL 0:d92f9d21154c 1549
wolfSSL 0:d92f9d21154c 1550 if (key == NULL || rng == NULL)
wolfSSL 0:d92f9d21154c 1551 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1552
wolfSSL 0:d92f9d21154c 1553 /* find key size */
wolfSSL 0:d92f9d21154c 1554 for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++)
wolfSSL 0:d92f9d21154c 1555 ;
wolfSSL 0:d92f9d21154c 1556 keysize = ecc_sets[x].size;
wolfSSL 0:d92f9d21154c 1557
wolfSSL 0:d92f9d21154c 1558 if (keysize > ECC_MAXSIZE || ecc_sets[x].size == 0) {
wolfSSL 0:d92f9d21154c 1559 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 1560 }
wolfSSL 0:d92f9d21154c 1561 err = wc_ecc_make_key_ex(rng, key, &ecc_sets[x]);
wolfSSL 0:d92f9d21154c 1562 key->idx = x;
wolfSSL 0:d92f9d21154c 1563
wolfSSL 0:d92f9d21154c 1564 return err;
wolfSSL 0:d92f9d21154c 1565 }
wolfSSL 0:d92f9d21154c 1566
wolfSSL 0:d92f9d21154c 1567 int wc_ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
wolfSSL 0:d92f9d21154c 1568 {
wolfSSL 0:d92f9d21154c 1569 int err;
wolfSSL 0:d92f9d21154c 1570 ecc_point* base;
wolfSSL 0:d92f9d21154c 1571 mp_int prime;
wolfSSL 0:d92f9d21154c 1572 mp_int order;
wolfSSL 0:d92f9d21154c 1573 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 1574 byte* buf;
wolfSSL 0:d92f9d21154c 1575 #else
wolfSSL 0:d92f9d21154c 1576 byte buf[ECC_MAXSIZE];
wolfSSL 0:d92f9d21154c 1577 #endif
wolfSSL 0:d92f9d21154c 1578 int keysize;
wolfSSL 0:d92f9d21154c 1579 int po_init = 0; /* prime order Init flag for clear */
wolfSSL 0:d92f9d21154c 1580
wolfSSL 0:d92f9d21154c 1581 if (key == NULL || rng == NULL || dp == NULL)
wolfSSL 0:d92f9d21154c 1582 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1583
wolfSSL 0:d92f9d21154c 1584 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 1585 buf = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 1586 if (buf == NULL)
wolfSSL 0:d92f9d21154c 1587 return MEMORY_E;
wolfSSL 0:d92f9d21154c 1588 #endif
wolfSSL 0:d92f9d21154c 1589
wolfSSL 0:d92f9d21154c 1590 key->idx = -1;
wolfSSL 0:d92f9d21154c 1591 key->dp = dp;
wolfSSL 0:d92f9d21154c 1592 keysize = dp->size;
wolfSSL 0:d92f9d21154c 1593
wolfSSL 0:d92f9d21154c 1594 /* allocate ram */
wolfSSL 0:d92f9d21154c 1595 base = NULL;
wolfSSL 0:d92f9d21154c 1596
wolfSSL 0:d92f9d21154c 1597 /* make up random string */
wolfSSL 0:d92f9d21154c 1598 err = wc_RNG_GenerateBlock(rng, buf, keysize);
wolfSSL 0:d92f9d21154c 1599 if (err == 0)
wolfSSL 0:d92f9d21154c 1600 buf[0] |= 0x0c;
wolfSSL 0:d92f9d21154c 1601
wolfSSL 0:d92f9d21154c 1602 /* setup the key variables */
wolfSSL 0:d92f9d21154c 1603 if (err == 0) {
wolfSSL 0:d92f9d21154c 1604 #ifndef ALT_ECC_SIZE
wolfSSL 0:d92f9d21154c 1605 err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z,
wolfSSL 0:d92f9d21154c 1606 &key->k, &prime, &order);
wolfSSL 0:d92f9d21154c 1607 #else
wolfSSL 0:d92f9d21154c 1608 key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
wolfSSL 0:d92f9d21154c 1609 key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
wolfSSL 0:d92f9d21154c 1610 key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
wolfSSL 0:d92f9d21154c 1611 alt_fp_init(key->pubkey.x);
wolfSSL 0:d92f9d21154c 1612 alt_fp_init(key->pubkey.y);
wolfSSL 0:d92f9d21154c 1613 alt_fp_init(key->pubkey.z);
wolfSSL 0:d92f9d21154c 1614 err = mp_init_multi(&key->k, &prime, &order, NULL, NULL, NULL);
wolfSSL 0:d92f9d21154c 1615 #endif
wolfSSL 0:d92f9d21154c 1616 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 1617 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 1618 else
wolfSSL 0:d92f9d21154c 1619 po_init = 1;
wolfSSL 0:d92f9d21154c 1620 }
wolfSSL 0:d92f9d21154c 1621
wolfSSL 0:d92f9d21154c 1622 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1623 base = ecc_new_point();
wolfSSL 0:d92f9d21154c 1624 if (base == NULL)
wolfSSL 0:d92f9d21154c 1625 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 1626 }
wolfSSL 0:d92f9d21154c 1627
wolfSSL 0:d92f9d21154c 1628 /* read in the specs for this key */
wolfSSL 0:d92f9d21154c 1629 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1630 err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
wolfSSL 0:d92f9d21154c 1631 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1632 err = mp_read_radix(&order, (char *)key->dp->order, 16);
wolfSSL 0:d92f9d21154c 1633 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1634 err = mp_read_radix(base->x, (char *)key->dp->Gx, 16);
wolfSSL 0:d92f9d21154c 1635 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1636 err = mp_read_radix(base->y, (char *)key->dp->Gy, 16);
wolfSSL 0:d92f9d21154c 1637
wolfSSL 0:d92f9d21154c 1638 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1639 mp_set(base->z, 1);
wolfSSL 0:d92f9d21154c 1640 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1641 err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize);
wolfSSL 0:d92f9d21154c 1642
wolfSSL 0:d92f9d21154c 1643 /* the key should be smaller than the order of base point */
wolfSSL 0:d92f9d21154c 1644 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1645 if (mp_cmp(&key->k, &order) != MP_LT)
wolfSSL 0:d92f9d21154c 1646 err = mp_mod(&key->k, &order, &key->k);
wolfSSL 0:d92f9d21154c 1647 }
wolfSSL 0:d92f9d21154c 1648 /* make the public key */
wolfSSL 0:d92f9d21154c 1649 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1650 err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1);
wolfSSL 0:d92f9d21154c 1651
wolfSSL 0:d92f9d21154c 1652 #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
wolfSSL 0:d92f9d21154c 1653 /* validate the public key, order * pubkey = point at infinity */
wolfSSL 0:d92f9d21154c 1654 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1655 err = ecc_check_pubkey_order(key, &prime, &order);
wolfSSL 0:d92f9d21154c 1656 #endif /* WOLFSSL_VALIDATE_KEYGEN */
wolfSSL 0:d92f9d21154c 1657
wolfSSL 0:d92f9d21154c 1658 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1659 key->type = ECC_PRIVATEKEY;
wolfSSL 0:d92f9d21154c 1660
wolfSSL 0:d92f9d21154c 1661 if (err != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1662 /* clean up */
wolfSSL 0:d92f9d21154c 1663 mp_clear(key->pubkey.x);
wolfSSL 0:d92f9d21154c 1664 mp_clear(key->pubkey.y);
wolfSSL 0:d92f9d21154c 1665 mp_clear(key->pubkey.z);
wolfSSL 0:d92f9d21154c 1666 mp_clear(&key->k);
wolfSSL 0:d92f9d21154c 1667 }
wolfSSL 0:d92f9d21154c 1668 ecc_del_point(base);
wolfSSL 0:d92f9d21154c 1669 if (po_init) {
wolfSSL 0:d92f9d21154c 1670 mp_clear(&prime);
wolfSSL 0:d92f9d21154c 1671 mp_clear(&order);
wolfSSL 0:d92f9d21154c 1672 }
wolfSSL 0:d92f9d21154c 1673
wolfSSL 0:d92f9d21154c 1674 ForceZero(buf, ECC_MAXSIZE);
wolfSSL 0:d92f9d21154c 1675 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 1676 XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 1677 #endif
wolfSSL 0:d92f9d21154c 1678
wolfSSL 0:d92f9d21154c 1679 return err;
wolfSSL 0:d92f9d21154c 1680 }
wolfSSL 0:d92f9d21154c 1681
wolfSSL 0:d92f9d21154c 1682
wolfSSL 0:d92f9d21154c 1683 /* Setup dynamic pointers is using normal math for proper freeing */
wolfSSL 0:d92f9d21154c 1684 int wc_ecc_init(ecc_key* key)
wolfSSL 0:d92f9d21154c 1685 {
wolfSSL 0:d92f9d21154c 1686 (void)key;
wolfSSL 0:d92f9d21154c 1687
wolfSSL 0:d92f9d21154c 1688 #ifndef USE_FAST_MATH
wolfSSL 0:d92f9d21154c 1689 key->pubkey.x->dp = NULL;
wolfSSL 0:d92f9d21154c 1690 key->pubkey.y->dp = NULL;
wolfSSL 0:d92f9d21154c 1691 key->pubkey.z->dp = NULL;
wolfSSL 0:d92f9d21154c 1692
wolfSSL 0:d92f9d21154c 1693 key->k.dp = NULL;
wolfSSL 0:d92f9d21154c 1694 #endif
wolfSSL 0:d92f9d21154c 1695
wolfSSL 0:d92f9d21154c 1696 #ifdef ALT_ECC_SIZE
wolfSSL 0:d92f9d21154c 1697 if (mp_init(&key->k) != MP_OKAY)
wolfSSL 0:d92f9d21154c 1698 return MEMORY_E;
wolfSSL 0:d92f9d21154c 1699
wolfSSL 0:d92f9d21154c 1700 key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
wolfSSL 0:d92f9d21154c 1701 key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
wolfSSL 0:d92f9d21154c 1702 key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
wolfSSL 0:d92f9d21154c 1703 alt_fp_init(key->pubkey.x);
wolfSSL 0:d92f9d21154c 1704 alt_fp_init(key->pubkey.y);
wolfSSL 0:d92f9d21154c 1705 alt_fp_init(key->pubkey.z);
wolfSSL 0:d92f9d21154c 1706 #endif
wolfSSL 0:d92f9d21154c 1707
wolfSSL 0:d92f9d21154c 1708 return 0;
wolfSSL 0:d92f9d21154c 1709 }
wolfSSL 0:d92f9d21154c 1710
wolfSSL 0:d92f9d21154c 1711
wolfSSL 0:d92f9d21154c 1712 /**
wolfSSL 0:d92f9d21154c 1713 Sign a message digest
wolfSSL 0:d92f9d21154c 1714 in The message digest to sign
wolfSSL 0:d92f9d21154c 1715 inlen The length of the digest
wolfSSL 0:d92f9d21154c 1716 out [out] The destination for the signature
wolfSSL 0:d92f9d21154c 1717 outlen [in/out] The max size and resulting size of the signature
wolfSSL 0:d92f9d21154c 1718 key A private ECC key
wolfSSL 0:d92f9d21154c 1719 return MP_OKAY if successful
wolfSSL 0:d92f9d21154c 1720 */
wolfSSL 0:d92f9d21154c 1721 int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
wolfSSL 0:d92f9d21154c 1722 RNG* rng, ecc_key* key)
wolfSSL 0:d92f9d21154c 1723 {
wolfSSL 0:d92f9d21154c 1724 mp_int r;
wolfSSL 0:d92f9d21154c 1725 mp_int s;
wolfSSL 0:d92f9d21154c 1726 mp_int e;
wolfSSL 0:d92f9d21154c 1727 mp_int p;
wolfSSL 0:d92f9d21154c 1728 int err;
wolfSSL 0:d92f9d21154c 1729
wolfSSL 0:d92f9d21154c 1730 if (in == NULL || out == NULL || outlen == NULL || key == NULL || rng ==NULL)
wolfSSL 0:d92f9d21154c 1731 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1732
wolfSSL 0:d92f9d21154c 1733 /* is this a private key? */
wolfSSL 0:d92f9d21154c 1734 if (key->type != ECC_PRIVATEKEY) {
wolfSSL 0:d92f9d21154c 1735 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1736 }
wolfSSL 0:d92f9d21154c 1737
wolfSSL 0:d92f9d21154c 1738 /* is the IDX valid ? */
wolfSSL 0:d92f9d21154c 1739 if (ecc_is_valid_idx(key->idx) != 1) {
wolfSSL 0:d92f9d21154c 1740 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1741 }
wolfSSL 0:d92f9d21154c 1742
wolfSSL 0:d92f9d21154c 1743 /* get the hash and load it as a bignum into 'e' */
wolfSSL 0:d92f9d21154c 1744 /* init the bignums */
wolfSSL 0:d92f9d21154c 1745 if ((err = mp_init_multi(&r, &s, &p, &e, NULL, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 1746 return err;
wolfSSL 0:d92f9d21154c 1747 }
wolfSSL 0:d92f9d21154c 1748 err = mp_read_radix(&p, (char *)key->dp->order, 16);
wolfSSL 0:d92f9d21154c 1749
wolfSSL 0:d92f9d21154c 1750 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1751 /* we may need to truncate if hash is longer than key size */
wolfSSL 0:d92f9d21154c 1752 word32 orderBits = mp_count_bits(&p);
wolfSSL 0:d92f9d21154c 1753
wolfSSL 0:d92f9d21154c 1754 /* truncate down to byte size, may be all that's needed */
wolfSSL 0:d92f9d21154c 1755 if ( (WOLFSSL_BIT_SIZE * inlen) > orderBits)
wolfSSL 0:d92f9d21154c 1756 inlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE;
wolfSSL 0:d92f9d21154c 1757 err = mp_read_unsigned_bin(&e, (byte*)in, inlen);
wolfSSL 0:d92f9d21154c 1758
wolfSSL 0:d92f9d21154c 1759 /* may still need bit truncation too */
wolfSSL 0:d92f9d21154c 1760 if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits)
wolfSSL 0:d92f9d21154c 1761 mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
wolfSSL 0:d92f9d21154c 1762 }
wolfSSL 0:d92f9d21154c 1763
wolfSSL 0:d92f9d21154c 1764 /* make up a key and export the public copy */
wolfSSL 0:d92f9d21154c 1765 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1766 int loop_check = 0;
wolfSSL 0:d92f9d21154c 1767 ecc_key pubkey;
wolfSSL 0:d92f9d21154c 1768 wc_ecc_init(&pubkey);
wolfSSL 0:d92f9d21154c 1769 for (;;) {
wolfSSL 0:d92f9d21154c 1770 if (++loop_check > 64) {
wolfSSL 0:d92f9d21154c 1771 err = RNG_FAILURE_E;
wolfSSL 0:d92f9d21154c 1772 break;
wolfSSL 0:d92f9d21154c 1773 }
wolfSSL 0:d92f9d21154c 1774 err = wc_ecc_make_key_ex(rng, &pubkey, key->dp);
wolfSSL 0:d92f9d21154c 1775 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1776
wolfSSL 0:d92f9d21154c 1777 /* find r = x1 mod n */
wolfSSL 0:d92f9d21154c 1778 err = mp_mod(pubkey.pubkey.x, &p, &r);
wolfSSL 0:d92f9d21154c 1779 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1780
wolfSSL 0:d92f9d21154c 1781 if (mp_iszero(&r) == MP_YES) {
wolfSSL 0:d92f9d21154c 1782 mp_clear(pubkey.pubkey.x);
wolfSSL 0:d92f9d21154c 1783 mp_clear(pubkey.pubkey.y);
wolfSSL 0:d92f9d21154c 1784 mp_clear(pubkey.pubkey.z);
wolfSSL 0:d92f9d21154c 1785 mp_clear(&pubkey.k);
wolfSSL 0:d92f9d21154c 1786 }
wolfSSL 0:d92f9d21154c 1787 else {
wolfSSL 0:d92f9d21154c 1788 /* find s = (e + xr)/k */
wolfSSL 0:d92f9d21154c 1789 err = mp_invmod(&pubkey.k, &p, &pubkey.k);
wolfSSL 0:d92f9d21154c 1790 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1791
wolfSSL 0:d92f9d21154c 1792 err = mp_mulmod(&key->k, &r, &p, &s); /* s = xr */
wolfSSL 0:d92f9d21154c 1793 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1794
wolfSSL 0:d92f9d21154c 1795 err = mp_add(&e, &s, &s); /* s = e + xr */
wolfSSL 0:d92f9d21154c 1796 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1797
wolfSSL 0:d92f9d21154c 1798 err = mp_mod(&s, &p, &s); /* s = e + xr */
wolfSSL 0:d92f9d21154c 1799 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1800
wolfSSL 0:d92f9d21154c 1801 err = mp_mulmod(&s, &pubkey.k, &p, &s); /* s = (e + xr)/k */
wolfSSL 0:d92f9d21154c 1802 if (err != MP_OKAY) break;
wolfSSL 0:d92f9d21154c 1803
wolfSSL 0:d92f9d21154c 1804 if (mp_iszero(&s) == MP_NO)
wolfSSL 0:d92f9d21154c 1805 break;
wolfSSL 0:d92f9d21154c 1806 }
wolfSSL 0:d92f9d21154c 1807 }
wolfSSL 0:d92f9d21154c 1808 wc_ecc_free(&pubkey);
wolfSSL 0:d92f9d21154c 1809 }
wolfSSL 0:d92f9d21154c 1810
wolfSSL 0:d92f9d21154c 1811 /* store as SEQUENCE { r, s -- integer } */
wolfSSL 0:d92f9d21154c 1812 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1813 err = StoreECC_DSA_Sig(out, outlen, &r, &s);
wolfSSL 0:d92f9d21154c 1814
wolfSSL 0:d92f9d21154c 1815 mp_clear(&r);
wolfSSL 0:d92f9d21154c 1816 mp_clear(&s);
wolfSSL 0:d92f9d21154c 1817 mp_clear(&p);
wolfSSL 0:d92f9d21154c 1818 mp_clear(&e);
wolfSSL 0:d92f9d21154c 1819
wolfSSL 0:d92f9d21154c 1820 return err;
wolfSSL 0:d92f9d21154c 1821 }
wolfSSL 0:d92f9d21154c 1822
wolfSSL 0:d92f9d21154c 1823
wolfSSL 0:d92f9d21154c 1824 /**
wolfSSL 0:d92f9d21154c 1825 Free an ECC key from memory
wolfSSL 0:d92f9d21154c 1826 key The key you wish to free
wolfSSL 0:d92f9d21154c 1827 */
wolfSSL 0:d92f9d21154c 1828 void wc_ecc_free(ecc_key* key)
wolfSSL 0:d92f9d21154c 1829 {
wolfSSL 0:d92f9d21154c 1830 if (key == NULL)
wolfSSL 0:d92f9d21154c 1831 return;
wolfSSL 0:d92f9d21154c 1832
wolfSSL 0:d92f9d21154c 1833 mp_clear(key->pubkey.x);
wolfSSL 0:d92f9d21154c 1834 mp_clear(key->pubkey.y);
wolfSSL 0:d92f9d21154c 1835 mp_clear(key->pubkey.z);
wolfSSL 0:d92f9d21154c 1836 mp_clear(&key->k);
wolfSSL 0:d92f9d21154c 1837 }
wolfSSL 0:d92f9d21154c 1838
wolfSSL 0:d92f9d21154c 1839
wolfSSL 0:d92f9d21154c 1840 #ifdef USE_FAST_MATH
wolfSSL 0:d92f9d21154c 1841 #define GEN_MEM_ERR FP_MEM
wolfSSL 0:d92f9d21154c 1842 #else
wolfSSL 0:d92f9d21154c 1843 #define GEN_MEM_ERR MP_MEM
wolfSSL 0:d92f9d21154c 1844 #endif
wolfSSL 0:d92f9d21154c 1845
wolfSSL 0:d92f9d21154c 1846 #ifdef ECC_SHAMIR
wolfSSL 0:d92f9d21154c 1847
wolfSSL 0:d92f9d21154c 1848 /** Computes kA*A + kB*B = C using Shamir's Trick
wolfSSL 0:d92f9d21154c 1849 A First point to multiply
wolfSSL 0:d92f9d21154c 1850 kA What to multiple A by
wolfSSL 0:d92f9d21154c 1851 B Second point to multiply
wolfSSL 0:d92f9d21154c 1852 kB What to multiple B by
wolfSSL 0:d92f9d21154c 1853 C [out] Destination point (can overlap with A or B)
wolfSSL 0:d92f9d21154c 1854 modulus Modulus for curve
wolfSSL 0:d92f9d21154c 1855 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 1856 */
wolfSSL 0:d92f9d21154c 1857 #ifdef FP_ECC
wolfSSL 0:d92f9d21154c 1858 static int normal_ecc_mul2add(ecc_point* A, mp_int* kA,
wolfSSL 0:d92f9d21154c 1859 ecc_point* B, mp_int* kB,
wolfSSL 0:d92f9d21154c 1860 ecc_point* C, mp_int* modulus)
wolfSSL 0:d92f9d21154c 1861 #else
wolfSSL 0:d92f9d21154c 1862 static int ecc_mul2add(ecc_point* A, mp_int* kA,
wolfSSL 0:d92f9d21154c 1863 ecc_point* B, mp_int* kB,
wolfSSL 0:d92f9d21154c 1864 ecc_point* C, mp_int* modulus)
wolfSSL 0:d92f9d21154c 1865 #endif
wolfSSL 0:d92f9d21154c 1866 {
wolfSSL 0:d92f9d21154c 1867 ecc_point* precomp[16];
wolfSSL 0:d92f9d21154c 1868 unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;
wolfSSL 0:d92f9d21154c 1869 unsigned char* tA;
wolfSSL 0:d92f9d21154c 1870 unsigned char* tB;
wolfSSL 0:d92f9d21154c 1871 int err = MP_OKAY, first;
wolfSSL 0:d92f9d21154c 1872 int muInit = 0;
wolfSSL 0:d92f9d21154c 1873 int tableInit = 0;
wolfSSL 0:d92f9d21154c 1874 mp_digit mp;
wolfSSL 0:d92f9d21154c 1875 mp_int mu;
wolfSSL 0:d92f9d21154c 1876
wolfSSL 0:d92f9d21154c 1877 /* argchks */
wolfSSL 0:d92f9d21154c 1878 if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL ||
wolfSSL 0:d92f9d21154c 1879 modulus == NULL)
wolfSSL 0:d92f9d21154c 1880 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 1881
wolfSSL 0:d92f9d21154c 1882
wolfSSL 0:d92f9d21154c 1883 /* allocate memory */
wolfSSL 0:d92f9d21154c 1884 tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 1885 if (tA == NULL) {
wolfSSL 0:d92f9d21154c 1886 return GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 1887 }
wolfSSL 0:d92f9d21154c 1888 tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 1889 if (tB == NULL) {
wolfSSL 0:d92f9d21154c 1890 XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 1891 return GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 1892 }
wolfSSL 0:d92f9d21154c 1893 XMEMSET(tA, 0, ECC_BUFSIZE);
wolfSSL 0:d92f9d21154c 1894 XMEMSET(tB, 0, ECC_BUFSIZE);
wolfSSL 0:d92f9d21154c 1895
wolfSSL 0:d92f9d21154c 1896 /* get sizes */
wolfSSL 0:d92f9d21154c 1897 lenA = mp_unsigned_bin_size(kA);
wolfSSL 0:d92f9d21154c 1898 lenB = mp_unsigned_bin_size(kB);
wolfSSL 0:d92f9d21154c 1899 len = MAX(lenA, lenB);
wolfSSL 0:d92f9d21154c 1900
wolfSSL 0:d92f9d21154c 1901 /* sanity check */
wolfSSL 0:d92f9d21154c 1902 if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) {
wolfSSL 0:d92f9d21154c 1903 err = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 1904 }
wolfSSL 0:d92f9d21154c 1905
wolfSSL 0:d92f9d21154c 1906 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1907 /* extract and justify kA */
wolfSSL 0:d92f9d21154c 1908 err = mp_to_unsigned_bin(kA, (len - lenA) + tA);
wolfSSL 0:d92f9d21154c 1909
wolfSSL 0:d92f9d21154c 1910 /* extract and justify kB */
wolfSSL 0:d92f9d21154c 1911 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1912 err = mp_to_unsigned_bin(kB, (len - lenB) + tB);
wolfSSL 0:d92f9d21154c 1913
wolfSSL 0:d92f9d21154c 1914 /* allocate the table */
wolfSSL 0:d92f9d21154c 1915 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1916 for (x = 0; x < 16; x++) {
wolfSSL 0:d92f9d21154c 1917 precomp[x] = ecc_new_point();
wolfSSL 0:d92f9d21154c 1918 if (precomp[x] == NULL) {
wolfSSL 0:d92f9d21154c 1919 for (y = 0; y < x; ++y) {
wolfSSL 0:d92f9d21154c 1920 ecc_del_point(precomp[y]);
wolfSSL 0:d92f9d21154c 1921 }
wolfSSL 0:d92f9d21154c 1922 err = GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 1923 break;
wolfSSL 0:d92f9d21154c 1924 }
wolfSSL 0:d92f9d21154c 1925 }
wolfSSL 0:d92f9d21154c 1926 }
wolfSSL 0:d92f9d21154c 1927 }
wolfSSL 0:d92f9d21154c 1928
wolfSSL 0:d92f9d21154c 1929 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1930 tableInit = 1;
wolfSSL 0:d92f9d21154c 1931
wolfSSL 0:d92f9d21154c 1932 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1933 /* init montgomery reduction */
wolfSSL 0:d92f9d21154c 1934 err = mp_montgomery_setup(modulus, &mp);
wolfSSL 0:d92f9d21154c 1935
wolfSSL 0:d92f9d21154c 1936 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1937 err = mp_init(&mu);
wolfSSL 0:d92f9d21154c 1938 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1939 muInit = 1;
wolfSSL 0:d92f9d21154c 1940
wolfSSL 0:d92f9d21154c 1941 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1942 err = mp_montgomery_calc_normalization(&mu, modulus);
wolfSSL 0:d92f9d21154c 1943
wolfSSL 0:d92f9d21154c 1944 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1945 /* copy ones ... */
wolfSSL 0:d92f9d21154c 1946 err = mp_mulmod(A->x, &mu, modulus, precomp[1]->x);
wolfSSL 0:d92f9d21154c 1947
wolfSSL 0:d92f9d21154c 1948 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1949 err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y);
wolfSSL 0:d92f9d21154c 1950 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1951 err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z);
wolfSSL 0:d92f9d21154c 1952
wolfSSL 0:d92f9d21154c 1953 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1954 err = mp_mulmod(B->x, &mu, modulus, precomp[1<<2]->x);
wolfSSL 0:d92f9d21154c 1955 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1956 err = mp_mulmod(B->y, &mu, modulus, precomp[1<<2]->y);
wolfSSL 0:d92f9d21154c 1957 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1958 err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z);
wolfSSL 0:d92f9d21154c 1959
wolfSSL 0:d92f9d21154c 1960 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1961 /* precomp [i,0](A + B) table */
wolfSSL 0:d92f9d21154c 1962 err = ecc_projective_dbl_point(precomp[1], precomp[2], modulus, &mp);
wolfSSL 0:d92f9d21154c 1963
wolfSSL 0:d92f9d21154c 1964 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1965 err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3],
wolfSSL 0:d92f9d21154c 1966 modulus, &mp);
wolfSSL 0:d92f9d21154c 1967 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1968 /* precomp [0,i](A + B) table */
wolfSSL 0:d92f9d21154c 1969 err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], modulus, &mp);
wolfSSL 0:d92f9d21154c 1970
wolfSSL 0:d92f9d21154c 1971 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1972 err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2],
wolfSSL 0:d92f9d21154c 1973 modulus, &mp);
wolfSSL 0:d92f9d21154c 1974
wolfSSL 0:d92f9d21154c 1975 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1976 /* precomp [i,j](A + B) table (i != 0, j != 0) */
wolfSSL 0:d92f9d21154c 1977 for (x = 1; x < 4; x++) {
wolfSSL 0:d92f9d21154c 1978 for (y = 1; y < 4; y++) {
wolfSSL 0:d92f9d21154c 1979 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 1980 err = ecc_projective_add_point(precomp[x], precomp[(y<<2)],
wolfSSL 0:d92f9d21154c 1981 precomp[x+(y<<2)], modulus, &mp);
wolfSSL 0:d92f9d21154c 1982 }
wolfSSL 0:d92f9d21154c 1983 }
wolfSSL 0:d92f9d21154c 1984 }
wolfSSL 0:d92f9d21154c 1985
wolfSSL 0:d92f9d21154c 1986 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 1987 nibble = 3;
wolfSSL 0:d92f9d21154c 1988 first = 1;
wolfSSL 0:d92f9d21154c 1989 bitbufA = tA[0];
wolfSSL 0:d92f9d21154c 1990 bitbufB = tB[0];
wolfSSL 0:d92f9d21154c 1991
wolfSSL 0:d92f9d21154c 1992 /* for every byte of the multiplicands */
wolfSSL 0:d92f9d21154c 1993 for (x = -1;; ) {
wolfSSL 0:d92f9d21154c 1994 /* grab a nibble */
wolfSSL 0:d92f9d21154c 1995 if (++nibble == 4) {
wolfSSL 0:d92f9d21154c 1996 ++x; if (x == len) break;
wolfSSL 0:d92f9d21154c 1997 bitbufA = tA[x];
wolfSSL 0:d92f9d21154c 1998 bitbufB = tB[x];
wolfSSL 0:d92f9d21154c 1999 nibble = 0;
wolfSSL 0:d92f9d21154c 2000 }
wolfSSL 0:d92f9d21154c 2001
wolfSSL 0:d92f9d21154c 2002 /* extract two bits from both, shift/update */
wolfSSL 0:d92f9d21154c 2003 nA = (bitbufA >> 6) & 0x03;
wolfSSL 0:d92f9d21154c 2004 nB = (bitbufB >> 6) & 0x03;
wolfSSL 0:d92f9d21154c 2005 bitbufA = (bitbufA << 2) & 0xFF;
wolfSSL 0:d92f9d21154c 2006 bitbufB = (bitbufB << 2) & 0xFF;
wolfSSL 0:d92f9d21154c 2007
wolfSSL 0:d92f9d21154c 2008 /* if both zero, if first, continue */
wolfSSL 0:d92f9d21154c 2009 if ((nA == 0) && (nB == 0) && (first == 1)) {
wolfSSL 0:d92f9d21154c 2010 continue;
wolfSSL 0:d92f9d21154c 2011 }
wolfSSL 0:d92f9d21154c 2012
wolfSSL 0:d92f9d21154c 2013 /* double twice, only if this isn't the first */
wolfSSL 0:d92f9d21154c 2014 if (first == 0) {
wolfSSL 0:d92f9d21154c 2015 /* double twice */
wolfSSL 0:d92f9d21154c 2016 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2017 err = ecc_projective_dbl_point(C, C, modulus, &mp);
wolfSSL 0:d92f9d21154c 2018 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2019 err = ecc_projective_dbl_point(C, C, modulus, &mp);
wolfSSL 0:d92f9d21154c 2020 else
wolfSSL 0:d92f9d21154c 2021 break;
wolfSSL 0:d92f9d21154c 2022 }
wolfSSL 0:d92f9d21154c 2023
wolfSSL 0:d92f9d21154c 2024 /* if not both zero */
wolfSSL 0:d92f9d21154c 2025 if ((nA != 0) || (nB != 0)) {
wolfSSL 0:d92f9d21154c 2026 if (first == 1) {
wolfSSL 0:d92f9d21154c 2027 /* if first, copy from table */
wolfSSL 0:d92f9d21154c 2028 first = 0;
wolfSSL 0:d92f9d21154c 2029 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2030 err = mp_copy(precomp[nA + (nB<<2)]->x, C->x);
wolfSSL 0:d92f9d21154c 2031
wolfSSL 0:d92f9d21154c 2032 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2033 err = mp_copy(precomp[nA + (nB<<2)]->y, C->y);
wolfSSL 0:d92f9d21154c 2034
wolfSSL 0:d92f9d21154c 2035 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2036 err = mp_copy(precomp[nA + (nB<<2)]->z, C->z);
wolfSSL 0:d92f9d21154c 2037 else
wolfSSL 0:d92f9d21154c 2038 break;
wolfSSL 0:d92f9d21154c 2039 } else {
wolfSSL 0:d92f9d21154c 2040 /* if not first, add from table */
wolfSSL 0:d92f9d21154c 2041 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2042 err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C,
wolfSSL 0:d92f9d21154c 2043 modulus, &mp);
wolfSSL 0:d92f9d21154c 2044 else
wolfSSL 0:d92f9d21154c 2045 break;
wolfSSL 0:d92f9d21154c 2046 }
wolfSSL 0:d92f9d21154c 2047 }
wolfSSL 0:d92f9d21154c 2048 }
wolfSSL 0:d92f9d21154c 2049 }
wolfSSL 0:d92f9d21154c 2050
wolfSSL 0:d92f9d21154c 2051 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2052 /* reduce to affine */
wolfSSL 0:d92f9d21154c 2053 err = ecc_map(C, modulus, &mp);
wolfSSL 0:d92f9d21154c 2054
wolfSSL 0:d92f9d21154c 2055 /* clean up */
wolfSSL 0:d92f9d21154c 2056 if (muInit)
wolfSSL 0:d92f9d21154c 2057 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 2058
wolfSSL 0:d92f9d21154c 2059 if (tableInit) {
wolfSSL 0:d92f9d21154c 2060 for (x = 0; x < 16; x++) {
wolfSSL 0:d92f9d21154c 2061 ecc_del_point(precomp[x]);
wolfSSL 0:d92f9d21154c 2062 }
wolfSSL 0:d92f9d21154c 2063 }
wolfSSL 0:d92f9d21154c 2064 ForceZero(tA, ECC_BUFSIZE);
wolfSSL 0:d92f9d21154c 2065 ForceZero(tB, ECC_BUFSIZE);
wolfSSL 0:d92f9d21154c 2066 XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 2067 XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 2068
wolfSSL 0:d92f9d21154c 2069 return err;
wolfSSL 0:d92f9d21154c 2070 }
wolfSSL 0:d92f9d21154c 2071
wolfSSL 0:d92f9d21154c 2072
wolfSSL 0:d92f9d21154c 2073 #endif /* ECC_SHAMIR */
wolfSSL 0:d92f9d21154c 2074
wolfSSL 0:d92f9d21154c 2075
wolfSSL 0:d92f9d21154c 2076
wolfSSL 0:d92f9d21154c 2077 /* verify
wolfSSL 0:d92f9d21154c 2078 *
wolfSSL 0:d92f9d21154c 2079 * w = s^-1 mod n
wolfSSL 0:d92f9d21154c 2080 * u1 = xw
wolfSSL 0:d92f9d21154c 2081 * u2 = rw
wolfSSL 0:d92f9d21154c 2082 * X = u1*G + u2*Q
wolfSSL 0:d92f9d21154c 2083 * v = X_x1 mod n
wolfSSL 0:d92f9d21154c 2084 * accept if v == r
wolfSSL 0:d92f9d21154c 2085 */
wolfSSL 0:d92f9d21154c 2086
wolfSSL 0:d92f9d21154c 2087 /**
wolfSSL 0:d92f9d21154c 2088 Verify an ECC signature
wolfSSL 0:d92f9d21154c 2089 sig The signature to verify
wolfSSL 0:d92f9d21154c 2090 siglen The length of the signature (octets)
wolfSSL 0:d92f9d21154c 2091 hash The hash (message digest) that was signed
wolfSSL 0:d92f9d21154c 2092 hashlen The length of the hash (octets)
wolfSSL 0:d92f9d21154c 2093 stat Result of signature, 1==valid, 0==invalid
wolfSSL 0:d92f9d21154c 2094 key The corresponding public ECC key
wolfSSL 0:d92f9d21154c 2095 return MP_OKAY if successful (even if the signature is not valid)
wolfSSL 0:d92f9d21154c 2096 */
wolfSSL 0:d92f9d21154c 2097 int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
wolfSSL 0:d92f9d21154c 2098 word32 hashlen, int* stat, ecc_key* key)
wolfSSL 0:d92f9d21154c 2099 {
wolfSSL 0:d92f9d21154c 2100 ecc_point *mG, *mQ;
wolfSSL 0:d92f9d21154c 2101 mp_int r;
wolfSSL 0:d92f9d21154c 2102 mp_int s;
wolfSSL 0:d92f9d21154c 2103 mp_int v;
wolfSSL 0:d92f9d21154c 2104 mp_int w;
wolfSSL 0:d92f9d21154c 2105 mp_int u1;
wolfSSL 0:d92f9d21154c 2106 mp_int u2;
wolfSSL 0:d92f9d21154c 2107 mp_int e;
wolfSSL 0:d92f9d21154c 2108 mp_int p;
wolfSSL 0:d92f9d21154c 2109 mp_int m;
wolfSSL 0:d92f9d21154c 2110 int err;
wolfSSL 0:d92f9d21154c 2111
wolfSSL 0:d92f9d21154c 2112 if (sig == NULL || hash == NULL || stat == NULL || key == NULL)
wolfSSL 0:d92f9d21154c 2113 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2114
wolfSSL 0:d92f9d21154c 2115 /* default to invalid signature */
wolfSSL 0:d92f9d21154c 2116 *stat = 0;
wolfSSL 0:d92f9d21154c 2117
wolfSSL 0:d92f9d21154c 2118 /* is the IDX valid ? */
wolfSSL 0:d92f9d21154c 2119 if (ecc_is_valid_idx(key->idx) != 1) {
wolfSSL 0:d92f9d21154c 2120 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2121 }
wolfSSL 0:d92f9d21154c 2122
wolfSSL 0:d92f9d21154c 2123 /* allocate ints */
wolfSSL 0:d92f9d21154c 2124 if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 2125 return MEMORY_E;
wolfSSL 0:d92f9d21154c 2126 }
wolfSSL 0:d92f9d21154c 2127
wolfSSL 0:d92f9d21154c 2128 if ((err = mp_init(&m)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 2129 mp_clear(&v);
wolfSSL 0:d92f9d21154c 2130 mp_clear(&w);
wolfSSL 0:d92f9d21154c 2131 mp_clear(&u1);
wolfSSL 0:d92f9d21154c 2132 mp_clear(&u2);
wolfSSL 0:d92f9d21154c 2133 mp_clear(&p);
wolfSSL 0:d92f9d21154c 2134 mp_clear(&e);
wolfSSL 0:d92f9d21154c 2135 return MEMORY_E;
wolfSSL 0:d92f9d21154c 2136 }
wolfSSL 0:d92f9d21154c 2137
wolfSSL 0:d92f9d21154c 2138 /* allocate points */
wolfSSL 0:d92f9d21154c 2139 mG = ecc_new_point();
wolfSSL 0:d92f9d21154c 2140 mQ = ecc_new_point();
wolfSSL 0:d92f9d21154c 2141 if (mQ == NULL || mG == NULL)
wolfSSL 0:d92f9d21154c 2142 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 2143
wolfSSL 0:d92f9d21154c 2144 /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s.
wolfSSL 0:d92f9d21154c 2145 * If either of those don't allocate correctly, none of
wolfSSL 0:d92f9d21154c 2146 * the rest of this function will execute, and everything
wolfSSL 0:d92f9d21154c 2147 * gets cleaned up at the end. */
wolfSSL 0:d92f9d21154c 2148 XMEMSET(&r, 0, sizeof(r));
wolfSSL 0:d92f9d21154c 2149 XMEMSET(&s, 0, sizeof(s));
wolfSSL 0:d92f9d21154c 2150 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2151 err = DecodeECC_DSA_Sig(sig, siglen, &r, &s);
wolfSSL 0:d92f9d21154c 2152
wolfSSL 0:d92f9d21154c 2153 /* get the order */
wolfSSL 0:d92f9d21154c 2154 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2155 err = mp_read_radix(&p, (char *)key->dp->order, 16);
wolfSSL 0:d92f9d21154c 2156
wolfSSL 0:d92f9d21154c 2157 /* get the modulus */
wolfSSL 0:d92f9d21154c 2158 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2159 err = mp_read_radix(&m, (char *)key->dp->prime, 16);
wolfSSL 0:d92f9d21154c 2160
wolfSSL 0:d92f9d21154c 2161 /* check for zero */
wolfSSL 0:d92f9d21154c 2162 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2163 if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT ||
wolfSSL 0:d92f9d21154c 2164 mp_cmp(&s, &p) != MP_LT)
wolfSSL 0:d92f9d21154c 2165 err = MP_ZERO_E;
wolfSSL 0:d92f9d21154c 2166 }
wolfSSL 0:d92f9d21154c 2167 /* read hash */
wolfSSL 0:d92f9d21154c 2168 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2169 /* we may need to truncate if hash is longer than key size */
wolfSSL 0:d92f9d21154c 2170 unsigned int orderBits = mp_count_bits(&p);
wolfSSL 0:d92f9d21154c 2171
wolfSSL 0:d92f9d21154c 2172 /* truncate down to byte size, may be all that's needed */
wolfSSL 0:d92f9d21154c 2173 if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
wolfSSL 0:d92f9d21154c 2174 hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE;
wolfSSL 0:d92f9d21154c 2175 err = mp_read_unsigned_bin(&e, hash, hashlen);
wolfSSL 0:d92f9d21154c 2176
wolfSSL 0:d92f9d21154c 2177 /* may still need bit truncation too */
wolfSSL 0:d92f9d21154c 2178 if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
wolfSSL 0:d92f9d21154c 2179 mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
wolfSSL 0:d92f9d21154c 2180 }
wolfSSL 0:d92f9d21154c 2181
wolfSSL 0:d92f9d21154c 2182 /* w = s^-1 mod n */
wolfSSL 0:d92f9d21154c 2183 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2184 err = mp_invmod(&s, &p, &w);
wolfSSL 0:d92f9d21154c 2185
wolfSSL 0:d92f9d21154c 2186 /* u1 = ew */
wolfSSL 0:d92f9d21154c 2187 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2188 err = mp_mulmod(&e, &w, &p, &u1);
wolfSSL 0:d92f9d21154c 2189
wolfSSL 0:d92f9d21154c 2190 /* u2 = rw */
wolfSSL 0:d92f9d21154c 2191 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2192 err = mp_mulmod(&r, &w, &p, &u2);
wolfSSL 0:d92f9d21154c 2193
wolfSSL 0:d92f9d21154c 2194 /* find mG and mQ */
wolfSSL 0:d92f9d21154c 2195 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2196 err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16);
wolfSSL 0:d92f9d21154c 2197
wolfSSL 0:d92f9d21154c 2198 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2199 err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16);
wolfSSL 0:d92f9d21154c 2200 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2201 mp_set(mG->z, 1);
wolfSSL 0:d92f9d21154c 2202
wolfSSL 0:d92f9d21154c 2203 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2204 err = mp_copy(key->pubkey.x, mQ->x);
wolfSSL 0:d92f9d21154c 2205 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2206 err = mp_copy(key->pubkey.y, mQ->y);
wolfSSL 0:d92f9d21154c 2207 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2208 err = mp_copy(key->pubkey.z, mQ->z);
wolfSSL 0:d92f9d21154c 2209
wolfSSL 0:d92f9d21154c 2210 #ifndef ECC_SHAMIR
wolfSSL 0:d92f9d21154c 2211 {
wolfSSL 0:d92f9d21154c 2212 mp_digit mp;
wolfSSL 0:d92f9d21154c 2213
wolfSSL 0:d92f9d21154c 2214 /* compute u1*mG + u2*mQ = mG */
wolfSSL 0:d92f9d21154c 2215 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2216 err = ecc_mulmod(&u1, mG, mG, &m, 0);
wolfSSL 0:d92f9d21154c 2217 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2218 err = ecc_mulmod(&u2, mQ, mQ, &m, 0);
wolfSSL 0:d92f9d21154c 2219
wolfSSL 0:d92f9d21154c 2220 /* find the montgomery mp */
wolfSSL 0:d92f9d21154c 2221 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2222 err = mp_montgomery_setup(&m, &mp);
wolfSSL 0:d92f9d21154c 2223
wolfSSL 0:d92f9d21154c 2224 /* add them */
wolfSSL 0:d92f9d21154c 2225 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2226 err = ecc_projective_add_point(mQ, mG, mG, &m, &mp);
wolfSSL 0:d92f9d21154c 2227
wolfSSL 0:d92f9d21154c 2228 /* reduce */
wolfSSL 0:d92f9d21154c 2229 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2230 err = ecc_map(mG, &m, &mp);
wolfSSL 0:d92f9d21154c 2231 }
wolfSSL 0:d92f9d21154c 2232 #else
wolfSSL 0:d92f9d21154c 2233 /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
wolfSSL 0:d92f9d21154c 2234 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2235 err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &m);
wolfSSL 0:d92f9d21154c 2236 #endif /* ECC_SHAMIR */
wolfSSL 0:d92f9d21154c 2237
wolfSSL 0:d92f9d21154c 2238 /* v = X_x1 mod n */
wolfSSL 0:d92f9d21154c 2239 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2240 err = mp_mod(mG->x, &p, &v);
wolfSSL 0:d92f9d21154c 2241
wolfSSL 0:d92f9d21154c 2242 /* does v == r */
wolfSSL 0:d92f9d21154c 2243 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2244 if (mp_cmp(&v, &r) == MP_EQ)
wolfSSL 0:d92f9d21154c 2245 *stat = 1;
wolfSSL 0:d92f9d21154c 2246 }
wolfSSL 0:d92f9d21154c 2247
wolfSSL 0:d92f9d21154c 2248 ecc_del_point(mG);
wolfSSL 0:d92f9d21154c 2249 ecc_del_point(mQ);
wolfSSL 0:d92f9d21154c 2250
wolfSSL 0:d92f9d21154c 2251 mp_clear(&r);
wolfSSL 0:d92f9d21154c 2252 mp_clear(&s);
wolfSSL 0:d92f9d21154c 2253 mp_clear(&v);
wolfSSL 0:d92f9d21154c 2254 mp_clear(&w);
wolfSSL 0:d92f9d21154c 2255 mp_clear(&u1);
wolfSSL 0:d92f9d21154c 2256 mp_clear(&u2);
wolfSSL 0:d92f9d21154c 2257 mp_clear(&p);
wolfSSL 0:d92f9d21154c 2258 mp_clear(&e);
wolfSSL 0:d92f9d21154c 2259 mp_clear(&m);
wolfSSL 0:d92f9d21154c 2260
wolfSSL 0:d92f9d21154c 2261 return err;
wolfSSL 0:d92f9d21154c 2262 }
wolfSSL 0:d92f9d21154c 2263
wolfSSL 0:d92f9d21154c 2264
wolfSSL 0:d92f9d21154c 2265 /* export public ECC key in ANSI X9.63 format */
wolfSSL 0:d92f9d21154c 2266 int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
wolfSSL 0:d92f9d21154c 2267 {
wolfSSL 0:d92f9d21154c 2268 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 2269 byte* buf;
wolfSSL 0:d92f9d21154c 2270 #else
wolfSSL 0:d92f9d21154c 2271 byte buf[ECC_BUFSIZE];
wolfSSL 0:d92f9d21154c 2272 #endif
wolfSSL 0:d92f9d21154c 2273 word32 numlen;
wolfSSL 0:d92f9d21154c 2274 int ret = MP_OKAY;
wolfSSL 0:d92f9d21154c 2275
wolfSSL 0:d92f9d21154c 2276 /* return length needed only */
wolfSSL 0:d92f9d21154c 2277 if (key != NULL && out == NULL && outLen != NULL) {
wolfSSL 0:d92f9d21154c 2278 numlen = key->dp->size;
wolfSSL 0:d92f9d21154c 2279 *outLen = 1 + 2*numlen;
wolfSSL 0:d92f9d21154c 2280 return LENGTH_ONLY_E;
wolfSSL 0:d92f9d21154c 2281 }
wolfSSL 0:d92f9d21154c 2282
wolfSSL 0:d92f9d21154c 2283 if (key == NULL || out == NULL || outLen == NULL)
wolfSSL 0:d92f9d21154c 2284 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2285
wolfSSL 0:d92f9d21154c 2286 if (ecc_is_valid_idx(key->idx) == 0) {
wolfSSL 0:d92f9d21154c 2287 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2288 }
wolfSSL 0:d92f9d21154c 2289 numlen = key->dp->size;
wolfSSL 0:d92f9d21154c 2290
wolfSSL 0:d92f9d21154c 2291 if (*outLen < (1 + 2*numlen)) {
wolfSSL 0:d92f9d21154c 2292 *outLen = 1 + 2*numlen;
wolfSSL 0:d92f9d21154c 2293 return BUFFER_E;
wolfSSL 0:d92f9d21154c 2294 }
wolfSSL 0:d92f9d21154c 2295
wolfSSL 0:d92f9d21154c 2296 /* store byte 0x04 */
wolfSSL 0:d92f9d21154c 2297 out[0] = 0x04;
wolfSSL 0:d92f9d21154c 2298
wolfSSL 0:d92f9d21154c 2299 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 2300 buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 2301 if (buf == NULL)
wolfSSL 0:d92f9d21154c 2302 return MEMORY_E;
wolfSSL 0:d92f9d21154c 2303 #endif
wolfSSL 0:d92f9d21154c 2304
wolfSSL 0:d92f9d21154c 2305 do {
wolfSSL 0:d92f9d21154c 2306 /* pad and store x */
wolfSSL 0:d92f9d21154c 2307 XMEMSET(buf, 0, ECC_BUFSIZE);
wolfSSL 0:d92f9d21154c 2308 ret = mp_to_unsigned_bin(key->pubkey.x,
wolfSSL 0:d92f9d21154c 2309 buf + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
wolfSSL 0:d92f9d21154c 2310 if (ret != MP_OKAY)
wolfSSL 0:d92f9d21154c 2311 break;
wolfSSL 0:d92f9d21154c 2312 XMEMCPY(out+1, buf, numlen);
wolfSSL 0:d92f9d21154c 2313
wolfSSL 0:d92f9d21154c 2314 /* pad and store y */
wolfSSL 0:d92f9d21154c 2315 XMEMSET(buf, 0, ECC_BUFSIZE);
wolfSSL 0:d92f9d21154c 2316 ret = mp_to_unsigned_bin(key->pubkey.y,
wolfSSL 0:d92f9d21154c 2317 buf + (numlen - mp_unsigned_bin_size(key->pubkey.y)));
wolfSSL 0:d92f9d21154c 2318 if (ret != MP_OKAY)
wolfSSL 0:d92f9d21154c 2319 break;
wolfSSL 0:d92f9d21154c 2320 XMEMCPY(out+1+numlen, buf, numlen);
wolfSSL 0:d92f9d21154c 2321
wolfSSL 0:d92f9d21154c 2322 *outLen = 1 + 2*numlen;
wolfSSL 0:d92f9d21154c 2323 } while (0);
wolfSSL 0:d92f9d21154c 2324
wolfSSL 0:d92f9d21154c 2325 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 2326 XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 2327 #endif
wolfSSL 0:d92f9d21154c 2328
wolfSSL 0:d92f9d21154c 2329 return ret;
wolfSSL 0:d92f9d21154c 2330 }
wolfSSL 0:d92f9d21154c 2331
wolfSSL 0:d92f9d21154c 2332
wolfSSL 0:d92f9d21154c 2333 /* export public ECC key in ANSI X9.63 format, extended with
wolfSSL 0:d92f9d21154c 2334 * compression option */
wolfSSL 0:d92f9d21154c 2335 int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, int compressed)
wolfSSL 0:d92f9d21154c 2336 {
wolfSSL 0:d92f9d21154c 2337 if (compressed == 0)
wolfSSL 0:d92f9d21154c 2338 return wc_ecc_export_x963(key, out, outLen);
wolfSSL 0:d92f9d21154c 2339 #ifdef HAVE_COMP_KEY
wolfSSL 0:d92f9d21154c 2340 else
wolfSSL 0:d92f9d21154c 2341 return wc_ecc_export_x963_compressed(key, out, outLen);
wolfSSL 0:d92f9d21154c 2342 #endif
wolfSSL 0:d92f9d21154c 2343
wolfSSL 0:d92f9d21154c 2344 return NOT_COMPILED_IN;
wolfSSL 0:d92f9d21154c 2345 }
wolfSSL 0:d92f9d21154c 2346
wolfSSL 0:d92f9d21154c 2347
wolfSSL 0:d92f9d21154c 2348 /* is ec point on curve descriped by dp ? */
wolfSSL 0:d92f9d21154c 2349 static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
wolfSSL 0:d92f9d21154c 2350 {
wolfSSL 0:d92f9d21154c 2351 mp_int b, t1, t2;
wolfSSL 0:d92f9d21154c 2352 int err;
wolfSSL 0:d92f9d21154c 2353
wolfSSL 0:d92f9d21154c 2354 if ((err = mp_init_multi(&b, &t1, &t2, NULL, NULL, NULL)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 2355 return err;
wolfSSL 0:d92f9d21154c 2356 }
wolfSSL 0:d92f9d21154c 2357
wolfSSL 0:d92f9d21154c 2358 /* load b */
wolfSSL 0:d92f9d21154c 2359 err = mp_read_radix(&b, dp->Bf, 16);
wolfSSL 0:d92f9d21154c 2360
wolfSSL 0:d92f9d21154c 2361 /* compute y^2 */
wolfSSL 0:d92f9d21154c 2362 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2363 err = mp_sqr(ecp->y, &t1);
wolfSSL 0:d92f9d21154c 2364
wolfSSL 0:d92f9d21154c 2365 /* compute x^3 */
wolfSSL 0:d92f9d21154c 2366 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2367 err = mp_sqr(ecp->x, &t2);
wolfSSL 0:d92f9d21154c 2368 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2369 err = mp_mod(&t2, prime, &t2);
wolfSSL 0:d92f9d21154c 2370 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2371 err = mp_mul(ecp->x, &t2, &t2);
wolfSSL 0:d92f9d21154c 2372
wolfSSL 0:d92f9d21154c 2373 /* compute y^2 - x^3 */
wolfSSL 0:d92f9d21154c 2374 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2375 err = mp_sub(&t1, &t2, &t1);
wolfSSL 0:d92f9d21154c 2376
wolfSSL 0:d92f9d21154c 2377 /* compute y^2 - x^3 + 3x */
wolfSSL 0:d92f9d21154c 2378 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2379 err = mp_add(&t1, ecp->x, &t1);
wolfSSL 0:d92f9d21154c 2380 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2381 err = mp_add(&t1, ecp->x, &t1);
wolfSSL 0:d92f9d21154c 2382 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2383 err = mp_add(&t1, ecp->x, &t1);
wolfSSL 0:d92f9d21154c 2384 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2385 err = mp_mod(&t1, prime, &t1);
wolfSSL 0:d92f9d21154c 2386
wolfSSL 0:d92f9d21154c 2387 while (err == MP_OKAY && mp_cmp_d(&t1, 0) == MP_LT) {
wolfSSL 0:d92f9d21154c 2388 err = mp_add(&t1, prime, &t1);
wolfSSL 0:d92f9d21154c 2389 }
wolfSSL 0:d92f9d21154c 2390 while (err == MP_OKAY && mp_cmp(&t1, prime) != MP_LT) {
wolfSSL 0:d92f9d21154c 2391 err = mp_sub(&t1, prime, &t1);
wolfSSL 0:d92f9d21154c 2392 }
wolfSSL 0:d92f9d21154c 2393
wolfSSL 0:d92f9d21154c 2394 /* compare to b */
wolfSSL 0:d92f9d21154c 2395 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2396 if (mp_cmp(&t1, &b) != MP_EQ) {
wolfSSL 0:d92f9d21154c 2397 err = MP_VAL;
wolfSSL 0:d92f9d21154c 2398 } else {
wolfSSL 0:d92f9d21154c 2399 err = MP_OKAY;
wolfSSL 0:d92f9d21154c 2400 }
wolfSSL 0:d92f9d21154c 2401 }
wolfSSL 0:d92f9d21154c 2402
wolfSSL 0:d92f9d21154c 2403 mp_clear(&b);
wolfSSL 0:d92f9d21154c 2404 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 2405 mp_clear(&t2);
wolfSSL 0:d92f9d21154c 2406
wolfSSL 0:d92f9d21154c 2407 return err;
wolfSSL 0:d92f9d21154c 2408 }
wolfSSL 0:d92f9d21154c 2409
wolfSSL 0:d92f9d21154c 2410
wolfSSL 0:d92f9d21154c 2411 /* validate privkey * generator == pubkey, 0 on success */
wolfSSL 0:d92f9d21154c 2412 static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime)
wolfSSL 0:d92f9d21154c 2413 {
wolfSSL 0:d92f9d21154c 2414 ecc_point* base = NULL;
wolfSSL 0:d92f9d21154c 2415 ecc_point* res = NULL;
wolfSSL 0:d92f9d21154c 2416 int err;
wolfSSL 0:d92f9d21154c 2417
wolfSSL 0:d92f9d21154c 2418 if (key == NULL)
wolfSSL 0:d92f9d21154c 2419 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 2420
wolfSSL 0:d92f9d21154c 2421 base = ecc_new_point();
wolfSSL 0:d92f9d21154c 2422 if (base == NULL)
wolfSSL 0:d92f9d21154c 2423 return MEMORY_E;
wolfSSL 0:d92f9d21154c 2424
wolfSSL 0:d92f9d21154c 2425 /* set up base generator */
wolfSSL 0:d92f9d21154c 2426 err = mp_read_radix(base->x, (char*)key->dp->Gx, 16);
wolfSSL 0:d92f9d21154c 2427 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2428 err = mp_read_radix(base->y, (char*)key->dp->Gy, 16);
wolfSSL 0:d92f9d21154c 2429 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2430 mp_set(base->z, 1);
wolfSSL 0:d92f9d21154c 2431
wolfSSL 0:d92f9d21154c 2432 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2433 res = ecc_new_point();
wolfSSL 0:d92f9d21154c 2434 if (res == NULL)
wolfSSL 0:d92f9d21154c 2435 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 2436 else {
wolfSSL 0:d92f9d21154c 2437 err = ecc_mulmod(&key->k, base, res, prime, 1);
wolfSSL 0:d92f9d21154c 2438 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2439 /* compare result to public key */
wolfSSL 0:d92f9d21154c 2440 if (mp_cmp(res->x, key->pubkey.x) != MP_EQ ||
wolfSSL 0:d92f9d21154c 2441 mp_cmp(res->y, key->pubkey.y) != MP_EQ ||
wolfSSL 0:d92f9d21154c 2442 mp_cmp(res->z, key->pubkey.z) != MP_EQ) {
wolfSSL 0:d92f9d21154c 2443 /* didn't match */
wolfSSL 0:d92f9d21154c 2444 err = ECC_PRIV_KEY_E;
wolfSSL 0:d92f9d21154c 2445 }
wolfSSL 0:d92f9d21154c 2446 }
wolfSSL 0:d92f9d21154c 2447 }
wolfSSL 0:d92f9d21154c 2448 }
wolfSSL 0:d92f9d21154c 2449
wolfSSL 0:d92f9d21154c 2450 ecc_del_point(res);
wolfSSL 0:d92f9d21154c 2451 ecc_del_point(base);
wolfSSL 0:d92f9d21154c 2452
wolfSSL 0:d92f9d21154c 2453 return err;
wolfSSL 0:d92f9d21154c 2454 }
wolfSSL 0:d92f9d21154c 2455
wolfSSL 0:d92f9d21154c 2456
wolfSSL 0:d92f9d21154c 2457 #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
wolfSSL 0:d92f9d21154c 2458
wolfSSL 0:d92f9d21154c 2459 /* check privkey generator helper, creates prime needed */
wolfSSL 0:d92f9d21154c 2460 static int ecc_check_privkey_gen_helper(ecc_key* key)
wolfSSL 0:d92f9d21154c 2461 {
wolfSSL 0:d92f9d21154c 2462 mp_int prime;
wolfSSL 0:d92f9d21154c 2463 int err;
wolfSSL 0:d92f9d21154c 2464
wolfSSL 0:d92f9d21154c 2465 if (key == NULL)
wolfSSL 0:d92f9d21154c 2466 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 2467
wolfSSL 0:d92f9d21154c 2468 err = mp_init(&prime);
wolfSSL 0:d92f9d21154c 2469 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 2470 return err;
wolfSSL 0:d92f9d21154c 2471
wolfSSL 0:d92f9d21154c 2472 err = mp_read_radix(&prime, (char*)key->dp->prime, 16);
wolfSSL 0:d92f9d21154c 2473
wolfSSL 0:d92f9d21154c 2474 if (err == MP_OKAY);
wolfSSL 0:d92f9d21154c 2475 err = ecc_check_privkey_gen(key, &prime);
wolfSSL 0:d92f9d21154c 2476
wolfSSL 0:d92f9d21154c 2477 mp_clear(&prime);
wolfSSL 0:d92f9d21154c 2478
wolfSSL 0:d92f9d21154c 2479 return err;
wolfSSL 0:d92f9d21154c 2480 }
wolfSSL 0:d92f9d21154c 2481
wolfSSL 0:d92f9d21154c 2482 #endif /* WOLFSSL_VALIDATE_ECC_IMPORT */
wolfSSL 0:d92f9d21154c 2483
wolfSSL 0:d92f9d21154c 2484
wolfSSL 0:d92f9d21154c 2485 /* validate order * pubkey = point at infinity, 0 on success */
wolfSSL 0:d92f9d21154c 2486 static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order)
wolfSSL 0:d92f9d21154c 2487 {
wolfSSL 0:d92f9d21154c 2488 ecc_point* inf = NULL;
wolfSSL 0:d92f9d21154c 2489 int err;
wolfSSL 0:d92f9d21154c 2490
wolfSSL 0:d92f9d21154c 2491 if (key == NULL)
wolfSSL 0:d92f9d21154c 2492 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 2493
wolfSSL 0:d92f9d21154c 2494 inf = ecc_new_point();
wolfSSL 0:d92f9d21154c 2495 if (inf == NULL)
wolfSSL 0:d92f9d21154c 2496 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 2497 else {
wolfSSL 0:d92f9d21154c 2498 err = ecc_mulmod(order, &key->pubkey, inf, prime, 1);
wolfSSL 0:d92f9d21154c 2499 if (err == MP_OKAY && !ecc_point_is_at_infinity(inf))
wolfSSL 0:d92f9d21154c 2500 err = ECC_INF_E;
wolfSSL 0:d92f9d21154c 2501 }
wolfSSL 0:d92f9d21154c 2502
wolfSSL 0:d92f9d21154c 2503 ecc_del_point(inf);
wolfSSL 0:d92f9d21154c 2504
wolfSSL 0:d92f9d21154c 2505 return err;
wolfSSL 0:d92f9d21154c 2506 }
wolfSSL 0:d92f9d21154c 2507
wolfSSL 0:d92f9d21154c 2508
wolfSSL 0:d92f9d21154c 2509 /* perform sanity checks on ec key validity, 0 on success */
wolfSSL 0:d92f9d21154c 2510 int wc_ecc_check_key(ecc_key* key)
wolfSSL 0:d92f9d21154c 2511 {
wolfSSL 0:d92f9d21154c 2512 mp_int prime; /* used by multiple calls so let's cache */
wolfSSL 0:d92f9d21154c 2513 mp_int order; /* other callers have, so let's gen here */
wolfSSL 0:d92f9d21154c 2514 int err;
wolfSSL 0:d92f9d21154c 2515
wolfSSL 0:d92f9d21154c 2516 if (key == NULL)
wolfSSL 0:d92f9d21154c 2517 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 2518
wolfSSL 0:d92f9d21154c 2519 /* pubkey point cannot be at inifinity */
wolfSSL 0:d92f9d21154c 2520 if (ecc_point_is_at_infinity(&key->pubkey))
wolfSSL 0:d92f9d21154c 2521 return ECC_INF_E;
wolfSSL 0:d92f9d21154c 2522
wolfSSL 0:d92f9d21154c 2523 err = mp_init_multi(&prime, &order, NULL, NULL, NULL, NULL);
wolfSSL 0:d92f9d21154c 2524 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 2525 return err;
wolfSSL 0:d92f9d21154c 2526
wolfSSL 0:d92f9d21154c 2527 err = mp_read_radix(&prime, (char*)key->dp->prime, 16);
wolfSSL 0:d92f9d21154c 2528
wolfSSL 0:d92f9d21154c 2529 /* make sure point is actually on curve */
wolfSSL 0:d92f9d21154c 2530 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2531 err = ecc_is_point(key->dp, &key->pubkey, &prime);
wolfSSL 0:d92f9d21154c 2532
wolfSSL 0:d92f9d21154c 2533 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2534 err = mp_read_radix(&order, (char*)key->dp->order, 16);
wolfSSL 0:d92f9d21154c 2535
wolfSSL 0:d92f9d21154c 2536 /* pubkey * order must be at infinity */
wolfSSL 0:d92f9d21154c 2537 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2538 err = ecc_check_pubkey_order(key, &prime, &order);
wolfSSL 0:d92f9d21154c 2539
wolfSSL 0:d92f9d21154c 2540 /* private * base generator must equal pubkey */
wolfSSL 0:d92f9d21154c 2541 if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
wolfSSL 0:d92f9d21154c 2542 err = ecc_check_privkey_gen(key, &prime);
wolfSSL 0:d92f9d21154c 2543
wolfSSL 0:d92f9d21154c 2544 mp_clear(&order);
wolfSSL 0:d92f9d21154c 2545 mp_clear(&prime);
wolfSSL 0:d92f9d21154c 2546
wolfSSL 0:d92f9d21154c 2547 return err;
wolfSSL 0:d92f9d21154c 2548 }
wolfSSL 0:d92f9d21154c 2549
wolfSSL 0:d92f9d21154c 2550
wolfSSL 0:d92f9d21154c 2551 /* import public ECC key in ANSI X9.63 format */
wolfSSL 0:d92f9d21154c 2552 int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
wolfSSL 0:d92f9d21154c 2553 {
wolfSSL 0:d92f9d21154c 2554 int x, err;
wolfSSL 0:d92f9d21154c 2555 int compressed = 0;
wolfSSL 0:d92f9d21154c 2556
wolfSSL 0:d92f9d21154c 2557 if (in == NULL || key == NULL)
wolfSSL 0:d92f9d21154c 2558 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2559
wolfSSL 0:d92f9d21154c 2560 /* must be odd */
wolfSSL 0:d92f9d21154c 2561 if ((inLen & 1) == 0) {
wolfSSL 0:d92f9d21154c 2562 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2563 }
wolfSSL 0:d92f9d21154c 2564
wolfSSL 0:d92f9d21154c 2565 /* init key */
wolfSSL 0:d92f9d21154c 2566 #ifdef ALT_ECC_SIZE
wolfSSL 0:d92f9d21154c 2567 key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
wolfSSL 0:d92f9d21154c 2568 key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
wolfSSL 0:d92f9d21154c 2569 key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
wolfSSL 0:d92f9d21154c 2570 alt_fp_init(key->pubkey.x);
wolfSSL 0:d92f9d21154c 2571 alt_fp_init(key->pubkey.y);
wolfSSL 0:d92f9d21154c 2572 alt_fp_init(key->pubkey.z);
wolfSSL 0:d92f9d21154c 2573 err = mp_init(&key->k);
wolfSSL 0:d92f9d21154c 2574 #else
wolfSSL 0:d92f9d21154c 2575 err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k,
wolfSSL 0:d92f9d21154c 2576 NULL, NULL);
wolfSSL 0:d92f9d21154c 2577 #endif
wolfSSL 0:d92f9d21154c 2578 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 2579 return MEMORY_E;
wolfSSL 0:d92f9d21154c 2580
wolfSSL 0:d92f9d21154c 2581 /* check for 4, 2, or 3 */
wolfSSL 0:d92f9d21154c 2582 if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
wolfSSL 0:d92f9d21154c 2583 err = ASN_PARSE_E;
wolfSSL 0:d92f9d21154c 2584 }
wolfSSL 0:d92f9d21154c 2585
wolfSSL 0:d92f9d21154c 2586 if (in[0] == 0x02 || in[0] == 0x03) {
wolfSSL 0:d92f9d21154c 2587 #ifdef HAVE_COMP_KEY
wolfSSL 0:d92f9d21154c 2588 compressed = 1;
wolfSSL 0:d92f9d21154c 2589 #else
wolfSSL 0:d92f9d21154c 2590 err = NOT_COMPILED_IN;
wolfSSL 0:d92f9d21154c 2591 #endif
wolfSSL 0:d92f9d21154c 2592 }
wolfSSL 0:d92f9d21154c 2593
wolfSSL 0:d92f9d21154c 2594 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2595 /* determine the idx */
wolfSSL 0:d92f9d21154c 2596
wolfSSL 0:d92f9d21154c 2597 if (compressed)
wolfSSL 0:d92f9d21154c 2598 inLen = (inLen-1)*2 + 1; /* used uncompressed len */
wolfSSL 0:d92f9d21154c 2599
wolfSSL 0:d92f9d21154c 2600 for (x = 0; ecc_sets[x].size != 0; x++) {
wolfSSL 0:d92f9d21154c 2601 if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) {
wolfSSL 0:d92f9d21154c 2602 break;
wolfSSL 0:d92f9d21154c 2603 }
wolfSSL 0:d92f9d21154c 2604 }
wolfSSL 0:d92f9d21154c 2605 if (ecc_sets[x].size == 0) {
wolfSSL 0:d92f9d21154c 2606 err = ASN_PARSE_E;
wolfSSL 0:d92f9d21154c 2607 } else {
wolfSSL 0:d92f9d21154c 2608 /* set the idx */
wolfSSL 0:d92f9d21154c 2609 key->idx = x;
wolfSSL 0:d92f9d21154c 2610 key->dp = &ecc_sets[x];
wolfSSL 0:d92f9d21154c 2611 key->type = ECC_PUBLICKEY;
wolfSSL 0:d92f9d21154c 2612 }
wolfSSL 0:d92f9d21154c 2613 }
wolfSSL 0:d92f9d21154c 2614
wolfSSL 0:d92f9d21154c 2615 /* read data */
wolfSSL 0:d92f9d21154c 2616 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2617 err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
wolfSSL 0:d92f9d21154c 2618
wolfSSL 0:d92f9d21154c 2619 #ifdef HAVE_COMP_KEY
wolfSSL 0:d92f9d21154c 2620 if (err == MP_OKAY && compressed == 1) { /* build y */
wolfSSL 0:d92f9d21154c 2621 mp_int t1, t2, prime, a, b;
wolfSSL 0:d92f9d21154c 2622
wolfSSL 0:d92f9d21154c 2623 if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY)
wolfSSL 0:d92f9d21154c 2624 err = MEMORY_E;
wolfSSL 0:d92f9d21154c 2625
wolfSSL 0:d92f9d21154c 2626 /* load prime */
wolfSSL 0:d92f9d21154c 2627 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2628 err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
wolfSSL 0:d92f9d21154c 2629
wolfSSL 0:d92f9d21154c 2630 /* load a */
wolfSSL 0:d92f9d21154c 2631 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2632 err = mp_read_radix(&a, (char *)key->dp->Af, 16);
wolfSSL 0:d92f9d21154c 2633
wolfSSL 0:d92f9d21154c 2634 /* load b */
wolfSSL 0:d92f9d21154c 2635 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2636 err = mp_read_radix(&b, (char *)key->dp->Bf, 16);
wolfSSL 0:d92f9d21154c 2637
wolfSSL 0:d92f9d21154c 2638 /* compute x^3 */
wolfSSL 0:d92f9d21154c 2639 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2640 err = mp_sqr(key->pubkey.x, &t1);
wolfSSL 0:d92f9d21154c 2641
wolfSSL 0:d92f9d21154c 2642 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2643 err = mp_mulmod(&t1, key->pubkey.x, &prime, &t1);
wolfSSL 0:d92f9d21154c 2644
wolfSSL 0:d92f9d21154c 2645 /* compute x^3 + a*x */
wolfSSL 0:d92f9d21154c 2646 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2647 err = mp_mulmod(&a, key->pubkey.x, &prime, &t2);
wolfSSL 0:d92f9d21154c 2648
wolfSSL 0:d92f9d21154c 2649 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2650 err = mp_add(&t1, &t2, &t1);
wolfSSL 0:d92f9d21154c 2651
wolfSSL 0:d92f9d21154c 2652 /* compute x^3 + a*x + b */
wolfSSL 0:d92f9d21154c 2653 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2654 err = mp_add(&t1, &b, &t1);
wolfSSL 0:d92f9d21154c 2655
wolfSSL 0:d92f9d21154c 2656 /* compute sqrt(x^3 + a*x + b) */
wolfSSL 0:d92f9d21154c 2657 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2658 err = mp_sqrtmod_prime(&t1, &prime, &t2);
wolfSSL 0:d92f9d21154c 2659
wolfSSL 0:d92f9d21154c 2660 /* adjust y */
wolfSSL 0:d92f9d21154c 2661 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2662 if ((mp_isodd(&t2) && in[0] == 0x03) ||
wolfSSL 0:d92f9d21154c 2663 (!mp_isodd(&t2) && in[0] == 0x02)) {
wolfSSL 0:d92f9d21154c 2664 err = mp_mod(&t2, &prime, key->pubkey.y);
wolfSSL 0:d92f9d21154c 2665 }
wolfSSL 0:d92f9d21154c 2666 else {
wolfSSL 0:d92f9d21154c 2667 err = mp_submod(&prime, &t2, &prime, key->pubkey.y);
wolfSSL 0:d92f9d21154c 2668 }
wolfSSL 0:d92f9d21154c 2669 }
wolfSSL 0:d92f9d21154c 2670
wolfSSL 0:d92f9d21154c 2671 mp_clear(&a);
wolfSSL 0:d92f9d21154c 2672 mp_clear(&b);
wolfSSL 0:d92f9d21154c 2673 mp_clear(&prime);
wolfSSL 0:d92f9d21154c 2674 mp_clear(&t2);
wolfSSL 0:d92f9d21154c 2675 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 2676 }
wolfSSL 0:d92f9d21154c 2677 #endif
wolfSSL 0:d92f9d21154c 2678
wolfSSL 0:d92f9d21154c 2679 if (err == MP_OKAY && compressed == 0)
wolfSSL 0:d92f9d21154c 2680 err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
wolfSSL 0:d92f9d21154c 2681 (inLen-1)>>1);
wolfSSL 0:d92f9d21154c 2682 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2683 mp_set(key->pubkey.z, 1);
wolfSSL 0:d92f9d21154c 2684
wolfSSL 0:d92f9d21154c 2685 #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
wolfSSL 0:d92f9d21154c 2686 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2687 err = wc_ecc_check_key(key);
wolfSSL 0:d92f9d21154c 2688 #endif
wolfSSL 0:d92f9d21154c 2689
wolfSSL 0:d92f9d21154c 2690 if (err != MP_OKAY) {
wolfSSL 0:d92f9d21154c 2691 mp_clear(key->pubkey.x);
wolfSSL 0:d92f9d21154c 2692 mp_clear(key->pubkey.y);
wolfSSL 0:d92f9d21154c 2693 mp_clear(key->pubkey.z);
wolfSSL 0:d92f9d21154c 2694 mp_clear(&key->k);
wolfSSL 0:d92f9d21154c 2695 }
wolfSSL 0:d92f9d21154c 2696
wolfSSL 0:d92f9d21154c 2697 return err;
wolfSSL 0:d92f9d21154c 2698 }
wolfSSL 0:d92f9d21154c 2699
wolfSSL 0:d92f9d21154c 2700
wolfSSL 0:d92f9d21154c 2701 /* export ecc private key only raw, outLen is in/out size
wolfSSL 0:d92f9d21154c 2702 return MP_OKAY on success */
wolfSSL 0:d92f9d21154c 2703 int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
wolfSSL 0:d92f9d21154c 2704 {
wolfSSL 0:d92f9d21154c 2705 word32 numlen;
wolfSSL 0:d92f9d21154c 2706
wolfSSL 0:d92f9d21154c 2707 if (key == NULL || out == NULL || outLen == NULL)
wolfSSL 0:d92f9d21154c 2708 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2709
wolfSSL 0:d92f9d21154c 2710 if (ecc_is_valid_idx(key->idx) == 0) {
wolfSSL 0:d92f9d21154c 2711 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2712 }
wolfSSL 0:d92f9d21154c 2713 numlen = key->dp->size;
wolfSSL 0:d92f9d21154c 2714
wolfSSL 0:d92f9d21154c 2715 if (*outLen < numlen) {
wolfSSL 0:d92f9d21154c 2716 *outLen = numlen;
wolfSSL 0:d92f9d21154c 2717 return BUFFER_E;
wolfSSL 0:d92f9d21154c 2718 }
wolfSSL 0:d92f9d21154c 2719 *outLen = numlen;
wolfSSL 0:d92f9d21154c 2720 XMEMSET(out, 0, *outLen);
wolfSSL 0:d92f9d21154c 2721 return mp_to_unsigned_bin(&key->k, out + (numlen -
wolfSSL 0:d92f9d21154c 2722 mp_unsigned_bin_size(&key->k)));
wolfSSL 0:d92f9d21154c 2723 }
wolfSSL 0:d92f9d21154c 2724
wolfSSL 0:d92f9d21154c 2725
wolfSSL 0:d92f9d21154c 2726 /* ecc private key import, public key in ANSI X9.63 format, private raw */
wolfSSL 0:d92f9d21154c 2727 int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
wolfSSL 0:d92f9d21154c 2728 word32 pubSz, ecc_key* key)
wolfSSL 0:d92f9d21154c 2729 {
wolfSSL 0:d92f9d21154c 2730 int ret = wc_ecc_import_x963(pub, pubSz, key);
wolfSSL 0:d92f9d21154c 2731 if (ret != 0)
wolfSSL 0:d92f9d21154c 2732 return ret;
wolfSSL 0:d92f9d21154c 2733
wolfSSL 0:d92f9d21154c 2734 key->type = ECC_PRIVATEKEY;
wolfSSL 0:d92f9d21154c 2735
wolfSSL 0:d92f9d21154c 2736 ret = mp_read_unsigned_bin(&key->k, priv, privSz);
wolfSSL 0:d92f9d21154c 2737
wolfSSL 0:d92f9d21154c 2738 #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
wolfSSL 0:d92f9d21154c 2739 if (ret == MP_OKAY)
wolfSSL 0:d92f9d21154c 2740 ret = ecc_check_privkey_gen_helper(key);
wolfSSL 0:d92f9d21154c 2741 #endif
wolfSSL 0:d92f9d21154c 2742
wolfSSL 0:d92f9d21154c 2743 return ret;
wolfSSL 0:d92f9d21154c 2744 }
wolfSSL 0:d92f9d21154c 2745
wolfSSL 0:d92f9d21154c 2746 /**
wolfSSL 0:d92f9d21154c 2747 Convert ECC R,S to signature
wolfSSL 0:d92f9d21154c 2748 r R component of signature
wolfSSL 0:d92f9d21154c 2749 s S component of signature
wolfSSL 0:d92f9d21154c 2750 out DER-encoded ECDSA signature
wolfSSL 0:d92f9d21154c 2751 outlen [in/out] output buffer size, output signature size
wolfSSL 0:d92f9d21154c 2752 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 2753 */
wolfSSL 0:d92f9d21154c 2754 int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
wolfSSL 0:d92f9d21154c 2755 {
wolfSSL 0:d92f9d21154c 2756 int err;
wolfSSL 0:d92f9d21154c 2757 mp_int rtmp;
wolfSSL 0:d92f9d21154c 2758 mp_int stmp;
wolfSSL 0:d92f9d21154c 2759
wolfSSL 0:d92f9d21154c 2760 if (r == NULL || s == NULL || out == NULL || outlen == NULL)
wolfSSL 0:d92f9d21154c 2761 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2762
wolfSSL 0:d92f9d21154c 2763 err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL);
wolfSSL 0:d92f9d21154c 2764 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 2765 return err;
wolfSSL 0:d92f9d21154c 2766
wolfSSL 0:d92f9d21154c 2767 err = mp_read_radix(&rtmp, r, 16);
wolfSSL 0:d92f9d21154c 2768 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2769 err = mp_read_radix(&stmp, s, 16);
wolfSSL 0:d92f9d21154c 2770
wolfSSL 0:d92f9d21154c 2771 /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
wolfSSL 0:d92f9d21154c 2772 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2773 err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp);
wolfSSL 0:d92f9d21154c 2774
wolfSSL 0:d92f9d21154c 2775 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2776 if (mp_iszero(&rtmp) || mp_iszero(&stmp))
wolfSSL 0:d92f9d21154c 2777 err = MP_ZERO_E;
wolfSSL 0:d92f9d21154c 2778 }
wolfSSL 0:d92f9d21154c 2779
wolfSSL 0:d92f9d21154c 2780 mp_clear(&rtmp);
wolfSSL 0:d92f9d21154c 2781 mp_clear(&stmp);
wolfSSL 0:d92f9d21154c 2782
wolfSSL 0:d92f9d21154c 2783 return err;
wolfSSL 0:d92f9d21154c 2784 }
wolfSSL 0:d92f9d21154c 2785
wolfSSL 0:d92f9d21154c 2786 /**
wolfSSL 0:d92f9d21154c 2787 Import raw ECC key
wolfSSL 0:d92f9d21154c 2788 key The destination ecc_key structure
wolfSSL 0:d92f9d21154c 2789 qx x component of base point, as ASCII hex string
wolfSSL 0:d92f9d21154c 2790 qy y component of base point, as ASCII hex string
wolfSSL 0:d92f9d21154c 2791 d private key, as ASCII hex string
wolfSSL 0:d92f9d21154c 2792 curveName ECC curve name, from ecc_sets[]
wolfSSL 0:d92f9d21154c 2793 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 2794 */
wolfSSL 0:d92f9d21154c 2795 int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
wolfSSL 0:d92f9d21154c 2796 const char* d, const char* curveName)
wolfSSL 0:d92f9d21154c 2797 {
wolfSSL 0:d92f9d21154c 2798 int err, x;
wolfSSL 0:d92f9d21154c 2799
wolfSSL 0:d92f9d21154c 2800 if (key == NULL || qx == NULL || qy == NULL || d == NULL ||
wolfSSL 0:d92f9d21154c 2801 curveName == NULL)
wolfSSL 0:d92f9d21154c 2802 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 2803
wolfSSL 0:d92f9d21154c 2804 /* init key */
wolfSSL 0:d92f9d21154c 2805 #ifdef ALT_ECC_SIZE
wolfSSL 0:d92f9d21154c 2806 key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
wolfSSL 0:d92f9d21154c 2807 key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
wolfSSL 0:d92f9d21154c 2808 key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
wolfSSL 0:d92f9d21154c 2809 alt_fp_init(key->pubkey.x);
wolfSSL 0:d92f9d21154c 2810 alt_fp_init(key->pubkey.y);
wolfSSL 0:d92f9d21154c 2811 alt_fp_init(key->pubkey.z);
wolfSSL 0:d92f9d21154c 2812 err = mp_init(&key->k);
wolfSSL 0:d92f9d21154c 2813 #else
wolfSSL 0:d92f9d21154c 2814 err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k,
wolfSSL 0:d92f9d21154c 2815 NULL, NULL);
wolfSSL 0:d92f9d21154c 2816 #endif
wolfSSL 0:d92f9d21154c 2817 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 2818 return MEMORY_E;
wolfSSL 0:d92f9d21154c 2819
wolfSSL 0:d92f9d21154c 2820 /* read Qx */
wolfSSL 0:d92f9d21154c 2821 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2822 err = mp_read_radix(key->pubkey.x, qx, 16);
wolfSSL 0:d92f9d21154c 2823
wolfSSL 0:d92f9d21154c 2824 /* read Qy */
wolfSSL 0:d92f9d21154c 2825 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2826 err = mp_read_radix(key->pubkey.y, qy, 16);
wolfSSL 0:d92f9d21154c 2827
wolfSSL 0:d92f9d21154c 2828 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2829 mp_set(key->pubkey.z, 1);
wolfSSL 0:d92f9d21154c 2830
wolfSSL 0:d92f9d21154c 2831 /* read and set the curve */
wolfSSL 0:d92f9d21154c 2832 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2833 for (x = 0; ecc_sets[x].size != 0; x++) {
wolfSSL 0:d92f9d21154c 2834 if (XSTRNCMP(ecc_sets[x].name, curveName,
wolfSSL 0:d92f9d21154c 2835 XSTRLEN(curveName)) == 0) {
wolfSSL 0:d92f9d21154c 2836 break;
wolfSSL 0:d92f9d21154c 2837 }
wolfSSL 0:d92f9d21154c 2838 }
wolfSSL 0:d92f9d21154c 2839 if (ecc_sets[x].size == 0) {
wolfSSL 0:d92f9d21154c 2840 err = ASN_PARSE_E;
wolfSSL 0:d92f9d21154c 2841 } else {
wolfSSL 0:d92f9d21154c 2842 /* set the curve */
wolfSSL 0:d92f9d21154c 2843 key->idx = x;
wolfSSL 0:d92f9d21154c 2844 key->dp = &ecc_sets[x];
wolfSSL 0:d92f9d21154c 2845 key->type = ECC_PUBLICKEY;
wolfSSL 0:d92f9d21154c 2846 }
wolfSSL 0:d92f9d21154c 2847 }
wolfSSL 0:d92f9d21154c 2848
wolfSSL 0:d92f9d21154c 2849 /* import private key */
wolfSSL 0:d92f9d21154c 2850 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 2851 key->type = ECC_PRIVATEKEY;
wolfSSL 0:d92f9d21154c 2852 err = mp_read_radix(&key->k, d, 16);
wolfSSL 0:d92f9d21154c 2853 }
wolfSSL 0:d92f9d21154c 2854
wolfSSL 0:d92f9d21154c 2855 #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
wolfSSL 0:d92f9d21154c 2856 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 2857 err = wc_ecc_check_key(key);
wolfSSL 0:d92f9d21154c 2858 #endif
wolfSSL 0:d92f9d21154c 2859
wolfSSL 0:d92f9d21154c 2860 if (err != MP_OKAY) {
wolfSSL 0:d92f9d21154c 2861 mp_clear(key->pubkey.x);
wolfSSL 0:d92f9d21154c 2862 mp_clear(key->pubkey.y);
wolfSSL 0:d92f9d21154c 2863 mp_clear(key->pubkey.z);
wolfSSL 0:d92f9d21154c 2864 mp_clear(&key->k);
wolfSSL 0:d92f9d21154c 2865 }
wolfSSL 0:d92f9d21154c 2866
wolfSSL 0:d92f9d21154c 2867 return err;
wolfSSL 0:d92f9d21154c 2868 }
wolfSSL 0:d92f9d21154c 2869
wolfSSL 0:d92f9d21154c 2870
wolfSSL 0:d92f9d21154c 2871 /* key size in octets */
wolfSSL 0:d92f9d21154c 2872 int wc_ecc_size(ecc_key* key)
wolfSSL 0:d92f9d21154c 2873 {
wolfSSL 0:d92f9d21154c 2874 if (key == NULL) return 0;
wolfSSL 0:d92f9d21154c 2875
wolfSSL 0:d92f9d21154c 2876 return key->dp->size;
wolfSSL 0:d92f9d21154c 2877 }
wolfSSL 0:d92f9d21154c 2878
wolfSSL 0:d92f9d21154c 2879
wolfSSL 0:d92f9d21154c 2880 /* worst case estimate, check actual return from wc_ecc_sign_hash for actual value
wolfSSL 0:d92f9d21154c 2881 of signature size in octets */
wolfSSL 0:d92f9d21154c 2882 int wc_ecc_sig_size(ecc_key* key)
wolfSSL 0:d92f9d21154c 2883 {
wolfSSL 0:d92f9d21154c 2884 int sz = wc_ecc_size(key);
wolfSSL 0:d92f9d21154c 2885 if (sz <= 0)
wolfSSL 0:d92f9d21154c 2886 return sz;
wolfSSL 0:d92f9d21154c 2887
wolfSSL 0:d92f9d21154c 2888 return sz * 2 + SIG_HEADER_SZ + 4; /* (4) worst case estimate */
wolfSSL 0:d92f9d21154c 2889 }
wolfSSL 0:d92f9d21154c 2890
wolfSSL 0:d92f9d21154c 2891
wolfSSL 0:d92f9d21154c 2892 #ifdef FP_ECC
wolfSSL 0:d92f9d21154c 2893
wolfSSL 0:d92f9d21154c 2894 /* fixed point ECC cache */
wolfSSL 0:d92f9d21154c 2895 /* number of entries in the cache */
wolfSSL 0:d92f9d21154c 2896 #ifndef FP_ENTRIES
wolfSSL 0:d92f9d21154c 2897 #define FP_ENTRIES 16
wolfSSL 0:d92f9d21154c 2898 #endif
wolfSSL 0:d92f9d21154c 2899
wolfSSL 0:d92f9d21154c 2900 /* number of bits in LUT */
wolfSSL 0:d92f9d21154c 2901 #ifndef FP_LUT
wolfSSL 0:d92f9d21154c 2902 #define FP_LUT 8U
wolfSSL 0:d92f9d21154c 2903 #endif
wolfSSL 0:d92f9d21154c 2904
wolfSSL 0:d92f9d21154c 2905 #ifdef ECC_SHAMIR
wolfSSL 0:d92f9d21154c 2906 /* Sharmir requires a bigger LUT, TAO */
wolfSSL 0:d92f9d21154c 2907 #if (FP_LUT > 12) || (FP_LUT < 4)
wolfSSL 0:d92f9d21154c 2908 #error FP_LUT must be between 4 and 12 inclusively
wolfSSL 0:d92f9d21154c 2909 #endif
wolfSSL 0:d92f9d21154c 2910 #else
wolfSSL 0:d92f9d21154c 2911 #if (FP_LUT > 12) || (FP_LUT < 2)
wolfSSL 0:d92f9d21154c 2912 #error FP_LUT must be between 2 and 12 inclusively
wolfSSL 0:d92f9d21154c 2913 #endif
wolfSSL 0:d92f9d21154c 2914 #endif
wolfSSL 0:d92f9d21154c 2915
wolfSSL 0:d92f9d21154c 2916
wolfSSL 0:d92f9d21154c 2917 /** Our FP cache */
wolfSSL 0:d92f9d21154c 2918 typedef struct {
wolfSSL 0:d92f9d21154c 2919 ecc_point* g; /* cached COPY of base point */
wolfSSL 0:d92f9d21154c 2920 ecc_point* LUT[1U<<FP_LUT]; /* fixed point lookup */
wolfSSL 0:d92f9d21154c 2921 mp_int mu; /* copy of the montgomery constant */
wolfSSL 0:d92f9d21154c 2922 int lru_count; /* amount of times this entry has been used */
wolfSSL 0:d92f9d21154c 2923 int lock; /* flag to indicate cache eviction */
wolfSSL 0:d92f9d21154c 2924 /* permitted (0) or not (1) */
wolfSSL 0:d92f9d21154c 2925 } fp_cache_t;
wolfSSL 0:d92f9d21154c 2926
wolfSSL 0:d92f9d21154c 2927 /* if HAVE_THREAD_LS this cache is per thread, no locking needed */
wolfSSL 0:d92f9d21154c 2928 static THREAD_LS_T fp_cache_t fp_cache[FP_ENTRIES];
wolfSSL 0:d92f9d21154c 2929
wolfSSL 0:d92f9d21154c 2930 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 2931 static volatile int initMutex = 0; /* prevent multiple mutex inits */
wolfSSL 0:d92f9d21154c 2932 static wolfSSL_Mutex ecc_fp_lock;
wolfSSL 0:d92f9d21154c 2933 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 2934
wolfSSL 0:d92f9d21154c 2935 /* simple table to help direct the generation of the LUT */
wolfSSL 0:d92f9d21154c 2936 static const struct {
wolfSSL 0:d92f9d21154c 2937 int ham, terma, termb;
wolfSSL 0:d92f9d21154c 2938 } lut_orders[] = {
wolfSSL 0:d92f9d21154c 2939 { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 }, { 2, 1, 2 }, { 1, 0, 0 }, { 2, 1, 4 }, { 2, 2, 4 }, { 3, 3, 4 },
wolfSSL 0:d92f9d21154c 2940 { 1, 0, 0 }, { 2, 1, 8 }, { 2, 2, 8 }, { 3, 3, 8 }, { 2, 4, 8 }, { 3, 5, 8 }, { 3, 6, 8 }, { 4, 7, 8 },
wolfSSL 0:d92f9d21154c 2941 { 1, 0, 0 }, { 2, 1, 16 }, { 2, 2, 16 }, { 3, 3, 16 }, { 2, 4, 16 }, { 3, 5, 16 }, { 3, 6, 16 }, { 4, 7, 16 },
wolfSSL 0:d92f9d21154c 2942 { 2, 8, 16 }, { 3, 9, 16 }, { 3, 10, 16 }, { 4, 11, 16 }, { 3, 12, 16 }, { 4, 13, 16 }, { 4, 14, 16 }, { 5, 15, 16 },
wolfSSL 0:d92f9d21154c 2943 { 1, 0, 0 }, { 2, 1, 32 }, { 2, 2, 32 }, { 3, 3, 32 }, { 2, 4, 32 }, { 3, 5, 32 }, { 3, 6, 32 }, { 4, 7, 32 },
wolfSSL 0:d92f9d21154c 2944 { 2, 8, 32 }, { 3, 9, 32 }, { 3, 10, 32 }, { 4, 11, 32 }, { 3, 12, 32 }, { 4, 13, 32 }, { 4, 14, 32 }, { 5, 15, 32 },
wolfSSL 0:d92f9d21154c 2945 { 2, 16, 32 }, { 3, 17, 32 }, { 3, 18, 32 }, { 4, 19, 32 }, { 3, 20, 32 }, { 4, 21, 32 }, { 4, 22, 32 }, { 5, 23, 32 },
wolfSSL 0:d92f9d21154c 2946 { 3, 24, 32 }, { 4, 25, 32 }, { 4, 26, 32 }, { 5, 27, 32 }, { 4, 28, 32 }, { 5, 29, 32 }, { 5, 30, 32 }, { 6, 31, 32 },
wolfSSL 0:d92f9d21154c 2947 #if FP_LUT > 6
wolfSSL 0:d92f9d21154c 2948 { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 },
wolfSSL 0:d92f9d21154c 2949 { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 },
wolfSSL 0:d92f9d21154c 2950 { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 },
wolfSSL 0:d92f9d21154c 2951 { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 },
wolfSSL 0:d92f9d21154c 2952 { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 },
wolfSSL 0:d92f9d21154c 2953 { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 },
wolfSSL 0:d92f9d21154c 2954 { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 },
wolfSSL 0:d92f9d21154c 2955 { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 },
wolfSSL 0:d92f9d21154c 2956 #if FP_LUT > 7
wolfSSL 0:d92f9d21154c 2957 { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 },
wolfSSL 0:d92f9d21154c 2958 { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 },
wolfSSL 0:d92f9d21154c 2959 { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 },
wolfSSL 0:d92f9d21154c 2960 { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 },
wolfSSL 0:d92f9d21154c 2961 { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 },
wolfSSL 0:d92f9d21154c 2962 { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 },
wolfSSL 0:d92f9d21154c 2963 { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 },
wolfSSL 0:d92f9d21154c 2964 { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 },
wolfSSL 0:d92f9d21154c 2965 { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 },
wolfSSL 0:d92f9d21154c 2966 { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 },
wolfSSL 0:d92f9d21154c 2967 { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 },
wolfSSL 0:d92f9d21154c 2968 { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 },
wolfSSL 0:d92f9d21154c 2969 { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 },
wolfSSL 0:d92f9d21154c 2970 { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 },
wolfSSL 0:d92f9d21154c 2971 { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 },
wolfSSL 0:d92f9d21154c 2972 { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 },
wolfSSL 0:d92f9d21154c 2973 #if FP_LUT > 8
wolfSSL 0:d92f9d21154c 2974 { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 },
wolfSSL 0:d92f9d21154c 2975 { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 },
wolfSSL 0:d92f9d21154c 2976 { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 },
wolfSSL 0:d92f9d21154c 2977 { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 },
wolfSSL 0:d92f9d21154c 2978 { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 },
wolfSSL 0:d92f9d21154c 2979 { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 },
wolfSSL 0:d92f9d21154c 2980 { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 },
wolfSSL 0:d92f9d21154c 2981 { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 },
wolfSSL 0:d92f9d21154c 2982 { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 },
wolfSSL 0:d92f9d21154c 2983 { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 },
wolfSSL 0:d92f9d21154c 2984 { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 },
wolfSSL 0:d92f9d21154c 2985 { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 },
wolfSSL 0:d92f9d21154c 2986 { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 },
wolfSSL 0:d92f9d21154c 2987 { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 },
wolfSSL 0:d92f9d21154c 2988 { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 },
wolfSSL 0:d92f9d21154c 2989 { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 },
wolfSSL 0:d92f9d21154c 2990 { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 },
wolfSSL 0:d92f9d21154c 2991 { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 },
wolfSSL 0:d92f9d21154c 2992 { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 },
wolfSSL 0:d92f9d21154c 2993 { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 },
wolfSSL 0:d92f9d21154c 2994 { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 },
wolfSSL 0:d92f9d21154c 2995 { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 },
wolfSSL 0:d92f9d21154c 2996 { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 },
wolfSSL 0:d92f9d21154c 2997 { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 },
wolfSSL 0:d92f9d21154c 2998 { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 },
wolfSSL 0:d92f9d21154c 2999 { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 },
wolfSSL 0:d92f9d21154c 3000 { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 },
wolfSSL 0:d92f9d21154c 3001 { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 },
wolfSSL 0:d92f9d21154c 3002 { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 },
wolfSSL 0:d92f9d21154c 3003 { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 },
wolfSSL 0:d92f9d21154c 3004 { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 },
wolfSSL 0:d92f9d21154c 3005 { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 },
wolfSSL 0:d92f9d21154c 3006 #if FP_LUT > 9
wolfSSL 0:d92f9d21154c 3007 { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 },
wolfSSL 0:d92f9d21154c 3008 { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 },
wolfSSL 0:d92f9d21154c 3009 { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 },
wolfSSL 0:d92f9d21154c 3010 { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 },
wolfSSL 0:d92f9d21154c 3011 { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 },
wolfSSL 0:d92f9d21154c 3012 { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 },
wolfSSL 0:d92f9d21154c 3013 { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 },
wolfSSL 0:d92f9d21154c 3014 { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 },
wolfSSL 0:d92f9d21154c 3015 { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 },
wolfSSL 0:d92f9d21154c 3016 { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 },
wolfSSL 0:d92f9d21154c 3017 { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 },
wolfSSL 0:d92f9d21154c 3018 { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 },
wolfSSL 0:d92f9d21154c 3019 { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 },
wolfSSL 0:d92f9d21154c 3020 { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 },
wolfSSL 0:d92f9d21154c 3021 { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 },
wolfSSL 0:d92f9d21154c 3022 { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 },
wolfSSL 0:d92f9d21154c 3023 { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 },
wolfSSL 0:d92f9d21154c 3024 { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 },
wolfSSL 0:d92f9d21154c 3025 { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 },
wolfSSL 0:d92f9d21154c 3026 { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 },
wolfSSL 0:d92f9d21154c 3027 { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 },
wolfSSL 0:d92f9d21154c 3028 { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 },
wolfSSL 0:d92f9d21154c 3029 { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 },
wolfSSL 0:d92f9d21154c 3030 { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 },
wolfSSL 0:d92f9d21154c 3031 { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 },
wolfSSL 0:d92f9d21154c 3032 { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 },
wolfSSL 0:d92f9d21154c 3033 { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 },
wolfSSL 0:d92f9d21154c 3034 { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 },
wolfSSL 0:d92f9d21154c 3035 { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 },
wolfSSL 0:d92f9d21154c 3036 { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 },
wolfSSL 0:d92f9d21154c 3037 { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 },
wolfSSL 0:d92f9d21154c 3038 { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 },
wolfSSL 0:d92f9d21154c 3039 { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 },
wolfSSL 0:d92f9d21154c 3040 { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 },
wolfSSL 0:d92f9d21154c 3041 { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 },
wolfSSL 0:d92f9d21154c 3042 { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 },
wolfSSL 0:d92f9d21154c 3043 { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 },
wolfSSL 0:d92f9d21154c 3044 { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 },
wolfSSL 0:d92f9d21154c 3045 { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 },
wolfSSL 0:d92f9d21154c 3046 { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 },
wolfSSL 0:d92f9d21154c 3047 { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 },
wolfSSL 0:d92f9d21154c 3048 { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 },
wolfSSL 0:d92f9d21154c 3049 { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 },
wolfSSL 0:d92f9d21154c 3050 { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 },
wolfSSL 0:d92f9d21154c 3051 { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 },
wolfSSL 0:d92f9d21154c 3052 { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 },
wolfSSL 0:d92f9d21154c 3053 { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 },
wolfSSL 0:d92f9d21154c 3054 { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 },
wolfSSL 0:d92f9d21154c 3055 { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 },
wolfSSL 0:d92f9d21154c 3056 { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 },
wolfSSL 0:d92f9d21154c 3057 { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 },
wolfSSL 0:d92f9d21154c 3058 { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 },
wolfSSL 0:d92f9d21154c 3059 { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 },
wolfSSL 0:d92f9d21154c 3060 { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 },
wolfSSL 0:d92f9d21154c 3061 { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 },
wolfSSL 0:d92f9d21154c 3062 { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 },
wolfSSL 0:d92f9d21154c 3063 { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 },
wolfSSL 0:d92f9d21154c 3064 { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 },
wolfSSL 0:d92f9d21154c 3065 { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 },
wolfSSL 0:d92f9d21154c 3066 { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 },
wolfSSL 0:d92f9d21154c 3067 { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 },
wolfSSL 0:d92f9d21154c 3068 { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 },
wolfSSL 0:d92f9d21154c 3069 { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 },
wolfSSL 0:d92f9d21154c 3070 { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 },
wolfSSL 0:d92f9d21154c 3071 #if FP_LUT > 10
wolfSSL 0:d92f9d21154c 3072 { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 },
wolfSSL 0:d92f9d21154c 3073 { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 },
wolfSSL 0:d92f9d21154c 3074 { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 },
wolfSSL 0:d92f9d21154c 3075 { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 },
wolfSSL 0:d92f9d21154c 3076 { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 },
wolfSSL 0:d92f9d21154c 3077 { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 },
wolfSSL 0:d92f9d21154c 3078 { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 },
wolfSSL 0:d92f9d21154c 3079 { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 },
wolfSSL 0:d92f9d21154c 3080 { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 },
wolfSSL 0:d92f9d21154c 3081 { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 },
wolfSSL 0:d92f9d21154c 3082 { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 },
wolfSSL 0:d92f9d21154c 3083 { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 },
wolfSSL 0:d92f9d21154c 3084 { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 },
wolfSSL 0:d92f9d21154c 3085 { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 },
wolfSSL 0:d92f9d21154c 3086 { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 },
wolfSSL 0:d92f9d21154c 3087 { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 },
wolfSSL 0:d92f9d21154c 3088 { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 },
wolfSSL 0:d92f9d21154c 3089 { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 },
wolfSSL 0:d92f9d21154c 3090 { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 },
wolfSSL 0:d92f9d21154c 3091 { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 },
wolfSSL 0:d92f9d21154c 3092 { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 },
wolfSSL 0:d92f9d21154c 3093 { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 },
wolfSSL 0:d92f9d21154c 3094 { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 },
wolfSSL 0:d92f9d21154c 3095 { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 },
wolfSSL 0:d92f9d21154c 3096 { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 },
wolfSSL 0:d92f9d21154c 3097 { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 },
wolfSSL 0:d92f9d21154c 3098 { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 },
wolfSSL 0:d92f9d21154c 3099 { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 },
wolfSSL 0:d92f9d21154c 3100 { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 },
wolfSSL 0:d92f9d21154c 3101 { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 },
wolfSSL 0:d92f9d21154c 3102 { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 },
wolfSSL 0:d92f9d21154c 3103 { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 },
wolfSSL 0:d92f9d21154c 3104 { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 },
wolfSSL 0:d92f9d21154c 3105 { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 },
wolfSSL 0:d92f9d21154c 3106 { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 },
wolfSSL 0:d92f9d21154c 3107 { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 },
wolfSSL 0:d92f9d21154c 3108 { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 },
wolfSSL 0:d92f9d21154c 3109 { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 },
wolfSSL 0:d92f9d21154c 3110 { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 },
wolfSSL 0:d92f9d21154c 3111 { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 },
wolfSSL 0:d92f9d21154c 3112 { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 },
wolfSSL 0:d92f9d21154c 3113 { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 },
wolfSSL 0:d92f9d21154c 3114 { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 },
wolfSSL 0:d92f9d21154c 3115 { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 },
wolfSSL 0:d92f9d21154c 3116 { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 },
wolfSSL 0:d92f9d21154c 3117 { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 },
wolfSSL 0:d92f9d21154c 3118 { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 },
wolfSSL 0:d92f9d21154c 3119 { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 },
wolfSSL 0:d92f9d21154c 3120 { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 },
wolfSSL 0:d92f9d21154c 3121 { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 },
wolfSSL 0:d92f9d21154c 3122 { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 },
wolfSSL 0:d92f9d21154c 3123 { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 },
wolfSSL 0:d92f9d21154c 3124 { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 },
wolfSSL 0:d92f9d21154c 3125 { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 },
wolfSSL 0:d92f9d21154c 3126 { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 },
wolfSSL 0:d92f9d21154c 3127 { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 },
wolfSSL 0:d92f9d21154c 3128 { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 },
wolfSSL 0:d92f9d21154c 3129 { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 },
wolfSSL 0:d92f9d21154c 3130 { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 },
wolfSSL 0:d92f9d21154c 3131 { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 },
wolfSSL 0:d92f9d21154c 3132 { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 },
wolfSSL 0:d92f9d21154c 3133 { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 },
wolfSSL 0:d92f9d21154c 3134 { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 },
wolfSSL 0:d92f9d21154c 3135 { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 },
wolfSSL 0:d92f9d21154c 3136 { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 },
wolfSSL 0:d92f9d21154c 3137 { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 },
wolfSSL 0:d92f9d21154c 3138 { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 },
wolfSSL 0:d92f9d21154c 3139 { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 },
wolfSSL 0:d92f9d21154c 3140 { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 },
wolfSSL 0:d92f9d21154c 3141 { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 },
wolfSSL 0:d92f9d21154c 3142 { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 },
wolfSSL 0:d92f9d21154c 3143 { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 },
wolfSSL 0:d92f9d21154c 3144 { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 },
wolfSSL 0:d92f9d21154c 3145 { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 },
wolfSSL 0:d92f9d21154c 3146 { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 },
wolfSSL 0:d92f9d21154c 3147 { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 },
wolfSSL 0:d92f9d21154c 3148 { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 },
wolfSSL 0:d92f9d21154c 3149 { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 },
wolfSSL 0:d92f9d21154c 3150 { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 },
wolfSSL 0:d92f9d21154c 3151 { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 },
wolfSSL 0:d92f9d21154c 3152 { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 },
wolfSSL 0:d92f9d21154c 3153 { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 },
wolfSSL 0:d92f9d21154c 3154 { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 },
wolfSSL 0:d92f9d21154c 3155 { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 },
wolfSSL 0:d92f9d21154c 3156 { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 },
wolfSSL 0:d92f9d21154c 3157 { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 },
wolfSSL 0:d92f9d21154c 3158 { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 },
wolfSSL 0:d92f9d21154c 3159 { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 },
wolfSSL 0:d92f9d21154c 3160 { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 },
wolfSSL 0:d92f9d21154c 3161 { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 },
wolfSSL 0:d92f9d21154c 3162 { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 },
wolfSSL 0:d92f9d21154c 3163 { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 },
wolfSSL 0:d92f9d21154c 3164 { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 },
wolfSSL 0:d92f9d21154c 3165 { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 },
wolfSSL 0:d92f9d21154c 3166 { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 },
wolfSSL 0:d92f9d21154c 3167 { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 },
wolfSSL 0:d92f9d21154c 3168 { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 },
wolfSSL 0:d92f9d21154c 3169 { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 },
wolfSSL 0:d92f9d21154c 3170 { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 },
wolfSSL 0:d92f9d21154c 3171 { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 },
wolfSSL 0:d92f9d21154c 3172 { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 },
wolfSSL 0:d92f9d21154c 3173 { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 },
wolfSSL 0:d92f9d21154c 3174 { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 },
wolfSSL 0:d92f9d21154c 3175 { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 },
wolfSSL 0:d92f9d21154c 3176 { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 },
wolfSSL 0:d92f9d21154c 3177 { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 },
wolfSSL 0:d92f9d21154c 3178 { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 },
wolfSSL 0:d92f9d21154c 3179 { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 },
wolfSSL 0:d92f9d21154c 3180 { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 },
wolfSSL 0:d92f9d21154c 3181 { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 },
wolfSSL 0:d92f9d21154c 3182 { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 },
wolfSSL 0:d92f9d21154c 3183 { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 },
wolfSSL 0:d92f9d21154c 3184 { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 },
wolfSSL 0:d92f9d21154c 3185 { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 },
wolfSSL 0:d92f9d21154c 3186 { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 },
wolfSSL 0:d92f9d21154c 3187 { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 },
wolfSSL 0:d92f9d21154c 3188 { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 },
wolfSSL 0:d92f9d21154c 3189 { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 },
wolfSSL 0:d92f9d21154c 3190 { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 },
wolfSSL 0:d92f9d21154c 3191 { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 },
wolfSSL 0:d92f9d21154c 3192 { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 },
wolfSSL 0:d92f9d21154c 3193 { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 },
wolfSSL 0:d92f9d21154c 3194 { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 },
wolfSSL 0:d92f9d21154c 3195 { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 },
wolfSSL 0:d92f9d21154c 3196 { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 },
wolfSSL 0:d92f9d21154c 3197 { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 },
wolfSSL 0:d92f9d21154c 3198 { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 },
wolfSSL 0:d92f9d21154c 3199 { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 },
wolfSSL 0:d92f9d21154c 3200 #if FP_LUT > 11
wolfSSL 0:d92f9d21154c 3201 { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 },
wolfSSL 0:d92f9d21154c 3202 { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 },
wolfSSL 0:d92f9d21154c 3203 { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 },
wolfSSL 0:d92f9d21154c 3204 { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 },
wolfSSL 0:d92f9d21154c 3205 { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 },
wolfSSL 0:d92f9d21154c 3206 { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 },
wolfSSL 0:d92f9d21154c 3207 { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 },
wolfSSL 0:d92f9d21154c 3208 { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 },
wolfSSL 0:d92f9d21154c 3209 { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 },
wolfSSL 0:d92f9d21154c 3210 { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 },
wolfSSL 0:d92f9d21154c 3211 { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 },
wolfSSL 0:d92f9d21154c 3212 { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 },
wolfSSL 0:d92f9d21154c 3213 { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 },
wolfSSL 0:d92f9d21154c 3214 { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 },
wolfSSL 0:d92f9d21154c 3215 { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 },
wolfSSL 0:d92f9d21154c 3216 { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 },
wolfSSL 0:d92f9d21154c 3217 { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 },
wolfSSL 0:d92f9d21154c 3218 { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 },
wolfSSL 0:d92f9d21154c 3219 { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 },
wolfSSL 0:d92f9d21154c 3220 { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 },
wolfSSL 0:d92f9d21154c 3221 { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 },
wolfSSL 0:d92f9d21154c 3222 { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 },
wolfSSL 0:d92f9d21154c 3223 { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 },
wolfSSL 0:d92f9d21154c 3224 { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 },
wolfSSL 0:d92f9d21154c 3225 { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 },
wolfSSL 0:d92f9d21154c 3226 { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 },
wolfSSL 0:d92f9d21154c 3227 { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 },
wolfSSL 0:d92f9d21154c 3228 { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 },
wolfSSL 0:d92f9d21154c 3229 { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 },
wolfSSL 0:d92f9d21154c 3230 { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 },
wolfSSL 0:d92f9d21154c 3231 { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 },
wolfSSL 0:d92f9d21154c 3232 { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 },
wolfSSL 0:d92f9d21154c 3233 { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 },
wolfSSL 0:d92f9d21154c 3234 { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 },
wolfSSL 0:d92f9d21154c 3235 { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 },
wolfSSL 0:d92f9d21154c 3236 { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 },
wolfSSL 0:d92f9d21154c 3237 { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 },
wolfSSL 0:d92f9d21154c 3238 { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 },
wolfSSL 0:d92f9d21154c 3239 { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 },
wolfSSL 0:d92f9d21154c 3240 { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 },
wolfSSL 0:d92f9d21154c 3241 { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 },
wolfSSL 0:d92f9d21154c 3242 { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 },
wolfSSL 0:d92f9d21154c 3243 { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 },
wolfSSL 0:d92f9d21154c 3244 { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 },
wolfSSL 0:d92f9d21154c 3245 { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 },
wolfSSL 0:d92f9d21154c 3246 { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 },
wolfSSL 0:d92f9d21154c 3247 { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 },
wolfSSL 0:d92f9d21154c 3248 { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 },
wolfSSL 0:d92f9d21154c 3249 { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 },
wolfSSL 0:d92f9d21154c 3250 { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 },
wolfSSL 0:d92f9d21154c 3251 { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 },
wolfSSL 0:d92f9d21154c 3252 { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 },
wolfSSL 0:d92f9d21154c 3253 { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 },
wolfSSL 0:d92f9d21154c 3254 { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 },
wolfSSL 0:d92f9d21154c 3255 { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 },
wolfSSL 0:d92f9d21154c 3256 { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 },
wolfSSL 0:d92f9d21154c 3257 { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 },
wolfSSL 0:d92f9d21154c 3258 { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 },
wolfSSL 0:d92f9d21154c 3259 { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 },
wolfSSL 0:d92f9d21154c 3260 { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 },
wolfSSL 0:d92f9d21154c 3261 { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 },
wolfSSL 0:d92f9d21154c 3262 { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 },
wolfSSL 0:d92f9d21154c 3263 { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 },
wolfSSL 0:d92f9d21154c 3264 { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 },
wolfSSL 0:d92f9d21154c 3265 { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 },
wolfSSL 0:d92f9d21154c 3266 { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 },
wolfSSL 0:d92f9d21154c 3267 { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 },
wolfSSL 0:d92f9d21154c 3268 { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 },
wolfSSL 0:d92f9d21154c 3269 { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 },
wolfSSL 0:d92f9d21154c 3270 { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 },
wolfSSL 0:d92f9d21154c 3271 { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 },
wolfSSL 0:d92f9d21154c 3272 { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 },
wolfSSL 0:d92f9d21154c 3273 { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 },
wolfSSL 0:d92f9d21154c 3274 { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 },
wolfSSL 0:d92f9d21154c 3275 { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 },
wolfSSL 0:d92f9d21154c 3276 { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 },
wolfSSL 0:d92f9d21154c 3277 { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 },
wolfSSL 0:d92f9d21154c 3278 { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 },
wolfSSL 0:d92f9d21154c 3279 { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 },
wolfSSL 0:d92f9d21154c 3280 { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 },
wolfSSL 0:d92f9d21154c 3281 { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 },
wolfSSL 0:d92f9d21154c 3282 { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 },
wolfSSL 0:d92f9d21154c 3283 { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 },
wolfSSL 0:d92f9d21154c 3284 { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 },
wolfSSL 0:d92f9d21154c 3285 { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 },
wolfSSL 0:d92f9d21154c 3286 { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 },
wolfSSL 0:d92f9d21154c 3287 { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 },
wolfSSL 0:d92f9d21154c 3288 { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 },
wolfSSL 0:d92f9d21154c 3289 { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 },
wolfSSL 0:d92f9d21154c 3290 { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 },
wolfSSL 0:d92f9d21154c 3291 { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 },
wolfSSL 0:d92f9d21154c 3292 { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 },
wolfSSL 0:d92f9d21154c 3293 { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 },
wolfSSL 0:d92f9d21154c 3294 { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 },
wolfSSL 0:d92f9d21154c 3295 { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 },
wolfSSL 0:d92f9d21154c 3296 { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 },
wolfSSL 0:d92f9d21154c 3297 { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 },
wolfSSL 0:d92f9d21154c 3298 { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 },
wolfSSL 0:d92f9d21154c 3299 { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 },
wolfSSL 0:d92f9d21154c 3300 { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 },
wolfSSL 0:d92f9d21154c 3301 { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 },
wolfSSL 0:d92f9d21154c 3302 { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 },
wolfSSL 0:d92f9d21154c 3303 { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 },
wolfSSL 0:d92f9d21154c 3304 { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 },
wolfSSL 0:d92f9d21154c 3305 { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 },
wolfSSL 0:d92f9d21154c 3306 { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 },
wolfSSL 0:d92f9d21154c 3307 { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 },
wolfSSL 0:d92f9d21154c 3308 { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 },
wolfSSL 0:d92f9d21154c 3309 { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 },
wolfSSL 0:d92f9d21154c 3310 { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 },
wolfSSL 0:d92f9d21154c 3311 { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 },
wolfSSL 0:d92f9d21154c 3312 { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 },
wolfSSL 0:d92f9d21154c 3313 { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 },
wolfSSL 0:d92f9d21154c 3314 { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 },
wolfSSL 0:d92f9d21154c 3315 { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 },
wolfSSL 0:d92f9d21154c 3316 { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 },
wolfSSL 0:d92f9d21154c 3317 { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 },
wolfSSL 0:d92f9d21154c 3318 { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 },
wolfSSL 0:d92f9d21154c 3319 { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 },
wolfSSL 0:d92f9d21154c 3320 { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 },
wolfSSL 0:d92f9d21154c 3321 { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 },
wolfSSL 0:d92f9d21154c 3322 { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 },
wolfSSL 0:d92f9d21154c 3323 { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 },
wolfSSL 0:d92f9d21154c 3324 { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 },
wolfSSL 0:d92f9d21154c 3325 { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 },
wolfSSL 0:d92f9d21154c 3326 { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 },
wolfSSL 0:d92f9d21154c 3327 { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 },
wolfSSL 0:d92f9d21154c 3328 { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 },
wolfSSL 0:d92f9d21154c 3329 { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 },
wolfSSL 0:d92f9d21154c 3330 { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 },
wolfSSL 0:d92f9d21154c 3331 { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 },
wolfSSL 0:d92f9d21154c 3332 { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 },
wolfSSL 0:d92f9d21154c 3333 { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 },
wolfSSL 0:d92f9d21154c 3334 { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 },
wolfSSL 0:d92f9d21154c 3335 { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 },
wolfSSL 0:d92f9d21154c 3336 { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 },
wolfSSL 0:d92f9d21154c 3337 { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 },
wolfSSL 0:d92f9d21154c 3338 { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 },
wolfSSL 0:d92f9d21154c 3339 { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 },
wolfSSL 0:d92f9d21154c 3340 { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 },
wolfSSL 0:d92f9d21154c 3341 { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 },
wolfSSL 0:d92f9d21154c 3342 { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 },
wolfSSL 0:d92f9d21154c 3343 { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 },
wolfSSL 0:d92f9d21154c 3344 { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 },
wolfSSL 0:d92f9d21154c 3345 { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 },
wolfSSL 0:d92f9d21154c 3346 { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 },
wolfSSL 0:d92f9d21154c 3347 { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 },
wolfSSL 0:d92f9d21154c 3348 { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 },
wolfSSL 0:d92f9d21154c 3349 { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 },
wolfSSL 0:d92f9d21154c 3350 { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 },
wolfSSL 0:d92f9d21154c 3351 { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 },
wolfSSL 0:d92f9d21154c 3352 { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 },
wolfSSL 0:d92f9d21154c 3353 { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 },
wolfSSL 0:d92f9d21154c 3354 { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 },
wolfSSL 0:d92f9d21154c 3355 { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 },
wolfSSL 0:d92f9d21154c 3356 { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 },
wolfSSL 0:d92f9d21154c 3357 { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 },
wolfSSL 0:d92f9d21154c 3358 { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 },
wolfSSL 0:d92f9d21154c 3359 { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 },
wolfSSL 0:d92f9d21154c 3360 { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 },
wolfSSL 0:d92f9d21154c 3361 { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 },
wolfSSL 0:d92f9d21154c 3362 { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 },
wolfSSL 0:d92f9d21154c 3363 { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 },
wolfSSL 0:d92f9d21154c 3364 { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 },
wolfSSL 0:d92f9d21154c 3365 { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 },
wolfSSL 0:d92f9d21154c 3366 { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 },
wolfSSL 0:d92f9d21154c 3367 { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 },
wolfSSL 0:d92f9d21154c 3368 { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 },
wolfSSL 0:d92f9d21154c 3369 { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 },
wolfSSL 0:d92f9d21154c 3370 { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 },
wolfSSL 0:d92f9d21154c 3371 { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 },
wolfSSL 0:d92f9d21154c 3372 { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 },
wolfSSL 0:d92f9d21154c 3373 { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 },
wolfSSL 0:d92f9d21154c 3374 { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 },
wolfSSL 0:d92f9d21154c 3375 { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 },
wolfSSL 0:d92f9d21154c 3376 { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 },
wolfSSL 0:d92f9d21154c 3377 { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 },
wolfSSL 0:d92f9d21154c 3378 { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 },
wolfSSL 0:d92f9d21154c 3379 { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 },
wolfSSL 0:d92f9d21154c 3380 { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 },
wolfSSL 0:d92f9d21154c 3381 { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 },
wolfSSL 0:d92f9d21154c 3382 { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 },
wolfSSL 0:d92f9d21154c 3383 { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 },
wolfSSL 0:d92f9d21154c 3384 { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 },
wolfSSL 0:d92f9d21154c 3385 { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 },
wolfSSL 0:d92f9d21154c 3386 { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 },
wolfSSL 0:d92f9d21154c 3387 { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 },
wolfSSL 0:d92f9d21154c 3388 { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 },
wolfSSL 0:d92f9d21154c 3389 { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 },
wolfSSL 0:d92f9d21154c 3390 { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 },
wolfSSL 0:d92f9d21154c 3391 { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 },
wolfSSL 0:d92f9d21154c 3392 { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 },
wolfSSL 0:d92f9d21154c 3393 { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 },
wolfSSL 0:d92f9d21154c 3394 { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 },
wolfSSL 0:d92f9d21154c 3395 { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 },
wolfSSL 0:d92f9d21154c 3396 { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 },
wolfSSL 0:d92f9d21154c 3397 { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 },
wolfSSL 0:d92f9d21154c 3398 { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 },
wolfSSL 0:d92f9d21154c 3399 { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 },
wolfSSL 0:d92f9d21154c 3400 { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 },
wolfSSL 0:d92f9d21154c 3401 { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 },
wolfSSL 0:d92f9d21154c 3402 { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 },
wolfSSL 0:d92f9d21154c 3403 { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 },
wolfSSL 0:d92f9d21154c 3404 { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 },
wolfSSL 0:d92f9d21154c 3405 { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 },
wolfSSL 0:d92f9d21154c 3406 { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 },
wolfSSL 0:d92f9d21154c 3407 { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 },
wolfSSL 0:d92f9d21154c 3408 { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 },
wolfSSL 0:d92f9d21154c 3409 { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 },
wolfSSL 0:d92f9d21154c 3410 { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 },
wolfSSL 0:d92f9d21154c 3411 { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 },
wolfSSL 0:d92f9d21154c 3412 { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 },
wolfSSL 0:d92f9d21154c 3413 { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 },
wolfSSL 0:d92f9d21154c 3414 { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 },
wolfSSL 0:d92f9d21154c 3415 { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 },
wolfSSL 0:d92f9d21154c 3416 { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 },
wolfSSL 0:d92f9d21154c 3417 { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 },
wolfSSL 0:d92f9d21154c 3418 { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 },
wolfSSL 0:d92f9d21154c 3419 { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 },
wolfSSL 0:d92f9d21154c 3420 { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 },
wolfSSL 0:d92f9d21154c 3421 { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 },
wolfSSL 0:d92f9d21154c 3422 { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 },
wolfSSL 0:d92f9d21154c 3423 { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 },
wolfSSL 0:d92f9d21154c 3424 { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 },
wolfSSL 0:d92f9d21154c 3425 { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 },
wolfSSL 0:d92f9d21154c 3426 { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 },
wolfSSL 0:d92f9d21154c 3427 { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 },
wolfSSL 0:d92f9d21154c 3428 { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 },
wolfSSL 0:d92f9d21154c 3429 { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 },
wolfSSL 0:d92f9d21154c 3430 { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 },
wolfSSL 0:d92f9d21154c 3431 { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 },
wolfSSL 0:d92f9d21154c 3432 { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 },
wolfSSL 0:d92f9d21154c 3433 { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 },
wolfSSL 0:d92f9d21154c 3434 { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 },
wolfSSL 0:d92f9d21154c 3435 { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 },
wolfSSL 0:d92f9d21154c 3436 { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 },
wolfSSL 0:d92f9d21154c 3437 { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 },
wolfSSL 0:d92f9d21154c 3438 { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 },
wolfSSL 0:d92f9d21154c 3439 { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 },
wolfSSL 0:d92f9d21154c 3440 { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 },
wolfSSL 0:d92f9d21154c 3441 { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 },
wolfSSL 0:d92f9d21154c 3442 { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 },
wolfSSL 0:d92f9d21154c 3443 { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 },
wolfSSL 0:d92f9d21154c 3444 { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 },
wolfSSL 0:d92f9d21154c 3445 { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 },
wolfSSL 0:d92f9d21154c 3446 { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 },
wolfSSL 0:d92f9d21154c 3447 { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 },
wolfSSL 0:d92f9d21154c 3448 { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 },
wolfSSL 0:d92f9d21154c 3449 { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 },
wolfSSL 0:d92f9d21154c 3450 { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 },
wolfSSL 0:d92f9d21154c 3451 { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 },
wolfSSL 0:d92f9d21154c 3452 { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 },
wolfSSL 0:d92f9d21154c 3453 { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 },
wolfSSL 0:d92f9d21154c 3454 { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 },
wolfSSL 0:d92f9d21154c 3455 { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 },
wolfSSL 0:d92f9d21154c 3456 { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 },
wolfSSL 0:d92f9d21154c 3457 #endif
wolfSSL 0:d92f9d21154c 3458 #endif
wolfSSL 0:d92f9d21154c 3459 #endif
wolfSSL 0:d92f9d21154c 3460 #endif
wolfSSL 0:d92f9d21154c 3461 #endif
wolfSSL 0:d92f9d21154c 3462 #endif
wolfSSL 0:d92f9d21154c 3463 };
wolfSSL 0:d92f9d21154c 3464
wolfSSL 0:d92f9d21154c 3465 /* find a hole and free as required, return -1 if no hole found */
wolfSSL 0:d92f9d21154c 3466 static int find_hole(void)
wolfSSL 0:d92f9d21154c 3467 {
wolfSSL 0:d92f9d21154c 3468 unsigned x;
wolfSSL 0:d92f9d21154c 3469 int y, z;
wolfSSL 0:d92f9d21154c 3470 for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) {
wolfSSL 0:d92f9d21154c 3471 if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) {
wolfSSL 0:d92f9d21154c 3472 z = x;
wolfSSL 0:d92f9d21154c 3473 y = fp_cache[x].lru_count;
wolfSSL 0:d92f9d21154c 3474 }
wolfSSL 0:d92f9d21154c 3475 }
wolfSSL 0:d92f9d21154c 3476
wolfSSL 0:d92f9d21154c 3477 /* decrease all */
wolfSSL 0:d92f9d21154c 3478 for (x = 0; x < FP_ENTRIES; x++) {
wolfSSL 0:d92f9d21154c 3479 if (fp_cache[x].lru_count > 3) {
wolfSSL 0:d92f9d21154c 3480 --(fp_cache[x].lru_count);
wolfSSL 0:d92f9d21154c 3481 }
wolfSSL 0:d92f9d21154c 3482 }
wolfSSL 0:d92f9d21154c 3483
wolfSSL 0:d92f9d21154c 3484 /* free entry z */
wolfSSL 0:d92f9d21154c 3485 if (z >= 0 && fp_cache[z].g) {
wolfSSL 0:d92f9d21154c 3486 mp_clear(&fp_cache[z].mu);
wolfSSL 0:d92f9d21154c 3487 ecc_del_point(fp_cache[z].g);
wolfSSL 0:d92f9d21154c 3488 fp_cache[z].g = NULL;
wolfSSL 0:d92f9d21154c 3489 for (x = 0; x < (1U<<FP_LUT); x++) {
wolfSSL 0:d92f9d21154c 3490 ecc_del_point(fp_cache[z].LUT[x]);
wolfSSL 0:d92f9d21154c 3491 fp_cache[z].LUT[x] = NULL;
wolfSSL 0:d92f9d21154c 3492 }
wolfSSL 0:d92f9d21154c 3493 fp_cache[z].lru_count = 0;
wolfSSL 0:d92f9d21154c 3494 }
wolfSSL 0:d92f9d21154c 3495 return z;
wolfSSL 0:d92f9d21154c 3496 }
wolfSSL 0:d92f9d21154c 3497
wolfSSL 0:d92f9d21154c 3498 /* determine if a base is already in the cache and if so, where */
wolfSSL 0:d92f9d21154c 3499 static int find_base(ecc_point* g)
wolfSSL 0:d92f9d21154c 3500 {
wolfSSL 0:d92f9d21154c 3501 int x;
wolfSSL 0:d92f9d21154c 3502 for (x = 0; x < FP_ENTRIES; x++) {
wolfSSL 0:d92f9d21154c 3503 if (fp_cache[x].g != NULL &&
wolfSSL 0:d92f9d21154c 3504 mp_cmp(fp_cache[x].g->x, g->x) == MP_EQ &&
wolfSSL 0:d92f9d21154c 3505 mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ &&
wolfSSL 0:d92f9d21154c 3506 mp_cmp(fp_cache[x].g->z, g->z) == MP_EQ) {
wolfSSL 0:d92f9d21154c 3507 break;
wolfSSL 0:d92f9d21154c 3508 }
wolfSSL 0:d92f9d21154c 3509 }
wolfSSL 0:d92f9d21154c 3510 if (x == FP_ENTRIES) {
wolfSSL 0:d92f9d21154c 3511 x = -1;
wolfSSL 0:d92f9d21154c 3512 }
wolfSSL 0:d92f9d21154c 3513 return x;
wolfSSL 0:d92f9d21154c 3514 }
wolfSSL 0:d92f9d21154c 3515
wolfSSL 0:d92f9d21154c 3516 /* add a new base to the cache */
wolfSSL 0:d92f9d21154c 3517 static int add_entry(int idx, ecc_point *g)
wolfSSL 0:d92f9d21154c 3518 {
wolfSSL 0:d92f9d21154c 3519 unsigned x, y;
wolfSSL 0:d92f9d21154c 3520
wolfSSL 0:d92f9d21154c 3521 /* allocate base and LUT */
wolfSSL 0:d92f9d21154c 3522 fp_cache[idx].g = ecc_new_point();
wolfSSL 0:d92f9d21154c 3523 if (fp_cache[idx].g == NULL) {
wolfSSL 0:d92f9d21154c 3524 return GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 3525 }
wolfSSL 0:d92f9d21154c 3526
wolfSSL 0:d92f9d21154c 3527 /* copy x and y */
wolfSSL 0:d92f9d21154c 3528 if ((mp_copy(g->x, fp_cache[idx].g->x) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3529 (mp_copy(g->y, fp_cache[idx].g->y) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3530 (mp_copy(g->z, fp_cache[idx].g->z) != MP_OKAY)) {
wolfSSL 0:d92f9d21154c 3531 ecc_del_point(fp_cache[idx].g);
wolfSSL 0:d92f9d21154c 3532 fp_cache[idx].g = NULL;
wolfSSL 0:d92f9d21154c 3533 return GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 3534 }
wolfSSL 0:d92f9d21154c 3535
wolfSSL 0:d92f9d21154c 3536 for (x = 0; x < (1U<<FP_LUT); x++) {
wolfSSL 0:d92f9d21154c 3537 fp_cache[idx].LUT[x] = ecc_new_point();
wolfSSL 0:d92f9d21154c 3538 if (fp_cache[idx].LUT[x] == NULL) {
wolfSSL 0:d92f9d21154c 3539 for (y = 0; y < x; y++) {
wolfSSL 0:d92f9d21154c 3540 ecc_del_point(fp_cache[idx].LUT[y]);
wolfSSL 0:d92f9d21154c 3541 fp_cache[idx].LUT[y] = NULL;
wolfSSL 0:d92f9d21154c 3542 }
wolfSSL 0:d92f9d21154c 3543 ecc_del_point(fp_cache[idx].g);
wolfSSL 0:d92f9d21154c 3544 fp_cache[idx].g = NULL;
wolfSSL 0:d92f9d21154c 3545 fp_cache[idx].lru_count = 0;
wolfSSL 0:d92f9d21154c 3546 return GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 3547 }
wolfSSL 0:d92f9d21154c 3548 }
wolfSSL 0:d92f9d21154c 3549
wolfSSL 0:d92f9d21154c 3550 fp_cache[idx].lru_count = 0;
wolfSSL 0:d92f9d21154c 3551
wolfSSL 0:d92f9d21154c 3552 return MP_OKAY;
wolfSSL 0:d92f9d21154c 3553 }
wolfSSL 0:d92f9d21154c 3554
wolfSSL 0:d92f9d21154c 3555 /* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart
wolfSSL 0:d92f9d21154c 3556 *
wolfSSL 0:d92f9d21154c 3557 * The algorithm builds patterns in increasing bit order by first making all
wolfSSL 0:d92f9d21154c 3558 * single bit input patterns, then all two bit input patterns and so on
wolfSSL 0:d92f9d21154c 3559 */
wolfSSL 0:d92f9d21154c 3560 static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu)
wolfSSL 0:d92f9d21154c 3561 {
wolfSSL 0:d92f9d21154c 3562 unsigned x, y, err, bitlen, lut_gap;
wolfSSL 0:d92f9d21154c 3563 mp_int tmp;
wolfSSL 0:d92f9d21154c 3564
wolfSSL 0:d92f9d21154c 3565 if (mp_init(&tmp) != MP_OKAY)
wolfSSL 0:d92f9d21154c 3566 return GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 3567
wolfSSL 0:d92f9d21154c 3568 /* sanity check to make sure lut_order table is of correct size,
wolfSSL 0:d92f9d21154c 3569 should compile out to a NOP if true */
wolfSSL 0:d92f9d21154c 3570 if ((sizeof(lut_orders) / sizeof(lut_orders[0])) < (1U<<FP_LUT)) {
wolfSSL 0:d92f9d21154c 3571 err = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 3572 }
wolfSSL 0:d92f9d21154c 3573 else {
wolfSSL 0:d92f9d21154c 3574 /* get bitlen and round up to next multiple of FP_LUT */
wolfSSL 0:d92f9d21154c 3575 bitlen = mp_unsigned_bin_size(modulus) << 3;
wolfSSL 0:d92f9d21154c 3576 x = bitlen % FP_LUT;
wolfSSL 0:d92f9d21154c 3577 if (x) {
wolfSSL 0:d92f9d21154c 3578 bitlen += FP_LUT - x;
wolfSSL 0:d92f9d21154c 3579 }
wolfSSL 0:d92f9d21154c 3580 lut_gap = bitlen / FP_LUT;
wolfSSL 0:d92f9d21154c 3581
wolfSSL 0:d92f9d21154c 3582 /* init the mu */
wolfSSL 0:d92f9d21154c 3583 err = mp_init_copy(&fp_cache[idx].mu, mu);
wolfSSL 0:d92f9d21154c 3584 }
wolfSSL 0:d92f9d21154c 3585
wolfSSL 0:d92f9d21154c 3586 /* copy base */
wolfSSL 0:d92f9d21154c 3587 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 3588 if ((mp_mulmod(fp_cache[idx].g->x, mu, modulus,
wolfSSL 0:d92f9d21154c 3589 fp_cache[idx].LUT[1]->x) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3590 (mp_mulmod(fp_cache[idx].g->y, mu, modulus,
wolfSSL 0:d92f9d21154c 3591 fp_cache[idx].LUT[1]->y) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3592 (mp_mulmod(fp_cache[idx].g->z, mu, modulus,
wolfSSL 0:d92f9d21154c 3593 fp_cache[idx].LUT[1]->z) != MP_OKAY)) {
wolfSSL 0:d92f9d21154c 3594 err = MP_MULMOD_E;
wolfSSL 0:d92f9d21154c 3595 }
wolfSSL 0:d92f9d21154c 3596 }
wolfSSL 0:d92f9d21154c 3597
wolfSSL 0:d92f9d21154c 3598 /* make all single bit entries */
wolfSSL 0:d92f9d21154c 3599 for (x = 1; x < FP_LUT; x++) {
wolfSSL 0:d92f9d21154c 3600 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 3601 break;
wolfSSL 0:d92f9d21154c 3602 if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x,
wolfSSL 0:d92f9d21154c 3603 fp_cache[idx].LUT[1<<x]->x) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3604 (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y,
wolfSSL 0:d92f9d21154c 3605 fp_cache[idx].LUT[1<<x]->y) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3606 (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z,
wolfSSL 0:d92f9d21154c 3607 fp_cache[idx].LUT[1<<x]->z) != MP_OKAY)){
wolfSSL 0:d92f9d21154c 3608 err = MP_INIT_E;
wolfSSL 0:d92f9d21154c 3609 break;
wolfSSL 0:d92f9d21154c 3610 } else {
wolfSSL 0:d92f9d21154c 3611
wolfSSL 0:d92f9d21154c 3612 /* now double it bitlen/FP_LUT times */
wolfSSL 0:d92f9d21154c 3613 for (y = 0; y < lut_gap; y++) {
wolfSSL 0:d92f9d21154c 3614 if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<<x],
wolfSSL 0:d92f9d21154c 3615 fp_cache[idx].LUT[1<<x], modulus, mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3616 break;
wolfSSL 0:d92f9d21154c 3617 }
wolfSSL 0:d92f9d21154c 3618 }
wolfSSL 0:d92f9d21154c 3619 }
wolfSSL 0:d92f9d21154c 3620 }
wolfSSL 0:d92f9d21154c 3621
wolfSSL 0:d92f9d21154c 3622 /* now make all entries in increase order of hamming weight */
wolfSSL 0:d92f9d21154c 3623 for (x = 2; x <= FP_LUT; x++) {
wolfSSL 0:d92f9d21154c 3624 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 3625 break;
wolfSSL 0:d92f9d21154c 3626 for (y = 0; y < (1UL<<FP_LUT); y++) {
wolfSSL 0:d92f9d21154c 3627 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 3628 break;
wolfSSL 0:d92f9d21154c 3629 if (lut_orders[y].ham != (int)x) continue;
wolfSSL 0:d92f9d21154c 3630
wolfSSL 0:d92f9d21154c 3631 /* perform the add */
wolfSSL 0:d92f9d21154c 3632 if ((err = ecc_projective_add_point(
wolfSSL 0:d92f9d21154c 3633 fp_cache[idx].LUT[lut_orders[y].terma],
wolfSSL 0:d92f9d21154c 3634 fp_cache[idx].LUT[lut_orders[y].termb],
wolfSSL 0:d92f9d21154c 3635 fp_cache[idx].LUT[y], modulus, mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3636 break;
wolfSSL 0:d92f9d21154c 3637 }
wolfSSL 0:d92f9d21154c 3638 }
wolfSSL 0:d92f9d21154c 3639 }
wolfSSL 0:d92f9d21154c 3640
wolfSSL 0:d92f9d21154c 3641 /* now map all entries back to affine space to make point addition faster */
wolfSSL 0:d92f9d21154c 3642 for (x = 1; x < (1UL<<FP_LUT); x++) {
wolfSSL 0:d92f9d21154c 3643 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 3644 break;
wolfSSL 0:d92f9d21154c 3645
wolfSSL 0:d92f9d21154c 3646 /* convert z to normal from montgomery */
wolfSSL 0:d92f9d21154c 3647 err = mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, *mp);
wolfSSL 0:d92f9d21154c 3648
wolfSSL 0:d92f9d21154c 3649 /* invert it */
wolfSSL 0:d92f9d21154c 3650 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3651 err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus,
wolfSSL 0:d92f9d21154c 3652 fp_cache[idx].LUT[x]->z);
wolfSSL 0:d92f9d21154c 3653
wolfSSL 0:d92f9d21154c 3654 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3655 /* now square it */
wolfSSL 0:d92f9d21154c 3656 err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, &tmp);
wolfSSL 0:d92f9d21154c 3657
wolfSSL 0:d92f9d21154c 3658 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3659 /* fix x */
wolfSSL 0:d92f9d21154c 3660 err = mp_mulmod(fp_cache[idx].LUT[x]->x, &tmp, modulus,
wolfSSL 0:d92f9d21154c 3661 fp_cache[idx].LUT[x]->x);
wolfSSL 0:d92f9d21154c 3662
wolfSSL 0:d92f9d21154c 3663 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3664 /* get 1/z^3 */
wolfSSL 0:d92f9d21154c 3665 err = mp_mulmod(&tmp, fp_cache[idx].LUT[x]->z, modulus, &tmp);
wolfSSL 0:d92f9d21154c 3666
wolfSSL 0:d92f9d21154c 3667 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3668 /* fix y */
wolfSSL 0:d92f9d21154c 3669 err = mp_mulmod(fp_cache[idx].LUT[x]->y, &tmp, modulus,
wolfSSL 0:d92f9d21154c 3670 fp_cache[idx].LUT[x]->y);
wolfSSL 0:d92f9d21154c 3671
wolfSSL 0:d92f9d21154c 3672 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3673 /* free z */
wolfSSL 0:d92f9d21154c 3674 mp_clear(fp_cache[idx].LUT[x]->z);
wolfSSL 0:d92f9d21154c 3675 }
wolfSSL 0:d92f9d21154c 3676 mp_clear(&tmp);
wolfSSL 0:d92f9d21154c 3677
wolfSSL 0:d92f9d21154c 3678 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 3679 return MP_OKAY;
wolfSSL 0:d92f9d21154c 3680
wolfSSL 0:d92f9d21154c 3681 /* err cleanup */
wolfSSL 0:d92f9d21154c 3682 for (y = 0; y < (1U<<FP_LUT); y++) {
wolfSSL 0:d92f9d21154c 3683 ecc_del_point(fp_cache[idx].LUT[y]);
wolfSSL 0:d92f9d21154c 3684 fp_cache[idx].LUT[y] = NULL;
wolfSSL 0:d92f9d21154c 3685 }
wolfSSL 0:d92f9d21154c 3686 ecc_del_point(fp_cache[idx].g);
wolfSSL 0:d92f9d21154c 3687 fp_cache[idx].g = NULL;
wolfSSL 0:d92f9d21154c 3688 fp_cache[idx].lru_count = 0;
wolfSSL 0:d92f9d21154c 3689 mp_clear(&fp_cache[idx].mu);
wolfSSL 0:d92f9d21154c 3690 mp_clear(&tmp);
wolfSSL 0:d92f9d21154c 3691
wolfSSL 0:d92f9d21154c 3692 return err;
wolfSSL 0:d92f9d21154c 3693 }
wolfSSL 0:d92f9d21154c 3694
wolfSSL 0:d92f9d21154c 3695 /* perform a fixed point ECC mulmod */
wolfSSL 0:d92f9d21154c 3696 static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 3697 mp_digit* mp, int map)
wolfSSL 0:d92f9d21154c 3698 {
wolfSSL 0:d92f9d21154c 3699 #define KB_SIZE 128
wolfSSL 0:d92f9d21154c 3700
wolfSSL 0:d92f9d21154c 3701 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 3702 unsigned char* kb;
wolfSSL 0:d92f9d21154c 3703 #else
wolfSSL 0:d92f9d21154c 3704 unsigned char kb[128];
wolfSSL 0:d92f9d21154c 3705 #endif
wolfSSL 0:d92f9d21154c 3706 int x;
wolfSSL 0:d92f9d21154c 3707 unsigned y, z, err, bitlen, bitpos, lut_gap, first;
wolfSSL 0:d92f9d21154c 3708 mp_int tk;
wolfSSL 0:d92f9d21154c 3709
wolfSSL 0:d92f9d21154c 3710 if (mp_init(&tk) != MP_OKAY)
wolfSSL 0:d92f9d21154c 3711 return MP_INIT_E;
wolfSSL 0:d92f9d21154c 3712
wolfSSL 0:d92f9d21154c 3713 /* if it's smaller than modulus we fine */
wolfSSL 0:d92f9d21154c 3714 if (mp_unsigned_bin_size(k) > mp_unsigned_bin_size(modulus)) {
wolfSSL 0:d92f9d21154c 3715 mp_int order;
wolfSSL 0:d92f9d21154c 3716 if (mp_init(&order) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3717 mp_clear(&tk);
wolfSSL 0:d92f9d21154c 3718 return MP_INIT_E;
wolfSSL 0:d92f9d21154c 3719 }
wolfSSL 0:d92f9d21154c 3720
wolfSSL 0:d92f9d21154c 3721 /* find order */
wolfSSL 0:d92f9d21154c 3722 y = mp_unsigned_bin_size(modulus);
wolfSSL 0:d92f9d21154c 3723 for (x = 0; ecc_sets[x].size; x++) {
wolfSSL 0:d92f9d21154c 3724 if (y <= (unsigned)ecc_sets[x].size) break;
wolfSSL 0:d92f9d21154c 3725 }
wolfSSL 0:d92f9d21154c 3726
wolfSSL 0:d92f9d21154c 3727 /* back off if we are on the 521 bit curve */
wolfSSL 0:d92f9d21154c 3728 if (y == 66) --x;
wolfSSL 0:d92f9d21154c 3729
wolfSSL 0:d92f9d21154c 3730 if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3731 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3732 mp_clear(&tk);
wolfSSL 0:d92f9d21154c 3733 return err;
wolfSSL 0:d92f9d21154c 3734 }
wolfSSL 0:d92f9d21154c 3735
wolfSSL 0:d92f9d21154c 3736 /* k must be less than modulus */
wolfSSL 0:d92f9d21154c 3737 if (mp_cmp(k, &order) != MP_LT) {
wolfSSL 0:d92f9d21154c 3738 if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3739 mp_clear(&tk);
wolfSSL 0:d92f9d21154c 3740 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3741 return err;
wolfSSL 0:d92f9d21154c 3742 }
wolfSSL 0:d92f9d21154c 3743 } else {
wolfSSL 0:d92f9d21154c 3744 mp_copy(k, &tk);
wolfSSL 0:d92f9d21154c 3745 }
wolfSSL 0:d92f9d21154c 3746 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3747 } else {
wolfSSL 0:d92f9d21154c 3748 mp_copy(k, &tk);
wolfSSL 0:d92f9d21154c 3749 }
wolfSSL 0:d92f9d21154c 3750
wolfSSL 0:d92f9d21154c 3751 /* get bitlen and round up to next multiple of FP_LUT */
wolfSSL 0:d92f9d21154c 3752 bitlen = mp_unsigned_bin_size(modulus) << 3;
wolfSSL 0:d92f9d21154c 3753 x = bitlen % FP_LUT;
wolfSSL 0:d92f9d21154c 3754 if (x) {
wolfSSL 0:d92f9d21154c 3755 bitlen += FP_LUT - x;
wolfSSL 0:d92f9d21154c 3756 }
wolfSSL 0:d92f9d21154c 3757 lut_gap = bitlen / FP_LUT;
wolfSSL 0:d92f9d21154c 3758
wolfSSL 0:d92f9d21154c 3759 /* get the k value */
wolfSSL 0:d92f9d21154c 3760 if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
wolfSSL 0:d92f9d21154c 3761 mp_clear(&tk);
wolfSSL 0:d92f9d21154c 3762 return BUFFER_E;
wolfSSL 0:d92f9d21154c 3763 }
wolfSSL 0:d92f9d21154c 3764
wolfSSL 0:d92f9d21154c 3765 /* store k */
wolfSSL 0:d92f9d21154c 3766 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 3767 kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 3768 if (kb == NULL)
wolfSSL 0:d92f9d21154c 3769 return MEMORY_E;
wolfSSL 0:d92f9d21154c 3770 #endif
wolfSSL 0:d92f9d21154c 3771
wolfSSL 0:d92f9d21154c 3772 XMEMSET(kb, 0, KB_SIZE);
wolfSSL 0:d92f9d21154c 3773 if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3774 mp_clear(&tk);
wolfSSL 0:d92f9d21154c 3775 }
wolfSSL 0:d92f9d21154c 3776 else {
wolfSSL 0:d92f9d21154c 3777 /* let's reverse kb so it's little endian */
wolfSSL 0:d92f9d21154c 3778 x = 0;
wolfSSL 0:d92f9d21154c 3779 y = mp_unsigned_bin_size(&tk) - 1;
wolfSSL 0:d92f9d21154c 3780 mp_clear(&tk);
wolfSSL 0:d92f9d21154c 3781
wolfSSL 0:d92f9d21154c 3782 while ((unsigned)x < y) {
wolfSSL 0:d92f9d21154c 3783 z = kb[x]; kb[x] = kb[y]; kb[y] = z;
wolfSSL 0:d92f9d21154c 3784 ++x; --y;
wolfSSL 0:d92f9d21154c 3785 }
wolfSSL 0:d92f9d21154c 3786
wolfSSL 0:d92f9d21154c 3787 /* at this point we can start, yipee */
wolfSSL 0:d92f9d21154c 3788 first = 1;
wolfSSL 0:d92f9d21154c 3789 for (x = lut_gap-1; x >= 0; x--) {
wolfSSL 0:d92f9d21154c 3790 /* extract FP_LUT bits from kb spread out by lut_gap bits and offset
wolfSSL 0:d92f9d21154c 3791 by x bits from the start */
wolfSSL 0:d92f9d21154c 3792 bitpos = x;
wolfSSL 0:d92f9d21154c 3793 for (y = z = 0; y < FP_LUT; y++) {
wolfSSL 0:d92f9d21154c 3794 z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
wolfSSL 0:d92f9d21154c 3795 bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
wolfSSL 0:d92f9d21154c 3796 the mult in each loop */
wolfSSL 0:d92f9d21154c 3797 }
wolfSSL 0:d92f9d21154c 3798
wolfSSL 0:d92f9d21154c 3799 /* double if not first */
wolfSSL 0:d92f9d21154c 3800 if (!first) {
wolfSSL 0:d92f9d21154c 3801 if ((err = ecc_projective_dbl_point(R, R, modulus,
wolfSSL 0:d92f9d21154c 3802 mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3803 break;
wolfSSL 0:d92f9d21154c 3804 }
wolfSSL 0:d92f9d21154c 3805 }
wolfSSL 0:d92f9d21154c 3806
wolfSSL 0:d92f9d21154c 3807 /* add if not first, otherwise copy */
wolfSSL 0:d92f9d21154c 3808 if (!first && z) {
wolfSSL 0:d92f9d21154c 3809 if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
wolfSSL 0:d92f9d21154c 3810 modulus, mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3811 break;
wolfSSL 0:d92f9d21154c 3812 }
wolfSSL 0:d92f9d21154c 3813 } else if (z) {
wolfSSL 0:d92f9d21154c 3814 if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3815 (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 3816 (mp_copy(&fp_cache[idx].mu, R->z) != MP_OKAY)) {
wolfSSL 0:d92f9d21154c 3817 err = GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 3818 break;
wolfSSL 0:d92f9d21154c 3819 }
wolfSSL 0:d92f9d21154c 3820 first = 0;
wolfSSL 0:d92f9d21154c 3821 }
wolfSSL 0:d92f9d21154c 3822 }
wolfSSL 0:d92f9d21154c 3823 }
wolfSSL 0:d92f9d21154c 3824
wolfSSL 0:d92f9d21154c 3825 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 3826 z = 0;
wolfSSL 0:d92f9d21154c 3827 ForceZero(kb, KB_SIZE);
wolfSSL 0:d92f9d21154c 3828 /* map R back from projective space */
wolfSSL 0:d92f9d21154c 3829 if (map) {
wolfSSL 0:d92f9d21154c 3830 err = ecc_map(R, modulus, mp);
wolfSSL 0:d92f9d21154c 3831 } else {
wolfSSL 0:d92f9d21154c 3832 err = MP_OKAY;
wolfSSL 0:d92f9d21154c 3833 }
wolfSSL 0:d92f9d21154c 3834 }
wolfSSL 0:d92f9d21154c 3835
wolfSSL 0:d92f9d21154c 3836 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 3837 XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 3838 #endif
wolfSSL 0:d92f9d21154c 3839
wolfSSL 0:d92f9d21154c 3840 #undef KB_SIZE
wolfSSL 0:d92f9d21154c 3841
wolfSSL 0:d92f9d21154c 3842 return err;
wolfSSL 0:d92f9d21154c 3843 }
wolfSSL 0:d92f9d21154c 3844
wolfSSL 0:d92f9d21154c 3845 #ifdef ECC_SHAMIR
wolfSSL 0:d92f9d21154c 3846 /* perform a fixed point ECC mulmod */
wolfSSL 0:d92f9d21154c 3847 static int accel_fp_mul2add(int idx1, int idx2,
wolfSSL 0:d92f9d21154c 3848 mp_int* kA, mp_int* kB,
wolfSSL 0:d92f9d21154c 3849 ecc_point *R, mp_int* modulus, mp_digit* mp)
wolfSSL 0:d92f9d21154c 3850 {
wolfSSL 0:d92f9d21154c 3851 #define KB_SIZE 128
wolfSSL 0:d92f9d21154c 3852
wolfSSL 0:d92f9d21154c 3853 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 3854 unsigned char* kb[2];
wolfSSL 0:d92f9d21154c 3855 #else
wolfSSL 0:d92f9d21154c 3856 unsigned char kb[2][128];
wolfSSL 0:d92f9d21154c 3857 #endif
wolfSSL 0:d92f9d21154c 3858 int x;
wolfSSL 0:d92f9d21154c 3859 unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
wolfSSL 0:d92f9d21154c 3860 mp_int tka;
wolfSSL 0:d92f9d21154c 3861 mp_int tkb;
wolfSSL 0:d92f9d21154c 3862 mp_int order;
wolfSSL 0:d92f9d21154c 3863
wolfSSL 0:d92f9d21154c 3864 if (mp_init_multi(&tka, &tkb, 0, 0, 0, 0) != MP_OKAY)
wolfSSL 0:d92f9d21154c 3865 return MP_INIT_E;
wolfSSL 0:d92f9d21154c 3866
wolfSSL 0:d92f9d21154c 3867 /* if it's smaller than modulus we fine */
wolfSSL 0:d92f9d21154c 3868 if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) {
wolfSSL 0:d92f9d21154c 3869 /* find order */
wolfSSL 0:d92f9d21154c 3870 y = mp_unsigned_bin_size(modulus);
wolfSSL 0:d92f9d21154c 3871 for (x = 0; ecc_sets[x].size; x++) {
wolfSSL 0:d92f9d21154c 3872 if (y <= (unsigned)ecc_sets[x].size) break;
wolfSSL 0:d92f9d21154c 3873 }
wolfSSL 0:d92f9d21154c 3874
wolfSSL 0:d92f9d21154c 3875 /* back off if we are on the 521 bit curve */
wolfSSL 0:d92f9d21154c 3876 if (y == 66) --x;
wolfSSL 0:d92f9d21154c 3877
wolfSSL 0:d92f9d21154c 3878 if ((err = mp_init(&order)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3879 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3880 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3881 return err;
wolfSSL 0:d92f9d21154c 3882 }
wolfSSL 0:d92f9d21154c 3883 if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3884 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3885 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3886 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3887 return err;
wolfSSL 0:d92f9d21154c 3888 }
wolfSSL 0:d92f9d21154c 3889
wolfSSL 0:d92f9d21154c 3890 /* kA must be less than modulus */
wolfSSL 0:d92f9d21154c 3891 if (mp_cmp(kA, &order) != MP_LT) {
wolfSSL 0:d92f9d21154c 3892 if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3893 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3894 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3895 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3896 return err;
wolfSSL 0:d92f9d21154c 3897 }
wolfSSL 0:d92f9d21154c 3898 } else {
wolfSSL 0:d92f9d21154c 3899 mp_copy(kA, &tka);
wolfSSL 0:d92f9d21154c 3900 }
wolfSSL 0:d92f9d21154c 3901 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3902 } else {
wolfSSL 0:d92f9d21154c 3903 mp_copy(kA, &tka);
wolfSSL 0:d92f9d21154c 3904 }
wolfSSL 0:d92f9d21154c 3905
wolfSSL 0:d92f9d21154c 3906 /* if it's smaller than modulus we fine */
wolfSSL 0:d92f9d21154c 3907 if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) {
wolfSSL 0:d92f9d21154c 3908 /* find order */
wolfSSL 0:d92f9d21154c 3909 y = mp_unsigned_bin_size(modulus);
wolfSSL 0:d92f9d21154c 3910 for (x = 0; ecc_sets[x].size; x++) {
wolfSSL 0:d92f9d21154c 3911 if (y <= (unsigned)ecc_sets[x].size) break;
wolfSSL 0:d92f9d21154c 3912 }
wolfSSL 0:d92f9d21154c 3913
wolfSSL 0:d92f9d21154c 3914 /* back off if we are on the 521 bit curve */
wolfSSL 0:d92f9d21154c 3915 if (y == 66) --x;
wolfSSL 0:d92f9d21154c 3916
wolfSSL 0:d92f9d21154c 3917 if ((err = mp_init(&order)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3918 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3919 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3920 return err;
wolfSSL 0:d92f9d21154c 3921 }
wolfSSL 0:d92f9d21154c 3922 if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3923 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3924 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3925 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3926 return err;
wolfSSL 0:d92f9d21154c 3927 }
wolfSSL 0:d92f9d21154c 3928
wolfSSL 0:d92f9d21154c 3929 /* kB must be less than modulus */
wolfSSL 0:d92f9d21154c 3930 if (mp_cmp(kB, &order) != MP_LT) {
wolfSSL 0:d92f9d21154c 3931 if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3932 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3933 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3934 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3935 return err;
wolfSSL 0:d92f9d21154c 3936 }
wolfSSL 0:d92f9d21154c 3937 } else {
wolfSSL 0:d92f9d21154c 3938 mp_copy(kB, &tkb);
wolfSSL 0:d92f9d21154c 3939 }
wolfSSL 0:d92f9d21154c 3940 mp_clear(&order);
wolfSSL 0:d92f9d21154c 3941 } else {
wolfSSL 0:d92f9d21154c 3942 mp_copy(kB, &tkb);
wolfSSL 0:d92f9d21154c 3943 }
wolfSSL 0:d92f9d21154c 3944
wolfSSL 0:d92f9d21154c 3945 /* get bitlen and round up to next multiple of FP_LUT */
wolfSSL 0:d92f9d21154c 3946 bitlen = mp_unsigned_bin_size(modulus) << 3;
wolfSSL 0:d92f9d21154c 3947 x = bitlen % FP_LUT;
wolfSSL 0:d92f9d21154c 3948 if (x) {
wolfSSL 0:d92f9d21154c 3949 bitlen += FP_LUT - x;
wolfSSL 0:d92f9d21154c 3950 }
wolfSSL 0:d92f9d21154c 3951 lut_gap = bitlen / FP_LUT;
wolfSSL 0:d92f9d21154c 3952
wolfSSL 0:d92f9d21154c 3953 /* get the k value */
wolfSSL 0:d92f9d21154c 3954 if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
wolfSSL 0:d92f9d21154c 3955 (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) {
wolfSSL 0:d92f9d21154c 3956 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3957 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3958 return BUFFER_E;
wolfSSL 0:d92f9d21154c 3959 }
wolfSSL 0:d92f9d21154c 3960
wolfSSL 0:d92f9d21154c 3961 /* store k */
wolfSSL 0:d92f9d21154c 3962 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 3963 kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 3964 if (kb[0] == NULL)
wolfSSL 0:d92f9d21154c 3965 return MEMORY_E;
wolfSSL 0:d92f9d21154c 3966 #endif
wolfSSL 0:d92f9d21154c 3967
wolfSSL 0:d92f9d21154c 3968 XMEMSET(kb[0], 0, KB_SIZE);
wolfSSL 0:d92f9d21154c 3969 if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3970 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3971 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3972 XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 3973 return err;
wolfSSL 0:d92f9d21154c 3974 }
wolfSSL 0:d92f9d21154c 3975
wolfSSL 0:d92f9d21154c 3976 /* let's reverse kb so it's little endian */
wolfSSL 0:d92f9d21154c 3977 x = 0;
wolfSSL 0:d92f9d21154c 3978 y = mp_unsigned_bin_size(&tka) - 1;
wolfSSL 0:d92f9d21154c 3979 mp_clear(&tka);
wolfSSL 0:d92f9d21154c 3980 while ((unsigned)x < y) {
wolfSSL 0:d92f9d21154c 3981 z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z;
wolfSSL 0:d92f9d21154c 3982 ++x; --y;
wolfSSL 0:d92f9d21154c 3983 }
wolfSSL 0:d92f9d21154c 3984
wolfSSL 0:d92f9d21154c 3985 /* store b */
wolfSSL 0:d92f9d21154c 3986 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 3987 kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 3988 if (kb[1] == NULL) {
wolfSSL 0:d92f9d21154c 3989 XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 3990 return MEMORY_E;
wolfSSL 0:d92f9d21154c 3991 }
wolfSSL 0:d92f9d21154c 3992 #endif
wolfSSL 0:d92f9d21154c 3993
wolfSSL 0:d92f9d21154c 3994 XMEMSET(kb[1], 0, KB_SIZE);
wolfSSL 0:d92f9d21154c 3995 if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 3996 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 3997 }
wolfSSL 0:d92f9d21154c 3998 else {
wolfSSL 0:d92f9d21154c 3999 x = 0;
wolfSSL 0:d92f9d21154c 4000 y = mp_unsigned_bin_size(&tkb) - 1;
wolfSSL 0:d92f9d21154c 4001 mp_clear(&tkb);
wolfSSL 0:d92f9d21154c 4002 while ((unsigned)x < y) {
wolfSSL 0:d92f9d21154c 4003 z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
wolfSSL 0:d92f9d21154c 4004 ++x; --y;
wolfSSL 0:d92f9d21154c 4005 }
wolfSSL 0:d92f9d21154c 4006
wolfSSL 0:d92f9d21154c 4007 /* at this point we can start, yipee */
wolfSSL 0:d92f9d21154c 4008 first = 1;
wolfSSL 0:d92f9d21154c 4009 for (x = lut_gap-1; x >= 0; x--) {
wolfSSL 0:d92f9d21154c 4010 /* extract FP_LUT bits from kb spread out by lut_gap bits and
wolfSSL 0:d92f9d21154c 4011 offset by x bits from the start */
wolfSSL 0:d92f9d21154c 4012 bitpos = x;
wolfSSL 0:d92f9d21154c 4013 for (y = zA = zB = 0; y < FP_LUT; y++) {
wolfSSL 0:d92f9d21154c 4014 zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
wolfSSL 0:d92f9d21154c 4015 zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
wolfSSL 0:d92f9d21154c 4016 bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
wolfSSL 0:d92f9d21154c 4017 the mult in each loop */
wolfSSL 0:d92f9d21154c 4018 }
wolfSSL 0:d92f9d21154c 4019
wolfSSL 0:d92f9d21154c 4020 /* double if not first */
wolfSSL 0:d92f9d21154c 4021 if (!first) {
wolfSSL 0:d92f9d21154c 4022 if ((err = ecc_projective_dbl_point(R, R, modulus,
wolfSSL 0:d92f9d21154c 4023 mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 4024 break;
wolfSSL 0:d92f9d21154c 4025 }
wolfSSL 0:d92f9d21154c 4026 }
wolfSSL 0:d92f9d21154c 4027
wolfSSL 0:d92f9d21154c 4028 /* add if not first, otherwise copy */
wolfSSL 0:d92f9d21154c 4029 if (!first) {
wolfSSL 0:d92f9d21154c 4030 if (zA) {
wolfSSL 0:d92f9d21154c 4031 if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
wolfSSL 0:d92f9d21154c 4032 R, modulus, mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 4033 break;
wolfSSL 0:d92f9d21154c 4034 }
wolfSSL 0:d92f9d21154c 4035 }
wolfSSL 0:d92f9d21154c 4036 if (zB) {
wolfSSL 0:d92f9d21154c 4037 if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
wolfSSL 0:d92f9d21154c 4038 R, modulus, mp)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 4039 break;
wolfSSL 0:d92f9d21154c 4040 }
wolfSSL 0:d92f9d21154c 4041 }
wolfSSL 0:d92f9d21154c 4042 } else {
wolfSSL 0:d92f9d21154c 4043 if (zA) {
wolfSSL 0:d92f9d21154c 4044 if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 4045 (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 4046 (mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) {
wolfSSL 0:d92f9d21154c 4047 err = GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 4048 break;
wolfSSL 0:d92f9d21154c 4049 }
wolfSSL 0:d92f9d21154c 4050 first = 0;
wolfSSL 0:d92f9d21154c 4051 }
wolfSSL 0:d92f9d21154c 4052 if (zB && first == 0) {
wolfSSL 0:d92f9d21154c 4053 if (zB) {
wolfSSL 0:d92f9d21154c 4054 if ((err = ecc_projective_add_point(R,
wolfSSL 0:d92f9d21154c 4055 fp_cache[idx2].LUT[zB], R, modulus, mp)) != MP_OKAY){
wolfSSL 0:d92f9d21154c 4056 break;
wolfSSL 0:d92f9d21154c 4057 }
wolfSSL 0:d92f9d21154c 4058 }
wolfSSL 0:d92f9d21154c 4059 } else if (zB && first == 1) {
wolfSSL 0:d92f9d21154c 4060 if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 4061 (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) ||
wolfSSL 0:d92f9d21154c 4062 (mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) {
wolfSSL 0:d92f9d21154c 4063 err = GEN_MEM_ERR;
wolfSSL 0:d92f9d21154c 4064 break;
wolfSSL 0:d92f9d21154c 4065 }
wolfSSL 0:d92f9d21154c 4066 first = 0;
wolfSSL 0:d92f9d21154c 4067 }
wolfSSL 0:d92f9d21154c 4068 }
wolfSSL 0:d92f9d21154c 4069 }
wolfSSL 0:d92f9d21154c 4070 }
wolfSSL 0:d92f9d21154c 4071
wolfSSL 0:d92f9d21154c 4072 ForceZero(kb[0], KB_SIZE);
wolfSSL 0:d92f9d21154c 4073 ForceZero(kb[1], KB_SIZE);
wolfSSL 0:d92f9d21154c 4074
wolfSSL 0:d92f9d21154c 4075 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4076 XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4077 XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4078 #endif
wolfSSL 0:d92f9d21154c 4079
wolfSSL 0:d92f9d21154c 4080 #undef KB_SIZE
wolfSSL 0:d92f9d21154c 4081
wolfSSL 0:d92f9d21154c 4082 return ecc_map(R, modulus, mp);
wolfSSL 0:d92f9d21154c 4083 }
wolfSSL 0:d92f9d21154c 4084
wolfSSL 0:d92f9d21154c 4085 /** ECC Fixed Point mulmod global
wolfSSL 0:d92f9d21154c 4086 Computes kA*A + kB*B = C using Shamir's Trick
wolfSSL 0:d92f9d21154c 4087 A First point to multiply
wolfSSL 0:d92f9d21154c 4088 kA What to multiple A by
wolfSSL 0:d92f9d21154c 4089 B Second point to multiply
wolfSSL 0:d92f9d21154c 4090 kB What to multiple B by
wolfSSL 0:d92f9d21154c 4091 C [out] Destination point (can overlap with A or B)
wolfSSL 0:d92f9d21154c 4092 modulus Modulus for curve
wolfSSL 0:d92f9d21154c 4093 return MP_OKAY on success
wolfSSL 0:d92f9d21154c 4094 */
wolfSSL 0:d92f9d21154c 4095 int ecc_mul2add(ecc_point* A, mp_int* kA,
wolfSSL 0:d92f9d21154c 4096 ecc_point* B, mp_int* kB,
wolfSSL 0:d92f9d21154c 4097 ecc_point* C, mp_int* modulus)
wolfSSL 0:d92f9d21154c 4098 {
wolfSSL 0:d92f9d21154c 4099 int idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0;
wolfSSL 0:d92f9d21154c 4100 mp_digit mp;
wolfSSL 0:d92f9d21154c 4101 mp_int mu;
wolfSSL 0:d92f9d21154c 4102
wolfSSL 0:d92f9d21154c 4103 err = mp_init(&mu);
wolfSSL 0:d92f9d21154c 4104 if (err != MP_OKAY)
wolfSSL 0:d92f9d21154c 4105 return err;
wolfSSL 0:d92f9d21154c 4106
wolfSSL 0:d92f9d21154c 4107 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 4108 if (initMutex == 0) {
wolfSSL 0:d92f9d21154c 4109 InitMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4110 initMutex = 1;
wolfSSL 0:d92f9d21154c 4111 }
wolfSSL 0:d92f9d21154c 4112 if (LockMutex(&ecc_fp_lock) != 0)
wolfSSL 0:d92f9d21154c 4113 return BAD_MUTEX_E;
wolfSSL 0:d92f9d21154c 4114 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 4115
wolfSSL 0:d92f9d21154c 4116 /* find point */
wolfSSL 0:d92f9d21154c 4117 idx1 = find_base(A);
wolfSSL 0:d92f9d21154c 4118
wolfSSL 0:d92f9d21154c 4119 /* no entry? */
wolfSSL 0:d92f9d21154c 4120 if (idx1 == -1) {
wolfSSL 0:d92f9d21154c 4121 /* find hole and add it */
wolfSSL 0:d92f9d21154c 4122 if ((idx1 = find_hole()) >= 0) {
wolfSSL 0:d92f9d21154c 4123 err = add_entry(idx1, A);
wolfSSL 0:d92f9d21154c 4124 }
wolfSSL 0:d92f9d21154c 4125 }
wolfSSL 0:d92f9d21154c 4126 if (err == MP_OKAY && idx1 != -1) {
wolfSSL 0:d92f9d21154c 4127 /* increment LRU */
wolfSSL 0:d92f9d21154c 4128 ++(fp_cache[idx1].lru_count);
wolfSSL 0:d92f9d21154c 4129 }
wolfSSL 0:d92f9d21154c 4130
wolfSSL 0:d92f9d21154c 4131 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 4132 /* find point */
wolfSSL 0:d92f9d21154c 4133 idx2 = find_base(B);
wolfSSL 0:d92f9d21154c 4134
wolfSSL 0:d92f9d21154c 4135 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4136 /* no entry? */
wolfSSL 0:d92f9d21154c 4137 if (idx2 == -1) {
wolfSSL 0:d92f9d21154c 4138 /* find hole and add it */
wolfSSL 0:d92f9d21154c 4139 if ((idx2 = find_hole()) >= 0)
wolfSSL 0:d92f9d21154c 4140 err = add_entry(idx2, B);
wolfSSL 0:d92f9d21154c 4141 }
wolfSSL 0:d92f9d21154c 4142 }
wolfSSL 0:d92f9d21154c 4143
wolfSSL 0:d92f9d21154c 4144 if (err == MP_OKAY && idx2 != -1) {
wolfSSL 0:d92f9d21154c 4145 /* increment LRU */
wolfSSL 0:d92f9d21154c 4146 ++(fp_cache[idx2].lru_count);
wolfSSL 0:d92f9d21154c 4147 }
wolfSSL 0:d92f9d21154c 4148
wolfSSL 0:d92f9d21154c 4149 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4150 /* if it's 2 build the LUT, if it's higher just use the LUT */
wolfSSL 0:d92f9d21154c 4151 if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) {
wolfSSL 0:d92f9d21154c 4152 /* compute mp */
wolfSSL 0:d92f9d21154c 4153 err = mp_montgomery_setup(modulus, &mp);
wolfSSL 0:d92f9d21154c 4154
wolfSSL 0:d92f9d21154c 4155 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4156 mpInit = 1;
wolfSSL 0:d92f9d21154c 4157 err = mp_montgomery_calc_normalization(&mu, modulus);
wolfSSL 0:d92f9d21154c 4158 }
wolfSSL 0:d92f9d21154c 4159
wolfSSL 0:d92f9d21154c 4160 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 4161 /* build the LUT */
wolfSSL 0:d92f9d21154c 4162 err = build_lut(idx1, modulus, &mp, &mu);
wolfSSL 0:d92f9d21154c 4163 }
wolfSSL 0:d92f9d21154c 4164 }
wolfSSL 0:d92f9d21154c 4165
wolfSSL 0:d92f9d21154c 4166 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4167 /* if it's 2 build the LUT, if it's higher just use the LUT */
wolfSSL 0:d92f9d21154c 4168 if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) {
wolfSSL 0:d92f9d21154c 4169 if (mpInit == 0) {
wolfSSL 0:d92f9d21154c 4170 /* compute mp */
wolfSSL 0:d92f9d21154c 4171 err = mp_montgomery_setup(modulus, &mp);
wolfSSL 0:d92f9d21154c 4172 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4173 mpInit = 1;
wolfSSL 0:d92f9d21154c 4174 err = mp_montgomery_calc_normalization(&mu, modulus);
wolfSSL 0:d92f9d21154c 4175 }
wolfSSL 0:d92f9d21154c 4176 }
wolfSSL 0:d92f9d21154c 4177
wolfSSL 0:d92f9d21154c 4178 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 4179 /* build the LUT */
wolfSSL 0:d92f9d21154c 4180 err = build_lut(idx2, modulus, &mp, &mu);
wolfSSL 0:d92f9d21154c 4181 }
wolfSSL 0:d92f9d21154c 4182 }
wolfSSL 0:d92f9d21154c 4183
wolfSSL 0:d92f9d21154c 4184
wolfSSL 0:d92f9d21154c 4185 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4186 if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 &&
wolfSSL 0:d92f9d21154c 4187 fp_cache[idx2].lru_count >= 2) {
wolfSSL 0:d92f9d21154c 4188 if (mpInit == 0) {
wolfSSL 0:d92f9d21154c 4189 /* compute mp */
wolfSSL 0:d92f9d21154c 4190 err = mp_montgomery_setup(modulus, &mp);
wolfSSL 0:d92f9d21154c 4191 }
wolfSSL 0:d92f9d21154c 4192 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 4193 err = accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, &mp);
wolfSSL 0:d92f9d21154c 4194 } else {
wolfSSL 0:d92f9d21154c 4195 err = normal_ecc_mul2add(A, kA, B, kB, C, modulus);
wolfSSL 0:d92f9d21154c 4196 }
wolfSSL 0:d92f9d21154c 4197 }
wolfSSL 0:d92f9d21154c 4198
wolfSSL 0:d92f9d21154c 4199 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 4200 UnLockMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4201 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 4202 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 4203
wolfSSL 0:d92f9d21154c 4204 return err;
wolfSSL 0:d92f9d21154c 4205 }
wolfSSL 0:d92f9d21154c 4206 #endif
wolfSSL 0:d92f9d21154c 4207
wolfSSL 0:d92f9d21154c 4208 /** ECC Fixed Point mulmod global
wolfSSL 0:d92f9d21154c 4209 k The multiplicand
wolfSSL 0:d92f9d21154c 4210 G Base point to multiply
wolfSSL 0:d92f9d21154c 4211 R [out] Destination of product
wolfSSL 0:d92f9d21154c 4212 modulus The modulus for the curve
wolfSSL 0:d92f9d21154c 4213 map [boolean] If non-zero maps the point back to affine co-ordinates,
wolfSSL 0:d92f9d21154c 4214 otherwise it's left in jacobian-montgomery form
wolfSSL 0:d92f9d21154c 4215 return MP_OKAY if successful
wolfSSL 0:d92f9d21154c 4216 */
wolfSSL 0:d92f9d21154c 4217 int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
wolfSSL 0:d92f9d21154c 4218 int map)
wolfSSL 0:d92f9d21154c 4219 {
wolfSSL 0:d92f9d21154c 4220 int idx, err = MP_OKAY;
wolfSSL 0:d92f9d21154c 4221 mp_digit mp;
wolfSSL 0:d92f9d21154c 4222 mp_int mu;
wolfSSL 0:d92f9d21154c 4223 int mpSetup = 0;
wolfSSL 0:d92f9d21154c 4224
wolfSSL 0:d92f9d21154c 4225 if (mp_init(&mu) != MP_OKAY)
wolfSSL 0:d92f9d21154c 4226 return MP_INIT_E;
wolfSSL 0:d92f9d21154c 4227
wolfSSL 0:d92f9d21154c 4228 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 4229 if (initMutex == 0) {
wolfSSL 0:d92f9d21154c 4230 InitMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4231 initMutex = 1;
wolfSSL 0:d92f9d21154c 4232 }
wolfSSL 0:d92f9d21154c 4233
wolfSSL 0:d92f9d21154c 4234 if (LockMutex(&ecc_fp_lock) != 0)
wolfSSL 0:d92f9d21154c 4235 return BAD_MUTEX_E;
wolfSSL 0:d92f9d21154c 4236 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 4237
wolfSSL 0:d92f9d21154c 4238 /* find point */
wolfSSL 0:d92f9d21154c 4239 idx = find_base(G);
wolfSSL 0:d92f9d21154c 4240
wolfSSL 0:d92f9d21154c 4241 /* no entry? */
wolfSSL 0:d92f9d21154c 4242 if (idx == -1) {
wolfSSL 0:d92f9d21154c 4243 /* find hole and add it */
wolfSSL 0:d92f9d21154c 4244 idx = find_hole();
wolfSSL 0:d92f9d21154c 4245
wolfSSL 0:d92f9d21154c 4246 if (idx >= 0)
wolfSSL 0:d92f9d21154c 4247 err = add_entry(idx, G);
wolfSSL 0:d92f9d21154c 4248 }
wolfSSL 0:d92f9d21154c 4249 if (err == MP_OKAY && idx >= 0) {
wolfSSL 0:d92f9d21154c 4250 /* increment LRU */
wolfSSL 0:d92f9d21154c 4251 ++(fp_cache[idx].lru_count);
wolfSSL 0:d92f9d21154c 4252 }
wolfSSL 0:d92f9d21154c 4253
wolfSSL 0:d92f9d21154c 4254
wolfSSL 0:d92f9d21154c 4255 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4256 /* if it's 2 build the LUT, if it's higher just use the LUT */
wolfSSL 0:d92f9d21154c 4257 if (idx >= 0 && fp_cache[idx].lru_count == 2) {
wolfSSL 0:d92f9d21154c 4258 /* compute mp */
wolfSSL 0:d92f9d21154c 4259 err = mp_montgomery_setup(modulus, &mp);
wolfSSL 0:d92f9d21154c 4260
wolfSSL 0:d92f9d21154c 4261 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4262 /* compute mu */
wolfSSL 0:d92f9d21154c 4263 mpSetup = 1;
wolfSSL 0:d92f9d21154c 4264 err = mp_montgomery_calc_normalization(&mu, modulus);
wolfSSL 0:d92f9d21154c 4265 }
wolfSSL 0:d92f9d21154c 4266
wolfSSL 0:d92f9d21154c 4267 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 4268 /* build the LUT */
wolfSSL 0:d92f9d21154c 4269 err = build_lut(idx, modulus, &mp, &mu);
wolfSSL 0:d92f9d21154c 4270 }
wolfSSL 0:d92f9d21154c 4271 }
wolfSSL 0:d92f9d21154c 4272
wolfSSL 0:d92f9d21154c 4273 if (err == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4274 if (idx >= 0 && fp_cache[idx].lru_count >= 2) {
wolfSSL 0:d92f9d21154c 4275 if (mpSetup == 0) {
wolfSSL 0:d92f9d21154c 4276 /* compute mp */
wolfSSL 0:d92f9d21154c 4277 err = mp_montgomery_setup(modulus, &mp);
wolfSSL 0:d92f9d21154c 4278 }
wolfSSL 0:d92f9d21154c 4279 if (err == MP_OKAY)
wolfSSL 0:d92f9d21154c 4280 err = accel_fp_mul(idx, k, R, modulus, &mp, map);
wolfSSL 0:d92f9d21154c 4281 } else {
wolfSSL 0:d92f9d21154c 4282 err = normal_ecc_mulmod(k, G, R, modulus, map);
wolfSSL 0:d92f9d21154c 4283 }
wolfSSL 0:d92f9d21154c 4284 }
wolfSSL 0:d92f9d21154c 4285
wolfSSL 0:d92f9d21154c 4286 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 4287 UnLockMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4288 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 4289 mp_clear(&mu);
wolfSSL 0:d92f9d21154c 4290
wolfSSL 0:d92f9d21154c 4291 return err;
wolfSSL 0:d92f9d21154c 4292 }
wolfSSL 0:d92f9d21154c 4293
wolfSSL 0:d92f9d21154c 4294 /* helper function for freeing the cache ...
wolfSSL 0:d92f9d21154c 4295 must be called with the cache mutex locked */
wolfSSL 0:d92f9d21154c 4296 static void wc_ecc_fp_free_cache(void)
wolfSSL 0:d92f9d21154c 4297 {
wolfSSL 0:d92f9d21154c 4298 unsigned x, y;
wolfSSL 0:d92f9d21154c 4299 for (x = 0; x < FP_ENTRIES; x++) {
wolfSSL 0:d92f9d21154c 4300 if (fp_cache[x].g != NULL) {
wolfSSL 0:d92f9d21154c 4301 for (y = 0; y < (1U<<FP_LUT); y++) {
wolfSSL 0:d92f9d21154c 4302 ecc_del_point(fp_cache[x].LUT[y]);
wolfSSL 0:d92f9d21154c 4303 fp_cache[x].LUT[y] = NULL;
wolfSSL 0:d92f9d21154c 4304 }
wolfSSL 0:d92f9d21154c 4305 ecc_del_point(fp_cache[x].g);
wolfSSL 0:d92f9d21154c 4306 fp_cache[x].g = NULL;
wolfSSL 0:d92f9d21154c 4307 mp_clear(&fp_cache[x].mu);
wolfSSL 0:d92f9d21154c 4308 fp_cache[x].lru_count = 0;
wolfSSL 0:d92f9d21154c 4309 fp_cache[x].lock = 0;
wolfSSL 0:d92f9d21154c 4310 }
wolfSSL 0:d92f9d21154c 4311 }
wolfSSL 0:d92f9d21154c 4312 }
wolfSSL 0:d92f9d21154c 4313
wolfSSL 0:d92f9d21154c 4314 /** Free the Fixed Point cache */
wolfSSL 0:d92f9d21154c 4315 void wc_ecc_fp_free(void)
wolfSSL 0:d92f9d21154c 4316 {
wolfSSL 0:d92f9d21154c 4317 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 4318 if (initMutex == 0) {
wolfSSL 0:d92f9d21154c 4319 InitMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4320 initMutex = 1;
wolfSSL 0:d92f9d21154c 4321 }
wolfSSL 0:d92f9d21154c 4322
wolfSSL 0:d92f9d21154c 4323 if (LockMutex(&ecc_fp_lock) == 0) {
wolfSSL 0:d92f9d21154c 4324 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 4325
wolfSSL 0:d92f9d21154c 4326 wc_ecc_fp_free_cache();
wolfSSL 0:d92f9d21154c 4327
wolfSSL 0:d92f9d21154c 4328 #ifndef HAVE_THREAD_LS
wolfSSL 0:d92f9d21154c 4329 UnLockMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4330 FreeMutex(&ecc_fp_lock);
wolfSSL 0:d92f9d21154c 4331 initMutex = 0;
wolfSSL 0:d92f9d21154c 4332 }
wolfSSL 0:d92f9d21154c 4333 #endif /* HAVE_THREAD_LS */
wolfSSL 0:d92f9d21154c 4334 }
wolfSSL 0:d92f9d21154c 4335
wolfSSL 0:d92f9d21154c 4336
wolfSSL 0:d92f9d21154c 4337 #endif /* FP_ECC */
wolfSSL 0:d92f9d21154c 4338
wolfSSL 0:d92f9d21154c 4339 #ifdef HAVE_ECC_ENCRYPT
wolfSSL 0:d92f9d21154c 4340
wolfSSL 0:d92f9d21154c 4341
wolfSSL 0:d92f9d21154c 4342 enum ecCliState {
wolfSSL 0:d92f9d21154c 4343 ecCLI_INIT = 1,
wolfSSL 0:d92f9d21154c 4344 ecCLI_SALT_GET = 2,
wolfSSL 0:d92f9d21154c 4345 ecCLI_SALT_SET = 3,
wolfSSL 0:d92f9d21154c 4346 ecCLI_SENT_REQ = 4,
wolfSSL 0:d92f9d21154c 4347 ecCLI_RECV_RESP = 5,
wolfSSL 0:d92f9d21154c 4348 ecCLI_BAD_STATE = 99
wolfSSL 0:d92f9d21154c 4349 };
wolfSSL 0:d92f9d21154c 4350
wolfSSL 0:d92f9d21154c 4351 enum ecSrvState {
wolfSSL 0:d92f9d21154c 4352 ecSRV_INIT = 1,
wolfSSL 0:d92f9d21154c 4353 ecSRV_SALT_GET = 2,
wolfSSL 0:d92f9d21154c 4354 ecSRV_SALT_SET = 3,
wolfSSL 0:d92f9d21154c 4355 ecSRV_RECV_REQ = 4,
wolfSSL 0:d92f9d21154c 4356 ecSRV_SENT_RESP = 5,
wolfSSL 0:d92f9d21154c 4357 ecSRV_BAD_STATE = 99
wolfSSL 0:d92f9d21154c 4358 };
wolfSSL 0:d92f9d21154c 4359
wolfSSL 0:d92f9d21154c 4360
wolfSSL 0:d92f9d21154c 4361 struct ecEncCtx {
wolfSSL 0:d92f9d21154c 4362 const byte* kdfSalt; /* optional salt for kdf */
wolfSSL 0:d92f9d21154c 4363 const byte* kdfInfo; /* optional info for kdf */
wolfSSL 0:d92f9d21154c 4364 const byte* macSalt; /* optional salt for mac */
wolfSSL 0:d92f9d21154c 4365 word32 kdfSaltSz; /* size of kdfSalt */
wolfSSL 0:d92f9d21154c 4366 word32 kdfInfoSz; /* size of kdfInfo */
wolfSSL 0:d92f9d21154c 4367 word32 macSaltSz; /* size of macSalt */
wolfSSL 0:d92f9d21154c 4368 byte clientSalt[EXCHANGE_SALT_SZ]; /* for msg exchange */
wolfSSL 0:d92f9d21154c 4369 byte serverSalt[EXCHANGE_SALT_SZ]; /* for msg exchange */
wolfSSL 0:d92f9d21154c 4370 byte encAlgo; /* which encryption type */
wolfSSL 0:d92f9d21154c 4371 byte kdfAlgo; /* which key derivation function type */
wolfSSL 0:d92f9d21154c 4372 byte macAlgo; /* which mac function type */
wolfSSL 0:d92f9d21154c 4373 byte protocol; /* are we REQ_RESP client or server ? */
wolfSSL 0:d92f9d21154c 4374 byte cliSt; /* protocol state, for sanity checks */
wolfSSL 0:d92f9d21154c 4375 byte srvSt; /* protocol state, for sanity checks */
wolfSSL 0:d92f9d21154c 4376 };
wolfSSL 0:d92f9d21154c 4377
wolfSSL 0:d92f9d21154c 4378
wolfSSL 0:d92f9d21154c 4379 const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx)
wolfSSL 0:d92f9d21154c 4380 {
wolfSSL 0:d92f9d21154c 4381 if (ctx == NULL || ctx->protocol == 0)
wolfSSL 0:d92f9d21154c 4382 return NULL;
wolfSSL 0:d92f9d21154c 4383
wolfSSL 0:d92f9d21154c 4384 if (ctx->protocol == REQ_RESP_CLIENT) {
wolfSSL 0:d92f9d21154c 4385 if (ctx->cliSt == ecCLI_INIT) {
wolfSSL 0:d92f9d21154c 4386 ctx->cliSt = ecCLI_SALT_GET;
wolfSSL 0:d92f9d21154c 4387 return ctx->clientSalt;
wolfSSL 0:d92f9d21154c 4388 }
wolfSSL 0:d92f9d21154c 4389 else {
wolfSSL 0:d92f9d21154c 4390 ctx->cliSt = ecCLI_BAD_STATE;
wolfSSL 0:d92f9d21154c 4391 return NULL;
wolfSSL 0:d92f9d21154c 4392 }
wolfSSL 0:d92f9d21154c 4393 }
wolfSSL 0:d92f9d21154c 4394 else if (ctx->protocol == REQ_RESP_SERVER) {
wolfSSL 0:d92f9d21154c 4395 if (ctx->srvSt == ecSRV_INIT) {
wolfSSL 0:d92f9d21154c 4396 ctx->srvSt = ecSRV_SALT_GET;
wolfSSL 0:d92f9d21154c 4397 return ctx->serverSalt;
wolfSSL 0:d92f9d21154c 4398 }
wolfSSL 0:d92f9d21154c 4399 else {
wolfSSL 0:d92f9d21154c 4400 ctx->srvSt = ecSRV_BAD_STATE;
wolfSSL 0:d92f9d21154c 4401 return NULL;
wolfSSL 0:d92f9d21154c 4402 }
wolfSSL 0:d92f9d21154c 4403 }
wolfSSL 0:d92f9d21154c 4404
wolfSSL 0:d92f9d21154c 4405 return NULL;
wolfSSL 0:d92f9d21154c 4406 }
wolfSSL 0:d92f9d21154c 4407
wolfSSL 0:d92f9d21154c 4408
wolfSSL 0:d92f9d21154c 4409 /* optional set info, can be called before or after set_peer_salt */
wolfSSL 0:d92f9d21154c 4410 int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz)
wolfSSL 0:d92f9d21154c 4411 {
wolfSSL 0:d92f9d21154c 4412 if (ctx == NULL || info == 0 || sz < 0)
wolfSSL 0:d92f9d21154c 4413 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4414
wolfSSL 0:d92f9d21154c 4415 ctx->kdfInfo = info;
wolfSSL 0:d92f9d21154c 4416 ctx->kdfInfoSz = sz;
wolfSSL 0:d92f9d21154c 4417
wolfSSL 0:d92f9d21154c 4418 return 0;
wolfSSL 0:d92f9d21154c 4419 }
wolfSSL 0:d92f9d21154c 4420
wolfSSL 0:d92f9d21154c 4421
wolfSSL 0:d92f9d21154c 4422 static const char* exchange_info = "Secure Message Exchange";
wolfSSL 0:d92f9d21154c 4423
wolfSSL 0:d92f9d21154c 4424 int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt)
wolfSSL 0:d92f9d21154c 4425 {
wolfSSL 0:d92f9d21154c 4426 byte tmp[EXCHANGE_SALT_SZ/2];
wolfSSL 0:d92f9d21154c 4427 int halfSz = EXCHANGE_SALT_SZ/2;
wolfSSL 0:d92f9d21154c 4428
wolfSSL 0:d92f9d21154c 4429 if (ctx == NULL || ctx->protocol == 0 || salt == NULL)
wolfSSL 0:d92f9d21154c 4430 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4431
wolfSSL 0:d92f9d21154c 4432 if (ctx->protocol == REQ_RESP_CLIENT) {
wolfSSL 0:d92f9d21154c 4433 XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ);
wolfSSL 0:d92f9d21154c 4434 if (ctx->cliSt == ecCLI_SALT_GET)
wolfSSL 0:d92f9d21154c 4435 ctx->cliSt = ecCLI_SALT_SET;
wolfSSL 0:d92f9d21154c 4436 else {
wolfSSL 0:d92f9d21154c 4437 ctx->cliSt = ecCLI_BAD_STATE;
wolfSSL 0:d92f9d21154c 4438 return BAD_ENC_STATE_E;
wolfSSL 0:d92f9d21154c 4439 }
wolfSSL 0:d92f9d21154c 4440 }
wolfSSL 0:d92f9d21154c 4441 else {
wolfSSL 0:d92f9d21154c 4442 XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ);
wolfSSL 0:d92f9d21154c 4443 if (ctx->srvSt == ecSRV_SALT_GET)
wolfSSL 0:d92f9d21154c 4444 ctx->srvSt = ecSRV_SALT_SET;
wolfSSL 0:d92f9d21154c 4445 else {
wolfSSL 0:d92f9d21154c 4446 ctx->srvSt = ecSRV_BAD_STATE;
wolfSSL 0:d92f9d21154c 4447 return BAD_ENC_STATE_E;
wolfSSL 0:d92f9d21154c 4448 }
wolfSSL 0:d92f9d21154c 4449 }
wolfSSL 0:d92f9d21154c 4450
wolfSSL 0:d92f9d21154c 4451 /* mix half and half */
wolfSSL 0:d92f9d21154c 4452 /* tmp stores 2nd half of client before overwrite */
wolfSSL 0:d92f9d21154c 4453 XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz);
wolfSSL 0:d92f9d21154c 4454 XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz);
wolfSSL 0:d92f9d21154c 4455 XMEMCPY(ctx->serverSalt, tmp, halfSz);
wolfSSL 0:d92f9d21154c 4456
wolfSSL 0:d92f9d21154c 4457 ctx->kdfSalt = ctx->clientSalt;
wolfSSL 0:d92f9d21154c 4458 ctx->kdfSaltSz = EXCHANGE_SALT_SZ;
wolfSSL 0:d92f9d21154c 4459
wolfSSL 0:d92f9d21154c 4460 ctx->macSalt = ctx->serverSalt;
wolfSSL 0:d92f9d21154c 4461 ctx->macSaltSz = EXCHANGE_SALT_SZ;
wolfSSL 0:d92f9d21154c 4462
wolfSSL 0:d92f9d21154c 4463 if (ctx->kdfInfo == NULL) {
wolfSSL 0:d92f9d21154c 4464 /* default info */
wolfSSL 0:d92f9d21154c 4465 ctx->kdfInfo = (const byte*)exchange_info;
wolfSSL 0:d92f9d21154c 4466 ctx->kdfInfoSz = EXCHANGE_INFO_SZ;
wolfSSL 0:d92f9d21154c 4467 }
wolfSSL 0:d92f9d21154c 4468
wolfSSL 0:d92f9d21154c 4469 return 0;
wolfSSL 0:d92f9d21154c 4470 }
wolfSSL 0:d92f9d21154c 4471
wolfSSL 0:d92f9d21154c 4472
wolfSSL 0:d92f9d21154c 4473 static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, RNG* rng)
wolfSSL 0:d92f9d21154c 4474 {
wolfSSL 0:d92f9d21154c 4475 byte* saltBuffer = NULL;
wolfSSL 0:d92f9d21154c 4476
wolfSSL 0:d92f9d21154c 4477 if (ctx == NULL || rng == NULL || flags == 0)
wolfSSL 0:d92f9d21154c 4478 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4479
wolfSSL 0:d92f9d21154c 4480 saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt;
wolfSSL 0:d92f9d21154c 4481
wolfSSL 0:d92f9d21154c 4482 return wc_RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ);
wolfSSL 0:d92f9d21154c 4483 }
wolfSSL 0:d92f9d21154c 4484
wolfSSL 0:d92f9d21154c 4485
wolfSSL 0:d92f9d21154c 4486 static void ecc_ctx_init(ecEncCtx* ctx, int flags)
wolfSSL 0:d92f9d21154c 4487 {
wolfSSL 0:d92f9d21154c 4488 if (ctx) {
wolfSSL 0:d92f9d21154c 4489 XMEMSET(ctx, 0, sizeof(ecEncCtx));
wolfSSL 0:d92f9d21154c 4490
wolfSSL 0:d92f9d21154c 4491 ctx->encAlgo = ecAES_128_CBC;
wolfSSL 0:d92f9d21154c 4492 ctx->kdfAlgo = ecHKDF_SHA256;
wolfSSL 0:d92f9d21154c 4493 ctx->macAlgo = ecHMAC_SHA256;
wolfSSL 0:d92f9d21154c 4494 ctx->protocol = (byte)flags;
wolfSSL 0:d92f9d21154c 4495
wolfSSL 0:d92f9d21154c 4496 if (flags == REQ_RESP_CLIENT)
wolfSSL 0:d92f9d21154c 4497 ctx->cliSt = ecCLI_INIT;
wolfSSL 0:d92f9d21154c 4498 if (flags == REQ_RESP_SERVER)
wolfSSL 0:d92f9d21154c 4499 ctx->srvSt = ecSRV_INIT;
wolfSSL 0:d92f9d21154c 4500 }
wolfSSL 0:d92f9d21154c 4501 }
wolfSSL 0:d92f9d21154c 4502
wolfSSL 0:d92f9d21154c 4503
wolfSSL 0:d92f9d21154c 4504 /* allow ecc context reset so user doesn't have to init/free for resue */
wolfSSL 0:d92f9d21154c 4505 int wc_ecc_ctx_reset(ecEncCtx* ctx, RNG* rng)
wolfSSL 0:d92f9d21154c 4506 {
wolfSSL 0:d92f9d21154c 4507 if (ctx == NULL || rng == NULL)
wolfSSL 0:d92f9d21154c 4508 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4509
wolfSSL 0:d92f9d21154c 4510 ecc_ctx_init(ctx, ctx->protocol);
wolfSSL 0:d92f9d21154c 4511 return ecc_ctx_set_salt(ctx, ctx->protocol, rng);
wolfSSL 0:d92f9d21154c 4512 }
wolfSSL 0:d92f9d21154c 4513
wolfSSL 0:d92f9d21154c 4514
wolfSSL 0:d92f9d21154c 4515 /* alloc/init and set defaults, return new Context */
wolfSSL 0:d92f9d21154c 4516 ecEncCtx* wc_ecc_ctx_new(int flags, RNG* rng)
wolfSSL 0:d92f9d21154c 4517 {
wolfSSL 0:d92f9d21154c 4518 int ret = 0;
wolfSSL 0:d92f9d21154c 4519 ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), 0, DYNAMIC_TYPE_ECC);
wolfSSL 0:d92f9d21154c 4520
wolfSSL 0:d92f9d21154c 4521 if (ctx)
wolfSSL 0:d92f9d21154c 4522 ctx->protocol = (byte)flags;
wolfSSL 0:d92f9d21154c 4523
wolfSSL 0:d92f9d21154c 4524 ret = wc_ecc_ctx_reset(ctx, rng);
wolfSSL 0:d92f9d21154c 4525 if (ret != 0) {
wolfSSL 0:d92f9d21154c 4526 wc_ecc_ctx_free(ctx);
wolfSSL 0:d92f9d21154c 4527 ctx = NULL;
wolfSSL 0:d92f9d21154c 4528 }
wolfSSL 0:d92f9d21154c 4529
wolfSSL 0:d92f9d21154c 4530 return ctx;
wolfSSL 0:d92f9d21154c 4531 }
wolfSSL 0:d92f9d21154c 4532
wolfSSL 0:d92f9d21154c 4533
wolfSSL 0:d92f9d21154c 4534 /* free any resources, clear any keys */
wolfSSL 0:d92f9d21154c 4535 void wc_ecc_ctx_free(ecEncCtx* ctx)
wolfSSL 0:d92f9d21154c 4536 {
wolfSSL 0:d92f9d21154c 4537 if (ctx) {
wolfSSL 0:d92f9d21154c 4538 ForceZero(ctx, sizeof(ecEncCtx));
wolfSSL 0:d92f9d21154c 4539 XFREE(ctx, 0, DYNAMIC_TYPE_ECC);
wolfSSL 0:d92f9d21154c 4540 }
wolfSSL 0:d92f9d21154c 4541 }
wolfSSL 0:d92f9d21154c 4542
wolfSSL 0:d92f9d21154c 4543
wolfSSL 0:d92f9d21154c 4544 static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
wolfSSL 0:d92f9d21154c 4545 int* keysLen, word32* digestSz, word32* blockSz)
wolfSSL 0:d92f9d21154c 4546 {
wolfSSL 0:d92f9d21154c 4547 if (ctx) {
wolfSSL 0:d92f9d21154c 4548 switch (ctx->encAlgo) {
wolfSSL 0:d92f9d21154c 4549 case ecAES_128_CBC:
wolfSSL 0:d92f9d21154c 4550 *encKeySz = KEY_SIZE_128;
wolfSSL 0:d92f9d21154c 4551 *ivSz = IV_SIZE_64;
wolfSSL 0:d92f9d21154c 4552 *blockSz = AES_BLOCK_SIZE;
wolfSSL 0:d92f9d21154c 4553 break;
wolfSSL 0:d92f9d21154c 4554 default:
wolfSSL 0:d92f9d21154c 4555 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4556 }
wolfSSL 0:d92f9d21154c 4557
wolfSSL 0:d92f9d21154c 4558 switch (ctx->macAlgo) {
wolfSSL 0:d92f9d21154c 4559 case ecHMAC_SHA256:
wolfSSL 0:d92f9d21154c 4560 *digestSz = SHA256_DIGEST_SIZE;
wolfSSL 0:d92f9d21154c 4561 break;
wolfSSL 0:d92f9d21154c 4562 default:
wolfSSL 0:d92f9d21154c 4563 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4564 }
wolfSSL 0:d92f9d21154c 4565 } else
wolfSSL 0:d92f9d21154c 4566 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4567
wolfSSL 0:d92f9d21154c 4568 *keysLen = *encKeySz + *ivSz + *digestSz;
wolfSSL 0:d92f9d21154c 4569
wolfSSL 0:d92f9d21154c 4570 return 0;
wolfSSL 0:d92f9d21154c 4571 }
wolfSSL 0:d92f9d21154c 4572
wolfSSL 0:d92f9d21154c 4573
wolfSSL 0:d92f9d21154c 4574 /* ecc encrypt with shared secret run through kdf
wolfSSL 0:d92f9d21154c 4575 ctx holds non default algos and inputs
wolfSSL 0:d92f9d21154c 4576 msgSz should be the right size for encAlgo, i.e., already padded
wolfSSL 0:d92f9d21154c 4577 return 0 on success */
wolfSSL 0:d92f9d21154c 4578 int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
wolfSSL 0:d92f9d21154c 4579 word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
wolfSSL 0:d92f9d21154c 4580 {
wolfSSL 0:d92f9d21154c 4581 int ret;
wolfSSL 0:d92f9d21154c 4582 word32 blockSz;
wolfSSL 0:d92f9d21154c 4583 word32 digestSz;
wolfSSL 0:d92f9d21154c 4584 ecEncCtx localCtx;
wolfSSL 0:d92f9d21154c 4585 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4586 byte* sharedSecret;
wolfSSL 0:d92f9d21154c 4587 byte* keys;
wolfSSL 0:d92f9d21154c 4588 #else
wolfSSL 0:d92f9d21154c 4589 byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
wolfSSL 0:d92f9d21154c 4590 byte keys[ECC_BUFSIZE]; /* max size */
wolfSSL 0:d92f9d21154c 4591 #endif
wolfSSL 0:d92f9d21154c 4592 word32 sharedSz = ECC_MAXSIZE;
wolfSSL 0:d92f9d21154c 4593 int keysLen;
wolfSSL 0:d92f9d21154c 4594 int encKeySz;
wolfSSL 0:d92f9d21154c 4595 int ivSz;
wolfSSL 0:d92f9d21154c 4596 int offset = 0; /* keys offset if doing msg exchange */
wolfSSL 0:d92f9d21154c 4597 byte* encKey;
wolfSSL 0:d92f9d21154c 4598 byte* encIv;
wolfSSL 0:d92f9d21154c 4599 byte* macKey;
wolfSSL 0:d92f9d21154c 4600
wolfSSL 0:d92f9d21154c 4601 if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
wolfSSL 0:d92f9d21154c 4602 outSz == NULL)
wolfSSL 0:d92f9d21154c 4603 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4604
wolfSSL 0:d92f9d21154c 4605 if (ctx == NULL) { /* use defaults */
wolfSSL 0:d92f9d21154c 4606 ecc_ctx_init(&localCtx, 0);
wolfSSL 0:d92f9d21154c 4607 ctx = &localCtx;
wolfSSL 0:d92f9d21154c 4608 }
wolfSSL 0:d92f9d21154c 4609
wolfSSL 0:d92f9d21154c 4610 ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
wolfSSL 0:d92f9d21154c 4611 &blockSz);
wolfSSL 0:d92f9d21154c 4612 if (ret != 0)
wolfSSL 0:d92f9d21154c 4613 return ret;
wolfSSL 0:d92f9d21154c 4614
wolfSSL 0:d92f9d21154c 4615 if (ctx->protocol == REQ_RESP_SERVER) {
wolfSSL 0:d92f9d21154c 4616 offset = keysLen;
wolfSSL 0:d92f9d21154c 4617 keysLen *= 2;
wolfSSL 0:d92f9d21154c 4618
wolfSSL 0:d92f9d21154c 4619 if (ctx->srvSt != ecSRV_RECV_REQ)
wolfSSL 0:d92f9d21154c 4620 return BAD_ENC_STATE_E;
wolfSSL 0:d92f9d21154c 4621
wolfSSL 0:d92f9d21154c 4622 ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
wolfSSL 0:d92f9d21154c 4623 }
wolfSSL 0:d92f9d21154c 4624 else if (ctx->protocol == REQ_RESP_CLIENT) {
wolfSSL 0:d92f9d21154c 4625 if (ctx->cliSt != ecCLI_SALT_SET)
wolfSSL 0:d92f9d21154c 4626 return BAD_ENC_STATE_E;
wolfSSL 0:d92f9d21154c 4627
wolfSSL 0:d92f9d21154c 4628 ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
wolfSSL 0:d92f9d21154c 4629 }
wolfSSL 0:d92f9d21154c 4630
wolfSSL 0:d92f9d21154c 4631 if (keysLen > ECC_BUFSIZE) /* keys size */
wolfSSL 0:d92f9d21154c 4632 return BUFFER_E;
wolfSSL 0:d92f9d21154c 4633
wolfSSL 0:d92f9d21154c 4634 if ( (msgSz%blockSz) != 0)
wolfSSL 0:d92f9d21154c 4635 return BAD_PADDING_E;
wolfSSL 0:d92f9d21154c 4636
wolfSSL 0:d92f9d21154c 4637 if (*outSz < (msgSz + digestSz))
wolfSSL 0:d92f9d21154c 4638 return BUFFER_E;
wolfSSL 0:d92f9d21154c 4639
wolfSSL 0:d92f9d21154c 4640 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4641 sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4642 if (sharedSecret == NULL)
wolfSSL 0:d92f9d21154c 4643 return MEMORY_E;
wolfSSL 0:d92f9d21154c 4644
wolfSSL 0:d92f9d21154c 4645 keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4646 if (keys == NULL) {
wolfSSL 0:d92f9d21154c 4647 XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4648 return MEMORY_E;
wolfSSL 0:d92f9d21154c 4649 }
wolfSSL 0:d92f9d21154c 4650 #endif
wolfSSL 0:d92f9d21154c 4651
wolfSSL 0:d92f9d21154c 4652 ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
wolfSSL 0:d92f9d21154c 4653
wolfSSL 0:d92f9d21154c 4654 if (ret == 0) {
wolfSSL 0:d92f9d21154c 4655 switch (ctx->kdfAlgo) {
wolfSSL 0:d92f9d21154c 4656 case ecHKDF_SHA256 :
wolfSSL 0:d92f9d21154c 4657 ret = wc_HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
wolfSSL 0:d92f9d21154c 4658 ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
wolfSSL 0:d92f9d21154c 4659 keys, keysLen);
wolfSSL 0:d92f9d21154c 4660 break;
wolfSSL 0:d92f9d21154c 4661
wolfSSL 0:d92f9d21154c 4662 default:
wolfSSL 0:d92f9d21154c 4663 ret = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4664 break;
wolfSSL 0:d92f9d21154c 4665 }
wolfSSL 0:d92f9d21154c 4666 }
wolfSSL 0:d92f9d21154c 4667
wolfSSL 0:d92f9d21154c 4668 if (ret == 0) {
wolfSSL 0:d92f9d21154c 4669 encKey = keys + offset;
wolfSSL 0:d92f9d21154c 4670 encIv = encKey + encKeySz;
wolfSSL 0:d92f9d21154c 4671 macKey = encKey + encKeySz + ivSz;
wolfSSL 0:d92f9d21154c 4672
wolfSSL 0:d92f9d21154c 4673 switch (ctx->encAlgo) {
wolfSSL 0:d92f9d21154c 4674 case ecAES_128_CBC:
wolfSSL 0:d92f9d21154c 4675 {
wolfSSL 0:d92f9d21154c 4676 Aes aes;
wolfSSL 0:d92f9d21154c 4677 ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
wolfSSL 0:d92f9d21154c 4678 AES_ENCRYPTION);
wolfSSL 0:d92f9d21154c 4679 if (ret != 0)
wolfSSL 0:d92f9d21154c 4680 break;
wolfSSL 0:d92f9d21154c 4681 ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz);
wolfSSL 0:d92f9d21154c 4682 }
wolfSSL 0:d92f9d21154c 4683 break;
wolfSSL 0:d92f9d21154c 4684
wolfSSL 0:d92f9d21154c 4685 default:
wolfSSL 0:d92f9d21154c 4686 ret = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4687 break;
wolfSSL 0:d92f9d21154c 4688 }
wolfSSL 0:d92f9d21154c 4689 }
wolfSSL 0:d92f9d21154c 4690
wolfSSL 0:d92f9d21154c 4691 if (ret == 0) {
wolfSSL 0:d92f9d21154c 4692 switch (ctx->macAlgo) {
wolfSSL 0:d92f9d21154c 4693 case ecHMAC_SHA256:
wolfSSL 0:d92f9d21154c 4694 {
wolfSSL 0:d92f9d21154c 4695 Hmac hmac;
wolfSSL 0:d92f9d21154c 4696 ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
wolfSSL 0:d92f9d21154c 4697 if (ret != 0)
wolfSSL 0:d92f9d21154c 4698 break;
wolfSSL 0:d92f9d21154c 4699 ret = wc_HmacUpdate(&hmac, out, msgSz);
wolfSSL 0:d92f9d21154c 4700 if (ret != 0)
wolfSSL 0:d92f9d21154c 4701 break;
wolfSSL 0:d92f9d21154c 4702 ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
wolfSSL 0:d92f9d21154c 4703 if (ret != 0)
wolfSSL 0:d92f9d21154c 4704 break;
wolfSSL 0:d92f9d21154c 4705 ret = wc_HmacFinal(&hmac, out+msgSz);
wolfSSL 0:d92f9d21154c 4706 }
wolfSSL 0:d92f9d21154c 4707 break;
wolfSSL 0:d92f9d21154c 4708
wolfSSL 0:d92f9d21154c 4709 default:
wolfSSL 0:d92f9d21154c 4710 ret = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4711 break;
wolfSSL 0:d92f9d21154c 4712 }
wolfSSL 0:d92f9d21154c 4713 }
wolfSSL 0:d92f9d21154c 4714
wolfSSL 0:d92f9d21154c 4715 if (ret == 0)
wolfSSL 0:d92f9d21154c 4716 *outSz = msgSz + digestSz;
wolfSSL 0:d92f9d21154c 4717
wolfSSL 0:d92f9d21154c 4718 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4719 XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4720 XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4721 #endif
wolfSSL 0:d92f9d21154c 4722
wolfSSL 0:d92f9d21154c 4723 return ret;
wolfSSL 0:d92f9d21154c 4724 }
wolfSSL 0:d92f9d21154c 4725
wolfSSL 0:d92f9d21154c 4726
wolfSSL 0:d92f9d21154c 4727 /* ecc decrypt with shared secret run through kdf
wolfSSL 0:d92f9d21154c 4728 ctx holds non default algos and inputs
wolfSSL 0:d92f9d21154c 4729 return 0 on success */
wolfSSL 0:d92f9d21154c 4730 int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
wolfSSL 0:d92f9d21154c 4731 word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
wolfSSL 0:d92f9d21154c 4732 {
wolfSSL 0:d92f9d21154c 4733 int ret;
wolfSSL 0:d92f9d21154c 4734 word32 blockSz;
wolfSSL 0:d92f9d21154c 4735 word32 digestSz;
wolfSSL 0:d92f9d21154c 4736 ecEncCtx localCtx;
wolfSSL 0:d92f9d21154c 4737 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4738 byte* sharedSecret;
wolfSSL 0:d92f9d21154c 4739 byte* keys;
wolfSSL 0:d92f9d21154c 4740 #else
wolfSSL 0:d92f9d21154c 4741 byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
wolfSSL 0:d92f9d21154c 4742 byte keys[ECC_BUFSIZE]; /* max size */
wolfSSL 0:d92f9d21154c 4743 #endif
wolfSSL 0:d92f9d21154c 4744 word32 sharedSz = ECC_MAXSIZE;
wolfSSL 0:d92f9d21154c 4745 int keysLen;
wolfSSL 0:d92f9d21154c 4746 int encKeySz;
wolfSSL 0:d92f9d21154c 4747 int ivSz;
wolfSSL 0:d92f9d21154c 4748 int offset = 0; /* in case using msg exchange */
wolfSSL 0:d92f9d21154c 4749 byte* encKey;
wolfSSL 0:d92f9d21154c 4750 byte* encIv;
wolfSSL 0:d92f9d21154c 4751 byte* macKey;
wolfSSL 0:d92f9d21154c 4752
wolfSSL 0:d92f9d21154c 4753 if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
wolfSSL 0:d92f9d21154c 4754 outSz == NULL)
wolfSSL 0:d92f9d21154c 4755 return BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4756
wolfSSL 0:d92f9d21154c 4757 if (ctx == NULL) { /* use defaults */
wolfSSL 0:d92f9d21154c 4758 ecc_ctx_init(&localCtx, 0);
wolfSSL 0:d92f9d21154c 4759 ctx = &localCtx;
wolfSSL 0:d92f9d21154c 4760 }
wolfSSL 0:d92f9d21154c 4761
wolfSSL 0:d92f9d21154c 4762 ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
wolfSSL 0:d92f9d21154c 4763 &blockSz);
wolfSSL 0:d92f9d21154c 4764 if (ret != 0)
wolfSSL 0:d92f9d21154c 4765 return ret;
wolfSSL 0:d92f9d21154c 4766
wolfSSL 0:d92f9d21154c 4767 if (ctx->protocol == REQ_RESP_CLIENT) {
wolfSSL 0:d92f9d21154c 4768 offset = keysLen;
wolfSSL 0:d92f9d21154c 4769 keysLen *= 2;
wolfSSL 0:d92f9d21154c 4770
wolfSSL 0:d92f9d21154c 4771 if (ctx->cliSt != ecCLI_SENT_REQ)
wolfSSL 0:d92f9d21154c 4772 return BAD_ENC_STATE_E;
wolfSSL 0:d92f9d21154c 4773
wolfSSL 0:d92f9d21154c 4774 ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
wolfSSL 0:d92f9d21154c 4775 }
wolfSSL 0:d92f9d21154c 4776 else if (ctx->protocol == REQ_RESP_SERVER) {
wolfSSL 0:d92f9d21154c 4777 if (ctx->srvSt != ecSRV_SALT_SET)
wolfSSL 0:d92f9d21154c 4778 return BAD_ENC_STATE_E;
wolfSSL 0:d92f9d21154c 4779
wolfSSL 0:d92f9d21154c 4780 ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
wolfSSL 0:d92f9d21154c 4781 }
wolfSSL 0:d92f9d21154c 4782
wolfSSL 0:d92f9d21154c 4783 if (keysLen > ECC_BUFSIZE) /* keys size */
wolfSSL 0:d92f9d21154c 4784 return BUFFER_E;
wolfSSL 0:d92f9d21154c 4785
wolfSSL 0:d92f9d21154c 4786 if ( ((msgSz-digestSz) % blockSz) != 0)
wolfSSL 0:d92f9d21154c 4787 return BAD_PADDING_E;
wolfSSL 0:d92f9d21154c 4788
wolfSSL 0:d92f9d21154c 4789 if (*outSz < (msgSz - digestSz))
wolfSSL 0:d92f9d21154c 4790 return BUFFER_E;
wolfSSL 0:d92f9d21154c 4791
wolfSSL 0:d92f9d21154c 4792 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4793 sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4794 if (sharedSecret == NULL)
wolfSSL 0:d92f9d21154c 4795 return MEMORY_E;
wolfSSL 0:d92f9d21154c 4796
wolfSSL 0:d92f9d21154c 4797 keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4798 if (keys == NULL) {
wolfSSL 0:d92f9d21154c 4799 XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4800 return MEMORY_E;
wolfSSL 0:d92f9d21154c 4801 }
wolfSSL 0:d92f9d21154c 4802 #endif
wolfSSL 0:d92f9d21154c 4803
wolfSSL 0:d92f9d21154c 4804 ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
wolfSSL 0:d92f9d21154c 4805
wolfSSL 0:d92f9d21154c 4806 if (ret == 0) {
wolfSSL 0:d92f9d21154c 4807 switch (ctx->kdfAlgo) {
wolfSSL 0:d92f9d21154c 4808 case ecHKDF_SHA256 :
wolfSSL 0:d92f9d21154c 4809 ret = wc_HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
wolfSSL 0:d92f9d21154c 4810 ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
wolfSSL 0:d92f9d21154c 4811 keys, keysLen);
wolfSSL 0:d92f9d21154c 4812 break;
wolfSSL 0:d92f9d21154c 4813
wolfSSL 0:d92f9d21154c 4814 default:
wolfSSL 0:d92f9d21154c 4815 ret = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4816 break;
wolfSSL 0:d92f9d21154c 4817 }
wolfSSL 0:d92f9d21154c 4818 }
wolfSSL 0:d92f9d21154c 4819
wolfSSL 0:d92f9d21154c 4820 if (ret == 0) {
wolfSSL 0:d92f9d21154c 4821 encKey = keys + offset;
wolfSSL 0:d92f9d21154c 4822 encIv = encKey + encKeySz;
wolfSSL 0:d92f9d21154c 4823 macKey = encKey + encKeySz + ivSz;
wolfSSL 0:d92f9d21154c 4824
wolfSSL 0:d92f9d21154c 4825 switch (ctx->macAlgo) {
wolfSSL 0:d92f9d21154c 4826 case ecHMAC_SHA256:
wolfSSL 0:d92f9d21154c 4827 {
wolfSSL 0:d92f9d21154c 4828 byte verify[SHA256_DIGEST_SIZE];
wolfSSL 0:d92f9d21154c 4829 Hmac hmac;
wolfSSL 0:d92f9d21154c 4830 ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
wolfSSL 0:d92f9d21154c 4831 if (ret != 0)
wolfSSL 0:d92f9d21154c 4832 break;
wolfSSL 0:d92f9d21154c 4833 ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz);
wolfSSL 0:d92f9d21154c 4834 if (ret != 0)
wolfSSL 0:d92f9d21154c 4835 break;
wolfSSL 0:d92f9d21154c 4836 ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
wolfSSL 0:d92f9d21154c 4837 if (ret != 0)
wolfSSL 0:d92f9d21154c 4838 break;
wolfSSL 0:d92f9d21154c 4839 ret = wc_HmacFinal(&hmac, verify);
wolfSSL 0:d92f9d21154c 4840 if (ret != 0)
wolfSSL 0:d92f9d21154c 4841 break;
wolfSSL 0:d92f9d21154c 4842 if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0)
wolfSSL 0:d92f9d21154c 4843 ret = -1;
wolfSSL 0:d92f9d21154c 4844 }
wolfSSL 0:d92f9d21154c 4845 break;
wolfSSL 0:d92f9d21154c 4846
wolfSSL 0:d92f9d21154c 4847 default:
wolfSSL 0:d92f9d21154c 4848 ret = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4849 break;
wolfSSL 0:d92f9d21154c 4850 }
wolfSSL 0:d92f9d21154c 4851 }
wolfSSL 0:d92f9d21154c 4852
wolfSSL 0:d92f9d21154c 4853 if (ret == 0) {
wolfSSL 0:d92f9d21154c 4854 switch (ctx->encAlgo) {
wolfSSL 0:d92f9d21154c 4855 case ecAES_128_CBC:
wolfSSL 0:d92f9d21154c 4856 {
wolfSSL 0:d92f9d21154c 4857 Aes aes;
wolfSSL 0:d92f9d21154c 4858 ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
wolfSSL 0:d92f9d21154c 4859 AES_DECRYPTION);
wolfSSL 0:d92f9d21154c 4860 if (ret != 0)
wolfSSL 0:d92f9d21154c 4861 break;
wolfSSL 0:d92f9d21154c 4862 ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
wolfSSL 0:d92f9d21154c 4863 }
wolfSSL 0:d92f9d21154c 4864 break;
wolfSSL 0:d92f9d21154c 4865
wolfSSL 0:d92f9d21154c 4866 default:
wolfSSL 0:d92f9d21154c 4867 ret = BAD_FUNC_ARG;
wolfSSL 0:d92f9d21154c 4868 break;
wolfSSL 0:d92f9d21154c 4869 }
wolfSSL 0:d92f9d21154c 4870 }
wolfSSL 0:d92f9d21154c 4871
wolfSSL 0:d92f9d21154c 4872 if (ret == 0)
wolfSSL 0:d92f9d21154c 4873 *outSz = msgSz - digestSz;
wolfSSL 0:d92f9d21154c 4874
wolfSSL 0:d92f9d21154c 4875 #ifdef WOLFSSL_SMALL_STACK
wolfSSL 0:d92f9d21154c 4876 XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4877 XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
wolfSSL 0:d92f9d21154c 4878 #endif
wolfSSL 0:d92f9d21154c 4879
wolfSSL 0:d92f9d21154c 4880 return ret;
wolfSSL 0:d92f9d21154c 4881 }
wolfSSL 0:d92f9d21154c 4882
wolfSSL 0:d92f9d21154c 4883
wolfSSL 0:d92f9d21154c 4884 #endif /* HAVE_ECC_ENCRYPT */
wolfSSL 0:d92f9d21154c 4885
wolfSSL 0:d92f9d21154c 4886
wolfSSL 0:d92f9d21154c 4887 #ifdef HAVE_COMP_KEY
wolfSSL 0:d92f9d21154c 4888
wolfSSL 0:d92f9d21154c 4889 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
wolfSSL 0:d92f9d21154c 4890 * HAC pp. 73 Algorithm 2.149
wolfSSL 0:d92f9d21154c 4891 */
wolfSSL 0:d92f9d21154c 4892 int mp_jacobi(mp_int* a, mp_int* p, int* c)
wolfSSL 0:d92f9d21154c 4893 {
wolfSSL 0:d92f9d21154c 4894 mp_int a1, p1;
wolfSSL 0:d92f9d21154c 4895 int k, s, r, res;
wolfSSL 0:d92f9d21154c 4896 mp_digit residue;
wolfSSL 0:d92f9d21154c 4897
wolfSSL 0:d92f9d21154c 4898 /* if p <= 0 return MP_VAL */
wolfSSL 0:d92f9d21154c 4899 if (mp_cmp_d(p, 0) != MP_GT) {
wolfSSL 0:d92f9d21154c 4900 return MP_VAL;
wolfSSL 0:d92f9d21154c 4901 }
wolfSSL 0:d92f9d21154c 4902
wolfSSL 0:d92f9d21154c 4903 /* step 1. if a == 0, return 0 */
wolfSSL 0:d92f9d21154c 4904 if (mp_iszero (a) == 1) {
wolfSSL 0:d92f9d21154c 4905 *c = 0;
wolfSSL 0:d92f9d21154c 4906 return MP_OKAY;
wolfSSL 0:d92f9d21154c 4907 }
wolfSSL 0:d92f9d21154c 4908
wolfSSL 0:d92f9d21154c 4909 /* step 2. if a == 1, return 1 */
wolfSSL 0:d92f9d21154c 4910 if (mp_cmp_d (a, 1) == MP_EQ) {
wolfSSL 0:d92f9d21154c 4911 *c = 1;
wolfSSL 0:d92f9d21154c 4912 return MP_OKAY;
wolfSSL 0:d92f9d21154c 4913 }
wolfSSL 0:d92f9d21154c 4914
wolfSSL 0:d92f9d21154c 4915 /* default */
wolfSSL 0:d92f9d21154c 4916 s = 0;
wolfSSL 0:d92f9d21154c 4917
wolfSSL 0:d92f9d21154c 4918 /* step 3. write a = a1 * 2**k */
wolfSSL 0:d92f9d21154c 4919 if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 4920 return res;
wolfSSL 0:d92f9d21154c 4921 }
wolfSSL 0:d92f9d21154c 4922
wolfSSL 0:d92f9d21154c 4923 if ((res = mp_init (&p1)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 4924 mp_clear(&a1);
wolfSSL 0:d92f9d21154c 4925 return res;
wolfSSL 0:d92f9d21154c 4926 }
wolfSSL 0:d92f9d21154c 4927
wolfSSL 0:d92f9d21154c 4928 /* divide out larger power of two */
wolfSSL 0:d92f9d21154c 4929 k = mp_cnt_lsb(&a1);
wolfSSL 0:d92f9d21154c 4930 res = mp_div_2d(&a1, k, &a1, NULL);
wolfSSL 0:d92f9d21154c 4931
wolfSSL 0:d92f9d21154c 4932 if (res == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4933 /* step 4. if e is even set s=1 */
wolfSSL 0:d92f9d21154c 4934 if ((k & 1) == 0) {
wolfSSL 0:d92f9d21154c 4935 s = 1;
wolfSSL 0:d92f9d21154c 4936 } else {
wolfSSL 0:d92f9d21154c 4937 /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
wolfSSL 0:d92f9d21154c 4938 residue = p->dp[0] & 7;
wolfSSL 0:d92f9d21154c 4939
wolfSSL 0:d92f9d21154c 4940 if (residue == 1 || residue == 7) {
wolfSSL 0:d92f9d21154c 4941 s = 1;
wolfSSL 0:d92f9d21154c 4942 } else if (residue == 3 || residue == 5) {
wolfSSL 0:d92f9d21154c 4943 s = -1;
wolfSSL 0:d92f9d21154c 4944 }
wolfSSL 0:d92f9d21154c 4945 }
wolfSSL 0:d92f9d21154c 4946
wolfSSL 0:d92f9d21154c 4947 /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
wolfSSL 0:d92f9d21154c 4948 if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
wolfSSL 0:d92f9d21154c 4949 s = -s;
wolfSSL 0:d92f9d21154c 4950 }
wolfSSL 0:d92f9d21154c 4951 }
wolfSSL 0:d92f9d21154c 4952
wolfSSL 0:d92f9d21154c 4953 if (res == MP_OKAY) {
wolfSSL 0:d92f9d21154c 4954 /* if a1 == 1 we're done */
wolfSSL 0:d92f9d21154c 4955 if (mp_cmp_d (&a1, 1) == MP_EQ) {
wolfSSL 0:d92f9d21154c 4956 *c = s;
wolfSSL 0:d92f9d21154c 4957 } else {
wolfSSL 0:d92f9d21154c 4958 /* n1 = n mod a1 */
wolfSSL 0:d92f9d21154c 4959 res = mp_mod (p, &a1, &p1);
wolfSSL 0:d92f9d21154c 4960 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 4961 res = mp_jacobi (&p1, &a1, &r);
wolfSSL 0:d92f9d21154c 4962
wolfSSL 0:d92f9d21154c 4963 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 4964 *c = s * r;
wolfSSL 0:d92f9d21154c 4965 }
wolfSSL 0:d92f9d21154c 4966 }
wolfSSL 0:d92f9d21154c 4967
wolfSSL 0:d92f9d21154c 4968 /* done */
wolfSSL 0:d92f9d21154c 4969 mp_clear (&p1);
wolfSSL 0:d92f9d21154c 4970 mp_clear (&a1);
wolfSSL 0:d92f9d21154c 4971
wolfSSL 0:d92f9d21154c 4972 return res;
wolfSSL 0:d92f9d21154c 4973 }
wolfSSL 0:d92f9d21154c 4974
wolfSSL 0:d92f9d21154c 4975
wolfSSL 0:d92f9d21154c 4976 int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
wolfSSL 0:d92f9d21154c 4977 {
wolfSSL 0:d92f9d21154c 4978 int res, legendre, done = 0;
wolfSSL 0:d92f9d21154c 4979 mp_int t1, C, Q, S, Z, M, T, R, two;
wolfSSL 0:d92f9d21154c 4980 mp_digit i;
wolfSSL 0:d92f9d21154c 4981
wolfSSL 0:d92f9d21154c 4982 /* first handle the simple cases */
wolfSSL 0:d92f9d21154c 4983 if (mp_cmp_d(n, 0) == MP_EQ) {
wolfSSL 0:d92f9d21154c 4984 mp_zero(ret);
wolfSSL 0:d92f9d21154c 4985 return MP_OKAY;
wolfSSL 0:d92f9d21154c 4986 }
wolfSSL 0:d92f9d21154c 4987 if (mp_cmp_d(prime, 2) == MP_EQ) return MP_VAL; /* prime must be odd */
wolfSSL 0:d92f9d21154c 4988 /* TAO removed
wolfSSL 0:d92f9d21154c 4989 if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) return res;
wolfSSL 0:d92f9d21154c 4990 if (legendre == -1) return MP_VAL; */ /* quadratic non-residue mod prime */
wolfSSL 0:d92f9d21154c 4991
wolfSSL 0:d92f9d21154c 4992 if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY)
wolfSSL 0:d92f9d21154c 4993 return res;
wolfSSL 0:d92f9d21154c 4994
wolfSSL 0:d92f9d21154c 4995 if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL))
wolfSSL 0:d92f9d21154c 4996 != MP_OKAY) {
wolfSSL 0:d92f9d21154c 4997 mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z);
wolfSSL 0:d92f9d21154c 4998 mp_clear(&M);
wolfSSL 0:d92f9d21154c 4999 return res;
wolfSSL 0:d92f9d21154c 5000 }
wolfSSL 0:d92f9d21154c 5001
wolfSSL 0:d92f9d21154c 5002 /* SPECIAL CASE: if prime mod 4 == 3
wolfSSL 0:d92f9d21154c 5003 * compute directly: res = n^(prime+1)/4 mod prime
wolfSSL 0:d92f9d21154c 5004 * Handbook of Applied Cryptography algorithm 3.36
wolfSSL 0:d92f9d21154c 5005 */
wolfSSL 0:d92f9d21154c 5006 res = mp_mod_d(prime, 4, &i);
wolfSSL 0:d92f9d21154c 5007 if (res == MP_OKAY && i == 3) {
wolfSSL 0:d92f9d21154c 5008 res = mp_add_d(prime, 1, &t1);
wolfSSL 0:d92f9d21154c 5009
wolfSSL 0:d92f9d21154c 5010 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5011 res = mp_div_2(&t1, &t1);
wolfSSL 0:d92f9d21154c 5012 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5013 res = mp_div_2(&t1, &t1);
wolfSSL 0:d92f9d21154c 5014 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5015 res = mp_exptmod(n, &t1, prime, ret);
wolfSSL 0:d92f9d21154c 5016
wolfSSL 0:d92f9d21154c 5017 done = 1;
wolfSSL 0:d92f9d21154c 5018 }
wolfSSL 0:d92f9d21154c 5019
wolfSSL 0:d92f9d21154c 5020 /* NOW: TonelliShanks algorithm */
wolfSSL 0:d92f9d21154c 5021
wolfSSL 0:d92f9d21154c 5022 if (res == MP_OKAY && done == 0) {
wolfSSL 0:d92f9d21154c 5023
wolfSSL 0:d92f9d21154c 5024 /* factor out powers of 2 from prime-1, defining Q and S
wolfSSL 0:d92f9d21154c 5025 * as: prime-1 = Q*2^S */
wolfSSL 0:d92f9d21154c 5026 res = mp_copy(prime, &Q);
wolfSSL 0:d92f9d21154c 5027 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5028 res = mp_sub_d(&Q, 1, &Q);
wolfSSL 0:d92f9d21154c 5029 /* Q = prime - 1 */
wolfSSL 0:d92f9d21154c 5030 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5031 mp_zero(&S);
wolfSSL 0:d92f9d21154c 5032 /* S = 0 */
wolfSSL 0:d92f9d21154c 5033 while (res == MP_OKAY && mp_iseven(&Q)) {
wolfSSL 0:d92f9d21154c 5034 res = mp_div_2(&Q, &Q);
wolfSSL 0:d92f9d21154c 5035 /* Q = Q / 2 */
wolfSSL 0:d92f9d21154c 5036 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5037 res = mp_add_d(&S, 1, &S);
wolfSSL 0:d92f9d21154c 5038 /* S = S + 1 */
wolfSSL 0:d92f9d21154c 5039 }
wolfSSL 0:d92f9d21154c 5040
wolfSSL 0:d92f9d21154c 5041 /* find a Z such that the Legendre symbol (Z|prime) == -1 */
wolfSSL 0:d92f9d21154c 5042 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5043 res = mp_set_int(&Z, 2);
wolfSSL 0:d92f9d21154c 5044 /* Z = 2 */
wolfSSL 0:d92f9d21154c 5045 while (res == MP_OKAY) {
wolfSSL 0:d92f9d21154c 5046 res = mp_jacobi(&Z, prime, &legendre);
wolfSSL 0:d92f9d21154c 5047 if (res == MP_OKAY && legendre == -1)
wolfSSL 0:d92f9d21154c 5048 break;
wolfSSL 0:d92f9d21154c 5049 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5050 res = mp_add_d(&Z, 1, &Z);
wolfSSL 0:d92f9d21154c 5051 /* Z = Z + 1 */
wolfSSL 0:d92f9d21154c 5052 }
wolfSSL 0:d92f9d21154c 5053
wolfSSL 0:d92f9d21154c 5054 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5055 res = mp_exptmod(&Z, &Q, prime, &C);
wolfSSL 0:d92f9d21154c 5056 /* C = Z ^ Q mod prime */
wolfSSL 0:d92f9d21154c 5057 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5058 res = mp_add_d(&Q, 1, &t1);
wolfSSL 0:d92f9d21154c 5059 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5060 res = mp_div_2(&t1, &t1);
wolfSSL 0:d92f9d21154c 5061 /* t1 = (Q + 1) / 2 */
wolfSSL 0:d92f9d21154c 5062 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5063 res = mp_exptmod(n, &t1, prime, &R);
wolfSSL 0:d92f9d21154c 5064 /* R = n ^ ((Q + 1) / 2) mod prime */
wolfSSL 0:d92f9d21154c 5065 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5066 res = mp_exptmod(n, &Q, prime, &T);
wolfSSL 0:d92f9d21154c 5067 /* T = n ^ Q mod prime */
wolfSSL 0:d92f9d21154c 5068 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5069 res = mp_copy(&S, &M);
wolfSSL 0:d92f9d21154c 5070 /* M = S */
wolfSSL 0:d92f9d21154c 5071 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5072 res = mp_set_int(&two, 2);
wolfSSL 0:d92f9d21154c 5073
wolfSSL 0:d92f9d21154c 5074 while (res == MP_OKAY && done == 0) {
wolfSSL 0:d92f9d21154c 5075 res = mp_copy(&T, &t1);
wolfSSL 0:d92f9d21154c 5076 i = 0;
wolfSSL 0:d92f9d21154c 5077 while (res == MP_OKAY) {
wolfSSL 0:d92f9d21154c 5078 if (mp_cmp_d(&t1, 1) == MP_EQ)
wolfSSL 0:d92f9d21154c 5079 break;
wolfSSL 0:d92f9d21154c 5080 res = mp_exptmod(&t1, &two, prime, &t1);
wolfSSL 0:d92f9d21154c 5081 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5082 i++;
wolfSSL 0:d92f9d21154c 5083 }
wolfSSL 0:d92f9d21154c 5084 if (res == MP_OKAY && i == 0) {
wolfSSL 0:d92f9d21154c 5085 mp_copy(&R, ret);
wolfSSL 0:d92f9d21154c 5086 res = MP_OKAY;
wolfSSL 0:d92f9d21154c 5087 done = 1;
wolfSSL 0:d92f9d21154c 5088 }
wolfSSL 0:d92f9d21154c 5089
wolfSSL 0:d92f9d21154c 5090 if (done == 0) {
wolfSSL 0:d92f9d21154c 5091 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5092 res = mp_sub_d(&M, i, &t1);
wolfSSL 0:d92f9d21154c 5093 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5094 res = mp_sub_d(&t1, 1, &t1);
wolfSSL 0:d92f9d21154c 5095 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5096 res = mp_exptmod(&two, &t1, prime, &t1);
wolfSSL 0:d92f9d21154c 5097 /* t1 = 2 ^ (M - i - 1) */
wolfSSL 0:d92f9d21154c 5098 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5099 res = mp_exptmod(&C, &t1, prime, &t1);
wolfSSL 0:d92f9d21154c 5100 /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
wolfSSL 0:d92f9d21154c 5101 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5102 res = mp_sqrmod(&t1, prime, &C);
wolfSSL 0:d92f9d21154c 5103 /* C = (t1 * t1) mod prime */
wolfSSL 0:d92f9d21154c 5104 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5105 res = mp_mulmod(&R, &t1, prime, &R);
wolfSSL 0:d92f9d21154c 5106 /* R = (R * t1) mod prime */
wolfSSL 0:d92f9d21154c 5107 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5108 res = mp_mulmod(&T, &C, prime, &T);
wolfSSL 0:d92f9d21154c 5109 /* T = (T * C) mod prime */
wolfSSL 0:d92f9d21154c 5110 if (res == MP_OKAY)
wolfSSL 0:d92f9d21154c 5111 mp_set(&M, i);
wolfSSL 0:d92f9d21154c 5112 /* M = i */
wolfSSL 0:d92f9d21154c 5113 }
wolfSSL 0:d92f9d21154c 5114 }
wolfSSL 0:d92f9d21154c 5115 }
wolfSSL 0:d92f9d21154c 5116
wolfSSL 0:d92f9d21154c 5117 /* done */
wolfSSL 0:d92f9d21154c 5118 mp_clear(&t1);
wolfSSL 0:d92f9d21154c 5119 mp_clear(&C);
wolfSSL 0:d92f9d21154c 5120 mp_clear(&Q);
wolfSSL 0:d92f9d21154c 5121 mp_clear(&S);
wolfSSL 0:d92f9d21154c 5122 mp_clear(&Z);
wolfSSL 0:d92f9d21154c 5123 mp_clear(&M);
wolfSSL 0:d92f9d21154c 5124 mp_clear(&T);
wolfSSL 0:d92f9d21154c 5125 mp_clear(&R);
wolfSSL 0:d92f9d21154c 5126 mp_clear(&two);
wolfSSL 0:d92f9d21154c 5127
wolfSSL 0:d92f9d21154c 5128 return res;
wolfSSL 0:d92f9d21154c 5129 }
wolfSSL 0:d92f9d21154c 5130
wolfSSL 0:d92f9d21154c 5131
wolfSSL 0:d92f9d21154c 5132 /* export public ECC key in ANSI X9.63 format compressed */
wolfSSL 0:d92f9d21154c 5133 int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen)
wolfSSL 0:d92f9d21154c 5134 {
wolfSSL 0:d92f9d21154c 5135 word32 numlen;
wolfSSL 0:d92f9d21154c 5136 int ret = MP_OKAY;
wolfSSL 0:d92f9d21154c 5137
wolfSSL 0:d92f9d21154c 5138 if (key == NULL || out == NULL || outLen == NULL)
wolfSSL 0:d92f9d21154c 5139 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 5140
wolfSSL 0:d92f9d21154c 5141 if (ecc_is_valid_idx(key->idx) == 0) {
wolfSSL 0:d92f9d21154c 5142 return ECC_BAD_ARG_E;
wolfSSL 0:d92f9d21154c 5143 }
wolfSSL 0:d92f9d21154c 5144 numlen = key->dp->size;
wolfSSL 0:d92f9d21154c 5145
wolfSSL 0:d92f9d21154c 5146 if (*outLen < (1 + numlen)) {
wolfSSL 0:d92f9d21154c 5147 *outLen = 1 + numlen;
wolfSSL 0:d92f9d21154c 5148 return BUFFER_E;
wolfSSL 0:d92f9d21154c 5149 }
wolfSSL 0:d92f9d21154c 5150
wolfSSL 0:d92f9d21154c 5151 /* store first byte */
wolfSSL 0:d92f9d21154c 5152 out[0] = mp_isodd(key->pubkey.y) ? 0x03 : 0x02;
wolfSSL 0:d92f9d21154c 5153
wolfSSL 0:d92f9d21154c 5154 /* pad and store x */
wolfSSL 0:d92f9d21154c 5155 XMEMSET(out+1, 0, numlen);
wolfSSL 0:d92f9d21154c 5156 ret = mp_to_unsigned_bin(key->pubkey.x,
wolfSSL 0:d92f9d21154c 5157 out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
wolfSSL 0:d92f9d21154c 5158 *outLen = 1 + numlen;
wolfSSL 0:d92f9d21154c 5159 return ret;
wolfSSL 0:d92f9d21154c 5160 }
wolfSSL 0:d92f9d21154c 5161
wolfSSL 0:d92f9d21154c 5162
wolfSSL 0:d92f9d21154c 5163 /* d = a - b (mod c) */
wolfSSL 0:d92f9d21154c 5164 int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
wolfSSL 0:d92f9d21154c 5165 {
wolfSSL 0:d92f9d21154c 5166 int res;
wolfSSL 0:d92f9d21154c 5167 mp_int t;
wolfSSL 0:d92f9d21154c 5168
wolfSSL 0:d92f9d21154c 5169 if ((res = mp_init (&t)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 5170 return res;
wolfSSL 0:d92f9d21154c 5171 }
wolfSSL 0:d92f9d21154c 5172
wolfSSL 0:d92f9d21154c 5173 if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
wolfSSL 0:d92f9d21154c 5174 mp_clear (&t);
wolfSSL 0:d92f9d21154c 5175 return res;
wolfSSL 0:d92f9d21154c 5176 }
wolfSSL 0:d92f9d21154c 5177 res = mp_mod (&t, c, d);
wolfSSL 0:d92f9d21154c 5178 mp_clear (&t);
wolfSSL 0:d92f9d21154c 5179
wolfSSL 0:d92f9d21154c 5180 return res;
wolfSSL 0:d92f9d21154c 5181 }
wolfSSL 0:d92f9d21154c 5182
wolfSSL 0:d92f9d21154c 5183
wolfSSL 0:d92f9d21154c 5184 #endif /* HAVE_COMP_KEY */
wolfSSL 0:d92f9d21154c 5185
wolfSSL 0:d92f9d21154c 5186 #endif /* HAVE_ECC */
wolfSSL 0:d92f9d21154c 5187