A library for setting up Secure Socket Layer (SSL) connections and verifying remote hosts using certificates. Contains only the source files for mbed platform implementation of the library.

Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

Committer:
Mike Fiore
Date:
Mon Mar 23 16:51:07 2015 -0500
Revision:
6:cf58d49e1a86
Parent:
0:b86d15c6ba29
fix whitespace in sha512.c

Who changed what in which revision?

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