Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions tests/api/test_rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,56 @@ int test_wc_RsaDecrypt_BoundsCheck(void)
return EXPECT_RESULT();
} /* END test_wc_RsaDecryptBoundsCheck */

/*
* Oversized RSA modulus (mp_bitsused(n) > RSA_MAX_SIZE) must not overflow the
* static stack buffer used by RsaFunctionCheckIn (DECL_MP_INT_SIZE_DYN).
*/
int test_wc_RsaFunctionCheckIn_OversizedModulus(void)
{
EXPECT_DECLS;
#if !defined(NO_RSA) && defined(WC_RSA_NO_PADDING) && defined(WC_RSA_DIRECT) && \
defined(WOLFSSL_PUBLIC_MP) && !defined(NO_RSA_BOUNDS_CHECK) && \
(defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
!defined(WOLFSSL_SMALL_STACK) && \
(defined(USE_CERT_BUFFERS_1024) || defined(USE_CERT_BUFFERS_2048))
WC_RNG rng;
RsaKey key;
const byte* derKey;
word32 derKeySz;
word32 idx = 0;
byte flatC[256];
word32 flatCSz;
byte out[256];
word32 outSz = sizeof(out);

#ifdef USE_CERT_BUFFERS_1024
derKey = server_key_der_1024;
derKeySz = (word32)sizeof_server_key_der_1024;
flatCSz = 128;
#else
derKey = server_key_der_2048;
derKeySz = (word32)sizeof_server_key_der_2048;
flatCSz = 256;
#endif

XMEMSET(&key, 0, sizeof(RsaKey));
XMEMSET(&rng, 0, sizeof(WC_RNG));

ExpectIntEQ(wc_InitRsaKey(&key, HEAP_HINT), 0);
ExpectIntEQ(wc_InitRng(&rng), 0);
ExpectIntEQ(wc_RsaPrivateKeyDecode(derKey, &idx, &key, derKeySz), 0);
/* Force modulus bit count above RSA_MAX_SIZE. */
ExpectIntEQ(mp_set_bit(&key.n, RSA_MAX_SIZE), 0);
XMEMSET(flatC, 0, flatCSz);
ExpectIntEQ(wc_RsaDirect(flatC, flatCSz, out, &outSz, &key,
RSA_PRIVATE_DECRYPT, &rng), WC_NO_ERR_TRACE(WC_KEY_SIZE_E));

DoExpectIntEQ(wc_FreeRsaKey(&key), 0);
DoExpectIntEQ(wc_FreeRng(&rng), 0);
#endif
return EXPECT_RESULT();
} /* END test_wc_RsaFunctionCheckIn_OversizedModulus */

/*
* Test wc_RsaKeyToDer with an mp_int large enough to wrap size calculations.
*/
Expand Down
2 changes: 2 additions & 0 deletions tests/api/test_rsa.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ int test_wc_RsaEncryptSize(void);
int test_wc_RsaSSL_SignVerify(void);
int test_wc_RsaFlattenPublicKey(void);
int test_wc_RsaDecrypt_BoundsCheck(void);
int test_wc_RsaFunctionCheckIn_OversizedModulus(void);
int test_wc_RsaKeyToDer_SizeOverflow(void);

#define TEST_RSA_DECLS \
Expand All @@ -65,6 +66,7 @@ int test_wc_RsaKeyToDer_SizeOverflow(void);
TEST_DECL_GROUP("rsa", test_wc_RsaSSL_SignVerify), \
TEST_DECL_GROUP("rsa", test_wc_RsaFlattenPublicKey), \
TEST_DECL_GROUP("rsa", test_wc_RsaDecrypt_BoundsCheck), \
TEST_DECL_GROUP("rsa", test_wc_RsaFunctionCheckIn_OversizedModulus), \
TEST_DECL_GROUP("rsa", test_wc_RsaKeyToDer_SizeOverflow)

#endif /* WOLFCRYPT_TEST_RSA_H */
57 changes: 57 additions & 0 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,14 @@ ECC Curve Sizes:
#define MAX_ECC_BITS_USE MAX_ECC_BITS_NEEDED
#endif

#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
#define ECC_DECL_MP_OVER_MAX(bits) \
(MP_BITS_CNT(bits) > MP_BITS_CNT(MAX_ECC_BITS_USE))
#else
#define ECC_DECL_MP_OVER_MAX(bits) \
((bits) > MAX_ECC_BITS_USE)
#endif

#if !defined(WOLFSSL_CUSTOM_CURVES) && (ECC_MIN_KEY_SZ > 160) && \
(!defined(HAVE_ECC_KOBLITZ) || (ECC_MIN_KEY_SZ > 224))

Expand Down Expand Up @@ -2012,6 +2020,10 @@ static int _ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R,
mp_int *x, *y, *z;
int err;

if (ECC_DECL_MP_OVER_MAX(mp_bitsused(modulus))) {
return WC_KEY_SIZE_E;
}

/* if Q == R then swap P and Q, so we don't require a local x,y,z */
if (Q == R) {
ecc_point* tPt = P;
Expand Down Expand Up @@ -2412,6 +2424,10 @@ static int _ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a,
mp_int *x, *y, *z;
int err;

if (ECC_DECL_MP_OVER_MAX(mp_bitsused(modulus))) {
return WC_KEY_SIZE_E;
}

#ifdef WOLFSSL_SMALL_STACK
#ifdef WOLFSSL_SMALL_STACK_CACHE
if (R->key != NULL) {
Expand Down Expand Up @@ -2762,6 +2778,10 @@ int ecc_map_ex(ecc_point* P, mp_int* modulus, mp_digit mp, int ct)
#endif
mp_int *x, *y, *z;

if (ECC_DECL_MP_OVER_MAX(mp_bitsused(modulus))) {
return WC_KEY_SIZE_E;
}

/* special case for point at infinity */
if (mp_cmp_d(P->z, 0) == MP_EQ) {
err = mp_set(P->x, 0);
Expand Down Expand Up @@ -3580,8 +3600,13 @@ static int ecc_point_to_mont(ecc_point* p, ecc_point* r, mp_int* modulus,
void* heap)
{
int err = MP_OKAY;

DECL_MP_INT_SIZE_DYN(mu, mp_bitsused(modulus), MAX_ECC_BITS_USE);

if (ECC_DECL_MP_OVER_MAX(mp_bitsused(modulus))) {
return WC_KEY_SIZE_E;
}

(void)heap;

NEW_MP_INT_SIZE(mu, mp_bitsused(modulus), heap, DYNAMIC_TYPE_ECC);
Expand Down Expand Up @@ -3886,6 +3911,11 @@ static int ecc_check_order_minus_1(const mp_int* k, ecc_point* tG, ecc_point* R,
int err;
DECL_MP_INT_SIZE_DYN(t, mp_bitsused(order), MAX_ECC_BITS_USE);

if (ECC_DECL_MP_OVER_MAX(mp_bitsused(order)) ||
ECC_DECL_MP_OVER_MAX(mp_bitsused(modulus))) {
return WC_KEY_SIZE_E;
}

NEW_MP_INT_SIZE(t, mp_bitsused(modulus), NULL, DYNAMIC_TYPE_ECC);
#ifdef MP_INT_SIZE_CHECK_NULL
if (t == NULL) {
Expand Down Expand Up @@ -6836,6 +6866,10 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
word32 keySz;
#endif

if (ECC_DECL_MP_OVER_MAX(ECC_KEY_MAX_BITS(key))) {
return WC_KEY_SIZE_E;
}

if (in == NULL || out == NULL || outlen == NULL || key == NULL) {
return ECC_BAD_ARG_E;
}
Expand Down Expand Up @@ -7034,8 +7068,13 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng,
{
int err = MP_OKAY;
int loop_check = 0;

DECL_MP_INT_SIZE_DYN(b, ECC_KEY_MAX_BITS_NONULLCHECK(key), MAX_ECC_BITS_USE);

if (ECC_DECL_MP_OVER_MAX(ECC_KEY_MAX_BITS_NONULLCHECK(key))) {
return WC_KEY_SIZE_E;
}

NEW_MP_INT_SIZE(b, ECC_KEY_MAX_BITS_NONULLCHECK(key), key->heap, DYNAMIC_TYPE_ECC);
#ifdef MP_INT_SIZE_CHECK_NULL
if (b == NULL)
Expand Down Expand Up @@ -7363,6 +7402,9 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
#else
DECLARE_CURVE_SPECS(1);
#endif
if (ECC_DECL_MP_OVER_MAX(ECC_KEY_MAX_BITS(key))) {
return WC_KEY_SIZE_E;
}
#endif /* !WOLFSSL_SP_MATH */

if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) {
Expand Down Expand Up @@ -8280,8 +8322,13 @@ static int ecc_mont_norm_points(ecc_point* A, ecc_point* Am, ecc_point* B,
ecc_point* Bm, mp_int* modulus, void* heap)
{
int err = MP_OKAY;

DECL_MP_INT_SIZE_DYN(mu, mp_bitsused(modulus), MAX_ECC_BITS_USE);

if (ECC_DECL_MP_OVER_MAX(mp_bitsused(modulus))) {
return WC_KEY_SIZE_E;
}

(void)heap;

NEW_MP_INT_SIZE(mu, mp_bitsused(modulus), heap, DYNAMIC_TYPE_ECC);
Expand Down Expand Up @@ -8668,6 +8715,10 @@ int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
word32 keySz;
#endif

if (ECC_DECL_MP_OVER_MAX(ECC_KEY_MAX_BITS(key))) {
return WC_KEY_SIZE_E;
}

if (sig == NULL || hash == NULL || res == NULL || key == NULL) {
return ECC_BAD_ARG_E;
}
Expand Down Expand Up @@ -9038,6 +9089,7 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
ecc_point lcl_mG;
ecc_point lcl_mQ;
#endif

DECL_MP_INT_SIZE_DYN(w, ECC_KEY_MAX_BITS_NONULLCHECK(key), MAX_ECC_BITS_USE);
#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)
DECL_MP_INT_SIZE_DYN(e_lcl, ECC_KEY_MAX_BITS_NONULLCHECK(key), MAX_ECC_BITS_USE);
Expand All @@ -9050,6 +9102,11 @@ static int ecc_verify_hash(mp_int *r, mp_int *s, const byte* hash,
#endif
mp_int* u1 = NULL; /* Will be e. */
mp_int* u2 = NULL; /* Will be w. */

if (ECC_DECL_MP_OVER_MAX(ECC_KEY_MAX_BITS_NONULLCHECK(key))) {
return WC_KEY_SIZE_E;
}

#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V)
err = wc_ecc_alloc_mpint(key, &key->e);
if (err != 0) {
Expand Down
2 changes: 1 addition & 1 deletion wolfcrypt/src/random.c
Original file line number Diff line number Diff line change
Expand Up @@ -1715,7 +1715,7 @@ static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz,
void* heap, int devId)
{
int ret = 0;
#ifdef HAVE_HASHDRBG
#if defined(HAVE_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK)
#if !defined(HAVE_FIPS) && defined(WOLFSSL_RNG_USE_FULL_SEED)
word32 seedSz = SEED_SZ;
#else
Expand Down
27 changes: 26 additions & 1 deletion wolfcrypt/src/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ RSA keys can be used to encrypt, decrypt, sign and verify data.
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/logging.h>

#if defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)
#define RSA_DECL_MP_OVER_MAX(bits) \
(MP_BITS_CNT(bits) > MP_BITS_CNT(RSA_MAX_SIZE))
#else
#define RSA_DECL_MP_OVER_MAX(bits) \
((bits) > RSA_MAX_SIZE)
#endif

#ifdef WOLFSSL_AFALG_XILINX_RSA
#include <wolfssl/wolfcrypt/port/af_alg/wc_afalg.h>
#endif
Expand Down Expand Up @@ -839,6 +847,10 @@ int wc_CheckRsaKey(RsaKey* key)
}
#endif

if (RSA_DECL_MP_OVER_MAX(mp_bitsused(&key->n))) {
return WC_KEY_SIZE_E;
}

NEW_MP_INT_SIZE(tmp, mp_bitsused(&key->n), NULL, DYNAMIC_TYPE_RSA);
#ifdef MP_INT_SIZE_CHECK_NULL
if (tmp == NULL) {
Expand Down Expand Up @@ -2875,6 +2887,10 @@ static int RsaFunctionPrivate(mp_int* tmp, RsaKey* key, WC_RNG* rng)
DECL_MP_INT_SIZE_DYN(rndi, mp_bitsused(&key->n), RSA_MAX_SIZE);
#endif /* WC_RSA_BLINDING && !WC_NO_RNG */

if (RSA_DECL_MP_OVER_MAX(mp_bitsused(&key->n))) {
return WC_KEY_SIZE_E;
}

(void)rng;

#if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG)
Expand Down Expand Up @@ -3054,6 +3070,10 @@ static int RsaFunctionSync(const byte* in, word32 inLen, byte* out,
DECL_MP_INT_SIZE_DYN(tmp, mp_bitsused(&key->n), RSA_MAX_SIZE);
int ret = 0;

if (RSA_DECL_MP_OVER_MAX(mp_bitsused(&key->n))) {
return WC_KEY_SIZE_E;
}

(void)rng;

NEW_MP_INT_SIZE(tmp, mp_bitsused(&key->n), key->heap, DYNAMIC_TYPE_RSA);
Expand Down Expand Up @@ -3316,7 +3336,7 @@ int wc_RsaDirect(const byte* in, word32 inLen, byte* out, word32* outSz,
}

if ((ret = wc_RsaEncryptSize(key)) < 0) {
return BAD_FUNC_ARG;
return ret;
}

if (inLen != (word32)ret) {
Expand Down Expand Up @@ -3481,8 +3501,13 @@ int RsaFunctionCheckIn(const byte* in, word32 inLen, RsaKey* key,
int checkSmallCt)
{
int ret = 0;

DECL_MP_INT_SIZE_DYN(c, mp_bitsused(&key->n), RSA_MAX_SIZE);

if (RSA_DECL_MP_OVER_MAX(mp_bitsused(&key->n))) {
return WC_KEY_SIZE_E;
}

NEW_MP_INT_SIZE(c, mp_bitsused(&key->n), key->heap, DYNAMIC_TYPE_RSA);
#ifdef MP_INT_SIZE_CHECK_NULL
if (c == NULL)
Expand Down
8 changes: 6 additions & 2 deletions wolfssl/wolfcrypt/sp_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -895,9 +895,13 @@ while (0)
#define DECL_MP_INT_SIZE(name, bits) \
sp_int_digit name##d[MP_INT_SIZEOF_DIGITS(MP_BITS_CNT(bits))]; \
sp_int* (name) = (sp_int*)name##d
/* Zero out mp_int of minimal size. */
/* Bytes to zero for a static mp_int: min(requested bits size, declared buffer). */
#define MP_INT_ZERO_SIZE(name, bits) \
((sizeof(name##d) < MP_INT_SIZEOF(MP_BITS_CNT(bits))) ? \
sizeof(name##d) : MP_INT_SIZEOF(MP_BITS_CNT(bits)))
/* Zero out mp_int without clearing more than the declared digit buffer. */
#define NEW_MP_INT_SIZE(name, bits, heap, type) \
XMEMSET(name, 0, MP_INT_SIZEOF(MP_BITS_CNT(bits)))
XMEMSET((name), 0, MP_INT_ZERO_SIZE(name, bits))
/* Dispose of static mp_int. */
#define FREE_MP_INT_SIZE(name, heap, type) WC_DO_NOTHING
/* Type to force compiler to not complain about size. */
Expand Down
Loading