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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ecc.c Source File

ecc.c

00001 /* ecc.c
00002  *
00003  * Copyright (C) 2006-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 /* in case user set HAVE_ECC there */
00028 #include <cyassl/ctaocrypt/settings.h>
00029 
00030 #ifdef HAVE_ECC
00031 
00032 #include <cyassl/ctaocrypt/ecc.h>
00033 #include <cyassl/ctaocrypt/asn.h>
00034 #include <cyassl/ctaocrypt/error-crypt.h>
00035 
00036 #ifdef HAVE_ECC_ENCRYPT
00037     #include <cyassl/ctaocrypt/hmac.h>
00038     #include <cyassl/ctaocrypt/aes.h>
00039 #endif
00040 
00041 
00042 /* map
00043 
00044    ptmul -> mulmod
00045 
00046 */
00047 
00048 #define ECC112
00049 #define ECC128
00050 #define ECC160
00051 #define ECC192
00052 #define ECC224
00053 #define ECC256
00054 #define ECC384
00055 #define ECC521
00056 
00057 
00058 
00059 /* This holds the key settings.  ***MUST*** be organized by size from
00060    smallest to largest. */
00061 
00062 const ecc_set_type ecc_sets[] = {
00063 #ifdef ECC112
00064 {
00065         14,
00066         "SECP112R1",
00067         "DB7C2ABF62E35E668076BEAD208B",
00068         "DB7C2ABF62E35E668076BEAD2088",
00069         "659EF8BA043916EEDE8911702B22",
00070         "DB7C2ABF62E35E7628DFAC6561C5",
00071         "09487239995A5EE76B55F9C2F098",
00072         "A89CE5AF8724C0A23E0E0FF77500"
00073 },
00074 #endif
00075 #ifdef ECC128
00076 {
00077         16,
00078         "SECP128R1",
00079         "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
00080         "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
00081         "E87579C11079F43DD824993C2CEE5ED3",
00082         "FFFFFFFE0000000075A30D1B9038A115",
00083         "161FF7528B899B2D0C28607CA52C5B86",
00084         "CF5AC8395BAFEB13C02DA292DDED7A83",
00085 },
00086 #endif
00087 #ifdef ECC160
00088 {
00089         20,
00090         "SECP160R1",
00091         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
00092         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
00093         "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
00094         "0100000000000000000001F4C8F927AED3CA752257",
00095         "4A96B5688EF573284664698968C38BB913CBFC82",
00096         "23A628553168947D59DCC912042351377AC5FB32",
00097 },
00098 #endif
00099 #ifdef ECC192
00100 {
00101         24,
00102         "ECC-192",
00103         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
00104         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
00105         "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
00106         "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
00107         "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
00108         "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
00109 },
00110 #endif
00111 #ifdef ECC224
00112 {
00113         28,
00114         "ECC-224",
00115         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
00116         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
00117         "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
00118         "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
00119         "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
00120         "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
00121 },
00122 #endif
00123 #ifdef ECC256
00124 {
00125         32,
00126         "ECC-256",
00127         "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
00128         "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
00129         "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
00130         "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
00131         "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
00132         "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
00133 },
00134 #endif
00135 #ifdef ECC384
00136 {
00137         48,
00138         "ECC-384",
00139         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
00140         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
00141         "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
00142         "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
00143         "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
00144         "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
00145 },
00146 #endif
00147 #ifdef ECC521
00148 {
00149         66,
00150         "ECC-521",
00151         "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
00152         "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
00153         "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
00154         "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
00155         "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
00156         "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
00157 },
00158 #endif
00159 {
00160    0,
00161    NULL, NULL, NULL, NULL, NULL, NULL, NULL
00162 }
00163 };
00164 
00165 
00166 ecc_point* ecc_new_point(void);
00167 void ecc_del_point(ecc_point* p);
00168 int  ecc_map(ecc_point*, mp_int*, mp_digit*);
00169 int  ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
00170                               mp_int* modulus, mp_digit* mp);
00171 int  ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus,
00172                               mp_digit* mp);
00173 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
00174                       int map);
00175 #ifdef ECC_SHAMIR
00176 static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB,
00177                        ecc_point* C, mp_int* modulus);
00178 #endif
00179 
00180 int mp_jacobi(mp_int* a, mp_int* p, int* c);
00181 int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
00182 int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d);
00183 
00184 #ifdef HAVE_COMP_KEY
00185 static int ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
00186 #endif
00187 
00188 /* helper for either lib */
00189 static int get_digit_count(mp_int* a)
00190 {
00191     if (a == NULL)
00192         return 0;
00193 
00194     return a->used;
00195 }
00196 
00197 /* helper for either lib */
00198 static unsigned long get_digit(mp_int* a, int n)
00199 {
00200     if (a == NULL)
00201         return 0;
00202 
00203     return (n >= a->used || n < 0) ? 0 : a->dp[n];
00204 }
00205 
00206 
00207 #if defined(USE_FAST_MATH)
00208 
00209 /* fast math accelerated version, but not for fp ecc yet */
00210 
00211 /**
00212    Add two ECC points
00213    P        The point to add
00214    Q        The point to add
00215    R        [out] The destination of the double
00216    modulus  The modulus of the field the ECC curve is in
00217    mp       The "b" value from montgomery_setup()
00218    return   MP_OKAY on success
00219 */
00220 int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R,
00221                              mp_int* modulus, mp_digit* mp)
00222 {
00223    fp_int t1, t2, x, y, z;
00224    int    err;
00225 
00226    if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
00227        return ECC_BAD_ARG_E;
00228 
00229    if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
00230       return err;
00231    }
00232 
00233    /* should we dbl instead? */
00234    fp_sub(modulus, &Q->y, &t1);
00235    if ( (fp_cmp(&P->x, &Q->x) == FP_EQ) && 
00236         (get_digit_count(&Q->z) && fp_cmp(&P->z, &Q->z) == FP_EQ) &&
00237         (fp_cmp(&P->y, &Q->y) == FP_EQ || fp_cmp(&P->y, &t1) == FP_EQ)) {
00238         return ecc_projective_dbl_point(P, R, modulus, mp);
00239    }
00240 
00241    fp_copy(&P->x, &x);
00242    fp_copy(&P->y, &y);
00243    fp_copy(&P->z, &z);
00244 
00245    /* if Z is one then these are no-operations */
00246    if (get_digit_count(&Q->z)) {
00247       /* T1 = Z' * Z' */
00248       fp_sqr(&Q->z, &t1);
00249       fp_montgomery_reduce(&t1, modulus, *mp);
00250       /* X = X * T1 */
00251       fp_mul(&t1, &x, &x);
00252       fp_montgomery_reduce(&x, modulus, *mp);
00253       /* T1 = Z' * T1 */
00254       fp_mul(&Q->z, &t1, &t1);
00255       fp_montgomery_reduce(&t1, modulus, *mp);
00256       /* Y = Y * T1 */
00257       fp_mul(&t1, &y, &y);
00258       fp_montgomery_reduce(&y, modulus, *mp);
00259    }
00260 
00261    /* T1 = Z*Z */
00262    fp_sqr(&z, &t1);
00263    fp_montgomery_reduce(&t1, modulus, *mp);
00264    /* T2 = X' * T1 */
00265    fp_mul(&Q->x, &t1, &t2);
00266    fp_montgomery_reduce(&t2, modulus, *mp);
00267    /* T1 = Z * T1 */
00268    fp_mul(&z, &t1, &t1);
00269    fp_montgomery_reduce(&t1, modulus, *mp);
00270    /* T1 = Y' * T1 */
00271    fp_mul(&Q->y, &t1, &t1);
00272    fp_montgomery_reduce(&t1, modulus, *mp);
00273 
00274    /* Y = Y - T1 */
00275    fp_sub(&y, &t1, &y);
00276    if (fp_cmp_d(&y, 0) == FP_LT) {
00277       fp_add(&y, modulus, &y);
00278    }
00279    /* T1 = 2T1 */
00280    fp_add(&t1, &t1, &t1);
00281    if (fp_cmp(&t1, modulus) != FP_LT) {
00282       fp_sub(&t1, modulus, &t1);
00283    }
00284    /* T1 = Y + T1 */
00285    fp_add(&t1, &y, &t1);
00286    if (fp_cmp(&t1, modulus) != FP_LT) {
00287       fp_sub(&t1, modulus, &t1);
00288    }
00289    /* X = X - T2 */
00290    fp_sub(&x, &t2, &x);
00291    if (fp_cmp_d(&x, 0) == FP_LT) {
00292       fp_add(&x, modulus, &x);
00293    }
00294    /* T2 = 2T2 */
00295    fp_add(&t2, &t2, &t2);
00296    if (fp_cmp(&t2, modulus) != FP_LT) {
00297       fp_sub(&t2, modulus, &t2);
00298    }
00299    /* T2 = X + T2 */
00300    fp_add(&t2, &x, &t2);
00301    if (fp_cmp(&t2, modulus) != FP_LT) {
00302       fp_sub(&t2, modulus, &t2);
00303    }
00304 
00305    /* if Z' != 1 */
00306    if (get_digit_count(&Q->z)) {
00307       /* Z = Z * Z' */
00308       fp_mul(&z, &Q->z, &z);
00309       fp_montgomery_reduce(&z, modulus, *mp);
00310    }
00311 
00312    /* Z = Z * X */
00313    fp_mul(&z, &x, &z);
00314    fp_montgomery_reduce(&z, modulus, *mp);
00315 
00316    /* T1 = T1 * X  */
00317    fp_mul(&t1, &x, &t1);
00318    fp_montgomery_reduce(&t1, modulus, *mp);
00319    /* X = X * X */
00320    fp_sqr(&x, &x);
00321    fp_montgomery_reduce(&x, modulus, *mp);
00322    /* T2 = T2 * x */
00323    fp_mul(&t2, &x, &t2);
00324    fp_montgomery_reduce(&t2, modulus, *mp);
00325    /* T1 = T1 * X  */
00326    fp_mul(&t1, &x, &t1);
00327    fp_montgomery_reduce(&t1, modulus, *mp);
00328  
00329    /* X = Y*Y */
00330    fp_sqr(&y, &x);
00331    fp_montgomery_reduce(&x, modulus, *mp);
00332    /* X = X - T2 */
00333    fp_sub(&x, &t2, &x);
00334    if (fp_cmp_d(&x, 0) == FP_LT) {
00335       fp_add(&x, modulus, &x);
00336    }
00337 
00338    /* T2 = T2 - X */
00339    fp_sub(&t2, &x, &t2);
00340    if (fp_cmp_d(&t2, 0) == FP_LT) {
00341       fp_add(&t2, modulus, &t2);
00342    } 
00343    /* T2 = T2 - X */
00344    fp_sub(&t2, &x, &t2);
00345    if (fp_cmp_d(&t2, 0) == FP_LT) {
00346       fp_add(&t2, modulus, &t2);
00347    }
00348    /* T2 = T2 * Y */
00349    fp_mul(&t2, &y, &t2);
00350    fp_montgomery_reduce(&t2, modulus, *mp);
00351    /* Y = T2 - T1 */
00352    fp_sub(&t2, &t1, &y);
00353    if (fp_cmp_d(&y, 0) == FP_LT) {
00354       fp_add(&y, modulus, &y);
00355    }
00356    /* Y = Y/2 */
00357    if (fp_isodd(&y)) {
00358       fp_add(&y, modulus, &y);
00359    }
00360    fp_div_2(&y, &y);
00361 
00362    fp_copy(&x, &R->x);
00363    fp_copy(&y, &R->y);
00364    fp_copy(&z, &R->z);
00365    
00366    return MP_OKAY;
00367 }
00368 
00369 
00370 /**
00371    Double an ECC point
00372    P   The point to double
00373    R   [out] The destination of the double
00374    modulus  The modulus of the field the ECC curve is in
00375    mp       The "b" value from montgomery_setup()
00376    return   MP_OKAY on success
00377 */
00378 int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
00379                              mp_digit* mp)
00380 {
00381    fp_int   t1, t2;
00382    int      err;
00383 
00384    if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
00385        return ECC_BAD_ARG_E;
00386 
00387    if (P != R) {
00388       fp_copy(&P->x, &R->x);
00389       fp_copy(&P->y, &R->y);
00390       fp_copy(&P->z, &R->z);
00391    }
00392 
00393    if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
00394       return err;
00395    }
00396 
00397    /* t1 = Z * Z */
00398    fp_sqr(&R->z, &t1);
00399    fp_montgomery_reduce(&t1, modulus, *mp);
00400    /* Z = Y * Z */
00401    fp_mul(&R->z, &R->y, &R->z);
00402    fp_montgomery_reduce(&R->z, modulus, *mp);
00403    /* Z = 2Z */
00404    fp_add(&R->z, &R->z, &R->z);
00405    if (fp_cmp(&R->z, modulus) != FP_LT) {
00406       fp_sub(&R->z, modulus, &R->z);
00407    }
00408    
00409    /* &t2 = X - T1 */
00410    fp_sub(&R->x, &t1, &t2);
00411    if (fp_cmp_d(&t2, 0) == FP_LT) {
00412       fp_add(&t2, modulus, &t2);
00413    }
00414    /* T1 = X + T1 */
00415    fp_add(&t1, &R->x, &t1);
00416    if (fp_cmp(&t1, modulus) != FP_LT) {
00417       fp_sub(&t1, modulus, &t1);
00418    }
00419    /* T2 = T1 * T2 */
00420    fp_mul(&t1, &t2, &t2);
00421    fp_montgomery_reduce(&t2, modulus, *mp);
00422    /* T1 = 2T2 */
00423    fp_add(&t2, &t2, &t1);
00424    if (fp_cmp(&t1, modulus) != FP_LT) {
00425       fp_sub(&t1, modulus, &t1);
00426    }
00427    /* T1 = T1 + T2 */
00428    fp_add(&t1, &t2, &t1);
00429    if (fp_cmp(&t1, modulus) != FP_LT) {
00430       fp_sub(&t1, modulus, &t1);
00431    }
00432 
00433    /* Y = 2Y */
00434    fp_add(&R->y, &R->y, &R->y);
00435    if (fp_cmp(&R->y, modulus) != FP_LT) {
00436       fp_sub(&R->y, modulus, &R->y);
00437    }
00438    /* Y = Y * Y */
00439    fp_sqr(&R->y, &R->y);
00440    fp_montgomery_reduce(&R->y, modulus, *mp);
00441    /* T2 = Y * Y */
00442    fp_sqr(&R->y, &t2);
00443    fp_montgomery_reduce(&t2, modulus, *mp);
00444    /* T2 = T2/2 */
00445    if (fp_isodd(&t2)) {
00446       fp_add(&t2, modulus, &t2);
00447    }
00448    fp_div_2(&t2, &t2);
00449    /* Y = Y * X */
00450    fp_mul(&R->y, &R->x, &R->y);
00451    fp_montgomery_reduce(&R->y, modulus, *mp);
00452 
00453    /* X  = T1 * T1 */
00454    fp_sqr(&t1, &R->x);
00455    fp_montgomery_reduce(&R->x, modulus, *mp);
00456    /* X = X - Y */
00457    fp_sub(&R->x, &R->y, &R->x);
00458    if (fp_cmp_d(&R->x, 0) == FP_LT) {
00459       fp_add(&R->x, modulus, &R->x);
00460    }
00461    /* X = X - Y */
00462    fp_sub(&R->x, &R->y, &R->x);
00463    if (fp_cmp_d(&R->x, 0) == FP_LT) {
00464       fp_add(&R->x, modulus, &R->x);
00465    }
00466 
00467    /* Y = Y - X */     
00468    fp_sub(&R->y, &R->x, &R->y);
00469    if (fp_cmp_d(&R->y, 0) == FP_LT) {
00470       fp_add(&R->y, modulus, &R->y);
00471    }
00472    /* Y = Y * T1 */
00473    fp_mul(&R->y, &t1, &R->y);
00474    fp_montgomery_reduce(&R->y, modulus, *mp);
00475    /* Y = Y - T2 */
00476    fp_sub(&R->y, &t2, &R->y);
00477    if (fp_cmp_d(&R->y, 0) == FP_LT) {
00478       fp_add(&R->y, modulus, &R->y);
00479    }
00480  
00481    return MP_OKAY;
00482 }
00483 
00484 #else /* USE_FAST_MATH */
00485 
00486 /**
00487    Add two ECC points
00488    P        The point to add
00489    Q        The point to add
00490    R        [out] The destination of the double
00491    modulus  The modulus of the field the ECC curve is in
00492    mp       The "b" value from montgomery_setup()
00493    return   MP_OKAY on success
00494 */
00495 int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
00496                              mp_int* modulus, mp_digit* mp)
00497 {
00498    mp_int t1;
00499    mp_int t2;
00500    mp_int x;
00501    mp_int y;
00502    mp_int z;
00503    int    err;
00504 
00505    if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
00506        return ECC_BAD_ARG_E;
00507 
00508    if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
00509       return err;
00510    }
00511    
00512    /* should we dbl instead? */
00513    err = mp_sub(modulus, &Q->y, &t1);
00514 
00515    if (err == MP_OKAY) {
00516        if ( (mp_cmp(&P->x, &Q->x) == MP_EQ) && 
00517             (get_digit_count(&Q->z) && mp_cmp(&P->z, &Q->z) == MP_EQ) &&
00518             (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &t1) == MP_EQ)) {
00519                 mp_clear(&t1);
00520                 mp_clear(&t2);
00521                 mp_clear(&x);
00522                 mp_clear(&y);
00523                 mp_clear(&z);
00524 
00525                 return ecc_projective_dbl_point(P, R, modulus, mp);
00526        }
00527    }
00528 
00529    if (err == MP_OKAY)
00530        err = mp_copy(&P->x, &x);
00531    if (err == MP_OKAY)
00532        err = mp_copy(&P->y, &y);
00533    if (err == MP_OKAY)
00534        err = mp_copy(&P->z, &z);
00535 
00536    /* if Z is one then these are no-operations */
00537    if (err == MP_OKAY) {
00538        if (get_digit_count(&Q->z)) {
00539            /* T1 = Z' * Z' */
00540            err = mp_sqr(&Q->z, &t1);
00541            if (err == MP_OKAY)
00542                err = mp_montgomery_reduce(&t1, modulus, *mp);
00543 
00544            /* X = X * T1 */
00545            if (err == MP_OKAY)
00546                err = mp_mul(&t1, &x, &x);
00547            if (err == MP_OKAY)
00548                err = mp_montgomery_reduce(&x, modulus, *mp);
00549 
00550            /* T1 = Z' * T1 */
00551            if (err == MP_OKAY)
00552                err = mp_mul(&Q->z, &t1, &t1);
00553            if (err == MP_OKAY)
00554                err = mp_montgomery_reduce(&t1, modulus, *mp);
00555 
00556            /* Y = Y * T1 */
00557            if (err == MP_OKAY)
00558                err = mp_mul(&t1, &y, &y);
00559            if (err == MP_OKAY)
00560                err = mp_montgomery_reduce(&y, modulus, *mp);
00561        }
00562    }
00563 
00564    /* T1 = Z*Z */
00565    if (err == MP_OKAY)
00566        err = mp_sqr(&z, &t1);
00567    if (err == MP_OKAY)
00568        err = mp_montgomery_reduce(&t1, modulus, *mp);
00569 
00570    /* T2 = X' * T1 */
00571    if (err == MP_OKAY)
00572        err = mp_mul(&Q->x, &t1, &t2);
00573    if (err == MP_OKAY)
00574        err = mp_montgomery_reduce(&t2, modulus, *mp);
00575 
00576    /* T1 = Z * T1 */
00577    if (err == MP_OKAY)
00578        err = mp_mul(&z, &t1, &t1);
00579    if (err == MP_OKAY)
00580        err = mp_montgomery_reduce(&t1, modulus, *mp);
00581 
00582    /* T1 = Y' * T1 */
00583    if (err == MP_OKAY)
00584        err = mp_mul(&Q->y, &t1, &t1);
00585    if (err == MP_OKAY)
00586        err = mp_montgomery_reduce(&t1, modulus, *mp);
00587 
00588    /* Y = Y - T1 */
00589    if (err == MP_OKAY)
00590        err = mp_sub(&y, &t1, &y);
00591    if (err == MP_OKAY) {
00592        if (mp_cmp_d(&y, 0) == MP_LT)
00593            err = mp_add(&y, modulus, &y);
00594    }
00595    /* T1 = 2T1 */
00596    if (err == MP_OKAY)
00597        err = mp_add(&t1, &t1, &t1);
00598    if (err == MP_OKAY) {
00599        if (mp_cmp(&t1, modulus) != MP_LT)
00600            err = mp_sub(&t1, modulus, &t1);
00601    }
00602    /* T1 = Y + T1 */
00603    if (err == MP_OKAY)
00604        err = mp_add(&t1, &y, &t1);
00605    if (err == MP_OKAY) {
00606        if (mp_cmp(&t1, modulus) != MP_LT)
00607            err = mp_sub(&t1, modulus, &t1);
00608    }
00609    /* X = X - T2 */
00610    if (err == MP_OKAY)
00611        err = mp_sub(&x, &t2, &x);
00612    if (err == MP_OKAY) {
00613        if (mp_cmp_d(&x, 0) == MP_LT)
00614            err = mp_add(&x, modulus, &x);
00615    }
00616    /* T2 = 2T2 */
00617    if (err == MP_OKAY)
00618        err = mp_add(&t2, &t2, &t2);
00619    if (err == MP_OKAY) {
00620        if (mp_cmp(&t2, modulus) != MP_LT)
00621            err = mp_sub(&t2, modulus, &t2);
00622    }
00623    /* T2 = X + T2 */
00624    if (err == MP_OKAY)
00625        err = mp_add(&t2, &x, &t2);
00626    if (err == MP_OKAY) {
00627        if (mp_cmp(&t2, modulus) != MP_LT)
00628            err = mp_sub(&t2, modulus, &t2);
00629    }
00630 
00631    if (err == MP_OKAY) {
00632        if (get_digit_count(&Q->z)) {
00633            /* Z = Z * Z' */
00634            err = mp_mul(&z, &Q->z, &z);
00635            if (err == MP_OKAY)
00636                err = mp_montgomery_reduce(&z, modulus, *mp);
00637        }
00638    }
00639 
00640    /* Z = Z * X */
00641    if (err == MP_OKAY)
00642        err = mp_mul(&z, &x, &z);
00643    if (err == MP_OKAY)
00644        err = mp_montgomery_reduce(&z, modulus, *mp);
00645 
00646    /* T1 = T1 * X  */
00647    if (err == MP_OKAY)
00648        err = mp_mul(&t1, &x, &t1);
00649    if (err == MP_OKAY)
00650        err = mp_montgomery_reduce(&t1, modulus, *mp);
00651 
00652    /* X = X * X */
00653    if (err == MP_OKAY)
00654        err = mp_sqr(&x, &x);
00655    if (err == MP_OKAY)
00656        err = mp_montgomery_reduce(&x, modulus, *mp);
00657    
00658    /* T2 = T2 * x */
00659    if (err == MP_OKAY)
00660        err = mp_mul(&t2, &x, &t2);
00661    if (err == MP_OKAY)
00662        err = mp_montgomery_reduce(&t2, modulus, *mp);
00663 
00664    /* T1 = T1 * X  */
00665    if (err == MP_OKAY)
00666        err = mp_mul(&t1, &x, &t1);
00667    if (err == MP_OKAY)
00668        err = mp_montgomery_reduce(&t1, modulus, *mp);
00669  
00670    /* X = Y*Y */
00671    if (err == MP_OKAY)
00672        err = mp_sqr(&y, &x);
00673    if (err == MP_OKAY)
00674        err = mp_montgomery_reduce(&x, modulus, *mp);
00675 
00676    /* X = X - T2 */
00677    if (err == MP_OKAY)
00678        err = mp_sub(&x, &t2, &x);
00679    if (err == MP_OKAY) {
00680        if (mp_cmp_d(&x, 0) == MP_LT)
00681            err = mp_add(&x, modulus, &x);
00682    }
00683    /* T2 = T2 - X */
00684    if (err == MP_OKAY)
00685        err = mp_sub(&t2, &x, &t2);
00686    if (err == MP_OKAY) {
00687        if (mp_cmp_d(&t2, 0) == MP_LT)
00688            err = mp_add(&t2, modulus, &t2);
00689    } 
00690    /* T2 = T2 - X */
00691    if (err == MP_OKAY)
00692        err = mp_sub(&t2, &x, &t2);
00693    if (err == MP_OKAY) {
00694        if (mp_cmp_d(&t2, 0) == MP_LT)
00695            err = mp_add(&t2, modulus, &t2);
00696    }
00697    /* T2 = T2 * Y */
00698    if (err == MP_OKAY)
00699        err = mp_mul(&t2, &y, &t2);
00700    if (err == MP_OKAY)
00701        err = mp_montgomery_reduce(&t2, modulus, *mp);
00702 
00703    /* Y = T2 - T1 */
00704    if (err == MP_OKAY)
00705        err = mp_sub(&t2, &t1, &y);
00706    if (err == MP_OKAY) {
00707        if (mp_cmp_d(&y, 0) == MP_LT)
00708            err = mp_add(&y, modulus, &y);
00709    }
00710    /* Y = Y/2 */
00711    if (err == MP_OKAY) {
00712        if (mp_isodd(&y))
00713            err = mp_add(&y, modulus, &y);
00714    }
00715    if (err == MP_OKAY)
00716        err = mp_div_2(&y, &y);
00717 
00718    if (err == MP_OKAY)
00719        err = mp_copy(&x, &R->x);
00720    if (err == MP_OKAY)
00721        err = mp_copy(&y, &R->y);
00722    if (err == MP_OKAY)
00723        err = mp_copy(&z, &R->z);
00724 
00725    /* clean up */
00726    mp_clear(&t1);
00727    mp_clear(&t2);
00728    mp_clear(&x);
00729    mp_clear(&y);
00730    mp_clear(&z);
00731 
00732    return err;
00733 }
00734 
00735 
00736 /**
00737    Double an ECC point
00738    P   The point to double
00739    R   [out] The destination of the double
00740    modulus  The modulus of the field the ECC curve is in
00741    mp       The "b" value from montgomery_setup()
00742    return   MP_OKAY on success
00743 */
00744 int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
00745                              mp_digit* mp)
00746 {
00747    mp_int t1;
00748    mp_int t2;
00749    int    err;
00750 
00751    if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
00752        return ECC_BAD_ARG_E;
00753 
00754    if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
00755       return err;
00756    }
00757 
00758    if (P != R) {
00759       err = mp_copy(&P->x, &R->x);
00760       if (err == MP_OKAY)
00761           err = mp_copy(&P->y, &R->y);
00762       if (err == MP_OKAY)
00763           err = mp_copy(&P->z, &R->z);
00764    }
00765 
00766    /* t1 = Z * Z */
00767    if (err == MP_OKAY)
00768        err = mp_sqr(&R->z, &t1);
00769    if (err == MP_OKAY)
00770        err = mp_montgomery_reduce(&t1, modulus, *mp);
00771 
00772    /* Z = Y * Z */
00773    if (err == MP_OKAY)
00774        err = mp_mul(&R->z, &R->y, &R->z);
00775    if (err == MP_OKAY)
00776        err = mp_montgomery_reduce(&R->z, modulus, *mp);
00777 
00778    /* Z = 2Z */
00779    if (err == MP_OKAY)
00780        err = mp_add(&R->z, &R->z, &R->z);
00781    if (err == MP_OKAY) {
00782        if (mp_cmp(&R->z, modulus) != MP_LT)
00783            err = mp_sub(&R->z, modulus, &R->z);
00784    }
00785 
00786    /* T2 = X - T1 */
00787    if (err == MP_OKAY)
00788        err = mp_sub(&R->x, &t1, &t2);
00789    if (err == MP_OKAY) {
00790        if (mp_cmp_d(&t2, 0) == MP_LT)
00791            err = mp_add(&t2, modulus, &t2);
00792    }
00793    /* T1 = X + T1 */
00794    if (err == MP_OKAY)
00795        err = mp_add(&t1, &R->x, &t1);
00796    if (err == MP_OKAY) {
00797        if (mp_cmp(&t1, modulus) != MP_LT)
00798            err = mp_sub(&t1, modulus, &t1);
00799    }
00800    /* T2 = T1 * T2 */
00801    if (err == MP_OKAY)
00802        err = mp_mul(&t1, &t2, &t2);
00803    if (err == MP_OKAY)
00804        err = mp_montgomery_reduce(&t2, modulus, *mp);
00805 
00806    /* T1 = 2T2 */
00807    if (err == MP_OKAY)
00808        err = mp_add(&t2, &t2, &t1);
00809    if (err == MP_OKAY) {
00810        if (mp_cmp(&t1, modulus) != MP_LT)
00811            err = mp_sub(&t1, modulus, &t1);
00812    }
00813    /* T1 = T1 + T2 */
00814    if (err == MP_OKAY)
00815        err = mp_add(&t1, &t2, &t1);
00816    if (err == MP_OKAY) {
00817        if (mp_cmp(&t1, modulus) != MP_LT)
00818            err = mp_sub(&t1, modulus, &t1);
00819    }
00820    /* Y = 2Y */
00821    if (err == MP_OKAY)
00822        err = mp_add(&R->y, &R->y, &R->y);
00823    if (err == MP_OKAY) {
00824        if (mp_cmp(&R->y, modulus) != MP_LT)
00825            err = mp_sub(&R->y, modulus, &R->y);
00826    }
00827    /* Y = Y * Y */
00828    if (err == MP_OKAY)
00829        err = mp_sqr(&R->y, &R->y);
00830    if (err == MP_OKAY)
00831        err = mp_montgomery_reduce(&R->y, modulus, *mp);
00832    
00833    /* T2 = Y * Y */
00834    if (err == MP_OKAY)
00835        err = mp_sqr(&R->y, &t2);
00836    if (err == MP_OKAY)
00837        err = mp_montgomery_reduce(&t2, modulus, *mp);
00838 
00839    /* T2 = T2/2 */
00840    if (err == MP_OKAY) {
00841        if (mp_isodd(&t2))
00842            err = mp_add(&t2, modulus, &t2);
00843    }
00844    if (err == MP_OKAY)
00845        err = mp_div_2(&t2, &t2);
00846    
00847    /* Y = Y * X */
00848    if (err == MP_OKAY)
00849        err = mp_mul(&R->y, &R->x, &R->y);
00850    if (err == MP_OKAY)
00851        err = mp_montgomery_reduce(&R->y, modulus, *mp);
00852 
00853    /* X  = T1 * T1 */
00854    if (err == MP_OKAY)
00855        err = mp_sqr(&t1, &R->x);
00856    if (err == MP_OKAY)
00857        err = mp_montgomery_reduce(&R->x, modulus, *mp);
00858 
00859    /* X = X - Y */
00860    if (err == MP_OKAY)
00861        err = mp_sub(&R->x, &R->y, &R->x);
00862    if (err == MP_OKAY) {
00863        if (mp_cmp_d(&R->x, 0) == MP_LT)
00864            err = mp_add(&R->x, modulus, &R->x);
00865    }
00866    /* X = X - Y */
00867    if (err == MP_OKAY)
00868        err = mp_sub(&R->x, &R->y, &R->x);
00869    if (err == MP_OKAY) {
00870        if (mp_cmp_d(&R->x, 0) == MP_LT)
00871            err = mp_add(&R->x, modulus, &R->x);
00872    }
00873    /* Y = Y - X */     
00874    if (err == MP_OKAY)
00875        err = mp_sub(&R->y, &R->x, &R->y);
00876    if (err == MP_OKAY) {
00877        if (mp_cmp_d(&R->y, 0) == MP_LT)
00878            err = mp_add(&R->y, modulus, &R->y);
00879    }
00880    /* Y = Y * T1 */
00881    if (err == MP_OKAY)
00882        err = mp_mul(&R->y, &t1, &R->y);
00883    if (err == MP_OKAY)
00884        err = mp_montgomery_reduce(&R->y, modulus, *mp);
00885 
00886    /* Y = Y - T2 */
00887    if (err == MP_OKAY)
00888        err = mp_sub(&R->y, &t2, &R->y);
00889    if (err == MP_OKAY) {
00890        if (mp_cmp_d(&R->y, 0) == MP_LT)
00891            err = mp_add(&R->y, modulus, &R->y);
00892    }
00893 
00894    /* clean up */ 
00895    mp_clear(&t1);
00896    mp_clear(&t2);
00897 
00898    return err;
00899 }
00900 
00901 #endif /* USE_FAST_MATH */
00902 
00903 /**
00904   Map a projective jacbobian point back to affine space
00905   P        [in/out] The point to map
00906   modulus  The modulus of the field the ECC curve is in
00907   mp       The "b" value from montgomery_setup()
00908   return   MP_OKAY on success
00909 */
00910 int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp)
00911 {
00912    mp_int t1;
00913    mp_int t2;
00914    int    err;
00915 
00916    if (P == NULL || mp == NULL || modulus == NULL)
00917        return ECC_BAD_ARG_E;
00918 
00919    if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
00920       return MEMORY_E;
00921    }
00922 
00923    /* first map z back to normal */
00924    err = mp_montgomery_reduce(&P->z, modulus, *mp);
00925 
00926    /* get 1/z */
00927    if (err == MP_OKAY)
00928        err = mp_invmod(&P->z, modulus, &t1);
00929  
00930    /* get 1/z^2 and 1/z^3 */
00931    if (err == MP_OKAY)
00932        err = mp_sqr(&t1, &t2);
00933    if (err == MP_OKAY)
00934        err = mp_mod(&t2, modulus, &t2);
00935    if (err == MP_OKAY)
00936        err = mp_mul(&t1, &t2, &t1);
00937    if (err == MP_OKAY)
00938        err = mp_mod(&t1, modulus, &t1);
00939 
00940    /* multiply against x/y */
00941    if (err == MP_OKAY)
00942        err = mp_mul(&P->x, &t2, &P->x);
00943    if (err == MP_OKAY)
00944        err = mp_montgomery_reduce(&P->x, modulus, *mp);
00945    if (err == MP_OKAY)
00946        err = mp_mul(&P->y, &t1, &P->y);
00947    if (err == MP_OKAY)
00948        err = mp_montgomery_reduce(&P->y, modulus, *mp);
00949    
00950    if (err == MP_OKAY)
00951        mp_set(&P->z, 1);
00952 
00953    /* clean up */
00954    mp_clear(&t1);
00955    mp_clear(&t2);
00956 
00957    return err;
00958 }
00959 
00960 
00961 #ifndef ECC_TIMING_RESISTANT
00962 
00963 /* size of sliding window, don't change this! */
00964 #define WINSIZE 4
00965 
00966 /**
00967    Perform a point multiplication 
00968    k    The scalar to multiply by
00969    G    The base point
00970    R    [out] Destination for kG
00971    modulus  The modulus of the field the ECC curve is in
00972    map      Boolean whether to map back to affine or not
00973                 (1==map, 0 == leave in projective)
00974    return MP_OKAY on success
00975 */
00976 #ifdef FP_ECC
00977 static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
00978                              mp_int* modulus, int map)
00979 #else
00980 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
00981                       int map)
00982 #endif
00983 {
00984    ecc_point *tG, *M[8];
00985    int           i, j, err;
00986    mp_int        mu;
00987    mp_digit      mp;
00988    unsigned long buf;
00989    int           first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0,
00990                  digidx = 0;
00991 
00992    if (k == NULL || G == NULL || R == NULL || modulus == NULL)
00993        return ECC_BAD_ARG_E;
00994 
00995    /* init montgomery reduction */
00996    if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
00997       return err;
00998    }
00999    if ((err = mp_init(&mu)) != MP_OKAY) {
01000       return err;
01001    }
01002    if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
01003       mp_clear(&mu);
01004       return err;
01005    }
01006   
01007   /* alloc ram for window temps */
01008   for (i = 0; i < 8; i++) {
01009       M[i] = ecc_new_point();
01010       if (M[i] == NULL) {
01011          for (j = 0; j < i; j++) {
01012              ecc_del_point(M[j]);
01013          }
01014          mp_clear(&mu);
01015          return MEMORY_E;
01016       }
01017   }
01018 
01019    /* make a copy of G incase R==G */
01020    tG = ecc_new_point();
01021    if (tG == NULL)
01022        err = MEMORY_E;
01023 
01024    /* tG = G  and convert to montgomery */
01025    if (err == MP_OKAY) {
01026        if (mp_cmp_d(&mu, 1) == MP_EQ) {
01027            err = mp_copy(&G->x, &tG->x);
01028            if (err == MP_OKAY)
01029                err = mp_copy(&G->y, &tG->y);
01030            if (err == MP_OKAY)
01031                err = mp_copy(&G->z, &tG->z);
01032        } else {
01033            err = mp_mulmod(&G->x, &mu, modulus, &tG->x);
01034            if (err == MP_OKAY)
01035                err = mp_mulmod(&G->y, &mu, modulus, &tG->y);
01036            if (err == MP_OKAY)
01037                err = mp_mulmod(&G->z, &mu, modulus, &tG->z);
01038        }
01039    }
01040    mp_clear(&mu);
01041    
01042    /* calc the M tab, which holds kG for k==8..15 */
01043    /* M[0] == 8G */
01044    if (err == MP_OKAY)
01045        err = ecc_projective_dbl_point(tG, M[0], modulus, &mp);
01046    if (err == MP_OKAY)
01047        err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
01048    if (err == MP_OKAY)
01049        err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
01050 
01051    /* now find (8+k)G for k=1..7 */
01052    if (err == MP_OKAY)
01053        for (j = 9; j < 16; j++) {
01054            err = ecc_projective_add_point(M[j-9], tG, M[j-8], modulus, &mp);
01055            if (err != MP_OKAY) break;
01056        }
01057 
01058    /* setup sliding window */
01059    if (err == MP_OKAY) {
01060        mode   = 0;
01061        bitcnt = 1;
01062        buf    = 0;
01063        digidx = get_digit_count(k) - 1;
01064        bitcpy = bitbuf = 0;
01065        first  = 1;
01066 
01067        /* perform ops */
01068        for (;;) {
01069            /* grab next digit as required */
01070            if (--bitcnt == 0) {
01071                if (digidx == -1) {
01072                    break;
01073                }
01074                buf    = get_digit(k, digidx);
01075                bitcnt = (int) DIGIT_BIT; 
01076                --digidx;
01077            }
01078 
01079            /* grab the next msb from the ltiplicand */
01080            i = (int)(buf >> (DIGIT_BIT - 1)) & 1;
01081            buf <<= 1;
01082 
01083            /* skip leading zero bits */
01084            if (mode == 0 && i == 0)
01085                continue;
01086 
01087            /* if the bit is zero and mode == 1 then we double */
01088            if (mode == 1 && i == 0) {
01089                err = ecc_projective_dbl_point(R, R, modulus, &mp);
01090                if (err != MP_OKAY) break;
01091                continue;
01092            }
01093 
01094            /* else we add it to the window */
01095            bitbuf |= (i << (WINSIZE - ++bitcpy));
01096            mode = 2;
01097 
01098            if (bitcpy == WINSIZE) {
01099                /* if this is the first window we do a simple copy */
01100                if (first == 1) {
01101                    /* R = kG [k = first window] */
01102                    err = mp_copy(&M[bitbuf-8]->x, &R->x);
01103                    if (err != MP_OKAY) break;
01104 
01105                    err = mp_copy(&M[bitbuf-8]->y, &R->y);
01106                    if (err != MP_OKAY) break;
01107 
01108                    err = mp_copy(&M[bitbuf-8]->z, &R->z);
01109                    first = 0;
01110                } else {
01111                    /* normal window */
01112                    /* ok window is filled so double as required and add  */
01113                    /* double first */
01114                    for (j = 0; j < WINSIZE; j++) {
01115                        err = ecc_projective_dbl_point(R, R, modulus, &mp);
01116                        if (err != MP_OKAY) break;
01117                    }
01118                    if (err != MP_OKAY) break;  /* out of first for(;;) */
01119 
01120                    /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranted */
01121                    err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp);
01122                }
01123                if (err != MP_OKAY) break;
01124                /* empty window and reset */
01125                bitcpy = bitbuf = 0;
01126                mode = 1;
01127            }
01128        }
01129    }
01130 
01131    /* if bits remain then double/add */
01132    if (err == MP_OKAY) {
01133        if (mode == 2 && bitcpy > 0) {
01134            /* double then add */
01135            for (j = 0; j < bitcpy; j++) {
01136                /* only double if we have had at least one add first */
01137                if (first == 0) {
01138                    err = ecc_projective_dbl_point(R, R, modulus, &mp);
01139                    if (err != MP_OKAY) break;
01140                }
01141 
01142                bitbuf <<= 1;
01143                if ((bitbuf & (1 << WINSIZE)) != 0) {
01144                    if (first == 1) {
01145                        /* first add, so copy */
01146                        err = mp_copy(&tG->x, &R->x);
01147                        if (err != MP_OKAY) break;
01148 
01149                        err = mp_copy(&tG->y, &R->y);
01150                        if (err != MP_OKAY) break;
01151 
01152                        err = mp_copy(&tG->z, &R->z);
01153                        if (err != MP_OKAY) break;
01154                        first = 0;
01155                    } else {
01156                        /* then add */
01157                        err = ecc_projective_add_point(R, tG, R, modulus, &mp);
01158                        if (err != MP_OKAY) break;
01159                    }
01160                }
01161            }
01162        }
01163    }
01164 
01165    /* map R back from projective space */
01166    if (err == MP_OKAY && map)
01167        err = ecc_map(R, modulus, &mp);
01168 
01169    mp_clear(&mu);
01170    ecc_del_point(tG);
01171    for (i = 0; i < 8; i++) {
01172        ecc_del_point(M[i]);
01173    }
01174    return err;
01175 }
01176 
01177 #undef WINSIZE
01178 
01179 #else /* ECC_TIMING_RESISTANT */
01180 
01181 /**
01182    Perform a point multiplication  (timing resistant)
01183    k    The scalar to multiply by
01184    G    The base point
01185    R    [out] Destination for kG
01186    modulus  The modulus of the field the ECC curve is in
01187    map      Boolean whether to map back to affine or not
01188             (1==map, 0 == leave in projective)
01189    return MP_OKAY on success
01190 */
01191 #ifdef FP_ECC
01192 static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R,
01193                              mp_int* modulus, int map)
01194 #else
01195 static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
01196                       int map)
01197 #endif
01198 {
01199    ecc_point    *tG, *M[3];
01200    int           i, j, err;
01201    mp_int        mu;
01202    mp_digit      mp;
01203    unsigned long buf;
01204    int           first = 1, bitbuf = 0, bitcpy = 0, bitcnt = 0, mode = 0,
01205                  digidx = 0;
01206 
01207    if (k == NULL || G == NULL || R == NULL || modulus == NULL)
01208        return ECC_BAD_ARG_E;
01209 
01210    /* init montgomery reduction */
01211    if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
01212       return err;
01213    }
01214    if ((err = mp_init(&mu)) != MP_OKAY) {
01215       return err;
01216    }
01217    if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
01218       mp_clear(&mu);
01219       return err;
01220    }
01221 
01222   /* alloc ram for window temps */
01223   for (i = 0; i < 3; i++) {
01224       M[i] = ecc_new_point();
01225       if (M[i] == NULL) {
01226          for (j = 0; j < i; j++) {
01227              ecc_del_point(M[j]);
01228          }
01229          mp_clear(&mu);
01230          return MEMORY_E;
01231       }
01232   }
01233 
01234    /* make a copy of G incase R==G */
01235    tG = ecc_new_point();
01236    if (tG == NULL)
01237        err = MEMORY_E;
01238 
01239    /* tG = G  and convert to montgomery */
01240    if (err == MP_OKAY) {
01241        err = mp_mulmod(&G->x, &mu, modulus, &tG->x);
01242        if (err == MP_OKAY)
01243            err = mp_mulmod(&G->y, &mu, modulus, &tG->y);
01244        if (err == MP_OKAY)
01245            err = mp_mulmod(&G->z, &mu, modulus, &tG->z);
01246    }
01247    mp_clear(&mu);
01248 
01249    /* calc the M tab */
01250    /* M[0] == G */
01251    if (err == MP_OKAY)
01252        err = mp_copy(&tG->x, &M[0]->x);
01253    if (err == MP_OKAY)
01254        err = mp_copy(&tG->y, &M[0]->y);
01255    if (err == MP_OKAY)
01256        err = mp_copy(&tG->z, &M[0]->z);
01257 
01258    /* M[1] == 2G */
01259    if (err == MP_OKAY)
01260        err = ecc_projective_dbl_point(tG, M[1], modulus, &mp);
01261 
01262    /* setup sliding window */
01263    mode   = 0;
01264    bitcnt = 1;
01265    buf    = 0;
01266    digidx = get_digit_count(k) - 1;
01267    bitcpy = bitbuf = 0;
01268    first  = 1;
01269 
01270    /* perform ops */
01271    if (err == MP_OKAY) {
01272        for (;;) {
01273            /* grab next digit as required */
01274            if (--bitcnt == 0) {
01275                if (digidx == -1) {
01276                    break;
01277                }
01278                buf = get_digit(k, digidx);
01279                bitcnt = (int) DIGIT_BIT;
01280                --digidx;
01281            }
01282 
01283            /* grab the next msb from the ltiplicand */
01284            i = (buf >> (DIGIT_BIT - 1)) & 1;
01285            buf <<= 1;
01286 
01287            if (mode == 0 && i == 0) {
01288                /* dummy operations */
01289                if (err == MP_OKAY)
01290                    err = ecc_projective_add_point(M[0], M[1], M[2], modulus,
01291                                                   &mp);
01292                if (err == MP_OKAY)
01293                    err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp);
01294                if (err == MP_OKAY)
01295                    continue;
01296            }
01297 
01298            if (mode == 0 && i == 1) {
01299                mode = 1;
01300                /* dummy operations */
01301                if (err == MP_OKAY)
01302                    err = ecc_projective_add_point(M[0], M[1], M[2], modulus,
01303                                                   &mp);
01304                if (err == MP_OKAY)
01305                    err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp);
01306                if (err == MP_OKAY)
01307                    continue;
01308            }
01309 
01310            if (err == MP_OKAY)
01311                err = ecc_projective_add_point(M[0], M[1], M[i^1], modulus, &mp);
01312            if (err == MP_OKAY)
01313                err = ecc_projective_dbl_point(M[i], M[i], modulus, &mp);
01314            if (err != MP_OKAY)
01315                break;
01316        } /* end for */
01317    }
01318 
01319    /* copy result out */
01320    if (err == MP_OKAY)
01321        err = mp_copy(&M[0]->x, &R->x);
01322    if (err == MP_OKAY)
01323        err = mp_copy(&M[0]->y, &R->y);
01324    if (err == MP_OKAY)
01325        err = mp_copy(&M[0]->z, &R->z);
01326 
01327    /* map R back from projective space */
01328    if (err == MP_OKAY && map)
01329       err = ecc_map(R, modulus, &mp);
01330 
01331    /* done */
01332    mp_clear(&mu);
01333    ecc_del_point(tG);
01334    for (i = 0; i < 3; i++) {
01335        ecc_del_point(M[i]);
01336    }
01337    return err;
01338 }
01339 
01340 #endif /* ECC_TIMING_RESISTANT */
01341 
01342 
01343 /**
01344    Allocate a new ECC point
01345    return A newly allocated point or NULL on error 
01346 */
01347 ecc_point* ecc_new_point(void)
01348 {
01349    ecc_point* p;
01350    p = (ecc_point*)XMALLOC(sizeof(ecc_point), 0, DYNAMIC_TYPE_BIGINT);
01351    if (p == NULL) {
01352       return NULL;
01353    }
01354    XMEMSET(p, 0, sizeof(ecc_point));
01355    if (mp_init_multi(&p->x, &p->y, &p->z, NULL, NULL, NULL) != MP_OKAY) {
01356       XFREE(p, 0, DYNAMIC_TYPE_BIGINT);
01357       return NULL;
01358    }
01359    return p;
01360 }
01361 
01362 /** Free an ECC point from memory
01363   p   The point to free
01364 */
01365 void ecc_del_point(ecc_point* p)
01366 {
01367    /* prevents free'ing null arguments */
01368    if (p != NULL) {
01369       mp_clear(&p->x);
01370       mp_clear(&p->y);
01371       mp_clear(&p->z);
01372       XFREE(p, 0, DYNAMIC_TYPE_BIGINT);
01373    }
01374 }
01375 
01376 
01377 /** Returns whether an ECC idx is valid or not
01378   n      The idx number to check
01379   return 1 if valid, 0 if not
01380 */  
01381 static int ecc_is_valid_idx(int n)
01382 {
01383    int x;
01384 
01385    for (x = 0; ecc_sets[x].size != 0; x++)
01386        ;
01387    /* -1 is a valid index --- indicating that the domain params
01388       were supplied by the user */
01389    if ((n >= -1) && (n < x)) {
01390       return 1;
01391    }
01392    return 0;
01393 }
01394 
01395 
01396 /**
01397   Create an ECC shared secret between two keys
01398   private_key      The private ECC key
01399   public_key       The public key
01400   out              [out] Destination of the shared secret
01401                    Conforms to EC-DH from ANSI X9.63
01402   outlen           [in/out] The max size and resulting size of the shared secret
01403   return           MP_OKAY if successful
01404 */
01405 int ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
01406                       word32* outlen)
01407 {
01408    word32         x = 0;
01409    ecc_point*     result;
01410    mp_int         prime;
01411    int            err;
01412 
01413    if (private_key == NULL || public_key == NULL || out == NULL ||
01414                                                     outlen == NULL)
01415        return BAD_FUNC_ARG;
01416 
01417    /* type valid? */
01418    if (private_key->type != ECC_PRIVATEKEY) {
01419       return ECC_BAD_ARG_E;
01420    }
01421 
01422    if (ecc_is_valid_idx(private_key->idx) == 0 ||
01423        ecc_is_valid_idx(public_key->idx)  == 0)
01424       return ECC_BAD_ARG_E;
01425 
01426    if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0)
01427       return ECC_BAD_ARG_E;
01428 
01429    /* make new point */
01430    result = ecc_new_point();
01431    if (result == NULL) {
01432       return MEMORY_E;
01433    }
01434 
01435    if ((err = mp_init(&prime)) != MP_OKAY) {
01436       ecc_del_point(result);
01437       return err;
01438    }
01439 
01440    err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16);
01441 
01442    if (err == MP_OKAY)
01443        err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime,1);
01444 
01445    if (err == MP_OKAY) {
01446        x = mp_unsigned_bin_size(&prime);
01447        if (*outlen < x)
01448           err = BUFFER_E;
01449    }
01450 
01451    if (err == MP_OKAY) {
01452        XMEMSET(out, 0, x);
01453        err = mp_to_unsigned_bin(&result->x,out + (x -
01454                                             mp_unsigned_bin_size(&result->x)));
01455        *outlen = x;
01456    }
01457 
01458    mp_clear(&prime);
01459    ecc_del_point(result);
01460 
01461    return err;
01462 }
01463 
01464 
01465 int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp);
01466 
01467 /**
01468   Make a new ECC key 
01469   rng          An active RNG state
01470   keysize      The keysize for the new key (in octets from 20 to 65 bytes)
01471   key          [out] Destination of the newly created key
01472   return       MP_OKAY if successful,
01473                        upon error all allocated memory will be freed
01474 */
01475 int ecc_make_key(RNG* rng, int keysize, ecc_key* key)
01476 {
01477    int x, err;
01478 
01479    if (key == NULL || rng == NULL)
01480        return ECC_BAD_ARG_E;
01481 
01482    /* find key size */
01483    for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++)
01484        ;
01485    keysize = ecc_sets[x].size;
01486 
01487    if (keysize > ECC_MAXSIZE || ecc_sets[x].size == 0) {
01488       return BAD_FUNC_ARG;
01489    }
01490    err = ecc_make_key_ex(rng, key, &ecc_sets[x]);
01491    key->idx = x;
01492 
01493    return err;
01494 }
01495 
01496 int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
01497 {
01498    int            err;
01499    ecc_point*     base;
01500    mp_int         prime;
01501    mp_int         order;
01502 #ifdef CYASSL_SMALL_STACK
01503    byte*          buf;
01504 #else
01505    byte           buf[ECC_MAXSIZE];
01506 #endif
01507    int            keysize;
01508 
01509    if (key == NULL || rng == NULL || dp == NULL)
01510        return ECC_BAD_ARG_E;
01511 
01512 #ifdef CYASSL_SMALL_STACK
01513    buf = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01514    if (buf == NULL)
01515        return MEMORY_E;
01516 #endif
01517 
01518    key->idx = -1;
01519    key->dp  = dp;
01520    keysize  = dp->size;
01521 
01522    /* allocate ram */
01523    base = NULL;
01524 
01525    /* make up random string */
01526    err = RNG_GenerateBlock(rng, buf, keysize);
01527    if (err == 0)
01528        buf[0] |= 0x0c;
01529 
01530    /* setup the key variables */
01531    if (err == 0) {
01532        err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
01533                             &key->k, &prime, &order);
01534        if (err != MP_OKAY)
01535            err = MEMORY_E;
01536    }
01537 
01538    if (err == MP_OKAY) {
01539        base = ecc_new_point();
01540        if (base == NULL)
01541            err = MEMORY_E;
01542    }
01543 
01544    /* read in the specs for this key */
01545    if (err == MP_OKAY) 
01546        err = mp_read_radix(&prime,   (char *)key->dp->prime, 16);
01547    if (err == MP_OKAY) 
01548        err = mp_read_radix(&order,   (char *)key->dp->order, 16);
01549    if (err == MP_OKAY) 
01550        err = mp_read_radix(&base->x, (char *)key->dp->Gx, 16);
01551    if (err == MP_OKAY) 
01552        err = mp_read_radix(&base->y, (char *)key->dp->Gy, 16);
01553    
01554    if (err == MP_OKAY) 
01555        mp_set(&base->z, 1);
01556    if (err == MP_OKAY) 
01557        err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize);
01558 
01559    /* the key should be smaller than the order of base point */
01560    if (err == MP_OKAY) { 
01561        if (mp_cmp(&key->k, &order) != MP_LT)
01562            err = mp_mod(&key->k, &order, &key->k);
01563    }
01564    /* make the public key */
01565    if (err == MP_OKAY)
01566        err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1);
01567    if (err == MP_OKAY)
01568        key->type = ECC_PRIVATEKEY;
01569 
01570    if (err != MP_OKAY) {
01571        /* clean up */
01572        mp_clear(&key->pubkey.x);
01573        mp_clear(&key->pubkey.y);
01574        mp_clear(&key->pubkey.z);
01575        mp_clear(&key->k);
01576    }
01577    ecc_del_point(base);
01578    mp_clear(&prime);
01579    mp_clear(&order);
01580 
01581 #ifdef ECC_CLEAN_STACK
01582    XMEMSET(buf, 0, ECC_MAXSIZE);
01583 #endif
01584 
01585 #ifdef CYASSL_SMALL_STACK
01586    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01587 #endif
01588 
01589    return err;
01590 }
01591 
01592 
01593 /* Setup dynamic pointers is using normal math for proper freeing */
01594 void ecc_init(ecc_key* key)
01595 {
01596     (void)key;
01597 #ifndef USE_FAST_MATH
01598     key->pubkey.x.dp = NULL;
01599     key->pubkey.y.dp = NULL;
01600     key->pubkey.z.dp = NULL;
01601 
01602     key->k.dp = NULL;
01603 #endif
01604 }
01605 
01606 
01607 /**
01608   Sign a message digest
01609   in        The message digest to sign
01610   inlen     The length of the digest
01611   out       [out] The destination for the signature
01612   outlen    [in/out] The max size and resulting size of the signature
01613   key       A private ECC key
01614   return    MP_OKAY if successful
01615 */
01616 int ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, 
01617                   RNG* rng, ecc_key* key)
01618 {
01619    mp_int        r;
01620    mp_int        s;
01621    mp_int        e;
01622    mp_int        p;
01623    int           err;
01624 
01625    if (in == NULL || out == NULL || outlen == NULL || key == NULL || rng ==NULL)
01626        return ECC_BAD_ARG_E;
01627 
01628    /* is this a private key? */
01629    if (key->type != ECC_PRIVATEKEY) {
01630       return ECC_BAD_ARG_E;
01631    }
01632    
01633    /* is the IDX valid ?  */
01634    if (ecc_is_valid_idx(key->idx) != 1) {
01635       return ECC_BAD_ARG_E;
01636    }
01637 
01638    /* get the hash and load it as a bignum into 'e' */
01639    /* init the bignums */
01640    if ((err = mp_init_multi(&r, &s, &p, &e, NULL, NULL)) != MP_OKAY) { 
01641       return err;
01642    }
01643    err = mp_read_radix(&p, (char *)key->dp->order, 16);
01644 
01645    if (err == MP_OKAY) {
01646        /* we may need to truncate if hash is longer than key size */
01647        word32 orderBits = mp_count_bits(&p);
01648 
01649        /* truncate down to byte size, may be all that's needed */
01650        if ( (CYASSL_BIT_SIZE * inlen) > orderBits)
01651            inlen = (orderBits + CYASSL_BIT_SIZE - 1)/CYASSL_BIT_SIZE;
01652        err = mp_read_unsigned_bin(&e, (byte*)in, inlen);
01653 
01654        /* may still need bit truncation too */
01655        if (err == MP_OKAY && (CYASSL_BIT_SIZE * inlen) > orderBits)
01656            mp_rshb(&e, CYASSL_BIT_SIZE - (orderBits & 0x7));
01657    }
01658 
01659    /* make up a key and export the public copy */
01660    if (err == MP_OKAY) {
01661        ecc_key pubkey;
01662        ecc_init(&pubkey);
01663        for (;;) {
01664            err = ecc_make_key_ex(rng, &pubkey, key->dp);
01665            if (err != MP_OKAY) break;
01666 
01667            /* find r = x1 mod n */
01668            err = mp_mod(&pubkey.pubkey.x, &p, &r);
01669            if (err != MP_OKAY) break;
01670 
01671            if (mp_iszero(&r) == MP_YES)
01672                ecc_free(&pubkey);
01673            else { 
01674                /* find s = (e + xr)/k */
01675                err = mp_invmod(&pubkey.k, &p, &pubkey.k);
01676                if (err != MP_OKAY) break;
01677 
01678                err = mp_mulmod(&key->k, &r, &p, &s);   /* s = xr */
01679                if (err != MP_OKAY) break;
01680            
01681                err = mp_add(&e, &s, &s);               /* s = e +  xr */
01682                if (err != MP_OKAY) break;
01683 
01684                err = mp_mod(&s, &p, &s);               /* s = e +  xr */
01685                if (err != MP_OKAY) break;
01686 
01687                err = mp_mulmod(&s, &pubkey.k, &p, &s); /* s = (e + xr)/k */
01688                if (err != MP_OKAY) break;
01689 
01690                ecc_free(&pubkey);
01691                if (mp_iszero(&s) == MP_NO)
01692                    break;
01693             }
01694        }
01695        ecc_free(&pubkey);
01696    }
01697 
01698    /* store as SEQUENCE { r, s -- integer } */
01699    if (err == MP_OKAY)
01700        err = StoreECC_DSA_Sig(out, outlen, &r, &s);
01701 
01702    mp_clear(&r);
01703    mp_clear(&s);
01704    mp_clear(&p);
01705    mp_clear(&e);
01706 
01707    return err;
01708 }
01709 
01710 
01711 /**
01712   Free an ECC key from memory
01713   key   The key you wish to free
01714 */
01715 void ecc_free(ecc_key* key)
01716 {
01717    if (key == NULL)
01718        return;
01719 
01720    mp_clear(&key->pubkey.x);
01721    mp_clear(&key->pubkey.y);
01722    mp_clear(&key->pubkey.z);
01723    mp_clear(&key->k);
01724 }
01725 
01726 
01727 #ifdef USE_FAST_MATH
01728     #define GEN_MEM_ERR FP_MEM
01729 #else
01730     #define GEN_MEM_ERR MP_MEM
01731 #endif
01732 
01733 #ifdef ECC_SHAMIR
01734 
01735 /** Computes kA*A + kB*B = C using Shamir's Trick
01736   A        First point to multiply
01737   kA       What to multiple A by
01738   B        Second point to multiply
01739   kB       What to multiple B by
01740   C        [out] Destination point (can overlap with A or B)
01741   modulus  Modulus for curve 
01742   return MP_OKAY on success
01743 */
01744 #ifdef FP_ECC
01745 static int normal_ecc_mul2add(ecc_point* A, mp_int* kA,
01746                              ecc_point* B, mp_int* kB,
01747                              ecc_point* C, mp_int* modulus)
01748 #else
01749 static int ecc_mul2add(ecc_point* A, mp_int* kA,
01750                     ecc_point* B, mp_int* kB,
01751                     ecc_point* C, mp_int* modulus)
01752 #endif
01753 {
01754   ecc_point*     precomp[16];
01755   unsigned       bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;
01756   unsigned char* tA;
01757   unsigned char* tB;
01758   int            err = MP_OKAY, first;
01759   int            muInit    = 0;
01760   int            tableInit = 0;
01761   mp_digit mp;
01762   mp_int   mu;
01763  
01764   /* argchks */
01765   if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || 
01766                    modulus == NULL)
01767     return ECC_BAD_ARG_E;
01768 
01769 
01770   /* allocate memory */
01771   tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01772   if (tA == NULL) {
01773      return GEN_MEM_ERR;
01774   }
01775   tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01776   if (tB == NULL) {
01777      XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01778      return GEN_MEM_ERR;
01779   }
01780   XMEMSET(tA, 0, ECC_BUFSIZE);
01781   XMEMSET(tB, 0, ECC_BUFSIZE);
01782 
01783   /* get sizes */
01784   lenA = mp_unsigned_bin_size(kA);
01785   lenB = mp_unsigned_bin_size(kB);
01786   len  = MAX(lenA, lenB);
01787 
01788   /* sanity check */
01789   if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) {
01790      err = BAD_FUNC_ARG;
01791   }
01792 
01793   if (err == MP_OKAY) {
01794     /* extract and justify kA */
01795     err = mp_to_unsigned_bin(kA, (len - lenA) + tA);
01796 
01797     /* extract and justify kB */
01798     if (err == MP_OKAY)
01799         err = mp_to_unsigned_bin(kB, (len - lenB) + tB);
01800 
01801     /* allocate the table */
01802     if (err == MP_OKAY) {
01803         for (x = 0; x < 16; x++) {
01804             precomp[x] = ecc_new_point();
01805             if (precomp[x] == NULL) {
01806                 for (y = 0; y < x; ++y) {
01807                     ecc_del_point(precomp[y]);
01808                 }
01809                 err = GEN_MEM_ERR;
01810                 break;
01811             }
01812         }
01813     }
01814   }
01815 
01816   if (err == MP_OKAY)
01817     tableInit = 1;
01818 
01819   if (err == MP_OKAY)
01820    /* init montgomery reduction */
01821    err = mp_montgomery_setup(modulus, &mp);
01822 
01823   if (err == MP_OKAY)
01824     err = mp_init(&mu);
01825   if (err == MP_OKAY)
01826     muInit = 1;
01827 
01828   if (err == MP_OKAY)
01829     err = mp_montgomery_calc_normalization(&mu, modulus);
01830 
01831   if (err == MP_OKAY)
01832     /* copy ones ... */
01833     err = mp_mulmod(&A->x, &mu, modulus, &precomp[1]->x);
01834 
01835   if (err == MP_OKAY)
01836     err = mp_mulmod(&A->y, &mu, modulus, &precomp[1]->y);
01837   if (err == MP_OKAY)
01838     err = mp_mulmod(&A->z, &mu, modulus, &precomp[1]->z);
01839 
01840   if (err == MP_OKAY)
01841     err = mp_mulmod(&B->x, &mu, modulus, &precomp[1<<2]->x);
01842   if (err == MP_OKAY)
01843     err = mp_mulmod(&B->y, &mu, modulus, &precomp[1<<2]->y);
01844   if (err == MP_OKAY)
01845     err = mp_mulmod(&B->z, &mu, modulus, &precomp[1<<2]->z);
01846 
01847   if (err == MP_OKAY)
01848     /* precomp [i,0](A + B) table */
01849     err = ecc_projective_dbl_point(precomp[1], precomp[2], modulus, &mp);
01850 
01851   if (err == MP_OKAY)
01852     err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3],
01853                                    modulus, &mp);
01854   if (err == MP_OKAY)
01855     /* precomp [0,i](A + B) table */
01856     err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], modulus, &mp);
01857 
01858   if (err == MP_OKAY)
01859     err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2],
01860                                    modulus, &mp);
01861 
01862   if (err == MP_OKAY) {
01863     /* precomp [i,j](A + B) table (i != 0, j != 0) */
01864     for (x = 1; x < 4; x++) {
01865         for (y = 1; y < 4; y++) {
01866             if (err == MP_OKAY)
01867                 err = ecc_projective_add_point(precomp[x], precomp[(y<<2)],
01868                                                precomp[x+(y<<2)], modulus, &mp);
01869         }
01870     } 
01871   }  
01872 
01873   if (err == MP_OKAY) {
01874     nibble  = 3;
01875     first   = 1;
01876     bitbufA = tA[0];
01877     bitbufB = tB[0];
01878 
01879     /* for every byte of the multiplicands */
01880     for (x = -1;; ) {
01881         /* grab a nibble */
01882         if (++nibble == 4) {
01883             ++x; if (x == len) break;
01884             bitbufA = tA[x];
01885             bitbufB = tB[x];
01886             nibble  = 0;
01887         }
01888 
01889         /* extract two bits from both, shift/update */
01890         nA = (bitbufA >> 6) & 0x03;
01891         nB = (bitbufB >> 6) & 0x03;
01892         bitbufA = (bitbufA << 2) & 0xFF;   
01893         bitbufB = (bitbufB << 2) & 0xFF;   
01894 
01895         /* if both zero, if first, continue */
01896         if ((nA == 0) && (nB == 0) && (first == 1)) {
01897             continue;
01898         }
01899 
01900         /* double twice, only if this isn't the first */
01901         if (first == 0) {
01902             /* double twice */
01903             if (err == MP_OKAY)
01904                 err = ecc_projective_dbl_point(C, C, modulus, &mp);
01905             if (err == MP_OKAY)
01906                 err = ecc_projective_dbl_point(C, C, modulus, &mp);
01907             else
01908                 break;
01909         }
01910 
01911         /* if not both zero */
01912         if ((nA != 0) || (nB != 0)) {
01913             if (first == 1) {
01914                 /* if first, copy from table */
01915                 first = 0;
01916                 if (err == MP_OKAY)
01917                     err = mp_copy(&precomp[nA + (nB<<2)]->x, &C->x);
01918 
01919                 if (err == MP_OKAY)
01920                     err = mp_copy(&precomp[nA + (nB<<2)]->y, &C->y);
01921 
01922                 if (err == MP_OKAY)
01923                     err = mp_copy(&precomp[nA + (nB<<2)]->z, &C->z);
01924                 else
01925                     break;
01926             } else {
01927                 /* if not first, add from table */
01928                 if (err == MP_OKAY)
01929                     err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C,
01930                                                    modulus, &mp);
01931                 else
01932                     break;
01933             }
01934         }
01935     }
01936   }
01937 
01938   if (err == MP_OKAY)
01939     /* reduce to affine */
01940     err = ecc_map(C, modulus, &mp);
01941 
01942   /* clean up */
01943   if (muInit)
01944     mp_clear(&mu);
01945 
01946   if (tableInit) {
01947     for (x = 0; x < 16; x++) {
01948        ecc_del_point(precomp[x]);
01949     }
01950   }
01951 #ifdef ECC_CLEAN_STACK
01952    XMEMSET(tA, 0, ECC_BUFSIZE);
01953    XMEMSET(tB, 0, ECC_BUFSIZE);
01954 #endif
01955    XFREE(tA, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01956    XFREE(tB, NULL, DYNAMIC_TYPE_TMP_BUFFER);
01957 
01958    return err;
01959 }
01960 
01961 
01962 #endif /* ECC_SHAMIR */
01963 
01964 
01965 
01966 /* verify 
01967  *
01968  * w  = s^-1 mod n
01969  * u1 = xw 
01970  * u2 = rw
01971  * X = u1*G + u2*Q
01972  * v = X_x1 mod n
01973  * accept if v == r
01974  */
01975 
01976 /**
01977    Verify an ECC signature
01978    sig         The signature to verify
01979    siglen      The length of the signature (octets)
01980    hash        The hash (message digest) that was signed
01981    hashlen     The length of the hash (octets)
01982    stat        Result of signature, 1==valid, 0==invalid
01983    key         The corresponding public ECC key
01984    return      MP_OKAY if successful (even if the signature is not valid)
01985 */
01986 int ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
01987                     word32 hashlen, int* stat, ecc_key* key)
01988 {
01989    ecc_point    *mG, *mQ;
01990    mp_int        r;
01991    mp_int        s;
01992    mp_int        v;
01993    mp_int        w;
01994    mp_int        u1;
01995    mp_int        u2;
01996    mp_int        e;
01997    mp_int        p;
01998    mp_int        m;
01999    int           err;
02000 
02001    if (sig == NULL || hash == NULL || stat == NULL || key == NULL)
02002        return ECC_BAD_ARG_E; 
02003 
02004    /* default to invalid signature */
02005    *stat = 0;
02006 
02007    /* is the IDX valid ?  */
02008    if (ecc_is_valid_idx(key->idx) != 1) {
02009       return ECC_BAD_ARG_E;
02010    }
02011 
02012    /* allocate ints */
02013    if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) {
02014       return MEMORY_E;
02015    }
02016 
02017    if ((err = mp_init(&m)) != MP_OKAY) {
02018       mp_clear(&v);
02019       mp_clear(&w);
02020       mp_clear(&u1);
02021       mp_clear(&u2);
02022       mp_clear(&p);
02023       mp_clear(&e);
02024       return MEMORY_E;
02025    }
02026 
02027    /* allocate points */
02028    mG = ecc_new_point();
02029    mQ = ecc_new_point();
02030    if (mQ  == NULL || mG == NULL)
02031       err = MEMORY_E;
02032 
02033    /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s.
02034     * If either of those don't allocate correctly, none of
02035     * the rest of this function will execute, and everything
02036     * gets cleaned up at the end. */
02037    XMEMSET(&r, 0, sizeof(r));
02038    XMEMSET(&s, 0, sizeof(s));
02039    if (err == MP_OKAY) 
02040        err = DecodeECC_DSA_Sig(sig, siglen, &r, &s);
02041 
02042    /* get the order */
02043    if (err == MP_OKAY)
02044        err = mp_read_radix(&p, (char *)key->dp->order, 16);
02045 
02046    /* get the modulus */
02047    if (err == MP_OKAY)
02048        err = mp_read_radix(&m, (char *)key->dp->prime, 16);
02049 
02050    /* check for zero */
02051    if (err == MP_OKAY) {
02052        if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT ||
02053                                              mp_cmp(&s, &p) != MP_LT)
02054            err = MP_ZERO_E; 
02055    }
02056    /* read hash */
02057    if (err == MP_OKAY) {
02058        /* we may need to truncate if hash is longer than key size */
02059        unsigned int orderBits = mp_count_bits(&p);
02060 
02061        /* truncate down to byte size, may be all that's needed */
02062        if ( (CYASSL_BIT_SIZE * hashlen) > orderBits)
02063            hashlen = (orderBits + CYASSL_BIT_SIZE - 1)/CYASSL_BIT_SIZE;
02064        err = mp_read_unsigned_bin(&e, hash, hashlen);
02065 
02066        /* may still need bit truncation too */
02067        if (err == MP_OKAY && (CYASSL_BIT_SIZE * hashlen) > orderBits)
02068            mp_rshb(&e, CYASSL_BIT_SIZE - (orderBits & 0x7));
02069    }
02070 
02071    /*  w  = s^-1 mod n */
02072    if (err == MP_OKAY)
02073        err = mp_invmod(&s, &p, &w);
02074 
02075    /* u1 = ew */
02076    if (err == MP_OKAY)
02077        err = mp_mulmod(&e, &w, &p, &u1);
02078 
02079    /* u2 = rw */
02080    if (err == MP_OKAY)
02081        err = mp_mulmod(&r, &w, &p, &u2);
02082 
02083    /* find mG and mQ */
02084    if (err == MP_OKAY)
02085        err = mp_read_radix(&mG->x, (char *)key->dp->Gx, 16);
02086 
02087    if (err == MP_OKAY)
02088        err = mp_read_radix(&mG->y, (char *)key->dp->Gy, 16);
02089    if (err == MP_OKAY)
02090        mp_set(&mG->z, 1);
02091 
02092    if (err == MP_OKAY)
02093        err = mp_copy(&key->pubkey.x, &mQ->x);
02094    if (err == MP_OKAY)
02095        err = mp_copy(&key->pubkey.y, &mQ->y);
02096    if (err == MP_OKAY)
02097        err = mp_copy(&key->pubkey.z, &mQ->z);
02098 
02099 #ifndef ECC_SHAMIR
02100     {
02101        mp_digit      mp;
02102 
02103        /* compute u1*mG + u2*mQ = mG */
02104        if (err == MP_OKAY)
02105            err = ecc_mulmod(&u1, mG, mG, &m, 0);
02106        if (err == MP_OKAY)
02107            err = ecc_mulmod(&u2, mQ, mQ, &m, 0);
02108   
02109        /* find the montgomery mp */
02110        if (err == MP_OKAY)
02111            err = mp_montgomery_setup(&m, &mp);
02112 
02113        /* add them */
02114        if (err == MP_OKAY)
02115            err = ecc_projective_add_point(mQ, mG, mG, &m, &mp);
02116    
02117        /* reduce */
02118        if (err == MP_OKAY)
02119            err = ecc_map(mG, &m, &mp);
02120     }
02121 #else
02122        /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
02123        if (err == MP_OKAY)
02124            err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &m);
02125 #endif /* ECC_SHAMIR */ 
02126 
02127    /* v = X_x1 mod n */
02128    if (err == MP_OKAY)
02129        err = mp_mod(&mG->x, &p, &v);
02130 
02131    /* does v == r */
02132    if (err == MP_OKAY) {
02133        if (mp_cmp(&v, &r) == MP_EQ)
02134            *stat = 1;
02135    }
02136 
02137    ecc_del_point(mG);
02138    ecc_del_point(mQ);
02139 
02140    mp_clear(&r);
02141    mp_clear(&s);
02142    mp_clear(&v);
02143    mp_clear(&w);
02144    mp_clear(&u1);
02145    mp_clear(&u2);
02146    mp_clear(&p);
02147    mp_clear(&e);
02148    mp_clear(&m);
02149 
02150    return err;
02151 }
02152 
02153 
02154 /* export public ECC key in ANSI X9.63 format */
02155 int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
02156 {
02157 #ifdef CYASSL_SMALL_STACK
02158    byte*  buf;
02159 #else
02160    byte   buf[ECC_BUFSIZE];
02161 #endif
02162    word32 numlen;
02163    int    ret = MP_OKAY;
02164 
02165    /* return length needed only */
02166    if (key != NULL && out == NULL && outLen != NULL) {
02167       numlen = key->dp->size;
02168       *outLen = 1 + 2*numlen;
02169       return LENGTH_ONLY_E;
02170    }
02171 
02172    if (key == NULL || out == NULL || outLen == NULL)
02173       return ECC_BAD_ARG_E;
02174 
02175    if (ecc_is_valid_idx(key->idx) == 0) {
02176       return ECC_BAD_ARG_E;
02177    }
02178    numlen = key->dp->size;
02179 
02180    if (*outLen < (1 + 2*numlen)) {
02181       *outLen = 1 + 2*numlen;
02182       return BUFFER_E;
02183    }
02184 
02185    /* store byte 0x04 */
02186    out[0] = 0x04;
02187 
02188 #ifdef CYASSL_SMALL_STACK
02189    buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
02190    if (buf == NULL)
02191       return MEMORY_E;
02192 #endif
02193 
02194    do {
02195       /* pad and store x */
02196       XMEMSET(buf, 0, ECC_BUFSIZE);
02197       ret = mp_to_unsigned_bin(&key->pubkey.x,
02198                          buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
02199       if (ret != MP_OKAY)
02200          break;
02201       XMEMCPY(out+1, buf, numlen);
02202 
02203       /* pad and store y */
02204       XMEMSET(buf, 0, ECC_BUFSIZE);
02205       ret = mp_to_unsigned_bin(&key->pubkey.y,
02206                          buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y)));
02207       if (ret != MP_OKAY)
02208          break;
02209       XMEMCPY(out+1+numlen, buf, numlen);
02210 
02211       *outLen = 1 + 2*numlen;
02212    } while (0);
02213 
02214 #ifdef CYASSL_SMALL_STACK
02215    XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
02216 #endif
02217 
02218    return ret;
02219 }
02220 
02221 
02222 /* export public ECC key in ANSI X9.63 format, extended with
02223  * compression option */
02224 int ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, int compressed)
02225 {
02226     if (compressed == 0)
02227         return ecc_export_x963(key, out, outLen);
02228 #ifdef HAVE_COMP_KEY
02229     else
02230         return ecc_export_x963_compressed(key, out, outLen);
02231 #endif
02232 
02233     return NOT_COMPILED_IN;
02234 }
02235 
02236 
02237 /* import public ECC key in ANSI X9.63 format */
02238 int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
02239 {
02240    int x, err;
02241    int compressed = 0;
02242    
02243    if (in == NULL || key == NULL)
02244        return ECC_BAD_ARG_E;
02245 
02246    /* must be odd */
02247    if ((inLen & 1) == 0) {
02248       return ECC_BAD_ARG_E;
02249    }
02250 
02251    /* init key */
02252    if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
02253                      NULL, NULL) != MP_OKAY) {
02254       return MEMORY_E;
02255    }
02256    err = MP_OKAY;
02257 
02258    /* check for 4, 2, or 3 */
02259    if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
02260       err = ASN_PARSE_E;
02261    }
02262 
02263    if (in[0] == 0x02 || in[0] == 0x03) {
02264 #ifdef HAVE_COMP_KEY
02265        compressed = 1;
02266 #else
02267        err = NOT_COMPILED_IN;
02268 #endif
02269    }
02270 
02271    if (err == MP_OKAY) {
02272       /* determine the idx */
02273 
02274       if (compressed)
02275           inLen = (inLen-1)*2 + 1;  /* used uncompressed len */
02276 
02277       for (x = 0; ecc_sets[x].size != 0; x++) {
02278          if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) {
02279             break;
02280          }
02281       }
02282       if (ecc_sets[x].size == 0) {
02283          err = ASN_PARSE_E;
02284       } else {
02285           /* set the idx */
02286           key->idx  = x;
02287           key->dp = &ecc_sets[x];
02288           key->type = ECC_PUBLICKEY;
02289       }
02290    }
02291 
02292    /* read data */
02293    if (err == MP_OKAY)
02294        err = mp_read_unsigned_bin(&key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
02295 
02296 #ifdef HAVE_COMP_KEY
02297    if (err == MP_OKAY && compressed == 1) {   /* build y */
02298         mp_int t1, t2, prime, a, b;
02299 
02300         if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY)
02301             err = MEMORY_E;
02302 
02303         /* load prime */
02304         if (err == MP_OKAY)
02305             err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
02306 
02307         /* load a */
02308         if (err == MP_OKAY)
02309             err = mp_read_radix(&a, (char *)key->dp->Af, 16);
02310 
02311         /* load b */
02312         if (err == MP_OKAY)
02313             err = mp_read_radix(&b, (char *)key->dp->Bf, 16);
02314 
02315         /* compute x^3 */
02316         if (err == MP_OKAY)
02317             err = mp_sqr(&key->pubkey.x, &t1);
02318 
02319         if (err == MP_OKAY)
02320             err = mp_mulmod(&t1, &key->pubkey.x, &prime, &t1);
02321 
02322         /* compute x^3 + a*x */
02323         if (err == MP_OKAY)
02324             err = mp_mulmod(&a, &key->pubkey.x, &prime, &t2);
02325 
02326         if (err == MP_OKAY)
02327             err = mp_add(&t1, &t2, &t1);
02328 
02329         /* compute x^3 + a*x + b */
02330         if (err == MP_OKAY)
02331             err = mp_add(&t1, &b, &t1);
02332 
02333         /* compute sqrt(x^3 + a*x + b) */
02334         if (err == MP_OKAY)
02335             err = mp_sqrtmod_prime(&t1, &prime, &t2);
02336 
02337         /* adjust y */
02338         if (err == MP_OKAY) {
02339             if ((mp_isodd(&t2) && in[0] == 0x03) ||
02340                (!mp_isodd(&t2) && in[0] == 0x02)) {
02341                 err = mp_mod(&t2, &prime, &key->pubkey.y);
02342             }
02343             else {
02344                 err = mp_submod(&prime, &t2, &prime, &key->pubkey.y);
02345             }
02346         }
02347 
02348         mp_clear(&a);
02349         mp_clear(&b);
02350         mp_clear(&prime);
02351         mp_clear(&t2);
02352         mp_clear(&t1);
02353    }
02354 #endif
02355 
02356    if (err == MP_OKAY && compressed == 0)
02357        err = mp_read_unsigned_bin(&key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
02358                                   (inLen-1)>>1);
02359    if (err == MP_OKAY)
02360        mp_set(&key->pubkey.z, 1);
02361 
02362    if (err != MP_OKAY) {
02363        mp_clear(&key->pubkey.x);
02364        mp_clear(&key->pubkey.y);
02365        mp_clear(&key->pubkey.z);
02366        mp_clear(&key->k);
02367    }
02368 
02369    return err;
02370 }
02371 
02372 
02373 /* export ecc private key only raw, outLen is in/out size 
02374    return MP_OKAY on success */
02375 int ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
02376 {
02377    word32 numlen;
02378 
02379    if (key == NULL || out == NULL || outLen == NULL)
02380        return ECC_BAD_ARG_E;
02381 
02382    if (ecc_is_valid_idx(key->idx) == 0) {
02383       return ECC_BAD_ARG_E;
02384    }
02385    numlen = key->dp->size;
02386 
02387    if (*outLen < numlen) {
02388       *outLen = numlen;
02389       return BUFFER_E;
02390    }
02391    *outLen = numlen; 
02392    XMEMSET(out, 0, *outLen);
02393    return mp_to_unsigned_bin(&key->k, out + (numlen -
02394                                              mp_unsigned_bin_size(&key->k)));
02395 }
02396 
02397 
02398 /* ecc private key import, public key in ANSI X9.63 format, private raw */
02399 int ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
02400                            word32 pubSz, ecc_key* key)
02401 {
02402     int ret = ecc_import_x963(pub, pubSz, key);
02403     if (ret != 0)
02404         return ret;
02405 
02406     key->type = ECC_PRIVATEKEY;
02407 
02408     return mp_read_unsigned_bin(&key->k, priv, privSz);
02409 }
02410 
02411 /**
02412    Convert ECC R,S to signature
02413    r       R component of signature
02414    s       S component of signature
02415    out     DER-encoded ECDSA signature
02416    outlen  [in/out] output buffer size, output signature size
02417    return  MP_OKAY on success
02418 */
02419 int ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
02420 {
02421     int err;
02422     mp_int rtmp;
02423     mp_int stmp;
02424 
02425     if (r == NULL || s == NULL || out == NULL || outlen == NULL)
02426         return ECC_BAD_ARG_E;
02427 
02428     err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL);
02429     if (err != MP_OKAY)
02430         return err;
02431 
02432     err = mp_read_radix(&rtmp, r, 16);
02433     if (err == MP_OKAY)
02434         err = mp_read_radix(&stmp, s, 16);
02435 
02436     /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
02437     if (err == MP_OKAY)
02438         err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp);
02439 
02440     if (err == MP_OKAY) {
02441         if (mp_iszero(&rtmp) || mp_iszero(&stmp))
02442             err = MP_ZERO_E;
02443     }
02444 
02445     mp_clear(&rtmp);
02446     mp_clear(&stmp);
02447 
02448     return err;
02449 }
02450 
02451 /**
02452    Import raw ECC key
02453    key       The destination ecc_key structure
02454    qx        x component of base point, as ASCII hex string
02455    qy        y component of base point, as ASCII hex string
02456    d         private key, as ASCII hex string
02457    curveName ECC curve name, from ecc_sets[]
02458    return    MP_OKAY on success
02459 */
02460 int ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
02461                    const char* d, const char* curveName)
02462 {
02463     int err, x;
02464 
02465     if (key == NULL || qx == NULL || qy == NULL || d == NULL ||
02466         curveName == NULL)
02467         return ECC_BAD_ARG_E;
02468 
02469     /* init key */
02470     if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
02471                       NULL, NULL) != MP_OKAY) {
02472         return MEMORY_E;
02473     }
02474     err = MP_OKAY;
02475 
02476     /* read Qx */
02477     if (err == MP_OKAY)
02478         err = mp_read_radix(&key->pubkey.x, qx, 16);
02479 
02480     /* read Qy */
02481     if (err == MP_OKAY)
02482         err = mp_read_radix(&key->pubkey.y, qy, 16);
02483 
02484     if (err == MP_OKAY)
02485         mp_set(&key->pubkey.z, 1);
02486 
02487     /* read and set the curve */
02488     if (err == MP_OKAY) {
02489         for (x = 0; ecc_sets[x].size != 0; x++) {
02490             if (XSTRNCMP(ecc_sets[x].name, curveName,
02491                          XSTRLEN(curveName)) == 0) {
02492                 break;
02493             }
02494         }
02495         if (ecc_sets[x].size == 0) {
02496             err = ASN_PARSE_E;
02497         } else {
02498             /* set the curve */
02499             key->idx = x;
02500             key->dp = &ecc_sets[x];
02501             key->type = ECC_PUBLICKEY;
02502         }
02503     }
02504 
02505     /* import private key */
02506     if (err == MP_OKAY) {
02507         key->type = ECC_PRIVATEKEY;
02508         err = mp_read_radix(&key->k, d, 16);
02509     }
02510 
02511     if (err != MP_OKAY) {
02512         mp_clear(&key->pubkey.x);
02513         mp_clear(&key->pubkey.y);
02514         mp_clear(&key->pubkey.z);
02515         mp_clear(&key->k);
02516     }
02517 
02518     return err;
02519 }
02520 
02521 
02522 /* key size in octets */
02523 int ecc_size(ecc_key* key)
02524 {
02525     if (key == NULL) return 0;
02526 
02527     return key->dp->size;
02528 }
02529 
02530 
02531 /* worst case estimate, check actual return from ecc_sign_hash for actual value
02532    of signature size in octets */
02533 int ecc_sig_size(ecc_key* key)
02534 {
02535     int sz = ecc_size(key);
02536     if (sz < 0)
02537         return sz;
02538 
02539     return sz * 2 + SIG_HEADER_SZ + 4;  /* (4) worst case estimate */
02540 }
02541 
02542 
02543 #ifdef FP_ECC
02544 
02545 /* fixed point ECC cache */
02546 /* number of entries in the cache */
02547 #ifndef FP_ENTRIES
02548     #define FP_ENTRIES 16
02549 #endif
02550 
02551 /* number of bits in LUT */
02552 #ifndef FP_LUT
02553     #define FP_LUT     8U
02554 #endif
02555 
02556 #ifdef ECC_SHAMIR
02557     /* Sharmir requires a bigger LUT, TAO */
02558     #if (FP_LUT > 12) || (FP_LUT < 4)
02559         #error FP_LUT must be between 4 and 12 inclusively
02560     #endif
02561 #else
02562     #if (FP_LUT > 12) || (FP_LUT < 2)
02563         #error FP_LUT must be between 2 and 12 inclusively
02564     #endif
02565 #endif
02566 
02567 
02568 /** Our FP cache */
02569 typedef struct {
02570    ecc_point* g;               /* cached COPY of base point */
02571    ecc_point* LUT[1U<<FP_LUT]; /* fixed point lookup */ 
02572    mp_int     mu;              /* copy of the montgomery constant */
02573    int        lru_count;       /* amount of times this entry has been used */
02574    int        lock;            /* flag to indicate cache eviction */
02575                                /* permitted (0) or not (1) */
02576 } fp_cache_t;
02577 
02578 /* if HAVE_THREAD_LS this cache is per thread, no locking needed */
02579 static THREAD_LS_T fp_cache_t fp_cache[FP_ENTRIES];
02580 
02581 #ifndef HAVE_THREAD_LS
02582     static volatile int initMutex = 0;  /* prevent multiple mutex inits */
02583     static CyaSSL_Mutex ecc_fp_lock;
02584 #endif /* HAVE_THREAD_LS */
02585 
02586 /* simple table to help direct the generation of the LUT */
02587 static const struct {
02588    int ham, terma, termb;
02589 } lut_orders[] = {
02590    { 0, 0, 0 }, { 1, 0, 0 }, { 1, 0, 0 }, { 2, 1, 2 }, { 1, 0, 0 }, { 2, 1, 4 }, { 2, 2, 4 }, { 3, 3, 4 }, 
02591    { 1, 0, 0 }, { 2, 1, 8 }, { 2, 2, 8 }, { 3, 3, 8 }, { 2, 4, 8 }, { 3, 5, 8 }, { 3, 6, 8 }, { 4, 7, 8 }, 
02592    { 1, 0, 0 }, { 2, 1, 16 }, { 2, 2, 16 }, { 3, 3, 16 }, { 2, 4, 16 }, { 3, 5, 16 }, { 3, 6, 16 }, { 4, 7, 16 }, 
02593    { 2, 8, 16 }, { 3, 9, 16 }, { 3, 10, 16 }, { 4, 11, 16 }, { 3, 12, 16 }, { 4, 13, 16 }, { 4, 14, 16 }, { 5, 15, 16 }, 
02594    { 1, 0, 0 }, { 2, 1, 32 }, { 2, 2, 32 }, { 3, 3, 32 }, { 2, 4, 32 }, { 3, 5, 32 }, { 3, 6, 32 }, { 4, 7, 32 }, 
02595    { 2, 8, 32 }, { 3, 9, 32 }, { 3, 10, 32 }, { 4, 11, 32 }, { 3, 12, 32 }, { 4, 13, 32 }, { 4, 14, 32 }, { 5, 15, 32 }, 
02596    { 2, 16, 32 }, { 3, 17, 32 }, { 3, 18, 32 }, { 4, 19, 32 }, { 3, 20, 32 }, { 4, 21, 32 }, { 4, 22, 32 }, { 5, 23, 32 }, 
02597    { 3, 24, 32 }, { 4, 25, 32 }, { 4, 26, 32 }, { 5, 27, 32 }, { 4, 28, 32 }, { 5, 29, 32 }, { 5, 30, 32 }, { 6, 31, 32 }, 
02598 #if FP_LUT > 6
02599    { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, 
02600    { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, 
02601    { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, 
02602    { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, 
02603    { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, 
02604    { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, 
02605    { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, 
02606    { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, 
02607 #if FP_LUT > 7
02608    { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, 
02609    { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, 
02610    { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, 
02611    { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, 
02612    { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, 
02613    { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, 
02614    { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, 
02615    { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, 
02616    { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, 
02617    { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, 
02618    { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, 
02619    { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, 
02620    { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, 
02621    { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, 
02622    { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, 
02623    { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, 
02624 #if FP_LUT > 8
02625    { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, 
02626    { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, 
02627    { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, 
02628    { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, 
02629    { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, 
02630    { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, 
02631    { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, 
02632    { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, 
02633    { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, 
02634    { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, 
02635    { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, 
02636    { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, 
02637    { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, 
02638    { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, 
02639    { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, 
02640    { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, 
02641    { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, 
02642    { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, 
02643    { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, 
02644    { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, 
02645    { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, 
02646    { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, 
02647    { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, 
02648    { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, 
02649    { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, 
02650    { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, 
02651    { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, 
02652    { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, 
02653    { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, 
02654    { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, 
02655    { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, 
02656    { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, 
02657 #if FP_LUT > 9
02658    { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, 
02659    { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, 
02660    { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, 
02661    { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, 
02662    { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, 
02663    { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, 
02664    { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, 
02665    { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, 
02666    { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, 
02667    { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, 
02668    { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, 
02669    { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, 
02670    { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, 
02671    { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, 
02672    { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, 
02673    { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, 
02674    { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, 
02675    { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, 
02676    { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, 
02677    { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, 
02678    { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, 
02679    { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, 
02680    { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, 
02681    { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, 
02682    { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, 
02683    { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, 
02684    { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, 
02685    { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, 
02686    { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, 
02687    { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, 
02688    { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, 
02689    { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, 
02690    { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, 
02691    { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, 
02692    { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, 
02693    { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, 
02694    { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, 
02695    { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, 
02696    { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, 
02697    { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, 
02698    { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, 
02699    { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, 
02700    { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, 
02701    { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, 
02702    { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, 
02703    { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, 
02704    { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, 
02705    { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, 
02706    { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, 
02707    { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, 
02708    { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, 
02709    { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, 
02710    { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, 
02711    { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, 
02712    { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, 
02713    { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, 
02714    { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, 
02715    { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, 
02716    { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, 
02717    { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, 
02718    { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, 
02719    { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, 
02720    { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, 
02721    { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, 
02722 #if FP_LUT > 10
02723    { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, 
02724    { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, 
02725    { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, 
02726    { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, 
02727    { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, 
02728    { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, 
02729    { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, 
02730    { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, 
02731    { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, 
02732    { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, 
02733    { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, 
02734    { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, 
02735    { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, 
02736    { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, 
02737    { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, 
02738    { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, 
02739    { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, 
02740    { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, 
02741    { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, 
02742    { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, 
02743    { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, 
02744    { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, 
02745    { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, 
02746    { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, 
02747    { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, 
02748    { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, 
02749    { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, 
02750    { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, 
02751    { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, 
02752    { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, 
02753    { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, 
02754    { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, 
02755    { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, 
02756    { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, 
02757    { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, 
02758    { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, 
02759    { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, 
02760    { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, 
02761    { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, 
02762    { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, 
02763    { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, 
02764    { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, 
02765    { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, 
02766    { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, 
02767    { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, 
02768    { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, 
02769    { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, 
02770    { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, 
02771    { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, 
02772    { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, 
02773    { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, 
02774    { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, 
02775    { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, 
02776    { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, 
02777    { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, 
02778    { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, 
02779    { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, 
02780    { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, 
02781    { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, 
02782    { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, 
02783    { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, 
02784    { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, 
02785    { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, 
02786    { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, 
02787    { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, 
02788    { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, 
02789    { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, 
02790    { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, 
02791    { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, 
02792    { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, 
02793    { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, 
02794    { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, 
02795    { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, 
02796    { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, 
02797    { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, 
02798    { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, 
02799    { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, 
02800    { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, 
02801    { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, 
02802    { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, 
02803    { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, 
02804    { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, 
02805    { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, 
02806    { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, 
02807    { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, 
02808    { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, 
02809    { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, 
02810    { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, 
02811    { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, 
02812    { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, 
02813    { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, 
02814    { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, 
02815    { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, 
02816    { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, 
02817    { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, 
02818    { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, 
02819    { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, 
02820    { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, 
02821    { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, 
02822    { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, 
02823    { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, 
02824    { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, 
02825    { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, 
02826    { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, 
02827    { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, 
02828    { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, 
02829    { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, 
02830    { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, 
02831    { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, 
02832    { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, 
02833    { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, 
02834    { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, 
02835    { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, 
02836    { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, 
02837    { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, 
02838    { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, 
02839    { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, 
02840    { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, 
02841    { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, 
02842    { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, 
02843    { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, 
02844    { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, 
02845    { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, 
02846    { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, 
02847    { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, 
02848    { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, 
02849    { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, 
02850    { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, 
02851 #if FP_LUT > 11
02852    { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, 
02853    { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, 
02854    { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, 
02855    { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, 
02856    { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, 
02857    { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, 
02858    { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, 
02859    { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, 
02860    { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, 
02861    { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, 
02862    { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, 
02863    { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, 
02864    { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, 
02865    { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, 
02866    { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, 
02867    { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, 
02868    { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, 
02869    { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, 
02870    { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, 
02871    { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, 
02872    { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, 
02873    { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, 
02874    { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, 
02875    { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, 
02876    { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, 
02877    { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, 
02878    { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, 
02879    { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, 
02880    { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, 
02881    { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, 
02882    { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, 
02883    { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, 
02884    { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, 
02885    { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, 
02886    { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, 
02887    { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, 
02888    { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, 
02889    { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, 
02890    { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, 
02891    { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, 
02892    { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, 
02893    { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, 
02894    { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, 
02895    { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, 
02896    { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, 
02897    { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, 
02898    { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, 
02899    { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, 
02900    { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, 
02901    { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, 
02902    { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, 
02903    { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, 
02904    { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, 
02905    { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, 
02906    { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, 
02907    { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, 
02908    { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, 
02909    { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, 
02910    { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, 
02911    { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, 
02912    { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, 
02913    { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, 
02914    { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, 
02915    { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, 
02916    { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, 
02917    { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, 
02918    { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, 
02919    { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, 
02920    { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, 
02921    { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, 
02922    { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, 
02923    { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, 
02924    { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, 
02925    { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, 
02926    { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, 
02927    { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, 
02928    { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, 
02929    { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, 
02930    { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, 
02931    { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, 
02932    { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, 
02933    { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, 
02934    { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, 
02935    { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, 
02936    { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, 
02937    { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, 
02938    { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, 
02939    { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, 
02940    { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, 
02941    { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, 
02942    { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, 
02943    { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, 
02944    { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, 
02945    { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, 
02946    { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, 
02947    { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, 
02948    { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, 
02949    { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, 
02950    { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, 
02951    { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, 
02952    { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, 
02953    { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, 
02954    { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, 
02955    { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, 
02956    { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, 
02957    { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, 
02958    { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, 
02959    { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, 
02960    { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, 
02961    { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, 
02962    { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, 
02963    { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, 
02964    { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, 
02965    { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, 
02966    { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, 
02967    { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, 
02968    { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, 
02969    { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, 
02970    { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, 
02971    { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, 
02972    { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, 
02973    { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, 
02974    { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, 
02975    { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, 
02976    { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, 
02977    { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, 
02978    { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, 
02979    { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, 
02980    { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, 
02981    { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, 
02982    { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, 
02983    { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, 
02984    { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, 
02985    { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, 
02986    { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, 
02987    { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, 
02988    { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, 
02989    { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, 
02990    { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, 
02991    { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, 
02992    { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, 
02993    { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, 
02994    { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, 
02995    { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, 
02996    { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, 
02997    { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, 
02998    { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, 
02999    { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, 
03000    { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, 
03001    { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, 
03002    { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, 
03003    { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, 
03004    { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, 
03005    { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, 
03006    { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, 
03007    { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, 
03008    { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, 
03009    { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, 
03010    { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, 
03011    { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, 
03012    { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, 
03013    { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, 
03014    { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, 
03015    { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, 
03016    { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, 
03017    { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, 
03018    { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, 
03019    { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, 
03020    { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, 
03021    { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, 
03022    { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, 
03023    { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, 
03024    { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, 
03025    { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, 
03026    { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, 
03027    { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, 
03028    { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, 
03029    { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, 
03030    { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, 
03031    { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, 
03032    { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, 
03033    { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, 
03034    { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, 
03035    { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, 
03036    { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, 
03037    { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, 
03038    { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, 
03039    { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, 
03040    { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, 
03041    { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, 
03042    { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, 
03043    { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, 
03044    { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, 
03045    { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, 
03046    { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, 
03047    { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, 
03048    { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, 
03049    { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, 
03050    { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, 
03051    { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, 
03052    { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, 
03053    { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, 
03054    { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, 
03055    { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, 
03056    { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, 
03057    { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, 
03058    { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, 
03059    { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, 
03060    { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, 
03061    { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, 
03062    { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, 
03063    { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, 
03064    { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, 
03065    { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, 
03066    { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, 
03067    { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, 
03068    { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, 
03069    { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, 
03070    { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, 
03071    { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, 
03072    { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, 
03073    { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, 
03074    { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, 
03075    { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, 
03076    { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, 
03077    { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, 
03078    { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, 
03079    { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, 
03080    { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, 
03081    { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, 
03082    { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, 
03083    { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, 
03084    { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, 
03085    { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, 
03086    { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, 
03087    { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, 
03088    { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, 
03089    { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, 
03090    { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, 
03091    { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, 
03092    { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, 
03093    { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, 
03094    { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, 
03095    { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, 
03096    { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, 
03097    { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, 
03098    { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, 
03099    { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, 
03100    { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, 
03101    { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, 
03102    { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, 
03103    { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, 
03104    { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, 
03105    { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, 
03106    { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, 
03107    { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, 
03108 #endif
03109 #endif
03110 #endif
03111 #endif
03112 #endif
03113 #endif
03114 };
03115 
03116 /* find a hole and free as required, return -1 if no hole found */
03117 static int find_hole(void)
03118 {
03119    unsigned x;
03120    int      y, z;
03121    for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) {
03122        if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) {
03123           z = x;
03124           y = fp_cache[x].lru_count;
03125        }
03126    }
03127 
03128    /* decrease all */
03129    for (x = 0; x < FP_ENTRIES; x++) {
03130       if (fp_cache[x].lru_count > 3) {
03131          --(fp_cache[x].lru_count);
03132       }
03133    }
03134 
03135    /* free entry z */
03136    if (z >= 0 && fp_cache[z].g) {
03137       mp_clear(&fp_cache[z].mu);
03138       ecc_del_point(fp_cache[z].g);
03139       fp_cache[z].g  = NULL;
03140       for (x = 0; x < (1U<<FP_LUT); x++) {
03141          ecc_del_point(fp_cache[z].LUT[x]);
03142          fp_cache[z].LUT[x] = NULL;
03143       }
03144       fp_cache[z].lru_count = 0;
03145    }
03146    return z;
03147 }
03148 
03149 /* determine if a base is already in the cache and if so, where */
03150 static int find_base(ecc_point* g)
03151 {
03152    int x;
03153    for (x = 0; x < FP_ENTRIES; x++) {
03154       if (fp_cache[x].g != NULL && 
03155           mp_cmp(&fp_cache[x].g->x, &g->x) == MP_EQ && 
03156           mp_cmp(&fp_cache[x].g->y, &g->y) == MP_EQ && 
03157           mp_cmp(&fp_cache[x].g->z, &g->z) == MP_EQ) {
03158          break;
03159       }
03160    }
03161    if (x == FP_ENTRIES) {
03162       x = -1;
03163    }
03164    return x;
03165 }
03166 
03167 /* add a new base to the cache */
03168 static int add_entry(int idx, ecc_point *g)
03169 {
03170    unsigned x, y;
03171 
03172    /* allocate base and LUT */
03173    fp_cache[idx].g = ecc_new_point();
03174    if (fp_cache[idx].g == NULL) {
03175       return GEN_MEM_ERR;
03176    }
03177 
03178    /* copy x and y */
03179    if ((mp_copy(&g->x, &fp_cache[idx].g->x) != MP_OKAY) ||
03180        (mp_copy(&g->y, &fp_cache[idx].g->y) != MP_OKAY) ||
03181        (mp_copy(&g->z, &fp_cache[idx].g->z) != MP_OKAY)) {
03182       ecc_del_point(fp_cache[idx].g);
03183       fp_cache[idx].g = NULL;
03184       return GEN_MEM_ERR;
03185    }              
03186 
03187    for (x = 0; x < (1U<<FP_LUT); x++) {
03188       fp_cache[idx].LUT[x] = ecc_new_point();
03189       if (fp_cache[idx].LUT[x] == NULL) {
03190          for (y = 0; y < x; y++) {
03191             ecc_del_point(fp_cache[idx].LUT[y]);
03192             fp_cache[idx].LUT[y] = NULL;
03193          }
03194          ecc_del_point(fp_cache[idx].g);
03195          fp_cache[idx].g         = NULL;
03196          fp_cache[idx].lru_count = 0;
03197          return GEN_MEM_ERR;
03198       }
03199    }
03200    
03201    fp_cache[idx].lru_count = 0;
03202 
03203    return MP_OKAY;
03204 }
03205 
03206 /* build the LUT by spacing the bits of the input by #modulus/FP_LUT bits apart 
03207  * 
03208  * The algorithm builds patterns in increasing bit order by first making all 
03209  * single bit input patterns, then all two bit input patterns and so on
03210  */
03211 static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu)
03212 { 
03213    unsigned x, y, err, bitlen, lut_gap;
03214    mp_int tmp;
03215 
03216    if (mp_init(&tmp) != MP_OKAY)
03217        return GEN_MEM_ERR;
03218 
03219    /* sanity check to make sure lut_order table is of correct size,
03220       should compile out to a NOP if true */
03221    if ((sizeof(lut_orders) / sizeof(lut_orders[0])) < (1U<<FP_LUT)) {
03222        err = BAD_FUNC_ARG;
03223    }
03224    else {   
03225     /* get bitlen and round up to next multiple of FP_LUT */
03226     bitlen  = mp_unsigned_bin_size(modulus) << 3;
03227     x       = bitlen % FP_LUT;
03228     if (x) {
03229       bitlen += FP_LUT - x;
03230     }  
03231     lut_gap = bitlen / FP_LUT;
03232 
03233     /* init the mu */
03234     err = mp_init_copy(&fp_cache[idx].mu, mu);
03235    }
03236    
03237    /* copy base */
03238    if (err == MP_OKAY) {
03239      if ((mp_mulmod(&fp_cache[idx].g->x, mu, modulus,
03240                   &fp_cache[idx].LUT[1]->x) != MP_OKAY) || 
03241          (mp_mulmod(&fp_cache[idx].g->y, mu, modulus,
03242                   &fp_cache[idx].LUT[1]->y) != MP_OKAY) || 
03243          (mp_mulmod(&fp_cache[idx].g->z, mu, modulus,
03244                   &fp_cache[idx].LUT[1]->z) != MP_OKAY)) {
03245        err = MP_MULMOD_E; 
03246      }
03247    }
03248        
03249    /* make all single bit entries */
03250    for (x = 1; x < FP_LUT; x++) {
03251       if (err != MP_OKAY)
03252           break;
03253       if ((mp_copy(&fp_cache[idx].LUT[1<<(x-1)]->x,
03254                    &fp_cache[idx].LUT[1<<x]->x) != MP_OKAY) || 
03255           (mp_copy(&fp_cache[idx].LUT[1<<(x-1)]->y,
03256                    &fp_cache[idx].LUT[1<<x]->y) != MP_OKAY) || 
03257           (mp_copy(&fp_cache[idx].LUT[1<<(x-1)]->z,
03258                    &fp_cache[idx].LUT[1<<x]->z) != MP_OKAY)){
03259           err = MP_INIT_E;
03260           break;
03261       } else {
03262           
03263          /* now double it bitlen/FP_LUT times */
03264          for (y = 0; y < lut_gap; y++) {
03265              if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<<x],
03266                             fp_cache[idx].LUT[1<<x], modulus, mp)) != MP_OKAY) {
03267                  break;
03268              }
03269          }
03270      }
03271   }
03272       
03273    /* now make all entries in increase order of hamming weight */
03274    for (x = 2; x <= FP_LUT; x++) {
03275        if (err != MP_OKAY)
03276            break;
03277        for (y = 0; y < (1UL<<FP_LUT); y++) {
03278            if (err != MP_OKAY)
03279              break;
03280            if (lut_orders[y].ham != (int)x) continue;
03281                      
03282            /* perform the add */
03283            if ((err = ecc_projective_add_point(
03284                            fp_cache[idx].LUT[lut_orders[y].terma],
03285                            fp_cache[idx].LUT[lut_orders[y].termb],
03286                            fp_cache[idx].LUT[y], modulus, mp)) != MP_OKAY) {
03287               break;
03288            }
03289        }
03290    }
03291       
03292    /* now map all entries back to affine space to make point addition faster */
03293    for (x = 1; x < (1UL<<FP_LUT); x++) {
03294        if (err != MP_OKAY)
03295            break;
03296 
03297        /* convert z to normal from montgomery */
03298        err = mp_montgomery_reduce(&fp_cache[idx].LUT[x]->z, modulus, *mp);
03299  
03300        /* invert it */
03301        if (err == MP_OKAY)
03302          err = mp_invmod(&fp_cache[idx].LUT[x]->z, modulus,
03303                          &fp_cache[idx].LUT[x]->z);
03304 
03305        if (err == MP_OKAY)
03306          /* now square it */
03307          err = mp_sqrmod(&fp_cache[idx].LUT[x]->z, modulus, &tmp);
03308        
03309        if (err == MP_OKAY)
03310          /* fix x */
03311          err = mp_mulmod(&fp_cache[idx].LUT[x]->x, &tmp, modulus,
03312                          &fp_cache[idx].LUT[x]->x);
03313 
03314        if (err == MP_OKAY)
03315          /* get 1/z^3 */
03316          err = mp_mulmod(&tmp, &fp_cache[idx].LUT[x]->z, modulus, &tmp);
03317 
03318        if (err == MP_OKAY)
03319          /* fix y */
03320          err = mp_mulmod(&fp_cache[idx].LUT[x]->y, &tmp, modulus,
03321                          &fp_cache[idx].LUT[x]->y);
03322 
03323        if (err == MP_OKAY)
03324          /* free z */
03325          mp_clear(&fp_cache[idx].LUT[x]->z);
03326    }
03327    mp_clear(&tmp);
03328 
03329    if (err == MP_OKAY)
03330      return MP_OKAY;
03331 
03332    /* err cleanup */
03333    for (y = 0; y < (1U<<FP_LUT); y++) {
03334       ecc_del_point(fp_cache[idx].LUT[y]);
03335       fp_cache[idx].LUT[y] = NULL;
03336    }
03337    ecc_del_point(fp_cache[idx].g);
03338    fp_cache[idx].g         = NULL;
03339    fp_cache[idx].lru_count = 0;
03340    mp_clear(&fp_cache[idx].mu);
03341    mp_clear(&tmp);
03342 
03343    return err;
03344 }
03345 
03346 /* perform a fixed point ECC mulmod */
03347 static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus,
03348                         mp_digit* mp, int map)
03349 {
03350 #define KB_SIZE 128
03351 
03352 #ifdef CYASSL_SMALL_STACK
03353    unsigned char* kb;
03354 #else
03355    unsigned char kb[128];
03356 #endif
03357    int      x;
03358    unsigned y, z, err, bitlen, bitpos, lut_gap, first;
03359    mp_int   tk;
03360 
03361    if (mp_init(&tk) != MP_OKAY)
03362        return MP_INIT_E;
03363 
03364    /* if it's smaller than modulus we fine */
03365    if (mp_unsigned_bin_size(k) > mp_unsigned_bin_size(modulus)) {
03366       mp_int order;
03367       if (mp_init(&order) != MP_OKAY) {
03368         mp_clear(&tk);
03369         return MP_INIT_E;
03370       }
03371 
03372       /* find order */
03373       y = mp_unsigned_bin_size(modulus);
03374       for (x = 0; ecc_sets[x].size; x++) {
03375          if (y <= (unsigned)ecc_sets[x].size) break;
03376       }
03377    
03378       /* back off if we are on the 521 bit curve */
03379       if (y == 66) --x;
03380       
03381       if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
03382          mp_clear(&order);
03383          mp_clear(&tk);
03384          return err;
03385       }
03386 
03387       /* k must be less than modulus */
03388       if (mp_cmp(k, &order) != MP_LT) {
03389          if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) {
03390             mp_clear(&tk);
03391             mp_clear(&order);
03392             return err;
03393          }
03394       } else {
03395          mp_copy(k, &tk);
03396       }
03397       mp_clear(&order);
03398    } else {
03399       mp_copy(k, &tk);
03400    }       
03401    
03402    /* get bitlen and round up to next multiple of FP_LUT */
03403    bitlen  = mp_unsigned_bin_size(modulus) << 3;
03404    x       = bitlen % FP_LUT;
03405    if (x) {
03406       bitlen += FP_LUT - x;
03407    }  
03408    lut_gap = bitlen / FP_LUT;
03409         
03410    /* get the k value */
03411    if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) {
03412       mp_clear(&tk);
03413       return BUFFER_E;
03414    }
03415    
03416    /* store k */
03417 #ifdef CYASSL_SMALL_STACK
03418    kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03419    if (kb == NULL)
03420       return MEMORY_E;
03421 #endif
03422 
03423    XMEMSET(kb, 0, KB_SIZE);
03424    if ((err = mp_to_unsigned_bin(&tk, kb)) != MP_OKAY) {
03425       mp_clear(&tk);
03426    }
03427    else {
03428       /* let's reverse kb so it's little endian */
03429       x = 0;
03430       y = mp_unsigned_bin_size(&tk) - 1;
03431       mp_clear(&tk);
03432 
03433       while ((unsigned)x < y) {
03434          z = kb[x]; kb[x] = kb[y]; kb[y] = z;
03435          ++x; --y;
03436       }
03437 
03438       /* at this point we can start, yipee */
03439       first = 1;
03440       for (x = lut_gap-1; x >= 0; x--) {
03441           /* extract FP_LUT bits from kb spread out by lut_gap bits and offset
03442              by x bits from the start */
03443           bitpos = x;
03444           for (y = z = 0; y < FP_LUT; y++) {
03445              z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y;
03446              bitpos += lut_gap;  /* it's y*lut_gap + x, but here we can avoid
03447                                     the mult in each loop */
03448           }
03449 
03450           /* double if not first */
03451           if (!first) {
03452              if ((err = ecc_projective_dbl_point(R, R, modulus,
03453                                                               mp)) != MP_OKAY) {
03454                 break;
03455              }
03456           }
03457 
03458           /* add if not first, otherwise copy */
03459           if (!first && z) {
03460              if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
03461                                                      modulus, mp)) != MP_OKAY) {
03462                 break;
03463              }
03464           } else if (z) {
03465              if ((mp_copy(&fp_cache[idx].LUT[z]->x, &R->x) != MP_OKAY) ||
03466                  (mp_copy(&fp_cache[idx].LUT[z]->y, &R->y) != MP_OKAY) ||
03467                  (mp_copy(&fp_cache[idx].mu,        &R->z) != MP_OKAY)) {
03468                  err = GEN_MEM_ERR;
03469                  break;
03470              }
03471                  first = 0;
03472           }
03473       }
03474    }
03475 
03476    if (err == MP_OKAY) {
03477       z = 0;
03478       XMEMSET(kb, 0, KB_SIZE);
03479       /* map R back from projective space */
03480       if (map) {
03481          err = ecc_map(R, modulus, mp);
03482       } else {
03483          err = MP_OKAY;
03484       }
03485    }
03486 
03487 #ifdef CYASSL_SMALL_STACK
03488    XFREE(kb, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03489 #endif
03490 
03491 #undef KB_SIZE
03492 
03493    return err;
03494 }
03495 
03496 #ifdef ECC_SHAMIR
03497 /* perform a fixed point ECC mulmod */
03498 static int accel_fp_mul2add(int idx1, int idx2, 
03499                             mp_int* kA, mp_int* kB,
03500                             ecc_point *R, mp_int* modulus, mp_digit* mp)
03501 {
03502 #define KB_SIZE 128
03503 
03504 #ifdef CYASSL_SMALL_STACK
03505    unsigned char* kb[2];
03506 #else
03507    unsigned char kb[2][128];
03508 #endif
03509    int      x;
03510    unsigned y, z, err, bitlen, bitpos, lut_gap, first, zA, zB;
03511    mp_int tka;
03512    mp_int tkb;
03513    mp_int order;
03514 
03515    if (mp_init_multi(&tka, &tkb, 0, 0, 0, 0) != MP_OKAY)
03516        return MP_INIT_E;
03517 
03518    /* if it's smaller than modulus we fine */
03519    if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) {
03520       /* find order */
03521       y = mp_unsigned_bin_size(modulus);
03522       for (x = 0; ecc_sets[x].size; x++) {
03523          if (y <= (unsigned)ecc_sets[x].size) break;
03524       }
03525    
03526       /* back off if we are on the 521 bit curve */
03527       if (y == 66) --x;
03528       
03529       if ((err = mp_init(&order)) != MP_OKAY) {
03530          mp_clear(&tkb);
03531          mp_clear(&tka);
03532          return err;
03533       }      
03534       if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
03535          mp_clear(&tkb);
03536          mp_clear(&tka);
03537          mp_clear(&order);
03538          return err;
03539       }
03540 
03541       /* kA must be less than modulus */
03542       if (mp_cmp(kA, &order) != MP_LT) {
03543          if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) {
03544             mp_clear(&tkb);
03545             mp_clear(&tka);
03546             mp_clear(&order);
03547             return err;
03548          }
03549       } else {
03550          mp_copy(kA, &tka);
03551       }
03552       mp_clear(&order);
03553    } else {
03554       mp_copy(kA, &tka);
03555    }       
03556 
03557    /* if it's smaller than modulus we fine */
03558    if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) {
03559       /* find order */
03560       y = mp_unsigned_bin_size(modulus);
03561       for (x = 0; ecc_sets[x].size; x++) {
03562          if (y <= (unsigned)ecc_sets[x].size) break;
03563       }
03564    
03565       /* back off if we are on the 521 bit curve */
03566       if (y == 66) --x;
03567       
03568       if ((err = mp_init(&order)) != MP_OKAY) {
03569          mp_clear(&tkb);
03570          mp_clear(&tka);
03571          return err;
03572       }      
03573       if ((err = mp_read_radix(&order, ecc_sets[x].order, 16)) != MP_OKAY) {
03574          mp_clear(&tkb);
03575          mp_clear(&tka);
03576          mp_clear(&order);
03577          return err;
03578       }
03579 
03580       /* kB must be less than modulus */
03581       if (mp_cmp(kB, &order) != MP_LT) {
03582          if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) {
03583             mp_clear(&tkb);
03584             mp_clear(&tka);
03585             mp_clear(&order);
03586             return err;
03587          }
03588       } else {
03589          mp_copy(kB, &tkb);
03590       }
03591       mp_clear(&order);
03592    } else {
03593       mp_copy(kB, &tkb);
03594    }     
03595 
03596    /* get bitlen and round up to next multiple of FP_LUT */
03597    bitlen  = mp_unsigned_bin_size(modulus) << 3;
03598    x       = bitlen % FP_LUT;
03599    if (x) {
03600       bitlen += FP_LUT - x;
03601    }  
03602    lut_gap = bitlen / FP_LUT;
03603         
03604    /* get the k value */
03605    if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) ||
03606        (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2))  ) {
03607       mp_clear(&tka);
03608       mp_clear(&tkb);
03609       return BUFFER_E;
03610    }
03611    
03612    /* store k */
03613 #ifdef CYASSL_SMALL_STACK
03614    kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03615    if (kb[0] == NULL)
03616       return MEMORY_E;
03617 #endif
03618 
03619    XMEMSET(kb[0], 0, KB_SIZE);
03620    if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) {
03621       mp_clear(&tka);
03622       mp_clear(&tkb);
03623       XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
03624       return err;
03625    }
03626    
03627    /* let's reverse kb so it's little endian */
03628    x = 0;
03629    y = mp_unsigned_bin_size(&tka) - 1;
03630    mp_clear(&tka);
03631    while ((unsigned)x < y) {
03632       z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = z;
03633       ++x; --y;
03634    }      
03635    
03636    /* store b */
03637 #ifdef CYASSL_SMALL_STACK
03638    kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
03639    if (kb[1] == NULL) {
03640       XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
03641       return MEMORY_E;
03642    }
03643 #endif
03644 
03645    XMEMSET(kb[1], 0, KB_SIZE);
03646    if ((err = mp_to_unsigned_bin(&tkb, kb[1])) != MP_OKAY) {
03647       mp_clear(&tkb);
03648    }
03649    else {
03650       x = 0;
03651       y = mp_unsigned_bin_size(&tkb) - 1;
03652       mp_clear(&tkb);
03653       while ((unsigned)x < y) {
03654          z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = z;
03655          ++x; --y;
03656       }
03657 
03658       /* at this point we can start, yipee */
03659       first = 1;
03660       for (x = lut_gap-1; x >= 0; x--) {
03661           /* extract FP_LUT bits from kb spread out by lut_gap bits and
03662              offset by x bits from the start */
03663           bitpos = x;
03664           for (y = zA = zB = 0; y < FP_LUT; y++) {
03665              zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y;
03666              zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y;
03667              bitpos += lut_gap;    /* it's y*lut_gap + x, but here we can avoid
03668                                       the mult in each loop */
03669           }
03670 
03671           /* double if not first */
03672           if (!first) {
03673              if ((err = ecc_projective_dbl_point(R, R, modulus,
03674                                                               mp)) != MP_OKAY) {
03675                 break;
03676              }
03677           }
03678 
03679           /* add if not first, otherwise copy */
03680           if (!first) {
03681              if (zA) {
03682                 if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
03683                                                   R, modulus, mp)) != MP_OKAY) {
03684                    break;
03685                 }
03686              }
03687              if (zB) {
03688                 if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
03689                                                   R, modulus, mp)) != MP_OKAY) {
03690                    break;
03691                 }
03692              }
03693           } else {
03694              if (zA) {
03695                  if ((mp_copy(&fp_cache[idx1].LUT[zA]->x, &R->x) != MP_OKAY) ||
03696                     (mp_copy(&fp_cache[idx1].LUT[zA]->y,  &R->y) != MP_OKAY) ||
03697                     (mp_copy(&fp_cache[idx1].mu,          &R->z) != MP_OKAY)) {
03698                      err = GEN_MEM_ERR;
03699                      break;
03700                  }
03701                     first = 0;
03702              }
03703              if (zB && first == 0) {
03704                 if (zB) {
03705                    if ((err = ecc_projective_add_point(R,
03706                            fp_cache[idx2].LUT[zB], R, modulus, mp)) != MP_OKAY){
03707                       break;
03708                    }
03709                 }
03710              } else if (zB && first == 1) {
03711                  if ((mp_copy(&fp_cache[idx2].LUT[zB]->x, &R->x) != MP_OKAY) ||
03712                     (mp_copy(&fp_cache[idx2].LUT[zB]->y, &R->y) != MP_OKAY) ||
03713                     (mp_copy(&fp_cache[idx2].mu,        &R->z) != MP_OKAY)) {
03714                      err = GEN_MEM_ERR;
03715                      break;
03716                  }
03717                     first = 0;
03718              }
03719           }
03720       }
03721    }
03722 
03723    XMEMSET(kb[0], 0, KB_SIZE);
03724    XMEMSET(kb[1], 0, KB_SIZE);
03725 
03726 #ifdef CYASSL_SMALL_STACK
03727    XFREE(kb[0], NULL, DYNAMIC_TYPE_TMP_BUFFER);
03728    XFREE(kb[1], NULL, DYNAMIC_TYPE_TMP_BUFFER);
03729 #endif
03730 
03731 #undef KB_SIZE
03732 
03733    return ecc_map(R, modulus, mp);
03734 }
03735 
03736 /** ECC Fixed Point mulmod global
03737   Computes kA*A + kB*B = C using Shamir's Trick
03738   A        First point to multiply
03739   kA       What to multiple A by
03740   B        Second point to multiply
03741   kB       What to multiple B by
03742   C        [out] Destination point (can overlap with A or B)
03743   modulus  Modulus for curve 
03744   return MP_OKAY on success
03745 */ 
03746 int ecc_mul2add(ecc_point* A, mp_int* kA,
03747                 ecc_point* B, mp_int* kB,
03748                 ecc_point* C, mp_int* modulus)
03749 {
03750    int  idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0;
03751    mp_digit mp;
03752    mp_int   mu;
03753   
03754    err = mp_init(&mu);
03755    if (err != MP_OKAY)
03756        return err;
03757 
03758 #ifndef HAVE_THREAD_LS
03759    if (initMutex == 0) {
03760         InitMutex(&ecc_fp_lock);
03761         initMutex = 1;
03762    }
03763    if (LockMutex(&ecc_fp_lock) != 0)
03764       return BAD_MUTEX_E;
03765 #endif /* HAVE_THREAD_LS */
03766 
03767       /* find point */
03768       idx1 = find_base(A);
03769 
03770       /* no entry? */
03771       if (idx1 == -1) {
03772          /* find hole and add it */
03773          if ((idx1 = find_hole()) >= 0) {
03774             err = add_entry(idx1, A);
03775          }
03776       }
03777       if (err == MP_OKAY && idx1 != -1) {
03778          /* increment LRU */
03779          ++(fp_cache[idx1].lru_count);
03780       }
03781 
03782       if (err == MP_OKAY)
03783         /* find point */
03784         idx2 = find_base(B);
03785 
03786       if (err == MP_OKAY) {
03787         /* no entry? */
03788         if (idx2 == -1) {
03789            /* find hole and add it */
03790            if ((idx2 = find_hole()) >= 0)
03791               err = add_entry(idx2, B);
03792          }
03793       }
03794 
03795       if (err == MP_OKAY && idx2 != -1) {
03796          /* increment LRU */
03797          ++(fp_cache[idx2].lru_count);
03798       }
03799 
03800       if (err == MP_OKAY) {
03801         /* if it's 2 build the LUT, if it's higher just use the LUT */
03802         if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) {
03803            /* compute mp */
03804            err = mp_montgomery_setup(modulus, &mp);
03805 
03806            if (err == MP_OKAY) {
03807              mpInit = 1;
03808              err = mp_montgomery_calc_normalization(&mu, modulus);
03809            }
03810                  
03811            if (err == MP_OKAY)
03812              /* build the LUT */
03813                err = build_lut(idx1, modulus, &mp, &mu);
03814         }
03815       }
03816 
03817       if (err == MP_OKAY) {
03818         /* if it's 2 build the LUT, if it's higher just use the LUT */
03819         if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) {
03820            if (mpInit == 0) {
03821                 /* compute mp */
03822                 err = mp_montgomery_setup(modulus, &mp);
03823                 if (err == MP_OKAY) {
03824                     mpInit = 1;
03825                     err = mp_montgomery_calc_normalization(&mu, modulus);
03826                 }
03827             }
03828                  
03829             if (err == MP_OKAY) 
03830             /* build the LUT */
03831               err = build_lut(idx2, modulus, &mp, &mu);
03832         }
03833       }
03834 
03835 
03836       if (err == MP_OKAY) {
03837         if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 &&
03838                                      fp_cache[idx2].lru_count >= 2) {
03839            if (mpInit == 0) {
03840               /* compute mp */
03841               err = mp_montgomery_setup(modulus, &mp);
03842            }
03843            if (err == MP_OKAY)
03844              err = accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, &mp);
03845         } else {
03846            err = normal_ecc_mul2add(A, kA, B, kB, C, modulus);
03847         }
03848     }
03849 
03850 #ifndef HAVE_THREAD_LS
03851     UnLockMutex(&ecc_fp_lock);
03852 #endif /* HAVE_THREAD_LS */
03853     mp_clear(&mu);
03854 
03855     return err;
03856 }
03857 #endif
03858 
03859 /** ECC Fixed Point mulmod global
03860     k        The multiplicand
03861     G        Base point to multiply
03862     R        [out] Destination of product
03863     modulus  The modulus for the curve
03864     map      [boolean] If non-zero maps the point back to affine co-ordinates,
03865              otherwise it's left in jacobian-montgomery form
03866     return MP_OKAY if successful
03867 */   
03868 int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
03869                int map)
03870 {
03871    int   idx, err = MP_OKAY;
03872    mp_digit mp;
03873    mp_int   mu;
03874    int      mpSetup = 0;
03875 
03876    if (mp_init(&mu) != MP_OKAY)
03877        return MP_INIT_E;
03878    
03879 #ifndef HAVE_THREAD_LS
03880    if (initMutex == 0) {
03881         InitMutex(&ecc_fp_lock);
03882         initMutex = 1;
03883    }
03884    
03885    if (LockMutex(&ecc_fp_lock) != 0)
03886       return BAD_MUTEX_E;
03887 #endif /* HAVE_THREAD_LS */
03888 
03889       /* find point */
03890       idx = find_base(G);
03891 
03892       /* no entry? */
03893       if (idx == -1) {
03894          /* find hole and add it */
03895          idx = find_hole();
03896 
03897          if (idx >= 0)
03898             err = add_entry(idx, G);
03899       }
03900       if (err == MP_OKAY && idx != -1) {
03901          /* increment LRU */
03902          ++(fp_cache[idx].lru_count);
03903       }
03904 
03905 
03906       if (err == MP_OKAY) { 
03907         /* if it's 2 build the LUT, if it's higher just use the LUT */
03908         if (idx >= 0 && fp_cache[idx].lru_count == 2) {
03909            /* compute mp */
03910            err = mp_montgomery_setup(modulus, &mp);
03911 
03912            if (err == MP_OKAY) {
03913              /* compute mu */
03914              mpSetup = 1;
03915              err = mp_montgomery_calc_normalization(&mu, modulus);
03916            }
03917                  
03918            if (err == MP_OKAY) 
03919              /* build the LUT */
03920              err = build_lut(idx, modulus, &mp, &mu);
03921         }
03922       }
03923 
03924       if (err == MP_OKAY) { 
03925         if (idx >= 0 && fp_cache[idx].lru_count >= 2) {
03926            if (mpSetup == 0) {
03927               /* compute mp */
03928               err = mp_montgomery_setup(modulus, &mp);
03929            }
03930            if (err == MP_OKAY)
03931              err = accel_fp_mul(idx, k, R, modulus, &mp, map);
03932         } else {
03933            err = normal_ecc_mulmod(k, G, R, modulus, map);
03934         }
03935      }
03936 
03937 #ifndef HAVE_THREAD_LS
03938     UnLockMutex(&ecc_fp_lock);
03939 #endif /* HAVE_THREAD_LS */
03940     mp_clear(&mu);
03941 
03942     return err;
03943 }
03944 
03945 /* helper function for freeing the cache ...
03946    must be called with the cache mutex locked */
03947 static void ecc_fp_free_cache(void)
03948 {
03949    unsigned x, y;
03950    for (x = 0; x < FP_ENTRIES; x++) {
03951       if (fp_cache[x].g != NULL) {
03952          for (y = 0; y < (1U<<FP_LUT); y++) {
03953             ecc_del_point(fp_cache[x].LUT[y]);
03954             fp_cache[x].LUT[y] = NULL;
03955          }
03956          ecc_del_point(fp_cache[x].g);
03957          fp_cache[x].g         = NULL;
03958          mp_clear(&fp_cache[x].mu);
03959          fp_cache[x].lru_count = 0;
03960          fp_cache[x].lock = 0;
03961       }         
03962    }
03963 }         
03964 
03965 /** Free the Fixed Point cache */
03966 void ecc_fp_free(void)
03967 {
03968 #ifndef HAVE_THREAD_LS
03969    if (initMutex == 0) {
03970         InitMutex(&ecc_fp_lock);
03971         initMutex = 1;
03972    }
03973    
03974    if (LockMutex(&ecc_fp_lock) == 0) {
03975 #endif /* HAVE_THREAD_LS */
03976 
03977        ecc_fp_free_cache();
03978 
03979 #ifndef HAVE_THREAD_LS
03980        UnLockMutex(&ecc_fp_lock);
03981        FreeMutex(&ecc_fp_lock);
03982        initMutex = 0;
03983    }
03984 #endif /* HAVE_THREAD_LS */
03985 }
03986 
03987 
03988 #endif /* FP_ECC */
03989 
03990 #ifdef HAVE_ECC_ENCRYPT
03991 
03992 
03993 enum ecCliState {
03994     ecCLI_INIT      = 1,    
03995     ecCLI_SALT_GET  = 2,    
03996     ecCLI_SALT_SET  = 3,    
03997     ecCLI_SENT_REQ  = 4,    
03998     ecCLI_RECV_RESP = 5,    
03999     ecCLI_BAD_STATE = 99    
04000 };
04001 
04002 enum ecSrvState {
04003     ecSRV_INIT      = 1,    
04004     ecSRV_SALT_GET  = 2,    
04005     ecSRV_SALT_SET  = 3,    
04006     ecSRV_RECV_REQ  = 4,    
04007     ecSRV_SENT_RESP = 5,    
04008     ecSRV_BAD_STATE = 99    
04009 };
04010 
04011 
04012 struct ecEncCtx {
04013     const byte* kdfSalt;   /* optional salt for kdf */
04014     const byte* kdfInfo;   /* optional info for kdf */
04015     const byte* macSalt;   /* optional salt for mac */
04016     word32    kdfSaltSz;   /* size of kdfSalt */
04017     word32    kdfInfoSz;   /* size of kdfInfo */
04018     word32    macSaltSz;   /* size of macSalt */
04019     byte      clientSalt[EXCHANGE_SALT_SZ];  /* for msg exchange */
04020     byte      serverSalt[EXCHANGE_SALT_SZ];  /* for msg exchange */
04021     byte      encAlgo;     /* which encryption type */
04022     byte      kdfAlgo;     /* which key derivation function type */
04023     byte      macAlgo;     /* which mac function type */
04024     byte      protocol;    /* are we REQ_RESP client or server ? */
04025     byte      cliSt;       /* protocol state, for sanity checks */
04026     byte      srvSt;       /* protocol state, for sanity checks */
04027 };
04028 
04029 
04030 const byte* ecc_ctx_get_own_salt(ecEncCtx* ctx)
04031 {
04032     if (ctx == NULL || ctx->protocol == 0)
04033         return NULL;
04034 
04035     if (ctx->protocol == REQ_RESP_CLIENT) {
04036         if (ctx->cliSt == ecCLI_INIT) {
04037             ctx->cliSt =  ecCLI_SALT_GET;
04038             return ctx->clientSalt;
04039         }
04040         else {
04041             ctx->cliSt = ecCLI_BAD_STATE;
04042             return NULL;
04043         }
04044     }
04045     else if (ctx->protocol == REQ_RESP_SERVER) {
04046         if (ctx->srvSt == ecSRV_INIT) {
04047             ctx->srvSt =  ecSRV_SALT_GET;
04048             return ctx->serverSalt;
04049         }
04050         else {
04051             ctx->srvSt = ecSRV_BAD_STATE;
04052             return NULL;
04053         }
04054     }
04055 
04056     return NULL;
04057 }
04058 
04059 
04060 /* optional set info, can be called before or after set_peer_salt */
04061 int ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz)
04062 {
04063     if (ctx == NULL || info == 0 || sz < 0)
04064         return BAD_FUNC_ARG;
04065 
04066     ctx->kdfInfo   = info;
04067     ctx->kdfInfoSz = sz;
04068 
04069     return 0;
04070 }
04071 
04072 
04073 static const char* exchange_info = "Secure Message Exchange";
04074 
04075 int ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt)
04076 {
04077     byte tmp[EXCHANGE_SALT_SZ/2];
04078     int  halfSz = EXCHANGE_SALT_SZ/2;
04079 
04080     if (ctx == NULL || ctx->protocol == 0 || salt == NULL)
04081         return BAD_FUNC_ARG;
04082 
04083     if (ctx->protocol == REQ_RESP_CLIENT) {
04084         XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ);
04085         if (ctx->cliSt == ecCLI_SALT_GET)
04086             ctx->cliSt =  ecCLI_SALT_SET;
04087         else {
04088             ctx->cliSt =  ecCLI_BAD_STATE;
04089             return BAD_ENC_STATE_E;
04090         }
04091     }
04092     else {
04093         XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ);
04094         if (ctx->srvSt == ecSRV_SALT_GET)
04095             ctx->srvSt =  ecSRV_SALT_SET;
04096         else {
04097             ctx->srvSt =  ecSRV_BAD_STATE;
04098             return BAD_ENC_STATE_E;
04099         }
04100     }
04101 
04102     /* mix half and half */
04103     /* tmp stores 2nd half of client before overwrite */
04104     XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz);
04105     XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz);
04106     XMEMCPY(ctx->serverSalt, tmp, halfSz);
04107 
04108     ctx->kdfSalt   = ctx->clientSalt;
04109     ctx->kdfSaltSz = EXCHANGE_SALT_SZ;
04110 
04111     ctx->macSalt   = ctx->serverSalt;
04112     ctx->macSaltSz = EXCHANGE_SALT_SZ;
04113 
04114     if (ctx->kdfInfo == NULL) {
04115         /* default info */
04116         ctx->kdfInfo   = (const byte*)exchange_info;
04117         ctx->kdfInfoSz = EXCHANGE_INFO_SZ;
04118     }
04119 
04120     return 0;
04121 }
04122 
04123 
04124 static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, RNG* rng)
04125 {
04126     byte* saltBuffer = NULL;
04127 
04128     if (ctx == NULL || rng == NULL || flags == 0) 
04129         return BAD_FUNC_ARG;
04130 
04131     saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt;
04132 
04133     return RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ);
04134 }
04135 
04136 
04137 static void ecc_ctx_init(ecEncCtx* ctx, int flags)
04138 {
04139     if (ctx) {
04140         XMEMSET(ctx, 0, sizeof(ecEncCtx));
04141 
04142         ctx->encAlgo  = ecAES_128_CBC;
04143         ctx->kdfAlgo  = ecHKDF_SHA256;
04144         ctx->macAlgo  = ecHMAC_SHA256;
04145         ctx->protocol = (byte)flags;
04146 
04147         if (flags == REQ_RESP_CLIENT)
04148             ctx->cliSt = ecCLI_INIT;
04149         if (flags == REQ_RESP_SERVER)
04150             ctx->srvSt = ecSRV_INIT;
04151     }
04152 }
04153 
04154 
04155 /* allow ecc context reset so user doesn't have to init/free for resue */
04156 int ecc_ctx_reset(ecEncCtx* ctx, RNG* rng)
04157 {
04158     if (ctx == NULL || rng == NULL)
04159         return BAD_FUNC_ARG;
04160 
04161     ecc_ctx_init(ctx, ctx->protocol);
04162     return ecc_ctx_set_salt(ctx, ctx->protocol, rng);
04163 }
04164 
04165 
04166 /* alloc/init and set defaults, return new Context  */
04167 ecEncCtx* ecc_ctx_new(int flags, RNG* rng)
04168 {
04169     int       ret = 0;
04170     ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), 0, DYNAMIC_TYPE_ECC);
04171 
04172     if (ctx)
04173         ctx->protocol = (byte)flags;
04174 
04175     ret = ecc_ctx_reset(ctx, rng);
04176     if (ret != 0) {
04177         ecc_ctx_free(ctx);
04178         ctx = NULL;
04179     }
04180 
04181     return ctx;
04182 }
04183 
04184 
04185 /* free any resources, clear any keys */
04186 void ecc_ctx_free(ecEncCtx* ctx)
04187 {
04188     if (ctx) {
04189         XMEMSET(ctx, 0, sizeof(ecEncCtx));
04190         XFREE(ctx, 0, DYNAMIC_TYPE_ECC);
04191     }
04192 }
04193 
04194 
04195 static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz,
04196                              int* keysLen, word32* digestSz, word32* blockSz)
04197 {
04198     if (ctx) {
04199         switch (ctx->encAlgo) {
04200             case ecAES_128_CBC:
04201                 *encKeySz = KEY_SIZE_128;
04202                 *ivSz     = IV_SIZE_64;
04203                 *blockSz  = AES_BLOCK_SIZE;
04204                 break;
04205             default:
04206                 return BAD_FUNC_ARG;
04207         }
04208 
04209         switch (ctx->macAlgo) {
04210             case ecHMAC_SHA256:
04211                 *digestSz = SHA256_DIGEST_SIZE;
04212                 break;
04213             default:
04214                 return BAD_FUNC_ARG;
04215         }
04216     } else
04217         return BAD_FUNC_ARG;
04218 
04219     *keysLen  = *encKeySz + *ivSz + *digestSz;
04220 
04221     return 0;
04222 }
04223 
04224 
04225 /* ecc encrypt with shared secret run through kdf
04226    ctx holds non default algos and inputs
04227    msgSz should be the right size for encAlgo, i.e., already padded 
04228    return 0 on success */
04229 int ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
04230                 word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
04231 {
04232     int          ret;
04233     word32       blockSz;
04234     word32       digestSz;
04235     ecEncCtx     localCtx;
04236 #ifdef CYASSL_SMALL_STACK
04237     byte*        sharedSecret;
04238     byte*        keys;
04239 #else
04240     byte         sharedSecret[ECC_MAXSIZE];  /* 521 max size */
04241     byte         keys[ECC_BUFSIZE];         /* max size */
04242 #endif
04243     word32       sharedSz = ECC_MAXSIZE;
04244     int          keysLen;
04245     int          encKeySz;
04246     int          ivSz;
04247     int          offset = 0;         /* keys offset if doing msg exchange */
04248     byte*        encKey;
04249     byte*        encIv;
04250     byte*        macKey;
04251 
04252     if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
04253                            outSz  == NULL)
04254         return BAD_FUNC_ARG;
04255 
04256     if (ctx == NULL) {  /* use defaults */
04257         ecc_ctx_init(&localCtx, 0);
04258         ctx = &localCtx;  
04259     }
04260         
04261     ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
04262                             &blockSz);
04263     if (ret != 0)
04264         return ret;
04265 
04266     if (ctx->protocol == REQ_RESP_SERVER) {
04267         offset = keysLen;
04268         keysLen *= 2;
04269 
04270         if (ctx->srvSt != ecSRV_RECV_REQ)
04271             return BAD_ENC_STATE_E;
04272 
04273         ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
04274     }
04275     else if (ctx->protocol == REQ_RESP_CLIENT) {
04276         if (ctx->cliSt != ecCLI_SALT_SET)
04277             return BAD_ENC_STATE_E;
04278 
04279         ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */
04280     }
04281         
04282     if (keysLen > ECC_BUFSIZE) /* keys size */
04283         return BUFFER_E;
04284         
04285     if ( (msgSz%blockSz) != 0)
04286         return BAD_PADDING_E;
04287 
04288     if (*outSz < (msgSz + digestSz))
04289         return BUFFER_E;
04290 
04291 #ifdef CYASSL_SMALL_STACK
04292     sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04293     if (sharedSecret == NULL)
04294         return MEMORY_E;
04295 
04296     keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04297     if (keys == NULL) {
04298         XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04299         return MEMORY_E;
04300     }
04301 #endif
04302 
04303     ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
04304 
04305     if (ret == 0) {
04306        switch (ctx->kdfAlgo) {
04307            case ecHKDF_SHA256 :
04308                ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
04309                           ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
04310                           keys, keysLen);
04311                break;
04312 
04313            default:
04314                ret = BAD_FUNC_ARG;
04315                break;
04316        }
04317     }
04318 
04319     if (ret == 0) {
04320        encKey = keys + offset;
04321        encIv  = encKey + encKeySz;
04322        macKey = encKey + encKeySz + ivSz;
04323 
04324        switch (ctx->encAlgo) {
04325            case ecAES_128_CBC:
04326                {
04327                    Aes aes;
04328                    ret = AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
04329                                                                 AES_ENCRYPTION);
04330                    if (ret != 0)
04331                        break;
04332                    ret = AesCbcEncrypt(&aes, out, msg, msgSz);
04333                }
04334                break;
04335 
04336            default:
04337                ret = BAD_FUNC_ARG;
04338                break;
04339        }
04340     }
04341 
04342     if (ret == 0) {
04343        switch (ctx->macAlgo) {
04344            case ecHMAC_SHA256:
04345                {
04346                    Hmac hmac;
04347                    ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
04348                    if (ret != 0)
04349                        break;
04350                    ret = HmacUpdate(&hmac, out, msgSz);
04351                    if (ret != 0)
04352                        break;
04353                    ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
04354                    if (ret != 0)
04355                        break;
04356                    ret = HmacFinal(&hmac, out+msgSz);
04357                }
04358                break;
04359 
04360            default:
04361                ret = BAD_FUNC_ARG;
04362                break;
04363        }
04364     }
04365 
04366     if (ret == 0)
04367        *outSz = msgSz + digestSz;
04368 
04369 #ifdef CYASSL_SMALL_STACK
04370     XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04371     XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04372 #endif
04373 
04374     return ret;
04375 }
04376 
04377 
04378 /* ecc decrypt with shared secret run through kdf
04379    ctx holds non default algos and inputs
04380    return 0 on success */
04381 int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
04382                 word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx)
04383 {
04384     int          ret;
04385     word32       blockSz;
04386     word32       digestSz;
04387     ecEncCtx     localCtx;
04388 #ifdef CYASSL_SMALL_STACK
04389     byte*        sharedSecret;
04390     byte*        keys;
04391 #else
04392     byte         sharedSecret[ECC_MAXSIZE];  /* 521 max size */
04393     byte         keys[ECC_BUFSIZE];         /* max size */
04394 #endif
04395     word32       sharedSz = ECC_MAXSIZE;
04396     int          keysLen;
04397     int          encKeySz;
04398     int          ivSz;
04399     int          offset = 0;       /* in case using msg exchange */
04400     byte*        encKey;
04401     byte*        encIv;
04402     byte*        macKey;
04403 
04404     if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL ||
04405                            outSz  == NULL)
04406         return BAD_FUNC_ARG;
04407 
04408     if (ctx == NULL) {  /* use defaults */
04409         ecc_ctx_init(&localCtx, 0);
04410         ctx = &localCtx;  
04411     }
04412         
04413     ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz,
04414                             &blockSz);
04415     if (ret != 0)
04416         return ret;
04417         
04418     if (ctx->protocol == REQ_RESP_CLIENT) {
04419         offset = keysLen;
04420         keysLen *= 2;
04421 
04422         if (ctx->cliSt != ecCLI_SENT_REQ)
04423             return BAD_ENC_STATE_E;
04424 
04425         ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */
04426     }
04427     else if (ctx->protocol == REQ_RESP_SERVER) {
04428         if (ctx->srvSt != ecSRV_SALT_SET)
04429             return BAD_ENC_STATE_E;
04430 
04431         ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */
04432     }
04433         
04434     if (keysLen > ECC_BUFSIZE) /* keys size */
04435         return BUFFER_E;
04436         
04437     if ( ((msgSz-digestSz) % blockSz) != 0)
04438         return BAD_PADDING_E;
04439 
04440     if (*outSz < (msgSz - digestSz))
04441         return BUFFER_E;
04442 
04443 #ifdef CYASSL_SMALL_STACK
04444     sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04445     if (sharedSecret == NULL)
04446         return MEMORY_E;
04447 
04448     keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04449     if (keys == NULL) {
04450         XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04451         return MEMORY_E;
04452     }
04453 #endif
04454 
04455     ret = ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz);
04456 
04457     if (ret == 0) {
04458        switch (ctx->kdfAlgo) {
04459            case ecHKDF_SHA256 :
04460                ret = HKDF(SHA256, sharedSecret, sharedSz, ctx->kdfSalt,
04461                           ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz,
04462                           keys, keysLen);
04463                break;
04464 
04465            default:
04466                ret = BAD_FUNC_ARG;
04467                break;
04468        }
04469     }
04470 
04471     if (ret == 0) {
04472        encKey = keys + offset;
04473        encIv  = encKey + encKeySz;
04474        macKey = encKey + encKeySz + ivSz;
04475 
04476        switch (ctx->macAlgo) {
04477            case ecHMAC_SHA256:
04478                {
04479                    byte verify[SHA256_DIGEST_SIZE];
04480                    Hmac hmac;
04481                    ret = HmacSetKey(&hmac, SHA256, macKey, SHA256_DIGEST_SIZE);
04482                    if (ret != 0)
04483                        break;
04484                    ret = HmacUpdate(&hmac, msg, msgSz-digestSz);
04485                    if (ret != 0)
04486                        break;
04487                    ret = HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz);
04488                    if (ret != 0)
04489                        break;
04490                    ret = HmacFinal(&hmac, verify);
04491                    if (ret != 0)
04492                        break;
04493                    if (memcmp(verify, msg + msgSz - digestSz, digestSz) != 0)
04494                        ret = -1;
04495                }
04496                break;
04497 
04498            default:
04499                ret = BAD_FUNC_ARG;
04500                break;
04501        }
04502     }
04503 
04504     if (ret == 0) {
04505        switch (ctx->encAlgo) {
04506            case ecAES_128_CBC:
04507                {
04508                    Aes aes;
04509                    ret = AesSetKey(&aes, encKey, KEY_SIZE_128, encIv,
04510                                                                 AES_DECRYPTION);
04511                    if (ret != 0)
04512                        break;
04513                    ret = AesCbcDecrypt(&aes, out, msg, msgSz-digestSz);
04514                }
04515                break;
04516 
04517            default:
04518                ret = BAD_FUNC_ARG;
04519                break;
04520        }
04521     }
04522 
04523     if (ret == 0)
04524        *outSz = msgSz - digestSz;
04525 
04526 #ifdef CYASSL_SMALL_STACK
04527     XFREE(sharedSecret, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04528     XFREE(keys, NULL, DYNAMIC_TYPE_TMP_BUFFER);
04529 #endif
04530 
04531     return ret;
04532 }
04533 
04534 
04535 #endif /* HAVE_ECC_ENCRYPT */
04536 
04537 
04538 #ifdef HAVE_COMP_KEY
04539 
04540 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
04541  * HAC pp. 73 Algorithm 2.149
04542  */
04543 int mp_jacobi(mp_int* a, mp_int* p, int* c)
04544 {
04545   mp_int   a1, p1;
04546   int      k, s, r, res;
04547   mp_digit residue;
04548 
04549   /* if p <= 0 return MP_VAL */
04550   if (mp_cmp_d(p, 0) != MP_GT) {
04551      return MP_VAL;
04552   }
04553 
04554   /* step 1.  if a == 0, return 0 */
04555   if (mp_iszero (a) == 1) {
04556     *c = 0;
04557     return MP_OKAY;
04558   }
04559 
04560   /* step 2.  if a == 1, return 1 */
04561   if (mp_cmp_d (a, 1) == MP_EQ) {
04562     *c = 1;
04563     return MP_OKAY;
04564   }
04565 
04566   /* default */
04567   s = 0;
04568 
04569   /* step 3.  write a = a1 * 2**k  */
04570   if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
04571     return res;
04572   }
04573 
04574   if ((res = mp_init (&p1)) != MP_OKAY) {
04575     mp_clear(&a1);
04576     return res;
04577   }
04578 
04579   /* divide out larger power of two */
04580   k = mp_cnt_lsb(&a1);
04581   res = mp_div_2d(&a1, k, &a1, NULL);
04582 
04583   if (res == MP_OKAY) {
04584     /* step 4.  if e is even set s=1 */
04585     if ((k & 1) == 0) {
04586       s = 1;
04587     } else {
04588       /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
04589       residue = p->dp[0] & 7;
04590 
04591       if (residue == 1 || residue == 7) {
04592         s = 1;
04593       } else if (residue == 3 || residue == 5) {
04594         s = -1;
04595       }
04596     }
04597 
04598     /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
04599     if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
04600       s = -s;
04601     }
04602   }
04603 
04604   if (res == MP_OKAY) {
04605     /* if a1 == 1 we're done */
04606     if (mp_cmp_d (&a1, 1) == MP_EQ) {
04607       *c = s;
04608     } else {
04609       /* n1 = n mod a1 */
04610       res = mp_mod (p, &a1, &p1);
04611       if (res == MP_OKAY)
04612         res = mp_jacobi (&p1, &a1, &r);
04613 
04614       if (res == MP_OKAY)
04615       *c = s * r;
04616     }
04617   }
04618 
04619   /* done */
04620   mp_clear (&p1);
04621   mp_clear (&a1);
04622 
04623   return res;
04624 }
04625 
04626 
04627 int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
04628 {
04629   int res, legendre, done = 0;
04630   mp_int t1, C, Q, S, Z, M, T, R, two;
04631   mp_digit i;
04632 
04633   /* first handle the simple cases */
04634   if (mp_cmp_d(n, 0) == MP_EQ) {
04635     mp_zero(ret);
04636     return MP_OKAY;
04637   }
04638   if (mp_cmp_d(prime, 2) == MP_EQ)       return MP_VAL; /* prime must be odd */
04639   /* TAO removed
04640   if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY)      return res;
04641   if (legendre == -1)  return MP_VAL; */ /* quadratic non-residue mod prime */
04642 
04643   if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY)
04644     return res;
04645 
04646   if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL))
04647                           != MP_OKAY) {
04648     mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z);
04649     mp_clear(&M);
04650     return res;
04651   }
04652 
04653   /* SPECIAL CASE: if prime mod 4 == 3
04654    * compute directly: res = n^(prime+1)/4 mod prime
04655    * Handbook of Applied Cryptography algorithm 3.36
04656    */
04657   res = mp_mod_d(prime, 4, &i);
04658   if (res == MP_OKAY && i == 3) {
04659     res = mp_add_d(prime, 1, &t1);
04660 
04661     if (res == MP_OKAY)
04662       res = mp_div_2(&t1, &t1);
04663     if (res == MP_OKAY)
04664       res = mp_div_2(&t1, &t1);
04665     if (res == MP_OKAY)
04666       res = mp_exptmod(n, &t1, prime, ret);
04667 
04668     done = 1;
04669   }
04670 
04671   /* NOW: TonelliShanks algorithm */
04672 
04673  if (res == MP_OKAY && done == 0) {
04674 
04675    /* factor out powers of 2 from prime-1, defining Q and S
04676     *                                      as: prime-1 = Q*2^S */
04677     res = mp_copy(prime, &Q);
04678     if (res == MP_OKAY)
04679       res = mp_sub_d(&Q, 1, &Q);
04680     /* Q = prime - 1 */
04681     if (res == MP_OKAY)
04682       mp_zero(&S);
04683     /* S = 0 */
04684     while (res == MP_OKAY && mp_iseven(&Q)) {
04685       res = mp_div_2(&Q, &Q);
04686       /* Q = Q / 2 */
04687       if (res == MP_OKAY)
04688         res = mp_add_d(&S, 1, &S);
04689         /* S = S + 1 */
04690     }
04691 
04692     /* find a Z such that the Legendre symbol (Z|prime) == -1 */
04693     if (res == MP_OKAY)
04694       res = mp_set_int(&Z, 2);
04695     /* Z = 2 */
04696     while (res == MP_OKAY) {
04697       res = mp_jacobi(&Z, prime, &legendre);
04698       if (res == MP_OKAY && legendre == -1)
04699         break;
04700       if (res == MP_OKAY)
04701         res = mp_add_d(&Z, 1, &Z);
04702         /* Z = Z + 1 */
04703     }
04704 
04705     if (res == MP_OKAY)
04706       res = mp_exptmod(&Z, &Q, prime, &C);
04707       /* C = Z ^ Q mod prime */
04708     if (res == MP_OKAY)
04709       res = mp_add_d(&Q, 1, &t1);
04710     if (res == MP_OKAY)
04711       res = mp_div_2(&t1, &t1);
04712       /* t1 = (Q + 1) / 2 */
04713     if (res == MP_OKAY)
04714       res = mp_exptmod(n, &t1, prime, &R);
04715     /* R = n ^ ((Q + 1) / 2) mod prime */
04716     if (res == MP_OKAY)
04717       res = mp_exptmod(n, &Q, prime, &T);
04718     /* T = n ^ Q mod prime */
04719     if (res == MP_OKAY)
04720       res = mp_copy(&S, &M);
04721     /* M = S */
04722     if (res == MP_OKAY)
04723       res = mp_set_int(&two, 2);
04724 
04725     while (res == MP_OKAY && done == 0) {
04726       res = mp_copy(&T, &t1);
04727       i = 0;
04728       while (res == MP_OKAY) {
04729         if (mp_cmp_d(&t1, 1) == MP_EQ)
04730             break;
04731         res = mp_exptmod(&t1, &two, prime, &t1);
04732         if (res == MP_OKAY)
04733           i++;
04734       }
04735       if (res == MP_OKAY && i == 0) {
04736         mp_copy(&R, ret);
04737         res = MP_OKAY;
04738         done = 1;
04739       }
04740 
04741       if (done == 0) {
04742         if (res == MP_OKAY)
04743           res = mp_sub_d(&M, i, &t1);
04744         if (res == MP_OKAY)
04745           res = mp_sub_d(&t1, 1, &t1);
04746         if (res == MP_OKAY)
04747           res = mp_exptmod(&two, &t1, prime, &t1);
04748         /* t1 = 2 ^ (M - i - 1) */
04749         if (res == MP_OKAY)
04750           res = mp_exptmod(&C, &t1, prime, &t1);
04751         /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
04752         if (res == MP_OKAY)
04753           res = mp_sqrmod(&t1, prime, &C);
04754         /* C = (t1 * t1) mod prime */
04755         if (res == MP_OKAY)
04756           res = mp_mulmod(&R, &t1, prime, &R);
04757         /* R = (R * t1) mod prime */
04758         if (res == MP_OKAY)
04759           res = mp_mulmod(&T, &C, prime, &T);
04760         /* T = (T * C) mod prime */
04761         if (res == MP_OKAY)
04762           mp_set(&M, i);
04763         /* M = i */
04764       }
04765     }
04766   }
04767 
04768   /* done */
04769   mp_clear(&t1);
04770   mp_clear(&C);
04771   mp_clear(&Q);
04772   mp_clear(&S);
04773   mp_clear(&Z);
04774   mp_clear(&M);
04775   mp_clear(&T);
04776   mp_clear(&R);
04777   mp_clear(&two);
04778 
04779   return res;
04780 }
04781 
04782 
04783 /* export public ECC key in ANSI X9.63 format compressed */
04784 int ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen)
04785 {
04786    word32 numlen;
04787    int    ret = MP_OKAY;
04788 
04789    if (key == NULL || out == NULL || outLen == NULL)
04790        return ECC_BAD_ARG_E;
04791 
04792    if (ecc_is_valid_idx(key->idx) == 0) {
04793       return ECC_BAD_ARG_E;
04794    }
04795    numlen = key->dp->size;
04796 
04797    if (*outLen < (1 + numlen)) {
04798       *outLen = 1 + numlen;
04799       return BUFFER_E;
04800    }
04801 
04802    /* store first byte */
04803    out[0] = mp_isodd(&key->pubkey.y) ? 0x03 : 0x02;
04804 
04805    /* pad and store x */
04806    XMEMSET(out+1, 0, numlen);
04807    ret = mp_to_unsigned_bin(&key->pubkey.x,
04808                        out+1 + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
04809    *outLen = 1 + numlen;
04810    return ret;
04811 }
04812 
04813 
04814 /* d = a - b (mod c) */
04815 int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
04816 {
04817   int     res;
04818   mp_int  t;
04819 
04820   if ((res = mp_init (&t)) != MP_OKAY) {
04821     return res;
04822   }
04823 
04824   if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
04825     mp_clear (&t);
04826     return res;
04827   }
04828   res = mp_mod (&t, c, d);
04829   mp_clear (&t);
04830 
04831   return res;
04832 }
04833 
04834 
04835 #endif /* HAVE_COMP_KEY */
04836 
04837 #endif /* HAVE_ECC */