From 6c4bcb3b596aaf2e259f16dc7edd7a57b60076ba Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 3 Aug 2020 10:15:56 +1000 Subject: [PATCH] tfm: Check for overflow and return error (fixed max size) --- wolfcrypt/src/tfm.c | 604 ++++++++++++++++++++++++++++++---------- wolfssl/wolfcrypt/tfm.h | 22 +- 2 files changed, 471 insertions(+), 155 deletions(-) diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 16468ff9f..25ad17088 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -103,9 +103,10 @@ word32 CheckRunTimeFastMath(void) /* Functions */ -void fp_add(fp_int *a, fp_int *b, fp_int *c) +int fp_add(fp_int *a, fp_int *b, fp_int *c) { - int sa, sb; + int sa, sb; + int ret = FP_OKAY; /* get sign of both inputs */ sa = a->sign; @@ -116,7 +117,7 @@ void fp_add(fp_int *a, fp_int *b, fp_int *c) /* both positive or both negative */ /* add their magnitudes, copy the sign */ c->sign = sa; - s_fp_add (a, b, c); + ret = s_fp_add (a, b, c); } else { /* one positive, the other negative */ /* subtract the one with the greater magnitude from */ @@ -130,10 +131,12 @@ void fp_add(fp_int *a, fp_int *b, fp_int *c) s_fp_sub (a, b, c); } } + + return ret; } /* unsigned addition */ -void s_fp_add(fp_int *a, fp_int *b, fp_int *c) +int s_fp_add(fp_int *a, fp_int *b, fp_int *c) { int x, y, oldused; fp_word t; @@ -152,6 +155,9 @@ void s_fp_add(fp_int *a, fp_int *b, fp_int *c) c->dp[c->used++] = (fp_digit)t; ++x; } + if (x == FP_SIZE) { + return FP_VAL; + } c->used = x; @@ -160,12 +166,14 @@ void s_fp_add(fp_int *a, fp_int *b, fp_int *c) c->dp[x] = 0; } fp_clamp(c); + return FP_OKAY; } /* c = a - b */ -void fp_sub(fp_int *a, fp_int *b, fp_int *c) +int fp_sub(fp_int *a, fp_int *b, fp_int *c) { - int sa, sb; + int sa, sb; + int ret = FP_OKAY; sa = a->sign; sb = b->sign; @@ -176,7 +184,7 @@ void fp_sub(fp_int *a, fp_int *b, fp_int *c) /* In either case, ADD their magnitudes, */ /* and use the sign of the first number. */ c->sign = sa; - s_fp_add (a, b, c); + ret = s_fp_add (a, b, c); } else { /* subtract a positive from a positive, OR */ /* subtract a negative from a negative. */ @@ -195,6 +203,7 @@ void fp_sub(fp_int *a, fp_int *b, fp_int *c) s_fp_sub (b, a, c); } } + return ret; } /* unsigned subtraction ||a|| >= ||b|| ALWAYS! */ @@ -242,9 +251,9 @@ int fp_mul(fp_int *A, fp_int *B, fp_int *C) y = MAX(A->used, B->used); yy = MIN(A->used, B->used); - /* call generic if we're out of range */ + /* fail if we are out of range */ if (y + yy > FP_SIZE) { - ret = fp_mul_comba(A, B, C); + ret = FP_VAL; goto clean; } @@ -356,10 +365,16 @@ clean: return ret; } -void fp_mul_2(fp_int * a, fp_int * b) +int fp_mul_2(fp_int * a, fp_int * b) { int x, oldused; + /* Make sure value to double and result are in range. */ + if ((a->used > (FP_SIZE-1)) || ((a->used == (FP_SIZE - 1)) && + ((a->dp[FP_SIZE - 1] & ((fp_digit)1 << (DIGIT_BIT - 1))) != 0))) { + return FP_VAL; + } + oldused = b->used; b->used = a->used; @@ -391,7 +406,7 @@ void fp_mul_2(fp_int * a, fp_int * b) } /* new leading digit? */ - if (r != 0 && b->used != (FP_SIZE-1)) { + if (r != 0) { /* add a MSB which is always 1 at this point */ *tmpb = 1; ++(b->used); @@ -404,10 +419,12 @@ void fp_mul_2(fp_int * a, fp_int * b) } } b->sign = a->sign; + + return FP_OKAY; } /* c = a * b */ -void fp_mul_d(fp_int *a, fp_digit b, fp_int *c) +int fp_mul_d(fp_int *a, fp_digit b, fp_int *c) { fp_word w; int x, oldused; @@ -431,11 +448,15 @@ void fp_mul_d(fp_int *a, fp_digit b, fp_int *c) for (; x < oldused && x < FP_SIZE; x++) { c->dp[x] = 0; } + if (x == FP_SIZE) + return FP_VAL; + fp_clamp(c); + return FP_OKAY; } /* c = a * 2**d */ -void fp_mul_2d(fp_int *a, int b, fp_int *c) +int fp_mul_2d(fp_int *a, int b, fp_int *c) { fp_digit carry, carrytmp, shift; int x; @@ -445,7 +466,9 @@ void fp_mul_2d(fp_int *a, int b, fp_int *c) /* handle whole digits */ if (b >= DIGIT_BIT) { - fp_lshd(c, b/DIGIT_BIT); + int ret = fp_lshd(c, b/DIGIT_BIT); + if (ret != FP_OKAY) + return ret; } b %= DIGIT_BIT; @@ -462,8 +485,11 @@ void fp_mul_2d(fp_int *a, int b, fp_int *c) if (carry && x < FP_SIZE) { c->dp[c->used++] = carry; } + if (x == FP_SIZE) + return FP_VAL; } fp_clamp(c); + return FP_OKAY; } /* generic PxQ multiplier */ @@ -529,6 +555,8 @@ int fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) fp_int *tmp; #endif + if (A->used + B->used >= FP_SIZE) return FP_VAL; + IF_HAVE_INTEL_MULX(ret = fp_mul_comba_mulx(A, B, C), return ret) ; #ifdef WOLFSSL_SMALL_STACK @@ -598,6 +626,7 @@ int fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) { int n, t, i, norm, neg; + int ret; #ifndef WOLFSSL_SMALL_STACK fp_int q[1], x[1], y[1], t1[1], t2[1]; #else @@ -643,11 +672,23 @@ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ norm = fp_count_bits(y) % DIGIT_BIT; if (norm < (int)(DIGIT_BIT-1)) { - norm = (DIGIT_BIT-1) - norm; - fp_mul_2d (x, norm, x); - fp_mul_2d (y, norm, y); + norm = (DIGIT_BIT-1) - norm; + ret = fp_mul_2d (x, norm, x); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } + ret = fp_mul_2d (y, norm, y); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } } else { - norm = 0; + norm = 0; } /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ @@ -655,11 +696,23 @@ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) t = y->used - 1; /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ - fp_lshd (y, n - t); /* y = y*b**{n-t} */ + ret = fp_lshd (y, n - t); /* y = y*b**{n-t} */ + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } while (fp_cmp (x, y) != FP_LT) { ++(q->dp[n - t]); - fp_sub (x, y, x); + ret = fp_sub (x, y, x); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } } /* reset y by shifting it back down */ @@ -697,7 +750,13 @@ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) t1->dp[0] = (t - 1 < 0) ? 0 : y->dp[t - 1]; t1->dp[1] = y->dp[t]; t1->used = 2; - fp_mul_d (t1, q->dp[i - t - 1], t1); + ret = fp_mul_d (t1, q->dp[i - t - 1], t1); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } /* find right hand */ t2->dp[0] = (i - 2 < 0) ? 0 : x->dp[i - 2]; @@ -707,15 +766,45 @@ int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) } while (fp_cmp_mag(t1, t2) == FP_GT); /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ - fp_mul_d (y, q->dp[i - t - 1], t1); - fp_lshd (t1, i - t - 1); - fp_sub (x, t1, x); + ret = fp_mul_d (y, q->dp[i - t - 1], t1); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } + ret = fp_lshd (t1, i - t - 1); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } + ret = fp_sub (x, t1, x); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ if (x->sign == FP_NEG) { fp_copy (y, t1); - fp_lshd (t1, i - t - 1); - fp_add (x, t1, x); + ret = fp_lshd (t1, i - t - 1); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } + ret = fp_add (x, t1, x); + if (ret != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return ret; + } q->dp[i - t - 1] = q->dp[i - t - 1] - 1; } } @@ -850,7 +939,7 @@ int fp_mod(fp_int *a, fp_int *b, fp_int *c) err = fp_div(a, b, NULL, t); if (err == FP_OKAY) { if (t->sign != b->sign) { - fp_add(t, b, c); + err = fp_add(t, b, c); } else { fp_copy(t, c); } @@ -953,8 +1042,20 @@ top: /* 4.2 if A or B is odd then */ if (fp_isodd (A) == FP_YES || fp_isodd (B) == FP_YES) { /* A = (A+y)/2, B = (B-x)/2 */ - fp_add (A, y, A); - fp_sub (B, x, B); + err = fp_add (A, y, A); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_OKAY; + } + err = fp_sub (B, x, B); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } /* A = A/2, B = B/2 */ fp_div_2 (A, A); @@ -969,8 +1070,20 @@ top: /* 5.2 if C or D is odd then */ if (fp_isodd (C) == FP_YES || fp_isodd (D) == FP_YES) { /* C = (C+y)/2, D = (D-x)/2 */ - fp_add (C, y, C); - fp_sub (D, x, D); + err = fp_add (C, y, C); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_OKAY; + } + err = fp_sub (D, x, D); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } /* C = C/2, D = D/2 */ fp_div_2 (C, C); @@ -980,14 +1093,50 @@ top: /* 6. if u >= v then */ if (fp_cmp (u, v) != FP_LT) { /* u = u - v, A = A - C, B = B - D */ - fp_sub (u, v, u); - fp_sub (A, C, A); - fp_sub (B, D, B); + err = fp_sub (u, v, u); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_sub (A, C, A); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_sub (B, D, B); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } else { /* v - v - u, C = C - A, D = D - B */ - fp_sub (v, u, v); - fp_sub (C, A, C); - fp_sub (D, B, D); + err = fp_sub (v, u, v); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_sub (C, A, C); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_sub (D, B, D); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } /* if not zero goto step 4 */ @@ -1006,12 +1155,24 @@ top: /* if its too low */ while (fp_cmp_d(C, 0) == FP_LT) { - fp_add(C, b, C); + err = fp_add(C, b, C); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_OKAY; + } } /* too big */ while (fp_cmp_mag(C, b) != FP_LT) { - fp_sub(C, b, C); + err = fp_sub(C, b, C); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_OKAY; + } } /* C is now the inverse */ @@ -1097,7 +1258,13 @@ top: /* 4.2 if B is odd then */ if (fp_isodd (B) == FP_YES) { - fp_sub (B, x, B); + err = fp_sub (B, x, B); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } /* B = B/2 */ fp_div_2 (B, B); @@ -1111,7 +1278,13 @@ top: /* 5.2 if D is odd then */ if (fp_isodd (D) == FP_YES) { /* D = (D-x)/2 */ - fp_sub (D, x, D); + err = fp_sub (D, x, D); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } /* D = D/2 */ fp_div_2 (D, D); @@ -1120,12 +1293,36 @@ top: /* 6. if u >= v then */ if (fp_cmp (u, v) != FP_LT) { /* u = u - v, B = B - D */ - fp_sub (u, v, u); - fp_sub (B, D, B); + err = fp_sub (u, v, u); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_sub (B, D, B); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } else { /* v - v - u, D = D - B */ - fp_sub (v, u, v); - fp_sub (D, B, D); + err = fp_sub (v, u, v); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } + err = fp_sub (D, B, D); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } /* if not zero goto step 4 */ @@ -1147,10 +1344,22 @@ top: neg = a->sign; while (D->sign == FP_NEG) { fp_add (D, b, D); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return FP_OKAY; + } } /* too big */ while (fp_cmp_mag(D, b) != FP_LT) { - fp_sub(D, b, D); + err = fp_sub(D, b, D); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } } fp_copy (D, c); c->sign = neg; @@ -1282,15 +1491,17 @@ int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) #endif fp_init(t); - fp_sub(a, b, t); -#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) - if (d->size < FP_SIZE) { - err = fp_mod(t, c, t); - fp_copy(t, d); - } else -#endif - { - err = fp_mod(t, c, d); + err = fp_sub(a, b, t); + if (err == FP_OKAY) { + #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(t, c, t); + fp_copy(t, d); + } else + #endif + { + err = fp_mod(t, c, d); + } } #ifdef WOLFSSL_SMALL_STACK @@ -1316,15 +1527,17 @@ int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) #endif fp_init(t); - fp_add(a, b, t); -#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) - if (d->size < FP_SIZE) { - err = fp_mod(t, c, t); - fp_copy(t, d); - } else -#endif - { - err = fp_mod(t, c, d); + err = fp_add(a, b, t); + if (err == FP_OKAY) { + #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(t, c, t); + fp_copy(t, d); + } else + #endif + { + err = fp_mod(t, c, d); + } } #ifdef WOLFSSL_SMALL_STACK @@ -1430,7 +1643,11 @@ int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y) case TFM_EXPTMOD_NB_MONT: /* mod m -> R[0] */ - fp_montgomery_calc_normalization(&nb->R[0], P); + err = fp_montgomery_calc_normalization(&nb->R[0], P); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } nb->state = TFM_EXPTMOD_NB_MONT_RED; break; @@ -1472,7 +1689,11 @@ int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y) case TFM_EXPTMOD_NB_MONT_MODCHK: /* m matches sign of (G * R mod m) */ if (nb->R[1].sign != P->sign) { - fp_add(&nb->R[1], P, &nb->R[1]); + err = fp_add(&nb->R[1], P, &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } } /* set initial mode and bit cnt */ @@ -1600,7 +1821,13 @@ static int _fp_exptmod_ct(fp_int * G, fp_int * X, int digits, fp_int * P, #endif /* now we need R mod m */ - fp_montgomery_calc_normalization (&R[0], P); + err = fp_montgomery_calc_normalization (&R[0], P); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_BIGINT); + #endif + return err; + } /* now set R[0][1] to G * R mod m */ if (fp_cmp_mag(P, G) != FP_GT) { @@ -1783,17 +2010,23 @@ static int _fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) * The first half of the table is not computed though except for M[0] and M[1] */ - /* now we need R mod m */ - fp_montgomery_calc_normalization (res, P); + /* now we need R mod m */ + err = fp_montgomery_calc_normalization (res, P); + if (err != FP_OKAY) { +#ifndef WOLFSSL_NO_MALLOC + XFREE(M, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return err; + } - /* now set M[1] to G * R mod m */ - if (fp_cmp_mag(P, G) != FP_GT) { - /* G > P so we reduce it first */ - fp_mod(G, P, &M[1]); - } else { - fp_copy(G, &M[1]); - } - fp_mulmod (&M[1], res, P, &M[1]); + /* now set M[1] to G * R mod m */ + if (fp_cmp_mag(P, G) != FP_GT) { + /* G > P so we reduce it first */ + fp_mod(G, P, &M[1]); + } else { + fp_copy(G, &M[1]); + } + fp_mulmod (&M[1], res, P, &M[1]); /* compute the value at M[1<<(winsize-1)] by * squaring M[1] (winsize-1) times */ @@ -2032,10 +2265,22 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, fp_init(res); fp_init(tmp); - fp_mul_2d(P, 1 << WINSIZE, tmp); + err = fp_mul_2d(P, 1 << WINSIZE, tmp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } /* now we need R mod m */ - fp_montgomery_calc_normalization(res, P); + err = fp_montgomery_calc_normalization(res, P); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } /* Get the top bits left over after taking WINSIZE bits starting at the * least-significant. @@ -2047,8 +2292,20 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, buf = X->dp[digidx--]; bitbuf = (int)(buf >> bitcnt); /* Multiply montgomery representation of 1 by 2 ^ top */ - fp_mul_2d(res, bitbuf, res); - fp_add(res, tmp, res); + err = fp_mul_2d(res, bitbuf, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_add(res, tmp, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } err = fp_mod(res, P, res); if (err != FP_OKAY) { #ifdef WOLFSSL_SMALL_STACK @@ -2108,9 +2365,21 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, } /* then multiply by 2^bitbuf */ - fp_mul_2d(res, bitbuf, res); + err = fp_mul_2d(res, bitbuf, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } /* Add in value to make mod operation take same time */ - fp_add(res, tmp, res); + err = fp_add(res, tmp, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } err = fp_mod(res, P, res); if (err != FP_OKAY) { #ifdef WOLFSSL_SMALL_STACK @@ -2170,6 +2439,11 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, fp_int res[1]; #endif + /* now setup montgomery */ + if ((err = fp_montgomery_setup(P, &mp)) != FP_OKAY) { + return err; + } + #ifdef WOLFSSL_SMALL_STACK res = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (res == NULL) { @@ -2177,16 +2451,17 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, } #endif - /* now setup montgomery */ - if ((err = fp_montgomery_setup(P, &mp)) != FP_OKAY) { - return err; - } - /* setup result */ fp_init(res); /* now we need R mod m */ - fp_montgomery_calc_normalization(res, P); + err = fp_montgomery_calc_normalization(res, P); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } /* Get the top bits left over after taking WINSIZE bits starting at the * least-significant. @@ -2198,7 +2473,13 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, buf = X->dp[digidx--]; bitbuf = (int)(buf >> bitcnt); /* Multiply montgomery representation of 1 by 2 ^ top */ - fp_mul_2d(res, bitbuf, res); + err = fp_mul_2d(res, bitbuf, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } err = fp_mod(res, P, res); if (err != FP_OKAY) { #ifdef WOLFSSL_SMALL_STACK @@ -2258,7 +2539,13 @@ static int _fp_exptmod_base_2(fp_int * X, int digits, fp_int * P, } /* then multiply by 2^bitbuf */ - fp_mul_2d(res, bitbuf, res); + err = fp_mul_2d(res, bitbuf, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(res, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } err = fp_mod(res, P, res); if (err != FP_OKAY) { #ifdef WOLFSSL_SMALL_STACK @@ -2354,8 +2641,8 @@ int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) #else err = _fp_exptmod_nct(&tmp[0], &tmp[1], P, Y); #endif - if (P->sign == FP_NEG) { - fp_add(Y, P, Y); + if ((err == 0) && (P->sign == FP_NEG)) { + err = fp_add(Y, P, Y); } } #ifdef WOLFSSL_SMALL_STACK @@ -2435,8 +2722,8 @@ int fp_exptmod_ex(fp_int * G, fp_int * X, int digits, fp_int * P, fp_int * Y) if (X != Y) { X->sign = FP_NEG; } - if (P->sign == FP_NEG) { - fp_add(Y, P, Y); + if ((err == 0) && (P->sign == FP_NEG)) { + err = fp_add(Y, P, Y); } } #ifdef WOLFSSL_SMALL_STACK @@ -2507,8 +2794,8 @@ int fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) if (X != Y) { X->sign = FP_NEG; } - if (P->sign == FP_NEG) { - fp_add(Y, P, Y); + if ((err == 0) && (P->sign == FP_NEG)) { + err = fp_add(Y, P, Y); } } #ifdef WOLFSSL_SMALL_STACK @@ -2868,7 +3155,7 @@ int fp_montgomery_setup(fp_int *a, fp_digit *rho) /* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ -void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) +int fp_montgomery_calc_normalization(fp_int *a, fp_int *b) { int x, bits; @@ -2886,11 +3173,15 @@ void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) /* now compute C = A * B mod b */ for (x = bits - 1; x < (int)DIGIT_BIT; x++) { - fp_mul_2 (a, a); + int err = fp_mul_2 (a, a); + if (err != FP_OKAY) { + return err; + } if (fp_cmp_mag (a, b) != FP_LT) { s_fp_sub (a, b, a); } } + return FP_OKAY; } @@ -3017,7 +3308,7 @@ int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) /* bail if too large */ if (m->used > (FP_SIZE/2)) { (void)mu; /* shut up compiler */ - return FP_OKAY; + return FP_VAL; } #ifdef TFM_SMALL_MONT_SET @@ -3098,7 +3389,7 @@ int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) return FP_OKAY; } -void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) +int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) { #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) const word32 maxC = (a->size * sizeof(fp_digit)); @@ -3151,7 +3442,10 @@ void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) #else /* read the bytes in */ for (; c > 0; c--) { - fp_mul_2d (a, 8, a); + int err = fp_mul_2d (a, 8, a); + if (err != FP_OKAY) { + return err; + } a->dp[0] |= *b++; if (a->used == 0) { @@ -3160,6 +3454,8 @@ void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) } #endif fp_clamp (a); + + return FP_OKAY; } int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) @@ -3274,21 +3570,23 @@ void fp_set(fp_int *a, fp_digit b) #ifndef MP_SET_CHUNK_BITS #define MP_SET_CHUNK_BITS 4 #endif -void fp_set_int(fp_int *a, unsigned long b) +int fp_set_int(fp_int *a, unsigned long b) { int x; /* use direct fp_set if b is less than fp_digit max */ if (b < FP_DIGIT_MAX) { fp_set (a, (fp_digit)b); - return; + return FP_OKAY; } fp_zero (a); /* set chunk bits at a time */ for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { - fp_mul_2d (a, MP_SET_CHUNK_BITS, a); + int err = fp_mul_2d (a, MP_SET_CHUNK_BITS, a); + if (err != FP_OKAY) + return err; /* OR in the top bits of the source */ a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & @@ -3303,6 +3601,8 @@ void fp_set_int(fp_int *a, unsigned long b) /* clamp digits */ fp_clamp(a); + + return FP_OKAY; } /* check if a bit is set */ @@ -3383,12 +3683,13 @@ int fp_leading_bit(fp_int *a) return bit; } -void fp_lshd(fp_int *a, int x) +int fp_lshd(fp_int *a, int x) { int y; - /* move up and truncate as required */ - y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); + if (a->used + x > FP_SIZE) return FP_VAL; + + y = a->used + x - 1; /* store new size */ a->used = y + 1; @@ -3405,6 +3706,7 @@ void fp_lshd(fp_int *a, int x) /* clamp digits */ fp_clamp(a); + return FP_OKAY; } @@ -3507,6 +3809,7 @@ int fp_sub_d(fp_int *a, fp_digit b, fp_int *c) #else fp_int *tmp; #endif + int err = FP_OKAY; #ifdef WOLFSSL_SMALL_STACK tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_BIGINT); @@ -3518,18 +3821,18 @@ int fp_sub_d(fp_int *a, fp_digit b, fp_int *c) fp_set(tmp, b); #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) if (c->size < FP_SIZE) { - fp_sub(a, tmp, tmp); + err = fp_sub(a, tmp, tmp); fp_copy(tmp, c); } else #endif { - fp_sub(a, tmp, c); + err = fp_sub(a, tmp, c); } #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_BIGINT); #endif - return FP_OKAY; + return err; } @@ -3649,15 +3952,13 @@ int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, /* high level addition (handles signs) */ int mp_add (mp_int * a, mp_int * b, mp_int * c) { - fp_add(a, b, c); - return MP_OKAY; + return fp_add(a, b, c); } /* high level subtraction (handles signs) */ int mp_sub (mp_int * a, mp_int * b, mp_int * c) { - fp_sub(a, b, c); - return MP_OKAY; + return fp_sub(a, b, c); } /* high level multiplication (handles sign) */ @@ -3672,8 +3973,7 @@ int mp_mul (mp_int * a, mp_int * b, mp_int * c) int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { - fp_mul_d(a, b, c); - return MP_OKAY; + return fp_mul_d(a, b, c); } /* d = a * b (mod c) */ @@ -3778,7 +4078,7 @@ int mp_unsigned_bin_size (mp_int * a) int mp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) { - return fp_to_unsigned_bin_at_pos(x, t, b); + return fp_to_unsigned_bin_at_pos(x, t, b); } /* store in unsigned [big endian] format */ @@ -3794,37 +4094,35 @@ int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c) /* 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, b, c); - return MP_OKAY; + return fp_read_unsigned_bin(a, b, c); } int mp_sub_d(fp_int *a, fp_digit b, fp_int *c) { - return fp_sub_d(a, b, c); + return fp_sub_d(a, b, c); } int mp_mul_2d(fp_int *a, int b, fp_int *c) { - fp_mul_2d(a, b, c); - return MP_OKAY; + return fp_mul_2d(a, b, c); } int mp_2expt(fp_int* a, int b) { - fp_2expt(a, b); - return MP_OKAY; + fp_2expt(a, b); + return MP_OKAY; } int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d) { - return fp_div(a, b, c, d); + return fp_div(a, b, c, d); } int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) { - fp_div_2d(a, b, c, d); - return MP_OKAY; + fp_div_2d(a, b, c, d); + return MP_OKAY; } void fp_copy(fp_int *a, fp_int *b) @@ -3905,8 +4203,7 @@ void mp_rshd (mp_int* a, int x) int mp_set_int(mp_int *a, unsigned long b) { - fp_set_int(a, b); - return MP_OKAY; + return fp_set_int(a, b); } int mp_is_bit_set (mp_int *a, mp_digit b) @@ -3968,8 +4265,7 @@ int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c) /* fast math conversion */ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b) { - fp_montgomery_calc_normalization(a, b); - return MP_OKAY; + return fp_montgomery_calc_normalization(a, b); } #endif /* WOLFSSL_KEYGEN || HAVE_ECC */ @@ -4483,7 +4779,14 @@ int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) return err; } - fp_read_unsigned_bin(b, base, baseSz); + err = fp_read_unsigned_bin(b, base, baseSz); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_BIGINT); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } if (fp_cmp_d(b, 2) != FP_GT || fp_cmp(b, c) != FP_LT) { continue; } @@ -4604,7 +4907,11 @@ int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); /* load value */ - fp_read_unsigned_bin(N, buf, len); + err = fp_read_unsigned_bin(N, buf, len); + if (err != 0) { + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } /* test */ /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance @@ -4728,16 +5035,19 @@ int fp_gcd(fp_int *a, fp_int *b, fp_int *c) defined(WC_RSA_BLINDING) || !defined(NO_DSA) || \ (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK)) /* c = a + b */ -void fp_add_d(fp_int *a, fp_digit b, fp_int *c) +int fp_add_d(fp_int *a, fp_digit b, fp_int *c) { #ifndef WOLFSSL_SMALL_STACK fp_int tmp; + int err; fp_init(&tmp); fp_set(&tmp, b); - fp_add(a, &tmp, c); + err = fp_add(a, &tmp, c); + return err; #else int i; fp_word t = b; + int err = FP_OKAY; fp_copy(a, c); for (i = 0; t != 0 && i < FP_SIZE && i < c->used; i++) { @@ -4749,14 +5059,17 @@ void fp_add_d(fp_int *a, fp_digit b, fp_int *c) c->dp[i] = t; c->used++; } + if (i == FP_SIZE && t != 0) { + err = FP_VAL; + } + return err; #endif } /* external compatibility */ int mp_add_d(fp_int *a, fp_digit b, fp_int *c) { - fp_add_d(a, b, c); - return MP_OKAY; + return fp_add_d(a, b, c); } #endif /* HAVE_ECC || !NO_PWDBASED || OPENSSL_EXTRA || WC_RSA_BLINDING || @@ -4864,8 +5177,12 @@ static int fp_read_radix(fp_int *a, const char *str, int radix) * to the number, otherwise exit the loop. */ if (y < radix) { - fp_mul_d (a, (fp_digit) radix, a); - fp_add_d (a, (fp_digit) y, a); + int ret = fp_mul_d (a, (fp_digit) radix, a); + if (ret != FP_OKAY) + return ret; + ret = fp_add_d (a, (fp_digit) y, a); + if (ret != FP_OKAY) + return ret; } else { break; } @@ -5121,15 +5438,14 @@ void mp_dump(const char* desc, mp_int* a, byte verbose) int mp_abs(mp_int* a, mp_int* b) { - fp_abs(a, b); - return FP_OKAY; + fp_abs(a, b); + return FP_OKAY; } int mp_lshd (mp_int * a, int b) { - fp_lshd(a, b); - return FP_OKAY; + return fp_lshd(a, b); } #endif /* USE_FAST_MATH */ diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index b11c7f5a3..2f1324675 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -432,7 +432,7 @@ MP_API void fp_free(fp_int* a); /* set to a small digit */ void fp_set(fp_int *a, fp_digit b); -void fp_set_int(fp_int *a, unsigned long b); +int fp_set_int(fp_int *a, unsigned long b); /* check if a bit is set */ int fp_is_bit_set(fp_int *a, fp_digit b); @@ -459,7 +459,7 @@ void fp_rshd(fp_int *a, int x); void fp_rshb(fp_int *a, int x); /* left shift x digits */ -void fp_lshd(fp_int *a, int x); +int fp_lshd(fp_int *a, int x); /* signed comparison */ int fp_cmp(fp_int *a, fp_int *b); @@ -470,19 +470,19 @@ int fp_cmp_mag(fp_int *a, fp_int *b); /* power of 2 operations */ void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); void fp_mod_2d(fp_int *a, int b, fp_int *c); -void fp_mul_2d(fp_int *a, int b, fp_int *c); +int fp_mul_2d(fp_int *a, int b, fp_int *c); void fp_2expt (fp_int *a, int b); -void fp_mul_2(fp_int *a, fp_int *c); +int fp_mul_2(fp_int *a, fp_int *c); void fp_div_2(fp_int *a, fp_int *c); /* Counts the number of lsbs which are zero before the first zero bit */ int fp_cnt_lsb(fp_int *a); /* c = a + b */ -void fp_add(fp_int *a, fp_int *b, fp_int *c); +int fp_add(fp_int *a, fp_int *b, fp_int *c); /* c = a - b */ -void fp_sub(fp_int *a, fp_int *b, fp_int *c); +int fp_sub(fp_int *a, fp_int *b, fp_int *c); /* c = a * b */ int fp_mul(fp_int *a, fp_int *b, fp_int *c); @@ -500,13 +500,13 @@ int fp_mod(fp_int *a, fp_int *b, fp_int *c); int fp_cmp_d(fp_int *a, fp_digit b); /* c = a + b */ -void fp_add_d(fp_int *a, fp_digit b, fp_int *c); +int fp_add_d(fp_int *a, fp_digit b, fp_int *c); /* c = a - b */ int fp_sub_d(fp_int *a, fp_digit b, fp_int *c); /* c = a * b */ -void fp_mul_d(fp_int *a, fp_digit b, fp_int *c); +int fp_mul_d(fp_int *a, fp_digit b, fp_int *c); /* a/b => cb + d == a */ /*int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d);*/ @@ -549,7 +549,7 @@ int fp_montgomery_setup(fp_int *a, fp_digit *mp); /* computes a = B**n mod b without division or multiplication useful for * normalizing numbers in a Montgomery system. */ -void fp_montgomery_calc_normalization(fp_int *a, fp_int *b); +int fp_montgomery_calc_normalization(fp_int *a, fp_int *b); /* computes x/R == x (mod N) via Montgomery Reduction */ int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); @@ -637,7 +637,7 @@ 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, const unsigned char *b, int c); +int fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c); int fp_to_unsigned_bin(fp_int *a, unsigned char *b); int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c); int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b); @@ -652,7 +652,7 @@ int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b); /* VARIOUS LOW LEVEL STUFFS */ -void s_fp_add(fp_int *a, fp_int *b, fp_int *c); +int s_fp_add(fp_int *a, fp_int *b, fp_int *c); void s_fp_sub(fp_int *a, fp_int *b, fp_int *c); void fp_reverse(unsigned char *s, int len);