diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index bc8c6c685..4c951d8ff 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -11433,8 +11433,8 @@ static int _sp_invmod_div(sp_int* a, sp_int* m, sp_int* x, sp_int* y, sp_int* b, sp_int* c, sp_int* inv) { int err = MP_OKAY; - sp_int* d; - sp_int* r; + sp_int* d = NULL; + sp_int* r = NULL; sp_int* s; #ifndef WOLFSSL_SP_INT_NEGATIVE int bneg = 0; @@ -11459,23 +11459,25 @@ static int _sp_invmod_div(sp_int* a, sp_int* m, sp_int* x, sp_int* y, sp_int* b, while ((err == MP_OKAY) && (!sp_isone(x)) && (!sp_iszero(x))) { /* 2.1. d = x / y, r = x mod y */ err = sp_div(x, y, d, r); - /* 2.2. c -= d * b */ - if (sp_isone(d)) { - /* c -= 1 * b */ - sp_sub(c, b, c); - } - else { - /* d *= b */ - err = sp_mul(d, b, d); - /* c -= d */ - if (err == MP_OKAY) { - sp_sub(c, d, c); + if (err == MP_OKAY) { + /* 2.2. c -= d * b */ + if (sp_isone(d)) { + /* c -= 1 * b */ + sp_sub(c, b, c); } + else { + /* d *= b */ + err = sp_mul(d, b, d); + /* c -= d */ + if (err == MP_OKAY) { + sp_sub(c, d, c); + } + } + /* 2.3. x = y, y = r */ + s = x; x = y; y = r; r = s; + /* 2.4. s = b, b = c, c = s */ + s = b; b = c; c = s; } - /* 2.3. x = y, y = r */ - s = x; x = y; y = r; r = s; - /* 2.4. s = b, b = c, c = s */ - s = b; b = c; c = s; } /* 3. If y != 0 then NO_INVERSE */ if ((err == MP_OKAY) && (!sp_iszero(y))) { @@ -11494,46 +11496,49 @@ static int _sp_invmod_div(sp_int* a, sp_int* m, sp_int* x, sp_int* y, sp_int* b, while ((err == MP_OKAY) && (!sp_isone(x)) && (!sp_iszero(x))) { /* 2.1. d = x / y, r = x mod y */ err = sp_div(x, y, d, r); - if (sp_isone(d)) { - /* c -= 1 * b */ - if ((bneg ^ cneg) == 1) { - /* c -= -b or -c -= b, therefore add. */ - _sp_add_off(c, b, c, 0); - } - else if (_sp_cmp_abs(c, b) == MP_LT) { - /* |c| < |b| and same sign, reverse subtract and negate. */ - _sp_sub_off(b, c, c, 0); - cneg = !cneg; - } - else { - /* |c| >= |b| */ - _sp_sub_off(c, b, c, 0); - } - } - else { - /* d *= b */ - err = sp_mul(d, b, d); - /* c -= d */ - if (err == MP_OKAY) { + if (err == MP_OKAY) { + if (sp_isone(d)) { + /* c -= 1 * b */ if ((bneg ^ cneg) == 1) { - /* c -= -d or -c -= d, therefore add. */ - _sp_add_off(c, d, c, 0); + /* c -= -b or -c -= b, therefore add. */ + _sp_add_off(c, b, c, 0); } - else if (_sp_cmp_abs(c, d) == MP_LT) { - /* |c| < |d| and same sign, reverse subtract and negate. */ - _sp_sub_off(d, c, c, 0); + else if (_sp_cmp_abs(c, b) == MP_LT) { + /* |c| < |b| and same sign, reverse subtract and negate. */ + _sp_sub_off(b, c, c, 0); cneg = !cneg; } else { - _sp_sub_off(c, d, c, 0); + /* |c| >= |b| */ + _sp_sub_off(c, b, c, 0); } } + else { + /* d *= b */ + err = sp_mul(d, b, d); + /* c -= d */ + if (err == MP_OKAY) { + if ((bneg ^ cneg) == 1) { + /* c -= -d or -c -= d, therefore add. */ + _sp_add_off(c, d, c, 0); + } + else if (_sp_cmp_abs(c, d) == MP_LT) { + /* |c| < |d| and same sign, reverse subtract and negate. + */ + _sp_sub_off(d, c, c, 0); + cneg = !cneg; + } + else { + _sp_sub_off(c, d, c, 0); + } + } + } + /* 2.3. x = y, y = r */ + s = x; x = y; y = r; r = s; + /* 2.4. s = b, b = c, c = s */ + s = b; b = c; c = s; + neg = bneg; bneg = cneg; cneg = neg; } - /* 2.3. x = y, y = r */ - s = x; x = y; y = r; r = s; - /* 2.4. s = b, b = c, c = s */ - s = b; b = c; c = s; - neg = bneg; bneg = cneg; cneg = neg; } /* 3. If y != 0 then NO_INVERSE */ if ((err == MP_OKAY) && (!sp_iszero(y))) { @@ -11654,21 +11659,22 @@ int sp_invmod(sp_int* a, sp_int* m, sp_int* r) sp_mod(m, a, v); /* v == 0 when a divides m evenly - no inverse. */ if (sp_iszero(v)) { - /* Force u to be the no inverse answer. */ - sp_set(u, 0); + err = MP_VAL; } evenMod = 1; } - /* Calculate inverse. */ - #if !defined(WOLFSSL_SP_SMALL) && (!defined(NO_RSA) || !defined(NO_DH)) - if (sp_count_bits(mm) >= 1024) { - err = _sp_invmod_div(ma, mm, u, v, b, c, c); - } - else - #endif - { - err = _sp_invmod(ma, mm, u, v, b, c); + if (err == MP_OKAY) { + /* Calculate inverse. */ + #if !defined(WOLFSSL_SP_SMALL) && (!defined(NO_RSA) || !defined(NO_DH)) + if (sp_count_bits(mm) >= 1024) { + err = _sp_invmod_div(ma, mm, u, v, b, c, c); + } + else + #endif + { + err = _sp_invmod(ma, mm, u, v, b, c); + } } /* Fixup for even modulus. */ @@ -11686,7 +11692,7 @@ int sp_invmod(sp_int* a, sp_int* m, sp_int* r) sp_sub(m, c, r); } } - else { + else if (err == MP_OKAY) { err = sp_copy(c, r); } } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index d888bc2f1..1bd518697 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -43216,6 +43216,16 @@ static int mp_test_invmod(mp_int* a, mp_int* m, mp_int* r) ret = mp_invmod(a, m, r); if (ret != MP_VAL) return -13172; + mp_set(a, 3); + mp_set(m, 6); + ret = mp_invmod(a, m, r); + if (ret != MP_VAL) + return -13181; + mp_set(a, 5*9); + mp_set(m, 6*9); + ret = mp_invmod(a, m, r); + if (ret != MP_VAL) + return -13182; mp_set(a, 1); mp_set(m, 4); ret = mp_invmod(a, m, r);