diff --git a/configure.ac b/configure.ac index aad0843f2..3132eca12 100644 --- a/configure.ac +++ b/configure.ac @@ -768,6 +768,18 @@ fi AM_CONDITIONAL([BUILD_ECC], [test "x$ENABLED_ECC" = "xyes"]) +# ECC Custom Curves +AC_ARG_ENABLE([ecccustcurves], + [AS_HELP_STRING([--enable-ecccustcurves],[Enable ECC custom curves (default: disabled)])], + [ ENABLED_ECCCUSTCURVES=$enableval ], + [ ENABLED_ECCCUSTCURVES=no ] + ) + +if test "$ENABLED_ECCCUSTCURVES" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_CUSTOM_CURVES" +fi + # for using memory optimization setting on both curve25519 and ed25519 ENABLED_CURVED25519_SMALL=no diff --git a/src/ssl.c b/src/ssl.c index 4a45ba34e..e50898458 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -16341,7 +16341,7 @@ int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) } switch(group->curve_nid) { - case NID_X9_62_prime256v1: + case NID_secp256k1: return 256; case NID_secp384r1: return 384; @@ -16527,7 +16527,7 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) { - mp_int prime; + mp_int a, prime; (void)ctx; (void)n; @@ -16549,25 +16549,29 @@ int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, } } - /* compute the prime value of the curve */ - if (mp_init(&prime) != MP_OKAY) { - WOLFSSL_MSG("wolfSSL_EC_POINT_mul init BN failed"); + /* read the curve prime and a */ + if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_POINT_mul init 'prime/A' failed"); return SSL_FAILURE; } - if (mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, 16) != MP_OKAY){ - WOLFSSL_MSG("wolfSSL_EC_POINT_mul read prime curve value failed"); + WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'prime' curve value failed"); + return SSL_FAILURE; + } + if (mp_read_radix(&a, ecc_sets[group->curve_idx].Af, 16) != MP_OKAY){ + WOLFSSL_MSG("wolfSSL_EC_POINT_mul read 'A' curve value failed"); return SSL_FAILURE; } /* r = q * m % prime */ if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, - (ecc_point*)r->internal, &prime, 1) != MP_OKAY) { + (ecc_point*)r->internal, &a, &prime, 1) != MP_OKAY) { WOLFSSL_MSG("ecc_mulmod failure"); mp_clear(&prime); return SSL_FAILURE; } + mp_clear(&a); mp_clear(&prime); /* set the external value for the computed point */ diff --git a/wolfcrypt/src/asm.c b/wolfcrypt/src/asm.c index 8976204c6..0f91c8c9f 100644 --- a/wolfcrypt/src/asm.c +++ b/wolfcrypt/src/asm.c @@ -136,7 +136,7 @@ __asm__( \ "adcl $0,%%edx \n\t" \ "movl %%edx,%1 \n\t" \ :"=g"(_c[LO]), "=r"(cy) \ -:"0"(_c[LO]), "1"(cy), "g"(mu), "g"(*tmpm++) \ +:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ : "%eax", "%edx", "cc") #define PROPCARRY \ @@ -533,25 +533,21 @@ __asm__( \ mu = c[x] * mp #define INNERMUL \ -__asm__( \ +__asm__( \ " mullw 16,%3,%4 \n\t" \ " mulhwu 17,%3,%4 \n\t" \ - " addc 16,16,%0 \n\t" \ + " addc 16,16,%2 \n\t" \ " addze 17,17 \n\t" \ - " lwz 18,%1 \n\t" \ - " addc 16,16,18 \n\t" \ + " addc %1,16,%5 \n\t" \ " addze %0,17 \n\t" \ - " stw 16,%1 \n\t" \ -:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "18","cc"); ++tmpm; +:"=r"(cy),"=r"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "cc"); ++tmpm; #define PROPCARRY \ -__asm__( \ - " lwz 16,%1 \n\t" \ - " addc 16,16,%0 \n\t" \ - " stw 16,%1 \n\t" \ - " xor %0,%0,%0 \n\t" \ - " addze %0,%0 \n\t" \ -:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"16","cc"); +__asm__( \ + " addc %1,%3,%2 \n\t" \ + " xor %0,%2,%2 \n\t" \ + " addze %0,%2 \n\t" \ +:"=r"(cy),"=r"(_c[0]):"0"(cy),"1"(_c[0]):"cc"); #elif defined(TFM_PPC64) @@ -740,7 +736,7 @@ __asm__( \ "addq %%rax,%0 \n\t" \ "adcq %%rdx,%1 \n\t" \ "adcq $0,%2 \n\t" \ - :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i) :"%rax","%rdx","cc"); + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "x"(i) :"%rax","%rdx","cc"); #define SQRADD2(i, j) \ __asm__( \ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 0f05bd463..4bd19bff3 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -40,7 +40,9 @@ Possible ECC enable options: * ECC_SHAMIR: Enables Shamir calc method default: on * HAVE_COMP_KEY: Enables compressed key default: off * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import default: off -*/ + * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off + * Includes the curve "a" variable in calculation + */ /* ECC Curves: @@ -80,13 +82,17 @@ ECC Curves: #include #endif +#ifdef USE_FAST_MATH + #define GEN_MEM_ERR FP_MEM +#else + #define GEN_MEM_ERR MP_MEM +#endif + + /* map - ptmul -> mulmod - */ - /* p256 curve on by default whether user curves or not */ #if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) #define ECC112 @@ -115,112 +121,112 @@ ECC Curves: -/* This holds the key settings. ***MUST*** be organized by size from - smallest to largest. */ +/* This holds the key settings. + ***MUST*** be organized by size from smallest to largest. */ const ecc_set_type ecc_sets[] = { #ifdef ECC112 { - 14, - NID_secp112r1, - "SECP112R1", - "DB7C2ABF62E35E668076BEAD208B", - "DB7C2ABF62E35E668076BEAD2088", - "659EF8BA043916EEDE8911702B22", - "DB7C2ABF62E35E7628DFAC6561C5", - "09487239995A5EE76B55F9C2F098", - "A89CE5AF8724C0A23E0E0FF77500" + 14, /* size/bytes */ + NID_secp112r1, /* NID */ + "SECP112R1", /* curve name */ + "DB7C2ABF62E35E668076BEAD208B", /* prime */ + "DB7C2ABF62E35E668076BEAD2088", /* A */ + "659EF8BA043916EEDE8911702B22", /* B */ + "DB7C2ABF62E35E7628DFAC6561C5", /* order */ + "9487239995A5EE76B55F9C2F098", /* Gx */ + "A89CE5AF8724C0A23E0E0FF77500", /* Gy */ }, #endif #ifdef ECC128 { - 16, - NID_secp128r1, - "SECP128R1", - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", - "E87579C11079F43DD824993C2CEE5ED3", - "FFFFFFFE0000000075A30D1B9038A115", - "161FF7528B899B2D0C28607CA52C5B86", - "CF5AC8395BAFEB13C02DA292DDED7A83", + 16, /* size/bytes */ + NID_secp128r1, /* NID */ + "SECP128R1", /* curve name */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "E87579C11079F43DD824993C2CEE5ED3", /* B */ + "FFFFFFFE0000000075A30D1B9038A115", /* order */ + "161FF7528B899B2D0C28607CA52C5B86", /* Gx */ + "CF5AC8395BAFEB13C02DA292DDED7A83", /* Gy */ }, #endif #ifdef ECC160 { - 20, - NID_secp160r1, - "SECP160R1", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", - "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", - "0100000000000000000001F4C8F927AED3CA752257", - "4A96B5688EF573284664698968C38BB913CBFC82", - "23A628553168947D59DCC912042351377AC5FB32", + 20, /* size/bytes */ + NID_secp160r1, /* NID */ + "SECP160R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", /* A */ + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", /* B */ + "100000000000000000001F4C8F927AED3CA752257",/* order */ + "4A96B5688EF573284664698968C38BB913CBFC82", /* Gx */ + "23A628553168947D59DCC912042351377AC5FB32", /* Gy */ }, #endif #ifdef ECC192 { - 24, - NID_cert192, - "ECC-192", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", - "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", - "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", - "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", - "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", + 24, /* size/bytes */ + NID_secp192k1, /* NID */ + "SECP192R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order */ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx */ + "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* Gy */ }, #endif #ifdef ECC224 { - 28, - NID_cert224, - "ECC-224", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", - "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", - "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", - "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", + 28, /* size/bytes */ + NID_secp224r1, /* NID */ + "SECP224R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* A */ + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */ }, #endif #ifdef ECC256 { - 32, - NID_X9_62_prime256v1, - "nistp256", - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", - "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", - "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", - "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", - "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", - "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", + 32, /* size/bytes */ + NID_secp256k1, /* NID */ + "SECP256R1", /* curve name */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* B */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* order */ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gx */ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy */ }, #endif #ifdef ECC384 { - 48, - NID_secp384r1, - "nistp384", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", - "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", - "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", - "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", + 48, /* size/bytes */ + NID_secp384r1, /* NID */ + "SECP384R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* A */ + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* order */ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gx */ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* Gy */ }, #endif #ifdef ECC521 { - 66, - NID_secp521r1, - "nistp521", - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", - "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", - "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", - "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", + 66, /* size/bytes */ + NID_secp521r1, /* NID */ + "SECP521R1", /* curve name */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", /* B */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* order */ + "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", /* Gx */ + "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* Gy */ }, #endif { @@ -230,20 +236,19 @@ const ecc_set_type ecc_sets[] = { }; -int ecc_map(ecc_point*, mp_int*, mp_digit*); +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); -static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order); + mp_int* a, mp_int* modulus, mp_digit mp); +int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, + mp_int* modulus, mp_digit mp); +static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, mp_int* order); #ifdef ECC_SHAMIR static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus, void* heap); + ecc_point* C, mp_int* a, mp_int* modulus, void* heap); #endif -int mp_jacobi(mp_int* a, mp_int* p, int* c); +int mp_jacobi(mp_int* a, mp_int* n, int* c); int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); -int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d); #ifdef HAVE_COMP_KEY static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); @@ -267,18 +272,18 @@ static mp_digit get_digit(mp_int* a, int n) 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 + a ECC curve parameter a 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* a, mp_int* modulus, mp_digit mp) { mp_int t1, t2; #ifdef ALT_ECC_SIZE @@ -287,7 +292,7 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, mp_int *x, *y, *z; int err; - if (P == NULL || Q == NULL || R == NULL || modulus == NULL || mp == NULL) { + if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; } @@ -311,7 +316,7 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) { mp_clear(&t1); mp_clear(&t2); - return ecc_projective_dbl_point(P, R, modulus, mp); + return ecc_projective_dbl_point(P, R, a, modulus, mp); } } @@ -354,25 +359,25 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, /* T1 = Z' * Z' */ err = mp_sqr(Q->z, &t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + 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); + 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); + 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); + err = mp_montgomery_reduce(y, modulus, mp); } } @@ -380,25 +385,25 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if (err == MP_OKAY) err = mp_sqr(z, &t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + 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); + 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); + 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); + err = mp_montgomery_reduce(&t1, modulus, mp); /* Y = Y - T1 */ if (err == MP_OKAY) @@ -448,7 +453,7 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, /* Z = Z * Z' */ err = mp_mul(z, Q->z, z); if (err == MP_OKAY) - err = mp_montgomery_reduce(z, modulus, *mp); + err = mp_montgomery_reduce(z, modulus, mp); } } @@ -456,37 +461,37 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if (err == MP_OKAY) err = mp_mul(z, x, z); if (err == MP_OKAY) - err = mp_montgomery_reduce(z, modulus, *mp); + 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); + 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); + 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); + 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); + 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); + err = mp_montgomery_reduce(x, modulus, mp); /* X = X - T2 */ if (err == MP_OKAY) @@ -513,7 +518,7 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if (err == MP_OKAY) err = mp_mul(&t2, y, &t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(&t2, modulus, mp); /* Y = T2 - T1 */ if (err == MP_OKAY) @@ -524,7 +529,7 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, } /* Y = Y/2 */ if (err == MP_OKAY) { - if (mp_isodd(y)) + if (mp_isodd(y) == MP_YES) err = mp_add(y, modulus, y); } if (err == MP_OKAY) @@ -548,17 +553,35 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, return err; } +/* ### Point doubling in Jacobian coordinate system ### + * + * let us have a curve: y^2 = x^3 + a*x + b + * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 + * + * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: + * Xr = M^2 - 2*S + * Yr = M * (S - Xr) - 8*T + * Zr = 2 * Yp * Zp + * + * M = 3 * Xp^2 + a*Zp^4 + * T = Yp^4 + * S = 4 * Xp * Yp^2 + * + * SPECIAL CASE: when a == 3 we can compute M as + * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) + */ /** Double an ECC point P The point to double R [out] The destination of the double + a ECC curve parameter a 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) +int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, + mp_int* modulus, mp_digit mp) { mp_int t1, t2; #ifdef ALT_ECC_SIZE @@ -567,7 +590,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, mp_int *x, *y, *z; int err; - if (P == NULL || R == NULL || modulus == NULL || mp == NULL) + if (P == NULL || R == NULL || modulus == NULL) return ECC_BAD_ARG_E; if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { @@ -601,17 +624,17 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) err = mp_copy(P->z, z); - /* t1 = Z * Z */ + /* T1 = Z * Z */ if (err == MP_OKAY) err = mp_sqr(z, &t1); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t1, modulus, *mp); + err = mp_montgomery_reduce(&t1, modulus, mp); /* Z = Y * Z */ if (err == MP_OKAY) err = mp_mul(z, y, z); if (err == MP_OKAY) - err = mp_montgomery_reduce(z, modulus, *mp); + err = mp_montgomery_reduce(z, modulus, mp); /* Z = 2Z */ if (err == MP_OKAY) @@ -621,6 +644,46 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, err = mp_sub(z, modulus, z); } + /* Determine if curve "a" should be used in calc */ +#ifdef WOLFSSL_CUSTOM_CURVES + /* T2 = T1 * T1 */ + if (err == MP_OKAY) + err = mp_sqr(&t1, &t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T2 * a */ + if (err == MP_OKAY) + err = mp_mulmod(&t2, a, modulus, &t1); + /* T2 = X * X */ + if (err == MP_OKAY) + err = mp_sqr(x, &t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(&t2, modulus, mp); + /* T1 = T2 + T1 */ + 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); + } + /* T1 = T2 + T1 */ + 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); + } + /* T1 = T2 + T1 */ + 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); + } +#else + /* Assumes a = 3 */ + (void)a; + /* T2 = X - T1 */ if (err == MP_OKAY) err = mp_sub(x, &t1, &t2); @@ -639,7 +702,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) err = mp_mul(&t1, &t2, &t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(&t2, modulus, mp); /* T1 = 2T2 */ if (err == MP_OKAY) @@ -655,6 +718,8 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (mp_cmp(&t1, modulus) != MP_LT) err = mp_sub(&t1, modulus, &t1); } +#endif /* WOLFSSL_CUSTOM_CURVES */ + /* Y = 2Y */ if (err == MP_OKAY) err = mp_add(y, y, y); @@ -666,17 +731,17 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) err = mp_sqr(y, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); /* T2 = Y * Y */ if (err == MP_OKAY) err = mp_sqr(y, &t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, *mp); + err = mp_montgomery_reduce(&t2, modulus, mp); /* T2 = T2/2 */ if (err == MP_OKAY) { - if (mp_isodd(&t2)) + if (mp_isodd(&t2) == MP_YES) err = mp_add(&t2, modulus, &t2); } if (err == MP_OKAY) @@ -686,13 +751,13 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) err = mp_mul(y, x, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); - /* X = T1 * T1 */ + /* X = T1 * T1 */ if (err == MP_OKAY) err = mp_sqr(&t1, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(x, modulus, *mp); + err = mp_montgomery_reduce(x, modulus, mp); /* X = X - Y */ if (err == MP_OKAY) @@ -708,6 +773,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (mp_cmp_d(x, 0) == MP_LT) err = mp_add(x, modulus, x); } + /* Y = Y - X */ if (err == MP_OKAY) err = mp_sub(y, x, y); @@ -719,7 +785,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) err = mp_mul(y, &t1, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); /* Y = Y - T2 */ if (err == MP_OKAY) @@ -755,13 +821,16 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* modulus, mp The "b" value from montgomery_setup() return MP_OKAY on success */ -int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) +int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) { - mp_int t1; - mp_int t2; + mp_int t1, t2; +#ifdef ALT_ECC_SIZE + mp_int rx, ry, rz; +#endif + mp_int *x, *y, *z; int err; - if (P == NULL || mp == NULL || modulus == NULL) + if (P == NULL || modulus == NULL) return ECC_BAD_ARG_E; /* special case for point at infinity */ @@ -776,12 +845,37 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) return MEMORY_E; } +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = ℞ + y = &ry; + z = &rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + mp_clear(&t1); + mp_clear(&t2); + return err; + } + + 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); +#else + /* Use destination directly */ + x = P->x; + y = P->y; + z = P->z; +#endif + /* first map z back to normal */ - err = mp_montgomery_reduce(P->z, modulus, *mp); + err = mp_montgomery_reduce(z, modulus, mp); /* get 1/z */ if (err == MP_OKAY) - err = mp_invmod(P->z, modulus, &t1); + err = mp_invmod(z, modulus, &t1); /* get 1/z^2 and 1/z^3 */ if (err == MP_OKAY) @@ -795,20 +889,29 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) /* multiply against x/y */ if (err == MP_OKAY) - err = mp_mul(P->x, &t2, P->x); + err = mp_mul(x, &t2, x); if (err == MP_OKAY) - err = mp_montgomery_reduce(P->x, modulus, *mp); + err = mp_montgomery_reduce(x, modulus, mp); if (err == MP_OKAY) - err = mp_mul(P->y, &t1, P->y); + err = mp_mul(y, &t1, y); if (err == MP_OKAY) - err = mp_montgomery_reduce(P->y, modulus, *mp); + err = mp_montgomery_reduce(y, modulus, mp); if (err == MP_OKAY) - mp_set(P->z, 1); + mp_set(z, 1); +#ifdef ALT_ECC_SIZE + /* return result */ + mp_copy(x, P->x); + mp_copy(y, P->y); + mp_copy(z, P->z); +#endif + +#ifndef USE_FAST_MATH /* clean up */ mp_clear(&t1); mp_clear(&t2); +#endif return err; } @@ -824,6 +927,7 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) k The scalar to multiply by G The base point R [out] Destination for kG + a ECC curve parameter a 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) @@ -831,13 +935,13 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit* mp) */ #ifdef FP_ECC static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, void* heap) #else int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, void* heap) #endif { - ecc_point *tG, *M[8]; + ecc_point *tG, *M[8]; int i, j, err; mp_int mu; mp_digit mp; @@ -848,17 +952,16 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (k == NULL || G == NULL || R == NULL || modulus == NULL) return ECC_BAD_ARG_E; + /* init variables */ + tG = NULL; + XMEMSET(M, 0, sizeof(M)); + err = mp_init(&mu); + /* 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; - } + if (err == MP_OKAY) + err = mp_montgomery_setup(modulus, &mp); + if (err == MP_OKAY) + err = mp_montgomery_calc_normalization(&mu, modulus); /* alloc ram for window temps */ for (i = 0; i < 8; i++) { @@ -893,21 +996,23 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, err = mp_mulmod(G->z, &mu, modulus, tG->z); } } + + /* done with mu */ 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); + err = ecc_projective_dbl_point(tG, M[0], a, modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp); + err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[0], M[0], modulus, &mp); + err = ecc_projective_dbl_point(M[0], M[0], a, 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); + err = ecc_projective_add_point(M[j-9], tG, M[j-8], a, modulus, mp); if (err != MP_OKAY) break; } @@ -942,7 +1047,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* 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); + err = ecc_projective_dbl_point(R, R, a, modulus, mp); if (err != MP_OKAY) break; continue; } @@ -968,13 +1073,14 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* 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); + err = ecc_projective_dbl_point(R, R, a, 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] guaranteed */ - err = ecc_projective_add_point(R,M[bitbuf-8],R,modulus,&mp); + err = ecc_projective_add_point(R, M[bitbuf-8], R, a, + modulus, mp); } if (err != MP_OKAY) break; /* empty window and reset */ @@ -991,7 +1097,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, 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); + err = ecc_projective_dbl_point(R, R, a, modulus, mp); if (err != MP_OKAY) break; } @@ -1010,7 +1116,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, first = 0; } else { /* then add */ - err = ecc_projective_add_point(R, tG, R, modulus, &mp); + err = ecc_projective_add_point(R, tG, R, a, modulus, + mp); if (err != MP_OKAY) break; } } @@ -1020,9 +1127,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* map R back from projective space */ if (err == MP_OKAY && map) - err = ecc_map(R, modulus, &mp); + err = ecc_map(R, modulus, mp); - mp_clear(&mu); wc_ecc_del_point_h(tG, heap); for (i = 0; i < 8; i++) { wc_ecc_del_point_h(M[i], heap); @@ -1031,10 +1137,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, } #ifndef FP_ECC -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map) +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map) { - return wc_ecc_mulmod_ex(k, G, R, modulus, map, NULL); + return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } #endif /* ! FP_ECC */ #undef WINSIZE @@ -1046,6 +1152,7 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, k The scalar to multiply by G The base point R [out] Destination for kG + a ECC curve parameter a 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) @@ -1053,14 +1160,14 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, */ #ifdef FP_ECC static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, void* heap) #else int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map, void* heap) + mp_int* a, mp_int* modulus, int map, void* heap) #endif { ecc_point *tG, *M[3]; - int i, j, err; + int i, err; mp_int mu; mp_digit mp; mp_digit buf; @@ -1069,17 +1176,16 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, if (k == NULL || G == NULL || R == NULL || modulus == NULL) return ECC_BAD_ARG_E; + /* init variables */ + tG = NULL; + XMEMSET(M, 0, sizeof(M)); + err = mp_init(&mu); + /* 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; - } + if (err == MP_OKAY) + err = mp_montgomery_setup(modulus, &mp); + if (err == MP_OKAY) + err = mp_montgomery_calc_normalization(&mu, modulus); /* alloc ram for window temps */ for (i = 0; i < 3; i++) { @@ -1088,10 +1194,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, for (j = 0; j < i; j++) { wc_ecc_del_point(M[j]); } - mp_clear(&mu); - return MEMORY_E; } - } + } /* make a copy of G in case R==G */ tG = wc_ecc_new_point_h(heap); @@ -1099,13 +1203,14 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, err = MEMORY_E; /* tG = G and convert to montgomery */ - if (err == MP_OKAY) { + if (err == MP_OKAY) 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); - } + 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); + + /* done with mu */ mp_clear(&mu); /* calc the M tab */ @@ -1119,7 +1224,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* M[1] == 2G */ if (err == MP_OKAY) - err = ecc_projective_dbl_point(tG, M[1], modulus, &mp); + err = ecc_projective_dbl_point(tG, M[1], a, modulus, mp); /* setup sliding window */ mode = 0; @@ -1145,32 +1250,33 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, buf <<= 1; if (mode == 0 && i == 0) { - /* dummy operations */ + /* timing resistant - dummy operations */ if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[2], modulus, - &mp); + err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, + mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp); + err = ecc_projective_dbl_point(M[1], M[2], a, modulus, mp); if (err == MP_OKAY) continue; } if (mode == 0 && i == 1) { mode = 1; - /* dummy operations */ + /* timing resistant - dummy operations */ if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[2], modulus, - &mp); + err = ecc_projective_add_point(M[0], M[1], M[2], a, modulus, + mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[1], M[2], modulus, &mp); + err = ecc_projective_dbl_point(M[1], M[2], a, modulus, mp); if (err == MP_OKAY) continue; } if (err == MP_OKAY) - err = ecc_projective_add_point(M[0], M[1], M[i^1], modulus, &mp); + err = ecc_projective_add_point(M[0], M[1], M[i^1], a, modulus, + mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(M[i], M[i], modulus, &mp); + err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp); if (err != MP_OKAY) break; } /* end for */ @@ -1186,10 +1292,9 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* map R back from projective space */ if (err == MP_OKAY && map) - err = ecc_map(R, modulus, &mp); + err = ecc_map(R, modulus, mp); /* done */ - mp_clear(&mu); wc_ecc_del_point_h(tG, heap); for (i = 0; i < 3; i++) { wc_ecc_del_point_h(M[i], heap); @@ -1199,10 +1304,10 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, #ifndef FP_ECC -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, - mp_int* modulus, int map) +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map) { - return wc_ecc_mulmod_ex(k, G, R, modulus, map, NULL); + return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } #endif /* ! FP_ECC */ #endif /* ECC_TIMING_RESISTANT */ @@ -1353,7 +1458,7 @@ int wc_ecc_is_valid_idx(int n) ; /* -1 is a valid index --- indicating that the domain params were supplied by the user */ - if ((n >= -1) && (n < x)) { + if ((n >= ECC_CUSTOM_IDX) && (n < x)) { return 1; } return 0; @@ -1375,6 +1480,7 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, word32 x = 0; ecc_point* result; mp_int prime; + mp_int a; int err; if (private_key == NULL || public_key == NULL || out == NULL || @@ -1401,16 +1507,19 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, return MEMORY_E; } - if ((err = mp_init(&prime)) != MP_OKAY) { + if ((err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { wc_ecc_del_point(result); return err; } - err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16); + /* read in the specs for this curve */ + err = mp_read_radix(&prime, private_key->dp->prime, 16); + if (err == MP_OKAY) + err = mp_read_radix(&a, private_key->dp->Af, 16); if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&private_key->k, &public_key->pubkey, result, - &prime, 1, private_key->heap); + err = wc_ecc_mulmod_ex(&private_key->k, &public_key->pubkey, result, &a, + &prime, 1, private_key->heap); if (err == MP_OKAY) { x = mp_unsigned_bin_size(&prime); @@ -1421,10 +1530,11 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, if (err == MP_OKAY) { XMEMSET(out, 0, x); err = mp_to_unsigned_bin(result->x,out + (x - - mp_unsigned_bin_size(result->x))); + mp_unsigned_bin_size(result->x))); *outlen = x; } + mp_clear(&a); mp_clear(&prime); wc_ecc_del_point_h(result, private_key->heap); @@ -1446,6 +1556,7 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, word32 x = 0; ecc_point* result; mp_int prime; + mp_int a; int err; if (private_key == NULL || point == NULL || out == NULL || outlen == NULL) @@ -1466,15 +1577,18 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, return MEMORY_E; } - if ((err = mp_init(&prime)) != MP_OKAY) { + if ((err = mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { wc_ecc_del_point_h(result, private_key->heap); return err; } - err = mp_read_radix(&prime, (char *)private_key->dp->prime, 16); + /* read in the specs for this curve */ + err = mp_read_radix(&prime, private_key->dp->prime, 16); + if (err == MP_OKAY) + err = mp_read_radix(&a, private_key->dp->Af, 16); if (err == MP_OKAY) - err = wc_ecc_mulmod(&private_key->k, point, result, &prime, 1); + err = wc_ecc_mulmod(&private_key->k, point, result, &a, &prime, 1); if (err == MP_OKAY) { x = mp_unsigned_bin_size(&prime); @@ -1489,6 +1603,7 @@ int wc_ecc_shared_secret_ssh(ecc_key* private_key, ecc_point* point, *outlen = x; } + mp_clear(&a); mp_clear(&prime); wc_ecc_del_point_h(result, private_key->heap); @@ -1509,127 +1624,145 @@ int wc_ecc_point_is_at_infinity(ecc_point* p) } -static int wc_ecc_make_key_ex(WC_RNG* rng, ecc_key* key, const ecc_set_type* dp) +int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, + const ecc_set_type* dp) { - int err; - ecc_point* base; - mp_int prime; - mp_int order; + int err, x; + ecc_point* base = NULL; + mp_int prime; + mp_int a; + mp_int order; #ifdef WOLFSSL_SMALL_STACK - byte* buf; + byte* buf; #else - byte buf[ECC_MAXSIZE_GEN]; + byte buf[ECC_MAXSIZE_GEN]; #endif - int keysize; - int po_init = 0; /* prime order Init flag for clear */ - if (key == NULL || rng == NULL || dp == NULL) - return ECC_BAD_ARG_E; + if (key == NULL || rng == NULL || (keysize <= 0 && dp == NULL)) { + return BAD_FUNC_ARG; + } + + /* determine curve type/index */ + if (dp == NULL) { + /* 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; + } + dp = &ecc_sets[x]; + } + else { + x = ECC_CUSTOM_IDX; + } + + key->idx = x; + key->dp = dp; #ifdef WOLFSSL_SMALL_STACK - buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (buf == NULL) - return MEMORY_E; + buf = (byte*)XMALLOC(ECC_MAXSIZE_GEN, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + return MEMORY_E; #endif - key->idx = -1; - key->dp = dp; + /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ + /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ + keysize = dp->size + 8; - /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ - /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ - keysize = dp->size + 8; + /* make up random string */ + err = wc_RNG_GenerateBlock(rng, buf, keysize); - /* allocate ram */ - base = NULL; + /* setup the key variables */ + if (err == 0) { + err = mp_init_multi(&key->k, &prime, &order, &a, NULL, NULL); + if (err == MP_OKAY) { + #ifndef ALT_ECC_SIZE + err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL, NULL); + #else + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); + #endif + } + } - /* make up random string */ - err = wc_RNG_GenerateBlock(rng, buf, keysize); + if (err == MP_OKAY) { + base = wc_ecc_new_point_h(key->heap); + if (base == NULL) + err = MEMORY_E; + } - /* setup the key variables */ - if (err == 0) { -#ifndef ALT_ECC_SIZE - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, - &key->k, &prime, &order); -#else - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; - key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; - key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; - alt_fp_init(key->pubkey.x); - alt_fp_init(key->pubkey.y); - alt_fp_init(key->pubkey.z); - err = mp_init_multi(&key->k, &prime, &order, NULL, NULL, NULL); -#endif - if (err != MP_OKAY) - err = MEMORY_E; - else - po_init = 1; - } + /* read in the specs for this curve */ + if (err == MP_OKAY) + err = mp_read_radix(&prime, key->dp->prime, 16); + if (err == MP_OKAY) + err = mp_read_radix(&order, key->dp->order, 16); + if (err == MP_OKAY) + err = mp_read_radix(&a, key->dp->Af, 16); - if (err == MP_OKAY) { - base = wc_ecc_new_point_h(key->heap); - if (base == NULL) - err = MEMORY_E; - } + /* read in the x/y for this key */ + if (err == MP_OKAY) + err = mp_read_radix(base->x, key->dp->Gx, 16); + if (err == MP_OKAY) + err = mp_read_radix(base->y, key->dp->Gy, 16); + if (err == MP_OKAY) + mp_set(base->z, 1); - /* 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); + /* load random buffer data into k */ + if (err == MP_OKAY) + err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize); - if (err == MP_OKAY) - mp_set(base->z, 1); - if (err == MP_OKAY) - err = mp_read_unsigned_bin(&key->k, (byte*)buf, keysize); + /* quick sanity check to make sure we're not dealing with a 0 key */ + if (err == MP_OKAY) { + if (mp_iszero(&key->k) == MP_YES) + err = MP_ZERO_E; + } - /* quick sanity check to make sure we're not dealing with a 0 key */ - if (err == MP_OKAY) { - if (MP_YES == mp_iszero(&key->k)) - err = MP_ZERO_E; - } + /* 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); + } - /* 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 = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, &prime, 1, - key->heap); + /* make the public key */ + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(&key->k, base, &key->pubkey, &a, &prime, 1, + key->heap); #ifdef WOLFSSL_VALIDATE_ECC_KEYGEN - /* validate the public key, order * pubkey = point at infinity */ - if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &prime, &order); + /* validate the public key, order * pubkey = point at infinity */ + if (err == MP_OKAY) + err = ecc_check_pubkey_order(key, &a, &prime, &order); #endif /* WOLFSSL_VALIDATE_KEYGEN */ - if (err == MP_OKAY) - key->type = ECC_PRIVATEKEY; + 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_forcezero(&key->k); - } - wc_ecc_del_point_h(base, key->heap); - if (po_init) { - mp_clear(&prime); - mp_clear(&order); - } + if (err != MP_OKAY) { + /* clean up */ + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + mp_forcezero(&key->k); + } - ForceZero(buf, ECC_MAXSIZE); + wc_ecc_del_point_h(base, key->heap); + mp_clear(&a); + mp_clear(&prime); + mp_clear(&order); + + ForceZero(buf, ECC_MAXSIZE); #ifdef WOLFSSL_SMALL_STACK - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - return err; + return err; } /** @@ -1642,23 +1775,7 @@ static int wc_ecc_make_key_ex(WC_RNG* rng, ecc_key* key, const ecc_set_type* dp) */ int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key) { - int x, err; - - if (key == NULL || rng == NULL) - return ECC_BAD_ARG_E; - - /* 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 = wc_ecc_make_key_ex(rng, key, &ecc_sets[x]); - key->idx = x; - - return err; + return wc_ecc_make_key_ex(rng, keysize, key, NULL); } /* Setup dynamic pointers is using normal math for proper freeing */ @@ -1787,7 +1904,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if ((err = mp_init_multi(&p, &e, NULL, NULL, NULL, NULL)) != MP_OKAY) { return err; } - err = mp_read_radix(&p, (char *)key->dp->order, 16); + err = mp_read_radix(&p, key->dp->order, 16); if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ @@ -1813,7 +1930,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, err = RNG_FAILURE_E; break; } - err = wc_ecc_make_key_ex(rng, &pubkey, key->dp); + err = wc_ecc_make_key_ex(rng, 0, &pubkey, key->dp); if (err != MP_OKAY) break; /* find r = x1 mod n */ @@ -1874,12 +1991,6 @@ void wc_ecc_free(ecc_key* key) } -#ifdef USE_FAST_MATH - #define GEN_MEM_ERR FP_MEM -#else - #define GEN_MEM_ERR MP_MEM -#endif - #ifdef ECC_SHAMIR /** Computes kA*A + kB*B = C using Shamir's Trick @@ -1888,34 +1999,34 @@ void wc_ecc_free(ecc_key* key) B Second point to multiply kB What to multiple B by C [out] Destination point (can overlap with A or B) + a ECC curve parameter a modulus Modulus for curve return MP_OKAY on success */ #ifdef FP_ECC static int normal_ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus, void* heap) + ecc_point* C, mp_int* a, mp_int* modulus, + void* heap) #else static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus, void* heap) + ecc_point* C, mp_int* a, mp_int* modulus, + void* heap) #endif { ecc_point* precomp[16]; - unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble; + unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; unsigned char* tA; unsigned char* tB; - int err = MP_OKAY, first; - int muInit = 0; - int tableInit = 0; + int err = MP_OKAY, first, x, y; mp_digit mp; - mp_int mu; /* argchks */ if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || - modulus == NULL) - return ECC_BAD_ARG_E; - + modulus == NULL) { + return ECC_BAD_ARG_E; + } /* allocate memory */ tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); @@ -1927,8 +2038,11 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, XFREE(tA, heap, DYNAMIC_TYPE_TMP_BUFFER); return GEN_MEM_ERR; } + + /* init variables */ XMEMSET(tA, 0, ECC_BUFSIZE); XMEMSET(tB, 0, ECC_BUFSIZE); + XMEMSET(precomp, 0, sizeof(precomp)); /* get sizes */ lenA = mp_unsigned_bin_size(kA); @@ -1937,7 +2051,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, /* sanity check */ if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) { - err = BAD_FUNC_ARG; + err = BAD_FUNC_ARG; } if (err == MP_OKAY) { @@ -1964,50 +2078,50 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, } if (err == MP_OKAY) - tableInit = 1; + /* init montgomery reduction */ + err = mp_montgomery_setup(modulus, &mp); - if (err == MP_OKAY) - /* init montgomery reduction */ - err = mp_montgomery_setup(modulus, &mp); - - if (err == MP_OKAY) + if (err == MP_OKAY) { + mp_int mu; err = mp_init(&mu); - if (err == MP_OKAY) - muInit = 1; + if (err == MP_OKAY) { + err = mp_montgomery_calc_normalization(&mu, modulus); - if (err == MP_OKAY) - err = mp_montgomery_calc_normalization(&mu, modulus); + if (err == MP_OKAY) + /* copy ones ... */ + err = mp_mulmod(A->x, &mu, modulus, precomp[1]->x); - if (err == MP_OKAY) - /* copy ones ... */ - err = mp_mulmod(A->x, &mu, modulus, precomp[1]->x); + if (err == MP_OKAY) + err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y); + if (err == MP_OKAY) + err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z); - if (err == MP_OKAY) - err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y); - if (err == MP_OKAY) - err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z); + if (err == MP_OKAY) + err = mp_mulmod(B->x, &mu, modulus, precomp[1<<2]->x); + if (err == MP_OKAY) + err = mp_mulmod(B->y, &mu, modulus, precomp[1<<2]->y); + if (err == MP_OKAY) + err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z); - if (err == MP_OKAY) - err = mp_mulmod(B->x, &mu, modulus, precomp[1<<2]->x); - if (err == MP_OKAY) - err = mp_mulmod(B->y, &mu, modulus, precomp[1<<2]->y); - if (err == MP_OKAY) - err = mp_mulmod(B->z, &mu, modulus, precomp[1<<2]->z); + /* done with mu */ + mp_clear(&mu); + } + } if (err == MP_OKAY) /* precomp [i,0](A + B) table */ - err = ecc_projective_dbl_point(precomp[1], precomp[2], modulus, &mp); + err = ecc_projective_dbl_point(precomp[1], precomp[2], a, modulus, mp); if (err == MP_OKAY) err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3], - modulus, &mp); + a, modulus, mp); if (err == MP_OKAY) /* precomp [0,i](A + B) table */ - err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], modulus, &mp); + err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], a, modulus, mp); if (err == MP_OKAY) err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2], - modulus, &mp); + a, modulus, mp); if (err == MP_OKAY) { /* precomp [i,j](A + B) table (i != 0, j != 0) */ @@ -2015,7 +2129,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, for (y = 1; y < 4; y++) { if (err == MP_OKAY) err = ecc_projective_add_point(precomp[x], precomp[(y<<2)], - precomp[x+(y<<2)], modulus, &mp); + precomp[x+(y<<2)], a, modulus, mp); } } } @@ -2027,10 +2141,10 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, bitbufB = tB[0]; /* for every byte of the multiplicands */ - for (x = (unsigned)-1;; ) { + for (x = -1;; ) { /* grab a nibble */ if (++nibble == 4) { - ++x; if (x == len) break; + ++x; if (x == (int)len) break; bitbufA = tA[x]; bitbufB = tB[x]; nibble = 0; @@ -2051,9 +2165,9 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, if (first == 0) { /* double twice */ if (err == MP_OKAY) - err = ecc_projective_dbl_point(C, C, modulus, &mp); + err = ecc_projective_dbl_point(C, C, a, modulus, mp); if (err == MP_OKAY) - err = ecc_projective_dbl_point(C, C, modulus, &mp); + err = ecc_projective_dbl_point(C, C, a, modulus, mp); else break; } @@ -2077,7 +2191,7 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, /* if not first, add from table */ if (err == MP_OKAY) err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C, - modulus, &mp); + a, modulus, mp); else break; } @@ -2085,25 +2199,21 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, } } + /* reduce to affine */ if (err == MP_OKAY) - /* reduce to affine */ - err = ecc_map(C, modulus, &mp); + err = ecc_map(C, modulus, mp); /* clean up */ - if (muInit) - mp_clear(&mu); - - if (tableInit) { - for (x = 0; x < 16; x++) { - wc_ecc_del_point_h(precomp[x], heap); - } + for (x = 0; x < 16; x++) { + wc_ecc_del_point_h(precomp[x], heap); } - ForceZero(tA, ECC_BUFSIZE); - ForceZero(tB, ECC_BUFSIZE); - XFREE(tA, heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tB, heap, DYNAMIC_TYPE_TMP_BUFFER); - return err; + ForceZero(tA, ECC_BUFSIZE); + ForceZero(tB, ECC_BUFSIZE); + XFREE(tA, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tB, heap, DYNAMIC_TYPE_TMP_BUFFER); + + return err; } @@ -2177,14 +2287,15 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, word32 hashlen, int* stat, ecc_key* key) { - ecc_point *mG, *mQ; + ecc_point *mG = NULL, *mQ = NULL; mp_int v; mp_int w; mp_int u1; mp_int u2; mp_int e; - mp_int p; - mp_int m; + mp_int order; + mp_int modulus; + mp_int a; int err; if (r == NULL || s == NULL || hash == NULL || stat == NULL || key == NULL) @@ -2199,16 +2310,16 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, } /* allocate ints */ - if ((err = mp_init_multi(&v, &w, &u1, &u2, &p, &e)) != MP_OKAY) { + if ((err = mp_init_multi(&v, &w, &u1, &u2, &order, &e)) != MP_OKAY) { return MEMORY_E; } - if ((err = mp_init(&m)) != MP_OKAY) { + if ((err = mp_init_multi(&modulus, &a, NULL, NULL, NULL, NULL)) != MP_OKAY) { mp_clear(&v); mp_clear(&w); mp_clear(&u1); mp_clear(&u2); - mp_clear(&p); + mp_clear(&order); mp_clear(&e); return MEMORY_E; } @@ -2219,24 +2330,26 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, if (mQ == NULL || mG == NULL) err = MEMORY_E; - /* get the order */ + /* read in the specs for this curve */ if (err == MP_OKAY) - err = mp_read_radix(&p, (char *)key->dp->order, 16); - - /* get the modulus */ + err = mp_read_radix(&order, key->dp->order, 16); if (err == MP_OKAY) - err = mp_read_radix(&m, (char *)key->dp->prime, 16); + err = mp_read_radix(&modulus, key->dp->prime, 16); + if (err == MP_OKAY) + err = mp_read_radix(&a, key->dp->Af, 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) + if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || + mp_cmp(r, &order) != MP_LT || mp_cmp(s, &order) != MP_LT) { err = MP_ZERO_E; + } } + /* read hash */ if (err == MP_OKAY) { /* we may need to truncate if hash is longer than key size */ - unsigned int orderBits = mp_count_bits(&p); + unsigned int orderBits = mp_count_bits(&order); /* truncate down to byte size, may be all that's needed */ if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) @@ -2250,22 +2363,22 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* w = s^-1 mod n */ if (err == MP_OKAY) - err = mp_invmod(s, &p, &w); + err = mp_invmod(s, &order, &w); /* u1 = ew */ if (err == MP_OKAY) - err = mp_mulmod(&e, &w, &p, &u1); + err = mp_mulmod(&e, &w, &order, &u1); /* u2 = rw */ if (err == MP_OKAY) - err = mp_mulmod(r, &w, &p, &u2); + err = mp_mulmod(r, &w, &order, &u2); /* find mG and mQ */ if (err == MP_OKAY) - err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16); + err = mp_read_radix(mG->x, key->dp->Gx, 16); if (err == MP_OKAY) - err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16); + err = mp_read_radix(mG->y, key->dp->Gy, 16); if (err == MP_OKAY) mp_set(mG->z, 1); @@ -2282,31 +2395,31 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, /* compute u1*mG + u2*mQ = mG */ if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u1, mG, mG, &m, 0, key->heap); + err = wc_ecc_mulmod(&u1, mG, mG, &a, &modulus, 0); if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u2, mQ, mQ, &m, 0, key->heap); + err = wc_ecc_mulmod(&u2, mQ, mQ, &a, &modulus, 0); /* find the montgomery mp */ if (err == MP_OKAY) - err = mp_montgomery_setup(&m, &mp); + err = mp_montgomery_setup(&modulus, &mp); /* add them */ if (err == MP_OKAY) - err = ecc_projective_add_point(mQ, mG, mG, &m, &mp); + err = ecc_projective_add_point(mQ, mG, mG, &a, &modulus, mp); /* reduce */ if (err == MP_OKAY) - err = ecc_map(mG, &m, &mp); + err = ecc_map(mG, &modulus, 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, key->heap); + err = ecc_mul2add(mG, &u1, mQ, &u2, mG, &a, &modulus, key->heap); #endif /* ECC_SHAMIR */ /* v = X_x1 mod n */ if (err == MP_OKAY) - err = mp_mod(mG->x, &p, &v); + err = mp_mod(mG->x, &order, &v); /* does v == r */ if (err == MP_OKAY) { @@ -2314,6 +2427,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, *stat = 1; } + /* cleanup */ wc_ecc_del_point_h(mG, key->heap); wc_ecc_del_point_h(mQ, key->heap); @@ -2321,9 +2435,10 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_clear(&w); mp_clear(&u1); mp_clear(&u2); - mp_clear(&p); + mp_clear(&order); mp_clear(&e); - mp_clear(&m); + mp_clear(&modulus); + mp_clear(&a); return err; } @@ -2384,29 +2499,23 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) err = MEMORY_E; - /* load prime */ + /* read in the specs for this curve */ if (err == MP_OKAY) - err = mp_read_radix(&prime, (char *)ecc_sets[curve_idx].prime, 16); - - /* load a */ + err = mp_read_radix(&prime, ecc_sets[curve_idx].prime, 16); if (err == MP_OKAY) - err = mp_read_radix(&a, (char *)ecc_sets[curve_idx].Af, 16); - - /* load b */ + err = mp_read_radix(&a, ecc_sets[curve_idx].Af, 16); if (err == MP_OKAY) - err = mp_read_radix(&b, (char *)ecc_sets[curve_idx].Bf, 16); + err = mp_read_radix(&b, ecc_sets[curve_idx].Bf, 16); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(point->x, &t1); - if (err == MP_OKAY) err = mp_mulmod(&t1, point->x, &prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) err = mp_mulmod(&a, point->x, &prime, &t2); - if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); @@ -2420,8 +2529,8 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, /* adjust y */ if (err == MP_OKAY) { - if ((mp_isodd(&t2) && in[0] == 0x03) || - (!mp_isodd(&t2) && in[0] == 0x02)) { + if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) || + (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) { err = mp_mod(&t2, &prime, point->y); } else { @@ -2605,18 +2714,21 @@ int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, } #endif /* HAVE_ECC_KEY_EXPORT */ + /* is ecc point on curve described by dp ? */ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) { - mp_int b, t1, t2; + mp_int a, b, t1, t2; int err; - if ((err = mp_init_multi(&b, &t1, &t2, NULL, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(&a, &b, &t1, &t2, NULL, NULL)) != MP_OKAY) { return err; } - /* load b */ - err = mp_read_radix(&b, dp->Bf, 16); + /* read in the specs for this curve */ + err = mp_read_radix(&a, dp->Af, 16); + if (err == MP_OKAY) + err = mp_read_radix(&b, dp->Bf, 16); /* compute y^2 */ if (err == MP_OKAY) @@ -2634,6 +2746,20 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) if (err == MP_OKAY) err = mp_sub(&t1, &t2, &t1); + /* Determine if curve "a" should be used in calc */ +#ifdef WOLFSSL_CUSTOM_CURVES + /* compute y^2 - x^3 + a*x */ + mp_clear(&t2); + if (err == MP_OKAY) + err = mp_submod(prime, &a, prime, &t2); + if (err == MP_OKAY) + err = mp_mulmod(&t2, ecp->x, prime, &t2); + if (err == MP_OKAY) + err = mp_addmod(&t1, &t2, prime, &t1); +#else + /* Assumes a = 3 */ + (void)a; + /* compute y^2 - x^3 + 3x */ if (err == MP_OKAY) err = mp_add(&t1, ecp->x, &t1); @@ -2643,7 +2769,9 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) err = mp_add(&t1, ecp->x, &t1); if (err == MP_OKAY) err = mp_mod(&t1, prime, &t1); +#endif /* WOLFSSL_CUSTOM_CURVES */ + /* adjust range (0, prime) */ while (err == MP_OKAY && mp_cmp_d(&t1, 0) == MP_LT) { err = mp_add(&t1, prime, &t1); } @@ -2660,6 +2788,7 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) } } + mp_clear(&a); mp_clear(&b); mp_clear(&t1); mp_clear(&t2); @@ -2669,7 +2798,7 @@ static int ecc_is_point(const ecc_set_type* dp, ecc_point* ecp, mp_int* prime) /* validate privkey * generator == pubkey, 0 on success */ -static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime) +static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) { ecc_point* base = NULL; ecc_point* res = NULL; @@ -2683,9 +2812,9 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime) return MEMORY_E; /* set up base generator */ - err = mp_read_radix(base->x, (char*)key->dp->Gx, 16); + err = mp_read_radix(base->x, key->dp->Gx, 16); if (err == MP_OKAY) - err = mp_read_radix(base->y, (char*)key->dp->Gy, 16); + err = mp_read_radix(base->y, key->dp->Gy, 16); if (err == MP_OKAY) mp_set(base->z, 1); @@ -2694,7 +2823,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* prime) if (res == NULL) err = MEMORY_E; else { - err = wc_ecc_mulmod_ex(&key->k, base, res, prime, 1, key->heap); + err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap); if (err == MP_OKAY) { /* compare result to public key */ if (mp_cmp(res->x, key->pubkey.x) != MP_EQ || @@ -2729,7 +2858,7 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) if (err != MP_OKAY) return err; - err = mp_read_radix(&prime, (char*)key->dp->prime, 16); + err = mp_read_radix(&prime, key->dp->prime, 16); if (err == MP_OKAY) err = ecc_check_privkey_gen(key, &prime); @@ -2743,7 +2872,8 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) /* validate order * pubkey = point at infinity, 0 on success */ -static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order) +static int ecc_check_pubkey_order(ecc_key* key, mp_int* a, mp_int* prime, + mp_int* order) { ecc_point* inf = NULL; int err; @@ -2755,7 +2885,8 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order) if (inf == NULL) err = MEMORY_E; else { - err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, prime, 1, key->heap); + err = wc_ecc_mulmod_ex(order, &key->pubkey, inf, a, prime, 1, + key->heap); if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf)) err = ECC_INF_E; } @@ -2770,6 +2901,7 @@ static int ecc_check_pubkey_order(ecc_key* key, mp_int* prime, mp_int* order) int wc_ecc_check_key(ecc_key* key) { mp_int prime; /* used by multiple calls so let's cache */ + mp_int a; mp_int order; /* other callers have, so let's gen here */ int err; @@ -2780,28 +2912,30 @@ int wc_ecc_check_key(ecc_key* key) if (wc_ecc_point_is_at_infinity(&key->pubkey)) return ECC_INF_E; - err = mp_init_multi(&prime, &order, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; + err = mp_init_multi(&prime, &a, &order, NULL, NULL, NULL); - err = mp_read_radix(&prime, (char*)key->dp->prime, 16); + /* read in the specs for this curve */ + if (err == MP_OKAY) + err = mp_read_radix(&prime, key->dp->prime, 16); + if (err == MP_OKAY) + err = mp_read_radix(&a, key->dp->Af, 16); + if (err == MP_OKAY) + err = mp_read_radix(&order, key->dp->order, 16); /* make sure point is actually on curve */ if (err == MP_OKAY) err = ecc_is_point(key->dp, &key->pubkey, &prime); - if (err == MP_OKAY) - err = mp_read_radix(&order, (char*)key->dp->order, 16); - /* pubkey * order must be at infinity */ if (err == MP_OKAY) - err = ecc_check_pubkey_order(key, &prime, &order); + err = ecc_check_pubkey_order(key, &a, &prime, &order); /* private * base generator must equal pubkey */ if (err == MP_OKAY && key->type == ECC_PRIVATEKEY) - err = ecc_check_privkey_gen(key, &prime); + err = ecc_check_privkey_gen(key, &a, &prime); mp_clear(&order); + mp_clear(&a); mp_clear(&prime); return err; @@ -2809,104 +2943,105 @@ int wc_ecc_check_key(ecc_key* key) #ifdef HAVE_ECC_KEY_IMPORT /* import public ECC key in ANSI X9.63 format */ -int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) +int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, + const ecc_set_type* dp) { - int x, err; - int compressed = 0; + int x, err; + int compressed = 0; - if (in == NULL || key == NULL) - return ECC_BAD_ARG_E; + if (in == NULL || key == NULL) + return ECC_BAD_ARG_E; - /* must be odd */ - if ((inLen & 1) == 0) { - return ECC_BAD_ARG_E; - } + /* must be odd */ + if ((inLen & 1) == 0) { + return ECC_BAD_ARG_E; + } - /* init key */ -#ifdef ALT_ECC_SIZE - key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; - key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; - key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; - alt_fp_init(key->pubkey.x); - alt_fp_init(key->pubkey.y); - alt_fp_init(key->pubkey.z); - err = mp_init(&key->k); -#else - err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, - NULL, NULL); -#endif - if (err != MP_OKAY) - return MEMORY_E; + /* init key */ + #ifdef ALT_ECC_SIZE + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); + err = mp_init(&key->k); + #else + err = mp_init_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, &key->k, + NULL, NULL); + #endif + if (err != MP_OKAY) + return MEMORY_E; - /* check for 4, 2, or 3 */ - if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) { - err = ASN_PARSE_E; - } + /* check for 4, 2, or 3 */ + if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) { + err = ASN_PARSE_E; + } - if (in[0] == 0x02 || in[0] == 0x03) { -#ifdef HAVE_COMP_KEY - compressed = 1; -#else - err = NOT_COMPILED_IN; -#endif - } + if (in[0] == 0x02 || in[0] == 0x03) { + #ifdef HAVE_COMP_KEY + compressed = 1; + #else + err = NOT_COMPILED_IN; + #endif + } - if (err == MP_OKAY) { - /* determine the idx */ + if (err == MP_OKAY) { + /* determine the idx */ + if (dp) { + /* set the idx */ + key->idx = ECC_CUSTOM_IDX; + key->dp = dp; + key->type = ECC_PUBLICKEY; + } + else { + if (compressed) + inLen = (inLen-1)*2 + 1; /* used uncompressed len */ - if (compressed) - inLen = (inLen-1)*2 + 1; /* used uncompressed len */ + 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) { + WOLFSSL_MSG("ecc_set size not found"); + err = ASN_PARSE_E; + } else { + key->idx = x; + key->dp = &ecc_sets[x]; + key->type = ECC_PUBLICKEY; + } + } + } - 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) { - WOLFSSL_MSG("ecc_set size not found"); - err = ASN_PARSE_E; - } else { - /* set the idx */ - key->idx = x; - key->dp = &ecc_sets[x]; - key->type = ECC_PUBLICKEY; - } - } - - /* read data */ - if (err == MP_OKAY) - err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in+1, (inLen-1)>>1); + /* read data */ + if (err == MP_OKAY) + err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in+1, (inLen-1)>>1); #ifdef HAVE_COMP_KEY - if (err == MP_OKAY && compressed == 1) { /* build y */ + if (err == MP_OKAY && compressed == 1) { /* build y */ mp_int t1, t2, prime, a, b; if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY) err = MEMORY_E; - /* load prime */ + /* read in the specs for this curve */ if (err == MP_OKAY) - err = mp_read_radix(&prime, (char *)key->dp->prime, 16); - - /* load a */ + err = mp_read_radix(&prime, key->dp->prime, 16); if (err == MP_OKAY) - err = mp_read_radix(&a, (char *)key->dp->Af, 16); - - /* load b */ + err = mp_read_radix(&a, key->dp->Af, 16); if (err == MP_OKAY) - err = mp_read_radix(&b, (char *)key->dp->Bf, 16); + err = mp_read_radix(&b, key->dp->Bf, 16); /* compute x^3 */ if (err == MP_OKAY) err = mp_sqr(key->pubkey.x, &t1); - if (err == MP_OKAY) err = mp_mulmod(&t1, key->pubkey.x, &prime, &t1); /* compute x^3 + a*x */ if (err == MP_OKAY) err = mp_mulmod(&a, key->pubkey.x, &prime, &t2); - if (err == MP_OKAY) err = mp_add(&t1, &t2, &t1); @@ -2920,13 +3055,14 @@ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) /* adjust y */ if (err == MP_OKAY) { - if ((mp_isodd(&t2) && in[0] == 0x03) || - (!mp_isodd(&t2) && in[0] == 0x02)) { - err = mp_mod(&t2, &prime, key->pubkey.y); + if ((mp_isodd(&t2) == MP_YES && in[0] == 0x03) || + (mp_isodd(&t2) == MP_NO && in[0] == 0x02)) { + err = mp_mod(&t2, &prime, &t2); } else { - err = mp_submod(&prime, &t2, &prime, key->pubkey.y); + err = mp_submod(&prime, &t2, &prime, &t2); } + mp_copy(&t2, key->pubkey.y); } mp_clear(&a); @@ -2934,28 +3070,33 @@ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) mp_clear(&prime); mp_clear(&t2); mp_clear(&t1); - } -#endif + } +#endif /* HAVE_COMP_KEY */ - if (err == MP_OKAY && compressed == 0) - 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 && compressed == 0) + 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); #ifdef WOLFSSL_VALIDATE_ECC_IMPORT - if (err == MP_OKAY) - err = wc_ecc_check_key(key); + if (err == MP_OKAY) + err = wc_ecc_check_key(key); #endif - if (err != MP_OKAY) { - mp_clear(key->pubkey.x); - mp_clear(key->pubkey.y); - mp_clear(key->pubkey.z); - mp_clear(&key->k); - } + 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; + return err; +} + +int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) +{ + return wc_ecc_import_x963_ex(in, inLen, key, NULL); } #endif /* HAVE_ECC_KEY_IMPORT */ @@ -2964,24 +3105,26 @@ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) return MP_OKAY on success */ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) { - word32 numlen; + word32 numlen; - if (key == NULL || out == NULL || outLen == NULL) - return ECC_BAD_ARG_E; + if (key == NULL || out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } - if (wc_ecc_is_valid_idx(key->idx) == 0) { - return ECC_BAD_ARG_E; - } - numlen = key->dp->size; + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + numlen = key->dp->size; - if (*outLen < numlen) { - *outLen = numlen; - return BUFFER_E; - } - *outLen = numlen; - XMEMSET(out, 0, *outLen); - return mp_to_unsigned_bin(&key->k, out + (numlen - - mp_unsigned_bin_size(&key->k))); + if (*outLen < numlen) { + *outLen = numlen; + return BUFFER_E; + } + *outLen = numlen; + XMEMSET(out, 0, *outLen); + + return mp_to_unsigned_bin(&key->k, out + (numlen - + mp_unsigned_bin_size(&key->k))); } #endif /* HAVE_ECC_KEY_EXPORT */ @@ -3038,7 +3181,7 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp); if (err == MP_OKAY) { - if (mp_iszero(&rtmp) || mp_iszero(&stmp)) + if (mp_iszero(&rtmp) == MP_YES || mp_iszero(&stmp) == MP_YES) err = MP_ZERO_E; } @@ -3050,23 +3193,14 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) #endif /* !NO_ASN */ #ifdef HAVE_ECC_KEY_IMPORT -/** - Import raw ECC key - key The destination ecc_key structure - qx x component of the public key, as ASCII hex string - qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string - curveName ECC curve name, from ecc_sets[] - return MP_OKAY on success -*/ -int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, - const char* d, const char* curveName) +static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, + const char* qy, const char* d, int x, const ecc_set_type* dp) { - int err, x; + int err; - if (key == NULL || qx == NULL || qy == NULL || d == NULL || - curveName == NULL) - return ECC_BAD_ARG_E; + if (key == NULL || qx == NULL || qy == NULL || d == NULL || dp == NULL) { + return BAD_FUNC_ARG; + } /* init key */ #ifdef ALT_ECC_SIZE @@ -3097,21 +3231,10 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, /* read and set the curve */ if (err == MP_OKAY) { - for (x = 0; ecc_sets[x].size != 0; x++) { - if (XSTRNCMP(ecc_sets[x].name, curveName, - XSTRLEN(curveName)) == 0) { - break; - } - } - if (ecc_sets[x].size == 0) { - WOLFSSL_MSG("ecc_set curve name not found"); - err = ASN_PARSE_E; - } else { - /* set the curve */ - key->idx = x; - key->dp = &ecc_sets[x]; - key->type = ECC_PUBLICKEY; - } + /* set curve type and index */ + key->idx = x; + key->dp = dp; + key->type = ECC_PUBLICKEY; } /* import private key */ @@ -3134,6 +3257,59 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, return err; } + +/** + Import raw ECC key + key The destination ecc_key structure + qx x component of the public key, as ASCII hex string + qy y component of the public key, as ASCII hex string + d private key, as ASCII hex string + dp Custom ecc_set_type + return MP_OKAY on success +*/ +int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, + const char* d, const ecc_set_type* dp) +{ + return wc_ecc_import_raw_private(key, qx, qy, d, ECC_CUSTOM_IDX, dp); + +} + +/** + Import raw ECC key + key The destination ecc_key structure + qx x component of the public key, as ASCII hex string + qy y component of the public key, as ASCII hex string + d private key, as ASCII hex string + curveName ECC curve name, from ecc_sets[] + return MP_OKAY on success +*/ +int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, + const char* d, const char* curveName) +{ + int err, x; + + if (key == NULL || qx == NULL || qy == NULL || d == NULL || + curveName == NULL) { + return BAD_FUNC_ARG; + } + + /* set curve type and index */ + for (x = 0; ecc_sets[x].size != 0; x++) { + if (XSTRNCMP(ecc_sets[x].name, curveName, + XSTRLEN(curveName)) == 0) { + break; + } + } + + if (ecc_sets[x].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + err = ASN_PARSE_E; + } else { + return wc_ecc_import_raw_private(key, qx, qy, d, x, &ecc_sets[x]); + } + + return err; +} #endif /* HAVE_ECC_KEY_IMPORT */ /* key size in octets */ @@ -3825,7 +4001,8 @@ static int add_entry(int idx, ecc_point *g) * The algorithm builds patterns in increasing bit order by first making all * single bit input patterns, then all two bit input patterns and so on */ -static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu) +static int build_lut(int idx, mp_int* a, mp_int* modulus, mp_digit mp, + mp_int* mu) { unsigned x, y, err, bitlen, lut_gap; mp_int tmp; @@ -3880,7 +4057,7 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu) /* now double it bitlen/FP_LUT times */ for (y = 0; y < lut_gap; y++) { if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<z, modulus, *mp); + err = mp_montgomery_reduce(fp_cache[idx].LUT[x]->z, modulus, mp); /* invert it */ if (err == MP_OKAY) @@ -3961,8 +4138,8 @@ static int build_lut(int idx, mp_int* modulus, mp_digit* mp, mp_int* mu) } /* perform a fixed point ECC mulmod */ -static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, - mp_digit* mp, int map) +static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, + mp_int* modulus, mp_digit mp, int map) { #define KB_SIZE 128 @@ -4069,8 +4246,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, /* double if not first */ if (!first) { - if ((err = ecc_projective_dbl_point(R, R, modulus, - mp)) != MP_OKAY) { + if ((err = ecc_projective_dbl_point(R, R, a, modulus, + mp)) != MP_OKAY) { break; } } @@ -4078,7 +4255,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, /* add if not first, otherwise copy */ if (!first && z) { if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, - modulus, mp)) != MP_OKAY) { + a, modulus, mp)) != MP_OKAY) { break; } } else if (z) { @@ -4097,6 +4274,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, z = 0; /* mp_to_unsigned_bin != MP_OKAY z will be declared/not set */ (void) z; /* Acknowledge the unused assignment */ ForceZero(kb, KB_SIZE); + /* map R back from projective space */ if (map) { err = ecc_map(R, modulus, mp); @@ -4118,7 +4296,8 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* modulus, /* perform a fixed point ECC mulmod */ static int accel_fp_mul2add(int idx1, int idx2, mp_int* kA, mp_int* kB, - ecc_point *R, mp_int* modulus, mp_digit* mp) + ecc_point *R, mp_int* a, + mp_int* modulus, mp_digit mp) { #define KB_SIZE 128 @@ -4299,7 +4478,7 @@ static int accel_fp_mul2add(int idx1, int idx2, /* double if not first */ if (!first) { - if ((err = ecc_projective_dbl_point(R, R, modulus, + if ((err = ecc_projective_dbl_point(R, R, a, modulus, mp)) != MP_OKAY) { break; } @@ -4309,13 +4488,13 @@ static int accel_fp_mul2add(int idx1, int idx2, if (!first) { if (zA) { if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA], - R, modulus, mp)) != MP_OKAY) { + R, a, modulus, mp)) != MP_OKAY) { break; } } if (zB) { if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB], - R, modulus, mp)) != MP_OKAY) { + R, a, modulus, mp)) != MP_OKAY) { break; } } @@ -4332,7 +4511,7 @@ static int accel_fp_mul2add(int idx1, int idx2, if (zB && first == 0) { if (zB) { if ((err = ecc_projective_add_point(R, - fp_cache[idx2].LUT[zB], R, modulus, mp)) != MP_OKAY){ + fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){ break; } } @@ -4373,12 +4552,13 @@ static int accel_fp_mul2add(int idx1, int idx2, B Second point to multiply kB What to multiple B by C [out] Destination point (can overlap with A or B) + a ECC curve parameter a modulus Modulus for curve return MP_OKAY on success */ int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB, - ecc_point* C, mp_int* modulus, void* heap) + ecc_point* C, mp_int* a, mp_int* modulus, void* heap) { int idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0; mp_digit mp; @@ -4443,7 +4623,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) /* build the LUT */ - err = build_lut(idx1, modulus, &mp, &mu); + err = build_lut(idx1, a, modulus, mp, &mu); } } @@ -4461,7 +4641,7 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) /* build the LUT */ - err = build_lut(idx2, modulus, &mp, &mu); + err = build_lut(idx2, a, modulus, mp, &mu); } } @@ -4474,9 +4654,9 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, err = mp_montgomery_setup(modulus, &mp); } if (err == MP_OKAY) - err = accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, &mp); + err = accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); } else { - err = normal_ecc_mul2add(A, kA, B, kB, C, modulus, heap); + err = normal_ecc_mul2add(A, kA, B, kB, C, a, modulus, heap); } } @@ -4493,15 +4673,16 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, k The multiplicand G Base point to multiply R [out] Destination of product + a ECC curve parameter a modulus The modulus for the curve map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, - int map) +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map) { - return wc_ecc_mulmod_ex(k, G, R, modulus, map, NULL); + return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); } @@ -4514,8 +4695,8 @@ int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, otherwise it's left in jacobian-montgomery form return MP_OKAY if successful */ -int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, - int map, void* heap) +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map, void* heap) { int idx, err = MP_OKAY; mp_digit mp; @@ -4566,7 +4747,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, if (err == MP_OKAY) /* build the LUT */ - err = build_lut(idx, modulus, &mp, &mu); + err = build_lut(idx, a, modulus, mp, &mu); } } @@ -4577,9 +4758,9 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* modulus, err = mp_montgomery_setup(modulus, &mp); } if (err == MP_OKAY) - err = accel_fp_mul(idx, k, R, modulus, &mp, map); + err = accel_fp_mul(idx, k, R, a, modulus, mp, map); } else { - err = normal_ecc_mulmod(k, G, R, modulus, map, heap); + err = normal_ecc_mulmod(k, G, R, a, modulus, map, heap); } } @@ -5199,22 +5380,34 @@ int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, /* computes the jacobi c = (a | n) (or Legendre if n is prime) * HAC pp. 73 Algorithm 2.149 + * HAC is wrong here, as the special case of (0 | 1) is not + * handled correctly. */ -int mp_jacobi(mp_int* a, mp_int* p, int* c) +int mp_jacobi(mp_int* a, mp_int* n, int* c) { mp_int a1, p1; int k, s, r, res; mp_digit residue; - /* if p <= 0 return MP_VAL */ - if (mp_cmp_d(p, 0) != MP_GT) { + /* if a < 0 return MP_VAL */ + if (mp_isneg(a) == MP_YES) { return MP_VAL; } - /* step 1. if a == 0, return 0 */ - if (mp_iszero (a) == 1) { - *c = 0; - return MP_OKAY; + /* if n <= 0 return MP_VAL */ + if (mp_cmp_d(n, 0) != MP_GT) { + return MP_VAL; + } + + /* step 1. handle case of a == 0 */ + if (mp_iszero (a) == MP_YES) { + /* special case of a == 0 and n == 1 */ + if (mp_cmp_d (n, 1) == MP_EQ) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; } /* step 2. if a == 1, return 1 */ @@ -5246,7 +5439,7 @@ int mp_jacobi(mp_int* a, mp_int* p, int* c) s = 1; } else { /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */ - residue = p->dp[0] & 7; + residue = n->dp[0] & 7; if (residue == 1 || residue == 7) { s = 1; @@ -5256,7 +5449,7 @@ int mp_jacobi(mp_int* a, mp_int* p, int* c) } /* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */ - if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { + if ( ((n->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) { s = -s; } } @@ -5267,7 +5460,7 @@ int mp_jacobi(mp_int* a, mp_int* p, int* c) *c = s; } else { /* n1 = n mod a1 */ - res = mp_mod (p, &a1, &p1); + res = mp_mod (n, &a1, &p1); if (res == MP_OKAY) res = mp_jacobi (&p1, &a1, &r); @@ -5295,7 +5488,11 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) mp_zero(ret); return MP_OKAY; } - if (mp_cmp_d(prime, 2) == MP_EQ) return MP_VAL; /* prime must be odd */ + + /* prime must be odd */ + if (mp_cmp_d(prime, 2) == MP_EQ) + return MP_VAL; + /* TAO removed if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) return res; if (legendre == -1) return MP_VAL; */ /* quadratic non-residue mod prime */ @@ -5329,56 +5526,65 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) } /* NOW: TonelliShanks algorithm */ + if (res == MP_OKAY && done == 0) { - if (res == MP_OKAY && done == 0) { - - /* factor out powers of 2 from prime-1, defining Q and S + /* factor out powers of 2 from prime-1, defining Q and S * as: prime-1 = Q*2^S */ + /* Q = prime - 1 */ res = mp_copy(prime, &Q); if (res == MP_OKAY) res = mp_sub_d(&Q, 1, &Q); - /* Q = prime - 1 */ + + /* S = 0 */ if (res == MP_OKAY) mp_zero(&S); - /* S = 0 */ + while (res == MP_OKAY && mp_iseven(&Q)) { - res = mp_div_2(&Q, &Q); /* Q = Q / 2 */ + res = mp_div_2(&Q, &Q); + + /* S = S + 1 */ if (res == MP_OKAY) res = mp_add_d(&S, 1, &S); - /* S = S + 1 */ } /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + /* Z = 2 */ if (res == MP_OKAY) res = mp_set_int(&Z, 2); - /* Z = 2 */ + while (res == MP_OKAY) { res = mp_jacobi(&Z, prime, &legendre); if (res == MP_OKAY && legendre == -1) break; + + /* Z = Z + 1 */ if (res == MP_OKAY) res = mp_add_d(&Z, 1, &Z); - /* Z = Z + 1 */ } + /* C = Z ^ Q mod prime */ if (res == MP_OKAY) res = mp_exptmod(&Z, &Q, prime, &C); - /* C = Z ^ Q mod prime */ + + /* t1 = (Q + 1) / 2 */ if (res == MP_OKAY) res = mp_add_d(&Q, 1, &t1); if (res == MP_OKAY) res = mp_div_2(&t1, &t1); - /* t1 = (Q + 1) / 2 */ - if (res == MP_OKAY) - res = mp_exptmod(n, &t1, prime, &R); + /* R = n ^ ((Q + 1) / 2) mod prime */ if (res == MP_OKAY) - res = mp_exptmod(n, &Q, prime, &T); + res = mp_exptmod(n, &t1, prime, &R); + /* T = n ^ Q mod prime */ if (res == MP_OKAY) - res = mp_copy(&S, &M); + res = mp_exptmod(n, &Q, prime, &T); + /* M = S */ + if (res == MP_OKAY) + res = mp_copy(&S, &M); + if (res == MP_OKAY) res = mp_set_int(&two, 2); @@ -5393,34 +5599,38 @@ int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) i++; } if (res == MP_OKAY && i == 0) { - mp_copy(&R, ret); - res = MP_OKAY; + res = mp_copy(&R, ret); done = 1; } if (done == 0) { + /* t1 = 2 ^ (M - i - 1) */ if (res == MP_OKAY) res = mp_sub_d(&M, i, &t1); if (res == MP_OKAY) res = mp_sub_d(&t1, 1, &t1); if (res == MP_OKAY) res = mp_exptmod(&two, &t1, prime, &t1); - /* t1 = 2 ^ (M - i - 1) */ - if (res == MP_OKAY) - res = mp_exptmod(&C, &t1, prime, &t1); + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ if (res == MP_OKAY) - res = mp_sqrmod(&t1, prime, &C); + res = mp_exptmod(&C, &t1, prime, &t1); + /* C = (t1 * t1) mod prime */ if (res == MP_OKAY) - res = mp_mulmod(&R, &t1, prime, &R); + res = mp_sqrmod(&t1, prime, &C); + /* R = (R * t1) mod prime */ if (res == MP_OKAY) - res = mp_mulmod(&T, &C, prime, &T); + res = mp_mulmod(&R, &t1, prime, &R); + /* T = (T * C) mod prime */ if (res == MP_OKAY) - mp_set(&M, i); + res = mp_mulmod(&T, &C, prime, &T); + /* M = i */ + if (res == MP_OKAY) + mp_set(&M, i); } } } @@ -5460,7 +5670,7 @@ int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen) } /* store first byte */ - out[0] = mp_isodd(key->pubkey.y) ? 0x03 : 0x02; + out[0] = mp_isodd(key->pubkey.y) == MP_YES ? 0x03 : 0x02; /* pad and store x */ XMEMSET(out+1, 0, numlen); @@ -5470,28 +5680,6 @@ int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen) return ret; } - -/* d = a - b (mod c) */ -int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) -{ - int res; - mp_int t; - - if ((res = mp_init (&t)) != MP_OKAY) { - return res; - } - - if ((res = mp_sub (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; - } - res = mp_mod (&t, c, d); - mp_clear (&t); - - return res; -} - - #endif /* HAVE_COMP_KEY */ #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 5c12622c7..a74e9805c 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -252,7 +252,7 @@ int mp_leading_bit (mp_int * a) if (mp_init_copy(&t, a) != MP_OKAY) return 0; - while (mp_iszero(&t) == 0) { + while (mp_iszero(&t) == MP_NO) { #ifndef MP_8BIT bit = (t.dp[0] & 0x80) != 0; #else @@ -277,7 +277,7 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) } x = 0; - while (mp_iszero (&t) == 0) { + while (mp_iszero (&t) == MP_NO) { #ifndef MP_8BIT b[x++] = (unsigned char) (t.dp[0] & 255); #else @@ -329,7 +329,7 @@ int mp_copy (mp_int * a, mp_int * b) /* zero b and copy the parameters over */ { - register mp_digit *tmpa, *tmpb; + mp_digit *tmpa, *tmpb; /* pointer aliases */ @@ -507,7 +507,7 @@ void mp_exch (mp_int * a, mp_int * b) /* shift right a certain number of bits */ void mp_rshb (mp_int *c, int x) { - register mp_digit *tmpc, mask, shift; + mp_digit *tmpc, mask, shift; mp_digit r, rr; mp_digit D = x; @@ -553,7 +553,7 @@ void mp_rshd (mp_int * a, int b) } { - register mp_digit *bottom, *top; + mp_digit *bottom, *top; /* shift the digits down */ @@ -686,8 +686,8 @@ int mp_mul_2d (mp_int * a, int b, mp_int * c) /* shift any bit count < DIGIT_BIT */ d = (mp_digit) (b % DIGIT_BIT); if (d != 0) { - register mp_digit *tmpc, shift, mask, r, rr; - register int x; + mp_digit *tmpc, shift, mask, r, rr; + int x; /* bitmask for carries */ mask = (((mp_digit)1) << d) - 1; @@ -740,7 +740,7 @@ int mp_lshd (mp_int * a, int b) } { - register mp_digit *top, *bottom; + mp_digit *top, *bottom; /* increment the used by the shift amount then copy upwards */ a->used += b; @@ -845,7 +845,7 @@ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* if the modulus is odd or dr != 0 use the montgomery method */ #ifdef BN_MP_EXPTMOD_FAST_C - if (mp_isodd (P) == 1 || dr != 0) { + if (mp_isodd (P) == MP_YES || dr != 0) { return mp_exptmod_fast (G, X, P, Y, dr); } else { #endif @@ -888,13 +888,13 @@ int mp_abs (mp_int * a, mp_int * b) int mp_invmod (mp_int * a, mp_int * b, mp_int * c) { /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { + if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { return MP_VAL; } #ifdef BN_FAST_MP_INVMOD_C /* if the modulus is odd we can use a faster routine instead */ - if (mp_isodd (b) == 1) { + if (mp_isodd (b) == MP_YES) { return fast_mp_invmod (a, b, c); } #endif @@ -917,7 +917,7 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) int res, neg, loop_check = 0; /* 2. [modified] b must be odd */ - if (mp_iseven (b) == 1) { + if (mp_iseven (b) == MP_YES) { return MP_VAL; } @@ -947,13 +947,13 @@ int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) top: /* 4. while u is even do */ - while (mp_iseven (&u) == 1) { + while (mp_iseven (&u) == MP_YES) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if B is odd then */ - if (mp_isodd (&B) == 1) { + if (mp_isodd (&B) == MP_YES) { if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { goto LBL_ERR; } @@ -965,13 +965,13 @@ top: } /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { + while (mp_iseven (&v) == MP_YES) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if D is odd then */ - if (mp_isodd (&D) == 1) { + if (mp_isodd (&D) == MP_YES) { /* D = (D-x)/2 */ if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { goto LBL_ERR; @@ -1005,7 +1005,7 @@ top: } /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) { + if (mp_iszero (&u) == MP_NO) { if (++loop_check > 4096) { res = MP_VAL; goto LBL_ERR; @@ -1055,7 +1055,7 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) int res; /* b cannot be negative */ - if (b->sign == MP_NEG || mp_iszero(b) == 1) { + if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { return MP_VAL; } @@ -1079,7 +1079,7 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) } /* 2. [modified] if x,y are both even then return an error! */ - if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { + if (mp_iseven (&x) == MP_YES && mp_iseven (&y) == MP_YES) { res = MP_VAL; goto LBL_ERR; } @@ -1096,13 +1096,13 @@ int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) top: /* 4. while u is even do */ - while (mp_iseven (&u) == 1) { + while (mp_iseven (&u) == MP_YES) { /* 4.1 u = u/2 */ if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto LBL_ERR; } /* 4.2 if A or B is odd then */ - if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) { + if (mp_isodd (&A) == MP_YES || mp_isodd (&B) == MP_YES) { /* A = (A+y)/2, B = (B-x)/2 */ if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { goto LBL_ERR; @@ -1121,13 +1121,13 @@ top: } /* 5. while v is even do */ - while (mp_iseven (&v) == 1) { + while (mp_iseven (&v) == MP_YES) { /* 5.1 v = v/2 */ if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto LBL_ERR; } /* 5.2 if C or D is odd then */ - if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) { + if (mp_isodd (&C) == MP_YES || mp_isodd (&D) == MP_YES) { /* C = (C+y)/2, D = (D-x)/2 */ if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { goto LBL_ERR; @@ -1175,7 +1175,7 @@ top: } /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) + if (mp_iszero (&u) == MP_NO) goto top; /* now a = C, b = D, gcd == g*v */ @@ -1347,7 +1347,7 @@ int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) int res, n, n2; /* is divisor zero ? */ - if (mp_iszero (b) == 1) { + if (mp_iszero (b) == MP_YES) { return MP_VAL; } @@ -1427,7 +1427,7 @@ int mp_div_2(mp_int * a, mp_int * b) oldused = b->used; b->used = a->used; { - register mp_digit r, rr, *tmpa, *tmpb; + mp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; @@ -1463,7 +1463,7 @@ int mp_div_2(mp_int * a, mp_int * b) /* high level addition (handles signs) */ int mp_add (mp_int * a, mp_int * b, mp_int * c) { - int sa, sb, res; + int sa, sb, res; /* get sign of both inputs */ sa = a->sign; @@ -1523,8 +1523,8 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) c->used = max + 1; { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; /* alias for digit pointers */ @@ -1599,8 +1599,8 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) c->used = max; { - register mp_digit u, *tmpa, *tmpb, *tmpc; - register int i; + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; /* alias for digit pointers */ tmpa = a->dp; @@ -2165,8 +2165,8 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * an array of double precision words W[...] */ { - register mp_word *_W; - register mp_digit *tmpx; + mp_word *_W; + mp_digit *tmpx; /* alias for the W[] array */ _W = W; @@ -2195,7 +2195,7 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * by casting the value down to a mp_digit. Note this requires * that W[ix-1] have the carry cleared (see after the inner loop) */ - register mp_digit mu; + mp_digit mu; mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); /* a = a + mu * m * b**i @@ -2213,9 +2213,9 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * first m->used words of W[] have the carries fixed */ { - register int iy; - register mp_digit *tmpn; - register mp_word *_W; + int iy; + mp_digit *tmpn; + mp_word *_W; /* alias for the digits of the modulus */ tmpn = n->dp; @@ -2238,8 +2238,8 @@ int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) * significant digits we zeroed]. */ { - register mp_digit *tmpx; - register mp_word *_W, *_W1; + mp_digit *tmpx; + mp_word *_W, *_W1; /* nox fix rest of carries */ @@ -2334,9 +2334,9 @@ int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) /* a = a + mu * m * b**i */ { - register int iy; - register mp_digit *tmpn, *tmpx, u; - register mp_word r; + int iy; + mp_digit *tmpn, *tmpx, u; + mp_word r; /* alias for digits of the modulus */ tmpn = n->dp; @@ -2643,16 +2643,56 @@ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) return res; } - if ((res = mp_mul (a, b, &t)) != MP_OKAY) { - mp_clear (&t); - return res; + res = mp_mul (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); } - res = mp_mod (&t, c, d); + mp_clear (&t); return res; } +/* d = a - b (mod c) */ +int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + res = mp_sub (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + + return res; +} + +/* d = a + b (mod c) */ +int mp_addmod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + res = mp_add (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + + return res; +} + /* computes b = a*a */ int mp_sqr (mp_int * a, mp_int * b) { @@ -2728,7 +2768,7 @@ int mp_mul_2(mp_int * a, mp_int * b) b->used = a->used; { - register mp_digit r, rr, *tmpa, *tmpb; + mp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; @@ -2997,7 +3037,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) #else mp_digit W[MP_WARRAY]; #endif - register mp_word _W; + mp_word _W; /* grow the destination as required */ if (c->alloc < digs) { @@ -3055,7 +3095,7 @@ int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) c->used = pa; { - register mp_digit *tmpc; + mp_digit *tmpc; tmpc = c->dp; for (ix = 0; ix < pa+1; ix++) { /* now extract the previous digit [below the carry] */ @@ -3234,7 +3274,6 @@ int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) bits = 1; } - /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { if ((res = mp_mul_2 (a, a)) != MP_OKAY) { @@ -3777,7 +3816,7 @@ int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) c->used = pa; { - register mp_digit *tmpc; + mp_digit *tmpc; tmpc = c->dp + digs; for (ix = digs; ix < pa; ix++) { /* TAO, <= could potentially overwrite */ @@ -4034,12 +4073,12 @@ int mp_cnt_lsb(mp_int *a) mp_digit q, qq; /* easy out */ - if (mp_iszero(a) == 1) { + if (mp_iszero(a) == MP_YES) { return 0; } /* scan lower digits until non-zero */ - for (x = 0; x < a->used && a->dp[x] == 0; x++); + for (x = 0; x < a->used && a->dp[x] == 0; x++) {} q = a->dp[x]; x *= DIGIT_BIT; @@ -4089,7 +4128,7 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) } /* quick outs */ - if (b == 1 || mp_iszero(a) == 1) { + if (b == 1 || mp_iszero(a) == MP_YES) { if (d != NULL) { *d = 0; } @@ -4539,7 +4578,7 @@ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) } } - while (mp_iszero(&v) == 0) { + while (mp_iszero(&v) == MP_NO) { /* make sure v is the largest */ if (mp_cmp_mag(&u, &v) == MP_GT) { /* swap u and v to make sure v is >= u */ @@ -4608,11 +4647,11 @@ int mp_read_radix (mp_int * a, const char *str, int radix) /* process each digit of the string */ while (*str) { - /* if the radix < 36 the conversion is case insensitive + /* if the radix <= 36 the conversion is case insensitive * this allows numbers like 1AB and 1ab to represent the same value * [e.g. in hex] */ - ch = (char) ((radix < 36) ? XTOUPPER((unsigned char)*str) : *str); + ch = (radix <= 36) ? (char)XTOUPPER((unsigned char)*str) : *str; for (y = 0; y < 64; y++) { if (ch == mp_s_rmap[y]) { break; @@ -4637,7 +4676,7 @@ int mp_read_radix (mp_int * a, const char *str, int radix) } /* set the sign only if a != 0 */ - if (mp_iszero(a) != 1) { + if (mp_iszero(a) != MP_YES) { a->sign = neg; } return MP_OKAY; @@ -4717,7 +4756,7 @@ int mp_toradix (mp_int *a, char *str, int radix) } /* quick out if its zero */ - if (mp_iszero(a) == 1) { + if (mp_iszero(a) == MP_YES) { *str++ = '0'; *str = '\0'; return MP_OKAY; @@ -4735,7 +4774,7 @@ int mp_toradix (mp_int *a, char *str, int radix) } digs = 0; - while (mp_iszero (&t) == 0) { + while (mp_iszero (&t) == MP_NO) { if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { mp_clear (&t); return res; diff --git a/wolfcrypt/src/srp.c b/wolfcrypt/src/srp.c index 389540dc4..73abb6ac8 100644 --- a/wolfcrypt/src/srp.c +++ b/wolfcrypt/src/srp.c @@ -428,7 +428,7 @@ int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) return BAD_FUNC_ARG; - if (mp_iszero(&srp->auth)) + if (mp_iszero(&srp->auth) == MP_YES) return SRP_CALL_ORDER_E; r = mp_init(&v); @@ -462,7 +462,7 @@ int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) if (!srp || !private || !size) return BAD_FUNC_ARG; - if (mp_iszero(&srp->auth)) + if (mp_iszero(&srp->auth) == MP_YES) return SRP_CALL_ORDER_E; r = mp_init(&p); @@ -470,7 +470,7 @@ int wc_SrpSetPrivate(Srp* srp, const byte* private, word32 size) return MP_INIT_E; if (!r) r = mp_read_unsigned_bin(&p, private, size); if (!r) r = mp_mod(&p, &srp->N, &srp->priv); - if (!r) r = mp_iszero(&srp->priv) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0; mp_clear(&p); @@ -499,7 +499,7 @@ int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) if (!srp || !pub || !size) return BAD_FUNC_ARG; - if (mp_iszero(&srp->auth)) + if (mp_iszero(&srp->auth) == MP_YES) return SRP_CALL_ORDER_E; modulusSz = mp_unsigned_bin_size(&srp->N); @@ -511,7 +511,7 @@ int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) return MP_INIT_E; /* priv = random() */ - if (mp_iszero(&srp->priv)) + if (mp_iszero(&srp->priv) == MP_YES) r = wc_SrpGenPrivate(srp, pub, modulusSz); /* client side: A = g ^ a % N */ @@ -524,7 +524,7 @@ int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); - if (!r) r = mp_iszero(&i) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_iszero(&i) == MP_YES ? SRP_BAD_KEY_E : 0; if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); if (!r) r = mp_add(&j, &pubkey, &i); @@ -601,7 +601,7 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, || !serverPubKey || serverPubKeySz == 0) return BAD_FUNC_ARG; - if (mp_iszero(&srp->priv)) + if (mp_iszero(&srp->priv) == MP_YES) return SRP_CALL_ORDER_E; /* initializing variables */ @@ -642,11 +642,11 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); - if (!r) r = mp_iszero(&temp1) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_iszero(&temp1) == MP_YES ? SRP_BAD_KEY_E : 0; if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); - if (!r) r = mp_iszero(&temp2) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_iszero(&temp2) == MP_YES ? SRP_BAD_KEY_E : 0; if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; if (!r) r = mp_sub(&temp2, &s, &temp1); @@ -663,7 +663,7 @@ int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); - if (!r) r = mp_iszero(&s) ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_iszero(&s) == MP_YES ? SRP_BAD_KEY_E : 0; if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 97ea4aeae..31bbd7c53 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -104,7 +104,7 @@ void fp_add(fp_int *a, fp_int *b, fp_int *c) void s_fp_add(fp_int *a, fp_int *b, fp_int *c) { int x, y, oldused; - register fp_word t; + fp_word t; y = MAX(a->used, b->used); oldused = MIN(c->used, FP_SIZE); /* help static analysis w/ largest size */ @@ -323,7 +323,7 @@ void fp_mul_2(fp_int * a, fp_int * b) b->used = a->used; { - register fp_digit r, rr, *tmpa, *tmpb; + fp_digit r, rr, *tmpa, *tmpb; /* alias for source */ tmpa = a->dp; @@ -498,8 +498,9 @@ void fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) /* execute loop */ COMBA_FORWARD; for (iz = 0; iz < iy; ++iz) { - /* TAO change COMBA_ADD back to MULADD */ - MULADD(*tmpx++, *tmpy--); + fp_digit _tmpx = *tmpx++; + fp_digit _tmpy = *tmpy--; + MULADD(_tmpx, _tmpy); } /* store term */ @@ -662,7 +663,7 @@ void fp_div_2(fp_int * a, fp_int * b) oldused = b->used; b->used = a->used; { - register fp_digit r, rr, *tmpa, *tmpb; + fp_digit r, rr, *tmpa, *tmpb; /* source alias */ tmpa = a->dp + b->used - 1; @@ -983,10 +984,55 @@ top: /* d = a * b (mod c) */ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) { - fp_int tmp; - fp_init(&tmp); - fp_mul(a, b, &tmp); - return fp_mod(&tmp, c, d); + int err; + fp_int t; + + fp_init(&t); + fp_mul(a, b, &t); +#ifdef ALT_ECC_SIZE + err = fp_mod(&t, c, &t); + fp_copy(&t, d); +#else + err = fp_mod(&t, c, d); +#endif + + return err; +} + +/* d = a - b (mod c) */ +int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; + fp_int t; + + fp_init(&t); + fp_sub(a, b, &t); +#ifdef ALT_ECC_SIZE + err = fp_mod(&t, c, &t); + fp_copy(&t, d); +#else + err = fp_mod(&t, c, d); +#endif + + return err; +} + +/* d = a + b (mod c) */ +int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; + fp_int t; + + fp_init(&t); + fp_add(a, b, &t); +#ifdef ALT_ECC_SIZE + err = fp_mod(&t, c, &t); + fp_copy(&t, d); +#else + err = fp_mod(&t, c, d); +#endif + + return err; } #ifdef TFM_TIMING_RESISTANT @@ -1056,7 +1102,7 @@ static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) return FP_OKAY; } -#else +#else /* TFM_TIMING_RESISTANT */ /* y = g**x (mod b) * Some restrictions... x must be positive and < b @@ -1750,13 +1796,13 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) _c = c + x; tmpm = m->dp; y = 0; - #if (defined(TFM_SSE2) || defined(TFM_X86_64)) +#if defined(INNERMUL8) for (; y < (pa & ~7); y += 8) { INNERMUL8 ; _c += 8; tmpm += 8; } - #endif +#endif for (; y < pa; y++) { INNERMUL; ++_c; @@ -1791,7 +1837,7 @@ void fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) } } -void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c) +void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) { /* zero the int */ fp_zero (a); @@ -1978,7 +2024,7 @@ void fp_lshd(fp_int *a, int x) /* right shift by bit count */ void fp_rshb(fp_int *c, int x) { - register fp_digit *tmpc, mask, shift; + fp_digit *tmpc, mask, shift; fp_digit r, rr; fp_digit D = x; @@ -2057,6 +2103,7 @@ void fp_sub_d(fp_int *a, fp_digit b, fp_int *c) fp_init(&tmp); fp_set(&tmp, b); fp_sub(a, &tmp, c); + fp_clear(&tmp); } @@ -2146,6 +2193,18 @@ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) return fp_mulmod(a, b, c, d); } +/* d = a - b (mod c) */ +int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +{ + return fp_submod(a, b, c, d); +} + +/* d = a + b (mod c) */ +int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +{ + return fp_addmod(a, b, c, d); +} + /* c = a mod b, 0 <= c < b */ int mp_mod (mp_int * a, mp_int * b, mp_int * c) { @@ -2196,7 +2255,7 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) /* reads a unsigned char array, assumes the msb is stored first [big endian] */ int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) { - fp_read_unsigned_bin(a, (unsigned char *)b, c); + fp_read_unsigned_bin(a, b, c); return MP_OKAY; } @@ -2263,6 +2322,10 @@ int mp_iszero(mp_int* a) return fp_iszero(a); } +int mp_isneg(mp_int* a) +{ + return fp_isneg(a); +} int mp_count_bits (mp_int* a) { @@ -2778,7 +2841,7 @@ void fp_add_d(fp_int *a, fp_digit b, fp_int *c) fp_int tmp; fp_init(&tmp); fp_set(&tmp, b); - fp_add(a,&tmp,c); + fp_add(a, &tmp, c); } /* external compatibility */ @@ -2804,6 +2867,9 @@ static int fp_read_radix(fp_int *a, const char *str, int radix) int y, neg; char ch; + /* set the integer to the default of zero */ + fp_zero (a); + /* make sure the radix is ok */ if (radix < 2 || radix > 64) { return FP_VAL; @@ -2819,16 +2885,13 @@ static int fp_read_radix(fp_int *a, const char *str, int radix) neg = FP_ZPOS; } - /* set the integer to the default of zero */ - fp_zero (a); - /* process each digit of the string */ while (*str) { - /* if the radix < 36 the conversion is case insensitive + /* if the radix <= 36 the conversion is case insensitive * this allows numbers like 1AB and 1ab to represent the same value * [e.g. in hex] */ - ch = (char) ((radix < 36) ? XTOUPPER((unsigned char)*str) : *str); + ch = (char)((radix <= 36) ? XTOUPPER((unsigned char)*str) : *str); for (y = 0; y < 64; y++) { if (ch == fp_s_rmap[y]) { break; diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index ceead20d1..4c2973202 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -253,6 +253,9 @@ int idea_test(void); #define FOURK_BUF 4096 +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + + static int err_sys(const char* msg, int es) { @@ -6466,7 +6469,7 @@ static int ecc_test_vector(int keySize) vec.d = "e14f37b3d1374ff8b03f41b9b3fdd2f0ebccf275d660d7f3"; vec.R = "6994d962bdd0d793ffddf855ec5bf2f91a9698b46258a63e"; vec.S = "02ba6465a234903744ab02bc8521405b73cf5fc00e1a9f41"; - vec.curveName = "ECC-192"; + vec.curveName = "SECP192R1"; break; #endif /* HAVE_ECC192 */ @@ -6494,7 +6497,7 @@ static int ecc_test_vector(int keySize) vec.d = "97c4b796e1639dd1035b708fc00dc7ba1682cec44a1002a1a820619f"; vec.R = "147b33758321e722a0360a4719738af848449e2c1d08defebc1671a7"; vec.S = "24fc7ed7f1352ca3872aa0916191289e2e04d454935d50fe6af3ad5b"; - vec.curveName = "ECC-224"; + vec.curveName = "SECP224R1"; break; #endif /* HAVE_ECC224 */ @@ -6522,7 +6525,7 @@ static int ecc_test_vector(int keySize) vec.d = "be34baa8d040a3b991f9075b56ba292f755b90e4b6dc10dad36715c33cfdac25"; vec.R = "2b826f5d44e2d0b6de531ad96b51e8f0c56fdfead3c236892e4d84eacfc3b75c"; vec.S = "a2248b62c03db35a7cd63e8a120a3521a89d3d2f61ff99035a2148ae32e3a248"; - vec.curveName = "nistp256"; + vec.curveName = "SECP256R1"; break; #endif /* !NO_ECC256 */ @@ -6550,7 +6553,7 @@ static int ecc_test_vector(int keySize) vec.d = "a492ce8fa90084c227e1a32f7974d39e9ff67a7e8705ec3419b35fb607582bebd461e0b1520ac76ec2dd4e9b63ebae71"; vec.R = "6820b8585204648aed63bdff47f6d9acebdea62944774a7d14f0e14aa0b9a5b99545b2daee6b3c74ebf606667a3f39b7"; vec.S = "491af1d0cccd56ddd520b233775d0bc6b40a6255cc55207d8e9356741f23c96c14714221078dbd5c17f4fdd89b32a907"; - vec.curveName = "nistp384"; + vec.curveName = "SECP384R1"; break; #endif /* HAVE_ECC384 */ @@ -6578,7 +6581,7 @@ static int ecc_test_vector(int keySize) vec.d = "1bd56bd106118eda246155bd43b42b8e13f0a6e25dd3bb376026fab4dc92b6157bc6dfec2d15dd3d0cf2a39aa68494042af48ba9601118da82c6f2108a3a203ad74"; vec.R = "0bd117b4807710898f9dd7778056485777668f0e78e6ddf5b000356121eb7a220e9493c7f9a57c077947f89ac45d5acb6661bbcd17abb3faea149ba0aa3bb1521be"; vec.S = "019cd2c5c3f9870ecdeb9b323abdf3a98cd5e231d85c6ddc5b71ab190739f7f226e6b134ba1d5889ddeb2751dabd97911dff90c34684cdbe7bb669b6c3d22f2480c"; - vec.curveName = "nistp521"; + vec.curveName = "SECP521R1"; break; #endif /* HAVE_ECC521 */ default: @@ -6672,7 +6675,7 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) } #endif /* WOLFSSL_KEY_GEN */ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, - int testCompressedKey) + int testCompressedKey, const ecc_set_type* dp) { #ifdef BENCH_EMBEDDED byte sharedA[128]; /* Needs to be at least keySize */ @@ -6700,34 +6703,34 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, wc_ecc_init(&userB); wc_ecc_init(&pubKey); - ret = wc_ecc_make_key(rng, keySize, &userA); + ret = wc_ecc_make_key_ex(rng, keySize, &userA, dp); if (ret != 0) - return -1014; + ERROR_OUT(-1014, done); ret = wc_ecc_check_key(&userA); if (ret != 0) - return -1023; + ERROR_OUT(-1023, done); - ret = wc_ecc_make_key(rng, keySize, &userB); + ret = wc_ecc_make_key_ex(rng, keySize, &userB, dp); if (ret != 0) - return -1002; + ERROR_OUT(-1002, done); #ifdef HAVE_ECC_DHE x = sizeof(sharedA); ret = wc_ecc_shared_secret(&userA, &userB, sharedA, &x); if (ret != 0) - return -1015; + ERROR_OUT(-1015, done); y = sizeof(sharedB); ret = wc_ecc_shared_secret(&userB, &userA, sharedB, &y); if (ret != 0) - return -1003; + ERROR_OUT(-1003, done); if (y != x) - return -1004; + ERROR_OUT(-1004, done); if (memcmp(sharedA, sharedB, x)) - return -1005; + ERROR_OUT(-1005, done); #endif /* HAVE_ECC_DHE */ #ifdef HAVE_ECC_KEY_EXPORT @@ -6735,21 +6738,21 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, ret = wc_ecc_export_x963(&userA, exportBuf, &x); if (ret != 0) - return -1006; + ERROR_OUT(-1006, done); #ifdef HAVE_ECC_KEY_IMPORT - ret = wc_ecc_import_x963(exportBuf, x, &pubKey); + ret = wc_ecc_import_x963_ex(exportBuf, x, &pubKey, dp); if (ret != 0) - return -1007; + ERROR_OUT(-1007, done); #ifdef HAVE_ECC_DHE y = sizeof(sharedB); ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); if (ret != 0) - return -1008; + ERROR_OUT(-1008, done); if (memcmp(sharedA, sharedB, y)) - return -1009; + ERROR_OUT(-1009, done); #endif /* HAVE_ECC_DHE */ if (testCompressedKey) { @@ -6759,22 +6762,22 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, ret = wc_ecc_export_x963_ex(&userA, exportBuf, &x, 1); if (ret != 0) - return -1010; + ERROR_OUT(-1010, done); wc_ecc_free(&pubKey); wc_ecc_init(&pubKey); ret = wc_ecc_import_x963(exportBuf, x, &pubKey); if (ret != 0) - return -1011; + ERROR_OUT(-1011, done); #ifdef HAVE_ECC_DHE y = sizeof(sharedB); ret = wc_ecc_shared_secret(&userB, &pubKey, sharedB, &y); if (ret != 0) - return -1012; + ERROR_OUT(-1012, done); if (memcmp(sharedA, sharedB, y)) - return -1013; + ERROR_OUT(-1013, done); #endif /* HAVE_ECC_DHE */ #endif /* HAVE_COMP_KEY */ } @@ -6792,16 +6795,16 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount, ret = wc_ecc_sign_hash(digest, sizeof(digest), sig, &x, rng, &userA); if (ret != 0) - return -1014; + ERROR_OUT(-1014, done); #ifdef HAVE_ECC_VERIFY for (i=0; i Basic Manipulations <--- */ #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) #define mp_iseven(a) \ - (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO) + (((a)->used > 0 && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO) #define mp_isodd(a) \ - (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO) - + (((a)->used > 0 && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO) +#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) /* number of primes */ #ifdef MP_8BIT @@ -296,6 +296,8 @@ int mp_mul_2(mp_int * a, mp_int * b); int mp_mul (mp_int * a, mp_int * b, mp_int * c); int mp_sqr (mp_int * a, mp_int * b); int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); int mp_2expt (mp_int * a, int b); int mp_set_bit (mp_int * a, int b); diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index edcfb740f..42c6966b5 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -383,6 +383,7 @@ typedef struct { #define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) #define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) #define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) +#define fp_isneg(a) (((a)->sign != 0) ? FP_YES : FP_NO) /* set to a small digit */ void fp_set(fp_int *a, fp_digit b); @@ -480,6 +481,12 @@ void fp_mul_d(fp_int *a, fp_digit b, fp_int *c); /* d = a * b (mod c) */ int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); +/* d = a - b (mod c) */ +int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +/* d = a + b (mod c) */ +int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + /* c = a * a (mod b) */ int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c); @@ -527,16 +534,16 @@ int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); /*int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);*/ -/* radix conersions */ +/* radix conversions */ int fp_count_bits(fp_int *a); int fp_leading_bit(fp_int *a); int fp_unsigned_bin_size(fp_int *a); -void fp_read_unsigned_bin(fp_int *a, unsigned char *b, int c); +void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c); void fp_to_unsigned_bin(fp_int *a, unsigned char *b); /*int fp_signed_bin_size(fp_int *a);*/ -/*void fp_read_signed_bin(fp_int *a, unsigned char *b, int c);*/ +/*void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c);*/ /*void fp_to_signed_bin(fp_int *a, unsigned char *b);*/ /*int fp_read_radix(fp_int *a, char *str, int radix);*/ @@ -591,20 +598,20 @@ void fp_sqr_comba64(fp_int *a, fp_int *b); */ /* Types */ - typedef fp_digit mp_digit; - typedef fp_word mp_word; - typedef fp_int mp_int; +typedef fp_digit mp_digit; +typedef fp_word mp_word; +typedef fp_int mp_int; /* Constants */ - #define MP_LT FP_LT /* less than */ - #define MP_EQ FP_EQ /* equal to */ - #define MP_GT FP_GT /* greater than */ - #define MP_VAL FP_VAL /* invalid */ - #define MP_MEM FP_MEM /* memory error */ - #define MP_NOT_INF FP_NOT_INF /* point not at infinity */ - #define MP_OKAY FP_OKAY /* ok result */ - #define MP_NO FP_NO /* yes/no result */ - #define MP_YES FP_YES /* yes/no result */ +#define MP_LT FP_LT /* less than */ +#define MP_EQ FP_EQ /* equal to */ +#define MP_GT FP_GT /* greater than */ +#define MP_VAL FP_VAL /* invalid */ +#define MP_MEM FP_MEM /* memory error */ +#define MP_NOT_INF FP_NOT_INF /* point not at infinity */ +#define MP_OKAY FP_OKAY /* ok result */ +#define MP_NO FP_NO /* yes/no result */ +#define MP_YES FP_YES /* yes/no result */ /* Prototypes */ #define mp_zero(a) fp_zero(a) @@ -620,6 +627,8 @@ int mp_add_d (mp_int * a, mp_digit b, mp_int * c); int mp_mul (mp_int * a, mp_int * b, mp_int * c); int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); int mp_mod(mp_int *a, mp_int *b, mp_int *c); int mp_invmod(mp_int *a, mp_int *b, mp_int *c); int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); @@ -637,6 +646,7 @@ int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); int mp_copy(fp_int* a, fp_int* b); int mp_isodd(mp_int* a); int mp_iszero(mp_int* a); +int mp_isneg(mp_int* a); int mp_count_bits(mp_int *a); int mp_leading_bit(mp_int *a); int mp_set_int(mp_int *a, mp_digit b);