From e6c22fbd85e4cb78cdd290d10f5359bc5a08874b Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 17 Jul 2018 10:18:05 +1000 Subject: [PATCH] Small stack support in ECC Small stack builds now dynamically allocate large stack variables. Cache option added to avoid repeated allocation of temporaries in add points, double point and map. Cached memory allocated in mulmod and mul2add. --- wolfcrypt/src/ecc.c | 1320 ++++++++++++++++++++++++++++++--------- wolfssl/wolfcrypt/ecc.h | 25 +- 2 files changed, 1052 insertions(+), 293 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index a61f92cc1..d6c433cd6 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1222,15 +1222,35 @@ enum ecc_curve_load_mask { static wolfSSL_Mutex ecc_curve_cache_mutex; #endif - #define DECLARE_CURVE_SPECS(intcount) ecc_curve_spec* curve = NULL; + #define DECLARE_CURVE_SPECS(curve, intcount) ecc_curve_spec* curve = NULL + #define ALLOC_CURVE_SPECS(intcount) + #define FREE_CURVE_SPECS() +#elif defined(WOLFSSL_SMALL_STACK) + #define DECLARE_CURVE_SPECS(curve, intcount) \ + mp_int* spec_ints = NULL; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_count = intcount + + #define ALLOC_CURVE_SPECS(intcount) \ + spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \ + DYNAMIC_TYPE_ECC); \ + if (spec_ints == NULL) \ + return MEMORY_E; \ + curve->spec_ints = spec_ints + #define FREE_CURVE_SPECS() \ + XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC) #else - #define DECLARE_CURVE_SPECS(intcount) \ + #define DECLARE_CURVE_SPECS(curve, intcount) \ mp_int spec_ints[(intcount)]; \ ecc_curve_spec curve_lcl; \ ecc_curve_spec* curve = &curve_lcl; \ XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ curve->spec_ints = spec_ints; \ - curve->spec_count = intcount; + curve->spec_count = intcount + #define ALLOC_CURVE_SPECS(intcount) + #define FREE_CURVE_SPECS() #endif /* ECC_CACHE_CURVE */ static void _wc_ecc_curve_free(ecc_curve_spec* curve) @@ -1505,12 +1525,22 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, mp_int* a, mp_int* modulus, mp_digit mp) { #ifndef WOLFSSL_SP_MATH - mp_int t1, t2; +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; #ifdef ALT_ECC_SIZE - mp_int rx, ry, rz; + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; #endif - mp_int *x, *y, *z; - int err; +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif + mp_int *x, *y, *z; + int err; if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { return ECC_BAD_ARG_E; @@ -1523,19 +1553,84 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, Q = tPt; } - if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key != NULL) { + t1 = R->key->t1; + t2 = R->key->t2; +#ifdef ALT_ECC_SIZE + rx = R->key->x; + ry = R->key->y; + rz = R->key->z; +#endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; } /* should we dbl instead? */ if (err == MP_OKAY) - err = mp_sub(modulus, Q->y, &t1); + err = mp_sub(modulus, Q->y, t1); if (err == MP_OKAY) { if ( (mp_cmp(P->x, Q->x) == MP_EQ) && (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && - (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, &t1) == MP_EQ)) { - mp_clear(&t1); - mp_clear(&t2); + (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) { + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } + #endif return ecc_projective_dbl_point(P, R, a, modulus, mp); } } @@ -1548,9 +1643,9 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, ecc_point x,y,z is reduced size */ #ifdef ALT_ECC_SIZE /* Use local stack variable */ - x = ℞ - y = &ry; - z = &rz; + x = rx; + y = ry; + z = rz; if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { goto done; @@ -1573,25 +1668,25 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, if (err == MP_OKAY) { if (!mp_iszero(Q->z)) { /* T1 = Z' * Z' */ - err = mp_sqr(Q->z, &t1); + 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); + err = mp_mul(t1, x, x); if (err == MP_OKAY) err = mp_montgomery_reduce(x, modulus, mp); /* T1 = Z' * T1 */ if (err == MP_OKAY) - err = mp_mul(Q->z, &t1, &t1); + 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); + err = mp_mul(t1, y, y); if (err == MP_OKAY) err = mp_montgomery_reduce(y, modulus, mp); } @@ -1599,69 +1694,69 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, /* T1 = Z*Z */ if (err == MP_OKAY) - err = mp_sqr(z, &t1); + 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); + 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); + 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); + 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) - err = mp_sub(y, &t1, y); + err = mp_sub(y, t1, y); if (err == MP_OKAY) { if (mp_isneg(y)) err = mp_add(y, modulus, y); } /* T1 = 2T1 */ if (err == MP_OKAY) - err = mp_add(&t1, &t1, &t1); + err = mp_add(t1, t1, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } /* T1 = Y + T1 */ if (err == MP_OKAY) - err = mp_add(&t1, y, &t1); + err = mp_add(t1, y, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } /* X = X - T2 */ if (err == MP_OKAY) - err = mp_sub(x, &t2, x); + err = mp_sub(x, t2, x); if (err == MP_OKAY) { if (mp_isneg(x)) err = mp_add(x, modulus, x); } /* T2 = 2T2 */ if (err == MP_OKAY) - err = mp_add(&t2, &t2, &t2); + err = mp_add(t2, t2, t2); if (err == MP_OKAY) { - if (mp_cmp(&t2, modulus) != MP_LT) - err = mp_sub(&t2, modulus, &t2); + if (mp_cmp(t2, modulus) != MP_LT) + err = mp_sub(t2, modulus, t2); } /* T2 = X + T2 */ if (err == MP_OKAY) - err = mp_add(&t2, x, &t2); + err = mp_add(t2, x, t2); if (err == MP_OKAY) { - if (mp_cmp(&t2, modulus) != MP_LT) - err = mp_sub(&t2, modulus, &t2); + if (mp_cmp(t2, modulus) != MP_LT) + err = mp_sub(t2, modulus, t2); } if (err == MP_OKAY) { @@ -1681,9 +1776,9 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, /* T1 = T1 * X */ if (err == MP_OKAY) - err = mp_mul(&t1, x, &t1); + 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) @@ -1693,15 +1788,15 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, /* T2 = T2 * x */ if (err == MP_OKAY) - err = mp_mul(&t2, x, &t2); + 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); + 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) @@ -1711,34 +1806,34 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, /* X = X - T2 */ if (err == MP_OKAY) - err = mp_sub(x, &t2, x); + err = mp_sub(x, t2, x); if (err == MP_OKAY) { if (mp_isneg(x)) err = mp_add(x, modulus, x); } /* T2 = T2 - X */ if (err == MP_OKAY) - err = mp_sub(&t2, x, &t2); + err = mp_sub(t2, x, t2); if (err == MP_OKAY) { - if (mp_isneg(&t2)) - err = mp_add(&t2, modulus, &t2); + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); } /* T2 = T2 - X */ if (err == MP_OKAY) - err = mp_sub(&t2, x, &t2); + err = mp_sub(t2, x, t2); if (err == MP_OKAY) { - if (mp_isneg(&t2)) - err = mp_add(&t2, modulus, &t2); + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); } /* T2 = T2 * Y */ if (err == MP_OKAY) - err = mp_mul(&t2, y, &t2); + 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) - err = mp_sub(&t2, &t1, y); + err = mp_sub(t2, t1, y); if (err == MP_OKAY) { if (mp_isneg(y)) err = mp_add(y, modulus, y); @@ -1763,8 +1858,22 @@ int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, done: /* clean up */ - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; #else @@ -1811,9 +1920,19 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, mp_int* modulus, mp_digit mp) { #ifndef WOLFSSL_SP_MATH - mp_int t1, t2; +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; #ifdef ALT_ECC_SIZE - mp_int rx, ry, rz; + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif #endif mp_int *x, *y, *z; int err; @@ -1821,7 +1940,58 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, 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) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key != NULL) { + t1 = R->key->t1; + t2 = R->key->t2; + #ifdef ALT_ECC_SIZE + rx = R->key->x; + ry = R->key->y; + rz = R->key->z; + #endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + } +#endif + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; } @@ -1829,13 +1999,27 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, ecc_point x,y,z is reduced size */ #ifdef ALT_ECC_SIZE /* Use local stack variable */ - x = ℞ - y = &ry; - z = &rz; + x = rx; + y = ry; + z = rz; if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } + #endif return err; } #else @@ -1854,9 +2038,9 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, /* T1 = Z * Z */ if (err == MP_OKAY) - err = mp_sqr(z, &t1); + 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) @@ -1876,44 +2060,44 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, #ifdef WOLFSSL_CUSTOM_CURVES if (err == MP_OKAY) { /* Use a and prime to determine if a == 3 */ - err = mp_submod(modulus, a, modulus, &t2); + err = mp_submod(modulus, a, modulus, t2); } - if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) { + if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) { /* use "a" in calc */ /* T2 = T1 * T1 */ if (err == MP_OKAY) - err = mp_sqr(&t1, &t2); + err = mp_sqr(t1, t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, mp); + err = mp_montgomery_reduce(t2, modulus, mp); /* T1 = T2 * a */ if (err == MP_OKAY) - err = mp_mulmod(&t2, a, modulus, &t1); + err = mp_mulmod(t2, a, modulus, t1); /* T2 = X * X */ if (err == MP_OKAY) - err = mp_sqr(x, &t2); + err = mp_sqr(x, t2); if (err == MP_OKAY) - err = mp_montgomery_reduce(&t2, modulus, mp); + err = mp_montgomery_reduce(t2, modulus, mp); /* T1 = T2 + T1 */ if (err == MP_OKAY) - err = mp_add(&t1, &t2, &t1); + err = mp_add(t1, t2, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + 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); + err = mp_add(t1, t2, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + 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); + err = mp_add(t1, t2, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } } else @@ -1924,37 +2108,37 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, /* T2 = X - T1 */ if (err == MP_OKAY) - err = mp_sub(x, &t1, &t2); + err = mp_sub(x, t1, t2); if (err == MP_OKAY) { - if (mp_isneg(&t2)) - err = mp_add(&t2, modulus, &t2); + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); } /* T1 = X + T1 */ if (err == MP_OKAY) - err = mp_add(&t1, x, &t1); + err = mp_add(t1, x, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } /* T2 = T1 * T2 */ if (err == MP_OKAY) - err = mp_mul(&t1, &t2, &t2); + 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) - err = mp_add(&t2, &t2, &t1); + err = mp_add(t2, t2, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } /* T1 = T1 + T2 */ if (err == MP_OKAY) - err = mp_add(&t1, &t2, &t1); + err = mp_add(t1, t2, t1); if (err == MP_OKAY) { - if (mp_cmp(&t1, modulus) != MP_LT) - err = mp_sub(&t1, modulus, &t1); + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); } } @@ -1973,17 +2157,17 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, /* T2 = Y * Y */ if (err == MP_OKAY) - err = mp_sqr(y, &t2); + 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) == MP_YES) - err = mp_add(&t2, modulus, &t2); + if (mp_isodd(t2) == MP_YES) + err = mp_add(t2, modulus, t2); } if (err == MP_OKAY) - err = mp_div_2(&t2, &t2); + err = mp_div_2(t2, t2); /* Y = Y * X */ if (err == MP_OKAY) @@ -1993,7 +2177,7 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, /* X = T1 * T1 */ if (err == MP_OKAY) - err = mp_sqr(&t1, x); + err = mp_sqr(t1, x); if (err == MP_OKAY) err = mp_montgomery_reduce(x, modulus, mp); @@ -2021,13 +2205,13 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, } /* Y = Y * T1 */ if (err == MP_OKAY) - err = mp_mul(y, &t1, y); + err = mp_mul(y, t1, y); if (err == MP_OKAY) err = mp_montgomery_reduce(y, modulus, mp); /* Y = Y - T2 */ if (err == MP_OKAY) - err = mp_sub(y, &t2, y); + err = mp_sub(y, t2, y); if (err == MP_OKAY) { if (mp_isneg(y)) err = mp_add(y, modulus, y); @@ -2043,8 +2227,23 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, #endif /* clean up */ - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; #else @@ -2069,10 +2268,20 @@ int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) { #ifndef WOLFSSL_SP_MATH - mp_int t1, t2; +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; #ifdef ALT_ECC_SIZE - mp_int rx, ry, rz; + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; #endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif /* WOLFSSL_SMALL_STACK */ mp_int *x, *y, *z; int err; @@ -2089,15 +2298,66 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) return err; } - if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key != NULL) { + t1 = P->key->t1; + t2 = P->key->t2; + #ifdef ALT_ECC_SIZE + rx = P->key->x; + ry = P->key->y; + rz = P->key->z; + #endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return MEMORY_E; } #ifdef ALT_ECC_SIZE /* Use local stack variable */ - x = ℞ - y = &ry; - z = &rz; + x = rx; + y = ry; + z = rz; if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { goto done; @@ -2125,25 +2385,25 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) /* get 1/z */ if (err == MP_OKAY) - err = mp_invmod(z, modulus, &t1); + err = mp_invmod(z, modulus, t1); /* get 1/z^2 and 1/z^3 */ if (err == MP_OKAY) - err = mp_sqr(&t1, &t2); + err = mp_sqr(t1, t2); if (err == MP_OKAY) - err = mp_mod(&t2, modulus, &t2); + err = mp_mod(t2, modulus, t2); if (err == MP_OKAY) - err = mp_mul(&t1, &t2, &t1); + err = mp_mul(t1, t2, t1); if (err == MP_OKAY) - err = mp_mod(&t1, modulus, &t1); + err = mp_mod(t1, modulus, t1); /* multiply against x/y */ if (err == MP_OKAY) - err = mp_mul(x, &t2, x); + err = mp_mul(x, t2, x); if (err == MP_OKAY) err = mp_montgomery_reduce(x, modulus, mp); if (err == MP_OKAY) - err = mp_mul(y, &t1, y); + err = mp_mul(y, t1, y); if (err == MP_OKAY) err = mp_montgomery_reduce(y, modulus, mp); @@ -2163,8 +2423,23 @@ done: #endif /* clean up */ - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif return err; #else @@ -2215,7 +2490,14 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, ecc_point *tG, *M[M_POINTS]; int i, err; - mp_int mu; +#ifdef WOLFSSL_SMALL_STACK + mp_int* mu = NULL; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif +#else + mp_int mu[1]; +#endif mp_digit mp; mp_digit buf; int bitcnt = 0, mode = 0, digidx = 0; @@ -2227,17 +2509,82 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* init variables */ tG = NULL; XMEMSET(M, 0, sizeof(M)); +#ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + return MEMORY_E; +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key.t1 == NULL || key.t2 == NULL +#ifdef ALT_ECC_SIZE + || key.x == NULL || key.y == NULL || key.z == NULL +#endif + ) { +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + XFREE(mu, heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK_CACHE */ /* init montgomery reduction */ if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif return err; } - if ((err = mp_init(&mu)) != MP_OKAY) { + if ((err = mp_init(mu)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif return err; } - if ((err = mp_montgomery_calc_normalization(&mu, modulus)) != MP_OKAY) { - mp_clear(&mu); + if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) { + mp_clear(mu); +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -2245,9 +2592,12 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, for (i = 0; i < M_POINTS; i++) { M[i] = wc_ecc_new_point_h(heap); if (M[i] == NULL) { - mp_clear(&mu); + mp_clear(mu); err = MEMORY_E; goto exit; } +#ifdef WOLFSSL_SMALL_STACK_CACHE + M[i]->key = &key; +#endif } /* make a copy of G in case R==G */ @@ -2257,24 +2607,27 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, /* tG = G and convert to montgomery */ if (err == MP_OKAY) { - if (mp_cmp_d(&mu, 1) == MP_EQ) { + if (mp_cmp_d(mu, 1) == MP_EQ) { err = mp_copy(G->x, tG->x); if (err == MP_OKAY) err = mp_copy(G->y, tG->y); if (err == MP_OKAY) err = mp_copy(G->z, tG->z); } else { - err = mp_mulmod(G->x, &mu, modulus, tG->x); + err = mp_mulmod(G->x, mu, modulus, tG->x); if (err == MP_OKAY) - err = mp_mulmod(G->y, &mu, modulus, tG->y); + err = mp_mulmod(G->y, mu, modulus, tG->y); if (err == MP_OKAY) - err = mp_mulmod(G->z, &mu, modulus, tG->z); + err = mp_mulmod(G->z, mu, modulus, tG->z); } } /* done with mu */ - mp_clear(&mu); + mp_clear(mu); +#ifdef WOLFSSL_SMALL_STACK_CACHE + R->key = &key; +#endif #ifndef ECC_TIMING_RESISTANT /* calc the M tab, which holds kG for k==8..15 */ @@ -2536,6 +2889,19 @@ exit: for (i = 0; i < M_POINTS; i++) { wc_ecc_del_point_h(M[i], heap); } +#ifdef WOLFSSL_SMALL_STACK_CACHE + R->key = NULL; +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif return err; #else @@ -2820,30 +3186,50 @@ static int wc_ecc_cmp_param(const char* curveParam, const byte* param, word32 paramSz) { int err = MP_OKAY; - mp_int a, b; +#ifdef WOLFSSL_SMALL_STACK + mp_int* a = NULL; + mp_int* b = NULL; +#else + mp_int a[1], b[1]; +#endif if (param == NULL || curveParam == NULL) return BAD_FUNC_ARG; - if ((err = mp_init_multi(&a, &b, NULL, NULL, NULL, NULL)) != MP_OKAY) +#ifdef WOLFSSL_SMALL_STACK + a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (a == NULL) + return MEMORY_E; + b = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (b == NULL) { + XFREE(a, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + if ((err = mp_init_multi(a, b, NULL, NULL, NULL, NULL)) != MP_OKAY) return err; if (err == MP_OKAY) - err = mp_read_unsigned_bin(&a, param, paramSz); + err = mp_read_unsigned_bin(a, param, paramSz); if (err == MP_OKAY) - err = mp_read_radix(&b, curveParam, MP_RADIX_HEX); + err = mp_read_radix(b, curveParam, MP_RADIX_HEX); if (err == MP_OKAY) { - if (mp_cmp(&a, &b) != MP_EQ) { + if (mp_cmp(a, b) != MP_EQ) { err = -1; } else { err = MP_EQ; } } - mp_clear(&a); - mp_clear(&b); + mp_clear(a); + mp_clear(b); +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_ECC); + XFREE(a, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -3160,18 +3546,22 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, byte* out, word32 *outlen) { int err; - DECLARE_CURVE_SPECS(2) + DECLARE_CURVE_SPECS(curve, 2); if (private_key == NULL || point == NULL || out == NULL || outlen == NULL) { return BAD_FUNC_ARG; } + ALLOC_CURVE_SPECS(2); + /* load curve info */ err = wc_ecc_curve_load(private_key->dp, &curve, (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); - if (err != MP_OKAY) + if (err != MP_OKAY) { + FREE_CURVE_SPECS(); return err; + } #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { @@ -3186,6 +3576,7 @@ int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, } wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); return err; } @@ -3350,7 +3741,7 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, ecc_point* base = NULL; #endif ecc_point* pub; - DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); #endif if (key == NULL) { @@ -3358,6 +3749,7 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, } #ifndef WOLFSSL_ATECC508A + /* if ecc_point passed in then use it as output for public key point */ if (pubOut != NULL) { pub = pubOut; @@ -3374,6 +3766,8 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, curve = curveIn; } else { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + /* load curve info */ if (err == MP_OKAY) err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); @@ -3448,6 +3842,9 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, /* free up local curve */ if (curveIn == NULL) { wc_ecc_curve_free(curve); + #ifndef WOLFSSL_ATECC508A + FREE_CURVE_SPECS(); + #endif } #else @@ -3484,7 +3881,9 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) { int err; #ifndef WOLFSSL_ATECC508A - DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) +#ifndef WOLFSSL_SP_MATH + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif #endif if (key == NULL || rng == NULL) { @@ -3548,6 +3947,8 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) err = WC_KEY_SIZE_E; #else { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + /* setup the key variables */ err = mp_init(&key->k); @@ -3574,6 +3975,9 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) /* cleanup allocations */ wc_ecc_curve_free(curve); + #ifndef WOLFSSL_ATECC508A + FREE_CURVE_SPECS(); + #endif } #endif @@ -3806,7 +4210,7 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, { int err; mp_int *r = NULL, *s = NULL; -#ifndef WOLFSSL_ASYNC_CRYPT +#if !defined(WOLFSSL_ASYNC_CRYPT) && !defined(WOLFSSL_SMALL_STACK) mp_int r_lcl, s_lcl; #endif @@ -3829,9 +4233,18 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, return err; r = key->r; s = key->s; -#else +#elif !defined(WOLFSSL_SMALL_STACK) r = &r_lcl; s = &s_lcl; +#else + r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (r == NULL) + return MEMORY_E; + s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (s == NULL) { + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } #endif switch(key->state) { @@ -3878,6 +4291,10 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, /* done with R/S */ mp_clear(r); mp_clear(s); + #if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_SMALL_STACK) + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif break; default: @@ -3917,13 +4334,13 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, int err; #ifndef WOLFSSL_SP_MATH mp_int* e; -#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) +#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \ + !defined(WOLFSSL_SMALL_STACK) mp_int e_lcl; #endif + DECLARE_CURVE_SPECS(curve, 1); #endif /* !WOLFSSL_SP_MATH */ - DECLARE_CURVE_SPECS(1) - if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) return ECC_BAD_ARG_E; @@ -3973,18 +4390,32 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #endif + ALLOC_CURVE_SPECS(1); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) err = wc_ecc_alloc_mpint(key, &key->e); - if (err != 0) + if (err != 0) { + FREE_CURVE_SPECS(); return err; + } e = key->e; -#else +#elif !defined(WOLFSSL_SMALL_STACK) e = &e_lcl; +#else + e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (e == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } #endif /* get the hash and load it as a bignum into 'e' */ /* init the bignums */ if ((err = mp_init(e)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(e, key->heap, DYNAMIC_TYPE_ECC); + #endif + FREE_CURVE_SPECS(); return err; } @@ -4008,8 +4439,12 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, /* make up a key and export the public copy */ if (err == MP_OKAY) { - int loop_check = 0; - ecc_key pubkey; + int loop_check = 0; + #ifdef WOLFSSL_SMALL_STACK + ecc_key* pubkey = NULL; + #else + ecc_key pubkey[1]; + #endif #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { @@ -4077,6 +4512,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, mp_clear(k); #endif wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); return err; } @@ -4084,18 +4520,38 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, } #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLFSSL_SMALL_STACK + pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC); + if (pubkey == NULL) + err = MEMORY_E; + #endif + /* don't use async for key, since we don't support async return here */ - if ((err = wc_ecc_init_ex(&pubkey, key->heap, INVALID_DEVID)) == MP_OKAY) { - mp_int b; + if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap, + INVALID_DEVID)) == MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* b = NULL; + #else + mp_int b[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, + DYNAMIC_TYPE_ECC); + if (b == NULL) + err = MEMORY_E; + } + #endif if (err == MP_OKAY) { - err = mp_init(&b); + err = mp_init(b); } #ifdef WOLFSSL_CUSTOM_CURVES /* if custom curve, apply params to pubkey */ if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) { - err = wc_ecc_set_custom_curve(&pubkey, key->dp); + err = wc_ecc_set_custom_curve(pubkey, key->dp); } #endif @@ -4107,7 +4563,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, break; } - err = wc_ecc_gen_k(rng, key->dp->size, &b, curve->order); + err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order); } while (err == MP_ZERO_E); loop_check = 0; @@ -4118,32 +4574,32 @@ 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, key->dp->size, &pubkey, + err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey, key->dp->id); if (err != MP_OKAY) break; /* find r = x1 mod n */ - err = mp_mod(pubkey.pubkey.x, curve->order, r); + err = mp_mod(pubkey->pubkey.x, curve->order, r); if (err != MP_OKAY) break; if (mp_iszero(r) == MP_YES) { #ifndef ALT_ECC_SIZE - mp_clear(pubkey.pubkey.x); - mp_clear(pubkey.pubkey.y); - mp_clear(pubkey.pubkey.z); + mp_clear(pubkey->pubkey.x); + mp_clear(pubkey->pubkey.y); + mp_clear(pubkey->pubkey.z); #endif - mp_forcezero(&pubkey.k); + mp_forcezero(&pubkey->k); } else { /* find s = (e + xr)/k = b.(e/k.b + x.r/k.b) */ /* k = k.b */ - err = mp_mulmod(&pubkey.k, &b, curve->order, &pubkey.k); + err = mp_mulmod(&pubkey->k, b, curve->order, &pubkey->k); if (err != MP_OKAY) break; /* k = 1/k.b */ - err = mp_invmod(&pubkey.k, curve->order, &pubkey.k); + err = mp_invmod(&pubkey->k, curve->order, &pubkey->k); if (err != MP_OKAY) break; /* s = x.r */ @@ -4151,11 +4607,11 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, if (err != MP_OKAY) break; /* s = x.r/k.b */ - err = mp_mulmod(&pubkey.k, s, curve->order, s); + err = mp_mulmod(&pubkey->k, s, curve->order, s); if (err != MP_OKAY) break; /* e = e/k.b */ - err = mp_mulmod(&pubkey.k, e, curve->order, e); + err = mp_mulmod(&pubkey->k, e, curve->order, e); if (err != MP_OKAY) break; /* s = e/k.b + x.r/k.b @@ -4165,7 +4621,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, /* s = b.(e + x.r)/k.b = (e + x.r)/k */ - err = mp_mulmod(s, &b, curve->order, s); + err = mp_mulmod(s, b, curve->order, s); if (err != MP_OKAY) break; /* s = (e + xr)/k */ @@ -4176,14 +4632,24 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, break; } } - wc_ecc_free(&pubkey); - mp_clear(&b); - mp_free(&b); + mp_clear(b); + mp_free(b); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + wc_ecc_free(pubkey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC); + #endif } } mp_clear(e); wc_ecc_curve_free(curve); +#ifdef WOLFSSL_SMALL_STACK + XFREE(e, key->heap, DYNAMIC_TYPE_ECC); +#endif + FREE_CURVE_SPECS(); #endif /* WOLFSSL_SP_MATH */ return err; @@ -4275,12 +4741,19 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, void* heap) #endif { - ecc_point* precomp[16]; +#ifdef WOLFSSL_SMALL_STACK + ecc_point** precomp = NULL; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif +#else + ecc_point* precomp[SHAMIR_PRECOMP_SZ]; +#endif unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; unsigned char* tA; unsigned char* tB; int err = MP_OKAY, first, x, y; - mp_digit mp = 0; + mp_digit mp = 0; /* argchks */ if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || @@ -4298,11 +4771,51 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); return GEN_MEM_ERR; } +#ifdef WOLFSSL_SMALL_STACK + precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (precomp == NULL) { + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return GEN_MEM_ERR; + } +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key.t1 == NULL || key.t2 == NULL +#ifdef ALT_ECC_SIZE + || key.x == NULL || key.y == NULL || key.z == NULL +#endif + ) { +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return MEMORY_E; + } + C->key = &key; +#endif /* WOLFSSL_SMALL_STACK_CACHE */ /* init variables */ XMEMSET(tA, 0, ECC_BUFSIZE); XMEMSET(tB, 0, ECC_BUFSIZE); +#ifndef WOLFSSL_SMALL_STACK XMEMSET(precomp, 0, sizeof(precomp)); +#else + XMEMSET(precomp, 0, sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ); +#endif /* get sizes */ lenA = mp_unsigned_bin_size(kA); @@ -4324,12 +4837,15 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, /* allocate the table */ if (err == MP_OKAY) { - for (x = 0; x < 16; x++) { + for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { precomp[x] = wc_ecc_new_point_h(heap); if (precomp[x] == NULL) { err = GEN_MEM_ERR; break; } + #ifdef WOLFSSL_SMALL_STACK_CACHE + precomp[x]->key = &key; + #endif } } } @@ -4339,29 +4855,43 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, err = mp_montgomery_setup(modulus, &mp); if (err == MP_OKAY) { - mp_int mu; - err = mp_init(&mu); + #ifdef WOLFSSL_SMALL_STACK + mp_int* mu = NULL; + #else + mp_int mu[1]; + #endif + #ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + err = MEMORY_E; + #endif if (err == MP_OKAY) { - err = mp_montgomery_calc_normalization(&mu, modulus); + err = mp_init(mu); + } + 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); + err = mp_mulmod(A->x, mu, modulus, precomp[1]->x); if (err == MP_OKAY) - err = mp_mulmod(A->y, &mu, modulus, precomp[1]->y); + err = mp_mulmod(A->y, mu, modulus, precomp[1]->y); if (err == MP_OKAY) - err = mp_mulmod(A->z, &mu, modulus, precomp[1]->z); + 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); + 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); + 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); + err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z); /* done with mu */ - mp_clear(&mu); + mp_clear(mu); + #ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); + #endif } } @@ -4383,11 +4913,12 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, if (err == MP_OKAY) { /* precomp [i,j](A + B) table (i != 0, j != 0) */ for (x = 1; x < 4; x++) { - for (y = 1; y < 4; y++) { - if (err == MP_OKAY) - err = ecc_projective_add_point(precomp[x], precomp[(y<<2)], - precomp[x+(y<<2)], a, modulus, mp); + for (y = 1; y < 4; y++) { + if (err == MP_OKAY) { + err = ecc_projective_add_point(precomp[x], precomp[(y<<2)], + precomp[x+(y<<2)], a, modulus, mp); } + } } } @@ -4462,14 +4993,27 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, err = ecc_map(C, modulus, mp); /* clean up */ - for (x = 0; x < 16; x++) { + for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { wc_ecc_del_point_h(precomp[x], heap); } ForceZero(tA, ECC_BUFSIZE); ForceZero(tB, ECC_BUFSIZE); - XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + C->key = NULL; +#endif +#ifdef WOLFSSL_SMALL_STACK + XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); +#endif XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); return err; } @@ -4506,7 +5050,9 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, int err; mp_int *r = NULL, *s = NULL; #ifndef WOLFSSL_ASYNC_CRYPT - mp_int r_lcl, s_lcl; +#ifndef WOLFSSL_SMALL_STACK + mp_int r_lcl[1], s_lcl[1]; +#endif #endif if (sig == NULL || hash == NULL || res == NULL || key == NULL) { @@ -4528,8 +5074,19 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, r = key->r; s = key->s; #else - r = &r_lcl; - s = &s_lcl; +#ifndef WOLFSSL_SMALL_STACK + r = r_lcl; + s = s_lcl; +#else + r = XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (r == NULL) + return MEMORY_E; + s = XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (s == NULL) { + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif #endif switch(key->state) { @@ -4560,6 +5117,10 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, /* done with R/S */ mp_clear(r); mp_clear(s); + #ifdef WOLFSSL_SMALL_STACK + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif #endif if (err < 0) { @@ -4612,15 +5173,25 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #elif !defined(WOLFSSL_SP_MATH) int did_init = 0; ecc_point *mG = NULL, *mQ = NULL; - mp_int v; - mp_int w; - mp_int u1; - mp_int u2; - mp_int* e; +#ifdef WOLFSSL_SMALL_STACK + mp_int* v = NULL; + mp_int* w = NULL; + mp_int* u1 = NULL; + mp_int* u2 = NULL; #if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) - mp_int e_lcl; + mp_int* e_lcl = NULL; #endif - DECLARE_CURVE_SPECS(ECC_CURVE_FIELD_COUNT) +#else /* WOLFSSL_SMALL_STACK */ + mp_int v[1]; + mp_int w[1]; + mp_int u1[1]; + mp_int u2[1]; +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + mp_int e_lcl[1]; +#endif +#endif /* WOLFSSL_SMALL_STACK */ + mp_int* e; + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); #endif if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) @@ -4668,7 +5239,6 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, (void)hashlen; #else - /* checking if private key with no public part */ if (key->type == ECC_PRIVATEKEY_ONLY) { WOLFSSL_MSG("Verify called with private key, generating public part"); @@ -4698,16 +5268,27 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, key->pubkey.z,r, s, res, key->heap); } -#endif -#endif +#endif /* WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ + + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); #if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) err = wc_ecc_alloc_mpint(key, &key->e); - if (err != 0) + if (err != 0) { + FREE_CURVE_SPECS(); return err; + } e = key->e; #else - e = &e_lcl; +#ifdef WOLFSSL_SMALL_STACK + e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (e_lcl == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } +#endif + e = e_lcl; #endif err = mp_init(e); @@ -4772,6 +5353,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_clear(e); #endif wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); return err; } @@ -4779,9 +5361,32 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, } #endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (v == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (w == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (u2 == NULL) + err = MEMORY_E; + } +#endif + /* allocate ints */ if (err == MP_OKAY) { - if ((err = mp_init_multi(&v, &w, &u1, &u2, NULL, NULL)) != MP_OKAY) { + if ((err = mp_init_multi(v, w, u1, u2, NULL, NULL)) != MP_OKAY) { err = MEMORY_E; } did_init = 1; @@ -4797,15 +5402,15 @@ 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, curve->order, &w); + err = mp_invmod(s, curve->order, w); /* u1 = ew */ if (err == MP_OKAY) - err = mp_mulmod(e, &w, curve->order, &u1); + err = mp_mulmod(e, w, curve->order, u1); /* u2 = rw */ if (err == MP_OKAY) - err = mp_mulmod(r, &w, curve->order, &u2); + err = mp_mulmod(r, w, curve->order, u2); /* find mG and mQ */ if (err == MP_OKAY) @@ -4825,9 +5430,9 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #ifdef FREESCALE_LTC_ECC /* use PKHA to compute u1*mG + u2*mQ */ if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u1, mG, mG, curve->Af, curve->prime, 0, key->heap); + err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) - err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); + err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); if (err == MP_OKAY) err = wc_ecc_point_add(mG, mQ, mG, curve->prime); #else @@ -4837,11 +5442,11 @@ 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, curve->Af, curve->prime, 0, + err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap); } if (err == MP_OKAY) { - err = wc_ecc_mulmod_ex(&u2, mQ, mQ, curve->Af, curve->prime, 0, + err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); } @@ -4861,18 +5466,18 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, #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, curve->Af, curve->prime, + err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime, key->heap); } #endif /* ECC_SHAMIR */ #endif /* FREESCALE_LTC_ECC */ /* v = X_x1 mod n */ if (err == MP_OKAY) - err = mp_mod(mG->x, curve->order, &v); + err = mp_mod(mG->x, curve->order, v); /* does v == r */ if (err == MP_OKAY) { - if (mp_cmp(&v, r) == MP_EQ) + if (mp_cmp(v, r) == MP_EQ) *res = 1; } @@ -4882,13 +5487,23 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, mp_clear(e); if (did_init) { - mp_clear(&v); - mp_clear(&w); - mp_clear(&u1); - mp_clear(&u2); + mp_clear(v); + mp_clear(w); + mp_clear(u1); + mp_clear(u2); } +#ifdef WOLFSSL_SMALL_STACK + XFREE(u2, key->heap, DYNAMIC_TYPE_ECC); + XFREE(u1, key->heap, DYNAMIC_TYPE_ECC); + XFREE(w, key->heap, DYNAMIC_TYPE_ECC); + XFREE(v, key->heap, DYNAMIC_TYPE_ECC); +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); +#endif +#endif wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); #endif /* WOLFSSL_SP_MATH */ #endif /* WOLFSSL_ATECC508A */ @@ -4967,7 +5582,9 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, #ifndef WOLFSSL_SP_MATH int did_init = 0; mp_int t1, t2; - DECLARE_CURVE_SPECS(3) + DECLARE_CURVE_SPECS(curve, 3); + + ALLOC_CURVE_SPECS(3); if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; @@ -5017,6 +5634,7 @@ int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, } wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); #else sp_ecc_uncompress_256(point->x, pointType, point->y); #endif @@ -5226,42 +5844,62 @@ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) { #ifndef WOLFSSL_SP_MATH int err; - mp_int t1, t2; +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#else + mp_int t1[1], t2[1]; +#endif - if ((err = mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + return MEMORY_E; + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t2 == NULL) { + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + #endif return err; } /* compute y^2 */ if (err == MP_OKAY) - err = mp_sqr(ecp->y, &t1); + err = mp_sqr(ecp->y, t1); /* compute x^3 */ if (err == MP_OKAY) - err = mp_sqr(ecp->x, &t2); + err = mp_sqr(ecp->x, t2); if (err == MP_OKAY) - err = mp_mod(&t2, prime, &t2); + err = mp_mod(t2, prime, t2); if (err == MP_OKAY) - err = mp_mul(ecp->x, &t2, &t2); + err = mp_mul(ecp->x, t2, t2); /* compute y^2 - x^3 */ if (err == MP_OKAY) - err = mp_sub(&t1, &t2, &t1); + err = mp_sub(t1, t2, t1); /* Determine if curve "a" should be used in calc */ #ifdef WOLFSSL_CUSTOM_CURVES if (err == MP_OKAY) { /* Use a and prime to determine if a == 3 */ - err = mp_set(&t2, 0); + err = mp_set(t2, 0); if (err == MP_OKAY) - err = mp_submod(prime, a, prime, &t2); + err = mp_submod(prime, a, prime, t2); } - if (err == MP_OKAY && mp_cmp_d(&t2, 3) != MP_EQ) { + if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) { /* compute y^2 - x^3 + a*x */ if (err == MP_OKAY) - err = mp_mulmod(&t2, ecp->x, prime, &t2); + err = mp_mulmod(t2, ecp->x, prime, t2); if (err == MP_OKAY) - err = mp_addmod(&t1, &t2, prime, &t1); + err = mp_addmod(t1, t2, prime, t1); } else #endif /* WOLFSSL_CUSTOM_CURVES */ @@ -5271,34 +5909,38 @@ int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) /* compute y^2 - x^3 + 3x */ if (err == MP_OKAY) - err = mp_add(&t1, ecp->x, &t1); + err = mp_add(t1, ecp->x, t1); if (err == MP_OKAY) - err = mp_add(&t1, ecp->x, &t1); + err = mp_add(t1, ecp->x, t1); if (err == MP_OKAY) - err = mp_add(&t1, ecp->x, &t1); + err = mp_add(t1, ecp->x, t1); if (err == MP_OKAY) - err = mp_mod(&t1, prime, &t1); + err = mp_mod(t1, prime, t1); } /* adjust range (0, prime) */ - while (err == MP_OKAY && mp_isneg(&t1)) { - err = mp_add(&t1, prime, &t1); + while (err == MP_OKAY && mp_isneg(t1)) { + err = mp_add(t1, prime, t1); } - while (err == MP_OKAY && mp_cmp(&t1, prime) != MP_LT) { - err = mp_sub(&t1, prime, &t1); + while (err == MP_OKAY && mp_cmp(t1, prime) != MP_LT) { + err = mp_sub(t1, prime, t1); } /* compare to b */ if (err == MP_OKAY) { - if (mp_cmp(&t1, b) != MP_EQ) { + if (mp_cmp(t1, b) != MP_EQ) { err = MP_VAL; } else { err = MP_OKAY; } } - mp_clear(&t1); - mp_clear(&t2); + mp_clear(t1); + mp_clear(t2); +#ifdef WOLFSSL_SMALL_STACK + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); +#endif return err; #else @@ -5317,11 +5959,13 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) int err = MP_OKAY; ecc_point* base = NULL; ecc_point* res = NULL; - DECLARE_CURVE_SPECS(2) + DECLARE_CURVE_SPECS(curve, 2); if (key == NULL) return BAD_FUNC_ARG; + ALLOC_CURVE_SPECS(2); + res = wc_ecc_new_point_h(key->heap); if (res == NULL) err = MEMORY_E; @@ -5371,6 +6015,7 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) wc_ecc_curve_free(curve); wc_ecc_del_point_h(res, key->heap); wc_ecc_del_point_h(base, key->heap); + FREE_CURVE_SPECS(); return err; } @@ -5383,7 +6028,7 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) { int err; #ifndef WOLFSSL_ATECC508A - DECLARE_CURVE_SPECS(2) + DECLARE_CURVE_SPECS(curve, 2); #endif if (key == NULL) @@ -5394,6 +6039,7 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) err = BAD_COND_E; #else + ALLOC_CURVE_SPECS(curve, 2); /* load curve info */ err = wc_ecc_curve_load(key->dp, &curve, @@ -5403,6 +6049,7 @@ static int ecc_check_privkey_gen_helper(ecc_key* key) err = ecc_check_privkey_gen(key, curve->Af, curve->prime); wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); #endif /* WOLFSSL_ATECC508A */ @@ -5462,15 +6109,15 @@ int wc_ecc_check_key(ecc_key* key) int err; #ifndef WOLFSSL_SP_MATH #ifndef WOLFSSL_ATECC508A - mp_int* b; + mp_int* b = NULL; #ifdef USE_ECC_B_PARAM - DECLARE_CURVE_SPECS(4) + DECLARE_CURVE_SPECS(curve, 4); #else +#ifndef WOLFSSL_SMALL_STACK mp_int b_lcl; - DECLARE_CURVE_SPECS(3) - b = &b_lcl; - XMEMSET(b, 0, sizeof(mp_int)); #endif + DECLARE_CURVE_SPECS(curve, 3); +#endif /* USE_ECC_B_PARAM */ #endif /* WOLFSSL_ATECC508A */ if (key == NULL) @@ -5484,11 +6131,31 @@ int wc_ecc_check_key(ecc_key* key) err = 0; /* consider key check success on ECC508A */ #else + #ifdef USE_ECC_B_PARAM + ALLOC_CURVE_SPECS(4); + #else + ALLOC_CURVE_SPECS(3); + #ifndef WOLFSSL_SMALL_STACK + b = &b_lcl; + #else + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (b == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } + #endif + XMEMSET(b, 0, sizeof(mp_int)); + #endif /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */ /* pubkey point cannot be at infinity */ - if (wc_ecc_point_is_at_infinity(&key->pubkey)) + if (wc_ecc_point_is_at_infinity(&key->pubkey)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + FREE_CURVE_SPECS(); return ECC_INF_E; + } /* load curve info */ err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | @@ -5537,8 +6204,13 @@ int wc_ecc_check_key(ecc_key* key) #ifndef USE_ECC_B_PARAM mp_clear(b); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif #endif + FREE_CURVE_SPECS(); + #endif /* WOLFSSL_ATECC508A */ #else if (key == NULL) @@ -5635,7 +6307,8 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, mp_int t1, t2; int did_init = 0; - DECLARE_CURVE_SPECS(3) + DECLARE_CURVE_SPECS(curve, 3); + ALLOC_CURVE_SPECS(3); if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) err = MEMORY_E; @@ -5687,6 +6360,7 @@ int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, } wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); #else sp_ecc_uncompress_256(key->pubkey.x, pointType, key->pubkey.y); #endif @@ -5932,31 +6606,56 @@ int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) { int err; - mp_int rtmp; - mp_int stmp; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif if (r == NULL || s == NULL || out == NULL || outlen == NULL) return ECC_BAD_ARG_E; - err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif - err = mp_read_radix(&rtmp, r, MP_RADIX_HEX); + err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + err = mp_read_radix(rtmp, r, MP_RADIX_HEX); if (err == MP_OKAY) - err = mp_read_radix(&stmp, s, MP_RADIX_HEX); + err = mp_read_radix(stmp, s, MP_RADIX_HEX); /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */ if (err == MP_OKAY) - err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp); + err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp); if (err == MP_OKAY) { - if (mp_iszero(&rtmp) == MP_YES || mp_iszero(&stmp) == MP_YES) + if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES) err = MP_ZERO_E; } - mp_clear(&rtmp); - mp_clear(&stmp); + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -5975,31 +6674,56 @@ int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz, byte* out, word32* outlen) { int err; - mp_int rtmp; - mp_int stmp; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif if (r == NULL || s == NULL || out == NULL || outlen == NULL) return ECC_BAD_ARG_E; - err = mp_init_multi(&rtmp, &stmp, NULL, NULL, NULL, NULL); - if (err != MP_OKAY) - return err; +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif - err = mp_read_unsigned_bin(&rtmp, r, rSz); + err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + err = mp_read_unsigned_bin(rtmp, r, rSz); if (err == MP_OKAY) - err = mp_read_unsigned_bin(&stmp, s, sSz); + err = mp_read_unsigned_bin(stmp, s, sSz); /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */ if (err == MP_OKAY) - err = StoreECC_DSA_Sig(out, outlen, &rtmp, &stmp); + err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp); if (err == MP_OKAY) { - if (mp_iszero(&rtmp) == MP_YES || mp_iszero(&stmp) == MP_YES) + if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES) err = MP_ZERO_E; } - mp_clear(&rtmp); - mp_clear(&stmp); + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } @@ -6019,40 +6743,60 @@ int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, { int err; word32 x = 0; - mp_int rtmp; - mp_int stmp; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL) return ECC_BAD_ARG_E; - err = DecodeECC_DSA_Sig(sig, sigLen, &rtmp, &stmp); +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp); /* extract r */ if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&rtmp); + x = mp_unsigned_bin_size(rtmp); if (*rLen < x) err = BUFFER_E; if (err == MP_OKAY) { *rLen = x; - err = mp_to_unsigned_bin(&rtmp, r); + err = mp_to_unsigned_bin(rtmp, r); } } /* extract s */ if (err == MP_OKAY) { - x = mp_unsigned_bin_size(&stmp); + x = mp_unsigned_bin_size(stmp); if (*sLen < x) err = BUFFER_E; if (err == MP_OKAY) { *sLen = x; - err = mp_to_unsigned_bin(&stmp, s); + err = mp_to_unsigned_bin(stmp, s); } } - mp_clear(&rtmp); - mp_clear(&stmp); + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif return err; } diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ed4054dd8..0f5b16073 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -135,6 +135,9 @@ enum { ECC_POINT_COMP_EVEN = 0x02, ECC_POINT_COMP_ODD = 0x03, ECC_POINT_UNCOMP = 0x04, + + /* Shamir's dual add constants */ + SHAMIR_PRECOMP_SZ = 16, }; /* Curve Types */ @@ -301,6 +304,11 @@ typedef struct alt_fp_int { } alt_fp_int; #endif /* ALT_ECC_SIZE */ +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif + /* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpreted as affine */ @@ -315,6 +323,9 @@ typedef struct { mp_int* z; /* The z coordinate */ alt_fp_int xyz[3]; #endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key* key; +#endif } ecc_point; /* ECC Flags */ @@ -360,12 +371,16 @@ struct ecc_key { CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ #endif #endif /* WOLFSSL_ASYNC_CRYPT */ -}; - -#ifndef WC_ECCKEY_TYPE_DEFINED - typedef struct ecc_key ecc_key; - #define WC_ECCKEY_TYPE_DEFINED +#ifdef WOLFSSL_SMALL_STACK_CACHE + mp_int* t1; + mp_int* t2; +#ifdef ALT_ECC_SIZE + mp_int* x; + mp_int* y; + mp_int* z; #endif +#endif +}; /* ECC predefined curve sets */