/ctaocrypt/src/ecc.c
C | 1537 lines | 1043 code | 228 blank | 266 comment | 646 complexity | fe067ba0b0cb666b4dd33f69234d94f7 MD5 | raw file
Possible License(s): GPL-2.0
- /* ecc.c
- *
- * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
- *
- * This file is part of CyaSSL.
- *
- * CyaSSL is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * CyaSSL is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- */
- #ifdef HAVE_CONFIG_H
- #include <config.h>
- #endif
- /* in case user set HAVE_ECC there */
- #include <cyassl/ctaocrypt/settings.h>
- #ifdef HAVE_ECC
- #include <cyassl/ctaocrypt/ecc.h>
- #include <cyassl/ctaocrypt/asn.h>
- #include <cyassl/ctaocrypt/error.h>
- /* map
- ptmul -> mulmod
- */
- #define ECC112
- #define ECC128
- #define ECC160
- #define ECC192
- #define ECC224
- #define ECC256
- #define ECC384
- #define ECC521
- /* This holds the key settings. ***MUST*** be organized by size from
- smallest to largest. */
- const ecc_set_type ecc_sets[] = {
- #ifdef ECC112
- {
- 14,
- "SECP112R1",
- "DB7C2ABF62E35E668076BEAD208B",
- "659EF8BA043916EEDE8911702B22",
- "DB7C2ABF62E35E7628DFAC6561C5",
- "09487239995A5EE76B55F9C2F098",
- "A89CE5AF8724C0A23E0E0FF77500"
- },
- #endif
- #ifdef ECC128
- {
- 16,
- "SECP128R1",
- "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
- "E87579C11079F43DD824993C2CEE5ED3",
- "FFFFFFFE0000000075A30D1B9038A115",
- "161FF7528B899B2D0C28607CA52C5B86",
- "CF5AC8395BAFEB13C02DA292DDED7A83",
- },
- #endif
- #ifdef ECC160
- {
- 20,
- "SECP160R1",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
- "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
- "0100000000000000000001F4C8F927AED3CA752257",
- "4A96B5688EF573284664698968C38BB913CBFC82",
- "23A628553168947D59DCC912042351377AC5FB32",
- },
- #endif
- #ifdef ECC192
- {
- 24,
- "ECC-192",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
- "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
- "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
- "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
- "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
- },
- #endif
- #ifdef ECC224
- {
- 28,
- "ECC-224",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
- "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
- "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
- "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
- },
- #endif
- #ifdef ECC256
- {
- 32,
- "ECC-256",
- "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
- "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
- "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
- "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
- "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
- },
- #endif
- #ifdef ECC384
- {
- 48,
- "ECC-384",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
- "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
- "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
- "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
- "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
- },
- #endif
- #ifdef ECC521
- {
- 66,
- "ECC-521",
- "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
- "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
- "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
- "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
- "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
- },
- #endif
- {
- 0,
- NULL, NULL, NULL, NULL, NULL, NULL
- }
- };
- ecc_point* ecc_new_point(void);
- void ecc_del_point(ecc_point* p);
- int ecc_map(ecc_point*, mp_int*, mp_digit*);
- int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
- mp_int* modulus, mp_digit* mp);
- int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* modulus,
- mp_digit* mp);
- /* helper for either lib */
- static int get_digit_count(mp_int* a)
- {
- if (a == NULL)
- return 0;
- return a->used;
- }
- /* helper for either lib */
- static unsigned long get_digit(mp_int* a, int n)
- {
- if (a == NULL)
- return 0;
- return (n >= a->used || n < 0) ? 0 : a->dp[n];
- }
- /**
- Add two ECC points
- P The point to add
- Q The point to add
- R [out] The destination of the double
- modulus The modulus of the field the ECC curve is in
- mp The "b" value from montgomery_setup()
- return MP_OKAY on success
- */
- int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
- mp_int* modulus, mp_digit* mp)
- {
- mp_int t1;
- mp_int t2;
- mp_int x;
- mp_int y;
- mp_int z;
- int err;
- if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL)
- return ECC_BAD_ARG_E;
- if ((err = mp_init_multi(&t1, &t2, &x, &y, &z, NULL)) != MP_OKAY) {
- return err;
- }
-
- /* should we dbl instead? */
- err = mp_sub(modulus, &Q->y, &t1);
- if (err == MP_OKAY) {
- if ( (mp_cmp(&P->x, &Q->x) == MP_EQ) &&
- (get_digit_count(&Q->z) && mp_cmp(&P->z, &Q->z) == MP_EQ) &&
- (mp_cmp(&P->y, &Q->y) == MP_EQ || mp_cmp(&P->y, &t1) == MP_EQ)) {
- mp_clear(&t1);
- mp_clear(&t2);
- mp_clear(&x);
- mp_clear(&y);
- mp_clear(&z);
- return ecc_projective_dbl_point(P, R, modulus, mp);
- }
- }
- if (err == MP_OKAY)
- err = mp_copy(&P->x, &x);
- if (err == MP_OKAY)
- err = mp_copy(&P->y, &y);
- if (err == MP_OKAY)
- err = mp_copy(&P->z, &z);
- /* if Z is one then these are no-operations */
- if (err == MP_OKAY) {
- if (get_digit_count(&Q->z)) {
- /* T1 = Z' * Z' */
- err = mp_sqr(&Q->z, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* X = X * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&t1, &x, &x);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&x, modulus, *mp);
- /* T1 = Z' * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&Q->z, &t1, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* Y = Y * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&t1, &y, &y);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&y, modulus, *mp);
- }
- }
- /* T1 = Z*Z */
- if (err == MP_OKAY)
- err = mp_sqr(&z, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* T2 = X' * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&Q->x, &t1, &t2);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t2, modulus, *mp);
- /* T1 = Z * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&z, &t1, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* T1 = Y' * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&Q->y, &t1, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* Y = Y - T1 */
- if (err == MP_OKAY)
- err = mp_sub(&y, &t1, &y);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&y, 0) == MP_LT)
- err = mp_add(&y, modulus, &y);
- }
- /* T1 = 2T1 */
- if (err == MP_OKAY)
- err = mp_add(&t1, &t1, &t1);
- if (err == MP_OKAY) {
- if (mp_cmp(&t1, modulus) != MP_LT)
- err = mp_sub(&t1, modulus, &t1);
- }
- /* T1 = Y + T1 */
- if (err == MP_OKAY)
- err = mp_add(&t1, &y, &t1);
- if (err == MP_OKAY) {
- if (mp_cmp(&t1, modulus) != MP_LT)
- err = mp_sub(&t1, modulus, &t1);
- }
- /* X = X - T2 */
- if (err == MP_OKAY)
- err = mp_sub(&x, &t2, &x);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&x, 0) == MP_LT)
- err = mp_add(&x, modulus, &x);
- }
- /* T2 = 2T2 */
- if (err == MP_OKAY)
- err = mp_add(&t2, &t2, &t2);
- if (err == MP_OKAY) {
- if (mp_cmp(&t2, modulus) != MP_LT)
- err = mp_sub(&t2, modulus, &t2);
- }
- /* T2 = X + T2 */
- if (err == MP_OKAY)
- err = mp_add(&t2, &x, &t2);
- if (err == MP_OKAY) {
- if (mp_cmp(&t2, modulus) != MP_LT)
- err = mp_sub(&t2, modulus, &t2);
- }
- if (err == MP_OKAY) {
- if (get_digit_count(&Q->z)) {
- /* Z = Z * Z' */
- err = mp_mul(&z, &Q->z, &z);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&z, modulus, *mp);
- }
- }
- /* Z = Z * X */
- if (err == MP_OKAY)
- err = mp_mul(&z, &x, &z);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&z, modulus, *mp);
- /* T1 = T1 * X */
- if (err == MP_OKAY)
- err = mp_mul(&t1, &x, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* X = X * X */
- if (err == MP_OKAY)
- err = mp_sqr(&x, &x);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&x, modulus, *mp);
-
- /* T2 = T2 * x */
- if (err == MP_OKAY)
- err = mp_mul(&t2, &x, &t2);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t2, modulus, *mp);
- /* T1 = T1 * X */
- if (err == MP_OKAY)
- err = mp_mul(&t1, &x, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
-
- /* X = Y*Y */
- if (err == MP_OKAY)
- err = mp_sqr(&y, &x);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&x, modulus, *mp);
- /* X = X - T2 */
- if (err == MP_OKAY)
- err = mp_sub(&x, &t2, &x);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&x, 0) == MP_LT)
- err = mp_add(&x, modulus, &x);
- }
- /* T2 = T2 - X */
- if (err == MP_OKAY)
- err = mp_sub(&t2, &x, &t2);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&t2, 0) == MP_LT)
- err = mp_add(&t2, modulus, &t2);
- }
- /* T2 = T2 - X */
- if (err == MP_OKAY)
- err = mp_sub(&t2, &x, &t2);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&t2, 0) == MP_LT)
- err = mp_add(&t2, modulus, &t2);
- }
- /* T2 = T2 * Y */
- if (err == MP_OKAY)
- err = mp_mul(&t2, &y, &t2);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t2, modulus, *mp);
- /* Y = T2 - T1 */
- if (err == MP_OKAY)
- err = mp_sub(&t2, &t1, &y);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&y, 0) == MP_LT)
- err = mp_add(&y, modulus, &y);
- }
- /* Y = Y/2 */
- if (err == MP_OKAY) {
- if (mp_isodd(&y))
- err = mp_add(&y, modulus, &y);
- }
- if (err == MP_OKAY)
- err = mp_div_2(&y, &y);
- if (err == MP_OKAY)
- err = mp_copy(&x, &R->x);
- if (err == MP_OKAY)
- err = mp_copy(&y, &R->y);
- if (err == MP_OKAY)
- err = mp_copy(&z, &R->z);
- /* clean up */
- mp_clear(&t1);
- mp_clear(&t2);
- mp_clear(&x);
- mp_clear(&y);
- mp_clear(&z);
- return err;
- }
- /**
- Double an ECC point
- P The point to double
- R [out] The destination of the double
- modulus The modulus of the field the ECC curve is in
- mp The "b" value from montgomery_setup()
- return MP_OKAY on success
- */
- int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus,
- mp_digit* mp)
- {
- mp_int t1;
- mp_int t2;
- int err;
- if (P == NULL || R == NULL || modulus == NULL || mp == NULL)
- return ECC_BAD_ARG_E;
- if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
- return err;
- }
- if (P != R) {
- err = mp_copy(&P->x, &R->x);
- if (err == MP_OKAY)
- err = mp_copy(&P->y, &R->y);
- if (err == MP_OKAY)
- err = mp_copy(&P->z, &R->z);
- }
- /* t1 = Z * Z */
- if (err == MP_OKAY)
- err = mp_sqr(&R->z, &t1);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t1, modulus, *mp);
- /* Z = Y * Z */
- if (err == MP_OKAY)
- err = mp_mul(&R->z, &R->y, &R->z);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&R->z, modulus, *mp);
- /* Z = 2Z */
- if (err == MP_OKAY)
- err = mp_add(&R->z, &R->z, &R->z);
- if (err == MP_OKAY) {
- if (mp_cmp(&R->z, modulus) != MP_LT)
- err = mp_sub(&R->z, modulus, &R->z);
- }
- /* T2 = X - T1 */
- if (err == MP_OKAY)
- err = mp_sub(&R->x, &t1, &t2);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&t2, 0) == MP_LT)
- err = mp_add(&t2, modulus, &t2);
- }
- /* T1 = X + T1 */
- if (err == MP_OKAY)
- err = mp_add(&t1, &R->x, &t1);
- if (err == MP_OKAY) {
- if (mp_cmp(&t1, modulus) != MP_LT)
- err = mp_sub(&t1, modulus, &t1);
- }
- /* T2 = T1 * T2 */
- if (err == MP_OKAY)
- err = mp_mul(&t1, &t2, &t2);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t2, modulus, *mp);
- /* T1 = 2T2 */
- if (err == MP_OKAY)
- err = mp_add(&t2, &t2, &t1);
- if (err == MP_OKAY) {
- if (mp_cmp(&t1, modulus) != MP_LT)
- err = mp_sub(&t1, modulus, &t1);
- }
- /* T1 = T1 + T2 */
- if (err == MP_OKAY)
- err = mp_add(&t1, &t2, &t1);
- if (err == MP_OKAY) {
- if (mp_cmp(&t1, modulus) != MP_LT)
- err = mp_sub(&t1, modulus, &t1);
- }
- /* Y = 2Y */
- if (err == MP_OKAY)
- err = mp_add(&R->y, &R->y, &R->y);
- if (err == MP_OKAY) {
- if (mp_cmp(&R->y, modulus) != MP_LT)
- err = mp_sub(&R->y, modulus, &R->y);
- }
- /* Y = Y * Y */
- if (err == MP_OKAY)
- err = mp_sqr(&R->y, &R->y);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&R->y, modulus, *mp);
-
- /* T2 = Y * Y */
- if (err == MP_OKAY)
- err = mp_sqr(&R->y, &t2);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&t2, modulus, *mp);
- /* T2 = T2/2 */
- if (err == MP_OKAY) {
- if (mp_isodd(&t2))
- err = mp_add(&t2, modulus, &t2);
- }
- if (err == MP_OKAY)
- err = mp_div_2(&t2, &t2);
-
- /* Y = Y * X */
- if (err == MP_OKAY)
- err = mp_mul(&R->y, &R->x, &R->y);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&R->y, modulus, *mp);
- /* X = T1 * T1 */
- if (err == MP_OKAY)
- err = mp_sqr(&t1, &R->x);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&R->x, modulus, *mp);
- /* X = X - Y */
- if (err == MP_OKAY)
- err = mp_sub(&R->x, &R->y, &R->x);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&R->x, 0) == MP_LT)
- err = mp_add(&R->x, modulus, &R->x);
- }
- /* X = X - Y */
- if (err == MP_OKAY)
- err = mp_sub(&R->x, &R->y, &R->x);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&R->x, 0) == MP_LT)
- err = mp_add(&R->x, modulus, &R->x);
- }
- /* Y = Y - X */
- if (err == MP_OKAY)
- err = mp_sub(&R->y, &R->x, &R->y);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&R->y, 0) == MP_LT)
- err = mp_add(&R->y, modulus, &R->y);
- }
- /* Y = Y * T1 */
- if (err == MP_OKAY)
- err = mp_mul(&R->y, &t1, &R->y);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&R->y, modulus, *mp);
- /* Y = Y - T2 */
- if (err == MP_OKAY)
- err = mp_sub(&R->y, &t2, &R->y);
- if (err == MP_OKAY) {
- if (mp_cmp_d(&R->y, 0) == MP_LT)
- err = mp_add(&R->y, modulus, &R->y);
- }
- /* clean up */
- mp_clear(&t1);
- mp_clear(&t2);
- return err;
- }
- /**
- Map a projective jacbobian point back to affine space
- P [in/out] The point to map
- modulus The modulus of the field the ECC curve is in
- mp The "b" value from montgomery_setup()
- return MP_OKAY on success
- */
- int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp)
- {
- mp_int t1;
- mp_int t2;
- int err;
- if (P == NULL || mp == NULL || modulus == NULL)
- return ECC_BAD_ARG_E;
- if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) {
- return MEMORY_E;
- }
- /* first map z back to normal */
- err = mp_montgomery_reduce(&P->z, modulus, *mp);
- /* get 1/z */
- if (err == MP_OKAY)
- err = mp_invmod(&P->z, modulus, &t1);
-
- /* get 1/z^2 and 1/z^3 */
- if (err == MP_OKAY)
- err = mp_sqr(&t1, &t2);
- if (err == MP_OKAY)
- err = mp_mod(&t2, modulus, &t2);
- if (err == MP_OKAY)
- err = mp_mul(&t1, &t2, &t1);
- if (err == MP_OKAY)
- err = mp_mod(&t1, modulus, &t1);
- /* multiply against x/y */
- if (err == MP_OKAY)
- err = mp_mul(&P->x, &t2, &P->x);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&P->x, modulus, *mp);
- if (err == MP_OKAY)
- err = mp_mul(&P->y, &t1, &P->y);
- if (err == MP_OKAY)
- err = mp_montgomery_reduce(&P->y, modulus, *mp);
-
- if (err == MP_OKAY)
- mp_set(&P->z, 1);
- /* clean up */
- mp_clear(&t1);
- mp_clear(&t2);
- return err;
- }
- #ifndef ECC_TIMING_RESISTANT
- /* size of sliding window, don't change this! */
- #define WINSIZE 4
- /**
- Perform a point multiplication
- k The scalar to multiply by
- G The base point
- R [out] Destination for kG
- modulus The modulus of the field the ECC curve is in
- map Boolean whether to map back to affine or not
- (1==map, 0 == leave in projective)
- return MP_OKAY on success
- */
- static int ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus,
- int map)
- {
- ecc_point *tG, *M[8];
- int i, j, err;
- mp_int mu;
- mp_digit mp;
- unsigned long buf;
- int first, bitbuf, bitcpy, bitcnt, mode, digidx;
- if (k == NULL || G == NULL || R == NULL || modulus == NULL)
- return ECC_BAD_ARG_E;
- /* init montgomery reduction */
- if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
- return err;
- }
- if ((err = mp_init(&mu)) != MP_OKAY) {
- return err;
- }
- if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) {
- mp_clear(&mu);
- return err;
- }
-
- /* alloc ram for window temps */
- for (i = 0; i < 8; i++) {
- M[i] = ecc_new_point();
- if (M[i] == NULL) {
- for (j = 0; j < i; j++) {
- ecc_del_point(M[j]);
- }
- mp_clear(&mu);
- return MEMORY_E;
- }
- }
- /* make a copy of G incase R==G */
- tG = ecc_new_point();
- if (tG == NULL)
- err = MEMORY_E;
- /* tG = G and convert to montgomery */
- if (err == MP_OKAY) {
- if (mp_cmp_d(&mu, 1) == MP_EQ) {
- err = mp_copy(&G->x, &tG->x);
- if (err == MP_OKAY)
- err = mp_copy(&G->y, &tG->y);
- if (err == MP_OKAY)
- err = mp_copy(&G->z, &tG->z);
- } else {
- err = mp_mulmod(&G->x, &mu, modulus, &tG->x);
- if (err == MP_OKAY)
- err = mp_mulmod(&G->y, &mu, modulus, &tG->y);
- if (err == MP_OKAY)
- err = mp_mulmod(&G->z, &mu, modulus, &tG->z);
- }
- }
- mp_clear(&mu);
-
- /* calc the M tab, which holds kG for k==8..15 */
- /* M[0] == 8G */
- if (err == MP_OKAY)
- err = ecc_projective_dbl_point(tG, M[0], modulus, &mp);
- if (err == MP_OKAY)
- err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
- if (err == MP_OKAY)
- err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp);
- /* now find (8+k)G for k=1..7 */
- if (err == MP_OKAY)
- for (j = 9; j < 16; j++) {
- err = ecc_projective_add_point(M[j-9], tG, M[j-8], modulus, &mp);
- if (err != MP_OKAY) break;
- }
- /* setup sliding window */
- if (err == MP_OKAY) {
- mode = 0;
- bitcnt = 1;
- buf = 0;
- digidx = get_digit_count(k) - 1;
- bitcpy = bitbuf = 0;
- first = 1;
- /* perform ops */
- for (;;) {
- /* grab next digit as required */
- if (--bitcnt == 0) {
- if (digidx == -1) {
- break;
- }
- buf = get_digit(k, digidx);
- bitcnt = (int) DIGIT_BIT;
- --digidx;
- }
- /* grab the next msb from the ltiplicand */
- i = (int)(buf >> (DIGIT_BIT - 1)) & 1;
- buf <<= 1;
- /* skip leading zero bits */
- if (mode == 0 && i == 0)
- continue;
- /* if the bit is zero and mode == 1 then we double */
- if (mode == 1 && i == 0) {
- err = ecc_projective_dbl_point(R, R, modulus, &mp);
- if (err != MP_OKAY) break;
- continue;
- }
- /* else we add it to the window */
- bitbuf |= (i << (WINSIZE - ++bitcpy));
- mode = 2;
- if (bitcpy == WINSIZE) {
- /* if this is the first window we do a simple copy */
- if (first == 1) {
- /* R = kG [k = first window] */
- err = mp_copy(&M[bitbuf-8]->x, &R->x);
- if (err != MP_OKAY) break;
- err = mp_copy(&M[bitbuf-8]->y, &R->y);
- if (err != MP_OKAY) break;
- err = mp_copy(&M[bitbuf-8]->z, &R->z);
- first = 0;
- } else {
- /* normal window */
- /* ok window is filled so double as required and add */
- /* double first */
- for (j = 0; j < WINSIZE; j++) {
- err = ecc_projective_dbl_point(R, R, modulus, &mp);
- if (err != MP_OKAY) break;
- }
- if (err != MP_OKAY) break; /* out of first for(;;) */
- /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranted */
- err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp);
- }
- if (err != MP_OKAY) break;
- /* empty window and reset */
- bitcpy = bitbuf = 0;
- mode = 1;
- }
- }
- }
- /* if bits remain then double/add */
- if (err == MP_OKAY) {
- if (mode == 2 && bitcpy > 0) {
- /* double then add */
- for (j = 0; j < bitcpy; j++) {
- /* only double if we have had at least one add first */
- if (first == 0) {
- err = ecc_projective_dbl_point(R, R, modulus, &mp);
- if (err != MP_OKAY) break;
- }
- bitbuf <<= 1;
- if ((bitbuf & (1 << WINSIZE)) != 0) {
- if (first == 1) {
- /* first add, so copy */
- err = mp_copy(&tG->x, &R->x);
- if (err != MP_OKAY) break;
- err = mp_copy(&tG->y, &R->y);
- if (err != MP_OKAY) break;
- err = mp_copy(&tG->z, &R->z);
- if (err != MP_OKAY) break;
- first = 0;
- } else {
- /* then add */
- err = ecc_projective_add_point(R, tG, R, modulus, &mp);
- if (err != MP_OKAY) break;
- }
- }
- }
- }
- }
- /* map R back from projective space */
- if (err == MP_OKAY && map)
- err = ecc_map(R, modulus, &mp);
- mp_clear(&mu);
- ecc_del_point(tG);
- for (i = 0; i < 8; i++) {
- ecc_del_point(M[i]);
- }
- return err;
- }
- #undef WINSIZE
- #endif /* ECC_TIMING_RESISTANT */
- /**
- Allocate a new ECC point
- return A newly allocated point or NULL on error
- */
- ecc_point* ecc_new_point(void)
- {
- ecc_point* p;
- p = (ecc_point*)XMALLOC(sizeof(ecc_point), 0, DYNAMIC_TYPE_BIGINT);
- if (p == NULL) {
- return NULL;
- }
- XMEMSET(p, 0, sizeof(ecc_point));
- if (mp_init_multi(&p->x, &p->y, &p->z, NULL, NULL, NULL) != MP_OKAY) {
- XFREE(p, 0, DYNAMIC_TYPE_BIGINT);
- return NULL;
- }
- return p;
- }
- /** Free an ECC point from memory
- p The point to free
- */
- void ecc_del_point(ecc_point* p)
- {
- /* prevents free'ing null arguments */
- if (p != NULL) {
- mp_clear(&p->x);
- mp_clear(&p->y);
- mp_clear(&p->z);
- XFREE(p, 0, DYNAMIC_TYPE_BIGINT);
- }
- }
- /** Returns whether an ECC idx is valid or not
- n The idx number to check
- return 1 if valid, 0 if not
- */
- static int ecc_is_valid_idx(int n)
- {
- int x;
- for (x = 0; ecc_sets[x].size != 0; x++)
- ;
- /* -1 is a valid index --- indicating that the domain params
- were supplied by the user */
- if ((n >= -1) && (n < x)) {
- return 1;
- }
- return 0;
- }
- /**
- Create an ECC shared secret between two keys
- private_key The private ECC key
- public_key The public key
- out [out] Destination of the shared secret
- Conforms to EC-DH from ANSI X9.63
- outlen [in/out] The max size and resulting size of the shared secret
- return MP_OKAY if successful
- */
- int ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
- word32* outlen)
- {
- word32 x = 0;
- ecc_point* result;
- mp_int prime;
- int err;
- if (private_key == NULL || public_key == NULL || out == NULL ||
- outlen == NULL)
- return BAD_FUNC_ARG;
- /* type valid? */
- if (private_key->type != ECC_PRIVATEKEY) {
- return ECC_BAD_ARG_E;
- }
- if (ecc_is_valid_idx(private_key->idx) == 0 ||
- ecc_is_valid_idx(public_key->idx) == 0)
- return ECC_BAD_ARG_E;
- if (XSTRNCMP(private_key->dp->name, public_key->dp->name, ECC_MAXNAME) != 0)
- return ECC_BAD_ARG_E;
- /* make new point */
- result = ecc_new_point();
- if (result == NULL) {
- return MEMORY_E;
- }
- if ((err = mp_init(&prime)) != MP_OKAY) {
- ecc_del_point(result);
- return err;
- }
- err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16);
- if (err == MP_OKAY)
- err = ecc_mulmod(&private_key->k, &public_key->pubkey, result, &prime,1);
- if (err == MP_OKAY) {
- x = mp_unsigned_bin_size(&prime);
- if (*outlen < x)
- err = BUFFER_E;
- }
- if (err == MP_OKAY) {
- XMEMSET(out, 0, x);
- err = mp_to_unsigned_bin(&result->x,out + (x -
- mp_unsigned_bin_size(&result->x)));
- *outlen = x;
- }
- mp_clear(&prime);
- ecc_del_point(result);
- return err;
- }
- int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp);
- /**
- Make a new ECC key
- rng An active RNG state
- keysize The keysize for the new key (in octets from 20 to 65 bytes)
- key [out] Destination of the newly created key
- return MP_OKAY if successful,
- upon error all allocated memory will be freed
- */
- int ecc_make_key(RNG* rng, int keysize, ecc_key* key)
- {
- int x, err;
- /* find key size */
- for (x = 0; (keysize > ecc_sets[x].size) && (ecc_sets[x].size != 0); x++)
- ;
- keysize = ecc_sets[x].size;
- if (keysize > ECC_MAXSIZE || ecc_sets[x].size == 0) {
- return BAD_FUNC_ARG;
- }
- err = ecc_make_key_ex(rng, key, &ecc_sets[x]);
- key->idx = x;
- return err;
- }
- int ecc_make_key_ex(RNG* rng, ecc_key* key, const ecc_set_type* dp)
- {
- int err;
- ecc_point* base;
- mp_int prime;
- mp_int order;
- byte buf[ECC_MAXSIZE];
- int keysize;
- if (key == NULL || rng == NULL || dp == NULL)
- return ECC_BAD_ARG_E;
- key->idx = -1;
- key->dp = dp;
- keysize = dp->size;
- /* allocate ram */
- base = NULL;
- /* make up random string */
- RNG_GenerateBlock(rng, buf, keysize);
- buf[0] |= 0x0c;
- /* setup the key variables */
- if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
- &key->k, &prime, &order)) != MP_OKAY)
- return MEMORY_E;
- base = ecc_new_point();
- if (base == NULL)
- err = MEMORY_E;
- /* read in the specs for this key */
- if (err == MP_OKAY)
- err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
- if (err == MP_OKAY)
- err = mp_read_radix(&order, (char *)key->dp->order, 16);
- if (err == MP_OKAY)
- err = mp_read_radix(&base->x, (char *)key->dp->Gx, 16);
- if (err == MP_OKAY)
- err = mp_read_radix(&base->y, (char *)key->dp->Gy, 16);
-
- if (err == MP_OKAY)
- mp_set(&base->z, 1);
- if (err == MP_OKAY)
- err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize);
- /* the key should be smaller than the order of base point */
- if (err == MP_OKAY) {
- if (mp_cmp(&key->k, &order) != MP_LT)
- err = mp_mod(&key->k, &order, &key->k);
- }
- /* make the public key */
- if (err == MP_OKAY)
- err = ecc_mulmod(&key->k, base, &key->pubkey, &prime, 1);
- if (err == MP_OKAY)
- key->type = ECC_PRIVATEKEY;
- if (err != MP_OKAY) {
- /* clean up */
- mp_clear(&key->pubkey.x);
- mp_clear(&key->pubkey.y);
- mp_clear(&key->pubkey.z);
- mp_clear(&key->k);
- }
- ecc_del_point(base);
- mp_clear(&prime);
- mp_clear(&order);
- #ifdef ECC_CLEAN_STACK
- XMEMSET(buff, 0, ECC_MAXSIZE);
- #endif
- return err;
- }
- /* Setup dynamic pointers is using normal math for proper freeing */
- void ecc_init(ecc_key* key)
- {
- (void)key;
- #ifndef USE_FAST_MATH
- key->pubkey.x.dp = NULL;
- key->pubkey.y.dp = NULL;
- key->pubkey.z.dp = NULL;
- key->k.dp = NULL;
- #endif
- }
- /**
- Sign a message digest
- in The message digest to sign
- inlen The length of the digest
- out [out] The destination for the signature
- outlen [in/out] The max size and resulting size of the signature
- key A private ECC key
- return MP_OKAY if successful
- */
- int ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
- RNG* rng, ecc_key* key)
- {
- mp_int r;
- mp_int s;
- mp_int e;
- mp_int p;
- int err;
- if (in == NULL || out == NULL || outlen == NULL || key == NULL || rng ==NULL)
- return ECC_BAD_ARG_E;
- /* is this a private key? */
- if (key->type != ECC_PRIVATEKEY) {
- return ECC_BAD_ARG_E;
- }
-
- /* is the IDX valid ? */
- if (ecc_is_valid_idx(key->idx) != 1) {
- return ECC_BAD_ARG_E;
- }
- /* get the hash and load it as a bignum into 'e' */
- /* init the bignums */
- if ((err = mp_init_multi(&r, &s, &p, &e, NULL, NULL)) != MP_OKAY) {
- return err;
- }
- err = mp_read_radix(&p, (char *)key->dp->order, 16);
- if (err == MP_OKAY) {
- int truncLen = (int)inlen;
- if (truncLen > ecc_size(key))
- truncLen = ecc_size(key);
- err = mp_read_unsigned_bin(&e, (byte*)in, truncLen);
- }
- /* make up a key and export the public copy */
- if (err == MP_OKAY) {
- ecc_key pubkey;
- ecc_init(&pubkey);
- for (;;) {
- err = ecc_make_key_ex(rng, &pubkey, key->dp);
- if (err != MP_OKAY) break;
- /* find r = x1 mod n */
- err = mp_mod(&pubkey.pubkey.x, &p, &r);
- if (err != MP_OKAY) break;
- if (mp_iszero(&r) == MP_YES)
- ecc_free(&pubkey);
- else {
- /* find s = (e + xr)/k */
- err = mp_invmod(&pubkey.k, &p, &pubkey.k);
- if (err != MP_OKAY) break;
- err = mp_mulmod(&key->k, &r, &p, &s); /* s = xr */
- if (err != MP_OKAY) break;
-
- err = mp_add(&e, &s, &s); /* s = e + xr */
- if (err != MP_OKAY) break;
- err = mp_mod(&s, &p, &s); /* s = e + xr */
- if (err != MP_OKAY) break;
- err = mp_mulmod(&s, &pubkey.k, &p, &s); /* s = (e + xr)/k */
- if (err != MP_OKAY) break;
- ecc_free(&pubkey);
- if (mp_iszero(&s) == MP_NO)
- break;
- }
- }
- ecc_free(&pubkey);
- }
- /* store as SEQUENCE { r, s -- integer } */
- if (err == MP_OKAY)
- err = StoreECC_DSA_Sig(out, outlen, &r, &s);
- mp_clear(&r);
- mp_clear(&s);
- mp_clear(&p);
- mp_clear(&e);
- return err;
- }
- /**
- Free an ECC key from memory
- key The key you wish to free
- */
- void ecc_free(ecc_key* key)
- {
- if (key == NULL)
- return;
- mp_clear(&key->pubkey.x);
- mp_clear(&key->pubkey.y);
- mp_clear(&key->pubkey.z);
- mp_clear(&key->k);
- }
- /* verify
- *
- * w = s^-1 mod n
- * u1 = xw
- * u2 = rw
- * X = u1*G + u2*Q
- * v = X_x1 mod n
- * accept if v == r
- */
- /**
- Verify an ECC signature
- sig The signature to verify
- siglen The length of the signature (octets)
- hash The hash (message digest) that was signed
- hashlen The length of the hash (octets)
- stat Result of signature, 1==valid, 0==invalid
- key The corresponding public ECC key
- return MP_OKAY if successful (even if the signature is not valid)
- */
- int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen,
- int* stat, ecc_key* key)
- {
- ecc_point *mG, *mQ;
- mp_int r;
- mp_int s;
- mp_int v;
- mp_int w;
- mp_int u1;
- mp_int u2;
- mp_int e;
- mp_int p;
- mp_int m;
- mp_digit mp;
- int err;
- if (sig == NULL || hash == NULL || stat == NULL || key == NULL)
- return ECC_BAD_ARG_E;
- /* default to invalid signature */
- *stat = 0;
- /* is the IDX valid ? */
- if (ecc_is_valid_idx(key->idx) != 1) {
- return ECC_BAD_ARG_E;
- }
- /* allocate ints */
- if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) {
- return MEMORY_E;
- }
- if ((err = mp_init(&m)) != MP_OKAY) {
- mp_clear(&v);
- mp_clear(&w);
- mp_clear(&u1);
- mp_clear(&u2);
- mp_clear(&p);
- mp_clear(&e);
- return MEMORY_E;
- }
- /* allocate points */
- mG = ecc_new_point();
- mQ = ecc_new_point();
- if (mQ == NULL || mG == NULL)
- err = MEMORY_E;
- /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s.
- * If either of those don't allocate correctly, none of
- * the rest of this function will execute, and everything
- * gets cleaned up at the end. */
- XMEMSET(&r, 0, sizeof(r));
- XMEMSET(&s, 0, sizeof(s));
- if (err == MP_OKAY)
- err = DecodeECC_DSA_Sig(sig, siglen, &r, &s);
- /* get the order */
- if (err == MP_OKAY)
- err = mp_read_radix(&p, (char *)key->dp->order, 16);
- /* get the modulus */
- if (err == MP_OKAY)
- err = mp_read_radix(&m, (char *)key->dp->prime, 16);
- /* check for zero */
- if (err == MP_OKAY) {
- if (mp_iszero(&r) || mp_iszero(&s) || mp_cmp(&r, &p) != MP_LT ||
- mp_cmp(&s, &p) != MP_LT)
- err = MP_ZERO_E;
- }
- /* read hash */
- if (err == MP_OKAY) {
- int truncLen = (int)hashlen;
- if (truncLen > ecc_size(key))
- truncLen = ecc_size(key);
- err = mp_read_unsigned_bin(&e, (byte*)hash, truncLen);
- }
- /* w = s^-1 mod n */
- if (err == MP_OKAY)
- err = mp_invmod(&s, &p, &w);
- /* u1 = ew */
- if (err == MP_OKAY)
- err = mp_mulmod(&e, &w, &p, &u1);
- /* u2 = rw */
- if (err == MP_OKAY)
- err = mp_mulmod(&r, &w, &p, &u2);
- /* find mG and mQ */
- if (err == MP_OKAY)
- err = mp_read_radix(&mG->x, (char *)key->dp->Gx, 16);
- if (err == MP_OKAY)
- err = mp_read_radix(&mG->y, (char *)key->dp->Gy, 16);
- if (err == MP_OKAY)
- mp_set(&mG->z, 1);
- if (err == MP_OKAY)
- err = mp_copy(&key->pubkey.x, &mQ->x);
- if (err == MP_OKAY)
- err = mp_copy(&key->pubkey.y, &mQ->y);
- if (err == MP_OKAY)
- err = mp_copy(&key->pubkey.z, &mQ->z);
- #ifndef ECC_SHAMIR
- /* compute u1*mG + u2*mQ = mG */
- if (err == MP_OKAY)
- err = ecc_mulmod(&u1, mG, mG, &m, 0);
- if (err == MP_OKAY)
- err = ecc_mulmod(&u2, mQ, mQ, &m, 0);
-
- /* find the montgomery mp */
- if (err == MP_OKAY)
- err = mp_montgomery_setup(&m, &mp);
- /* add them */
- if (err == MP_OKAY)
- err = ecc_projective_add_point(mQ, mG, mG, &m, &mp);
-
- /* reduce */
- if (err == MP_OKAY)
- err = ecc_map(mG, &m, &mp);
- #else
- /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
- if (err == MP_OKAY)
- err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &m);
- #endif /* ECC_SHAMIR */
- /* v = X_x1 mod n */
- if (err == MP_OKAY)
- err = mp_mod(&mG->x, &p, &v);
- /* does v == r */
- if (err == MP_OKAY) {
- if (mp_cmp(&v, &r) == MP_EQ)
- *stat = 1;
- }
- ecc_del_point(mG);
- ecc_del_point(mQ);
- mp_clear(&r);
- mp_clear(&s);
- mp_clear(&v);
- mp_clear(&w);
- mp_clear(&u1);
- mp_clear(&u2);
- mp_clear(&p);
- mp_clear(&e);
- mp_clear(&m);
- return err;
- }
- /* export public ECC key in ANSI X9.63 format */
- int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
- {
- byte buf[ECC_BUFSIZE];
- word32 numlen;
- if (key == NULL || out == NULL || outLen == NULL)
- return ECC_BAD_ARG_E;
- if (ecc_is_valid_idx(key->idx) == 0) {
- return ECC_BAD_ARG_E;
- }
- numlen = key->dp->size;
- if (*outLen < (1 + 2*numlen)) {
- *outLen = 1 + 2*numlen;
- return BUFFER_E;
- }
- /* store byte 0x04 */
- out[0] = 0x04;
- /* pad and store x */
- XMEMSET(buf, 0, sizeof(buf));
- mp_to_unsigned_bin(&key->pubkey.x,
- buf + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
- XMEMCPY(out+1, buf, numlen);
- /* pad and store y */
- XMEMSET(buf, 0, sizeof(buf));
- mp_to_unsigned_bin(&key->pubkey.y,
- buf + (numlen - mp_unsigned_bin_size(&key->pubkey.y)));
- XMEMCPY(out+1+numlen, buf, numlen);
- *outLen = 1 + 2*numlen;
- return 0;
- }
- /* import public ECC key in ANSI X9.63 format */
- int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
- {
- int x, err;
-
- if (in == NULL || key == NULL)
- return ECC_BAD_ARG_E;
- /* must be odd */
- if ((inLen & 1) == 0) {
- return ECC_BAD_ARG_E;
- }
- /* init key */
- if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
- NULL, NULL) != MP_OKAY) {
- return MEMORY_E;
- }
- err = MP_OKAY;
- /* check for 4, 6 or 7 */
- if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
- err = ASN_PARSE_E;
- }
- /* read data */
- if (err == MP_OKAY)
- err = mp_read_unsigned_bin(&key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
- if (err == MP_OKAY)
- err = mp_read_unsigned_bin(&key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
- (inLen-1)>>1);
-
- if (err == MP_OKAY)
- mp_set(&key->pubkey.z, 1);
- if (err == MP_OKAY) {
- /* determine the idx */
- for (x = 0; ecc_sets[x].size != 0; x++) {
- if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) {
- break;
- }
- }
- if (ecc_sets[x].size == 0) {
- err = ASN_PARSE_E;
- } else {
- /* set the idx */
- key->idx = x;
- key->dp = &ecc_sets[x];
- key->type = ECC_PUBLICKEY;
- }
- }
- if (err != MP_OKAY) {
- mp_clear(&key->pubkey.x);
- mp_clear(&key->pubkey.y);
- mp_clear(&key->pubkey.z);
- mp_clear(&key->k);
- }
- return err;
- }
- /* ecc private key import, public key in ANSI X9.63 format, private raw */
- int ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
- word32 pubSz, ecc_key* key)
- {
- int ret = ecc_import_x963(pub, pubSz, key);
- if (ret != 0)
- return ret;
- key->type = ECC_PRIVATEKEY;
- return mp_read_unsigned_bin(&key->k, priv, privSz);
- }
- /* key size in octets */
- int ecc_size(ecc_key* key)
- {
- if (key == NULL) return 0;
- return key->dp->size;
- }
- /* signature size in octets */
- int ecc_sig_size(ecc_key* key)
- {
- int sz = ecc_size(key);
- if (sz < 0)
- return sz;
- return sz * 2 + SIG_HEADER_SZ;
- }
- #endif /* HAVE_ECC */