diff --git a/src/pk.c b/src/pk.c index bfc039e5d0..f4761a7418 100644 --- a/src/pk.c +++ b/src/pk.c @@ -6911,9 +6911,15 @@ static int pem_write_data(const char *name, const char *header, int headerLen; char* pem = NULL; word32 pemLen; - word32 derLen = (word32)len; + word32 derLen; byte* p; + /* Reject lengths that would wrap the PEM size calculation below. */ + if ((len < 0) || ((word32)len >= (WOLFSSL_MAX_32BIT / 4))) { + return BAD_FUNC_ARG; + } + derLen = (word32)len; + nameLen = (int)XSTRLEN(name); headerLen = (int)XSTRLEN(header); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5d961fc9aa..ec3f69cf09 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2461,8 +2461,8 @@ int GetLength_ex(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, *len = 0; /* Check there is at least one byte available containing length information. - */ - if ((idx + 1) > maxIdx) { + * Use >= to avoid a word32 wrap when idx is near UINT_MAX. */ + if (idx >= maxIdx) { WOLFSSL_MSG("GetLength - bad index on input"); return BUFFER_E; } @@ -2495,7 +2495,7 @@ int GetLength_ex(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, } /* Check the number of bytes required are available. */ - if ((idx + (word32)bytes) > maxIdx) { + if ((word32)bytes > (maxIdx - idx)) { WOLFSSL_MSG("GetLength - bad long length"); return BUFFER_E; } @@ -2520,7 +2520,7 @@ int GetLength_ex(const byte* input, word32* inOutIdx, int* len, word32 maxIdx, } /* When requested, check the buffer has at least length bytes left. */ - if (check && ((idx + length) > maxIdx)) { + if (check && (length > (maxIdx - idx))) { WOLFSSL_MSG("GetLength - value exceeds buffer length"); return BUFFER_E; } diff --git a/wolfcrypt/src/coding.c b/wolfcrypt/src/coding.c index c89dab769c..b184d77a5b 100644 --- a/wolfcrypt/src/coding.c +++ b/wolfcrypt/src/coding.c @@ -525,6 +525,10 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, if (in == NULL && inLen > 0) return BAD_FUNC_ARG; + /* Reject lengths that would wrap the encoded-size calculation below. */ + if (inLen >= (WOLFSSL_MAX_32BIT / 4)) + return BAD_FUNC_ARG; + outSz = (inLen + 3 - 1) / 3 * 4; addSz = (outSz + BASE64_LINE_SZ - 1) / BASE64_LINE_SZ; /* new lines */ diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 65789c41c7..bcd050c117 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -762,12 +762,22 @@ int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) int res; int digits_needed; + if (c < 0) { + return MP_VAL; + } + while (c > 0 && b[0] == 0) { c--; b++; } - digits_needed = ((c * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT; + /* reject sizes where the bit count would overflow, doing the math in + * word32 so c * CHAR_BIT can't overflow */ + if ((word32)c > (WOLFSSL_MAX_32BIT - (DIGIT_BIT - 1)) / CHAR_BIT) { + return MP_VAL; + } + + digits_needed = (int)(((word32)c * CHAR_BIT + DIGIT_BIT - 1) / DIGIT_BIT); /* make sure there are enough digits available */ if (a->alloc < digits_needed) { diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 66bcfef391..82a1a63e3a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -27262,11 +27262,9 @@ static wc_test_ret_t rsa_decode_test(RsaKey* keyPub) ret = WC_TEST_RET_ENC_EC(ret); goto done; } -#if defined(USE_INTEGER_HEAP_MATH) - #define RSA_RAW_BADLEN_EXPECT 0 -#else + /* All math backends now reject a negative/oversized length in + * mp_read_unsigned_bin, so a (word32)-1 length fails consistently. */ #define RSA_RAW_BADLEN_EXPECT WC_NO_ERR_TRACE(ASN_GETINT_E) -#endif ret = wc_RsaPublicKeyDecodeRaw(n, (word32)-1, e, sizeof(e), keyPub); if (ret != RSA_RAW_BADLEN_EXPECT) { ret = WC_TEST_RET_ENC_EC(ret);