From ab4a0a66ea6823005c770aa67c74ee97e6722529 Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Mon, 5 Oct 2026 11:05:11 -0600 Subject: [PATCH 1/3] Handle even moduli in sp_exptmod_nct for RSA public-only builds --- .github/configs/os-check-linux.json | 4 ++ wolfcrypt/src/sp_int.c | 61 ++++++++++++++++++++++ wolfcrypt/test/test.c | 78 +++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/.github/configs/os-check-linux.json b/.github/configs/os-check-linux.json index 2dcbdfba8d2..8ba426eb331 100644 --- a/.github/configs/os-check-linux.json +++ b/.github/configs/os-check-linux.json @@ -542,6 +542,10 @@ "comment": "RSA verify-only with ECC cofactor ECDH (HAVE_ECC_CDH, set by --enable-ecccustcurves=all), whose wc_ecc_shared_secret_gen_sync() calls mp_mul_d. SAKKE stays off, so the HAVE_ECC_CDH term in settings.h is the only reason sp_mul_d is built. This gives link-time coverage of that term only: the mp_mul_d call runs only when cofactor != 1, and no curve at or above ECC_MIN_KEY_SZ has another cofactor.", "configure": ["--enable-cryptonly", "--enable-rsavfy", "--enable-ecccustcurves=all", "--disable-examples"]}, +{"name": "cryptonly-rsapub-no-dh-public-mp", "minutes": 1.0, + "comment": "RSA public only with DH off, so sp_exptmod_ex hands every modulus to sp_exptmod_nct and the constant-time generic exponentiation is not compiled. WOLFSSL_PUBLIC_MP lets wolfcrypt test run mp_test, whose even modulus checks cover the non-Montgomery path of sp_exptmod_nct in this shape.", + "configure": ["--enable-cryptonly", "--enable-rsapub", "--disable-dh", + "--disable-examples", "CPPFLAGS=-DWOLFSSL_PUBLIC_MP"]}, {"name": "pkcs12-pbkdf-mp-api", "minutes": 1.0, "comment": "WC_PKCS12_PBKDF_USING_MP_API selects a second wc_PKCS12_PBKDF_ex implementation that no configure option reaches.", "configure": ["--enable-pkcs12", "--enable-des3", "--enable-opensslextra", diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 24d65221cad..93a0e96c250 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -14830,6 +14830,62 @@ static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, } #endif /* WOLFSSL_SP_FAST_NCT_EXPTMOD || !WOLFSSL_SP_SMALL */ +#if defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m + * Left-to-right binary square-and-multiply, reducing by m at each step. + * Works for any modulus including even moduli, which Montgomery form does not + * support. Is NOT constant time. + * + * Assumes e is greater than zero. + * + * @param [in] b SP integer that is the base. + * @param [in] e SP integer that is the exponent. + * @param [in] m SP integer that is the modulus. + * @param [out] r SP integer to hold result. + * + * @return MP_OKAY on success. + * @return MP_MEM when dynamic memory allocation fails. + */ +static int _sp_exptmod_nct_generic(const sp_int* b, const sp_int* e, + const sp_int* m, sp_int* r) +{ + int i; + int err = MP_OKAY; + int bits = sp_count_bits(e); + DECL_SP_INT_ARRAY(t, m->used * 2 + 1, 2); + + /* Allocate memory for: + * - base reduced modulo m + * - temporary result (in case r is same var as another parameter). */ + ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, 2, err, NULL); + if (err == MP_OKAY) { + _sp_init_size(t[0], m->used * 2 + 1); + _sp_init_size(t[1], m->used * 2 + 1); + /* t[1] = b mod m */ + err = sp_mod(b, m, t[1]); + } + if (err == MP_OKAY) { + /* Result starts as base as top bit of exponent is set. */ + _sp_copy(t[1], t[0]); + } + /* For each bit in exponent starting at second highest. */ + for (i = bits - 2; (err == MP_OKAY) && (i >= 0); i--) { + err = sp_sqrmod(t[0], m, t[0]); + if ((err == MP_OKAY) && + (((e->dp[i >> SP_WORD_SHIFT] >> (i & SP_WORD_MASK)) & 1) != + 0)) { + err = sp_mulmod(t[0], t[1], m, t[0]); + } + } + if (err == MP_OKAY) { + _sp_copy(t[0], r); + } + + FREE_SP_INT_ARRAY(t, NULL); + return err; +} +#endif /* WOLFSSL_RSA_VERIFY_ONLY || WOLFSSL_RSA_PUBLIC_ONLY */ + /* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m * Non-constant time implementation. * @@ -14890,6 +14946,11 @@ int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) else if (mp_iseven(m)) { err = _sp_exptmod_ex(b, e, (int)(e->used * SP_WORD_SIZE), m, r); } +#else + /* Montgomery form requires an odd modulus. */ + else if (mp_iseven(m)) { + err = _sp_exptmod_nct_generic(b, e, m, r); + } #endif else { err = _sp_exptmod_nct(b, e, m, r); diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 9fabf2da026..c99313c1bd0 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -95280,6 +95280,84 @@ static wc_test_ret_t mp_test_exptmod(mp_int* b, mp_int* e, mp_int* m, mp_int* r, return WC_TEST_RET_ENC_NC; } + /* Even modulus, more varied inputs: + * k == 0: base >= m (m + 7) must give the same result as base 7. + * k == 1: exponent 2^130 + 1 spans several words for any word size. + * Reference: square the base 130 times, then multiply by it. + * k == 2: single word even modulus 10 with base 17 >= m, exponent 6. */ + for (k = 0; k < 3; k++) { + int i; + int sqrs = 0; + + if ((ret = mp_set(m, 1)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + if (k == 2) { + ret = mp_set(m, 10); + } + else { + ret = mp_mul_2d(m, 521, m); /* m = 2^521 */ + } + if (ret == MP_OKAY) { + ret = mp_set(b, 7); + } + if (ret == MP_OKAY) { + ret = mp_set(t, 1); + } + if (ret != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + + if (k == 1) { + /* t = b^(2^130 + 1) mod m */ + sqrs = 130; + if ((ret = mp_copy(b, t)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + for (i = 0; i < sqrs; i++) { + if ((ret = mp_sqrmod(t, m, t)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + } + if ((ret = mp_mulmod(t, b, m, t)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + if ((ret = mp_set(e, 1)) != MP_OKAY || + (ret = mp_mul_2d(e, sqrs, e)) != MP_OKAY || + (ret = mp_add_d(e, 1, e)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + } + else { + /* t = b^6 mod m, with the reduced base. */ + if ((ret = mp_set(e, 6)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + for (i = 0; i < 6; i++) { + if ((ret = mp_mulmod(t, b, m, t)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + } + /* Bring the base to m + b so it needs reducing. */ + if ((ret = mp_add(b, m, b)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + } + + if ((ret = mp_exptmod_ex(b, e, (int)e->used, m, r)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + if (mp_cmp(r, t) != MP_EQ) { + return WC_TEST_RET_ENC_NC; + } + if ((ret = mp_exptmod_nct(b, e, m, r)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + if (mp_cmp(r, t) != MP_EQ) { + return WC_TEST_RET_ENC_NC; + } + } + #if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0) #if defined(SP_INT_BITS) && (SP_INT_BITS >= 2048) From ee291fab4d201c320149a4f4df4f88882a082bc5 Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Fri, 6 Nov 2026 13:19:08 -0700 Subject: [PATCH 2/3] Reject even moduli in sp_exptmod_nct when the generic path is not built --- .github/configs/os-check-linux.json | 6 +- wolfcrypt/src/sp_int.c | 71 +++------------------ wolfcrypt/test/test.c | 95 +++++------------------------ 3 files changed, 31 insertions(+), 141 deletions(-) diff --git a/.github/configs/os-check-linux.json b/.github/configs/os-check-linux.json index 8ba426eb331..0c4843561a7 100644 --- a/.github/configs/os-check-linux.json +++ b/.github/configs/os-check-linux.json @@ -543,9 +543,13 @@ "configure": ["--enable-cryptonly", "--enable-rsavfy", "--enable-ecccustcurves=all", "--disable-examples"]}, {"name": "cryptonly-rsapub-no-dh-public-mp", "minutes": 1.0, - "comment": "RSA public only with DH off, so sp_exptmod_ex hands every modulus to sp_exptmod_nct and the constant-time generic exponentiation is not compiled. WOLFSSL_PUBLIC_MP lets wolfcrypt test run mp_test, whose even modulus checks cover the non-Montgomery path of sp_exptmod_nct in this shape.", + "comment": "RSA public only with DH off, so sp_exptmod_ex hands every modulus to sp_exptmod_nct and the constant-time generic exponentiation is not compiled. WOLFSSL_PUBLIC_MP lets wolfcrypt test run mp_test, whose even modulus checks confirm sp_exptmod_nct returns MP_VAL in this shape instead of a wrong Montgomery result.", "configure": ["--enable-cryptonly", "--enable-rsapub", "--disable-dh", "--disable-examples", "CPPFLAGS=-DWOLFSSL_PUBLIC_MP"]}, +{"name": "cryptonly-rsapub-public-mp", "minutes": 1.0, + "comment": "RSA public only with DH at its default (on), so the generic exponentiation is compiled and sp_exptmod_nct must use it for an even modulus rather than Montgomery. WOLFSSL_PUBLIC_MP lets wolfcrypt test run mp_test's even modulus checks in this shape.", + "configure": ["--enable-cryptonly", "--enable-rsapub", + "--disable-examples", "CPPFLAGS=-DWOLFSSL_PUBLIC_MP"]}, {"name": "pkcs12-pbkdf-mp-api", "minutes": 1.0, "comment": "WC_PKCS12_PBKDF_USING_MP_API selects a second wc_PKCS12_PBKDF_ex implementation that no configure option reaches.", "configure": ["--enable-pkcs12", "--enable-des3", "--enable-opensslextra", diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 93a0e96c250..dc440b31e57 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -14199,7 +14199,8 @@ static int _sp_exptmod_base_2(const sp_int* e, int digits, const sp_int* m, * * @return MP_OKAY on success. * @return MP_VAL when b, e, m or r is NULL, digits is negative, or m <= 0 or - * e is negative. + * e is negative; or m is even in an RSA verify/public only build + * without DH. * @return MP_MEM when dynamic memory allocation fails. */ int sp_exptmod_ex(const sp_int* b, const sp_int* e, int digits, const sp_int* m, @@ -14830,62 +14831,6 @@ static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, } #endif /* WOLFSSL_SP_FAST_NCT_EXPTMOD || !WOLFSSL_SP_SMALL */ -#if defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_RSA_PUBLIC_ONLY) -/* Internal. Exponentiates b to the power of e modulo m into r: r = b ^ e mod m - * Left-to-right binary square-and-multiply, reducing by m at each step. - * Works for any modulus including even moduli, which Montgomery form does not - * support. Is NOT constant time. - * - * Assumes e is greater than zero. - * - * @param [in] b SP integer that is the base. - * @param [in] e SP integer that is the exponent. - * @param [in] m SP integer that is the modulus. - * @param [out] r SP integer to hold result. - * - * @return MP_OKAY on success. - * @return MP_MEM when dynamic memory allocation fails. - */ -static int _sp_exptmod_nct_generic(const sp_int* b, const sp_int* e, - const sp_int* m, sp_int* r) -{ - int i; - int err = MP_OKAY; - int bits = sp_count_bits(e); - DECL_SP_INT_ARRAY(t, m->used * 2 + 1, 2); - - /* Allocate memory for: - * - base reduced modulo m - * - temporary result (in case r is same var as another parameter). */ - ALLOC_SP_INT_ARRAY(t, m->used * 2 + 1, 2, err, NULL); - if (err == MP_OKAY) { - _sp_init_size(t[0], m->used * 2 + 1); - _sp_init_size(t[1], m->used * 2 + 1); - /* t[1] = b mod m */ - err = sp_mod(b, m, t[1]); - } - if (err == MP_OKAY) { - /* Result starts as base as top bit of exponent is set. */ - _sp_copy(t[1], t[0]); - } - /* For each bit in exponent starting at second highest. */ - for (i = bits - 2; (err == MP_OKAY) && (i >= 0); i--) { - err = sp_sqrmod(t[0], m, t[0]); - if ((err == MP_OKAY) && - (((e->dp[i >> SP_WORD_SHIFT] >> (i & SP_WORD_MASK)) & 1) != - 0)) { - err = sp_mulmod(t[0], t[1], m, t[0]); - } - } - if (err == MP_OKAY) { - _sp_copy(t[0], r); - } - - FREE_SP_INT_ARRAY(t, NULL); - return err; -} -#endif /* WOLFSSL_RSA_VERIFY_ONLY || WOLFSSL_RSA_PUBLIC_ONLY */ - /* Exponentiates b to the power of e modulo m into r: r = b ^ e mod m * Non-constant time implementation. * @@ -14895,7 +14840,8 @@ static int _sp_exptmod_nct_generic(const sp_int* b, const sp_int* e, * @param [out] r SP integer to hold result. * * @return MP_OKAY on success. - * @return MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative. + * @return MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative; or + * m is even in an RSA verify/public only build without DH. * @return MP_MEM when dynamic memory allocation fails. */ int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) @@ -14942,14 +14888,17 @@ int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) else if (m->used * 2 >= r->size) { err = MP_VAL; } -#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH) || \ + defined(OPENSSL_ALL) else if (mp_iseven(m)) { err = _sp_exptmod_ex(b, e, (int)(e->used * SP_WORD_SIZE), m, r); } #else - /* Montgomery form requires an odd modulus. */ + /* Montgomery form requires an odd modulus and the generic implementation + * is not compiled in (RSA verify/public only without DH). */ else if (mp_iseven(m)) { - err = _sp_exptmod_nct_generic(b, e, m, r); + err = MP_VAL; } #endif else { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index c99313c1bd0..e0159bc762a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -95254,7 +95254,10 @@ static wc_test_ret_t mp_test_exptmod(mp_int* b, mp_int* e, mp_int* m, mp_int* r, /* Even, multi-word modulus uses the generic exponentiation path for * both mp_exptmod_ex and mp_exptmod_nct. Verify b^6 mod m against - * repeated modular multiplication. */ + * repeated modular multiplication. RSA public only builds without DH + * do not compile the generic path, and mp_exptmod_ex hands every modulus + * to mp_exptmod_nct, so both must reject the even modulus instead of + * returning a wrong Montgomery result. */ if ((ret = mp_set(m, 1)) != MP_OKAY || (ret = mp_mul_2d(m, 521, m)) != MP_OKAY || /* m = 2^521 (even) */ (ret = mp_set(b, 7)) != MP_OKAY || @@ -95267,6 +95270,17 @@ static wc_test_ret_t mp_test_exptmod(mp_int* b, mp_int* e, mp_int* m, mp_int* r, return WC_TEST_RET_ENC_EC(ret); } } +#if defined(WOLFSSL_RSA_PUBLIC_ONLY) && defined(NO_DH) && \ + !defined(OPENSSL_ALL) + ret = mp_exptmod_ex(b, e, (int)e->used, m, r); + if (ret != WC_NO_ERR_TRACE(MP_VAL)) { + return WC_TEST_RET_ENC_EC(ret); + } + ret = mp_exptmod_nct(b, e, m, r); + if (ret != WC_NO_ERR_TRACE(MP_VAL)) { + return WC_TEST_RET_ENC_EC(ret); + } +#else if ((ret = mp_exptmod_ex(b, e, (int)e->used, m, r)) != MP_OKAY) { return WC_TEST_RET_ENC_EC(ret); } @@ -95279,84 +95293,7 @@ static wc_test_ret_t mp_test_exptmod(mp_int* b, mp_int* e, mp_int* m, mp_int* r, if (mp_cmp(r, t) != MP_EQ) { return WC_TEST_RET_ENC_NC; } - - /* Even modulus, more varied inputs: - * k == 0: base >= m (m + 7) must give the same result as base 7. - * k == 1: exponent 2^130 + 1 spans several words for any word size. - * Reference: square the base 130 times, then multiply by it. - * k == 2: single word even modulus 10 with base 17 >= m, exponent 6. */ - for (k = 0; k < 3; k++) { - int i; - int sqrs = 0; - - if ((ret = mp_set(m, 1)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - if (k == 2) { - ret = mp_set(m, 10); - } - else { - ret = mp_mul_2d(m, 521, m); /* m = 2^521 */ - } - if (ret == MP_OKAY) { - ret = mp_set(b, 7); - } - if (ret == MP_OKAY) { - ret = mp_set(t, 1); - } - if (ret != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - - if (k == 1) { - /* t = b^(2^130 + 1) mod m */ - sqrs = 130; - if ((ret = mp_copy(b, t)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - for (i = 0; i < sqrs; i++) { - if ((ret = mp_sqrmod(t, m, t)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - } - if ((ret = mp_mulmod(t, b, m, t)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - if ((ret = mp_set(e, 1)) != MP_OKAY || - (ret = mp_mul_2d(e, sqrs, e)) != MP_OKAY || - (ret = mp_add_d(e, 1, e)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - } - else { - /* t = b^6 mod m, with the reduced base. */ - if ((ret = mp_set(e, 6)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - for (i = 0; i < 6; i++) { - if ((ret = mp_mulmod(t, b, m, t)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - } - /* Bring the base to m + b so it needs reducing. */ - if ((ret = mp_add(b, m, b)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - } - - if ((ret = mp_exptmod_ex(b, e, (int)e->used, m, r)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - if (mp_cmp(r, t) != MP_EQ) { - return WC_TEST_RET_ENC_NC; - } - if ((ret = mp_exptmod_nct(b, e, m, r)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - if (mp_cmp(r, t) != MP_EQ) { - return WC_TEST_RET_ENC_NC; - } - } +#endif #if !defined(HAVE_FIPS) || FIPS_VERSION3_GE(7,0,0) From dcdf6d26e0059ea479065d6c61e105e74a8f1db3 Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Fri, 6 Nov 2026 13:19:08 -0700 Subject: [PATCH 3/3] Align even modulus test guard and MP_VAL docs with sp_exptmod_nct --- wolfcrypt/src/sp_int.c | 20 +++++++++++--------- wolfcrypt/test/test.c | 20 +++++++++++--------- 2 files changed, 22 insertions(+), 18 deletions(-) diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index dc440b31e57..5623b72d9bf 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -14200,7 +14200,7 @@ static int _sp_exptmod_base_2(const sp_int* e, int digits, const sp_int* m, * @return MP_OKAY on success. * @return MP_VAL when b, e, m or r is NULL, digits is negative, or m <= 0 or * e is negative; or m is even in an RSA verify/public only build - * without DH. + * without DH or OPENSSL_ALL. * @return MP_MEM when dynamic memory allocation fails. */ int sp_exptmod_ex(const sp_int* b, const sp_int* e, int digits, const sp_int* m, @@ -14380,7 +14380,9 @@ int sp_exptmod_ex(const sp_int* b, const sp_int* e, int digits, const sp_int* m, * @param [out] r SP integer to hold result. * * @return MP_OKAY on success. - * @return MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative. + * @return MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative; or + * m is even in an RSA verify/public only build without DH or + * OPENSSL_ALL. * @return MP_MEM when dynamic memory allocation fails. */ int sp_exptmod(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) @@ -14841,7 +14843,8 @@ static int _sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, * * @return MP_OKAY on success. * @return MP_VAL when b, e, m or r is NULL; or m <= 0 or e is negative; or - * m is even in an RSA verify/public only build without DH. + * m is even in an RSA verify/public only build without DH or + * OPENSSL_ALL. * @return MP_MEM when dynamic memory allocation fails. */ int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) @@ -14888,19 +14891,18 @@ int sp_exptmod_nct(const sp_int* b, const sp_int* e, const sp_int* m, sp_int* r) else if (m->used * 2 >= r->size) { err = MP_VAL; } + else if (mp_iseven(m)) { #if (defined(WOLFSSL_SP_MATH_ALL) && !defined(WOLFSSL_RSA_VERIFY_ONLY) && \ !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || !defined(NO_DH) || \ defined(OPENSSL_ALL) - else if (mp_iseven(m)) { err = _sp_exptmod_ex(b, e, (int)(e->used * SP_WORD_SIZE), m, r); - } #else - /* Montgomery form requires an odd modulus and the generic implementation - * is not compiled in (RSA verify/public only without DH). */ - else if (mp_iseven(m)) { + /* Montgomery form requires an odd modulus and the generic + * implementation is not compiled in (RSA verify/public only without + * DH). */ err = MP_VAL; - } #endif + } else { err = _sp_exptmod_nct(b, e, m, r); } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index e0159bc762a..6278b71b14c 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -95261,17 +95261,11 @@ static wc_test_ret_t mp_test_exptmod(mp_int* b, mp_int* e, mp_int* m, mp_int* r, if ((ret = mp_set(m, 1)) != MP_OKAY || (ret = mp_mul_2d(m, 521, m)) != MP_OKAY || /* m = 2^521 (even) */ (ret = mp_set(b, 7)) != MP_OKAY || - (ret = mp_set(e, 6)) != MP_OKAY || - (ret = mp_set(t, 1)) != MP_OKAY) { + (ret = mp_set(e, 6)) != MP_OKAY) { return WC_TEST_RET_ENC_EC(ret); } - for (k = 0; k < 6; k++) { - if ((ret = mp_mulmod(t, b, m, t)) != MP_OKAY) { - return WC_TEST_RET_ENC_EC(ret); - } - } -#if defined(WOLFSSL_RSA_PUBLIC_ONLY) && defined(NO_DH) && \ - !defined(OPENSSL_ALL) +#if (defined(WOLFSSL_RSA_VERIFY_ONLY) || defined(WOLFSSL_RSA_PUBLIC_ONLY)) && \ + defined(NO_DH) && !defined(OPENSSL_ALL) ret = mp_exptmod_ex(b, e, (int)e->used, m, r); if (ret != WC_NO_ERR_TRACE(MP_VAL)) { return WC_TEST_RET_ENC_EC(ret); @@ -95281,6 +95275,14 @@ static wc_test_ret_t mp_test_exptmod(mp_int* b, mp_int* e, mp_int* m, mp_int* r, return WC_TEST_RET_ENC_EC(ret); } #else + if ((ret = mp_set(t, 1)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + for (k = 0; k < 6; k++) { + if ((ret = mp_mulmod(t, b, m, t)) != MP_OKAY) { + return WC_TEST_RET_ENC_EC(ret); + } + } if ((ret = mp_exptmod_ex(b, e, (int)e->used, m, r)) != MP_OKAY) { return WC_TEST_RET_ENC_EC(ret); }