[164] | 1 | /* ecc.c
|
---|
| 2 | *
|
---|
| 3 | * Copyright (C) 2006-2015 wolfSSL Inc.
|
---|
| 4 | *
|
---|
| 5 | * This file is part of wolfSSL. (formerly known as CyaSSL)
|
---|
| 6 | *
|
---|
| 7 | * wolfSSL is free software; you can redistribute it and/or modify
|
---|
| 8 | * it under the terms of the GNU General Public License as published by
|
---|
| 9 | * the Free Software Foundation; either version 2 of the License, or
|
---|
| 10 | * (at your option) any later version.
|
---|
| 11 | *
|
---|
| 12 | * wolfSSL is distributed in the hope that it will be useful,
|
---|
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
| 15 | * GNU General Public License for more details.
|
---|
| 16 | *
|
---|
| 17 | * You should have received a copy of the GNU General Public License
|
---|
| 18 | * along with this program; if not, write to the Free Software
|
---|
| 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
---|
| 20 | */
|
---|
| 21 |
|
---|
| 22 |
|
---|
| 23 | #ifdef HAVE_CONFIG_H
|
---|
| 24 | #include <config.h>
|
---|
| 25 | #endif
|
---|
| 26 |
|
---|
| 27 | /* in case user set HAVE_ECC there */
|
---|
| 28 | #include <wolfssl/wolfcrypt/settings.h>
|
---|
| 29 |
|
---|
| 30 | #ifdef HAVE_ECC
|
---|
| 31 |
|
---|
| 32 | #include <wolfssl/wolfcrypt/ecc.h>
|
---|
| 33 | #include <wolfssl/openssl/ec.h>
|
---|
| 34 | #include <wolfssl/wolfcrypt/asn.h>
|
---|
| 35 | #include <wolfssl/wolfcrypt/error-crypt.h>
|
---|
| 36 |
|
---|
| 37 | #ifdef HAVE_ECC_ENCRYPT
|
---|
| 38 | #include <wolfssl/wolfcrypt/hmac.h>
|
---|
| 39 | #include <wolfssl/wolfcrypt/aes.h>
|
---|
| 40 | #endif
|
---|
| 41 |
|
---|
| 42 | #ifdef NO_INLINE
|
---|
| 43 | #include <wolfssl/wolfcrypt/misc.h>
|
---|
| 44 | #else
|
---|
| 45 | #include <wolfcrypt/src/misc.c>
|
---|
| 46 | #endif
|
---|
| 47 |
|
---|
| 48 | /* map
|
---|
| 49 |
|
---|
| 50 | ptmul -> mulmod
|
---|
| 51 |
|
---|
| 52 | */
|
---|
| 53 |
|
---|
| 54 |
|
---|
| 55 | /* p256 curve on by default whether user curves or not */
|
---|
| 56 | #if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES)
|
---|
| 57 | #define ECC112
|
---|
| 58 | #endif
|
---|
| 59 | #if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES)
|
---|
| 60 | #define ECC128
|
---|
| 61 | #endif
|
---|
| 62 | #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES)
|
---|
| 63 | #define ECC160
|
---|
| 64 | #endif
|
---|
| 65 | #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES)
|
---|
| 66 | #define ECC192
|
---|
| 67 | #endif
|
---|
| 68 | #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES)
|
---|
| 69 | #define ECC224
|
---|
| 70 | #endif
|
---|
| 71 | #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES)
|
---|
| 72 | #define ECC256
|
---|
| 73 | #endif
|
---|
| 74 | #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)
|
---|
| 75 | #define ECC384
|
---|
| 76 | #endif
|
---|
| 77 | #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES)
|
---|
| 78 | #define ECC521
|
---|
| 79 | #endif
|
---|
| 80 |
|
---|
| 81 |
|
---|
| 82 |
|
---|
| 83 | /* This holds the key settings. ***MUST*** be organized by size from
|
---|
| 84 | smallest to largest. */
|
---|
| 85 |
|
---|
| 86 | const ecc_set_type ecc_sets[] = {
|
---|
| 87 | #ifdef ECC112
|
---|
| 88 | {
|
---|
| 89 | 14,
|
---|
| 90 | NID_secp111r1,
|
---|
| 91 | "SECP112R1",
|
---|
| 92 | "DB7C2ABF62E35E668076BEAD208B",
|
---|
| 93 | "DB7C2ABF62E35E668076BEAD2088",
|
---|
| 94 | "659EF8BA043916EEDE8911702B22",
|
---|
| 95 | "DB7C2ABF62E35E7628DFAC6561C5",
|
---|
| 96 | "09487239995A5EE76B55F9C2F098",
|
---|
| 97 | "A89CE5AF8724C0A23E0E0FF77500"
|
---|
| 98 | },
|
---|
| 99 | #endif
|
---|
| 100 | #ifdef ECC128
|
---|
| 101 | {
|
---|
| 102 | 16,
|
---|
| 103 | NID_secp128r1,
|
---|
| 104 | "SECP128R1",
|
---|
| 105 | "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
---|
| 106 | "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
---|
| 107 | "E87579C11079F43DD824993C2CEE5ED3",
|
---|
| 108 | "FFFFFFFE0000000075A30D1B9038A115",
|
---|
| 109 | "161FF7528B899B2D0C28607CA52C5B86",
|
---|
| 110 | "CF5AC8395BAFEB13C02DA292DDED7A83",
|
---|
| 111 | },
|
---|
| 112 | #endif
|
---|
| 113 | #ifdef ECC160
|
---|
| 114 | {
|
---|
| 115 | 20,
|
---|
| 116 | NID_secp160r1,
|
---|
| 117 | "SECP160R1",
|
---|
| 118 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
---|
| 119 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
---|
| 120 | "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
---|
| 121 | "0100000000000000000001F4C8F927AED3CA752257",
|
---|
| 122 | "4A96B5688EF573284664698968C38BB913CBFC82",
|
---|
| 123 | "23A628553168947D59DCC912042351377AC5FB32",
|
---|
| 124 | },
|
---|
| 125 | #endif
|
---|
| 126 | #ifdef ECC192
|
---|
| 127 | {
|
---|
| 128 | 24,
|
---|
| 129 | NID_cert192,
|
---|
| 130 | "ECC-192",
|
---|
| 131 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
---|
| 132 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
---|
| 133 | "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
---|
| 134 | "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
---|
| 135 | "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
---|
| 136 | "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
---|
| 137 | },
|
---|
| 138 | #endif
|
---|
| 139 | #ifdef ECC224
|
---|
| 140 | {
|
---|
| 141 | 28,
|
---|
| 142 | NID_cert224,
|
---|
| 143 | "ECC-224",
|
---|
| 144 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
---|
| 145 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
---|
| 146 | "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
---|
| 147 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
---|
| 148 | "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
---|
| 149 | "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
---|
| 150 | },
|
---|
| 151 | #endif
|
---|
| 152 | #ifdef ECC256
|
---|
| 153 | {
|
---|
| 154 | 32,
|
---|
| 155 | NID_X9_62_prime256v1,
|
---|
| 156 | "nistp256",
|
---|
| 157 | "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
---|
| 158 | "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
---|
| 159 | "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
---|
| 160 | "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
---|
| 161 | "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
---|
| 162 | "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
---|
| 163 | },
|
---|
| 164 | #endif
|
---|
| 165 | #ifdef ECC384
|
---|
| 166 | {
|
---|
| 167 | 48,
|
---|
| 168 | NID_secp384r1,
|
---|
| 169 | "nistp384",
|
---|
| 170 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
---|
| 171 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
---|
| 172 | "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
---|
| 173 | "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
---|
| 174 | "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
---|
| 175 | "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
---|
| 176 | },
|
---|
| 177 | #endif
|
---|
| 178 | #ifdef ECC521
|
---|
| 179 | {
|
---|
| 180 | 66,
|
---|
| 181 | NID_secp521r1,
|
---|
| 182 | "nistp521",
|
---|
| 183 | "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
---|
| 184 | "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
---|
| 185 | "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
---|
| 186 | "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
---|
| 187 | "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
---|
| 188 | "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
---|
| 189 | },
|
---|
| 190 | #endif
|
---|
| 191 | {
|
---|
| 192 | 0, -1,
|
---|
| 193 | NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
---|
| 194 | }
|
---|
| 195 | };
|
---|
| 196 |
|
---|
| 197 |
|
---|
| 198 | int ecc_map(ecc_point*, mp_int*, mp_digit*);
|
---|
| 199 | int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
|
---|
| 200 | mp_int* modulus, mp_digit* mp);
|
---|
| 201 | int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus,
|
---|
| 202 | mp_digit* mp);
|
---|
| 203 | static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order);
|
---|
| 204 | #ifdef ECC_SHAMIR
|
---|
| 205 | static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB,
|
---|
| 206 | ecc_point* C, mp_int* modulus);
|
---|
| 207 | #endif
|
---|
| 208 |
|
---|
| 209 | int mp_jacobi(mp_int* a, mp_int* p, int* c);
|
---|
| 210 | int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
|
---|
| 211 | int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d);
|
---|
| 212 |
|
---|
| 213 | #ifdef HAVE_COMP_KEY
|
---|
| 214 | static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
|
---|
| 215 | #endif
|
---|
| 216 |
|
---|
| 217 | /* helper for either lib */
|
---|
| 218 | static int get_digit_count(mp_int* a)
|
---|
| 219 | {
|
---|
| 220 | if (a == NULL)
|
---|
| 221 | return 0;
|
---|
| 222 |
|
---|
| 223 | return a->used;
|
---|
| 224 | }
|
---|
| 225 |
|
---|
| 226 | /* helper for either lib */
|
---|
| 227 | static mp_digit get_digit(mp_int* a, int n)
|
---|
| 228 | {
|
---|
| 229 | if (a == NULL)
|
---|
| 230 | return 0;
|
---|
| 231 |
|
---|
| 232 | return (n >= a->used || n < 0) ? 0 : a->dp[n];
|
---|
| 233 | }
|
---|
| 234 |
|
---|
| 235 |
|
---|
| 236 | #if defined(USE_FAST_MATH)
|
---|
| 237 |
|
---|
| 238 | /* fast math accelerated version, but not for fp ecc yet */
|
---|
| 239 |
|
---|
| 240 | /**
|
---|
| 241 | Add two ECC points
|
---|
| 242 | P The point to add
|
---|
| 243 | Q The point to add
|
---|
| 244 | R [out] The destination of the double
|
---|
| 245 | modulus The modulus of the field the ECC curve is in
|
---|
| 246 | mp The "b" value from montgomery_setup()
|
---|
| 247 | return MP_OKAY on success
|
---|
| 248 | */
|
---|
| 249 | int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R,
|
---|
| 250 | mp_int* modulus, mp_digit* mp)
|
---|
| 251 | {
|
---|
| 252 | fp_int t1, t2, x, y, z;
|
---|
| 253 | int err;
|
---|
| 254 |
|
---|
| 255 | if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
|
---|
| 256 | return ECC_BAD_ARG_E;
|
---|
| 257 |
|
---|
| 258 | if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
|
---|
| 259 | return err;
|
---|
| 260 | }
|
---|
| 261 |
|
---|
| 262 | /* should we dbl instead? */
|
---|
| 263 | fp_sub(modulus, Q->y, &t1);
|
---|
| 264 | if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
|
---|
| 265 | (get_digit_count(Q->z) && fp_cmp(P->z, Q->z) == FP_EQ) &&
|
---|
| 266 | (fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
|
---|
| 267 | return ecc_projective_dbl_point(P, R, modulus, mp);
|
---|
| 268 | }
|
---|
| 269 |
|
---|
| 270 | fp_copy(P->x, &x);
|
---|
| 271 | fp_copy(P->y, &y);
|
---|
| 272 | fp_copy(P->z, &z);
|
---|
| 273 |
|
---|
| 274 | /* if Z is one then these are no-operations */
|
---|
| 275 | if (get_digit_count(Q->z)) {
|
---|
| 276 | /* T1 = Z' * Z' */
|
---|
| 277 | fp_sqr(Q->z, &t1);
|
---|
| 278 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 279 | /* X = X * T1 */
|
---|
| 280 | fp_mul(&t1, &x, &x);
|
---|
| 281 | fp_montgomery_reduce(&x, modulus, *mp);
|
---|
| 282 | /* T1 = Z' * T1 */
|
---|
| 283 | fp_mul(Q->z, &t1, &t1);
|
---|
| 284 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 285 | /* Y = Y * T1 */
|
---|
| 286 | fp_mul(&t1, &y, &y);
|
---|
| 287 | fp_montgomery_reduce(&y, modulus, *mp);
|
---|
| 288 | }
|
---|
| 289 |
|
---|
| 290 | /* T1 = Z*Z */
|
---|
| 291 | fp_sqr(&z, &t1);
|
---|
| 292 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 293 | /* T2 = X' * T1 */
|
---|
| 294 | fp_mul(Q->x, &t1, &t2);
|
---|
| 295 | fp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 296 | /* T1 = Z * T1 */
|
---|
| 297 | fp_mul(&z, &t1, &t1);
|
---|
| 298 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 299 | /* T1 = Y' * T1 */
|
---|
| 300 | fp_mul(Q->y, &t1, &t1);
|
---|
| 301 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 302 |
|
---|
| 303 | /* Y = Y - T1 */
|
---|
| 304 | fp_sub(&y, &t1, &y);
|
---|
| 305 | if (fp_cmp_d(&y, 0) == FP_LT) {
|
---|
| 306 | fp_add(&y, modulus, &y);
|
---|
| 307 | }
|
---|
| 308 | /* T1 = 2T1 */
|
---|
| 309 | fp_add(&t1, &t1, &t1);
|
---|
| 310 | if (fp_cmp(&t1, modulus) != FP_LT) {
|
---|
| 311 | fp_sub(&t1, modulus, &t1);
|
---|
| 312 | }
|
---|
| 313 | /* T1 = Y + T1 */
|
---|
| 314 | fp_add(&t1, &y, &t1);
|
---|
| 315 | if (fp_cmp(&t1, modulus) != FP_LT) {
|
---|
| 316 | fp_sub(&t1, modulus, &t1);
|
---|
| 317 | }
|
---|
| 318 | /* X = X - T2 */
|
---|
| 319 | fp_sub(&x, &t2, &x);
|
---|
| 320 | if (fp_cmp_d(&x, 0) == FP_LT) {
|
---|
| 321 | fp_add(&x, modulus, &x);
|
---|
| 322 | }
|
---|
| 323 | /* T2 = 2T2 */
|
---|
| 324 | fp_add(&t2, &t2, &t2);
|
---|
| 325 | if (fp_cmp(&t2, modulus) != FP_LT) {
|
---|
| 326 | fp_sub(&t2, modulus, &t2);
|
---|
| 327 | }
|
---|
| 328 | /* T2 = X + T2 */
|
---|
| 329 | fp_add(&t2, &x, &t2);
|
---|
| 330 | if (fp_cmp(&t2, modulus) != FP_LT) {
|
---|
| 331 | fp_sub(&t2, modulus, &t2);
|
---|
| 332 | }
|
---|
| 333 |
|
---|
| 334 | /* if Z' != 1 */
|
---|
| 335 | if (get_digit_count(Q->z)) {
|
---|
| 336 | /* Z = Z * Z' */
|
---|
| 337 | fp_mul(&z, Q->z, &z);
|
---|
| 338 | fp_montgomery_reduce(&z, modulus, *mp);
|
---|
| 339 | }
|
---|
| 340 |
|
---|
| 341 | /* Z = Z * X */
|
---|
| 342 | fp_mul(&z, &x, &z);
|
---|
| 343 | fp_montgomery_reduce(&z, modulus, *mp);
|
---|
| 344 |
|
---|
| 345 | /* T1 = T1 * X */
|
---|
| 346 | fp_mul(&t1, &x, &t1);
|
---|
| 347 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 348 | /* X = X * X */
|
---|
| 349 | fp_sqr(&x, &x);
|
---|
| 350 | fp_montgomery_reduce(&x, modulus, *mp);
|
---|
| 351 | /* T2 = T2 * x */
|
---|
| 352 | fp_mul(&t2, &x, &t2);
|
---|
| 353 | fp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 354 | /* T1 = T1 * X */
|
---|
| 355 | fp_mul(&t1, &x, &t1);
|
---|
| 356 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 357 |
|
---|
| 358 | /* X = Y*Y */
|
---|
| 359 | fp_sqr(&y, &x);
|
---|
| 360 | fp_montgomery_reduce(&x, modulus, *mp);
|
---|
| 361 | /* X = X - T2 */
|
---|
| 362 | fp_sub(&x, &t2, &x);
|
---|
| 363 | if (fp_cmp_d(&x, 0) == FP_LT) {
|
---|
| 364 | fp_add(&x, modulus, &x);
|
---|
| 365 | }
|
---|
| 366 |
|
---|
| 367 | /* T2 = T2 - X */
|
---|
| 368 | fp_sub(&t2, &x, &t2);
|
---|
| 369 | if (fp_cmp_d(&t2, 0) == FP_LT) {
|
---|
| 370 | fp_add(&t2, modulus, &t2);
|
---|
| 371 | }
|
---|
| 372 | /* T2 = T2 - X */
|
---|
| 373 | fp_sub(&t2, &x, &t2);
|
---|
| 374 | if (fp_cmp_d(&t2, 0) == FP_LT) {
|
---|
| 375 | fp_add(&t2, modulus, &t2);
|
---|
| 376 | }
|
---|
| 377 | /* T2 = T2 * Y */
|
---|
| 378 | fp_mul(&t2, &y, &t2);
|
---|
| 379 | fp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 380 | /* Y = T2 - T1 */
|
---|
| 381 | fp_sub(&t2, &t1, &y);
|
---|
| 382 | if (fp_cmp_d(&y, 0) == FP_LT) {
|
---|
| 383 | fp_add(&y, modulus, &y);
|
---|
| 384 | }
|
---|
| 385 | /* Y = Y/2 */
|
---|
| 386 | if (fp_isodd(&y)) {
|
---|
| 387 | fp_add(&y, modulus, &y);
|
---|
| 388 | }
|
---|
| 389 | fp_div_2(&y, &y);
|
---|
| 390 |
|
---|
| 391 | fp_copy(&x, R->x);
|
---|
| 392 | fp_copy(&y, R->y);
|
---|
| 393 | fp_copy(&z, R->z);
|
---|
| 394 |
|
---|
| 395 | return MP_OKAY;
|
---|
| 396 | }
|
---|
| 397 |
|
---|
| 398 |
|
---|
| 399 | /**
|
---|
| 400 | Double an ECC point
|
---|
| 401 | P The point to double
|
---|
| 402 | R [out] The destination of the double
|
---|
| 403 | modulus The modulus of the field the ECC curve is in
|
---|
| 404 | mp The "b" value from montgomery_setup()
|
---|
| 405 | return MP_OKAY on success
|
---|
| 406 | */
|
---|
| 407 | int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
|
---|
| 408 | mp_digit* mp)
|
---|
| 409 | {
|
---|
| 410 | fp_int t1, t2;
|
---|
| 411 | int err;
|
---|
| 412 |
|
---|
| 413 | if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
|
---|
| 414 | return ECC_BAD_ARG_E;
|
---|
| 415 |
|
---|
| 416 | if (P != R) {
|
---|
| 417 | fp_copy(P->x, R->x);
|
---|
| 418 | fp_copy(P->y, R->y);
|
---|
| 419 | fp_copy(P->z, R->z);
|
---|
| 420 | }
|
---|
| 421 |
|
---|
| 422 | if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
|
---|
| 423 | return err;
|
---|
| 424 | }
|
---|
| 425 |
|
---|
| 426 | /* t1 = Z * Z */
|
---|
| 427 | fp_sqr(R->z, &t1);
|
---|
| 428 | fp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 429 | /* Z = Y * Z */
|
---|
| 430 | fp_mul(R->z, R->y, R->z);
|
---|
| 431 | fp_montgomery_reduce(R->z, modulus, *mp);
|
---|
| 432 | /* Z = 2Z */
|
---|
| 433 | fp_add(R->z, R->z, R->z);
|
---|
| 434 | if (fp_cmp(R->z, modulus) != FP_LT) {
|
---|
| 435 | fp_sub(R->z, modulus, R->z);
|
---|
| 436 | }
|
---|
| 437 |
|
---|
| 438 | /* &t2 = X - T1 */
|
---|
| 439 | fp_sub(R->x, &t1, &t2);
|
---|
| 440 | if (fp_cmp_d(&t2, 0) == FP_LT) {
|
---|
| 441 | fp_add(&t2, modulus, &t2);
|
---|
| 442 | }
|
---|
| 443 | /* T1 = X + T1 */
|
---|
| 444 | fp_add(&t1, R->x, &t1);
|
---|
| 445 | if (fp_cmp(&t1, modulus) != FP_LT) {
|
---|
| 446 | fp_sub(&t1, modulus, &t1);
|
---|
| 447 | }
|
---|
| 448 | /* T2 = T1 * T2 */
|
---|
| 449 | fp_mul(&t1, &t2, &t2);
|
---|
| 450 | fp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 451 | /* T1 = 2T2 */
|
---|
| 452 | fp_add(&t2, &t2, &t1);
|
---|
| 453 | if (fp_cmp(&t1, modulus) != FP_LT) {
|
---|
| 454 | fp_sub(&t1, modulus, &t1);
|
---|
| 455 | }
|
---|
| 456 | /* T1 = T1 + T2 */
|
---|
| 457 | fp_add(&t1, &t2, &t1);
|
---|
| 458 | if (fp_cmp(&t1, modulus) != FP_LT) {
|
---|
| 459 | fp_sub(&t1, modulus, &t1);
|
---|
| 460 | }
|
---|
| 461 |
|
---|
| 462 | /* Y = 2Y */
|
---|
| 463 | fp_add(R->y, R->y, R->y);
|
---|
| 464 | if (fp_cmp(R->y, modulus) != FP_LT) {
|
---|
| 465 | fp_sub(R->y, modulus, R->y);
|
---|
| 466 | }
|
---|
| 467 | /* Y = Y * Y */
|
---|
| 468 | fp_sqr(R->y, R->y);
|
---|
| 469 | fp_montgomery_reduce(R->y, modulus, *mp);
|
---|
| 470 | /* T2 = Y * Y */
|
---|
| 471 | fp_sqr(R->y, &t2);
|
---|
| 472 | fp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 473 | /* T2 = T2/2 */
|
---|
| 474 | if (fp_isodd(&t2)) {
|
---|
| 475 | fp_add(&t2, modulus, &t2);
|
---|
| 476 | }
|
---|
| 477 | fp_div_2(&t2, &t2);
|
---|
| 478 | /* Y = Y * X */
|
---|
| 479 | fp_mul(R->y, R->x, R->y);
|
---|
| 480 | fp_montgomery_reduce(R->y, modulus, *mp);
|
---|
| 481 |
|
---|
| 482 | /* X = T1 * T1 */
|
---|
| 483 | fp_sqr(&t1, R->x);
|
---|
| 484 | fp_montgomery_reduce(R->x, modulus, *mp);
|
---|
| 485 | /* X = X - Y */
|
---|
| 486 | fp_sub(R->x, R->y, R->x);
|
---|
| 487 | if (fp_cmp_d(R->x, 0) == FP_LT) {
|
---|
| 488 | fp_add(R->x, modulus, R->x);
|
---|
| 489 | }
|
---|
| 490 | /* X = X - Y */
|
---|
| 491 | fp_sub(R->x, R->y, R->x);
|
---|
| 492 | if (fp_cmp_d(R->x, 0) == FP_LT) {
|
---|
| 493 | fp_add(R->x, modulus, R->x);
|
---|
| 494 | }
|
---|
| 495 |
|
---|
| 496 | /* Y = Y - X */
|
---|
| 497 | fp_sub(R->y, R->x, R->y);
|
---|
| 498 | if (fp_cmp_d(R->y, 0) == FP_LT) {
|
---|
| 499 | fp_add(R->y, modulus, R->y);
|
---|
| 500 | }
|
---|
| 501 | /* Y = Y * T1 */
|
---|
| 502 | fp_mul(R->y, &t1, R->y);
|
---|
| 503 | fp_montgomery_reduce(R->y, modulus, *mp);
|
---|
| 504 | /* Y = Y - T2 */
|
---|
| 505 | fp_sub(R->y, &t2, R->y);
|
---|
| 506 | if (fp_cmp_d(R->y, 0) == FP_LT) {
|
---|
| 507 | fp_add(R->y, modulus, R->y);
|
---|
| 508 | }
|
---|
| 509 |
|
---|
| 510 | return MP_OKAY;
|
---|
| 511 | }
|
---|
| 512 |
|
---|
| 513 | #else /* USE_FAST_MATH */
|
---|
| 514 |
|
---|
| 515 | /**
|
---|
| 516 | Add two ECC points
|
---|
| 517 | P The point to add
|
---|
| 518 | Q The point to add
|
---|
| 519 | R [out] The destination of the double
|
---|
| 520 | modulus The modulus of the field the ECC curve is in
|
---|
| 521 | mp The "b" value from montgomery_setup()
|
---|
| 522 | return MP_OKAY on success
|
---|
| 523 | */
|
---|
| 524 | int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
|
---|
| 525 | mp_int* modulus, mp_digit* mp)
|
---|
| 526 | {
|
---|
| 527 | mp_int t1;
|
---|
| 528 | mp_int t2;
|
---|
| 529 | mp_int x;
|
---|
| 530 | mp_int y;
|
---|
| 531 | mp_int z;
|
---|
| 532 | int err;
|
---|
| 533 |
|
---|
| 534 | if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
|
---|
| 535 | return ECC_BAD_ARG_E;
|
---|
| 536 |
|
---|
| 537 | if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
|
---|
| 538 | return err;
|
---|
| 539 | }
|
---|
| 540 |
|
---|
| 541 | /* should we dbl instead? */
|
---|
| 542 | err = mp_sub(modulus, Q->y, &t1);
|
---|
| 543 |
|
---|
| 544 | if (err == MP_OKAY) {
|
---|
| 545 | if ( (mp_cmp(P->x, Q->x) == MP_EQ) &&
|
---|
| 546 | (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) &&
|
---|
| 547 | (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) {
|
---|
| 548 | mp_clear(&t1);
|
---|
| 549 | mp_clear(&t2);
|
---|
| 550 | mp_clear(&x);
|
---|
| 551 | mp_clear(&y);
|
---|
| 552 | mp_clear(&z);
|
---|
| 553 |
|
---|
| 554 | return ecc_projective_dbl_point(P, R, modulus, mp);
|
---|
| 555 | }
|
---|
| 556 | }
|
---|
| 557 |
|
---|
| 558 | if (err == MP_OKAY)
|
---|
| 559 | err = mp_copy(P->x, &x);
|
---|
| 560 | if (err == MP_OKAY)
|
---|
| 561 | err = mp_copy(P->y, &y);
|
---|
| 562 | if (err == MP_OKAY)
|
---|
| 563 | err = mp_copy(P->z, &z);
|
---|
| 564 |
|
---|
| 565 | /* if Z is one then these are no-operations */
|
---|
| 566 | if (err == MP_OKAY) {
|
---|
| 567 | if (get_digit_count(Q->z)) {
|
---|
| 568 | /* T1 = Z' * Z' */
|
---|
| 569 | err = mp_sqr(Q->z, &t1);
|
---|
| 570 | if (err == MP_OKAY)
|
---|
| 571 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 572 |
|
---|
| 573 | /* X = X * T1 */
|
---|
| 574 | if (err == MP_OKAY)
|
---|
| 575 | err = mp_mul(&t1, &x, &x);
|
---|
| 576 | if (err == MP_OKAY)
|
---|
| 577 | err = mp_montgomery_reduce(&x, modulus, *mp);
|
---|
| 578 |
|
---|
| 579 | /* T1 = Z' * T1 */
|
---|
| 580 | if (err == MP_OKAY)
|
---|
| 581 | err = mp_mul(Q->z, &t1, &t1);
|
---|
| 582 | if (err == MP_OKAY)
|
---|
| 583 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 584 |
|
---|
| 585 | /* Y = Y * T1 */
|
---|
| 586 | if (err == MP_OKAY)
|
---|
| 587 | err = mp_mul(&t1, &y, &y);
|
---|
| 588 | if (err == MP_OKAY)
|
---|
| 589 | err = mp_montgomery_reduce(&y, modulus, *mp);
|
---|
| 590 | }
|
---|
| 591 | }
|
---|
| 592 |
|
---|
| 593 | /* T1 = Z*Z */
|
---|
| 594 | if (err == MP_OKAY)
|
---|
| 595 | err = mp_sqr(&z, &t1);
|
---|
| 596 | if (err == MP_OKAY)
|
---|
| 597 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 598 |
|
---|
| 599 | /* T2 = X' * T1 */
|
---|
| 600 | if (err == MP_OKAY)
|
---|
| 601 | err = mp_mul(Q->x, &t1, &t2);
|
---|
| 602 | if (err == MP_OKAY)
|
---|
| 603 | err = mp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 604 |
|
---|
| 605 | /* T1 = Z * T1 */
|
---|
| 606 | if (err == MP_OKAY)
|
---|
| 607 | err = mp_mul(&z, &t1, &t1);
|
---|
| 608 | if (err == MP_OKAY)
|
---|
| 609 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 610 |
|
---|
| 611 | /* T1 = Y' * T1 */
|
---|
| 612 | if (err == MP_OKAY)
|
---|
| 613 | err = mp_mul(Q->y, &t1, &t1);
|
---|
| 614 | if (err == MP_OKAY)
|
---|
| 615 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 616 |
|
---|
| 617 | /* Y = Y - T1 */
|
---|
| 618 | if (err == MP_OKAY)
|
---|
| 619 | err = mp_sub(&y, &t1, &y);
|
---|
| 620 | if (err == MP_OKAY) {
|
---|
| 621 | if (mp_cmp_d(&y, 0) == MP_LT)
|
---|
| 622 | err = mp_add(&y, modulus, &y);
|
---|
| 623 | }
|
---|
| 624 | /* T1 = 2T1 */
|
---|
| 625 | if (err == MP_OKAY)
|
---|
| 626 | err = mp_add(&t1, &t1, &t1);
|
---|
| 627 | if (err == MP_OKAY) {
|
---|
| 628 | if (mp_cmp(&t1, modulus) != MP_LT)
|
---|
| 629 | err = mp_sub(&t1, modulus, &t1);
|
---|
| 630 | }
|
---|
| 631 | /* T1 = Y + T1 */
|
---|
| 632 | if (err == MP_OKAY)
|
---|
| 633 | err = mp_add(&t1, &y, &t1);
|
---|
| 634 | if (err == MP_OKAY) {
|
---|
| 635 | if (mp_cmp(&t1, modulus) != MP_LT)
|
---|
| 636 | err = mp_sub(&t1, modulus, &t1);
|
---|
| 637 | }
|
---|
| 638 | /* X = X - T2 */
|
---|
| 639 | if (err == MP_OKAY)
|
---|
| 640 | err = mp_sub(&x, &t2, &x);
|
---|
| 641 | if (err == MP_OKAY) {
|
---|
| 642 | if (mp_cmp_d(&x, 0) == MP_LT)
|
---|
| 643 | err = mp_add(&x, modulus, &x);
|
---|
| 644 | }
|
---|
| 645 | /* T2 = 2T2 */
|
---|
| 646 | if (err == MP_OKAY)
|
---|
| 647 | err = mp_add(&t2, &t2, &t2);
|
---|
| 648 | if (err == MP_OKAY) {
|
---|
| 649 | if (mp_cmp(&t2, modulus) != MP_LT)
|
---|
| 650 | err = mp_sub(&t2, modulus, &t2);
|
---|
| 651 | }
|
---|
| 652 | /* T2 = X + T2 */
|
---|
| 653 | if (err == MP_OKAY)
|
---|
| 654 | err = mp_add(&t2, &x, &t2);
|
---|
| 655 | if (err == MP_OKAY) {
|
---|
| 656 | if (mp_cmp(&t2, modulus) != MP_LT)
|
---|
| 657 | err = mp_sub(&t2, modulus, &t2);
|
---|
| 658 | }
|
---|
| 659 |
|
---|
| 660 | if (err == MP_OKAY) {
|
---|
| 661 | if (get_digit_count(Q->z)) {
|
---|
| 662 | /* Z = Z * Z' */
|
---|
| 663 | err = mp_mul(&z, Q->z, &z);
|
---|
| 664 | if (err == MP_OKAY)
|
---|
| 665 | err = mp_montgomery_reduce(&z, modulus, *mp);
|
---|
| 666 | }
|
---|
| 667 | }
|
---|
| 668 |
|
---|
| 669 | /* Z = Z * X */
|
---|
| 670 | if (err == MP_OKAY)
|
---|
| 671 | err = mp_mul(&z, &x, &z);
|
---|
| 672 | if (err == MP_OKAY)
|
---|
| 673 | err = mp_montgomery_reduce(&z, modulus, *mp);
|
---|
| 674 |
|
---|
| 675 | /* T1 = T1 * X */
|
---|
| 676 | if (err == MP_OKAY)
|
---|
| 677 | err = mp_mul(&t1, &x, &t1);
|
---|
| 678 | if (err == MP_OKAY)
|
---|
| 679 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 680 |
|
---|
| 681 | /* X = X * X */
|
---|
| 682 | if (err == MP_OKAY)
|
---|
| 683 | err = mp_sqr(&x, &x);
|
---|
| 684 | if (err == MP_OKAY)
|
---|
| 685 | err = mp_montgomery_reduce(&x, modulus, *mp);
|
---|
| 686 |
|
---|
| 687 | /* T2 = T2 * x */
|
---|
| 688 | if (err == MP_OKAY)
|
---|
| 689 | err = mp_mul(&t2, &x, &t2);
|
---|
| 690 | if (err == MP_OKAY)
|
---|
| 691 | err = mp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 692 |
|
---|
| 693 | /* T1 = T1 * X */
|
---|
| 694 | if (err == MP_OKAY)
|
---|
| 695 | err = mp_mul(&t1, &x, &t1);
|
---|
| 696 | if (err == MP_OKAY)
|
---|
| 697 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 698 |
|
---|
| 699 | /* X = Y*Y */
|
---|
| 700 | if (err == MP_OKAY)
|
---|
| 701 | err = mp_sqr(&y, &x);
|
---|
| 702 | if (err == MP_OKAY)
|
---|
| 703 | err = mp_montgomery_reduce(&x, modulus, *mp);
|
---|
| 704 |
|
---|
| 705 | /* X = X - T2 */
|
---|
| 706 | if (err == MP_OKAY)
|
---|
| 707 | err = mp_sub(&x, &t2, &x);
|
---|
| 708 | if (err == MP_OKAY) {
|
---|
| 709 | if (mp_cmp_d(&x, 0) == MP_LT)
|
---|
| 710 | err = mp_add(&x, modulus, &x);
|
---|
| 711 | }
|
---|
| 712 | /* T2 = T2 - X */
|
---|
| 713 | if (err == MP_OKAY)
|
---|
| 714 | err = mp_sub(&t2, &x, &t2);
|
---|
| 715 | if (err == MP_OKAY) {
|
---|
| 716 | if (mp_cmp_d(&t2, 0) == MP_LT)
|
---|
| 717 | err = mp_add(&t2, modulus, &t2);
|
---|
| 718 | }
|
---|
| 719 | /* T2 = T2 - X */
|
---|
| 720 | if (err == MP_OKAY)
|
---|
| 721 | err = mp_sub(&t2, &x, &t2);
|
---|
| 722 | if (err == MP_OKAY) {
|
---|
| 723 | if (mp_cmp_d(&t2, 0) == MP_LT)
|
---|
| 724 | err = mp_add(&t2, modulus, &t2);
|
---|
| 725 | }
|
---|
| 726 | /* T2 = T2 * Y */
|
---|
| 727 | if (err == MP_OKAY)
|
---|
| 728 | err = mp_mul(&t2, &y, &t2);
|
---|
| 729 | if (err == MP_OKAY)
|
---|
| 730 | err = mp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 731 |
|
---|
| 732 | /* Y = T2 - T1 */
|
---|
| 733 | if (err == MP_OKAY)
|
---|
| 734 | err = mp_sub(&t2, &t1, &y);
|
---|
| 735 | if (err == MP_OKAY) {
|
---|
| 736 | if (mp_cmp_d(&y, 0) == MP_LT)
|
---|
| 737 | err = mp_add(&y, modulus, &y);
|
---|
| 738 | }
|
---|
| 739 | /* Y = Y/2 */
|
---|
| 740 | if (err == MP_OKAY) {
|
---|
| 741 | if (mp_isodd(&y))
|
---|
| 742 | err = mp_add(&y, modulus, &y);
|
---|
| 743 | }
|
---|
| 744 | if (err == MP_OKAY)
|
---|
| 745 | err = mp_div_2(&y, &y);
|
---|
| 746 |
|
---|
| 747 | if (err == MP_OKAY)
|
---|
| 748 | err = mp_copy(&x, R->x);
|
---|
| 749 | if (err == MP_OKAY)
|
---|
| 750 | err = mp_copy(&y, R->y);
|
---|
| 751 | if (err == MP_OKAY)
|
---|
| 752 | err = mp_copy(&z, R->z);
|
---|
| 753 |
|
---|
| 754 | /* clean up */
|
---|
| 755 | mp_clear(&t1);
|
---|
| 756 | mp_clear(&t2);
|
---|
| 757 | mp_clear(&x);
|
---|
| 758 | mp_clear(&y);
|
---|
| 759 | mp_clear(&z);
|
---|
| 760 |
|
---|
| 761 | return err;
|
---|
| 762 | }
|
---|
| 763 |
|
---|
| 764 |
|
---|
| 765 | /**
|
---|
| 766 | Double an ECC point
|
---|
| 767 | P The point to double
|
---|
| 768 | R [out] The destination of the double
|
---|
| 769 | modulus The modulus of the field the ECC curve is in
|
---|
| 770 | mp The "b" value from montgomery_setup()
|
---|
| 771 | return MP_OKAY on success
|
---|
| 772 | */
|
---|
| 773 | int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
|
---|
| 774 | mp_digit* mp)
|
---|
| 775 | {
|
---|
| 776 | mp_int t1;
|
---|
| 777 | mp_int t2;
|
---|
| 778 | int err;
|
---|
| 779 |
|
---|
| 780 | if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
|
---|
| 781 | return ECC_BAD_ARG_E;
|
---|
| 782 |
|
---|
| 783 | if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
|
---|
| 784 | return err;
|
---|
| 785 | }
|
---|
| 786 |
|
---|
| 787 | if (P != R) {
|
---|
| 788 | err = mp_copy(P->x, R->x);
|
---|
| 789 | if (err == MP_OKAY)
|
---|
| 790 | err = mp_copy(P->y, R->y);
|
---|
| 791 | if (err == MP_OKAY)
|
---|
| 792 | err = mp_copy(P->z, R->z);
|
---|
| 793 | }
|
---|
| 794 |
|
---|
| 795 | /* t1 = Z * Z */
|
---|
| 796 | if (err == MP_OKAY)
|
---|
| 797 | err = mp_sqr(R->z, &t1);
|
---|
| 798 | if (err == MP_OKAY)
|
---|
| 799 | err = mp_montgomery_reduce(&t1, modulus, *mp);
|
---|
| 800 |
|
---|
| 801 | /* Z = Y * Z */
|
---|
| 802 | if (err == MP_OKAY)
|
---|
| 803 | err = mp_mul(R->z, R->y, R->z);
|
---|
| 804 | if (err == MP_OKAY)
|
---|
| 805 | err = mp_montgomery_reduce(R->z, modulus, *mp);
|
---|
| 806 |
|
---|
| 807 | /* Z = 2Z */
|
---|
| 808 | if (err == MP_OKAY)
|
---|
| 809 | err = mp_add(R->z, R->z, R->z);
|
---|
| 810 | if (err == MP_OKAY) {
|
---|
| 811 | if (mp_cmp(R->z, modulus) != MP_LT)
|
---|
| 812 | err = mp_sub(R->z, modulus, R->z);
|
---|
| 813 | }
|
---|
| 814 |
|
---|
| 815 | /* T2 = X - T1 */
|
---|
| 816 | if (err == MP_OKAY)
|
---|
| 817 | err = mp_sub(R->x, &t1, &t2);
|
---|
| 818 | if (err == MP_OKAY) {
|
---|
| 819 | if (mp_cmp_d(&t2, 0) == MP_LT)
|
---|
| 820 | err = mp_add(&t2, modulus, &t2);
|
---|
| 821 | }
|
---|
| 822 | /* T1 = X + T1 */
|
---|
| 823 | if (err == MP_OKAY)
|
---|
| 824 | err = mp_add(&t1, R->x, &t1);
|
---|
| 825 | if (err == MP_OKAY) {
|
---|
| 826 | if (mp_cmp(&t1, modulus) != MP_LT)
|
---|
| 827 | err = mp_sub(&t1, modulus, &t1);
|
---|
| 828 | }
|
---|
| 829 | /* T2 = T1 * T2 */
|
---|
| 830 | if (err == MP_OKAY)
|
---|
| 831 | err = mp_mul(&t1, &t2, &t2);
|
---|
| 832 | if (err == MP_OKAY)
|
---|
| 833 | err = mp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 834 |
|
---|
| 835 | /* T1 = 2T2 */
|
---|
| 836 | if (err == MP_OKAY)
|
---|
| 837 | err = mp_add(&t2, &t2, &t1);
|
---|
| 838 | if (err == MP_OKAY) {
|
---|
| 839 | if (mp_cmp(&t1, modulus) != MP_LT)
|
---|
| 840 | err = mp_sub(&t1, modulus, &t1);
|
---|
| 841 | }
|
---|
| 842 | /* T1 = T1 + T2 */
|
---|
| 843 | if (err == MP_OKAY)
|
---|
| 844 | err = mp_add(&t1, &t2, &t1);
|
---|
| 845 | if (err == MP_OKAY) {
|
---|
| 846 | if (mp_cmp(&t1, modulus) != MP_LT)
|
---|
| 847 | err = mp_sub(&t1, modulus, &t1);
|
---|
| 848 | }
|
---|
| 849 | /* Y = 2Y */
|
---|
| 850 | if (err == MP_OKAY)
|
---|
| 851 | err = mp_add(R->y, R->y, R->y);
|
---|
| 852 | if (err == MP_OKAY) {
|
---|
| 853 | if (mp_cmp(R->y, modulus) != MP_LT)
|
---|
| 854 | err = mp_sub(R->y, modulus, R->y);
|
---|
| 855 | }
|
---|
| 856 | /* Y = Y * Y */
|
---|
| 857 | if (err == MP_OKAY)
|
---|
| 858 | err = mp_sqr(R->y, R->y);
|
---|
| 859 | if (err == MP_OKAY)
|
---|
| 860 | err = mp_montgomery_reduce(R->y, modulus, *mp);
|
---|
| 861 |
|
---|
| 862 | /* T2 = Y * Y */
|
---|
| 863 | if (err == MP_OKAY)
|
---|
| 864 | err = mp_sqr(R->y, &t2);
|
---|
| 865 | if (err == MP_OKAY)
|
---|
| 866 | err = mp_montgomery_reduce(&t2, modulus, *mp);
|
---|
| 867 |
|
---|
| 868 | /* T2 = T2/2 */
|
---|
| 869 | if (err == MP_OKAY) {
|
---|
| 870 | if (mp_isodd(&t2))
|
---|
| 871 | err = mp_add(&t2, modulus, &t2);
|
---|
| 872 | }
|
---|
| 873 | if (err == MP_OKAY)
|
---|
| 874 | err = mp_div_2(&t2, &t2);
|
---|
| 875 |
|
---|
| 876 | /* Y = Y * X */
|
---|
| 877 | if (err == MP_OKAY)
|
---|
| 878 | err = mp_mul(R->y, R->x, R->y);
|
---|
| 879 | if (err == MP_OKAY)
|
---|
| 880 | err = mp_montgomery_reduce(R->y, modulus, *mp);
|
---|
| 881 |
|
---|
| 882 | /* X = T1 * T1 */
|
---|
| 883 | if (err == MP_OKAY)
|
---|
| 884 | err = mp_sqr(&t1, R->x);
|
---|
| 885 | if (err == MP_OKAY)
|
---|
| 886 | err = mp_montgomery_reduce(R->x, modulus, *mp);
|
---|
| 887 |
|
---|
| 888 | /* X = X - Y */
|
---|
| 889 | if (err == MP_OKAY)
|
---|
| 890 | err = mp_sub(R->x, R->y, R->x);
|
---|
| 891 | if (err == MP_OKAY) {
|
---|
| 892 | if (mp_cmp_d(R->x, 0) == MP_LT)
|
---|
| 893 | err = mp_add(R->x, modulus, R->x);
|
---|
| 894 | }
|
---|
| 895 | /* X = X - Y */
|
---|
| 896 | if (err == MP_OKAY)
|
---|
| 897 | err = mp_sub(R->x, R->y, R->x);
|
---|
| 898 | if (err == MP_OKAY) {
|
---|
| 899 | if (mp_cmp_d(R->x, 0) == MP_LT)
|
---|
| 900 | err = mp_add(R->x, modulus, R->x);
|
---|
| 901 | }
|
---|
| 902 | /* Y = Y - X */
|
---|
| 903 | if (err == MP_OKAY)
|
---|
| 904 | err = mp_sub(R->y, R->x, R->y);
|
---|
| 905 | if (err == MP_OKAY) {
|
---|
| 906 | if (mp_cmp_d(R->y, 0) == MP_LT)
|
---|
| 907 | err = mp_add(R->y, modulus, R->y);
|
---|
| 908 | }
|
---|
| 909 | /* Y = Y * T1 */
|
---|
| 910 | if (err == MP_OKAY)
|
---|
| 911 | err = mp_mul(R->y, &t1, R->y);
|
---|
| 912 | if (err == MP_OKAY)
|
---|
| 913 | err = mp_montgomery_reduce(R->y, modulus, *mp);
|
---|
| 914 |
|
---|
| 915 | /* Y = Y - T2 */
|
---|
| 916 | if (err == MP_OKAY)
|
---|
| 917 | err = mp_sub(R->y, &t2, R->y);
|
---|
| 918 | if (err == MP_OKAY) {
|
---|
| 919 | if (mp_cmp_d(R->y, 0) == MP_LT)
|
---|
| 920 | err = mp_add(R->y, modulus, R->y);
|
---|
| 921 | }
|
---|
| 922 |
|
---|
| 923 | /* clean up */
|
---|
| 924 | mp_clear(&t1);
|
---|
| 925 | mp_clear(&t2);
|
---|
| 926 |
|
---|
| 927 | return err;
|
---|
| 928 | }
|
---|
| 929 |
|
---|
| 930 | #endif /* USE_FAST_MATH */
|
---|
| 931 |
|
---|
| 932 | /**
|
---|
| 933 | Map a projective jacbobian point back to affine space
|
---|
| 934 | P [in/out] The point to map
|
---|
| 935 | modulus The modulus of the field the ECC curve is in
|
---|
| 936 | mp The "b" value from montgomery_setup()
|
---|
| 937 | return MP_OKAY on success
|
---|
| 938 | */
|
---|
| 939 | int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp)
|
---|
| 940 | {
|
---|
| 941 | mp_int t1;
|
---|
| 942 | mp_int t2;
|
---|
| 943 | int err;
|
---|
| 944 |
|
---|
| 945 | if (P == NULL || mp == NULL || modulus == NULL)
|
---|
| 946 | return ECC_BAD_ARG_E;
|
---|
| 947 |
|
---|
| 948 | /* special case for point at infinity */
|
---|
| 949 | if (mp_cmp_d(P->z, 0) == MP_EQ) {
|
---|
| 950 | mp_set(P->x, 0);
|
---|
| 951 | mp_set(P->y, 0);
|
---|
| 952 | mp_set(P->z, 1);
|
---|
| 953 | return MP_OKAY;
|
---|
| 954 | }
|
---|
| 955 |
|
---|
| 956 | if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
|
---|
| 957 | return MEMORY_E;
|
---|
| 958 | }
|
---|
| 959 |
|
---|
| 960 | /* first map z back to normal */
|
---|
| 961 | err = mp_montgomery_reduce(P->z, modulus, *mp);
|
---|
| 962 |
|
---|
| 963 | /* get 1/z */
|
---|
| 964 | if (err == MP_OKAY)
|
---|
| 965 | err = mp_invmod(P->z, modulus, &t1);
|
---|
| 966 |
|
---|
| 967 | /* get 1/z^2 and 1/z^3 */
|
---|
| 968 | if (err == MP_OKAY)
|
---|
| 969 | err = mp_sqr(&t1, &t2);
|
---|
| 970 | if (err == MP_OKAY)
|
---|
| 971 | err = mp_mod(&t2, modulus, &t2);
|
---|
| 972 | if (err == MP_OKAY)
|
---|
| 973 | err = mp_mul(&t1, &t2, &t1);
|
---|
| 974 | if (err == MP_OKAY)
|
---|
| 975 | err = mp_mod(&t1, modulus, &t1);
|
---|
| 976 |
|
---|
| 977 | /* multiply against x/y */
|
---|
| 978 | if (err == MP_OKAY)
|
---|
| 979 | err = mp_mul(P->x, &t2, P->x);
|
---|
| 980 | if (err == MP_OKAY)
|
---|
| 981 | err = mp_montgomery_reduce(P->x, modulus, *mp);
|
---|
| 982 | if (err == MP_OKAY)
|
---|
| 983 | err = mp_mul(P->y, &t1, P->y);
|
---|
| 984 | if (err == MP_OKAY)
|
---|
| 985 | err = mp_montgomery_reduce(P->y, modulus, *mp);
|
---|
| 986 |
|
---|
| 987 | if (err == MP_OKAY)
|
---|
| 988 | mp_set(P->z, 1);
|
---|
| 989 |
|
---|
| 990 | /* clean up */
|
---|
| 991 | mp_clear(&t1);
|
---|
| 992 | mp_clear(&t2);
|
---|
| 993 |
|
---|
| 994 | return err;
|
---|
| 995 | }
|
---|
| 996 |
|
---|
| 997 |
|
---|
| 998 | #ifndef ECC_TIMING_RESISTANT
|
---|
| 999 |
|
---|
| 1000 | /* size of sliding window, don't change this! */
|
---|
| 1001 | #define WINSIZE 4
|
---|
| 1002 |
|
---|
| 1003 | /**
|
---|
| 1004 | Perform a point multiplication
|
---|
| 1005 | k The scalar to multiply by
|
---|
| 1006 | G The base point
|
---|
| 1007 | R [out] Destination for kG
|
---|
| 1008 | modulus The modulus of the field the ECC curve is in
|
---|
| 1009 | map Boolean whether to map back to affine or not
|
---|
| 1010 | (1==map, 0 == leave in projective)
|
---|
| 1011 | return MP_OKAY on success
|
---|
| 1012 | */
|
---|
| 1013 | #ifdef FP_ECC
|
---|
| 1014 | static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
|
---|
| 1015 | mp_int* modulus, int map)
|
---|
| 1016 | #else
|
---|
| 1017 | int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
|
---|
| 1018 | int map)
|
---|
| 1019 | #endif
|
---|
| 1020 | {
|
---|
| 1021 | ecc_point *tG, *M[8];
|
---|
| 1022 | int i, j, err;
|
---|
| 1023 | mp_int mu;
|
---|
| 1024 | mp_digit mp;
|
---|
| 1025 | mp_digit buf;
|
---|
| 1026 | int first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0,
|
---|
| 1027 | digidx = 0;
|
---|
| 1028 |
|
---|
| 1029 | if (k == NULL || G == NULL || R == NULL || modulus == NULL)
|
---|
| 1030 | return ECC_BAD_ARG_E;
|
---|
| 1031 |
|
---|
| 1032 | /* init montgomery reduction */
|
---|
| 1033 | if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
|
---|
| 1034 | return err;
|
---|
| 1035 | }
|
---|
| 1036 | if ((err = mp_init(&mu)) != MP_OKAY) {
|
---|
| 1037 | return err;
|
---|
| 1038 | }
|
---|
| 1039 | if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
|
---|
| 1040 | mp_clear(&mu);
|
---|
| 1041 | return err;
|
---|
| 1042 | }
|
---|
| 1043 |
|
---|
| 1044 | /* alloc ram for window temps */
|
---|
| 1045 | for (i = 0; i < 8; i++) {
|
---|
| 1046 | M[i] = wc_ecc_new_point();
|
---|
| 1047 | if (M[i] == NULL) {
|
---|
| 1048 | for (j = 0; j < i; j++) {
|
---|
| 1049 | wc_ecc_del_point(M[j]);
|
---|
| 1050 | }
|
---|
| 1051 | mp_clear(&mu);
|
---|
| 1052 | return MEMORY_E;
|
---|
| 1053 | }
|
---|
| 1054 | }
|
---|
| 1055 |
|
---|
| 1056 | /* make a copy of G incase R==G */
|
---|
| 1057 | tG = wc_ecc_new_point();
|
---|
| 1058 | if (tG == NULL)
|
---|
| 1059 | err = MEMORY_E;
|
---|
| 1060 |
|
---|
| 1061 | /* tG = G and convert to montgomery */
|
---|
| 1062 | if (err == MP_OKAY) {
|
---|
| 1063 | if (mp_cmp_d(&mu, 1) == MP_EQ) {
|
---|
| 1064 | err = mp_copy(G->x, tG->x);
|
---|
| 1065 | if (err == MP_OKAY)
|
---|
| 1066 | err = mp_copy(G->y, tG->y);
|
---|
| 1067 | if (err == MP_OKAY)
|
---|
| 1068 | err = mp_copy(G->z, tG->z);
|
---|
| 1069 | } else {
|
---|
| 1070 | err = mp_mulmod(G->x, &mu, modulus, tG->x);
|
---|
| 1071 | if (err == MP_OKAY)
|
---|
| 1072 | err = mp_mulmod(G->y, &mu, modulus, tG->y);
|
---|
| 1073 | if (err == MP_OKAY)
|
---|
| 1074 | err = mp_mulmod(G->z, &mu, modulus, tG->z);
|
---|
| 1075 | }
|
---|
| 1076 | }
|
---|
| 1077 | mp_clear(&mu);
|
---|
| 1078 |
|
---|
| 1079 | /* calc the M tab, which holds kG for k==8..15 */
|
---|
| 1080 | /* M[0] == 8G */
|
---|
| 1081 | if (err == MP_OKAY)
|
---|
| 1082 | err = ecc_projective_dbl_point(tG, M[0], modulus, &mp);
|
---|
| 1083 | if (err == MP_OKAY)
|
---|
| 1084 | err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
|
---|
| 1085 | if (err == MP_OKAY)
|
---|
| 1086 | err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
|
---|
| 1087 |
|
---|
| 1088 | /* now find (8+k)G for k=1..7 */
|
---|
| 1089 | if (err == MP_OKAY)
|
---|
| 1090 | for (j = 9; j < 16; j++) {
|
---|
| 1091 | err = ecc_projective_add_point(M[j-9], tG, M[j-8], modulus, &mp);
|
---|
| 1092 | if (err != MP_OKAY) break;
|
---|
| 1093 | }
|
---|
| 1094 |
|
---|
| 1095 | /* setup sliding window */
|
---|
| 1096 | if (err == MP_OKAY) {
|
---|
| 1097 | mode = 0;
|
---|
| 1098 | bitcnt = 1;
|
---|
| 1099 | buf = 0;
|
---|
| 1100 | digidx = get_digit_count(k) - 1;
|
---|
| 1101 | bitcpy = bitbuf = 0;
|
---|
| 1102 | first = 1;
|
---|
| 1103 |
|
---|
| 1104 | /* perform ops */
|
---|
| 1105 | for (;;) {
|
---|
| 1106 | /* grab next digit as required */
|
---|
| 1107 | if (--bitcnt == 0) {
|
---|
| 1108 | if (digidx == -1) {
|
---|
| 1109 | break;
|
---|
| 1110 | }
|
---|
| 1111 | buf = get_digit(k, digidx);
|
---|
| 1112 | bitcnt = (int) DIGIT_BIT;
|
---|
| 1113 | --digidx;
|
---|
| 1114 | }
|
---|
| 1115 |
|
---|
| 1116 | /* grab the next msb from the ltiplicand */
|
---|
| 1117 | i = (int)(buf >> (DIGIT_BIT - 1)) & 1;
|
---|
| 1118 | buf <<= 1;
|
---|
| 1119 |
|
---|
| 1120 | /* skip leading zero bits */
|
---|
| 1121 | if (mode == 0 && i == 0)
|
---|
| 1122 | continue;
|
---|
| 1123 |
|
---|
| 1124 | /* if the bit is zero and mode == 1 then we double */
|
---|
| 1125 | if (mode == 1 && i == 0) {
|
---|
| 1126 | err = ecc_projective_dbl_point(R, R, modulus, &mp);
|
---|
| 1127 | if (err != MP_OKAY) break;
|
---|
| 1128 | continue;
|
---|
| 1129 | }
|
---|
| 1130 |
|
---|
| 1131 | /* else we add it to the window */
|
---|
| 1132 | bitbuf |= (i << (WINSIZE - ++bitcpy));
|
---|
| 1133 | mode = 2;
|
---|
| 1134 |
|
---|
| 1135 | if (bitcpy == WINSIZE) {
|
---|
| 1136 | /* if this is the first window we do a simple copy */
|
---|
| 1137 | if (first == 1) {
|
---|
| 1138 | /* R = kG [k = first window] */
|
---|
| 1139 | err = mp_copy(M[bitbuf-8]->x, R->x);
|
---|
| 1140 | if (err != MP_OKAY) break;
|
---|
| 1141 |
|
---|
| 1142 | err = mp_copy(M[bitbuf-8]->y, R->y);
|
---|
| 1143 | if (err != MP_OKAY) break;
|
---|
| 1144 |
|
---|
| 1145 | err = mp_copy(M[bitbuf-8]->z, R->z);
|
---|
| 1146 | first = 0;
|
---|
| 1147 | } else {
|
---|
| 1148 | /* normal window */
|
---|
| 1149 | /* ok window is filled so double as required and add */
|
---|
| 1150 | /* double first */
|
---|
| 1151 | for (j = 0; j < WINSIZE; j++) {
|
---|
| 1152 | err = ecc_projective_dbl_point(R, R, modulus, &mp);
|
---|
| 1153 | if (err != MP_OKAY) break;
|
---|
| 1154 | }
|
---|
| 1155 | if (err != MP_OKAY) break; /* out of first for(;;) */
|
---|
| 1156 |
|
---|
| 1157 | /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranted */
|
---|
| 1158 | err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp);
|
---|
| 1159 | }
|
---|
| 1160 | if (err != MP_OKAY) break;
|
---|
| 1161 | /* empty window and reset */
|
---|
| 1162 | bitcpy = bitbuf = 0;
|
---|
| 1163 | mode = 1;
|
---|
| 1164 | }
|
---|
| 1165 | }
|
---|
| 1166 | }
|
---|
| 1167 |
|
---|
| 1168 | /* if bits remain then double/add */
|
---|
| 1169 | if (err == MP_OKAY) {
|
---|
| 1170 | if (mode == 2 && bitcpy > 0) {
|
---|
| 1171 | /* double then add */
|
---|
| 1172 | for (j = 0; j < bitcpy; j++) {
|
---|
| 1173 | /* only double if we have had at least one add first */
|
---|
| 1174 | if (first == 0) {
|
---|
| 1175 | err = ecc_projective_dbl_point(R, R, modulus, &mp);
|
---|
| 1176 | if (err != MP_OKAY) break;
|
---|
| 1177 | }
|
---|
| 1178 |
|
---|
| 1179 | bitbuf <<= 1;
|
---|
| 1180 | if ((bitbuf & (1 << WINSIZE)) != 0) {
|
---|
| 1181 | if (first == 1) {
|
---|
| 1182 | /* first add, so copy */
|
---|
| 1183 | err = mp_copy(tG->x, R->x);
|
---|
| 1184 | if (err != MP_OKAY) break;
|
---|
| 1185 |
|
---|
| 1186 | err = mp_copy(tG->y, R->y);
|
---|
| 1187 | if (err != MP_OKAY) break;
|
---|
| 1188 |
|
---|
| 1189 | err = mp_copy(tG->z, R->z);
|
---|
| 1190 | if (err != MP_OKAY) break;
|
---|
| 1191 | first = 0;
|
---|
| 1192 | } else {
|
---|
| 1193 | /* then add */
|
---|
| 1194 | err = ecc_projective_add_point(R, tG, R, modulus, &mp);
|
---|
| 1195 | if (err != MP_OKAY) break;
|
---|
| 1196 | }
|
---|
| 1197 | }
|
---|
| 1198 | }
|
---|
| 1199 | }
|
---|
| 1200 | }
|
---|
| 1201 |
|
---|
| 1202 | /* map R back from projective space */
|
---|
| 1203 | if (err == MP_OKAY && map)
|
---|
| 1204 | err = ecc_map(R, modulus, &mp);
|
---|
| 1205 |
|
---|
| 1206 | mp_clear(&mu);
|
---|
| 1207 | wc_ecc_del_point(tG);
|
---|
| 1208 | for (i = 0; i < 8; i++) {
|
---|
| 1209 | wc_ecc_del_point(M[i]);
|
---|
| 1210 | }
|
---|
| 1211 | return err;
|
---|
| 1212 | }
|
---|
| 1213 |
|
---|
| 1214 | #undef WINSIZE
|
---|
| 1215 |
|
---|
| 1216 | #else /* ECC_TIMING_RESISTANT */
|
---|
| 1217 |
|
---|
| 1218 | /**
|
---|
| 1219 | Perform a point multiplication (timing resistant)
|
---|
| 1220 | k The scalar to multiply by
|
---|
| 1221 | G The base point
|
---|
| 1222 | R [out] Destination for kG
|
---|
| 1223 | modulus The modulus of the field the ECC curve is in
|
---|
| 1224 | map Boolean whether to map back to affine or not
|
---|
| 1225 | (1==map, 0 == leave in projective)
|
---|
| 1226 | return MP_OKAY on success
|
---|
| 1227 | */
|
---|
| 1228 | #ifdef FP_ECC
|
---|
| 1229 | static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
|
---|
| 1230 | mp_int* modulus, int map)
|
---|
| 1231 | #else
|
---|
| 1232 | int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
|
---|
| 1233 | int map)
|
---|
| 1234 | #endif
|
---|
| 1235 | {
|
---|
| 1236 | ecc_point *tG, *M[3];
|
---|
| 1237 | int i, j, err;
|
---|
| 1238 | mp_int mu;
|
---|
| 1239 | mp_digit mp;
|
---|
| 1240 | mp_digit buf;
|
---|
| 1241 | int bitcnt = 0, mode = 0, digidx = 0;
|
---|
| 1242 |
|
---|
| 1243 | if (k == NULL || G == NULL || R == NULL || modulus == NULL)
|
---|
| 1244 | return ECC_BAD_ARG_E;
|
---|
| 1245 |
|
---|
| 1246 | /* init montgomery reduction */
|
---|
| 1247 | if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
|
---|
| 1248 | return err;
|
---|
| 1249 | }
|
---|
| 1250 | if ((err = mp_init(&mu)) != MP_OKAY) {
|
---|
| 1251 | return err;
|
---|
| 1252 | }
|
---|
| 1253 | if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
|
---|
| 1254 | mp_clear(&mu);
|
---|
| 1255 | return err;
|
---|
| 1256 | }
|
---|
| 1257 |
|
---|
| 1258 | /* alloc ram for window temps */
|
---|
| 1259 | for (i = 0; i < 3; i++) {
|
---|
| 1260 | M[i] = wc_ecc_new_point();
|
---|
| 1261 | if (M[i] == NULL) {
|
---|
| 1262 | for (j = 0; j < i; j++) {
|
---|
| 1263 | wc_ecc_del_point(M[j]);
|
---|
| 1264 | }
|
---|
| 1265 | mp_clear(&mu);
|
---|
| 1266 | return MEMORY_E;
|
---|
| 1267 | }
|
---|
| 1268 | }
|
---|
| 1269 |
|
---|
| 1270 | /* make a copy of G incase R==G */
|
---|
| 1271 | tG = wc_ecc_new_point();
|
---|
| 1272 | if (tG == NULL)
|
---|
| 1273 | err = MEMORY_E;
|
---|
| 1274 |
|
---|
| 1275 | /* tG = G and convert to montgomery */
|
---|
| 1276 | if (err == MP_OKAY) {
|
---|
| 1277 | err = mp_mulmod(G->x, &mu, modulus, tG->x);
|
---|
| 1278 | if (err == MP_OKAY)
|
---|
| 1279 | err = mp_mulmod(G->y, &mu, modulus, tG->y);
|
---|
| 1280 | if (err == MP_OKAY)
|
---|
| 1281 | err = mp_mulmod(G->z, &mu, modulus, tG->z);
|
---|
| 1282 | }
|
---|
| 1283 | mp_clear(&mu);
|
---|
| 1284 |
|
---|
| 1285 | /* calc the M tab */
|
---|
| 1286 | /* M[0] == G */
|
---|
| 1287 | if (err == MP_OKAY)
|
---|
| 1288 | err = mp_copy(tG->x, M[0]->x);
|
---|
| 1289 | if (err == MP_OKAY)
|
---|
| 1290 | err = mp_copy(tG->y, M[0]->y);
|
---|
| 1291 | if (err == MP_OKAY)
|
---|
| 1292 | err = mp_copy(tG->z, M[0]->z);
|
---|
| 1293 |
|
---|
| 1294 | /* M[1] == 2G */
|
---|
| 1295 | if (err == MP_OKAY)
|
---|
| 1296 | err = ecc_projective_dbl_point(tG, M[1], modulus, &mp);
|
---|
| 1297 |
|
---|
| 1298 | /* setup sliding window */
|
---|
| 1299 | mode = 0;
|
---|
| 1300 | bitcnt = 1;
|
---|
| 1301 | buf = 0;
|
---|
| 1302 | digidx = get_digit_count(k) - 1;
|
---|
| 1303 |
|
---|
| 1304 | /* perform ops */
|
---|
| 1305 | if (err == MP_OKAY) {
|
---|
| 1306 | for (;;) {
|
---|
| 1307 | /* grab next digit as required */
|
---|
| 1308 | if (--bitcnt == 0) {
|
---|
| 1309 | if (digidx == -1) {
|
---|
| 1310 | break;
|
---|
| 1311 | }
|
---|
| 1312 | buf = get_digit(k, digidx);
|
---|
| 1313 | bitcnt = (int) DIGIT_BIT;
|
---|
| 1314 | --digidx;
|
---|
| 1315 | }
|
---|
| 1316 |
|
---|
| 1317 | /* grab the next msb from the ltiplicand */
|
---|
| 1318 | i = (buf >> (DIGIT_BIT - 1)) & 1;
|
---|
| 1319 | buf <<= 1;
|
---|
| 1320 |
|
---|
| 1321 | if (mode == 0 && i == 0) {
|
---|
| 1322 | /* dummy operations */
|
---|
| 1323 | if (err == MP_OKAY)
|
---|
| 1324 | err = ecc_projective_add_point(M[0], M[1], M[2], modulus,
|
---|
| 1325 | &mp);
|
---|
| 1326 | if (err == MP_OKAY)
|
---|
| 1327 | err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp);
|
---|
| 1328 | if (err == MP_OKAY)
|
---|
| 1329 | continue;
|
---|
| 1330 | }
|
---|
| 1331 |
|
---|
| 1332 | if (mode == 0 && i == 1) {
|
---|
| 1333 | mode = 1;
|
---|
| 1334 | /* dummy operations */
|
---|
| 1335 | if (err == MP_OKAY)
|
---|
| 1336 | err = ecc_projective_add_point(M[0], M[1], M[2], modulus,
|
---|
| 1337 | &mp);
|
---|
| 1338 | if (err == MP_OKAY)
|
---|
| 1339 | err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp);
|
---|
| 1340 | if (err == MP_OKAY)
|
---|
| 1341 | continue;
|
---|
| 1342 | }
|
---|
| 1343 |
|
---|
| 1344 | if (err == MP_OKAY)
|
---|
| 1345 | err = ecc_projective_add_point(M[0], M[1], M[i^1], modulus, &mp);
|
---|
| 1346 | if (err == MP_OKAY)
|
---|
| 1347 | err = ecc_projective_dbl_point(M[i], M[i], modulus, &mp);
|
---|
| 1348 | if (err != MP_OKAY)
|
---|
| 1349 | break;
|
---|
| 1350 | } /* end for */
|
---|
| 1351 | }
|
---|
| 1352 |
|
---|
| 1353 | /* copy result out */
|
---|
| 1354 | if (err == MP_OKAY)
|
---|
| 1355 | err = mp_copy(M[0]->x, R->x);
|
---|
| 1356 | if (err == MP_OKAY)
|
---|
| 1357 | err = mp_copy(M[0]->y, R->y);
|
---|
| 1358 | if (err == MP_OKAY)
|
---|
| 1359 | err = mp_copy(M[0]->z, R->z);
|
---|
| 1360 |
|
---|
| 1361 | /* map R back from projective space */
|
---|
| 1362 | if (err == MP_OKAY && map)
|
---|
| 1363 | err = ecc_map(R, modulus, &mp);
|
---|
| 1364 |
|
---|
| 1365 | /* done */
|
---|
| 1366 | mp_clear(&mu);
|
---|
| 1367 | wc_ecc_del_point(tG);
|
---|
| 1368 | for (i = 0; i < 3; i++) {
|
---|
| 1369 | wc_ecc_del_point(M[i]);
|
---|
| 1370 | }
|
---|
| 1371 | return err;
|
---|
| 1372 | }
|
---|
| 1373 |
|
---|
| 1374 | #endif /* ECC_TIMING_RESISTANT */
|
---|
| 1375 |
|
---|
| 1376 |
|
---|
| 1377 | #ifdef ALT_ECC_SIZE
|
---|
| 1378 |
|
---|
| 1379 | static void alt_fp_init(fp_int* a)
|
---|
| 1380 | {
|
---|
| 1381 | a->size = FP_SIZE_ECC;
|
---|
| 1382 | fp_zero(a);
|
---|
| 1383 | }
|
---|
| 1384 |
|
---|
| 1385 | #endif /* ALT_ECC_SIZE */
|
---|
| 1386 |
|
---|
| 1387 |
|
---|
| 1388 | /**
|
---|
| 1389 | Allocate a new ECC point
|
---|
| 1390 | return A newly allocated point or NULL on error
|
---|
| 1391 | */
|
---|
| 1392 | ecc_point* wc_ecc_new_point(void)
|
---|
| 1393 | {
|
---|
| 1394 | ecc_point* p;
|
---|
| 1395 |
|
---|
| 1396 | p = (ecc_point*)XMALLOC(sizeof(ecc_point), 0, DYNAMIC_TYPE_ECC);
|
---|
| 1397 | if (p == NULL) {
|
---|
| 1398 | return NULL;
|
---|
| 1399 | }
|
---|
| 1400 | XMEMSET(p, 0, sizeof(ecc_point));
|
---|
| 1401 |
|
---|
| 1402 | #ifndef USE_FAST_MATH
|
---|
| 1403 | p->x->dp = NULL;
|
---|
| 1404 | p->y->dp = NULL;
|
---|
| 1405 | p->z->dp = NULL;
|
---|
| 1406 | #endif
|
---|
| 1407 |
|
---|
| 1408 | #ifndef ALT_ECC_SIZE
|
---|
| 1409 | if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) {
|
---|
| 1410 | XFREE(p, 0, DYNAMIC_TYPE_ECC);
|
---|
| 1411 | return NULL;
|
---|
| 1412 | }
|
---|
| 1413 | #else
|
---|
| 1414 | p->x = (mp_int*)&p->xyz[0];
|
---|
| 1415 | p->y = (mp_int*)&p->xyz[1];
|
---|
| 1416 | p->z = (mp_int*)&p->xyz[2];
|
---|
| 1417 | alt_fp_init(p->x);
|
---|
| 1418 | alt_fp_init(p->y);
|
---|
| 1419 | alt_fp_init(p->z);
|
---|
| 1420 | #endif
|
---|
| 1421 |
|
---|
| 1422 | return p;
|
---|
| 1423 | }
|
---|
| 1424 |
|
---|
| 1425 | /** Free an ECC point from memory
|
---|
| 1426 | p The point to free
|
---|
| 1427 | */
|
---|
| 1428 | void wc_ecc_del_point(ecc_point* p)
|
---|
| 1429 | {
|
---|
| 1430 | /* prevents free'ing null arguments */
|
---|
| 1431 | if (p != NULL) {
|
---|
| 1432 | mp_clear(p->x);
|
---|
| 1433 | mp_clear(p->y);
|
---|
| 1434 | mp_clear(p->z);
|
---|
| 1435 | XFREE(p, 0, DYNAMIC_TYPE_ECC);
|
---|
| 1436 | }
|
---|
| 1437 | }
|
---|
| 1438 |
|
---|
| 1439 | /** Copy the value of a point to an other one
|
---|
| 1440 | p The point to copy
|
---|
| 1441 | r The created point
|
---|
| 1442 | */
|
---|
| 1443 | int wc_ecc_copy_point(ecc_point* p, ecc_point *r)
|
---|
| 1444 | {
|
---|
| 1445 | int ret;
|
---|
| 1446 |
|
---|
| 1447 | /* prevents null arguments */
|
---|
| 1448 | if (p == NULL || r == NULL)
|
---|
| 1449 | return ECC_BAD_ARG_E;
|
---|
| 1450 |
|
---|
| 1451 | ret = mp_copy(p->x, r->x);
|
---|
| 1452 | if (ret != MP_OKAY)
|
---|
| 1453 | return ret;
|
---|
| 1454 | ret = mp_copy(p->y, r->y);
|
---|
| 1455 | if (ret != MP_OKAY)
|
---|
| 1456 | return ret;
|
---|
| 1457 | ret = mp_copy(p->z, r->z);
|
---|
| 1458 | if (ret != MP_OKAY)
|
---|
| 1459 | return ret;
|
---|
| 1460 |
|
---|
| 1461 | return MP_OKAY;
|
---|
| 1462 | }
|
---|
| 1463 |
|
---|
| 1464 | /** Compare the value of a point with an other one
|
---|
| 1465 | a The point to compare
|
---|
| 1466 | b The othe point to compare
|
---|
| 1467 |
|
---|
| 1468 | return MP_EQ if equal, MP_LT/MP_GT if not, < 0 in case of error
|
---|
| 1469 | */
|
---|
| 1470 | int wc_ecc_cmp_point(ecc_point* a, ecc_point *b)
|
---|
| 1471 | {
|
---|
| 1472 | int ret;
|
---|
| 1473 |
|
---|
| 1474 | /* prevents null arguments */
|
---|
| 1475 | if (a == NULL || b == NULL)
|
---|
| 1476 | return BAD_FUNC_ARG;
|
---|
| 1477 |
|
---|
| 1478 | ret = mp_cmp(a->x, b->x);
|
---|
| 1479 | if (ret != MP_EQ)
|
---|
| 1480 | return ret;
|
---|
| 1481 | ret = mp_cmp(a->y, b->y);
|
---|
| 1482 | if (ret != MP_EQ)
|
---|
| 1483 | return ret;
|
---|
| 1484 | ret = mp_cmp(a->z, b->z);
|
---|
| 1485 | if (ret != MP_EQ)
|
---|
| 1486 | return ret;
|
---|
| 1487 |
|
---|
| 1488 | return MP_EQ;
|
---|
| 1489 | }
|
---|
| 1490 |
|
---|
| 1491 | /** Returns whether an ECC idx is valid or not
|
---|
| 1492 | n The idx number to check
|
---|
| 1493 | return 1 if valid, 0 if not
|
---|
| 1494 | */
|
---|
| 1495 | int wc_ecc_is_valid_idx(int n)
|
---|
| 1496 | {
|
---|
| 1497 | int x;
|
---|
| 1498 |
|
---|
| 1499 | for (x = 0; ecc_sets[x].size != 0; x++)
|
---|
| 1500 | ;
|
---|
| 1501 | /* -1 is a valid index --- indicating that the domain params
|
---|
| 1502 | were supplied by the user */
|
---|
| 1503 | if ((n >= -1) && (n < x)) {
|
---|
| 1504 | return 1;
|
---|
| 1505 | }
|
---|
| 1506 | return 0;
|
---|
| 1507 | }
|
---|
| 1508 |
|
---|
| 1509 |
|
---|
| 1510 | /**
|
---|
| 1511 | Create an ECC shared secret between two keys
|
---|
| 1512 | private_key The private ECC key
|
---|
| 1513 | public_key The public key
|
---|
| 1514 | out [out] Destination of the shared secret
|
---|
| 1515 | Conforms to EC-DH from ANSI X9.63
|
---|
| 1516 | outlen [in/out] The max size and resulting size of the shared secret
|
---|
| 1517 | return MP_OKAY if successful
|
---|
| 1518 | */
|
---|
| 1519 | int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
|
---|
| 1520 | word32* outlen)
|
---|
| 1521 | {
|
---|
| 1522 | word32 x = 0;
|
---|
| 1523 | ecc_point* result;
|
---|
| 1524 | mp_int prime;
|
---|
| 1525 | int err;
|
---|
| 1526 |
|
---|
| 1527 | if (private_key == NULL || public_key == NULL || out == NULL ||
|
---|
| 1528 | outlen == NULL)
|
---|
| 1529 | return BAD_FUNC_ARG;
|
---|
| 1530 |
|
---|
| 1531 | /* type valid? */
|
---|
| 1532 | if (private_key->type != ECC_PRIVATEKEY) {
|
---|
| 1533 | return ECC_BAD_ARG_E;
|
---|
| 1534 | }
|
---|
| 1535 |
|
---|
| 1536 | if (wc_ecc_is_valid_idx(private_key->idx) == 0 ||
|
---|
| 1537 | wc_ecc_is_valid_idx(public_key->idx) == 0)
|
---|
| 1538 | return ECC_BAD_ARG_E;
|
---|
| 1539 |
|
---|
| 1540 | if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0)
|
---|
| 1541 | return ECC_BAD_ARG_E;
|
---|
| 1542 |
|
---|
| 1543 | /* make new point */
|
---|
| 1544 | result = wc_ecc_new_point();
|
---|
| 1545 | if (result == NULL) {
|
---|
| 1546 | return MEMORY_E;
|
---|
| 1547 | }
|
---|
| 1548 |
|
---|
| 1549 | if ((err = mp_init(&prime)) != MP_OKAY) {
|
---|
| 1550 | wc_ecc_del_point(result);
|
---|
| 1551 | return err;
|
---|
| 1552 | }
|
---|
| 1553 |
|
---|
| 1554 | err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16);
|
---|
| 1555 |
|
---|
| 1556 | if (err == MP_OKAY)
|
---|
| 1557 | err = wc_ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime,1);
|
---|
| 1558 |
|
---|
| 1559 | if (err == MP_OKAY) {
|
---|
| 1560 | x = mp_unsigned_bin_size(&prime);
|
---|
| 1561 | if (*outlen < x)
|
---|
| 1562 | err = BUFFER_E;
|
---|
| 1563 | }
|
---|
| 1564 |
|
---|
| 1565 | if (err == MP_OKAY) {
|
---|
| 1566 | XMEMSET(out, 0, x);
|
---|
| 1567 | err = mp_to_unsigned_bin(result->x,out + (x -
|
---|
| 1568 | mp_unsigned_bin_size(result->x)));
|
---|
| 1569 | *outlen = x;
|
---|
| 1570 | }
|
---|
| 1571 |
|
---|
| 1572 | mp_clear(&prime);
|
---|
| 1573 | wc_ecc_del_point(result);
|
---|
| 1574 |
|
---|
| 1575 | return err;
|
---|
| 1576 | }
|
---|
| 1577 |
|
---|
| 1578 | /**
|
---|
| 1579 | Create an ECC shared secret between two keys
|
---|
| 1580 | private_key The private ECC key
|
---|
| 1581 | point The point to use (public key)
|
---|
| 1582 | out [out] Destination of the shared secret
|
---|
| 1583 | Conforms to EC-DH from ANSI X9.63
|
---|
| 1584 | outlen [in/out] The max size and resulting size of the shared secret
|
---|
| 1585 | return MP_OKAY if successful
|
---|
| 1586 | */
|
---|
| 1587 | int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point,
|
---|
| 1588 | byte* out, word32 *outlen)
|
---|
| 1589 | {
|
---|
| 1590 | word32 x = 0;
|
---|
| 1591 | ecc_point* result;
|
---|
| 1592 | mp_int prime;
|
---|
| 1593 | int err;
|
---|
| 1594 |
|
---|
| 1595 | if (private_key == NULL || point == NULL || out == NULL || outlen == NULL)
|
---|
| 1596 | return BAD_FUNC_ARG;
|
---|
| 1597 |
|
---|
| 1598 | /* type valid? */
|
---|
| 1599 | if (private_key->type != ECC_PRIVATEKEY) {
|
---|
| 1600 | return ECC_BAD_ARG_E;
|
---|
| 1601 | }
|
---|
| 1602 |
|
---|
| 1603 | if (wc_ecc_is_valid_idx(private_key->idx) == 0)
|
---|
| 1604 | return ECC_BAD_ARG_E;
|
---|
| 1605 |
|
---|
| 1606 | /* make new point */
|
---|
| 1607 | result = wc_ecc_new_point();
|
---|
| 1608 | if (result == NULL) {
|
---|
| 1609 | return MEMORY_E;
|
---|
| 1610 | }
|
---|
| 1611 |
|
---|
| 1612 | if ((err = mp_init(&prime)) != MP_OKAY) {
|
---|
| 1613 | wc_ecc_del_point(result);
|
---|
| 1614 | return err;
|
---|
| 1615 | }
|
---|
| 1616 |
|
---|
| 1617 | err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16);
|
---|
| 1618 |
|
---|
| 1619 | if (err == MP_OKAY)
|
---|
| 1620 | err = wc_ecc_mulmod(&private_key->k, point, result, &prime, 1);
|
---|
| 1621 |
|
---|
| 1622 | if (err == MP_OKAY) {
|
---|
| 1623 | x = mp_unsigned_bin_size(&prime);
|
---|
| 1624 | if (*outlen < x)
|
---|
| 1625 | err = BUFFER_E;
|
---|
| 1626 | }
|
---|
| 1627 |
|
---|
| 1628 | if (err == MP_OKAY) {
|
---|
| 1629 | XMEMSET(out, 0, x);
|
---|
| 1630 | err = mp_to_unsigned_bin(result->x,out +
|
---|
| 1631 | (x - mp_unsigned_bin_size(result->x)));
|
---|
| 1632 | *outlen = x;
|
---|
| 1633 | }
|
---|
| 1634 |
|
---|
| 1635 | mp_clear(&prime);
|
---|
| 1636 | wc_ecc_del_point(result);
|
---|
| 1637 |
|
---|
| 1638 | return err;
|
---|
| 1639 | }
|
---|
| 1640 |
|
---|
| 1641 |
|
---|
| 1642 | /* return 1 if point is at infinity, 0 if not, < 0 on error */
|
---|
| 1643 | int wc_ecc_point_is_at_infinity(ecc_point* p)
|
---|
| 1644 | {
|
---|
| 1645 | if (p == NULL)
|
---|
| 1646 | return BAD_FUNC_ARG;
|
---|
| 1647 |
|
---|
| 1648 | if (get_digit_count(p->x) == 0 && get_digit_count(p->y) == 0)
|
---|
| 1649 | return 1;
|
---|
| 1650 |
|
---|
| 1651 | return 0;
|
---|
| 1652 | }
|
---|
| 1653 |
|
---|
| 1654 |
|
---|
| 1655 | static int wc_ecc_make_key_ex(WC_RNG* rng, ecc_key* key, const ecc_set_type* dp)
|
---|
| 1656 | {
|
---|
| 1657 | int err;
|
---|
| 1658 | ecc_point* base;
|
---|
| 1659 | mp_int prime;
|
---|
| 1660 | mp_int order;
|
---|
| 1661 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 1662 | byte* buf;
|
---|
| 1663 | #else
|
---|
| 1664 | byte buf[ECC_MAXSIZE_GEN];
|
---|
| 1665 | #endif
|
---|
| 1666 | int keysize;
|
---|
| 1667 | int po_init = 0; /* prime order Init flag for clear */
|
---|
| 1668 |
|
---|
| 1669 | if (key == NULL || rng == NULL || dp == NULL)
|
---|
| 1670 | return ECC_BAD_ARG_E;
|
---|
| 1671 |
|
---|
| 1672 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 1673 | buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 1674 | if (buf == NULL)
|
---|
| 1675 | return MEMORY_E;
|
---|
| 1676 | #endif
|
---|
| 1677 |
|
---|
| 1678 | key->idx = -1;
|
---|
| 1679 | key->dp = dp;
|
---|
| 1680 |
|
---|
| 1681 | /*generate 8 extra bytes to mitigate bias from the modulo operation below*/
|
---|
| 1682 | /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/
|
---|
| 1683 | keysize = dp->size + 8;
|
---|
| 1684 |
|
---|
| 1685 | /* allocate ram */
|
---|
| 1686 | base = NULL;
|
---|
| 1687 |
|
---|
| 1688 | /* make up random string */
|
---|
| 1689 | err = wc_RNG_GenerateBlock(rng, buf, keysize);
|
---|
| 1690 |
|
---|
| 1691 | /* setup the key variables */
|
---|
| 1692 | if (err == 0) {
|
---|
| 1693 | #ifndef ALT_ECC_SIZE
|
---|
| 1694 | err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z,
|
---|
| 1695 | &key->k, &prime, &order);
|
---|
| 1696 | #else
|
---|
| 1697 | key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
|
---|
| 1698 | key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
|
---|
| 1699 | key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
|
---|
| 1700 | alt_fp_init(key->pubkey.x);
|
---|
| 1701 | alt_fp_init(key->pubkey.y);
|
---|
| 1702 | alt_fp_init(key->pubkey.z);
|
---|
| 1703 | err = mp_init_multi(&key->k, &prime, &order, NULL, NULL, NULL);
|
---|
| 1704 | #endif
|
---|
| 1705 | if (err != MP_OKAY)
|
---|
| 1706 | err = MEMORY_E;
|
---|
| 1707 | else
|
---|
| 1708 | po_init = 1;
|
---|
| 1709 | }
|
---|
| 1710 |
|
---|
| 1711 | if (err == MP_OKAY) {
|
---|
| 1712 | base = wc_ecc_new_point();
|
---|
| 1713 | if (base == NULL)
|
---|
| 1714 | err = MEMORY_E;
|
---|
| 1715 | }
|
---|
| 1716 |
|
---|
| 1717 | /* read in the specs for this key */
|
---|
| 1718 | if (err == MP_OKAY)
|
---|
| 1719 | err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
|
---|
| 1720 | if (err == MP_OKAY)
|
---|
| 1721 | err = mp_read_radix(&order, (char *)key->dp->order, 16);
|
---|
| 1722 | if (err == MP_OKAY)
|
---|
| 1723 | err = mp_read_radix(base->x, (char *)key->dp->Gx, 16);
|
---|
| 1724 | if (err == MP_OKAY)
|
---|
| 1725 | err = mp_read_radix(base->y, (char *)key->dp->Gy, 16);
|
---|
| 1726 |
|
---|
| 1727 | if (err == MP_OKAY)
|
---|
| 1728 | mp_set(base->z, 1);
|
---|
| 1729 | if (err == MP_OKAY)
|
---|
| 1730 | err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize);
|
---|
| 1731 |
|
---|
| 1732 | /* quick sanity check to make sure we're not dealing with a 0 key */
|
---|
| 1733 | if (err == MP_OKAY) {
|
---|
| 1734 | if (MP_YES == mp_iszero(&key->k))
|
---|
| 1735 | err = MP_ZERO_E;
|
---|
| 1736 | }
|
---|
| 1737 |
|
---|
| 1738 | /* the key should be smaller than the order of base point */
|
---|
| 1739 | if (err == MP_OKAY) {
|
---|
| 1740 | if (mp_cmp(&key->k, &order) != MP_LT)
|
---|
| 1741 | err = mp_mod(&key->k, &order, &key->k);
|
---|
| 1742 | }
|
---|
| 1743 | /* make the public key */
|
---|
| 1744 | if (err == MP_OKAY)
|
---|
| 1745 | err = wc_ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1);
|
---|
| 1746 |
|
---|
| 1747 | #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN
|
---|
| 1748 | /* validate the public key, order * pubkey = point at infinity */
|
---|
| 1749 | if (err == MP_OKAY)
|
---|
| 1750 | err = ecc_check_pubkey_order(key, &prime, &order);
|
---|
| 1751 | #endif /* WOLFSSL_VALIDATE_KEYGEN */
|
---|
| 1752 |
|
---|
| 1753 | if (err == MP_OKAY)
|
---|
| 1754 | key->type = ECC_PRIVATEKEY;
|
---|
| 1755 |
|
---|
| 1756 | if (err != MP_OKAY) {
|
---|
| 1757 | /* clean up */
|
---|
| 1758 | mp_clear(key->pubkey.x);
|
---|
| 1759 | mp_clear(key->pubkey.y);
|
---|
| 1760 | mp_clear(key->pubkey.z);
|
---|
| 1761 | mp_clear(&key->k);
|
---|
| 1762 | }
|
---|
| 1763 | wc_ecc_del_point(base);
|
---|
| 1764 | if (po_init) {
|
---|
| 1765 | mp_clear(&prime);
|
---|
| 1766 | mp_clear(&order);
|
---|
| 1767 | }
|
---|
| 1768 |
|
---|
| 1769 | ForceZero(buf, ECC_MAXSIZE);
|
---|
| 1770 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 1771 | XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 1772 | #endif
|
---|
| 1773 |
|
---|
| 1774 | return err;
|
---|
| 1775 | }
|
---|
| 1776 |
|
---|
| 1777 | /**
|
---|
| 1778 | Make a new ECC key
|
---|
| 1779 | rng An active RNG state
|
---|
| 1780 | keysize The keysize for the new key (in octets from 20 to 65 bytes)
|
---|
| 1781 | key [out] Destination of the newly created key
|
---|
| 1782 | return MP_OKAY if successful,
|
---|
| 1783 | upon error all allocated memory will be freed
|
---|
| 1784 | */
|
---|
| 1785 | int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key)
|
---|
| 1786 | {
|
---|
| 1787 | int x, err;
|
---|
| 1788 |
|
---|
| 1789 | if (key == NULL || rng == NULL)
|
---|
| 1790 | return ECC_BAD_ARG_E;
|
---|
| 1791 |
|
---|
| 1792 | /* find key size */
|
---|
| 1793 | for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++)
|
---|
| 1794 | ;
|
---|
| 1795 | keysize = ecc_sets[x].size;
|
---|
| 1796 |
|
---|
| 1797 | if (keysize > ECC_MAXSIZE || ecc_sets[x].size == 0) {
|
---|
| 1798 | return BAD_FUNC_ARG;
|
---|
| 1799 | }
|
---|
| 1800 | err = wc_ecc_make_key_ex(rng, key, &ecc_sets[x]);
|
---|
| 1801 | key->idx = x;
|
---|
| 1802 |
|
---|
| 1803 | return err;
|
---|
| 1804 | }
|
---|
| 1805 |
|
---|
| 1806 | /* Setup dynamic pointers is using normal math for proper freeing */
|
---|
| 1807 | int wc_ecc_init(ecc_key* key)
|
---|
| 1808 | {
|
---|
| 1809 | (void)key;
|
---|
| 1810 |
|
---|
| 1811 | #ifndef USE_FAST_MATH
|
---|
| 1812 | key->pubkey.x->dp = NULL;
|
---|
| 1813 | key->pubkey.y->dp = NULL;
|
---|
| 1814 | key->pubkey.z->dp = NULL;
|
---|
| 1815 |
|
---|
| 1816 | key->k.dp = NULL;
|
---|
| 1817 | #endif
|
---|
| 1818 |
|
---|
| 1819 | #ifdef ALT_ECC_SIZE
|
---|
| 1820 | if (mp_init(&key->k) != MP_OKAY)
|
---|
| 1821 | return MEMORY_E;
|
---|
| 1822 |
|
---|
| 1823 | key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
|
---|
| 1824 | key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
|
---|
| 1825 | key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
|
---|
| 1826 | alt_fp_init(key->pubkey.x);
|
---|
| 1827 | alt_fp_init(key->pubkey.y);
|
---|
| 1828 | alt_fp_init(key->pubkey.z);
|
---|
| 1829 | #endif
|
---|
| 1830 |
|
---|
| 1831 | return MP_OKAY;
|
---|
| 1832 | }
|
---|
| 1833 |
|
---|
| 1834 |
|
---|
| 1835 | /**
|
---|
| 1836 | Sign a message digest
|
---|
| 1837 | in The message digest to sign
|
---|
| 1838 | inlen The length of the digest
|
---|
| 1839 | out [out] The destination for the signature
|
---|
| 1840 | outlen [in/out] The max size and resulting size of the signature
|
---|
| 1841 | key A private ECC key
|
---|
| 1842 | return MP_OKAY if successful
|
---|
| 1843 | */
|
---|
| 1844 | int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
|
---|
| 1845 | WC_RNG* rng, ecc_key* key)
|
---|
| 1846 | {
|
---|
| 1847 | mp_int r;
|
---|
| 1848 | mp_int s;
|
---|
| 1849 | int err;
|
---|
| 1850 |
|
---|
| 1851 | if (in == NULL || out == NULL || outlen == NULL ||
|
---|
| 1852 | key == NULL || rng == NULL)
|
---|
| 1853 | return ECC_BAD_ARG_E;
|
---|
| 1854 |
|
---|
| 1855 | if ((err = mp_init_multi(&r, &s, NULL, NULL, NULL, NULL)) != MP_OKAY) {
|
---|
| 1856 | return err;
|
---|
| 1857 | }
|
---|
| 1858 |
|
---|
| 1859 | err = wc_ecc_sign_hash_ex(in, inlen, rng, key, &r, &s);
|
---|
| 1860 | if (err == MP_OKAY)
|
---|
| 1861 | err = StoreECC_DSA_Sig(out, outlen, &r, &s);
|
---|
| 1862 |
|
---|
| 1863 | mp_clear(&r);
|
---|
| 1864 | mp_clear(&s);
|
---|
| 1865 |
|
---|
| 1866 | return err;
|
---|
| 1867 | }
|
---|
| 1868 |
|
---|
| 1869 | /**
|
---|
| 1870 | Sign a message digest
|
---|
| 1871 | in The message digest to sign
|
---|
| 1872 | inlen The length of the digest
|
---|
| 1873 | out [out] The destination for the signature
|
---|
| 1874 | outlen [in/out] The max size and resulting size of the signature
|
---|
| 1875 | key A private ECC key
|
---|
| 1876 | r [out] The destination for r component of the signature
|
---|
| 1877 | s [out] The destination for s component of the signature
|
---|
| 1878 | return MP_OKAY if successful
|
---|
| 1879 | */
|
---|
| 1880 | int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
|
---|
| 1881 | ecc_key* key, mp_int *r, mp_int *s)
|
---|
| 1882 | {
|
---|
| 1883 | mp_int e;
|
---|
| 1884 | mp_int p;
|
---|
| 1885 | int err;
|
---|
| 1886 |
|
---|
| 1887 | if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL)
|
---|
| 1888 | return ECC_BAD_ARG_E;
|
---|
| 1889 |
|
---|
| 1890 | /* is this a private key? */
|
---|
| 1891 | if (key->type != ECC_PRIVATEKEY) {
|
---|
| 1892 | return ECC_BAD_ARG_E;
|
---|
| 1893 | }
|
---|
| 1894 |
|
---|
| 1895 | /* is the IDX valid ? */
|
---|
| 1896 | if (wc_ecc_is_valid_idx(key->idx) != 1) {
|
---|
| 1897 | return ECC_BAD_ARG_E;
|
---|
| 1898 | }
|
---|
| 1899 |
|
---|
| 1900 | /* get the hash and load it as a bignum into 'e' */
|
---|
| 1901 | /* init the bignums */
|
---|
| 1902 | if ((err = mp_init_multi(&p, &e, NULL, NULL, NULL, NULL)) != MP_OKAY) {
|
---|
| 1903 | return err;
|
---|
| 1904 | }
|
---|
| 1905 | err = mp_read_radix(&p, (char *)key->dp->order, 16);
|
---|
| 1906 |
|
---|
| 1907 | if (err == MP_OKAY) {
|
---|
| 1908 | /* we may need to truncate if hash is longer than key size */
|
---|
| 1909 | word32 orderBits = mp_count_bits(&p);
|
---|
| 1910 |
|
---|
| 1911 | /* truncate down to byte size, may be all that's needed */
|
---|
| 1912 | if ( (WOLFSSL_BIT_SIZE * inlen) > orderBits)
|
---|
| 1913 | inlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE;
|
---|
| 1914 | err = mp_read_unsigned_bin(&e, (byte*)in, inlen);
|
---|
| 1915 |
|
---|
| 1916 | /* may still need bit truncation too */
|
---|
| 1917 | if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits)
|
---|
| 1918 | mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
|
---|
| 1919 | }
|
---|
| 1920 |
|
---|
| 1921 | /* make up a key and export the public copy */
|
---|
| 1922 | if (err == MP_OKAY) {
|
---|
| 1923 | int loop_check = 0;
|
---|
| 1924 | ecc_key pubkey;
|
---|
| 1925 | if (wc_ecc_init(&pubkey) == MP_OKAY) {
|
---|
| 1926 | for (;;) {
|
---|
| 1927 | if (++loop_check > 64) {
|
---|
| 1928 | err = RNG_FAILURE_E;
|
---|
| 1929 | break;
|
---|
| 1930 | }
|
---|
| 1931 | err = wc_ecc_make_key_ex(rng, &pubkey, key->dp);
|
---|
| 1932 | if (err != MP_OKAY) break;
|
---|
| 1933 |
|
---|
| 1934 | /* find r = x1 mod n */
|
---|
| 1935 | err = mp_mod(pubkey.pubkey.x, &p, r);
|
---|
| 1936 | if (err != MP_OKAY) break;
|
---|
| 1937 |
|
---|
| 1938 | if (mp_iszero(r) == MP_YES) {
|
---|
| 1939 | mp_clear(pubkey.pubkey.x);
|
---|
| 1940 | mp_clear(pubkey.pubkey.y);
|
---|
| 1941 | mp_clear(pubkey.pubkey.z);
|
---|
| 1942 | mp_clear(&pubkey.k);
|
---|
| 1943 | }
|
---|
| 1944 | else {
|
---|
| 1945 | /* find s = (e + xr)/k */
|
---|
| 1946 | err = mp_invmod(&pubkey.k, &p, &pubkey.k);
|
---|
| 1947 | if (err != MP_OKAY) break;
|
---|
| 1948 |
|
---|
| 1949 | err = mp_mulmod(&key->k, r, &p, s); /* s = xr */
|
---|
| 1950 | if (err != MP_OKAY) break;
|
---|
| 1951 |
|
---|
| 1952 | err = mp_add(&e, s, s); /* s = e + xr */
|
---|
| 1953 | if (err != MP_OKAY) break;
|
---|
| 1954 |
|
---|
| 1955 | err = mp_mod(s, &p, s); /* s = e + xr */
|
---|
| 1956 | if (err != MP_OKAY) break;
|
---|
| 1957 |
|
---|
| 1958 | err = mp_mulmod(s, &pubkey.k, &p, s); /* s = (e + xr)/k */
|
---|
| 1959 | if (err != MP_OKAY) break;
|
---|
| 1960 |
|
---|
| 1961 | if (mp_iszero(s) == MP_NO)
|
---|
| 1962 | break;
|
---|
| 1963 | }
|
---|
| 1964 | }
|
---|
| 1965 | wc_ecc_free(&pubkey);
|
---|
| 1966 | }
|
---|
| 1967 | }
|
---|
| 1968 |
|
---|
| 1969 | mp_clear(&p);
|
---|
| 1970 | mp_clear(&e);
|
---|
| 1971 |
|
---|
| 1972 | return err;
|
---|
| 1973 | }
|
---|
| 1974 |
|
---|
| 1975 |
|
---|
| 1976 | /**
|
---|
| 1977 | Free an ECC key from memory
|
---|
| 1978 | key The key you wish to free
|
---|
| 1979 | */
|
---|
| 1980 | void wc_ecc_free(ecc_key* key)
|
---|
| 1981 | {
|
---|
| 1982 | if (key == NULL)
|
---|
| 1983 | return;
|
---|
| 1984 |
|
---|
| 1985 | mp_clear(key->pubkey.x);
|
---|
| 1986 | mp_clear(key->pubkey.y);
|
---|
| 1987 | mp_clear(key->pubkey.z);
|
---|
| 1988 | mp_clear(&key->k);
|
---|
| 1989 | }
|
---|
| 1990 |
|
---|
| 1991 |
|
---|
| 1992 | #ifdef USE_FAST_MATH
|
---|
| 1993 | #define GEN_MEM_ERR FP_MEM
|
---|
| 1994 | #else
|
---|
| 1995 | #define GEN_MEM_ERR MP_MEM
|
---|
| 1996 | #endif
|
---|
| 1997 |
|
---|
| 1998 | #ifdef ECC_SHAMIR
|
---|
| 1999 |
|
---|
| 2000 | /** Computes kA*A + kB*B = C using Shamir's Trick
|
---|
| 2001 | A First point to multiply
|
---|
| 2002 | kA What to multiple A by
|
---|
| 2003 | B Second point to multiply
|
---|
| 2004 | kB What to multiple B by
|
---|
| 2005 | C [out] Destination point (can overlap with A or B)
|
---|
| 2006 | modulus Modulus for curve
|
---|
| 2007 | return MP_OKAY on success
|
---|
| 2008 | */
|
---|
| 2009 | #ifdef FP_ECC
|
---|
| 2010 | static int normal_ecc_mul2add(ecc_point* A, mp_int* kA,
|
---|
| 2011 | ecc_point* B, mp_int* kB,
|
---|
| 2012 | ecc_point* C, mp_int* modulus)
|
---|
| 2013 | #else
|
---|
| 2014 | static int ecc_mul2add(ecc_point* A, mp_int* kA,
|
---|
| 2015 | ecc_point* B, mp_int* kB,
|
---|
| 2016 | ecc_point* C, mp_int* modulus)
|
---|
| 2017 | #endif
|
---|
| 2018 | {
|
---|
| 2019 | ecc_point* precomp[16];
|
---|
| 2020 | unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;
|
---|
| 2021 | unsigned char* tA;
|
---|
| 2022 | unsigned char* tB;
|
---|
| 2023 | int err = MP_OKAY, first;
|
---|
| 2024 | int muInit = 0;
|
---|
| 2025 | int tableInit = 0;
|
---|
| 2026 | mp_digit mp;
|
---|
| 2027 | mp_int mu;
|
---|
| 2028 |
|
---|
| 2029 | /* argchks */
|
---|
| 2030 | if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL ||
|
---|
| 2031 | modulus == NULL)
|
---|
| 2032 | return ECC_BAD_ARG_E;
|
---|
| 2033 |
|
---|
| 2034 |
|
---|
| 2035 | /* allocate memory */
|
---|
| 2036 | tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2037 | if (tA == NULL) {
|
---|
| 2038 | return GEN_MEM_ERR;
|
---|
| 2039 | }
|
---|
| 2040 | tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2041 | if (tB == NULL) {
|
---|
| 2042 | XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2043 | return GEN_MEM_ERR;
|
---|
| 2044 | }
|
---|
| 2045 | XMEMSET(tA, 0, ECC_BUFSIZE);
|
---|
| 2046 | XMEMSET(tB, 0, ECC_BUFSIZE);
|
---|
| 2047 |
|
---|
| 2048 | /* get sizes */
|
---|
| 2049 | lenA = mp_unsigned_bin_size(kA);
|
---|
| 2050 | lenB = mp_unsigned_bin_size(kB);
|
---|
| 2051 | len = MAX(lenA, lenB);
|
---|
| 2052 |
|
---|
| 2053 | /* sanity check */
|
---|
| 2054 | if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) {
|
---|
| 2055 | err = BAD_FUNC_ARG;
|
---|
| 2056 | }
|
---|
| 2057 |
|
---|
| 2058 | if (err == MP_OKAY) {
|
---|
| 2059 | /* extract and justify kA */
|
---|
| 2060 | err = mp_to_unsigned_bin(kA, (len - lenA) + tA);
|
---|
| 2061 |
|
---|
| 2062 | /* extract and justify kB */
|
---|
| 2063 | if (err == MP_OKAY)
|
---|
| 2064 | err = mp_to_unsigned_bin(kB, (len - lenB) + tB);
|
---|
| 2065 |
|
---|
| 2066 | /* allocate the table */
|
---|
| 2067 | if (err == MP_OKAY) {
|
---|
| 2068 | for (x = 0; x < 16; x++) {
|
---|
| 2069 | precomp[x] = wc_ecc_new_point();
|
---|
| 2070 | if (precomp[x] == NULL) {
|
---|
| 2071 | for (y = 0; y < x; ++y) {
|
---|
| 2072 | wc_ecc_del_point(precomp[y]);
|
---|
| 2073 | }
|
---|
| 2074 | err = GEN_MEM_ERR;
|
---|
| 2075 | break;
|
---|
| 2076 | }
|
---|
| 2077 | }
|
---|
| 2078 | }
|
---|
| 2079 | }
|
---|
| 2080 |
|
---|
| 2081 | if (err == MP_OKAY)
|
---|
| 2082 | tableInit = 1;
|
---|
| 2083 |
|
---|
| 2084 | if (err == MP_OKAY)
|
---|
| 2085 | /* init montgomery reduction */
|
---|
| 2086 | err = mp_montgomery_setup(modulus, &mp);
|
---|
| 2087 |
|
---|
| 2088 | if (err == MP_OKAY)
|
---|
| 2089 | err = mp_init(&mu);
|
---|
| 2090 | if (err == MP_OKAY)
|
---|
| 2091 | muInit = 1;
|
---|
| 2092 |
|
---|
| 2093 | if (err == MP_OKAY)
|
---|
| 2094 | err = mp_montgomery_calc_normalization(&mu, modulus);
|
---|
| 2095 |
|
---|
| 2096 | if (err == MP_OKAY)
|
---|
| 2097 | /* copy ones ... */
|
---|
| 2098 | err = mp_mulmod(A->x, &mu, modulus, precomp[1]->x);
|
---|
| 2099 |
|
---|
| 2100 | if (err == MP_OKAY)
|
---|
| 2101 | err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y);
|
---|
| 2102 | if (err == MP_OKAY)
|
---|
| 2103 | err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z);
|
---|
| 2104 |
|
---|
| 2105 | if (err == MP_OKAY)
|
---|
| 2106 | err = mp_mulmod(B->x, &mu, modulus, precomp[1<<2]->x);
|
---|
| 2107 | if (err == MP_OKAY)
|
---|
| 2108 | err = mp_mulmod(B->y, &mu, modulus, precomp[1<<2]->y);
|
---|
| 2109 | if (err == MP_OKAY)
|
---|
| 2110 | err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z);
|
---|
| 2111 |
|
---|
| 2112 | if (err == MP_OKAY)
|
---|
| 2113 | /* precomp [i,0](A + B) table */
|
---|
| 2114 | err = ecc_projective_dbl_point(precomp[1], precomp[2], modulus, &mp);
|
---|
| 2115 |
|
---|
| 2116 | if (err == MP_OKAY)
|
---|
| 2117 | err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3],
|
---|
| 2118 | modulus, &mp);
|
---|
| 2119 | if (err == MP_OKAY)
|
---|
| 2120 | /* precomp [0,i](A + B) table */
|
---|
| 2121 | err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], modulus, &mp);
|
---|
| 2122 |
|
---|
| 2123 | if (err == MP_OKAY)
|
---|
| 2124 | err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2],
|
---|
| 2125 | modulus, &mp);
|
---|
| 2126 |
|
---|
| 2127 | if (err == MP_OKAY) {
|
---|
| 2128 | /* precomp [i,j](A + B) table (i != 0, j != 0) */
|
---|
| 2129 | for (x = 1; x < 4; x++) {
|
---|
| 2130 | for (y = 1; y < 4; y++) {
|
---|
| 2131 | if (err == MP_OKAY)
|
---|
| 2132 | err = ecc_projective_add_point(precomp[x], precomp[(y<<2)],
|
---|
| 2133 | precomp[x+(y<<2)], modulus, &mp);
|
---|
| 2134 | }
|
---|
| 2135 | }
|
---|
| 2136 | }
|
---|
| 2137 |
|
---|
| 2138 | if (err == MP_OKAY) {
|
---|
| 2139 | nibble = 3;
|
---|
| 2140 | first = 1;
|
---|
| 2141 | bitbufA = tA[0];
|
---|
| 2142 | bitbufB = tB[0];
|
---|
| 2143 |
|
---|
| 2144 | /* for every byte of the multiplicands */
|
---|
| 2145 | for (x = -1;; ) {
|
---|
| 2146 | /* grab a nibble */
|
---|
| 2147 | if (++nibble == 4) {
|
---|
| 2148 | ++x; if (x == len) break;
|
---|
| 2149 | bitbufA = tA[x];
|
---|
| 2150 | bitbufB = tB[x];
|
---|
| 2151 | nibble = 0;
|
---|
| 2152 | }
|
---|
| 2153 |
|
---|
| 2154 | /* extract two bits from both, shift/update */
|
---|
| 2155 | nA = (bitbufA >> 6) & 0x03;
|
---|
| 2156 | nB = (bitbufB >> 6) & 0x03;
|
---|
| 2157 | bitbufA = (bitbufA << 2) & 0xFF;
|
---|
| 2158 | bitbufB = (bitbufB << 2) & 0xFF;
|
---|
| 2159 |
|
---|
| 2160 | /* if both zero, if first, continue */
|
---|
| 2161 | if ((nA == 0) && (nB == 0) && (first == 1)) {
|
---|
| 2162 | continue;
|
---|
| 2163 | }
|
---|
| 2164 |
|
---|
| 2165 | /* double twice, only if this isn't the first */
|
---|
| 2166 | if (first == 0) {
|
---|
| 2167 | /* double twice */
|
---|
| 2168 | if (err == MP_OKAY)
|
---|
| 2169 | err = ecc_projective_dbl_point(C, C, modulus, &mp);
|
---|
| 2170 | if (err == MP_OKAY)
|
---|
| 2171 | err = ecc_projective_dbl_point(C, C, modulus, &mp);
|
---|
| 2172 | else
|
---|
| 2173 | break;
|
---|
| 2174 | }
|
---|
| 2175 |
|
---|
| 2176 | /* if not both zero */
|
---|
| 2177 | if ((nA != 0) || (nB != 0)) {
|
---|
| 2178 | if (first == 1) {
|
---|
| 2179 | /* if first, copy from table */
|
---|
| 2180 | first = 0;
|
---|
| 2181 | if (err == MP_OKAY)
|
---|
| 2182 | err = mp_copy(precomp[nA + (nB<<2)]->x, C->x);
|
---|
| 2183 |
|
---|
| 2184 | if (err == MP_OKAY)
|
---|
| 2185 | err = mp_copy(precomp[nA + (nB<<2)]->y, C->y);
|
---|
| 2186 |
|
---|
| 2187 | if (err == MP_OKAY)
|
---|
| 2188 | err = mp_copy(precomp[nA + (nB<<2)]->z, C->z);
|
---|
| 2189 | else
|
---|
| 2190 | break;
|
---|
| 2191 | } else {
|
---|
| 2192 | /* if not first, add from table */
|
---|
| 2193 | if (err == MP_OKAY)
|
---|
| 2194 | err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C,
|
---|
| 2195 | modulus, &mp);
|
---|
| 2196 | else
|
---|
| 2197 | break;
|
---|
| 2198 | }
|
---|
| 2199 | }
|
---|
| 2200 | }
|
---|
| 2201 | }
|
---|
| 2202 |
|
---|
| 2203 | if (err == MP_OKAY)
|
---|
| 2204 | /* reduce to affine */
|
---|
| 2205 | err = ecc_map(C, modulus, &mp);
|
---|
| 2206 |
|
---|
| 2207 | /* clean up */
|
---|
| 2208 | if (muInit)
|
---|
| 2209 | mp_clear(&mu);
|
---|
| 2210 |
|
---|
| 2211 | if (tableInit) {
|
---|
| 2212 | for (x = 0; x < 16; x++) {
|
---|
| 2213 | wc_ecc_del_point(precomp[x]);
|
---|
| 2214 | }
|
---|
| 2215 | }
|
---|
| 2216 | ForceZero(tA, ECC_BUFSIZE);
|
---|
| 2217 | ForceZero(tB, ECC_BUFSIZE);
|
---|
| 2218 | XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2219 | XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2220 |
|
---|
| 2221 | return err;
|
---|
| 2222 | }
|
---|
| 2223 |
|
---|
| 2224 |
|
---|
| 2225 | #endif /* ECC_SHAMIR */
|
---|
| 2226 |
|
---|
| 2227 |
|
---|
| 2228 |
|
---|
| 2229 | /* verify
|
---|
| 2230 | *
|
---|
| 2231 | * w = s^-1 mod n
|
---|
| 2232 | * u1 = xw
|
---|
| 2233 | * u2 = rw
|
---|
| 2234 | * X = u1*G + u2*Q
|
---|
| 2235 | * v = X_x1 mod n
|
---|
| 2236 | * accept if v == r
|
---|
| 2237 | */
|
---|
| 2238 |
|
---|
| 2239 | /**
|
---|
| 2240 | Verify an ECC signature
|
---|
| 2241 | sig The signature to verify
|
---|
| 2242 | siglen The length of the signature (octets)
|
---|
| 2243 | hash The hash (message digest) that was signed
|
---|
| 2244 | hashlen The length of the hash (octets)
|
---|
| 2245 | stat Result of signature, 1==valid, 0==invalid
|
---|
| 2246 | key The corresponding public ECC key
|
---|
| 2247 | return MP_OKAY if successful (even if the signature is not valid)
|
---|
| 2248 | */
|
---|
| 2249 | int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
|
---|
| 2250 | word32 hashlen, int* stat, ecc_key* key)
|
---|
| 2251 | {
|
---|
| 2252 | mp_int r;
|
---|
| 2253 | mp_int s;
|
---|
| 2254 | int err;
|
---|
| 2255 |
|
---|
| 2256 | if (sig == NULL || hash == NULL || stat == NULL || key == NULL)
|
---|
| 2257 | return ECC_BAD_ARG_E;
|
---|
| 2258 |
|
---|
| 2259 | /* default to invalid signature */
|
---|
| 2260 | *stat = 0;
|
---|
| 2261 |
|
---|
| 2262 | /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s.
|
---|
| 2263 | * If either of those don't allocate correctly, none of
|
---|
| 2264 | * the rest of this function will execute, and everything
|
---|
| 2265 | * gets cleaned up at the end. */
|
---|
| 2266 | XMEMSET(&r, 0, sizeof(r));
|
---|
| 2267 | XMEMSET(&s, 0, sizeof(s));
|
---|
| 2268 |
|
---|
| 2269 | err = DecodeECC_DSA_Sig(sig, siglen, &r, &s);
|
---|
| 2270 |
|
---|
| 2271 | if (err == MP_OKAY)
|
---|
| 2272 | err = wc_ecc_verify_hash_ex(&r, &s, hash, hashlen, stat, key);
|
---|
| 2273 |
|
---|
| 2274 | mp_clear(&r);
|
---|
| 2275 | mp_clear(&s);
|
---|
| 2276 |
|
---|
| 2277 | return err;
|
---|
| 2278 | }
|
---|
| 2279 |
|
---|
| 2280 | /**
|
---|
| 2281 | Verify an ECC signature
|
---|
| 2282 | r The signature R component to verify
|
---|
| 2283 | s The signature S component to verify
|
---|
| 2284 | hash The hash (message digest) that was signed
|
---|
| 2285 | hashlen The length of the hash (octets)
|
---|
| 2286 | stat Result of signature, 1==valid, 0==invalid
|
---|
| 2287 | key The corresponding public ECC key
|
---|
| 2288 | return MP_OKAY if successful (even if the signature is not valid)
|
---|
| 2289 | */
|
---|
| 2290 | int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
|
---|
| 2291 | word32 hashlen, int* stat, ecc_key* key)
|
---|
| 2292 | {
|
---|
| 2293 | ecc_point *mG, *mQ;
|
---|
| 2294 | mp_int v;
|
---|
| 2295 | mp_int w;
|
---|
| 2296 | mp_int u1;
|
---|
| 2297 | mp_int u2;
|
---|
| 2298 | mp_int e;
|
---|
| 2299 | mp_int p;
|
---|
| 2300 | mp_int m;
|
---|
| 2301 | int err;
|
---|
| 2302 |
|
---|
| 2303 | if (r == NULL || s == NULL || hash == NULL || stat == NULL || key == NULL)
|
---|
| 2304 | return ECC_BAD_ARG_E;
|
---|
| 2305 |
|
---|
| 2306 | /* default to invalid signature */
|
---|
| 2307 | *stat = 0;
|
---|
| 2308 |
|
---|
| 2309 | /* is the IDX valid ? */
|
---|
| 2310 | if (wc_ecc_is_valid_idx(key->idx) != 1) {
|
---|
| 2311 | return ECC_BAD_ARG_E;
|
---|
| 2312 | }
|
---|
| 2313 |
|
---|
| 2314 | /* allocate ints */
|
---|
| 2315 | if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) {
|
---|
| 2316 | return MEMORY_E;
|
---|
| 2317 | }
|
---|
| 2318 |
|
---|
| 2319 | if ((err = mp_init(&m)) != MP_OKAY) {
|
---|
| 2320 | mp_clear(&v);
|
---|
| 2321 | mp_clear(&w);
|
---|
| 2322 | mp_clear(&u1);
|
---|
| 2323 | mp_clear(&u2);
|
---|
| 2324 | mp_clear(&p);
|
---|
| 2325 | mp_clear(&e);
|
---|
| 2326 | return MEMORY_E;
|
---|
| 2327 | }
|
---|
| 2328 |
|
---|
| 2329 | /* allocate points */
|
---|
| 2330 | mG = wc_ecc_new_point();
|
---|
| 2331 | mQ = wc_ecc_new_point();
|
---|
| 2332 | if (mQ == NULL || mG == NULL)
|
---|
| 2333 | err = MEMORY_E;
|
---|
| 2334 |
|
---|
| 2335 | /* get the order */
|
---|
| 2336 | if (err == MP_OKAY)
|
---|
| 2337 | err = mp_read_radix(&p, (char *)key->dp->order, 16);
|
---|
| 2338 |
|
---|
| 2339 | /* get the modulus */
|
---|
| 2340 | if (err == MP_OKAY)
|
---|
| 2341 | err = mp_read_radix(&m, (char *)key->dp->prime, 16);
|
---|
| 2342 |
|
---|
| 2343 | /* check for zero */
|
---|
| 2344 | if (err == MP_OKAY) {
|
---|
| 2345 | if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, &p) != MP_LT ||
|
---|
| 2346 | mp_cmp(s, &p) != MP_LT)
|
---|
| 2347 | err = MP_ZERO_E;
|
---|
| 2348 | }
|
---|
| 2349 | /* read hash */
|
---|
| 2350 | if (err == MP_OKAY) {
|
---|
| 2351 | /* we may need to truncate if hash is longer than key size */
|
---|
| 2352 | unsigned int orderBits = mp_count_bits(&p);
|
---|
| 2353 |
|
---|
| 2354 | /* truncate down to byte size, may be all that's needed */
|
---|
| 2355 | if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
|
---|
| 2356 | hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1)/WOLFSSL_BIT_SIZE;
|
---|
| 2357 | err = mp_read_unsigned_bin(&e, hash, hashlen);
|
---|
| 2358 |
|
---|
| 2359 | /* may still need bit truncation too */
|
---|
| 2360 | if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits)
|
---|
| 2361 | mp_rshb(&e, WOLFSSL_BIT_SIZE - (orderBits & 0x7));
|
---|
| 2362 | }
|
---|
| 2363 |
|
---|
| 2364 | /* w = s^-1 mod n */
|
---|
| 2365 | if (err == MP_OKAY)
|
---|
| 2366 | err = mp_invmod(s, &p, &w);
|
---|
| 2367 |
|
---|
| 2368 | /* u1 = ew */
|
---|
| 2369 | if (err == MP_OKAY)
|
---|
| 2370 | err = mp_mulmod(&e, &w, &p, &u1);
|
---|
| 2371 |
|
---|
| 2372 | /* u2 = rw */
|
---|
| 2373 | if (err == MP_OKAY)
|
---|
| 2374 | err = mp_mulmod(r, &w, &p, &u2);
|
---|
| 2375 |
|
---|
| 2376 | /* find mG and mQ */
|
---|
| 2377 | if (err == MP_OKAY)
|
---|
| 2378 | err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16);
|
---|
| 2379 |
|
---|
| 2380 | if (err == MP_OKAY)
|
---|
| 2381 | err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16);
|
---|
| 2382 | if (err == MP_OKAY)
|
---|
| 2383 | mp_set(mG->z, 1);
|
---|
| 2384 |
|
---|
| 2385 | if (err == MP_OKAY)
|
---|
| 2386 | err = mp_copy(key->pubkey.x, mQ->x);
|
---|
| 2387 | if (err == MP_OKAY)
|
---|
| 2388 | err = mp_copy(key->pubkey.y, mQ->y);
|
---|
| 2389 | if (err == MP_OKAY)
|
---|
| 2390 | err = mp_copy(key->pubkey.z, mQ->z);
|
---|
| 2391 |
|
---|
| 2392 | #ifndef ECC_SHAMIR
|
---|
| 2393 | {
|
---|
| 2394 | mp_digit mp;
|
---|
| 2395 |
|
---|
| 2396 | /* compute u1*mG + u2*mQ = mG */
|
---|
| 2397 | if (err == MP_OKAY)
|
---|
| 2398 | err = wc_ecc_mulmod(&u1, mG, mG, &m, 0);
|
---|
| 2399 | if (err == MP_OKAY)
|
---|
| 2400 | err = wc_ecc_mulmod(&u2, mQ, mQ, &m, 0);
|
---|
| 2401 |
|
---|
| 2402 | /* find the montgomery mp */
|
---|
| 2403 | if (err == MP_OKAY)
|
---|
| 2404 | err = mp_montgomery_setup(&m, &mp);
|
---|
| 2405 |
|
---|
| 2406 | /* add them */
|
---|
| 2407 | if (err == MP_OKAY)
|
---|
| 2408 | err = ecc_projective_add_point(mQ, mG, mG, &m, &mp);
|
---|
| 2409 |
|
---|
| 2410 | /* reduce */
|
---|
| 2411 | if (err == MP_OKAY)
|
---|
| 2412 | err = ecc_map(mG, &m, &mp);
|
---|
| 2413 | }
|
---|
| 2414 | #else
|
---|
| 2415 | /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
|
---|
| 2416 | if (err == MP_OKAY)
|
---|
| 2417 | err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &m);
|
---|
| 2418 | #endif /* ECC_SHAMIR */
|
---|
| 2419 |
|
---|
| 2420 | /* v = X_x1 mod n */
|
---|
| 2421 | if (err == MP_OKAY)
|
---|
| 2422 | err = mp_mod(mG->x, &p, &v);
|
---|
| 2423 |
|
---|
| 2424 | /* does v == r */
|
---|
| 2425 | if (err == MP_OKAY) {
|
---|
| 2426 | if (mp_cmp(&v, r) == MP_EQ)
|
---|
| 2427 | *stat = 1;
|
---|
| 2428 | }
|
---|
| 2429 |
|
---|
| 2430 | wc_ecc_del_point(mG);
|
---|
| 2431 | wc_ecc_del_point(mQ);
|
---|
| 2432 |
|
---|
| 2433 | mp_clear(&v);
|
---|
| 2434 | mp_clear(&w);
|
---|
| 2435 | mp_clear(&u1);
|
---|
| 2436 | mp_clear(&u2);
|
---|
| 2437 | mp_clear(&p);
|
---|
| 2438 | mp_clear(&e);
|
---|
| 2439 | mp_clear(&m);
|
---|
| 2440 |
|
---|
| 2441 | return err;
|
---|
| 2442 | }
|
---|
| 2443 |
|
---|
| 2444 | /* import point from der */
|
---|
| 2445 | int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx,
|
---|
| 2446 | ecc_point* point)
|
---|
| 2447 | {
|
---|
| 2448 | int err = 0;
|
---|
| 2449 | int compressed = 0;
|
---|
| 2450 |
|
---|
| 2451 | if (in == NULL || point == NULL || (curve_idx < 0) ||
|
---|
| 2452 | (wc_ecc_is_valid_idx(curve_idx) == 0))
|
---|
| 2453 | return ECC_BAD_ARG_E;
|
---|
| 2454 |
|
---|
| 2455 | /* must be odd */
|
---|
| 2456 | if ((inLen & 1) == 0) {
|
---|
| 2457 | return ECC_BAD_ARG_E;
|
---|
| 2458 | }
|
---|
| 2459 |
|
---|
| 2460 | /* init point */
|
---|
| 2461 | #ifdef ALT_ECC_SIZE
|
---|
| 2462 | point->x = (mp_int*)&point->xyz[0];
|
---|
| 2463 | point->y = (mp_int*)&point->xyz[1];
|
---|
| 2464 | point->z = (mp_int*)&point->xyz[2];
|
---|
| 2465 | alt_fp_init(point->x);
|
---|
| 2466 | alt_fp_init(point->y);
|
---|
| 2467 | alt_fp_init(point->z);
|
---|
| 2468 | #else
|
---|
| 2469 | err = mp_init_multi(point->x, point->y, point->z, NULL, NULL, NULL);
|
---|
| 2470 | #endif
|
---|
| 2471 | if (err != MP_OKAY)
|
---|
| 2472 | return MEMORY_E;
|
---|
| 2473 |
|
---|
| 2474 | /* check for 4, 2, or 3 */
|
---|
| 2475 | if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
|
---|
| 2476 | err = ASN_PARSE_E;
|
---|
| 2477 | }
|
---|
| 2478 |
|
---|
| 2479 | if (in[0] == 0x02 || in[0] == 0x03) {
|
---|
| 2480 | #ifdef HAVE_COMP_KEY
|
---|
| 2481 | compressed = 1;
|
---|
| 2482 | #else
|
---|
| 2483 | err = NOT_COMPILED_IN;
|
---|
| 2484 | #endif
|
---|
| 2485 | }
|
---|
| 2486 |
|
---|
| 2487 | /* read data */
|
---|
| 2488 | if (err == MP_OKAY)
|
---|
| 2489 | err = mp_read_unsigned_bin(point->x, (byte*)in+1, (inLen-1)>>1);
|
---|
| 2490 |
|
---|
| 2491 | #ifdef HAVE_COMP_KEY
|
---|
| 2492 | if (err == MP_OKAY && compressed == 1) { /* build y */
|
---|
| 2493 | mp_int t1, t2, prime, a, b;
|
---|
| 2494 |
|
---|
| 2495 | if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY)
|
---|
| 2496 | err = MEMORY_E;
|
---|
| 2497 |
|
---|
| 2498 | /* load prime */
|
---|
| 2499 | if (err == MP_OKAY)
|
---|
| 2500 | err = mp_read_radix(&prime, (char *)ecc_sets[curve_idx].prime, 16);
|
---|
| 2501 |
|
---|
| 2502 | /* load a */
|
---|
| 2503 | if (err == MP_OKAY)
|
---|
| 2504 | err = mp_read_radix(&a, (char *)ecc_sets[curve_idx].Af, 16);
|
---|
| 2505 |
|
---|
| 2506 | /* load b */
|
---|
| 2507 | if (err == MP_OKAY)
|
---|
| 2508 | err = mp_read_radix(&b, (char *)ecc_sets[curve_idx].Bf, 16);
|
---|
| 2509 |
|
---|
| 2510 | /* compute x^3 */
|
---|
| 2511 | if (err == MP_OKAY)
|
---|
| 2512 | err = mp_sqr(point->x, &t1);
|
---|
| 2513 |
|
---|
| 2514 | if (err == MP_OKAY)
|
---|
| 2515 | err = mp_mulmod(&t1, point->x, &prime, &t1);
|
---|
| 2516 |
|
---|
| 2517 | /* compute x^3 + a*x */
|
---|
| 2518 | if (err == MP_OKAY)
|
---|
| 2519 | err = mp_mulmod(&a, point->x, &prime, &t2);
|
---|
| 2520 |
|
---|
| 2521 | if (err == MP_OKAY)
|
---|
| 2522 | err = mp_add(&t1, &t2, &t1);
|
---|
| 2523 |
|
---|
| 2524 | /* compute x^3 + a*x + b */
|
---|
| 2525 | if (err == MP_OKAY)
|
---|
| 2526 | err = mp_add(&t1, &b, &t1);
|
---|
| 2527 |
|
---|
| 2528 | /* compute sqrt(x^3 + a*x + b) */
|
---|
| 2529 | if (err == MP_OKAY)
|
---|
| 2530 | err = mp_sqrtmod_prime(&t1, &prime, &t2);
|
---|
| 2531 |
|
---|
| 2532 | /* adjust y */
|
---|
| 2533 | if (err == MP_OKAY) {
|
---|
| 2534 | if ((mp_isodd(&t2) && in[0] == 0x03) ||
|
---|
| 2535 | (!mp_isodd(&t2) && in[0] == 0x02)) {
|
---|
| 2536 | err = mp_mod(&t2, &prime, point->y);
|
---|
| 2537 | }
|
---|
| 2538 | else {
|
---|
| 2539 | err = mp_submod(&prime, &t2, &prime, point->y);
|
---|
| 2540 | }
|
---|
| 2541 | }
|
---|
| 2542 |
|
---|
| 2543 | mp_clear(&a);
|
---|
| 2544 | mp_clear(&b);
|
---|
| 2545 | mp_clear(&prime);
|
---|
| 2546 | mp_clear(&t2);
|
---|
| 2547 | mp_clear(&t1);
|
---|
| 2548 | }
|
---|
| 2549 | #endif
|
---|
| 2550 |
|
---|
| 2551 | if (err == MP_OKAY && compressed == 0)
|
---|
| 2552 | err = mp_read_unsigned_bin(point->y,
|
---|
| 2553 | (byte*)in+1+((inLen-1)>>1), (inLen-1)>>1);
|
---|
| 2554 | if (err == MP_OKAY)
|
---|
| 2555 | mp_set(point->z, 1);
|
---|
| 2556 |
|
---|
| 2557 | if (err != MP_OKAY) {
|
---|
| 2558 | mp_clear(point->x);
|
---|
| 2559 | mp_clear(point->y);
|
---|
| 2560 | mp_clear(point->z);
|
---|
| 2561 | }
|
---|
| 2562 |
|
---|
| 2563 | return err;
|
---|
| 2564 | }
|
---|
| 2565 |
|
---|
| 2566 | /* export point to der */
|
---|
| 2567 | int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out,
|
---|
| 2568 | word32* outLen)
|
---|
| 2569 | {
|
---|
| 2570 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 2571 | byte* buf;
|
---|
| 2572 | #else
|
---|
| 2573 | byte buf[ECC_BUFSIZE];
|
---|
| 2574 | #endif
|
---|
| 2575 | word32 numlen;
|
---|
| 2576 | int ret = MP_OKAY;
|
---|
| 2577 |
|
---|
| 2578 | if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0))
|
---|
| 2579 | return ECC_BAD_ARG_E;
|
---|
| 2580 |
|
---|
| 2581 | /* return length needed only */
|
---|
| 2582 | if (point != NULL && out == NULL && outLen != NULL) {
|
---|
| 2583 | numlen = ecc_sets[curve_idx].size;
|
---|
| 2584 | *outLen = 1 + 2*numlen;
|
---|
| 2585 | return LENGTH_ONLY_E;
|
---|
| 2586 | }
|
---|
| 2587 |
|
---|
| 2588 | if (point == NULL || out == NULL || outLen == NULL)
|
---|
| 2589 | return ECC_BAD_ARG_E;
|
---|
| 2590 |
|
---|
| 2591 | numlen = ecc_sets[curve_idx].size;
|
---|
| 2592 |
|
---|
| 2593 | if (*outLen < (1 + 2*numlen)) {
|
---|
| 2594 | *outLen = 1 + 2*numlen;
|
---|
| 2595 | return BUFFER_E;
|
---|
| 2596 | }
|
---|
| 2597 |
|
---|
| 2598 | /* store byte 0x04 */
|
---|
| 2599 | out[0] = 0x04;
|
---|
| 2600 |
|
---|
| 2601 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 2602 | buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2603 | if (buf == NULL)
|
---|
| 2604 | return MEMORY_E;
|
---|
| 2605 | #endif
|
---|
| 2606 |
|
---|
| 2607 | /* pad and store x */
|
---|
| 2608 | XMEMSET(buf, 0, ECC_BUFSIZE);
|
---|
| 2609 | ret = mp_to_unsigned_bin(point->x, buf +
|
---|
| 2610 | (numlen - mp_unsigned_bin_size(point->x)));
|
---|
| 2611 | if (ret != MP_OKAY)
|
---|
| 2612 | goto done;
|
---|
| 2613 | XMEMCPY(out+1, buf, numlen);
|
---|
| 2614 |
|
---|
| 2615 | /* pad and store y */
|
---|
| 2616 | XMEMSET(buf, 0, ECC_BUFSIZE);
|
---|
| 2617 | ret = mp_to_unsigned_bin(point->y, buf +
|
---|
| 2618 | (numlen - mp_unsigned_bin_size(point->y)));
|
---|
| 2619 | if (ret != MP_OKAY)
|
---|
| 2620 | goto done;
|
---|
| 2621 | XMEMCPY(out+1+numlen, buf, numlen);
|
---|
| 2622 |
|
---|
| 2623 | *outLen = 1 + 2*numlen;
|
---|
| 2624 |
|
---|
| 2625 | done:
|
---|
| 2626 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 2627 | XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2628 | #endif
|
---|
| 2629 |
|
---|
| 2630 | return ret;
|
---|
| 2631 | }
|
---|
| 2632 |
|
---|
| 2633 |
|
---|
| 2634 | /* export public ECC key in ANSI X9.63 format */
|
---|
| 2635 | int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
|
---|
| 2636 | {
|
---|
| 2637 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 2638 | byte* buf;
|
---|
| 2639 | #else
|
---|
| 2640 | byte buf[ECC_BUFSIZE];
|
---|
| 2641 | #endif
|
---|
| 2642 | word32 numlen;
|
---|
| 2643 | int ret = MP_OKAY;
|
---|
| 2644 |
|
---|
| 2645 | /* return length needed only */
|
---|
| 2646 | if (key != NULL && out == NULL && outLen != NULL) {
|
---|
| 2647 | numlen = key->dp->size;
|
---|
| 2648 | *outLen = 1 + 2*numlen;
|
---|
| 2649 | return LENGTH_ONLY_E;
|
---|
| 2650 | }
|
---|
| 2651 |
|
---|
| 2652 | if (key == NULL || out == NULL || outLen == NULL)
|
---|
| 2653 | return ECC_BAD_ARG_E;
|
---|
| 2654 |
|
---|
| 2655 | if (wc_ecc_is_valid_idx(key->idx) == 0) {
|
---|
| 2656 | return ECC_BAD_ARG_E;
|
---|
| 2657 | }
|
---|
| 2658 | numlen = key->dp->size;
|
---|
| 2659 |
|
---|
| 2660 | if (*outLen < (1 + 2*numlen)) {
|
---|
| 2661 | *outLen = 1 + 2*numlen;
|
---|
| 2662 | return BUFFER_E;
|
---|
| 2663 | }
|
---|
| 2664 |
|
---|
| 2665 | /* store byte 0x04 */
|
---|
| 2666 | out[0] = 0x04;
|
---|
| 2667 |
|
---|
| 2668 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 2669 | buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2670 | if (buf == NULL)
|
---|
| 2671 | return MEMORY_E;
|
---|
| 2672 | #endif
|
---|
| 2673 |
|
---|
| 2674 | /* pad and store x */
|
---|
| 2675 | XMEMSET(buf, 0, ECC_BUFSIZE);
|
---|
| 2676 | ret = mp_to_unsigned_bin(key->pubkey.x,
|
---|
| 2677 | buf + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
|
---|
| 2678 | if (ret != MP_OKAY)
|
---|
| 2679 | goto done;
|
---|
| 2680 | XMEMCPY(out+1, buf, numlen);
|
---|
| 2681 |
|
---|
| 2682 | /* pad and store y */
|
---|
| 2683 | XMEMSET(buf, 0, ECC_BUFSIZE);
|
---|
| 2684 | ret = mp_to_unsigned_bin(key->pubkey.y,
|
---|
| 2685 | buf + (numlen - mp_unsigned_bin_size(key->pubkey.y)));
|
---|
| 2686 | if (ret != MP_OKAY)
|
---|
| 2687 | goto done;
|
---|
| 2688 | XMEMCPY(out+1+numlen, buf, numlen);
|
---|
| 2689 |
|
---|
| 2690 | *outLen = 1 + 2*numlen;
|
---|
| 2691 |
|
---|
| 2692 | done:
|
---|
| 2693 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 2694 | XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 2695 | #endif
|
---|
| 2696 |
|
---|
| 2697 | return ret;
|
---|
| 2698 | }
|
---|
| 2699 |
|
---|
| 2700 |
|
---|
| 2701 | /* export public ECC key in ANSI X9.63 format, extended with
|
---|
| 2702 | * compression option */
|
---|
| 2703 | int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen,
|
---|
| 2704 | int compressed)
|
---|
| 2705 | {
|
---|
| 2706 | if (compressed == 0)
|
---|
| 2707 | return wc_ecc_export_x963(key, out, outLen);
|
---|
| 2708 | #ifdef HAVE_COMP_KEY
|
---|
| 2709 | else
|
---|
| 2710 | return wc_ecc_export_x963_compressed(key, out, outLen);
|
---|
| 2711 | #endif
|
---|
| 2712 |
|
---|
| 2713 | return NOT_COMPILED_IN;
|
---|
| 2714 | }
|
---|
| 2715 |
|
---|
| 2716 |
|
---|
| 2717 | /* is ec point on curve descriped by dp ? */
|
---|
| 2718 | static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime)
|
---|
| 2719 | {
|
---|
| 2720 | mp_int b, t1, t2;
|
---|
| 2721 | int err;
|
---|
| 2722 |
|
---|
| 2723 | if ((err = mp_init_multi(&b, &t1, &t2, NULL, NULL, NULL)) != MP_OKAY) {
|
---|
| 2724 | return err;
|
---|
| 2725 | }
|
---|
| 2726 |
|
---|
| 2727 | /* load b */
|
---|
| 2728 | err = mp_read_radix(&b, dp->Bf, 16);
|
---|
| 2729 |
|
---|
| 2730 | /* compute y^2 */
|
---|
| 2731 | if (err == MP_OKAY)
|
---|
| 2732 | err = mp_sqr(ecp->y, &t1);
|
---|
| 2733 |
|
---|
| 2734 | /* compute x^3 */
|
---|
| 2735 | if (err == MP_OKAY)
|
---|
| 2736 | err = mp_sqr(ecp->x, &t2);
|
---|
| 2737 | if (err == MP_OKAY)
|
---|
| 2738 | err = mp_mod(&t2, prime, &t2);
|
---|
| 2739 | if (err == MP_OKAY)
|
---|
| 2740 | err = mp_mul(ecp->x, &t2, &t2);
|
---|
| 2741 |
|
---|
| 2742 | /* compute y^2 - x^3 */
|
---|
| 2743 | if (err == MP_OKAY)
|
---|
| 2744 | err = mp_sub(&t1, &t2, &t1);
|
---|
| 2745 |
|
---|
| 2746 | /* compute y^2 - x^3 + 3x */
|
---|
| 2747 | if (err == MP_OKAY)
|
---|
| 2748 | err = mp_add(&t1, ecp->x, &t1);
|
---|
| 2749 | if (err == MP_OKAY)
|
---|
| 2750 | err = mp_add(&t1, ecp->x, &t1);
|
---|
| 2751 | if (err == MP_OKAY)
|
---|
| 2752 | err = mp_add(&t1, ecp->x, &t1);
|
---|
| 2753 | if (err == MP_OKAY)
|
---|
| 2754 | err = mp_mod(&t1, prime, &t1);
|
---|
| 2755 |
|
---|
| 2756 | while (err == MP_OKAY && mp_cmp_d(&t1, 0) == MP_LT) {
|
---|
| 2757 | err = mp_add(&t1, prime, &t1);
|
---|
| 2758 | }
|
---|
| 2759 | while (err == MP_OKAY && mp_cmp(&t1, prime) != MP_LT) {
|
---|
| 2760 | err = mp_sub(&t1, prime, &t1);
|
---|
| 2761 | }
|
---|
| 2762 |
|
---|
| 2763 | /* compare to b */
|
---|
| 2764 | if (err == MP_OKAY) {
|
---|
| 2765 | if (mp_cmp(&t1, &b) != MP_EQ) {
|
---|
| 2766 | err = MP_VAL;
|
---|
| 2767 | } else {
|
---|
| 2768 | err = MP_OKAY;
|
---|
| 2769 | }
|
---|
| 2770 | }
|
---|
| 2771 |
|
---|
| 2772 | mp_clear(&b);
|
---|
| 2773 | mp_clear(&t1);
|
---|
| 2774 | mp_clear(&t2);
|
---|
| 2775 |
|
---|
| 2776 | return err;
|
---|
| 2777 | }
|
---|
| 2778 |
|
---|
| 2779 |
|
---|
| 2780 | /* validate privkey * generator == pubkey, 0 on success */
|
---|
| 2781 | static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime)
|
---|
| 2782 | {
|
---|
| 2783 | ecc_point* base = NULL;
|
---|
| 2784 | ecc_point* res = NULL;
|
---|
| 2785 | int err;
|
---|
| 2786 |
|
---|
| 2787 | if (key == NULL)
|
---|
| 2788 | return BAD_FUNC_ARG;
|
---|
| 2789 |
|
---|
| 2790 | base = wc_ecc_new_point();
|
---|
| 2791 | if (base == NULL)
|
---|
| 2792 | return MEMORY_E;
|
---|
| 2793 |
|
---|
| 2794 | /* set up base generator */
|
---|
| 2795 | err = mp_read_radix(base->x, (char*)key->dp->Gx, 16);
|
---|
| 2796 | if (err == MP_OKAY)
|
---|
| 2797 | err = mp_read_radix(base->y, (char*)key->dp->Gy, 16);
|
---|
| 2798 | if (err == MP_OKAY)
|
---|
| 2799 | mp_set(base->z, 1);
|
---|
| 2800 |
|
---|
| 2801 | if (err == MP_OKAY) {
|
---|
| 2802 | res = wc_ecc_new_point();
|
---|
| 2803 | if (res == NULL)
|
---|
| 2804 | err = MEMORY_E;
|
---|
| 2805 | else {
|
---|
| 2806 | err = wc_ecc_mulmod(&key->k, base, res, prime, 1);
|
---|
| 2807 | if (err == MP_OKAY) {
|
---|
| 2808 | /* compare result to public key */
|
---|
| 2809 | if (mp_cmp(res->x, key->pubkey.x) != MP_EQ ||
|
---|
| 2810 | mp_cmp(res->y, key->pubkey.y) != MP_EQ ||
|
---|
| 2811 | mp_cmp(res->z, key->pubkey.z) != MP_EQ) {
|
---|
| 2812 | /* didn't match */
|
---|
| 2813 | err = ECC_PRIV_KEY_E;
|
---|
| 2814 | }
|
---|
| 2815 | }
|
---|
| 2816 | }
|
---|
| 2817 | }
|
---|
| 2818 |
|
---|
| 2819 | wc_ecc_del_point(res);
|
---|
| 2820 | wc_ecc_del_point(base);
|
---|
| 2821 |
|
---|
| 2822 | return err;
|
---|
| 2823 | }
|
---|
| 2824 |
|
---|
| 2825 |
|
---|
| 2826 | #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
---|
| 2827 |
|
---|
| 2828 | /* check privkey generator helper, creates prime needed */
|
---|
| 2829 | static int ecc_check_privkey_gen_helper(ecc_key* key)
|
---|
| 2830 | {
|
---|
| 2831 | mp_int prime;
|
---|
| 2832 | int err;
|
---|
| 2833 |
|
---|
| 2834 | if (key == NULL)
|
---|
| 2835 | return BAD_FUNC_ARG;
|
---|
| 2836 |
|
---|
| 2837 | err = mp_init(&prime);
|
---|
| 2838 | if (err != MP_OKAY)
|
---|
| 2839 | return err;
|
---|
| 2840 |
|
---|
| 2841 | err = mp_read_radix(&prime, (char*)key->dp->prime, 16);
|
---|
| 2842 |
|
---|
| 2843 | if (err == MP_OKAY);
|
---|
| 2844 | err = ecc_check_privkey_gen(key, &prime);
|
---|
| 2845 |
|
---|
| 2846 | mp_clear(&prime);
|
---|
| 2847 |
|
---|
| 2848 | return err;
|
---|
| 2849 | }
|
---|
| 2850 |
|
---|
| 2851 | #endif /* WOLFSSL_VALIDATE_ECC_IMPORT */
|
---|
| 2852 |
|
---|
| 2853 |
|
---|
| 2854 | /* validate order * pubkey = point at infinity, 0 on success */
|
---|
| 2855 | static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order)
|
---|
| 2856 | {
|
---|
| 2857 | ecc_point* inf = NULL;
|
---|
| 2858 | int err;
|
---|
| 2859 |
|
---|
| 2860 | if (key == NULL)
|
---|
| 2861 | return BAD_FUNC_ARG;
|
---|
| 2862 |
|
---|
| 2863 | inf = wc_ecc_new_point();
|
---|
| 2864 | if (inf == NULL)
|
---|
| 2865 | err = MEMORY_E;
|
---|
| 2866 | else {
|
---|
| 2867 | err = wc_ecc_mulmod(order, &key->pubkey, inf, prime, 1);
|
---|
| 2868 | if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf))
|
---|
| 2869 | err = ECC_INF_E;
|
---|
| 2870 | }
|
---|
| 2871 |
|
---|
| 2872 | wc_ecc_del_point(inf);
|
---|
| 2873 |
|
---|
| 2874 | return err;
|
---|
| 2875 | }
|
---|
| 2876 |
|
---|
| 2877 |
|
---|
| 2878 | /* perform sanity checks on ec key validity, 0 on success */
|
---|
| 2879 | int wc_ecc_check_key(ecc_key* key)
|
---|
| 2880 | {
|
---|
| 2881 | mp_int prime; /* used by multiple calls so let's cache */
|
---|
| 2882 | mp_int order; /* other callers have, so let's gen here */
|
---|
| 2883 | int err;
|
---|
| 2884 |
|
---|
| 2885 | if (key == NULL)
|
---|
| 2886 | return BAD_FUNC_ARG;
|
---|
| 2887 |
|
---|
| 2888 | /* pubkey point cannot be at inifinity */
|
---|
| 2889 | if (wc_ecc_point_is_at_infinity(&key->pubkey))
|
---|
| 2890 | return ECC_INF_E;
|
---|
| 2891 |
|
---|
| 2892 | err = mp_init_multi(&prime, &order, NULL, NULL, NULL, NULL);
|
---|
| 2893 | if (err != MP_OKAY)
|
---|
| 2894 | return err;
|
---|
| 2895 |
|
---|
| 2896 | err = mp_read_radix(&prime, (char*)key->dp->prime, 16);
|
---|
| 2897 |
|
---|
| 2898 | /* make sure point is actually on curve */
|
---|
| 2899 | if (err == MP_OKAY)
|
---|
| 2900 | err = ecc_is_point(key->dp, &key->pubkey, &prime);
|
---|
| 2901 |
|
---|
| 2902 | if (err == MP_OKAY)
|
---|
| 2903 | err = mp_read_radix(&order, (char*)key->dp->order, 16);
|
---|
| 2904 |
|
---|
| 2905 | /* pubkey * order must be at infinity */
|
---|
| 2906 | if (err == MP_OKAY)
|
---|
| 2907 | err = ecc_check_pubkey_order(key, &prime, &order);
|
---|
| 2908 |
|
---|
| 2909 | /* private * base generator must equal pubkey */
|
---|
| 2910 | if (err == MP_OKAY && key->type == ECC_PRIVATEKEY)
|
---|
| 2911 | err = ecc_check_privkey_gen(key, &prime);
|
---|
| 2912 |
|
---|
| 2913 | mp_clear(&order);
|
---|
| 2914 | mp_clear(&prime);
|
---|
| 2915 |
|
---|
| 2916 | return err;
|
---|
| 2917 | }
|
---|
| 2918 |
|
---|
| 2919 |
|
---|
| 2920 | /* import public ECC key in ANSI X9.63 format */
|
---|
| 2921 | int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
|
---|
| 2922 | {
|
---|
| 2923 | int x, err;
|
---|
| 2924 | int compressed = 0;
|
---|
| 2925 |
|
---|
| 2926 | if (in == NULL || key == NULL)
|
---|
| 2927 | return ECC_BAD_ARG_E;
|
---|
| 2928 |
|
---|
| 2929 | /* must be odd */
|
---|
| 2930 | if ((inLen & 1) == 0) {
|
---|
| 2931 | return ECC_BAD_ARG_E;
|
---|
| 2932 | }
|
---|
| 2933 |
|
---|
| 2934 | /* init key */
|
---|
| 2935 | #ifdef ALT_ECC_SIZE
|
---|
| 2936 | key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
|
---|
| 2937 | key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
|
---|
| 2938 | key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
|
---|
| 2939 | alt_fp_init(key->pubkey.x);
|
---|
| 2940 | alt_fp_init(key->pubkey.y);
|
---|
| 2941 | alt_fp_init(key->pubkey.z);
|
---|
| 2942 | err = mp_init(&key->k);
|
---|
| 2943 | #else
|
---|
| 2944 | err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k,
|
---|
| 2945 | NULL, NULL);
|
---|
| 2946 | #endif
|
---|
| 2947 | if (err != MP_OKAY)
|
---|
| 2948 | return MEMORY_E;
|
---|
| 2949 |
|
---|
| 2950 | /* check for 4, 2, or 3 */
|
---|
| 2951 | if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
|
---|
| 2952 | err = ASN_PARSE_E;
|
---|
| 2953 | }
|
---|
| 2954 |
|
---|
| 2955 | if (in[0] == 0x02 || in[0] == 0x03) {
|
---|
| 2956 | #ifdef HAVE_COMP_KEY
|
---|
| 2957 | compressed = 1;
|
---|
| 2958 | #else
|
---|
| 2959 | err = NOT_COMPILED_IN;
|
---|
| 2960 | #endif
|
---|
| 2961 | }
|
---|
| 2962 |
|
---|
| 2963 | if (err == MP_OKAY) {
|
---|
| 2964 | /* determine the idx */
|
---|
| 2965 |
|
---|
| 2966 | if (compressed)
|
---|
| 2967 | inLen = (inLen-1)*2 + 1; /* used uncompressed len */
|
---|
| 2968 |
|
---|
| 2969 | for (x = 0; ecc_sets[x].size != 0; x++) {
|
---|
| 2970 | if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) {
|
---|
| 2971 | break;
|
---|
| 2972 | }
|
---|
| 2973 | }
|
---|
| 2974 | if (ecc_sets[x].size == 0) {
|
---|
| 2975 | err = ASN_PARSE_E;
|
---|
| 2976 | } else {
|
---|
| 2977 | /* set the idx */
|
---|
| 2978 | key->idx = x;
|
---|
| 2979 | key->dp = &ecc_sets[x];
|
---|
| 2980 | key->type = ECC_PUBLICKEY;
|
---|
| 2981 | }
|
---|
| 2982 | }
|
---|
| 2983 |
|
---|
| 2984 | /* read data */
|
---|
| 2985 | if (err == MP_OKAY)
|
---|
| 2986 | err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
|
---|
| 2987 |
|
---|
| 2988 | #ifdef HAVE_COMP_KEY
|
---|
| 2989 | if (err == MP_OKAY && compressed == 1) { /* build y */
|
---|
| 2990 | mp_int t1, t2, prime, a, b;
|
---|
| 2991 |
|
---|
| 2992 | if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY)
|
---|
| 2993 | err = MEMORY_E;
|
---|
| 2994 |
|
---|
| 2995 | /* load prime */
|
---|
| 2996 | if (err == MP_OKAY)
|
---|
| 2997 | err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
|
---|
| 2998 |
|
---|
| 2999 | /* load a */
|
---|
| 3000 | if (err == MP_OKAY)
|
---|
| 3001 | err = mp_read_radix(&a, (char *)key->dp->Af, 16);
|
---|
| 3002 |
|
---|
| 3003 | /* load b */
|
---|
| 3004 | if (err == MP_OKAY)
|
---|
| 3005 | err = mp_read_radix(&b, (char *)key->dp->Bf, 16);
|
---|
| 3006 |
|
---|
| 3007 | /* compute x^3 */
|
---|
| 3008 | if (err == MP_OKAY)
|
---|
| 3009 | err = mp_sqr(key->pubkey.x, &t1);
|
---|
| 3010 |
|
---|
| 3011 | if (err == MP_OKAY)
|
---|
| 3012 | err = mp_mulmod(&t1, key->pubkey.x, &prime, &t1);
|
---|
| 3013 |
|
---|
| 3014 | /* compute x^3 + a*x */
|
---|
| 3015 | if (err == MP_OKAY)
|
---|
| 3016 | err = mp_mulmod(&a, key->pubkey.x, &prime, &t2);
|
---|
| 3017 |
|
---|
| 3018 | if (err == MP_OKAY)
|
---|
| 3019 | err = mp_add(&t1, &t2, &t1);
|
---|
| 3020 |
|
---|
| 3021 | /* compute x^3 + a*x + b */
|
---|
| 3022 | if (err == MP_OKAY)
|
---|
| 3023 | err = mp_add(&t1, &b, &t1);
|
---|
| 3024 |
|
---|
| 3025 | /* compute sqrt(x^3 + a*x + b) */
|
---|
| 3026 | if (err == MP_OKAY)
|
---|
| 3027 | err = mp_sqrtmod_prime(&t1, &prime, &t2);
|
---|
| 3028 |
|
---|
| 3029 | /* adjust y */
|
---|
| 3030 | if (err == MP_OKAY) {
|
---|
| 3031 | if ((mp_isodd(&t2) && in[0] == 0x03) ||
|
---|
| 3032 | (!mp_isodd(&t2) && in[0] == 0x02)) {
|
---|
| 3033 | err = mp_mod(&t2, &prime, key->pubkey.y);
|
---|
| 3034 | }
|
---|
| 3035 | else {
|
---|
| 3036 | err = mp_submod(&prime, &t2, &prime, key->pubkey.y);
|
---|
| 3037 | }
|
---|
| 3038 | }
|
---|
| 3039 |
|
---|
| 3040 | mp_clear(&a);
|
---|
| 3041 | mp_clear(&b);
|
---|
| 3042 | mp_clear(&prime);
|
---|
| 3043 | mp_clear(&t2);
|
---|
| 3044 | mp_clear(&t1);
|
---|
| 3045 | }
|
---|
| 3046 | #endif
|
---|
| 3047 |
|
---|
| 3048 | if (err == MP_OKAY && compressed == 0)
|
---|
| 3049 | err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
|
---|
| 3050 | (inLen-1)>>1);
|
---|
| 3051 | if (err == MP_OKAY)
|
---|
| 3052 | mp_set(key->pubkey.z, 1);
|
---|
| 3053 |
|
---|
| 3054 | #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
---|
| 3055 | if (err == MP_OKAY)
|
---|
| 3056 | err = wc_ecc_check_key(key);
|
---|
| 3057 | #endif
|
---|
| 3058 |
|
---|
| 3059 | if (err != MP_OKAY) {
|
---|
| 3060 | mp_clear(key->pubkey.x);
|
---|
| 3061 | mp_clear(key->pubkey.y);
|
---|
| 3062 | mp_clear(key->pubkey.z);
|
---|
| 3063 | mp_clear(&key->k);
|
---|
| 3064 | }
|
---|
| 3065 |
|
---|
| 3066 | return err;
|
---|
| 3067 | }
|
---|
| 3068 |
|
---|
| 3069 |
|
---|
| 3070 | /* export ecc private key only raw, outLen is in/out size
|
---|
| 3071 | return MP_OKAY on success */
|
---|
| 3072 | int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
|
---|
| 3073 | {
|
---|
| 3074 | word32 numlen;
|
---|
| 3075 |
|
---|
| 3076 | if (key == NULL || out == NULL || outLen == NULL)
|
---|
| 3077 | return ECC_BAD_ARG_E;
|
---|
| 3078 |
|
---|
| 3079 | if (wc_ecc_is_valid_idx(key->idx) == 0) {
|
---|
| 3080 | return ECC_BAD_ARG_E;
|
---|
| 3081 | }
|
---|
| 3082 | numlen = key->dp->size;
|
---|
| 3083 |
|
---|
| 3084 | if (*outLen < numlen) {
|
---|
| 3085 | *outLen = numlen;
|
---|
| 3086 | return BUFFER_E;
|
---|
| 3087 | }
|
---|
| 3088 | *outLen = numlen;
|
---|
| 3089 | XMEMSET(out, 0, *outLen);
|
---|
| 3090 | return mp_to_unsigned_bin(&key->k, out + (numlen -
|
---|
| 3091 | mp_unsigned_bin_size(&key->k)));
|
---|
| 3092 | }
|
---|
| 3093 |
|
---|
| 3094 |
|
---|
| 3095 | /* ecc private key import, public key in ANSI X9.63 format, private raw */
|
---|
| 3096 | int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
|
---|
| 3097 | word32 pubSz, ecc_key* key)
|
---|
| 3098 | {
|
---|
| 3099 | int ret = wc_ecc_import_x963(pub, pubSz, key);
|
---|
| 3100 | if (ret != 0)
|
---|
| 3101 | return ret;
|
---|
| 3102 |
|
---|
| 3103 | key->type = ECC_PRIVATEKEY;
|
---|
| 3104 |
|
---|
| 3105 | ret = mp_read_unsigned_bin(&key->k, priv, privSz);
|
---|
| 3106 |
|
---|
| 3107 | #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
---|
| 3108 | if (ret == MP_OKAY)
|
---|
| 3109 | ret = ecc_check_privkey_gen_helper(key);
|
---|
| 3110 | #endif
|
---|
| 3111 |
|
---|
| 3112 | return ret;
|
---|
| 3113 | }
|
---|
| 3114 |
|
---|
| 3115 | /**
|
---|
| 3116 | Convert ECC R,S to signature
|
---|
| 3117 | r R component of signature
|
---|
| 3118 | s S component of signature
|
---|
| 3119 | out DER-encoded ECDSA signature
|
---|
| 3120 | outlen [in/out] output buffer size, output signature size
|
---|
| 3121 | return MP_OKAY on success
|
---|
| 3122 | */
|
---|
| 3123 | int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
|
---|
| 3124 | {
|
---|
| 3125 | int err;
|
---|
| 3126 | mp_int rtmp;
|
---|
| 3127 | mp_int stmp;
|
---|
| 3128 |
|
---|
| 3129 | if (r == NULL || s == NULL || out == NULL || outlen == NULL)
|
---|
| 3130 | return ECC_BAD_ARG_E;
|
---|
| 3131 |
|
---|
| 3132 | err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL);
|
---|
| 3133 | if (err != MP_OKAY)
|
---|
| 3134 | return err;
|
---|
| 3135 |
|
---|
| 3136 | err = mp_read_radix(&rtmp, r, 16);
|
---|
| 3137 | if (err == MP_OKAY)
|
---|
| 3138 | err = mp_read_radix(&stmp, s, 16);
|
---|
| 3139 |
|
---|
| 3140 | /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
|
---|
| 3141 | if (err == MP_OKAY)
|
---|
| 3142 | err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp);
|
---|
| 3143 |
|
---|
| 3144 | if (err == MP_OKAY) {
|
---|
| 3145 | if (mp_iszero(&rtmp) || mp_iszero(&stmp))
|
---|
| 3146 | err = MP_ZERO_E;
|
---|
| 3147 | }
|
---|
| 3148 |
|
---|
| 3149 | mp_clear(&rtmp);
|
---|
| 3150 | mp_clear(&stmp);
|
---|
| 3151 |
|
---|
| 3152 | return err;
|
---|
| 3153 | }
|
---|
| 3154 |
|
---|
| 3155 | /**
|
---|
| 3156 | Import raw ECC key
|
---|
| 3157 | key The destination ecc_key structure
|
---|
| 3158 | qx x component of base point, as ASCII hex string
|
---|
| 3159 | qy y component of base point, as ASCII hex string
|
---|
| 3160 | d private key, as ASCII hex string
|
---|
| 3161 | curveName ECC curve name, from ecc_sets[]
|
---|
| 3162 | return MP_OKAY on success
|
---|
| 3163 | */
|
---|
| 3164 | int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
|
---|
| 3165 | const char* d, const char* curveName)
|
---|
| 3166 | {
|
---|
| 3167 | int err, x;
|
---|
| 3168 |
|
---|
| 3169 | if (key == NULL || qx == NULL || qy == NULL || d == NULL ||
|
---|
| 3170 | curveName == NULL)
|
---|
| 3171 | return ECC_BAD_ARG_E;
|
---|
| 3172 |
|
---|
| 3173 | /* init key */
|
---|
| 3174 | #ifdef ALT_ECC_SIZE
|
---|
| 3175 | key->pubkey.x = (mp_int*)&key->pubkey.xyz[0];
|
---|
| 3176 | key->pubkey.y = (mp_int*)&key->pubkey.xyz[1];
|
---|
| 3177 | key->pubkey.z = (mp_int*)&key->pubkey.xyz[2];
|
---|
| 3178 | alt_fp_init(key->pubkey.x);
|
---|
| 3179 | alt_fp_init(key->pubkey.y);
|
---|
| 3180 | alt_fp_init(key->pubkey.z);
|
---|
| 3181 | err = mp_init(&key->k);
|
---|
| 3182 | #else
|
---|
| 3183 | err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k,
|
---|
| 3184 | NULL, NULL);
|
---|
| 3185 | #endif
|
---|
| 3186 | if (err != MP_OKAY)
|
---|
| 3187 | return MEMORY_E;
|
---|
| 3188 |
|
---|
| 3189 | /* read Qx */
|
---|
| 3190 | if (err == MP_OKAY)
|
---|
| 3191 | err = mp_read_radix(key->pubkey.x, qx, 16);
|
---|
| 3192 |
|
---|
| 3193 | /* read Qy */
|
---|
| 3194 | if (err == MP_OKAY)
|
---|
| 3195 | err = mp_read_radix(key->pubkey.y, qy, 16);
|
---|
| 3196 |
|
---|
| 3197 | if (err == MP_OKAY)
|
---|
| 3198 | mp_set(key->pubkey.z, 1);
|
---|
| 3199 |
|
---|
| 3200 | /* read and set the curve */
|
---|
| 3201 | if (err == MP_OKAY) {
|
---|
| 3202 | for (x = 0; ecc_sets[x].size != 0; x++) {
|
---|
| 3203 | if (XSTRNCMP(ecc_sets[x].name, curveName,
|
---|
| 3204 | XSTRLEN(curveName)) == 0) {
|
---|
| 3205 | break;
|
---|
| 3206 | }
|
---|
| 3207 | }
|
---|
| 3208 | if (ecc_sets[x].size == 0) {
|
---|
| 3209 | err = ASN_PARSE_E;
|
---|
| 3210 | } else {
|
---|
| 3211 | /* set the curve */
|
---|
| 3212 | key->idx = x;
|
---|
| 3213 | key->dp = &ecc_sets[x];
|
---|
| 3214 | key->type = ECC_PUBLICKEY;
|
---|
| 3215 | }
|
---|
| 3216 | }
|
---|
| 3217 |
|
---|
| 3218 | /* import private key */
|
---|
| 3219 | if (err == MP_OKAY) {
|
---|
| 3220 | key->type = ECC_PRIVATEKEY;
|
---|
| 3221 | err = mp_read_radix(&key->k, d, 16);
|
---|
| 3222 | }
|
---|
| 3223 |
|
---|
| 3224 | #ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
---|
| 3225 | if (err == MP_OKAY)
|
---|
| 3226 | err = wc_ecc_check_key(key);
|
---|
| 3227 | #endif
|
---|
| 3228 |
|
---|
| 3229 | if (err != MP_OKAY) {
|
---|
| 3230 | mp_clear(key->pubkey.x);
|
---|
| 3231 | mp_clear(key->pubkey.y);
|
---|
| 3232 | mp_clear(key->pubkey.z);
|
---|
| 3233 | mp_clear(&key->k);
|
---|
| 3234 | }
|
---|
| 3235 |
|
---|
| 3236 | return err;
|
---|
| 3237 | }
|
---|
| 3238 |
|
---|
| 3239 |
|
---|
| 3240 | /* key size in octets */
|
---|
| 3241 | int wc_ecc_size(ecc_key* key)
|
---|
| 3242 | {
|
---|
| 3243 | if (key == NULL) return 0;
|
---|
| 3244 |
|
---|
| 3245 | return key->dp->size;
|
---|
| 3246 | }
|
---|
| 3247 |
|
---|
| 3248 |
|
---|
| 3249 | /* worst case estimate, check actual return from wc_ecc_sign_hash for actual
|
---|
| 3250 | value of signature size in octets */
|
---|
| 3251 | int wc_ecc_sig_size(ecc_key* key)
|
---|
| 3252 | {
|
---|
| 3253 | int sz = wc_ecc_size(key);
|
---|
| 3254 | if (sz <= 0)
|
---|
| 3255 | return sz;
|
---|
| 3256 |
|
---|
| 3257 | return sz * 2 + SIG_HEADER_SZ + 4; /* (4) worst case estimate */
|
---|
| 3258 | }
|
---|
| 3259 |
|
---|
| 3260 |
|
---|
| 3261 | #ifdef FP_ECC
|
---|
| 3262 |
|
---|
| 3263 | /* fixed point ECC cache */
|
---|
| 3264 | /* number of entries in the cache */
|
---|
| 3265 | #ifndef FP_ENTRIES
|
---|
| 3266 | #define FP_ENTRIES 16
|
---|
| 3267 | #endif
|
---|
| 3268 |
|
---|
| 3269 | /* number of bits in LUT */
|
---|
| 3270 | #ifndef FP_LUT
|
---|
| 3271 | #define FP_LUT 8U
|
---|
| 3272 | #endif
|
---|
| 3273 |
|
---|
| 3274 | #ifdef ECC_SHAMIR
|
---|
| 3275 | /* Sharmir requires a bigger LUT, TAO */
|
---|
| 3276 | #if (FP_LUT > 12) || (FP_LUT < 4)
|
---|
| 3277 | #error FP_LUT must be between 4 and 12 inclusively
|
---|
| 3278 | #endif
|
---|
| 3279 | #else
|
---|
| 3280 | #if (FP_LUT > 12) || (FP_LUT < 2)
|
---|
| 3281 | #error FP_LUT must be between 2 and 12 inclusively
|
---|
| 3282 | #endif
|
---|
| 3283 | #endif
|
---|
| 3284 |
|
---|
| 3285 |
|
---|
| 3286 | /** Our FP cache */
|
---|
| 3287 | typedef struct {
|
---|
| 3288 | ecc_point* g; /* cached COPY of base point */
|
---|
| 3289 | ecc_point* LUT[1U<<FP_LUT]; /* fixed point lookup */
|
---|
| 3290 | mp_int mu; /* copy of the montgomery constant */
|
---|
| 3291 | int lru_count; /* amount of times this entry has been used */
|
---|
| 3292 | int lock; /* flag to indicate cache eviction */
|
---|
| 3293 | /* permitted (0) or not (1) */
|
---|
| 3294 | } fp_cache_t;
|
---|
| 3295 |
|
---|
| 3296 | /* if HAVE_THREAD_LS this cache is per thread, no locking needed */
|
---|
| 3297 | static THREAD_LS_T fp_cache_t fp_cache[FP_ENTRIES];
|
---|
| 3298 |
|
---|
| 3299 | #ifndef HAVE_THREAD_LS
|
---|
| 3300 | static volatile int initMutex = 0; /* prevent multiple mutex inits */
|
---|
| 3301 | static wolfSSL_Mutex ecc_fp_lock;
|
---|
| 3302 | #endif /* HAVE_THREAD_LS */
|
---|
| 3303 |
|
---|
| 3304 | /* simple table to help direct the generation of the LUT */
|
---|
| 3305 | static const struct {
|
---|
| 3306 | int ham, terma, termb;
|
---|
| 3307 | } lut_orders[] = {
|
---|
| 3308 | { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 }, { 2, 1, 2 }, { 1, 0, 0 }, { 2, 1, 4 }, { 2, 2, 4 }, { 3, 3, 4 },
|
---|
| 3309 | { 1, 0, 0 }, { 2, 1, 8 }, { 2, 2, 8 }, { 3, 3, 8 }, { 2, 4, 8 }, { 3, 5, 8 }, { 3, 6, 8 }, { 4, 7, 8 },
|
---|
| 3310 | { 1, 0, 0 }, { 2, 1, 16 }, { 2, 2, 16 }, { 3, 3, 16 }, { 2, 4, 16 }, { 3, 5, 16 }, { 3, 6, 16 }, { 4, 7, 16 },
|
---|
| 3311 | { 2, 8, 16 }, { 3, 9, 16 }, { 3, 10, 16 }, { 4, 11, 16 }, { 3, 12, 16 }, { 4, 13, 16 }, { 4, 14, 16 }, { 5, 15, 16 },
|
---|
| 3312 | { 1, 0, 0 }, { 2, 1, 32 }, { 2, 2, 32 }, { 3, 3, 32 }, { 2, 4, 32 }, { 3, 5, 32 }, { 3, 6, 32 }, { 4, 7, 32 },
|
---|
| 3313 | { 2, 8, 32 }, { 3, 9, 32 }, { 3, 10, 32 }, { 4, 11, 32 }, { 3, 12, 32 }, { 4, 13, 32 }, { 4, 14, 32 }, { 5, 15, 32 },
|
---|
| 3314 | { 2, 16, 32 }, { 3, 17, 32 }, { 3, 18, 32 }, { 4, 19, 32 }, { 3, 20, 32 }, { 4, 21, 32 }, { 4, 22, 32 }, { 5, 23, 32 },
|
---|
| 3315 | { 3, 24, 32 }, { 4, 25, 32 }, { 4, 26, 32 }, { 5, 27, 32 }, { 4, 28, 32 }, { 5, 29, 32 }, { 5, 30, 32 }, { 6, 31, 32 },
|
---|
| 3316 | #if FP_LUT > 6
|
---|
| 3317 | { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 },
|
---|
| 3318 | { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 },
|
---|
| 3319 | { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 },
|
---|
| 3320 | { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 },
|
---|
| 3321 | { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 },
|
---|
| 3322 | { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 },
|
---|
| 3323 | { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 },
|
---|
| 3324 | { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 },
|
---|
| 3325 | #if FP_LUT > 7
|
---|
| 3326 | { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 },
|
---|
| 3327 | { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 },
|
---|
| 3328 | { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 },
|
---|
| 3329 | { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 },
|
---|
| 3330 | { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 },
|
---|
| 3331 | { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 },
|
---|
| 3332 | { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 },
|
---|
| 3333 | { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 },
|
---|
| 3334 | { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 },
|
---|
| 3335 | { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 },
|
---|
| 3336 | { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 },
|
---|
| 3337 | { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 },
|
---|
| 3338 | { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 },
|
---|
| 3339 | { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 },
|
---|
| 3340 | { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 },
|
---|
| 3341 | { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 },
|
---|
| 3342 | #if FP_LUT > 8
|
---|
| 3343 | { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 },
|
---|
| 3344 | { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 },
|
---|
| 3345 | { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 },
|
---|
| 3346 | { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 },
|
---|
| 3347 | { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 },
|
---|
| 3348 | { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 },
|
---|
| 3349 | { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 },
|
---|
| 3350 | { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 },
|
---|
| 3351 | { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 },
|
---|
| 3352 | { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 },
|
---|
| 3353 | { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 },
|
---|
| 3354 | { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 },
|
---|
| 3355 | { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 },
|
---|
| 3356 | { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 },
|
---|
| 3357 | { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 },
|
---|
| 3358 | { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 },
|
---|
| 3359 | { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 },
|
---|
| 3360 | { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 },
|
---|
| 3361 | { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 },
|
---|
| 3362 | { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 },
|
---|
| 3363 | { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 },
|
---|
| 3364 | { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 },
|
---|
| 3365 | { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 },
|
---|
| 3366 | { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 },
|
---|
| 3367 | { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 },
|
---|
| 3368 | { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 },
|
---|
| 3369 | { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 },
|
---|
| 3370 | { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 },
|
---|
| 3371 | { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 },
|
---|
| 3372 | { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 },
|
---|
| 3373 | { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 },
|
---|
| 3374 | { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 },
|
---|
| 3375 | #if FP_LUT > 9
|
---|
| 3376 | { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 },
|
---|
| 3377 | { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 },
|
---|
| 3378 | { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 },
|
---|
| 3379 | { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 },
|
---|
| 3380 | { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 },
|
---|
| 3381 | { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 },
|
---|
| 3382 | { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 },
|
---|
| 3383 | { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 },
|
---|
| 3384 | { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 },
|
---|
| 3385 | { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 },
|
---|
| 3386 | { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 },
|
---|
| 3387 | { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 },
|
---|
| 3388 | { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 },
|
---|
| 3389 | { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 },
|
---|
| 3390 | { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 },
|
---|
| 3391 | { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 },
|
---|
| 3392 | { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 },
|
---|
| 3393 | { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 },
|
---|
| 3394 | { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 },
|
---|
| 3395 | { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 },
|
---|
| 3396 | { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 },
|
---|
| 3397 | { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 },
|
---|
| 3398 | { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 },
|
---|
| 3399 | { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 },
|
---|
| 3400 | { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 },
|
---|
| 3401 | { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 },
|
---|
| 3402 | { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 },
|
---|
| 3403 | { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 },
|
---|
| 3404 | { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 },
|
---|
| 3405 | { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 },
|
---|
| 3406 | { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 },
|
---|
| 3407 | { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 },
|
---|
| 3408 | { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 },
|
---|
| 3409 | { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 },
|
---|
| 3410 | { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 },
|
---|
| 3411 | { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 },
|
---|
| 3412 | { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 },
|
---|
| 3413 | { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 },
|
---|
| 3414 | { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 },
|
---|
| 3415 | { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 },
|
---|
| 3416 | { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 },
|
---|
| 3417 | { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 },
|
---|
| 3418 | { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 },
|
---|
| 3419 | { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 },
|
---|
| 3420 | { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 },
|
---|
| 3421 | { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 },
|
---|
| 3422 | { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 },
|
---|
| 3423 | { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 },
|
---|
| 3424 | { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 },
|
---|
| 3425 | { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 },
|
---|
| 3426 | { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 },
|
---|
| 3427 | { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 },
|
---|
| 3428 | { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 },
|
---|
| 3429 | { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 },
|
---|
| 3430 | { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 },
|
---|
| 3431 | { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 },
|
---|
| 3432 | { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 },
|
---|
| 3433 | { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 },
|
---|
| 3434 | { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 },
|
---|
| 3435 | { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 },
|
---|
| 3436 | { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 },
|
---|
| 3437 | { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 },
|
---|
| 3438 | { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 },
|
---|
| 3439 | { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 },
|
---|
| 3440 | #if FP_LUT > 10
|
---|
| 3441 | { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 },
|
---|
| 3442 | { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 },
|
---|
| 3443 | { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 },
|
---|
| 3444 | { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 },
|
---|
| 3445 | { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 },
|
---|
| 3446 | { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 },
|
---|
| 3447 | { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 },
|
---|
| 3448 | { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 },
|
---|
| 3449 | { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 },
|
---|
| 3450 | { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 },
|
---|
| 3451 | { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 },
|
---|
| 3452 | { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 },
|
---|
| 3453 | { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 },
|
---|
| 3454 | { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 },
|
---|
| 3455 | { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 },
|
---|
| 3456 | { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 },
|
---|
| 3457 | { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 },
|
---|
| 3458 | { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 },
|
---|
| 3459 | { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 },
|
---|
| 3460 | { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 },
|
---|
| 3461 | { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 },
|
---|
| 3462 | { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 },
|
---|
| 3463 | { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 },
|
---|
| 3464 | { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 },
|
---|
| 3465 | { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 },
|
---|
| 3466 | { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 },
|
---|
| 3467 | { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 },
|
---|
| 3468 | { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 },
|
---|
| 3469 | { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 },
|
---|
| 3470 | { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 },
|
---|
| 3471 | { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 },
|
---|
| 3472 | { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 },
|
---|
| 3473 | { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 },
|
---|
| 3474 | { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 },
|
---|
| 3475 | { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 },
|
---|
| 3476 | { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 },
|
---|
| 3477 | { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 },
|
---|
| 3478 | { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 },
|
---|
| 3479 | { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 },
|
---|
| 3480 | { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 },
|
---|
| 3481 | { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 },
|
---|
| 3482 | { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 },
|
---|
| 3483 | { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 },
|
---|
| 3484 | { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 },
|
---|
| 3485 | { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 },
|
---|
| 3486 | { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 },
|
---|
| 3487 | { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 },
|
---|
| 3488 | { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 },
|
---|
| 3489 | { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 },
|
---|
| 3490 | { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 },
|
---|
| 3491 | { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 },
|
---|
| 3492 | { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 },
|
---|
| 3493 | { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 },
|
---|
| 3494 | { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 },
|
---|
| 3495 | { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 },
|
---|
| 3496 | { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 },
|
---|
| 3497 | { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 },
|
---|
| 3498 | { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 },
|
---|
| 3499 | { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 },
|
---|
| 3500 | { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 },
|
---|
| 3501 | { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 },
|
---|
| 3502 | { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 },
|
---|
| 3503 | { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 },
|
---|
| 3504 | { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 },
|
---|
| 3505 | { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 },
|
---|
| 3506 | { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 },
|
---|
| 3507 | { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 },
|
---|
| 3508 | { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 },
|
---|
| 3509 | { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 },
|
---|
| 3510 | { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 },
|
---|
| 3511 | { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 },
|
---|
| 3512 | { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 },
|
---|
| 3513 | { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 },
|
---|
| 3514 | { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 },
|
---|
| 3515 | { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 },
|
---|
| 3516 | { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 },
|
---|
| 3517 | { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 },
|
---|
| 3518 | { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 },
|
---|
| 3519 | { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 },
|
---|
| 3520 | { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 },
|
---|
| 3521 | { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 },
|
---|
| 3522 | { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 },
|
---|
| 3523 | { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 },
|
---|
| 3524 | { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 },
|
---|
| 3525 | { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 },
|
---|
| 3526 | { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 },
|
---|
| 3527 | { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 },
|
---|
| 3528 | { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 },
|
---|
| 3529 | { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 },
|
---|
| 3530 | { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 },
|
---|
| 3531 | { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 },
|
---|
| 3532 | { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 },
|
---|
| 3533 | { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 },
|
---|
| 3534 | { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 },
|
---|
| 3535 | { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 },
|
---|
| 3536 | { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 },
|
---|
| 3537 | { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 },
|
---|
| 3538 | { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 },
|
---|
| 3539 | { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 },
|
---|
| 3540 | { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 },
|
---|
| 3541 | { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 },
|
---|
| 3542 | { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 },
|
---|
| 3543 | { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 },
|
---|
| 3544 | { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 },
|
---|
| 3545 | { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 },
|
---|
| 3546 | { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 },
|
---|
| 3547 | { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 },
|
---|
| 3548 | { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 },
|
---|
| 3549 | { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 },
|
---|
| 3550 | { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 },
|
---|
| 3551 | { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 },
|
---|
| 3552 | { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 },
|
---|
| 3553 | { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 },
|
---|
| 3554 | { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 },
|
---|
| 3555 | { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 },
|
---|
| 3556 | { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 },
|
---|
| 3557 | { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 },
|
---|
| 3558 | { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 },
|
---|
| 3559 | { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 },
|
---|
| 3560 | { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 },
|
---|
| 3561 | { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 },
|
---|
| 3562 | { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 },
|
---|
| 3563 | { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 },
|
---|
| 3564 | { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 },
|
---|
| 3565 | { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 },
|
---|
| 3566 | { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 },
|
---|
| 3567 | { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 },
|
---|
| 3568 | { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 },
|
---|
| 3569 | #if FP_LUT > 11
|
---|
| 3570 | { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 },
|
---|
| 3571 | { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 },
|
---|
| 3572 | { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 },
|
---|
| 3573 | { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 },
|
---|
| 3574 | { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 },
|
---|
| 3575 | { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 },
|
---|
| 3576 | { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 },
|
---|
| 3577 | { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 },
|
---|
| 3578 | { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 },
|
---|
| 3579 | { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 },
|
---|
| 3580 | { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 },
|
---|
| 3581 | { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 },
|
---|
| 3582 | { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 },
|
---|
| 3583 | { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 },
|
---|
| 3584 | { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 },
|
---|
| 3585 | { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 },
|
---|
| 3586 | { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 },
|
---|
| 3587 | { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 },
|
---|
| 3588 | { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 },
|
---|
| 3589 | { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 },
|
---|
| 3590 | { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 },
|
---|
| 3591 | { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 },
|
---|
| 3592 | { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 },
|
---|
| 3593 | { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 },
|
---|
| 3594 | { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 },
|
---|
| 3595 | { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 },
|
---|
| 3596 | { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 },
|
---|
| 3597 | { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 },
|
---|
| 3598 | { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 },
|
---|
| 3599 | { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 },
|
---|
| 3600 | { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 },
|
---|
| 3601 | { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 },
|
---|
| 3602 | { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 },
|
---|
| 3603 | { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 },
|
---|
| 3604 | { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 },
|
---|
| 3605 | { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 },
|
---|
| 3606 | { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 },
|
---|
| 3607 | { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 },
|
---|
| 3608 | { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 },
|
---|
| 3609 | { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 },
|
---|
| 3610 | { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 },
|
---|
| 3611 | { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 },
|
---|
| 3612 | { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 },
|
---|
| 3613 | { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 },
|
---|
| 3614 | { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 },
|
---|
| 3615 | { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 },
|
---|
| 3616 | { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 },
|
---|
| 3617 | { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 },
|
---|
| 3618 | { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 },
|
---|
| 3619 | { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 },
|
---|
| 3620 | { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 },
|
---|
| 3621 | { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 },
|
---|
| 3622 | { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 },
|
---|
| 3623 | { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 },
|
---|
| 3624 | { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 },
|
---|
| 3625 | { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 },
|
---|
| 3626 | { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 },
|
---|
| 3627 | { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 },
|
---|
| 3628 | { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 },
|
---|
| 3629 | { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 },
|
---|
| 3630 | { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 },
|
---|
| 3631 | { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 },
|
---|
| 3632 | { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 },
|
---|
| 3633 | { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 },
|
---|
| 3634 | { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 },
|
---|
| 3635 | { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 },
|
---|
| 3636 | { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 },
|
---|
| 3637 | { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 },
|
---|
| 3638 | { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 },
|
---|
| 3639 | { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 },
|
---|
| 3640 | { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 },
|
---|
| 3641 | { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 },
|
---|
| 3642 | { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 },
|
---|
| 3643 | { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 },
|
---|
| 3644 | { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 },
|
---|
| 3645 | { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 },
|
---|
| 3646 | { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 },
|
---|
| 3647 | { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 },
|
---|
| 3648 | { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 },
|
---|
| 3649 | { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 },
|
---|
| 3650 | { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 },
|
---|
| 3651 | { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 },
|
---|
| 3652 | { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 },
|
---|
| 3653 | { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 },
|
---|
| 3654 | { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 },
|
---|
| 3655 | { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 },
|
---|
| 3656 | { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 },
|
---|
| 3657 | { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 },
|
---|
| 3658 | { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 },
|
---|
| 3659 | { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 },
|
---|
| 3660 | { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 },
|
---|
| 3661 | { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 },
|
---|
| 3662 | { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 },
|
---|
| 3663 | { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 },
|
---|
| 3664 | { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 },
|
---|
| 3665 | { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 },
|
---|
| 3666 | { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 },
|
---|
| 3667 | { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 },
|
---|
| 3668 | { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 },
|
---|
| 3669 | { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 },
|
---|
| 3670 | { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 },
|
---|
| 3671 | { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 },
|
---|
| 3672 | { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 },
|
---|
| 3673 | { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 },
|
---|
| 3674 | { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 },
|
---|
| 3675 | { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 },
|
---|
| 3676 | { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 },
|
---|
| 3677 | { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 },
|
---|
| 3678 | { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 },
|
---|
| 3679 | { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 },
|
---|
| 3680 | { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 },
|
---|
| 3681 | { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 },
|
---|
| 3682 | { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 },
|
---|
| 3683 | { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 },
|
---|
| 3684 | { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 },
|
---|
| 3685 | { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 },
|
---|
| 3686 | { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 },
|
---|
| 3687 | { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 },
|
---|
| 3688 | { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 },
|
---|
| 3689 | { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 },
|
---|
| 3690 | { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 },
|
---|
| 3691 | { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 },
|
---|
| 3692 | { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 },
|
---|
| 3693 | { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 },
|
---|
| 3694 | { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 },
|
---|
| 3695 | { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 },
|
---|
| 3696 | { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 },
|
---|
| 3697 | { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 },
|
---|
| 3698 | { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 },
|
---|
| 3699 | { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 },
|
---|
| 3700 | { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 },
|
---|
| 3701 | { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 },
|
---|
| 3702 | { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 },
|
---|
| 3703 | { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 },
|
---|
| 3704 | { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 },
|
---|
| 3705 | { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 },
|
---|
| 3706 | { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 },
|
---|
| 3707 | { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 },
|
---|
| 3708 | { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 },
|
---|
| 3709 | { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 },
|
---|
| 3710 | { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 },
|
---|
| 3711 | { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 },
|
---|
| 3712 | { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 },
|
---|
| 3713 | { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 },
|
---|
| 3714 | { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 },
|
---|
| 3715 | { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 },
|
---|
| 3716 | { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 },
|
---|
| 3717 | { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 },
|
---|
| 3718 | { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 },
|
---|
| 3719 | { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 },
|
---|
| 3720 | { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 },
|
---|
| 3721 | { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 },
|
---|
| 3722 | { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 },
|
---|
| 3723 | { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 },
|
---|
| 3724 | { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 },
|
---|
| 3725 | { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 },
|
---|
| 3726 | { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 },
|
---|
| 3727 | { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 },
|
---|
| 3728 | { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 },
|
---|
| 3729 | { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 },
|
---|
| 3730 | { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 },
|
---|
| 3731 | { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 },
|
---|
| 3732 | { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 },
|
---|
| 3733 | { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 },
|
---|
| 3734 | { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 },
|
---|
| 3735 | { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 },
|
---|
| 3736 | { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 },
|
---|
| 3737 | { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 },
|
---|
| 3738 | { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 },
|
---|
| 3739 | { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 },
|
---|
| 3740 | { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 },
|
---|
| 3741 | { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 },
|
---|
| 3742 | { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 },
|
---|
| 3743 | { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 },
|
---|
| 3744 | { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 },
|
---|
| 3745 | { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 },
|
---|
| 3746 | { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 },
|
---|
| 3747 | { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 },
|
---|
| 3748 | { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 },
|
---|
| 3749 | { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 },
|
---|
| 3750 | { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 },
|
---|
| 3751 | { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 },
|
---|
| 3752 | { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 },
|
---|
| 3753 | { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 },
|
---|
| 3754 | { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 },
|
---|
| 3755 | { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 },
|
---|
| 3756 | { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 },
|
---|
| 3757 | { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 },
|
---|
| 3758 | { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 },
|
---|
| 3759 | { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 },
|
---|
| 3760 | { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 },
|
---|
| 3761 | { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 },
|
---|
| 3762 | { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 },
|
---|
| 3763 | { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 },
|
---|
| 3764 | { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 },
|
---|
| 3765 | { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 },
|
---|
| 3766 | { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 },
|
---|
| 3767 | { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 },
|
---|
| 3768 | { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 },
|
---|
| 3769 | { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 },
|
---|
| 3770 | { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 },
|
---|
| 3771 | { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 },
|
---|
| 3772 | { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 },
|
---|
| 3773 | { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 },
|
---|
| 3774 | { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 },
|
---|
| 3775 | { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 },
|
---|
| 3776 | { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 },
|
---|
| 3777 | { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 },
|
---|
| 3778 | { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 },
|
---|
| 3779 | { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 },
|
---|
| 3780 | { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 },
|
---|
| 3781 | { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 },
|
---|
| 3782 | { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 },
|
---|
| 3783 | { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 },
|
---|
| 3784 | { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 },
|
---|
| 3785 | { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 },
|
---|
| 3786 | { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 },
|
---|
| 3787 | { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 },
|
---|
| 3788 | { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 },
|
---|
| 3789 | { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 },
|
---|
| 3790 | { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 },
|
---|
| 3791 | { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 },
|
---|
| 3792 | { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 },
|
---|
| 3793 | { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 },
|
---|
| 3794 | { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 },
|
---|
| 3795 | { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 },
|
---|
| 3796 | { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 },
|
---|
| 3797 | { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 },
|
---|
| 3798 | { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 },
|
---|
| 3799 | { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 },
|
---|
| 3800 | { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 },
|
---|
| 3801 | { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 },
|
---|
| 3802 | { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 },
|
---|
| 3803 | { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 },
|
---|
| 3804 | { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 },
|
---|
| 3805 | { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 },
|
---|
| 3806 | { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 },
|
---|
| 3807 | { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 },
|
---|
| 3808 | { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 },
|
---|
| 3809 | { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 },
|
---|
| 3810 | { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 },
|
---|
| 3811 | { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 },
|
---|
| 3812 | { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 },
|
---|
| 3813 | { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 },
|
---|
| 3814 | { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 },
|
---|
| 3815 | { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 },
|
---|
| 3816 | { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 },
|
---|
| 3817 | { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 },
|
---|
| 3818 | { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 },
|
---|
| 3819 | { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 },
|
---|
| 3820 | { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 },
|
---|
| 3821 | { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 },
|
---|
| 3822 | { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 },
|
---|
| 3823 | { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 },
|
---|
| 3824 | { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 },
|
---|
| 3825 | { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 },
|
---|
| 3826 | #endif
|
---|
| 3827 | #endif
|
---|
| 3828 | #endif
|
---|
| 3829 | #endif
|
---|
| 3830 | #endif
|
---|
| 3831 | #endif
|
---|
| 3832 | };
|
---|
| 3833 |
|
---|
| 3834 | /* find a hole and free as required, return -1 if no hole found */
|
---|
| 3835 | static int find_hole(void)
|
---|
| 3836 | {
|
---|
| 3837 | unsigned x;
|
---|
| 3838 | int y, z;
|
---|
| 3839 | for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) {
|
---|
| 3840 | if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) {
|
---|
| 3841 | z = x;
|
---|
| 3842 | y = fp_cache[x].lru_count;
|
---|
| 3843 | }
|
---|
| 3844 | }
|
---|
| 3845 |
|
---|
| 3846 | /* decrease all */
|
---|
| 3847 | for (x = 0; x < FP_ENTRIES; x++) {
|
---|
| 3848 | if (fp_cache[x].lru_count > 3) {
|
---|
| 3849 | --(fp_cache[x].lru_count);
|
---|
| 3850 | }
|
---|
| 3851 | }
|
---|
| 3852 |
|
---|
| 3853 | /* free entry z */
|
---|
| 3854 | if (z >= 0 && fp_cache[z].g) {
|
---|
| 3855 | mp_clear(&fp_cache[z].mu);
|
---|
| 3856 | wc_ecc_del_point(fp_cache[z].g);
|
---|
| 3857 | fp_cache[z].g = NULL;
|
---|
| 3858 | for (x = 0; x < (1U<<FP_LUT); x++) {
|
---|
| 3859 | wc_ecc_del_point(fp_cache[z].LUT[x]);
|
---|
| 3860 | fp_cache[z].LUT[x] = NULL;
|
---|
| 3861 | }
|
---|
| 3862 | fp_cache[z].lru_count = 0;
|
---|
| 3863 | }
|
---|
| 3864 | return z;
|
---|
| 3865 | }
|
---|
| 3866 |
|
---|
| 3867 | /* determine if a base is already in the cache and if so, where */
|
---|
| 3868 | static int find_base(ecc_point* g)
|
---|
| 3869 | {
|
---|
| 3870 | int x;
|
---|
| 3871 | for (x = 0; x < FP_ENTRIES; x++) {
|
---|
| 3872 | if (fp_cache[x].g != NULL &&
|
---|
| 3873 | mp_cmp(fp_cache[x].g->x, g->x) == MP_EQ &&
|
---|
| 3874 | mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ &&
|
---|
| 3875 | mp_cmp(fp_cache[x].g->z, g->z) == MP_EQ) {
|
---|
| 3876 | break;
|
---|
| 3877 | }
|
---|
| 3878 | }
|
---|
| 3879 | if (x == FP_ENTRIES) {
|
---|
| 3880 | x = -1;
|
---|
| 3881 | }
|
---|
| 3882 | return x;
|
---|
| 3883 | }
|
---|
| 3884 |
|
---|
| 3885 | /* add a new base to the cache */
|
---|
| 3886 | static int add_entry(int idx, ecc_point *g)
|
---|
| 3887 | {
|
---|
| 3888 | unsigned x, y;
|
---|
| 3889 |
|
---|
| 3890 | /* allocate base and LUT */
|
---|
| 3891 | fp_cache[idx].g = wc_ecc_new_point();
|
---|
| 3892 | if (fp_cache[idx].g == NULL) {
|
---|
| 3893 | return GEN_MEM_ERR;
|
---|
| 3894 | }
|
---|
| 3895 |
|
---|
| 3896 | /* copy x and y */
|
---|
| 3897 | if ((mp_copy(g->x, fp_cache[idx].g->x) != MP_OKAY) ||
|
---|
| 3898 | (mp_copy(g->y, fp_cache[idx].g->y) != MP_OKAY) ||
|
---|
| 3899 | (mp_copy(g->z, fp_cache[idx].g->z) != MP_OKAY)) {
|
---|
| 3900 | wc_ecc_del_point(fp_cache[idx].g);
|
---|
| 3901 | fp_cache[idx].g = NULL;
|
---|
| 3902 | return GEN_MEM_ERR;
|
---|
| 3903 | }
|
---|
| 3904 |
|
---|
| 3905 | for (x = 0; x < (1U<<FP_LUT); x++) {
|
---|
| 3906 | fp_cache[idx].LUT[x] = wc_ecc_new_point();
|
---|
| 3907 | if (fp_cache[idx].LUT[x] == NULL) {
|
---|
| 3908 | for (y = 0; y < x; y++) {
|
---|
| 3909 | wc_ecc_del_point(fp_cache[idx].LUT[y]);
|
---|
| 3910 | fp_cache[idx].LUT[y] = NULL;
|
---|
| 3911 | }
|
---|
| 3912 | wc_ecc_del_point(fp_cache[idx].g);
|
---|
| 3913 | fp_cache[idx].g = NULL;
|
---|
| 3914 | fp_cache[idx].lru_count = 0;
|
---|
| 3915 | return GEN_MEM_ERR;
|
---|
| 3916 | }
|
---|
| 3917 | }
|
---|
| 3918 |
|
---|
| 3919 | fp_cache[idx].lru_count = 0;
|
---|
| 3920 |
|
---|
| 3921 | return MP_OKAY;
|
---|
| 3922 | }
|
---|
| 3923 |
|
---|
| 3924 | /* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart
|
---|
| 3925 | *
|
---|
| 3926 | * The algorithm builds patterns in increasing bit order by first making all
|
---|
| 3927 | * single bit input patterns, then all two bit input patterns and so on
|
---|
| 3928 | */
|
---|
| 3929 | static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu)
|
---|
| 3930 | {
|
---|
| 3931 | unsigned x, y, err, bitlen, lut_gap;
|
---|
| 3932 | mp_int tmp;
|
---|
| 3933 |
|
---|
| 3934 | if (mp_init(&tmp) != MP_OKAY)
|
---|
| 3935 | return GEN_MEM_ERR;
|
---|
| 3936 |
|
---|
| 3937 | /* sanity check to make sure lut_order table is of correct size,
|
---|
| 3938 | should compile out to a NOP if true */
|
---|
| 3939 | if ((sizeof(lut_orders) / sizeof(lut_orders[0])) < (1U<<FP_LUT)) {
|
---|
| 3940 | err = BAD_FUNC_ARG;
|
---|
| 3941 | }
|
---|
| 3942 | else {
|
---|
| 3943 | /* get bitlen and round up to next multiple of FP_LUT */
|
---|
| 3944 | bitlen = mp_unsigned_bin_size(modulus) << 3;
|
---|
| 3945 | x = bitlen % FP_LUT;
|
---|
| 3946 | if (x) {
|
---|
| 3947 | bitlen += FP_LUT - x;
|
---|
| 3948 | }
|
---|
| 3949 | lut_gap = bitlen / FP_LUT;
|
---|
| 3950 |
|
---|
| 3951 | /* init the mu */
|
---|
| 3952 | err = mp_init_copy(&fp_cache[idx].mu, mu);
|
---|
| 3953 | }
|
---|
| 3954 |
|
---|
| 3955 | /* copy base */
|
---|
| 3956 | if (err == MP_OKAY) {
|
---|
| 3957 | if ((mp_mulmod(fp_cache[idx].g->x, mu, modulus,
|
---|
| 3958 | fp_cache[idx].LUT[1]->x) != MP_OKAY) ||
|
---|
| 3959 | (mp_mulmod(fp_cache[idx].g->y, mu, modulus,
|
---|
| 3960 | fp_cache[idx].LUT[1]->y) != MP_OKAY) ||
|
---|
| 3961 | (mp_mulmod(fp_cache[idx].g->z, mu, modulus,
|
---|
| 3962 | fp_cache[idx].LUT[1]->z) != MP_OKAY)) {
|
---|
| 3963 | err = MP_MULMOD_E;
|
---|
| 3964 | }
|
---|
| 3965 | }
|
---|
| 3966 |
|
---|
| 3967 | /* make all single bit entries */
|
---|
| 3968 | for (x = 1; x < FP_LUT; x++) {
|
---|
| 3969 | if (err != MP_OKAY)
|
---|
| 3970 | break;
|
---|
| 3971 | if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x,
|
---|
| 3972 | fp_cache[idx].LUT[1<<x]->x) != MP_OKAY) ||
|
---|
| 3973 | (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y,
|
---|
| 3974 | fp_cache[idx].LUT[1<<x]->y) != MP_OKAY) ||
|
---|
| 3975 | (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z,
|
---|
| 3976 | fp_cache[idx].LUT[1<<x]->z) != MP_OKAY)){
|
---|
| 3977 | err = MP_INIT_E;
|
---|
| 3978 | break;
|
---|
| 3979 | } else {
|
---|
| 3980 |
|
---|
| 3981 | /* now double it bitlen/FP_LUT times */
|
---|
| 3982 | for (y = 0; y < lut_gap; y++) {
|
---|
| 3983 | if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<<x],
|
---|
| 3984 | fp_cache[idx].LUT[1<<x], modulus, mp)) != MP_OKAY) {
|
---|
| 3985 | break;
|
---|
| 3986 | }
|
---|
| 3987 | }
|
---|
| 3988 | }
|
---|
| 3989 | }
|
---|
| 3990 |
|
---|
| 3991 | /* now make all entries in increase order of hamming weight */
|
---|
| 3992 | for (x = 2; x <= FP_LUT; x++) {
|
---|
| 3993 | if (err != MP_OKAY)
|
---|
| 3994 | break;
|
---|
| 3995 | for (y = 0; y < (1UL<<FP_LUT); y++) {
|
---|
| 3996 | if (err != MP_OKAY)
|
---|
| 3997 | break;
|
---|
| 3998 | if (lut_orders[y].ham != (int)x) continue;
|
---|
| 3999 |
|
---|
| 4000 | /* perform the add */
|
---|
| 4001 | if ((err = ecc_projective_add_point(
|
---|
| 4002 | fp_cache[idx].LUT[lut_orders[y].terma],
|
---|
| 4003 | fp_cache[idx].LUT[lut_orders[y].termb],
|
---|
| 4004 | fp_cache[idx].LUT[y], modulus, mp)) != MP_OKAY) {
|
---|
| 4005 | break;
|
---|
| 4006 | }
|
---|
| 4007 | }
|
---|
| 4008 | }
|
---|
| 4009 |
|
---|
| 4010 | /* now map all entries back to affine space to make point addition faster */
|
---|
| 4011 | for (x = 1; x < (1UL<<FP_LUT); x++) {
|
---|
| 4012 | if (err != MP_OKAY)
|
---|
| 4013 | break;
|
---|
| 4014 |
|
---|
| 4015 | /* convert z to normal from montgomery */
|
---|
| 4016 | err = mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, *mp);
|
---|
| 4017 |
|
---|
| 4018 | /* invert it */
|
---|
| 4019 | if (err == MP_OKAY)
|
---|
| 4020 | err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus,
|
---|
| 4021 | fp_cache[idx].LUT[x]->z);
|
---|
| 4022 |
|
---|
| 4023 | if (err == MP_OKAY)
|
---|
| 4024 | /* now square it */
|
---|
| 4025 | err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, &tmp);
|
---|
| 4026 |
|
---|
| 4027 | if (err == MP_OKAY)
|
---|
| 4028 | /* fix x */
|
---|
| 4029 | err = mp_mulmod(fp_cache[idx].LUT[x]->x, &tmp, modulus,
|
---|
| 4030 | fp_cache[idx].LUT[x]->x);
|
---|
| 4031 |
|
---|
| 4032 | if (err == MP_OKAY)
|
---|
| 4033 | /* get 1/z^3 */
|
---|
| 4034 | err = mp_mulmod(&tmp, fp_cache[idx].LUT[x]->z, modulus, &tmp);
|
---|
| 4035 |
|
---|
| 4036 | if (err == MP_OKAY)
|
---|
| 4037 | /* fix y */
|
---|
| 4038 | err = mp_mulmod(fp_cache[idx].LUT[x]->y, &tmp, modulus,
|
---|
| 4039 | fp_cache[idx].LUT[x]->y);
|
---|
| 4040 |
|
---|
| 4041 | if (err == MP_OKAY)
|
---|
| 4042 | /* free z */
|
---|
| 4043 | mp_clear(fp_cache[idx].LUT[x]->z);
|
---|
| 4044 | }
|
---|
| 4045 | mp_clear(&tmp);
|
---|
| 4046 |
|
---|
| 4047 | if (err == MP_OKAY)
|
---|
| 4048 | return MP_OKAY;
|
---|
| 4049 |
|
---|
| 4050 | /* err cleanup */
|
---|
| 4051 | for (y = 0; y < (1U<<FP_LUT); y++) {
|
---|
| 4052 | wc_ecc_del_point(fp_cache[idx].LUT[y]);
|
---|
| 4053 | fp_cache[idx].LUT[y] = NULL;
|
---|
| 4054 | }
|
---|
| 4055 | wc_ecc_del_point(fp_cache[idx].g);
|
---|
| 4056 | fp_cache[idx].g = NULL;
|
---|
| 4057 | fp_cache[idx].lru_count = 0;
|
---|
| 4058 | mp_clear(&fp_cache[idx].mu);
|
---|
| 4059 | mp_clear(&tmp);
|
---|
| 4060 |
|
---|
| 4061 | return err;
|
---|
| 4062 | }
|
---|
| 4063 |
|
---|
| 4064 | /* perform a fixed point ECC mulmod */
|
---|
| 4065 | static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
|
---|
| 4066 | mp_digit* mp, int map)
|
---|
| 4067 | {
|
---|
| 4068 | #define KB_SIZE 128
|
---|
| 4069 |
|
---|
| 4070 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4071 | unsigned char* kb;
|
---|
| 4072 | #else
|
---|
| 4073 | unsigned char kb[128];
|
---|
| 4074 | #endif
|
---|
| 4075 | int x;
|
---|
| 4076 | unsigned y, z, err, bitlen, bitpos, lut_gap, first;
|
---|
| 4077 | mp_int tk;
|
---|
| 4078 |
|
---|
| 4079 | if (mp_init(&tk) != MP_OKAY)
|
---|
| 4080 | return MP_INIT_E;
|
---|
| 4081 |
|
---|
| 4082 | /* if it's smaller than modulus we fine */
|
---|
| 4083 | if (mp_unsigned_bin_size(k) > mp_unsigned_bin_size(modulus)) {
|
---|
| 4084 | mp_int order;
|
---|
| 4085 | if (mp_init(&order) != MP_OKAY) {
|
---|
| 4086 | mp_clear(&tk);
|
---|
| 4087 | return MP_INIT_E;
|
---|
| 4088 | }
|
---|
| 4089 |
|
---|
| 4090 | /* find order */
|
---|
| 4091 | y = mp_unsigned_bin_size(modulus);
|
---|
| 4092 | for (x = 0; ecc_sets[x].size; x++) {
|
---|
| 4093 | if (y <= (unsigned)ecc_sets[x].size) break;
|
---|
| 4094 | }
|
---|
| 4095 |
|
---|
| 4096 | /* back off if we are on the 521 bit curve */
|
---|
| 4097 | if (y == 66) --x;
|
---|
| 4098 |
|
---|
| 4099 | if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
|
---|
| 4100 | mp_clear(&order);
|
---|
| 4101 | mp_clear(&tk);
|
---|
| 4102 | return err;
|
---|
| 4103 | }
|
---|
| 4104 |
|
---|
| 4105 | /* k must be less than modulus */
|
---|
| 4106 | if (mp_cmp(k, &order) != MP_LT) {
|
---|
| 4107 | if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) {
|
---|
| 4108 | mp_clear(&tk);
|
---|
| 4109 | mp_clear(&order);
|
---|
| 4110 | return err;
|
---|
| 4111 | }
|
---|
| 4112 | } else {
|
---|
| 4113 | mp_copy(k, &tk);
|
---|
| 4114 | }
|
---|
| 4115 | mp_clear(&order);
|
---|
| 4116 | } else {
|
---|
| 4117 | mp_copy(k, &tk);
|
---|
| 4118 | }
|
---|
| 4119 |
|
---|
| 4120 | /* get bitlen and round up to next multiple of FP_LUT */
|
---|
| 4121 | bitlen = mp_unsigned_bin_size(modulus) << 3;
|
---|
| 4122 | x = bitlen % FP_LUT;
|
---|
| 4123 | if (x) {
|
---|
| 4124 | bitlen += FP_LUT - x;
|
---|
| 4125 | }
|
---|
| 4126 | lut_gap = bitlen / FP_LUT;
|
---|
| 4127 |
|
---|
| 4128 | /* get the k value */
|
---|
| 4129 | if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
|
---|
| 4130 | mp_clear(&tk);
|
---|
| 4131 | return BUFFER_E;
|
---|
| 4132 | }
|
---|
| 4133 |
|
---|
| 4134 | /* store k */
|
---|
| 4135 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4136 | kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4137 | if (kb == NULL)
|
---|
| 4138 | return MEMORY_E;
|
---|
| 4139 | #endif
|
---|
| 4140 |
|
---|
| 4141 | XMEMSET(kb, 0, KB_SIZE);
|
---|
| 4142 | if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) {
|
---|
| 4143 | mp_clear(&tk);
|
---|
| 4144 | }
|
---|
| 4145 | else {
|
---|
| 4146 | /* let's reverse kb so it's little endian */
|
---|
| 4147 | x = 0;
|
---|
| 4148 | y = mp_unsigned_bin_size(&tk) - 1;
|
---|
| 4149 | mp_clear(&tk);
|
---|
| 4150 |
|
---|
| 4151 | while ((unsigned)x < y) {
|
---|
| 4152 | z = kb[x]; kb[x] = kb[y]; kb[y] = z;
|
---|
| 4153 | ++x; --y;
|
---|
| 4154 | }
|
---|
| 4155 |
|
---|
| 4156 | /* at this point we can start, yipee */
|
---|
| 4157 | first = 1;
|
---|
| 4158 | for (x = lut_gap-1; x >= 0; x--) {
|
---|
| 4159 | /* extract FP_LUT bits from kb spread out by lut_gap bits and offset
|
---|
| 4160 | by x bits from the start */
|
---|
| 4161 | bitpos = x;
|
---|
| 4162 | for (y = z = 0; y < FP_LUT; y++) {
|
---|
| 4163 | z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
|
---|
| 4164 | bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
|
---|
| 4165 | the mult in each loop */
|
---|
| 4166 | }
|
---|
| 4167 |
|
---|
| 4168 | /* double if not first */
|
---|
| 4169 | if (!first) {
|
---|
| 4170 | if ((err = ecc_projective_dbl_point(R, R, modulus,
|
---|
| 4171 | mp)) != MP_OKAY) {
|
---|
| 4172 | break;
|
---|
| 4173 | }
|
---|
| 4174 | }
|
---|
| 4175 |
|
---|
| 4176 | /* add if not first, otherwise copy */
|
---|
| 4177 | if (!first && z) {
|
---|
| 4178 | if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
|
---|
| 4179 | modulus, mp)) != MP_OKAY) {
|
---|
| 4180 | break;
|
---|
| 4181 | }
|
---|
| 4182 | } else if (z) {
|
---|
| 4183 | if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) ||
|
---|
| 4184 | (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) ||
|
---|
| 4185 | (mp_copy(&fp_cache[idx].mu, R->z) != MP_OKAY)) {
|
---|
| 4186 | err = GEN_MEM_ERR;
|
---|
| 4187 | break;
|
---|
| 4188 | }
|
---|
| 4189 | first = 0;
|
---|
| 4190 | }
|
---|
| 4191 | }
|
---|
| 4192 | }
|
---|
| 4193 |
|
---|
| 4194 | if (err == MP_OKAY) {
|
---|
| 4195 | z = 0;
|
---|
| 4196 | ForceZero(kb, KB_SIZE);
|
---|
| 4197 | /* map R back from projective space */
|
---|
| 4198 | if (map) {
|
---|
| 4199 | err = ecc_map(R, modulus, mp);
|
---|
| 4200 | } else {
|
---|
| 4201 | err = MP_OKAY;
|
---|
| 4202 | }
|
---|
| 4203 | }
|
---|
| 4204 |
|
---|
| 4205 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4206 | XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4207 | #endif
|
---|
| 4208 |
|
---|
| 4209 | #undef KB_SIZE
|
---|
| 4210 |
|
---|
| 4211 | return err;
|
---|
| 4212 | }
|
---|
| 4213 |
|
---|
| 4214 | #ifdef ECC_SHAMIR
|
---|
| 4215 | /* perform a fixed point ECC mulmod */
|
---|
| 4216 | static int accel_fp_mul2add(int idx1, int idx2,
|
---|
| 4217 | mp_int* kA, mp_int* kB,
|
---|
| 4218 | ecc_point *R, mp_int* modulus, mp_digit* mp)
|
---|
| 4219 | {
|
---|
| 4220 | #define KB_SIZE 128
|
---|
| 4221 |
|
---|
| 4222 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4223 | unsigned char* kb[2];
|
---|
| 4224 | #else
|
---|
| 4225 | unsigned char kb[2][128];
|
---|
| 4226 | #endif
|
---|
| 4227 | int x;
|
---|
| 4228 | unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
|
---|
| 4229 | mp_int tka;
|
---|
| 4230 | mp_int tkb;
|
---|
| 4231 | mp_int order;
|
---|
| 4232 |
|
---|
| 4233 | if (mp_init_multi(&tka, &tkb, 0, 0, 0, 0) != MP_OKAY)
|
---|
| 4234 | return MP_INIT_E;
|
---|
| 4235 |
|
---|
| 4236 | /* if it's smaller than modulus we fine */
|
---|
| 4237 | if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) {
|
---|
| 4238 | /* find order */
|
---|
| 4239 | y = mp_unsigned_bin_size(modulus);
|
---|
| 4240 | for (x = 0; ecc_sets[x].size; x++) {
|
---|
| 4241 | if (y <= (unsigned)ecc_sets[x].size) break;
|
---|
| 4242 | }
|
---|
| 4243 |
|
---|
| 4244 | /* back off if we are on the 521 bit curve */
|
---|
| 4245 | if (y == 66) --x;
|
---|
| 4246 |
|
---|
| 4247 | if ((err = mp_init(&order)) != MP_OKAY) {
|
---|
| 4248 | mp_clear(&tkb);
|
---|
| 4249 | mp_clear(&tka);
|
---|
| 4250 | return err;
|
---|
| 4251 | }
|
---|
| 4252 | if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
|
---|
| 4253 | mp_clear(&tkb);
|
---|
| 4254 | mp_clear(&tka);
|
---|
| 4255 | mp_clear(&order);
|
---|
| 4256 | return err;
|
---|
| 4257 | }
|
---|
| 4258 |
|
---|
| 4259 | /* kA must be less than modulus */
|
---|
| 4260 | if (mp_cmp(kA, &order) != MP_LT) {
|
---|
| 4261 | if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) {
|
---|
| 4262 | mp_clear(&tkb);
|
---|
| 4263 | mp_clear(&tka);
|
---|
| 4264 | mp_clear(&order);
|
---|
| 4265 | return err;
|
---|
| 4266 | }
|
---|
| 4267 | } else {
|
---|
| 4268 | mp_copy(kA, &tka);
|
---|
| 4269 | }
|
---|
| 4270 | mp_clear(&order);
|
---|
| 4271 | } else {
|
---|
| 4272 | mp_copy(kA, &tka);
|
---|
| 4273 | }
|
---|
| 4274 |
|
---|
| 4275 | /* if it's smaller than modulus we fine */
|
---|
| 4276 | if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) {
|
---|
| 4277 | /* find order */
|
---|
| 4278 | y = mp_unsigned_bin_size(modulus);
|
---|
| 4279 | for (x = 0; ecc_sets[x].size; x++) {
|
---|
| 4280 | if (y <= (unsigned)ecc_sets[x].size) break;
|
---|
| 4281 | }
|
---|
| 4282 |
|
---|
| 4283 | /* back off if we are on the 521 bit curve */
|
---|
| 4284 | if (y == 66) --x;
|
---|
| 4285 |
|
---|
| 4286 | if ((err = mp_init(&order)) != MP_OKAY) {
|
---|
| 4287 | mp_clear(&tkb);
|
---|
| 4288 | mp_clear(&tka);
|
---|
| 4289 | return err;
|
---|
| 4290 | }
|
---|
| 4291 | if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
|
---|
| 4292 | mp_clear(&tkb);
|
---|
| 4293 | mp_clear(&tka);
|
---|
| 4294 | mp_clear(&order);
|
---|
| 4295 | return err;
|
---|
| 4296 | }
|
---|
| 4297 |
|
---|
| 4298 | /* kB must be less than modulus */
|
---|
| 4299 | if (mp_cmp(kB, &order) != MP_LT) {
|
---|
| 4300 | if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) {
|
---|
| 4301 | mp_clear(&tkb);
|
---|
| 4302 | mp_clear(&tka);
|
---|
| 4303 | mp_clear(&order);
|
---|
| 4304 | return err;
|
---|
| 4305 | }
|
---|
| 4306 | } else {
|
---|
| 4307 | mp_copy(kB, &tkb);
|
---|
| 4308 | }
|
---|
| 4309 | mp_clear(&order);
|
---|
| 4310 | } else {
|
---|
| 4311 | mp_copy(kB, &tkb);
|
---|
| 4312 | }
|
---|
| 4313 |
|
---|
| 4314 | /* get bitlen and round up to next multiple of FP_LUT */
|
---|
| 4315 | bitlen = mp_unsigned_bin_size(modulus) << 3;
|
---|
| 4316 | x = bitlen % FP_LUT;
|
---|
| 4317 | if (x) {
|
---|
| 4318 | bitlen += FP_LUT - x;
|
---|
| 4319 | }
|
---|
| 4320 | lut_gap = bitlen / FP_LUT;
|
---|
| 4321 |
|
---|
| 4322 | /* get the k value */
|
---|
| 4323 | if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
|
---|
| 4324 | (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) {
|
---|
| 4325 | mp_clear(&tka);
|
---|
| 4326 | mp_clear(&tkb);
|
---|
| 4327 | return BUFFER_E;
|
---|
| 4328 | }
|
---|
| 4329 |
|
---|
| 4330 | /* store k */
|
---|
| 4331 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4332 | kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4333 | if (kb[0] == NULL)
|
---|
| 4334 | return MEMORY_E;
|
---|
| 4335 | #endif
|
---|
| 4336 |
|
---|
| 4337 | XMEMSET(kb[0], 0, KB_SIZE);
|
---|
| 4338 | if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
|
---|
| 4339 | mp_clear(&tka);
|
---|
| 4340 | mp_clear(&tkb);
|
---|
| 4341 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4342 | XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4343 | #endif
|
---|
| 4344 | return err;
|
---|
| 4345 | }
|
---|
| 4346 |
|
---|
| 4347 | /* let's reverse kb so it's little endian */
|
---|
| 4348 | x = 0;
|
---|
| 4349 | y = mp_unsigned_bin_size(&tka) - 1;
|
---|
| 4350 | mp_clear(&tka);
|
---|
| 4351 | while ((unsigned)x < y) {
|
---|
| 4352 | z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z;
|
---|
| 4353 | ++x; --y;
|
---|
| 4354 | }
|
---|
| 4355 |
|
---|
| 4356 | /* store b */
|
---|
| 4357 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4358 | kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4359 | if (kb[1] == NULL) {
|
---|
| 4360 | XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4361 | return MEMORY_E;
|
---|
| 4362 | }
|
---|
| 4363 | #endif
|
---|
| 4364 |
|
---|
| 4365 | XMEMSET(kb[1], 0, KB_SIZE);
|
---|
| 4366 | if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) {
|
---|
| 4367 | mp_clear(&tkb);
|
---|
| 4368 | }
|
---|
| 4369 | else {
|
---|
| 4370 | x = 0;
|
---|
| 4371 | y = mp_unsigned_bin_size(&tkb) - 1;
|
---|
| 4372 | mp_clear(&tkb);
|
---|
| 4373 | while ((unsigned)x < y) {
|
---|
| 4374 | z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
|
---|
| 4375 | ++x; --y;
|
---|
| 4376 | }
|
---|
| 4377 |
|
---|
| 4378 | /* at this point we can start, yipee */
|
---|
| 4379 | first = 1;
|
---|
| 4380 | for (x = lut_gap-1; x >= 0; x--) {
|
---|
| 4381 | /* extract FP_LUT bits from kb spread out by lut_gap bits and
|
---|
| 4382 | offset by x bits from the start */
|
---|
| 4383 | bitpos = x;
|
---|
| 4384 | for (y = zA = zB = 0; y < FP_LUT; y++) {
|
---|
| 4385 | zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
|
---|
| 4386 | zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
|
---|
| 4387 | bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid
|
---|
| 4388 | the mult in each loop */
|
---|
| 4389 | }
|
---|
| 4390 |
|
---|
| 4391 | /* double if not first */
|
---|
| 4392 | if (!first) {
|
---|
| 4393 | if ((err = ecc_projective_dbl_point(R, R, modulus,
|
---|
| 4394 | mp)) != MP_OKAY) {
|
---|
| 4395 | break;
|
---|
| 4396 | }
|
---|
| 4397 | }
|
---|
| 4398 |
|
---|
| 4399 | /* add if not first, otherwise copy */
|
---|
| 4400 | if (!first) {
|
---|
| 4401 | if (zA) {
|
---|
| 4402 | if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
|
---|
| 4403 | R, modulus, mp)) != MP_OKAY) {
|
---|
| 4404 | break;
|
---|
| 4405 | }
|
---|
| 4406 | }
|
---|
| 4407 | if (zB) {
|
---|
| 4408 | if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
|
---|
| 4409 | R, modulus, mp)) != MP_OKAY) {
|
---|
| 4410 | break;
|
---|
| 4411 | }
|
---|
| 4412 | }
|
---|
| 4413 | } else {
|
---|
| 4414 | if (zA) {
|
---|
| 4415 | if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) ||
|
---|
| 4416 | (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) ||
|
---|
| 4417 | (mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) {
|
---|
| 4418 | err = GEN_MEM_ERR;
|
---|
| 4419 | break;
|
---|
| 4420 | }
|
---|
| 4421 | first = 0;
|
---|
| 4422 | }
|
---|
| 4423 | if (zB && first == 0) {
|
---|
| 4424 | if (zB) {
|
---|
| 4425 | if ((err = ecc_projective_add_point(R,
|
---|
| 4426 | fp_cache[idx2].LUT[zB], R, modulus, mp)) != MP_OKAY){
|
---|
| 4427 | break;
|
---|
| 4428 | }
|
---|
| 4429 | }
|
---|
| 4430 | } else if (zB && first == 1) {
|
---|
| 4431 | if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) ||
|
---|
| 4432 | (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) ||
|
---|
| 4433 | (mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) {
|
---|
| 4434 | err = GEN_MEM_ERR;
|
---|
| 4435 | break;
|
---|
| 4436 | }
|
---|
| 4437 | first = 0;
|
---|
| 4438 | }
|
---|
| 4439 | }
|
---|
| 4440 | }
|
---|
| 4441 | }
|
---|
| 4442 |
|
---|
| 4443 | ForceZero(kb[0], KB_SIZE);
|
---|
| 4444 | ForceZero(kb[1], KB_SIZE);
|
---|
| 4445 |
|
---|
| 4446 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4447 | XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4448 | XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 4449 | #endif
|
---|
| 4450 |
|
---|
| 4451 | #undef KB_SIZE
|
---|
| 4452 |
|
---|
| 4453 | return ecc_map(R, modulus, mp);
|
---|
| 4454 | }
|
---|
| 4455 |
|
---|
| 4456 | /** ECC Fixed Point mulmod global
|
---|
| 4457 | Computes kA*A + kB*B = C using Shamir's Trick
|
---|
| 4458 | A First point to multiply
|
---|
| 4459 | kA What to multiple A by
|
---|
| 4460 | B Second point to multiply
|
---|
| 4461 | kB What to multiple B by
|
---|
| 4462 | C [out] Destination point (can overlap with A or B)
|
---|
| 4463 | modulus Modulus for curve
|
---|
| 4464 | return MP_OKAY on success
|
---|
| 4465 | */
|
---|
| 4466 | int ecc_mul2add(ecc_point* A, mp_int* kA,
|
---|
| 4467 | ecc_point* B, mp_int* kB,
|
---|
| 4468 | ecc_point* C, mp_int* modulus)
|
---|
| 4469 | {
|
---|
| 4470 | int idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0;
|
---|
| 4471 | mp_digit mp;
|
---|
| 4472 | mp_int mu;
|
---|
| 4473 |
|
---|
| 4474 | err = mp_init(&mu);
|
---|
| 4475 | if (err != MP_OKAY)
|
---|
| 4476 | return err;
|
---|
| 4477 |
|
---|
| 4478 | #ifndef HAVE_THREAD_LS
|
---|
| 4479 | if (initMutex == 0) {
|
---|
| 4480 | InitMutex(&ecc_fp_lock);
|
---|
| 4481 | initMutex = 1;
|
---|
| 4482 | }
|
---|
| 4483 | if (LockMutex(&ecc_fp_lock) != 0)
|
---|
| 4484 | return BAD_MUTEX_E;
|
---|
| 4485 | #endif /* HAVE_THREAD_LS */
|
---|
| 4486 |
|
---|
| 4487 | /* find point */
|
---|
| 4488 | idx1 = find_base(A);
|
---|
| 4489 |
|
---|
| 4490 | /* no entry? */
|
---|
| 4491 | if (idx1 == -1) {
|
---|
| 4492 | /* find hole and add it */
|
---|
| 4493 | if ((idx1 = find_hole()) >= 0) {
|
---|
| 4494 | err = add_entry(idx1, A);
|
---|
| 4495 | }
|
---|
| 4496 | }
|
---|
| 4497 | if (err == MP_OKAY && idx1 != -1) {
|
---|
| 4498 | /* increment LRU */
|
---|
| 4499 | ++(fp_cache[idx1].lru_count);
|
---|
| 4500 | }
|
---|
| 4501 |
|
---|
| 4502 | if (err == MP_OKAY)
|
---|
| 4503 | /* find point */
|
---|
| 4504 | idx2 = find_base(B);
|
---|
| 4505 |
|
---|
| 4506 | if (err == MP_OKAY) {
|
---|
| 4507 | /* no entry? */
|
---|
| 4508 | if (idx2 == -1) {
|
---|
| 4509 | /* find hole and add it */
|
---|
| 4510 | if ((idx2 = find_hole()) >= 0)
|
---|
| 4511 | err = add_entry(idx2, B);
|
---|
| 4512 | }
|
---|
| 4513 | }
|
---|
| 4514 |
|
---|
| 4515 | if (err == MP_OKAY && idx2 != -1) {
|
---|
| 4516 | /* increment LRU */
|
---|
| 4517 | ++(fp_cache[idx2].lru_count);
|
---|
| 4518 | }
|
---|
| 4519 |
|
---|
| 4520 | if (err == MP_OKAY) {
|
---|
| 4521 | /* if it's 2 build the LUT, if it's higher just use the LUT */
|
---|
| 4522 | if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) {
|
---|
| 4523 | /* compute mp */
|
---|
| 4524 | err = mp_montgomery_setup(modulus, &mp);
|
---|
| 4525 |
|
---|
| 4526 | if (err == MP_OKAY) {
|
---|
| 4527 | mpInit = 1;
|
---|
| 4528 | err = mp_montgomery_calc_normalization(&mu, modulus);
|
---|
| 4529 | }
|
---|
| 4530 |
|
---|
| 4531 | if (err == MP_OKAY)
|
---|
| 4532 | /* build the LUT */
|
---|
| 4533 | err = build_lut(idx1, modulus, &mp, &mu);
|
---|
| 4534 | }
|
---|
| 4535 | }
|
---|
| 4536 |
|
---|
| 4537 | if (err == MP_OKAY) {
|
---|
| 4538 | /* if it's 2 build the LUT, if it's higher just use the LUT */
|
---|
| 4539 | if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) {
|
---|
| 4540 | if (mpInit == 0) {
|
---|
| 4541 | /* compute mp */
|
---|
| 4542 | err = mp_montgomery_setup(modulus, &mp);
|
---|
| 4543 | if (err == MP_OKAY) {
|
---|
| 4544 | mpInit = 1;
|
---|
| 4545 | err = mp_montgomery_calc_normalization(&mu, modulus);
|
---|
| 4546 | }
|
---|
| 4547 | }
|
---|
| 4548 |
|
---|
| 4549 | if (err == MP_OKAY)
|
---|
| 4550 | /* build the LUT */
|
---|
| 4551 | err = build_lut(idx2, modulus, &mp, &mu);
|
---|
| 4552 | }
|
---|
| 4553 | }
|
---|
| 4554 |
|
---|
| 4555 |
|
---|
| 4556 | if (err == MP_OKAY) {
|
---|
| 4557 | if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 &&
|
---|
| 4558 | fp_cache[idx2].lru_count >= 2) {
|
---|
| 4559 | if (mpInit == 0) {
|
---|
| 4560 | /* compute mp */
|
---|
| 4561 | err = mp_montgomery_setup(modulus, &mp);
|
---|
| 4562 | }
|
---|
| 4563 | if (err == MP_OKAY)
|
---|
| 4564 | err = accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, &mp);
|
---|
| 4565 | } else {
|
---|
| 4566 | err = normal_ecc_mul2add(A, kA, B, kB, C, modulus);
|
---|
| 4567 | }
|
---|
| 4568 | }
|
---|
| 4569 |
|
---|
| 4570 | #ifndef HAVE_THREAD_LS
|
---|
| 4571 | UnLockMutex(&ecc_fp_lock);
|
---|
| 4572 | #endif /* HAVE_THREAD_LS */
|
---|
| 4573 | mp_clear(&mu);
|
---|
| 4574 |
|
---|
| 4575 | return err;
|
---|
| 4576 | }
|
---|
| 4577 | #endif /* ECC_SHAMIR */
|
---|
| 4578 |
|
---|
| 4579 | /** ECC Fixed Point mulmod global
|
---|
| 4580 | k The multiplicand
|
---|
| 4581 | G Base point to multiply
|
---|
| 4582 | R [out] Destination of product
|
---|
| 4583 | modulus The modulus for the curve
|
---|
| 4584 | map [boolean] If non-zero maps the point back to affine co-ordinates,
|
---|
| 4585 | otherwise it's left in jacobian-montgomery form
|
---|
| 4586 | return MP_OKAY if successful
|
---|
| 4587 | */
|
---|
| 4588 | int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
|
---|
| 4589 | int map)
|
---|
| 4590 | {
|
---|
| 4591 | int idx, err = MP_OKAY;
|
---|
| 4592 | mp_digit mp;
|
---|
| 4593 | mp_int mu;
|
---|
| 4594 | int mpSetup = 0;
|
---|
| 4595 |
|
---|
| 4596 | if (mp_init(&mu) != MP_OKAY)
|
---|
| 4597 | return MP_INIT_E;
|
---|
| 4598 |
|
---|
| 4599 | #ifndef HAVE_THREAD_LS
|
---|
| 4600 | if (initMutex == 0) {
|
---|
| 4601 | InitMutex(&ecc_fp_lock);
|
---|
| 4602 | initMutex = 1;
|
---|
| 4603 | }
|
---|
| 4604 |
|
---|
| 4605 | if (LockMutex(&ecc_fp_lock) != 0)
|
---|
| 4606 | return BAD_MUTEX_E;
|
---|
| 4607 | #endif /* HAVE_THREAD_LS */
|
---|
| 4608 |
|
---|
| 4609 | /* find point */
|
---|
| 4610 | idx = find_base(G);
|
---|
| 4611 |
|
---|
| 4612 | /* no entry? */
|
---|
| 4613 | if (idx == -1) {
|
---|
| 4614 | /* find hole and add it */
|
---|
| 4615 | idx = find_hole();
|
---|
| 4616 |
|
---|
| 4617 | if (idx >= 0)
|
---|
| 4618 | err = add_entry(idx, G);
|
---|
| 4619 | }
|
---|
| 4620 | if (err == MP_OKAY && idx >= 0) {
|
---|
| 4621 | /* increment LRU */
|
---|
| 4622 | ++(fp_cache[idx].lru_count);
|
---|
| 4623 | }
|
---|
| 4624 |
|
---|
| 4625 |
|
---|
| 4626 | if (err == MP_OKAY) {
|
---|
| 4627 | /* if it's 2 build the LUT, if it's higher just use the LUT */
|
---|
| 4628 | if (idx >= 0 && fp_cache[idx].lru_count == 2) {
|
---|
| 4629 | /* compute mp */
|
---|
| 4630 | err = mp_montgomery_setup(modulus, &mp);
|
---|
| 4631 |
|
---|
| 4632 | if (err == MP_OKAY) {
|
---|
| 4633 | /* compute mu */
|
---|
| 4634 | mpSetup = 1;
|
---|
| 4635 | err = mp_montgomery_calc_normalization(&mu, modulus);
|
---|
| 4636 | }
|
---|
| 4637 |
|
---|
| 4638 | if (err == MP_OKAY)
|
---|
| 4639 | /* build the LUT */
|
---|
| 4640 | err = build_lut(idx, modulus, &mp, &mu);
|
---|
| 4641 | }
|
---|
| 4642 | }
|
---|
| 4643 |
|
---|
| 4644 | if (err == MP_OKAY) {
|
---|
| 4645 | if (idx >= 0 && fp_cache[idx].lru_count >= 2) {
|
---|
| 4646 | if (mpSetup == 0) {
|
---|
| 4647 | /* compute mp */
|
---|
| 4648 | err = mp_montgomery_setup(modulus, &mp);
|
---|
| 4649 | }
|
---|
| 4650 | if (err == MP_OKAY)
|
---|
| 4651 | err = accel_fp_mul(idx, k, R, modulus, &mp, map);
|
---|
| 4652 | } else {
|
---|
| 4653 | err = normal_ecc_mulmod(k, G, R, modulus, map);
|
---|
| 4654 | }
|
---|
| 4655 | }
|
---|
| 4656 |
|
---|
| 4657 | #ifndef HAVE_THREAD_LS
|
---|
| 4658 | UnLockMutex(&ecc_fp_lock);
|
---|
| 4659 | #endif /* HAVE_THREAD_LS */
|
---|
| 4660 | mp_clear(&mu);
|
---|
| 4661 |
|
---|
| 4662 | return err;
|
---|
| 4663 | }
|
---|
| 4664 |
|
---|
| 4665 | /* helper function for freeing the cache ...
|
---|
| 4666 | must be called with the cache mutex locked */
|
---|
| 4667 | static void wc_ecc_fp_free_cache(void)
|
---|
| 4668 | {
|
---|
| 4669 | unsigned x, y;
|
---|
| 4670 | for (x = 0; x < FP_ENTRIES; x++) {
|
---|
| 4671 | if (fp_cache[x].g != NULL) {
|
---|
| 4672 | for (y = 0; y < (1U<<FP_LUT); y++) {
|
---|
| 4673 | wc_ecc_del_point(fp_cache[x].LUT[y]);
|
---|
| 4674 | fp_cache[x].LUT[y] = NULL;
|
---|
| 4675 | }
|
---|
| 4676 | wc_ecc_del_point(fp_cache[x].g);
|
---|
| 4677 | fp_cache[x].g = NULL;
|
---|
| 4678 | mp_clear(&fp_cache[x].mu);
|
---|
| 4679 | fp_cache[x].lru_count = 0;
|
---|
| 4680 | fp_cache[x].lock = 0;
|
---|
| 4681 | }
|
---|
| 4682 | }
|
---|
| 4683 | }
|
---|
| 4684 |
|
---|
| 4685 | /** Free the Fixed Point cache */
|
---|
| 4686 | void wc_ecc_fp_free(void)
|
---|
| 4687 | {
|
---|
| 4688 | #ifndef HAVE_THREAD_LS
|
---|
| 4689 | if (initMutex == 0) {
|
---|
| 4690 | InitMutex(&ecc_fp_lock);
|
---|
| 4691 | initMutex = 1;
|
---|
| 4692 | }
|
---|
| 4693 |
|
---|
| 4694 | if (LockMutex(&ecc_fp_lock) == 0) {
|
---|
| 4695 | #endif /* HAVE_THREAD_LS */
|
---|
| 4696 |
|
---|
| 4697 | wc_ecc_fp_free_cache();
|
---|
| 4698 |
|
---|
| 4699 | #ifndef HAVE_THREAD_LS
|
---|
| 4700 | UnLockMutex(&ecc_fp_lock);
|
---|
| 4701 | FreeMutex(&ecc_fp_lock);
|
---|
| 4702 | initMutex = 0;
|
---|
| 4703 | }
|
---|
| 4704 | #endif /* HAVE_THREAD_LS */
|
---|
| 4705 | }
|
---|
| 4706 |
|
---|
| 4707 |
|
---|
| 4708 | #endif /* FP_ECC */
|
---|
| 4709 |
|
---|
| 4710 | #ifdef HAVE_ECC_ENCRYPT
|
---|
| 4711 |
|
---|
| 4712 |
|
---|
| 4713 | enum ecCliState {
|
---|
| 4714 | ecCLI_INIT = 1,
|
---|
| 4715 | ecCLI_SALT_GET = 2,
|
---|
| 4716 | ecCLI_SALT_SET = 3,
|
---|
| 4717 | ecCLI_SENT_REQ = 4,
|
---|
| 4718 | ecCLI_RECV_RESP = 5,
|
---|
| 4719 | ecCLI_BAD_STATE = 99
|
---|
| 4720 | };
|
---|
| 4721 |
|
---|
| 4722 | enum ecSrvState {
|
---|
| 4723 | ecSRV_INIT = 1,
|
---|
| 4724 | ecSRV_SALT_GET = 2,
|
---|
| 4725 | ecSRV_SALT_SET = 3,
|
---|
| 4726 | ecSRV_RECV_REQ = 4,
|
---|
| 4727 | ecSRV_SENT_RESP = 5,
|
---|
| 4728 | ecSRV_BAD_STATE = 99
|
---|
| 4729 | };
|
---|
| 4730 |
|
---|
| 4731 |
|
---|
| 4732 | struct ecEncCtx {
|
---|
| 4733 | const byte* kdfSalt; /* optional salt for kdf */
|
---|
| 4734 | const byte* kdfInfo; /* optional info for kdf */
|
---|
| 4735 | const byte* macSalt; /* optional salt for mac */
|
---|
| 4736 | word32 kdfSaltSz; /* size of kdfSalt */
|
---|
| 4737 | word32 kdfInfoSz; /* size of kdfInfo */
|
---|
| 4738 | word32 macSaltSz; /* size of macSalt */
|
---|
| 4739 | byte clientSalt[EXCHANGE_SALT_SZ]; /* for msg exchange */
|
---|
| 4740 | byte serverSalt[EXCHANGE_SALT_SZ]; /* for msg exchange */
|
---|
| 4741 | byte encAlgo; /* which encryption type */
|
---|
| 4742 | byte kdfAlgo; /* which key derivation function type */
|
---|
| 4743 | byte macAlgo; /* which mac function type */
|
---|
| 4744 | byte protocol; /* are we REQ_RESP client or server ? */
|
---|
| 4745 | byte cliSt; /* protocol state, for sanity checks */
|
---|
| 4746 | byte srvSt; /* protocol state, for sanity checks */
|
---|
| 4747 | };
|
---|
| 4748 |
|
---|
| 4749 |
|
---|
| 4750 | const byte* wc_ecc_ctx_get_own_salt(ecEncCtx* ctx)
|
---|
| 4751 | {
|
---|
| 4752 | if (ctx == NULL || ctx->protocol == 0)
|
---|
| 4753 | return NULL;
|
---|
| 4754 |
|
---|
| 4755 | if (ctx->protocol == REQ_RESP_CLIENT) {
|
---|
| 4756 | if (ctx->cliSt == ecCLI_INIT) {
|
---|
| 4757 | ctx->cliSt = ecCLI_SALT_GET;
|
---|
| 4758 | return ctx->clientSalt;
|
---|
| 4759 | }
|
---|
| 4760 | else {
|
---|
| 4761 | ctx->cliSt = ecCLI_BAD_STATE;
|
---|
| 4762 | return NULL;
|
---|
| 4763 | }
|
---|
| 4764 | }
|
---|
| 4765 | else if (ctx->protocol == REQ_RESP_SERVER) {
|
---|
| 4766 | if (ctx->srvSt == ecSRV_INIT) {
|
---|
| 4767 | ctx->srvSt = ecSRV_SALT_GET;
|
---|
| 4768 | return ctx->serverSalt;
|
---|
| 4769 | }
|
---|
| 4770 | else {
|
---|
| 4771 | ctx->srvSt = ecSRV_BAD_STATE;
|
---|
| 4772 | return NULL;
|
---|
| 4773 | }
|
---|
| 4774 | }
|
---|
| 4775 |
|
---|
| 4776 | return NULL;
|
---|
| 4777 | }
|
---|
| 4778 |
|
---|
| 4779 |
|
---|
| 4780 | /* optional set info, can be called before or after set_peer_salt */
|
---|
| 4781 | int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz)
|
---|
| 4782 | {
|
---|
| 4783 | if (ctx == NULL || info == 0 || sz < 0)
|
---|
| 4784 | return BAD_FUNC_ARG;
|
---|
| 4785 |
|
---|
| 4786 | ctx->kdfInfo = info;
|
---|
| 4787 | ctx->kdfInfoSz = sz;
|
---|
| 4788 |
|
---|
| 4789 | return 0;
|
---|
| 4790 | }
|
---|
| 4791 |
|
---|
| 4792 |
|
---|
| 4793 | static const char* exchange_info = "Secure Message Exchange";
|
---|
| 4794 |
|
---|
| 4795 | int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt)
|
---|
| 4796 | {
|
---|
| 4797 | byte tmp[EXCHANGE_SALT_SZ/2];
|
---|
| 4798 | int halfSz = EXCHANGE_SALT_SZ/2;
|
---|
| 4799 |
|
---|
| 4800 | if (ctx == NULL || ctx->protocol == 0 || salt == NULL)
|
---|
| 4801 | return BAD_FUNC_ARG;
|
---|
| 4802 |
|
---|
| 4803 | if (ctx->protocol == REQ_RESP_CLIENT) {
|
---|
| 4804 | XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ);
|
---|
| 4805 | if (ctx->cliSt == ecCLI_SALT_GET)
|
---|
| 4806 | ctx->cliSt = ecCLI_SALT_SET;
|
---|
| 4807 | else {
|
---|
| 4808 | ctx->cliSt = ecCLI_BAD_STATE;
|
---|
| 4809 | return BAD_ENC_STATE_E;
|
---|
| 4810 | }
|
---|
| 4811 | }
|
---|
| 4812 | else {
|
---|
| 4813 | XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ);
|
---|
| 4814 | if (ctx->srvSt == ecSRV_SALT_GET)
|
---|
| 4815 | ctx->srvSt = ecSRV_SALT_SET;
|
---|
| 4816 | else {
|
---|
| 4817 | ctx->srvSt = ecSRV_BAD_STATE;
|
---|
| 4818 | return BAD_ENC_STATE_E;
|
---|
| 4819 | }
|
---|
| 4820 | }
|
---|
| 4821 |
|
---|
| 4822 | /* mix half and half */
|
---|
| 4823 | /* tmp stores 2nd half of client before overwrite */
|
---|
| 4824 | XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz);
|
---|
| 4825 | XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz);
|
---|
| 4826 | XMEMCPY(ctx->serverSalt, tmp, halfSz);
|
---|
| 4827 |
|
---|
| 4828 | ctx->kdfSalt = ctx->clientSalt;
|
---|
| 4829 | ctx->kdfSaltSz = EXCHANGE_SALT_SZ;
|
---|
| 4830 |
|
---|
| 4831 | ctx->macSalt = ctx->serverSalt;
|
---|
| 4832 | ctx->macSaltSz = EXCHANGE_SALT_SZ;
|
---|
| 4833 |
|
---|
| 4834 | if (ctx->kdfInfo == NULL) {
|
---|
| 4835 | /* default info */
|
---|
| 4836 | ctx->kdfInfo = (const byte*)exchange_info;
|
---|
| 4837 | ctx->kdfInfoSz = EXCHANGE_INFO_SZ;
|
---|
| 4838 | }
|
---|
| 4839 |
|
---|
| 4840 | return 0;
|
---|
| 4841 | }
|
---|
| 4842 |
|
---|
| 4843 |
|
---|
| 4844 | static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, WC_RNG* rng)
|
---|
| 4845 | {
|
---|
| 4846 | byte* saltBuffer = NULL;
|
---|
| 4847 |
|
---|
| 4848 | if (ctx == NULL || rng == NULL || flags == 0)
|
---|
| 4849 | return BAD_FUNC_ARG;
|
---|
| 4850 |
|
---|
| 4851 | saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt;
|
---|
| 4852 |
|
---|
| 4853 | return wc_RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ);
|
---|
| 4854 | }
|
---|
| 4855 |
|
---|
| 4856 |
|
---|
| 4857 | static void ecc_ctx_init(ecEncCtx* ctx, int flags)
|
---|
| 4858 | {
|
---|
| 4859 | if (ctx) {
|
---|
| 4860 | XMEMSET(ctx, 0, sizeof(ecEncCtx));
|
---|
| 4861 |
|
---|
| 4862 | ctx->encAlgo = ecAES_128_CBC;
|
---|
| 4863 | ctx->kdfAlgo = ecHKDF_SHA256;
|
---|
| 4864 | ctx->macAlgo = ecHMAC_SHA256;
|
---|
| 4865 | ctx->protocol = (byte)flags;
|
---|
| 4866 |
|
---|
| 4867 | if (flags == REQ_RESP_CLIENT)
|
---|
| 4868 | ctx->cliSt = ecCLI_INIT;
|
---|
| 4869 | if (flags == REQ_RESP_SERVER)
|
---|
| 4870 | ctx->srvSt = ecSRV_INIT;
|
---|
| 4871 | }
|
---|
| 4872 | }
|
---|
| 4873 |
|
---|
| 4874 |
|
---|
| 4875 | /* allow ecc context reset so user doesn't have to init/free for resue */
|
---|
| 4876 | int wc_ecc_ctx_reset(ecEncCtx* ctx, WC_RNG* rng)
|
---|
| 4877 | {
|
---|
| 4878 | if (ctx == NULL || rng == NULL)
|
---|
| 4879 | return BAD_FUNC_ARG;
|
---|
| 4880 |
|
---|
| 4881 | ecc_ctx_init(ctx, ctx->protocol);
|
---|
| 4882 | return ecc_ctx_set_salt(ctx, ctx->protocol, rng);
|
---|
| 4883 | }
|
---|
| 4884 |
|
---|
| 4885 |
|
---|
| 4886 | /* alloc/init and set defaults, return new Context */
|
---|
| 4887 | ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng)
|
---|
| 4888 | {
|
---|
| 4889 | int ret = 0;
|
---|
| 4890 | ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), 0, DYNAMIC_TYPE_ECC);
|
---|
| 4891 |
|
---|
| 4892 | if (ctx)
|
---|
| 4893 | ctx->protocol = (byte)flags;
|
---|
| 4894 |
|
---|
| 4895 | ret = wc_ecc_ctx_reset(ctx, rng);
|
---|
| 4896 | if (ret != 0) {
|
---|
| 4897 | wc_ecc_ctx_free(ctx);
|
---|
| 4898 | ctx = NULL;
|
---|
| 4899 | }
|
---|
| 4900 |
|
---|
| 4901 | return ctx;
|
---|
| 4902 | }
|
---|
| 4903 |
|
---|
| 4904 |
|
---|
| 4905 | /* free any resources, clear any keys */
|
---|
| 4906 | void wc_ecc_ctx_free(ecEncCtx* ctx)
|
---|
| 4907 | {
|
---|
| 4908 | if (ctx) {
|
---|
| 4909 | ForceZero(ctx, sizeof(ecEncCtx));
|
---|
| 4910 | XFREE(ctx, 0, DYNAMIC_TYPE_ECC);
|
---|
| 4911 | }
|
---|
| 4912 | }
|
---|
| 4913 |
|
---|
| 4914 |
|
---|
| 4915 | static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
|
---|
| 4916 | int* keysLen, word32* digestSz, word32* blockSz)
|
---|
| 4917 | {
|
---|
| 4918 | if (ctx) {
|
---|
| 4919 | switch (ctx->encAlgo) {
|
---|
| 4920 | case ecAES_128_CBC:
|
---|
| 4921 | *encKeySz = KEY_SIZE_128;
|
---|
| 4922 | *ivSz = IV_SIZE_128;
|
---|
| 4923 | *blockSz = AES_BLOCK_SIZE;
|
---|
| 4924 | break;
|
---|
| 4925 | default:
|
---|
| 4926 | return BAD_FUNC_ARG;
|
---|
| 4927 | }
|
---|
| 4928 |
|
---|
| 4929 | switch (ctx->macAlgo) {
|
---|
| 4930 | case ecHMAC_SHA256:
|
---|
| 4931 | *digestSz = SHA256_DIGEST_SIZE;
|
---|
| 4932 | break;
|
---|
| 4933 | default:
|
---|
| 4934 | return BAD_FUNC_ARG;
|
---|
| 4935 | }
|
---|
| 4936 | } else
|
---|
| 4937 | return BAD_FUNC_ARG;
|
---|
| 4938 |
|
---|
| 4939 | *keysLen = *encKeySz + *ivSz + *digestSz;
|
---|
| 4940 |
|
---|
| 4941 | return 0;
|
---|
| 4942 | }
|
---|
| 4943 |
|
---|
| 4944 |
|
---|
| 4945 | /* ecc encrypt with shared secret run through kdf
|
---|
| 4946 | ctx holds non default algos and inputs
|
---|
| 4947 | msgSz should be the right size for encAlgo, i.e., already padded
|
---|
| 4948 | return 0 on success */
|
---|
| 4949 | int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
---|
| 4950 | word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
|
---|
| 4951 | {
|
---|
| 4952 | int ret;
|
---|
| 4953 | word32 blockSz;
|
---|
| 4954 | word32 digestSz;
|
---|
| 4955 | ecEncCtx localCtx;
|
---|
| 4956 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 4957 | byte* sharedSecret;
|
---|
| 4958 | byte* keys;
|
---|
| 4959 | #else
|
---|
| 4960 | byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
---|
| 4961 | byte keys[ECC_BUFSIZE]; /* max size */
|
---|
| 4962 | #endif
|
---|
| 4963 | word32 sharedSz = ECC_MAXSIZE;
|
---|
| 4964 | int keysLen;
|
---|
| 4965 | int encKeySz;
|
---|
| 4966 | int ivSz;
|
---|
| 4967 | int offset = 0; /* keys offset if doing msg exchange */
|
---|
| 4968 | byte* encKey;
|
---|
| 4969 | byte* encIv;
|
---|
| 4970 | byte* macKey;
|
---|
| 4971 |
|
---|
| 4972 | if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
|
---|
| 4973 | outSz == NULL)
|
---|
| 4974 | return BAD_FUNC_ARG;
|
---|
| 4975 |
|
---|
| 4976 | if (ctx == NULL) { /* use defaults */
|
---|
| 4977 | ecc_ctx_init(&localCtx, 0);
|
---|
| 4978 | ctx = &localCtx;
|
---|
| 4979 | }
|
---|
| 4980 |
|
---|
| 4981 | ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
|
---|
| 4982 | &blockSz);
|
---|
| 4983 | if (ret != 0)
|
---|
| 4984 | return ret;
|
---|
| 4985 |
|
---|
| 4986 | if (ctx->protocol == REQ_RESP_SERVER) {
|
---|
| 4987 | offset = keysLen;
|
---|
| 4988 | keysLen *= 2;
|
---|
| 4989 |
|
---|
| 4990 | if (ctx->srvSt != ecSRV_RECV_REQ)
|
---|
| 4991 | return BAD_ENC_STATE_E;
|
---|
| 4992 |
|
---|
| 4993 | ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
|
---|
| 4994 | }
|
---|
| 4995 | else if (ctx->protocol == REQ_RESP_CLIENT) {
|
---|
| 4996 | if (ctx->cliSt != ecCLI_SALT_SET)
|
---|
| 4997 | return BAD_ENC_STATE_E;
|
---|
| 4998 |
|
---|
| 4999 | ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
|
---|
| 5000 | }
|
---|
| 5001 |
|
---|
| 5002 | if (keysLen > ECC_BUFSIZE) /* keys size */
|
---|
| 5003 | return BUFFER_E;
|
---|
| 5004 |
|
---|
| 5005 | if ( (msgSz%blockSz) != 0)
|
---|
| 5006 | return BAD_PADDING_E;
|
---|
| 5007 |
|
---|
| 5008 | if (*outSz < (msgSz + digestSz))
|
---|
| 5009 | return BUFFER_E;
|
---|
| 5010 |
|
---|
| 5011 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 5012 | sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5013 | if (sharedSecret == NULL)
|
---|
| 5014 | return MEMORY_E;
|
---|
| 5015 |
|
---|
| 5016 | keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5017 | if (keys == NULL) {
|
---|
| 5018 | XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5019 | return MEMORY_E;
|
---|
| 5020 | }
|
---|
| 5021 | #endif
|
---|
| 5022 |
|
---|
| 5023 | ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
---|
| 5024 |
|
---|
| 5025 | if (ret == 0) {
|
---|
| 5026 | switch (ctx->kdfAlgo) {
|
---|
| 5027 | case ecHKDF_SHA256 :
|
---|
| 5028 | ret = wc_HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
---|
| 5029 | ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
|
---|
| 5030 | keys, keysLen);
|
---|
| 5031 | break;
|
---|
| 5032 |
|
---|
| 5033 | default:
|
---|
| 5034 | ret = BAD_FUNC_ARG;
|
---|
| 5035 | break;
|
---|
| 5036 | }
|
---|
| 5037 | }
|
---|
| 5038 |
|
---|
| 5039 | if (ret == 0) {
|
---|
| 5040 | encKey = keys + offset;
|
---|
| 5041 | encIv = encKey + encKeySz;
|
---|
| 5042 | macKey = encKey + encKeySz + ivSz;
|
---|
| 5043 |
|
---|
| 5044 | switch (ctx->encAlgo) {
|
---|
| 5045 | case ecAES_128_CBC:
|
---|
| 5046 | {
|
---|
| 5047 | Aes aes;
|
---|
| 5048 | ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
|
---|
| 5049 | AES_ENCRYPTION);
|
---|
| 5050 | if (ret != 0)
|
---|
| 5051 | break;
|
---|
| 5052 | ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz);
|
---|
| 5053 | }
|
---|
| 5054 | break;
|
---|
| 5055 |
|
---|
| 5056 | default:
|
---|
| 5057 | ret = BAD_FUNC_ARG;
|
---|
| 5058 | break;
|
---|
| 5059 | }
|
---|
| 5060 | }
|
---|
| 5061 |
|
---|
| 5062 | if (ret == 0) {
|
---|
| 5063 | switch (ctx->macAlgo) {
|
---|
| 5064 | case ecHMAC_SHA256:
|
---|
| 5065 | {
|
---|
| 5066 | Hmac hmac;
|
---|
| 5067 | ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
---|
| 5068 | if (ret != 0)
|
---|
| 5069 | break;
|
---|
| 5070 | ret = wc_HmacUpdate(&hmac, out, msgSz);
|
---|
| 5071 | if (ret != 0)
|
---|
| 5072 | break;
|
---|
| 5073 | ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
---|
| 5074 | if (ret != 0)
|
---|
| 5075 | break;
|
---|
| 5076 | ret = wc_HmacFinal(&hmac, out+msgSz);
|
---|
| 5077 | }
|
---|
| 5078 | break;
|
---|
| 5079 |
|
---|
| 5080 | default:
|
---|
| 5081 | ret = BAD_FUNC_ARG;
|
---|
| 5082 | break;
|
---|
| 5083 | }
|
---|
| 5084 | }
|
---|
| 5085 |
|
---|
| 5086 | if (ret == 0)
|
---|
| 5087 | *outSz = msgSz + digestSz;
|
---|
| 5088 |
|
---|
| 5089 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 5090 | XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5091 | XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5092 | #endif
|
---|
| 5093 |
|
---|
| 5094 | return ret;
|
---|
| 5095 | }
|
---|
| 5096 |
|
---|
| 5097 |
|
---|
| 5098 | /* ecc decrypt with shared secret run through kdf
|
---|
| 5099 | ctx holds non default algos and inputs
|
---|
| 5100 | return 0 on success */
|
---|
| 5101 | int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
---|
| 5102 | word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
|
---|
| 5103 | {
|
---|
| 5104 | int ret;
|
---|
| 5105 | word32 blockSz;
|
---|
| 5106 | word32 digestSz;
|
---|
| 5107 | ecEncCtx localCtx;
|
---|
| 5108 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 5109 | byte* sharedSecret;
|
---|
| 5110 | byte* keys;
|
---|
| 5111 | #else
|
---|
| 5112 | byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */
|
---|
| 5113 | byte keys[ECC_BUFSIZE]; /* max size */
|
---|
| 5114 | #endif
|
---|
| 5115 | word32 sharedSz = ECC_MAXSIZE;
|
---|
| 5116 | int keysLen;
|
---|
| 5117 | int encKeySz;
|
---|
| 5118 | int ivSz;
|
---|
| 5119 | int offset = 0; /* in case using msg exchange */
|
---|
| 5120 | byte* encKey;
|
---|
| 5121 | byte* encIv;
|
---|
| 5122 | byte* macKey;
|
---|
| 5123 |
|
---|
| 5124 | if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
|
---|
| 5125 | outSz == NULL)
|
---|
| 5126 | return BAD_FUNC_ARG;
|
---|
| 5127 |
|
---|
| 5128 | if (ctx == NULL) { /* use defaults */
|
---|
| 5129 | ecc_ctx_init(&localCtx, 0);
|
---|
| 5130 | ctx = &localCtx;
|
---|
| 5131 | }
|
---|
| 5132 |
|
---|
| 5133 | ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
|
---|
| 5134 | &blockSz);
|
---|
| 5135 | if (ret != 0)
|
---|
| 5136 | return ret;
|
---|
| 5137 |
|
---|
| 5138 | if (ctx->protocol == REQ_RESP_CLIENT) {
|
---|
| 5139 | offset = keysLen;
|
---|
| 5140 | keysLen *= 2;
|
---|
| 5141 |
|
---|
| 5142 | if (ctx->cliSt != ecCLI_SENT_REQ)
|
---|
| 5143 | return BAD_ENC_STATE_E;
|
---|
| 5144 |
|
---|
| 5145 | ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
|
---|
| 5146 | }
|
---|
| 5147 | else if (ctx->protocol == REQ_RESP_SERVER) {
|
---|
| 5148 | if (ctx->srvSt != ecSRV_SALT_SET)
|
---|
| 5149 | return BAD_ENC_STATE_E;
|
---|
| 5150 |
|
---|
| 5151 | ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
|
---|
| 5152 | }
|
---|
| 5153 |
|
---|
| 5154 | if (keysLen > ECC_BUFSIZE) /* keys size */
|
---|
| 5155 | return BUFFER_E;
|
---|
| 5156 |
|
---|
| 5157 | if ( ((msgSz-digestSz) % blockSz) != 0)
|
---|
| 5158 | return BAD_PADDING_E;
|
---|
| 5159 |
|
---|
| 5160 | if (*outSz < (msgSz - digestSz))
|
---|
| 5161 | return BUFFER_E;
|
---|
| 5162 |
|
---|
| 5163 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 5164 | sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5165 | if (sharedSecret == NULL)
|
---|
| 5166 | return MEMORY_E;
|
---|
| 5167 |
|
---|
| 5168 | keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5169 | if (keys == NULL) {
|
---|
| 5170 | XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5171 | return MEMORY_E;
|
---|
| 5172 | }
|
---|
| 5173 | #endif
|
---|
| 5174 |
|
---|
| 5175 | ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
|
---|
| 5176 |
|
---|
| 5177 | if (ret == 0) {
|
---|
| 5178 | switch (ctx->kdfAlgo) {
|
---|
| 5179 | case ecHKDF_SHA256 :
|
---|
| 5180 | ret = wc_HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
|
---|
| 5181 | ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
|
---|
| 5182 | keys, keysLen);
|
---|
| 5183 | break;
|
---|
| 5184 |
|
---|
| 5185 | default:
|
---|
| 5186 | ret = BAD_FUNC_ARG;
|
---|
| 5187 | break;
|
---|
| 5188 | }
|
---|
| 5189 | }
|
---|
| 5190 |
|
---|
| 5191 | if (ret == 0) {
|
---|
| 5192 | encKey = keys + offset;
|
---|
| 5193 | encIv = encKey + encKeySz;
|
---|
| 5194 | macKey = encKey + encKeySz + ivSz;
|
---|
| 5195 |
|
---|
| 5196 | switch (ctx->macAlgo) {
|
---|
| 5197 | case ecHMAC_SHA256:
|
---|
| 5198 | {
|
---|
| 5199 | byte verify[SHA256_DIGEST_SIZE];
|
---|
| 5200 | Hmac hmac;
|
---|
| 5201 | ret = wc_HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
|
---|
| 5202 | if (ret != 0)
|
---|
| 5203 | break;
|
---|
| 5204 | ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz);
|
---|
| 5205 | if (ret != 0)
|
---|
| 5206 | break;
|
---|
| 5207 | ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
|
---|
| 5208 | if (ret != 0)
|
---|
| 5209 | break;
|
---|
| 5210 | ret = wc_HmacFinal(&hmac, verify);
|
---|
| 5211 | if (ret != 0)
|
---|
| 5212 | break;
|
---|
| 5213 | if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0)
|
---|
| 5214 | ret = -1;
|
---|
| 5215 | }
|
---|
| 5216 | break;
|
---|
| 5217 |
|
---|
| 5218 | default:
|
---|
| 5219 | ret = BAD_FUNC_ARG;
|
---|
| 5220 | break;
|
---|
| 5221 | }
|
---|
| 5222 | }
|
---|
| 5223 |
|
---|
| 5224 | if (ret == 0) {
|
---|
| 5225 | switch (ctx->encAlgo) {
|
---|
| 5226 | case ecAES_128_CBC:
|
---|
| 5227 | {
|
---|
| 5228 | Aes aes;
|
---|
| 5229 | ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
|
---|
| 5230 | AES_DECRYPTION);
|
---|
| 5231 | if (ret != 0)
|
---|
| 5232 | break;
|
---|
| 5233 | ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
|
---|
| 5234 | }
|
---|
| 5235 | break;
|
---|
| 5236 |
|
---|
| 5237 | default:
|
---|
| 5238 | ret = BAD_FUNC_ARG;
|
---|
| 5239 | break;
|
---|
| 5240 | }
|
---|
| 5241 | }
|
---|
| 5242 |
|
---|
| 5243 | if (ret == 0)
|
---|
| 5244 | *outSz = msgSz - digestSz;
|
---|
| 5245 |
|
---|
| 5246 | #ifdef WOLFSSL_SMALL_STACK
|
---|
| 5247 | XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5248 | XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
---|
| 5249 | #endif
|
---|
| 5250 |
|
---|
| 5251 | return ret;
|
---|
| 5252 | }
|
---|
| 5253 |
|
---|
| 5254 |
|
---|
| 5255 | #endif /* HAVE_ECC_ENCRYPT */
|
---|
| 5256 |
|
---|
| 5257 |
|
---|
| 5258 | #ifdef HAVE_COMP_KEY
|
---|
| 5259 |
|
---|
| 5260 | /* computes the jacobi c = (a | n) (or Legendre if n is prime)
|
---|
| 5261 | * HAC pp. 73 Algorithm 2.149
|
---|
| 5262 | */
|
---|
| 5263 | int mp_jacobi(mp_int* a, mp_int* p, int* c)
|
---|
| 5264 | {
|
---|
| 5265 | mp_int a1, p1;
|
---|
| 5266 | int k, s, r, res;
|
---|
| 5267 | mp_digit residue;
|
---|
| 5268 |
|
---|
| 5269 | /* if p <= 0 return MP_VAL */
|
---|
| 5270 | if (mp_cmp_d(p, 0) != MP_GT) {
|
---|
| 5271 | return MP_VAL;
|
---|
| 5272 | }
|
---|
| 5273 |
|
---|
| 5274 | /* step 1. if a == 0, return 0 */
|
---|
| 5275 | if (mp_iszero (a) == 1) {
|
---|
| 5276 | *c = 0;
|
---|
| 5277 | return MP_OKAY;
|
---|
| 5278 | }
|
---|
| 5279 |
|
---|
| 5280 | /* step 2. if a == 1, return 1 */
|
---|
| 5281 | if (mp_cmp_d (a, 1) == MP_EQ) {
|
---|
| 5282 | *c = 1;
|
---|
| 5283 | return MP_OKAY;
|
---|
| 5284 | }
|
---|
| 5285 |
|
---|
| 5286 | /* default */
|
---|
| 5287 | s = 0;
|
---|
| 5288 |
|
---|
| 5289 | /* step 3. write a = a1 * 2**k */
|
---|
| 5290 | if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
|
---|
| 5291 | return res;
|
---|
| 5292 | }
|
---|
| 5293 |
|
---|
| 5294 | if ((res = mp_init (&p1)) != MP_OKAY) {
|
---|
| 5295 | mp_clear(&a1);
|
---|
| 5296 | return res;
|
---|
| 5297 | }
|
---|
| 5298 |
|
---|
| 5299 | /* divide out larger power of two */
|
---|
| 5300 | k = mp_cnt_lsb(&a1);
|
---|
| 5301 | res = mp_div_2d(&a1, k, &a1, NULL);
|
---|
| 5302 |
|
---|
| 5303 | if (res == MP_OKAY) {
|
---|
| 5304 | /* step 4. if e is even set s=1 */
|
---|
| 5305 | if ((k & 1) == 0) {
|
---|
| 5306 | s = 1;
|
---|
| 5307 | } else {
|
---|
| 5308 | /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
|
---|
| 5309 | residue = p->dp[0] & 7;
|
---|
| 5310 |
|
---|
| 5311 | if (residue == 1 || residue == 7) {
|
---|
| 5312 | s = 1;
|
---|
| 5313 | } else if (residue == 3 || residue == 5) {
|
---|
| 5314 | s = -1;
|
---|
| 5315 | }
|
---|
| 5316 | }
|
---|
| 5317 |
|
---|
| 5318 | /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
|
---|
| 5319 | if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
|
---|
| 5320 | s = -s;
|
---|
| 5321 | }
|
---|
| 5322 | }
|
---|
| 5323 |
|
---|
| 5324 | if (res == MP_OKAY) {
|
---|
| 5325 | /* if a1 == 1 we're done */
|
---|
| 5326 | if (mp_cmp_d (&a1, 1) == MP_EQ) {
|
---|
| 5327 | *c = s;
|
---|
| 5328 | } else {
|
---|
| 5329 | /* n1 = n mod a1 */
|
---|
| 5330 | res = mp_mod (p, &a1, &p1);
|
---|
| 5331 | if (res == MP_OKAY)
|
---|
| 5332 | res = mp_jacobi (&p1, &a1, &r);
|
---|
| 5333 |
|
---|
| 5334 | if (res == MP_OKAY)
|
---|
| 5335 | *c = s * r;
|
---|
| 5336 | }
|
---|
| 5337 | }
|
---|
| 5338 |
|
---|
| 5339 | /* done */
|
---|
| 5340 | mp_clear (&p1);
|
---|
| 5341 | mp_clear (&a1);
|
---|
| 5342 |
|
---|
| 5343 | return res;
|
---|
| 5344 | }
|
---|
| 5345 |
|
---|
| 5346 |
|
---|
| 5347 | int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
|
---|
| 5348 | {
|
---|
| 5349 | int res, legendre, done = 0;
|
---|
| 5350 | mp_int t1, C, Q, S, Z, M, T, R, two;
|
---|
| 5351 | mp_digit i;
|
---|
| 5352 |
|
---|
| 5353 | /* first handle the simple cases */
|
---|
| 5354 | if (mp_cmp_d(n, 0) == MP_EQ) {
|
---|
| 5355 | mp_zero(ret);
|
---|
| 5356 | return MP_OKAY;
|
---|
| 5357 | }
|
---|
| 5358 | if (mp_cmp_d(prime, 2) == MP_EQ) return MP_VAL; /* prime must be odd */
|
---|
| 5359 | /* TAO removed
|
---|
| 5360 | if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) return res;
|
---|
| 5361 | if (legendre == -1) return MP_VAL; */ /* quadratic non-residue mod prime */
|
---|
| 5362 |
|
---|
| 5363 | if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY)
|
---|
| 5364 | return res;
|
---|
| 5365 |
|
---|
| 5366 | if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL))
|
---|
| 5367 | != MP_OKAY) {
|
---|
| 5368 | mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z);
|
---|
| 5369 | mp_clear(&M);
|
---|
| 5370 | return res;
|
---|
| 5371 | }
|
---|
| 5372 |
|
---|
| 5373 | /* SPECIAL CASE: if prime mod 4 == 3
|
---|
| 5374 | * compute directly: res = n^(prime+1)/4 mod prime
|
---|
| 5375 | * Handbook of Applied Cryptography algorithm 3.36
|
---|
| 5376 | */
|
---|
| 5377 | res = mp_mod_d(prime, 4, &i);
|
---|
| 5378 | if (res == MP_OKAY && i == 3) {
|
---|
| 5379 | res = mp_add_d(prime, 1, &t1);
|
---|
| 5380 |
|
---|
| 5381 | if (res == MP_OKAY)
|
---|
| 5382 | res = mp_div_2(&t1, &t1);
|
---|
| 5383 | if (res == MP_OKAY)
|
---|
| 5384 | res = mp_div_2(&t1, &t1);
|
---|
| 5385 | if (res == MP_OKAY)
|
---|
| 5386 | res = mp_exptmod(n, &t1, prime, ret);
|
---|
| 5387 |
|
---|
| 5388 | done = 1;
|
---|
| 5389 | }
|
---|
| 5390 |
|
---|
| 5391 | /* NOW: TonelliShanks algorithm */
|
---|
| 5392 |
|
---|
| 5393 | if (res == MP_OKAY && done == 0) {
|
---|
| 5394 |
|
---|
| 5395 | /* factor out powers of 2 from prime-1, defining Q and S
|
---|
| 5396 | * as: prime-1 = Q*2^S */
|
---|
| 5397 | res = mp_copy(prime, &Q);
|
---|
| 5398 | if (res == MP_OKAY)
|
---|
| 5399 | res = mp_sub_d(&Q, 1, &Q);
|
---|
| 5400 | /* Q = prime - 1 */
|
---|
| 5401 | if (res == MP_OKAY)
|
---|
| 5402 | mp_zero(&S);
|
---|
| 5403 | /* S = 0 */
|
---|
| 5404 | while (res == MP_OKAY && mp_iseven(&Q)) {
|
---|
| 5405 | res = mp_div_2(&Q, &Q);
|
---|
| 5406 | /* Q = Q / 2 */
|
---|
| 5407 | if (res == MP_OKAY)
|
---|
| 5408 | res = mp_add_d(&S, 1, &S);
|
---|
| 5409 | /* S = S + 1 */
|
---|
| 5410 | }
|
---|
| 5411 |
|
---|
| 5412 | /* find a Z such that the Legendre symbol (Z|prime) == -1 */
|
---|
| 5413 | if (res == MP_OKAY)
|
---|
| 5414 | res = mp_set_int(&Z, 2);
|
---|
| 5415 | /* Z = 2 */
|
---|
| 5416 | while (res == MP_OKAY) {
|
---|
| 5417 | res = mp_jacobi(&Z, prime, &legendre);
|
---|
| 5418 | if (res == MP_OKAY && legendre == -1)
|
---|
| 5419 | break;
|
---|
| 5420 | if (res == MP_OKAY)
|
---|
| 5421 | res = mp_add_d(&Z, 1, &Z);
|
---|
| 5422 | /* Z = Z + 1 */
|
---|
| 5423 | }
|
---|
| 5424 |
|
---|
| 5425 | if (res == MP_OKAY)
|
---|
| 5426 | res = mp_exptmod(&Z, &Q, prime, &C);
|
---|
| 5427 | /* C = Z ^ Q mod prime */
|
---|
| 5428 | if (res == MP_OKAY)
|
---|
| 5429 | res = mp_add_d(&Q, 1, &t1);
|
---|
| 5430 | if (res == MP_OKAY)
|
---|
| 5431 | res = mp_div_2(&t1, &t1);
|
---|
| 5432 | /* t1 = (Q + 1) / 2 */
|
---|
| 5433 | if (res == MP_OKAY)
|
---|
| 5434 | res = mp_exptmod(n, &t1, prime, &R);
|
---|
| 5435 | /* R = n ^ ((Q + 1) / 2) mod prime */
|
---|
| 5436 | if (res == MP_OKAY)
|
---|
| 5437 | res = mp_exptmod(n, &Q, prime, &T);
|
---|
| 5438 | /* T = n ^ Q mod prime */
|
---|
| 5439 | if (res == MP_OKAY)
|
---|
| 5440 | res = mp_copy(&S, &M);
|
---|
| 5441 | /* M = S */
|
---|
| 5442 | if (res == MP_OKAY)
|
---|
| 5443 | res = mp_set_int(&two, 2);
|
---|
| 5444 |
|
---|
| 5445 | while (res == MP_OKAY && done == 0) {
|
---|
| 5446 | res = mp_copy(&T, &t1);
|
---|
| 5447 | i = 0;
|
---|
| 5448 | while (res == MP_OKAY) {
|
---|
| 5449 | if (mp_cmp_d(&t1, 1) == MP_EQ)
|
---|
| 5450 | break;
|
---|
| 5451 | res = mp_exptmod(&t1, &two, prime, &t1);
|
---|
| 5452 | if (res == MP_OKAY)
|
---|
| 5453 | i++;
|
---|
| 5454 | }
|
---|
| 5455 | if (res == MP_OKAY && i == 0) {
|
---|
| 5456 | mp_copy(&R, ret);
|
---|
| 5457 | res = MP_OKAY;
|
---|
| 5458 | done = 1;
|
---|
| 5459 | }
|
---|
| 5460 |
|
---|
| 5461 | if (done == 0) {
|
---|
| 5462 | if (res == MP_OKAY)
|
---|
| 5463 | res = mp_sub_d(&M, i, &t1);
|
---|
| 5464 | if (res == MP_OKAY)
|
---|
| 5465 | res = mp_sub_d(&t1, 1, &t1);
|
---|
| 5466 | if (res == MP_OKAY)
|
---|
| 5467 | res = mp_exptmod(&two, &t1, prime, &t1);
|
---|
| 5468 | /* t1 = 2 ^ (M - i - 1) */
|
---|
| 5469 | if (res == MP_OKAY)
|
---|
| 5470 | res = mp_exptmod(&C, &t1, prime, &t1);
|
---|
| 5471 | /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
|
---|
| 5472 | if (res == MP_OKAY)
|
---|
| 5473 | res = mp_sqrmod(&t1, prime, &C);
|
---|
| 5474 | /* C = (t1 * t1) mod prime */
|
---|
| 5475 | if (res == MP_OKAY)
|
---|
| 5476 | res = mp_mulmod(&R, &t1, prime, &R);
|
---|
| 5477 | /* R = (R * t1) mod prime */
|
---|
| 5478 | if (res == MP_OKAY)
|
---|
| 5479 | res = mp_mulmod(&T, &C, prime, &T);
|
---|
| 5480 | /* T = (T * C) mod prime */
|
---|
| 5481 | if (res == MP_OKAY)
|
---|
| 5482 | mp_set(&M, i);
|
---|
| 5483 | /* M = i */
|
---|
| 5484 | }
|
---|
| 5485 | }
|
---|
| 5486 | }
|
---|
| 5487 |
|
---|
| 5488 | /* done */
|
---|
| 5489 | mp_clear(&t1);
|
---|
| 5490 | mp_clear(&C);
|
---|
| 5491 | mp_clear(&Q);
|
---|
| 5492 | mp_clear(&S);
|
---|
| 5493 | mp_clear(&Z);
|
---|
| 5494 | mp_clear(&M);
|
---|
| 5495 | mp_clear(&T);
|
---|
| 5496 | mp_clear(&R);
|
---|
| 5497 | mp_clear(&two);
|
---|
| 5498 |
|
---|
| 5499 | return res;
|
---|
| 5500 | }
|
---|
| 5501 |
|
---|
| 5502 |
|
---|
| 5503 | /* export public ECC key in ANSI X9.63 format compressed */
|
---|
| 5504 | int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen)
|
---|
| 5505 | {
|
---|
| 5506 | word32 numlen;
|
---|
| 5507 | int ret = MP_OKAY;
|
---|
| 5508 |
|
---|
| 5509 | if (key == NULL || out == NULL || outLen == NULL)
|
---|
| 5510 | return ECC_BAD_ARG_E;
|
---|
| 5511 |
|
---|
| 5512 | if (wc_ecc_is_valid_idx(key->idx) == 0) {
|
---|
| 5513 | return ECC_BAD_ARG_E;
|
---|
| 5514 | }
|
---|
| 5515 | numlen = key->dp->size;
|
---|
| 5516 |
|
---|
| 5517 | if (*outLen < (1 + numlen)) {
|
---|
| 5518 | *outLen = 1 + numlen;
|
---|
| 5519 | return BUFFER_E;
|
---|
| 5520 | }
|
---|
| 5521 |
|
---|
| 5522 | /* store first byte */
|
---|
| 5523 | out[0] = mp_isodd(key->pubkey.y) ? 0x03 : 0x02;
|
---|
| 5524 |
|
---|
| 5525 | /* pad and store x */
|
---|
| 5526 | XMEMSET(out+1, 0, numlen);
|
---|
| 5527 | ret = mp_to_unsigned_bin(key->pubkey.x,
|
---|
| 5528 | out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x)));
|
---|
| 5529 | *outLen = 1 + numlen;
|
---|
| 5530 | return ret;
|
---|
| 5531 | }
|
---|
| 5532 |
|
---|
| 5533 |
|
---|
| 5534 | /* d = a - b (mod c) */
|
---|
| 5535 | int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
|
---|
| 5536 | {
|
---|
| 5537 | int res;
|
---|
| 5538 | mp_int t;
|
---|
| 5539 |
|
---|
| 5540 | if ((res = mp_init (&t)) != MP_OKAY) {
|
---|
| 5541 | return res;
|
---|
| 5542 | }
|
---|
| 5543 |
|
---|
| 5544 | if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
|
---|
| 5545 | mp_clear (&t);
|
---|
| 5546 | return res;
|
---|
| 5547 | }
|
---|
| 5548 | res = mp_mod (&t, c, d);
|
---|
| 5549 | mp_clear (&t);
|
---|
| 5550 |
|
---|
| 5551 | return res;
|
---|
| 5552 | }
|
---|
| 5553 |
|
---|
| 5554 |
|
---|
| 5555 | #endif /* HAVE_COMP_KEY */
|
---|
| 5556 |
|
---|
| 5557 | #endif /* HAVE_ECC */
|
---|