mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-05 10:50:53 +02:00
Fix issue in TLS_hmac size calculation
This commit is contained in:
@@ -1283,6 +1283,7 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
|
||||
int ret = 0;
|
||||
const byte* macSecret = NULL;
|
||||
word32 hashSz = 0;
|
||||
word32 totalSz = 0;
|
||||
|
||||
if (ssl == NULL)
|
||||
return BAD_FUNC_ARG;
|
||||
@@ -1294,11 +1295,23 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
|
||||
hashSz = ssl->specs.hash_size;
|
||||
#endif
|
||||
|
||||
/* Pre-compute sz + hashSz + padSz + 1 with overflow checking.
|
||||
* Used by fuzzer callback and Hmac_UpdateFinal* in the verify path. */
|
||||
if (verify && padSz >= 0) {
|
||||
word32 hmacSz;
|
||||
if (!WC_SAFE_SUM_WORD32(sz, hashSz, hmacSz) ||
|
||||
!WC_SAFE_SUM_WORD32(hmacSz, (word32)padSz, hmacSz) ||
|
||||
!WC_SAFE_SUM_WORD32(hmacSz, 1, hmacSz)) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
totalSz = hmacSz;
|
||||
}
|
||||
|
||||
#ifdef HAVE_FUZZER
|
||||
/* Fuzz "in" buffer with sz to be used in HMAC algorithm */
|
||||
if (ssl->fuzzerCb) {
|
||||
if (verify && padSz >= 0) {
|
||||
ssl->fuzzerCb(ssl, in, sz + hashSz + padSz + 1, FUZZ_HMAC,
|
||||
ssl->fuzzerCb(ssl, in, totalSz, FUZZ_HMAC,
|
||||
ssl->fuzzerCtx);
|
||||
}
|
||||
else {
|
||||
@@ -1335,19 +1348,18 @@ int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz,
|
||||
#ifdef HAVE_BLAKE2
|
||||
if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) {
|
||||
ret = Hmac_UpdateFinal(&hmac, digest, in,
|
||||
sz + hashSz + (word32)padSz + 1, myInner, innerSz);
|
||||
totalSz, myInner, innerSz);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = Hmac_UpdateFinal_CT(&hmac, digest, in,
|
||||
(sz + hashSz + (word32)padSz + 1),
|
||||
totalSz,
|
||||
(int)hashSz, myInner, innerSz);
|
||||
|
||||
}
|
||||
#else
|
||||
ret = Hmac_UpdateFinal(&hmac, digest, in, sz + hashSz +
|
||||
(word32)(padSz) + 1,
|
||||
ret = Hmac_UpdateFinal(&hmac, digest, in, totalSz,
|
||||
myInner, innerSz);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
#include <wolfssl/wolfcrypt/hmac.h>
|
||||
#include <wolfssl/wolfcrypt/types.h>
|
||||
#include <wolfssl/internal.h>
|
||||
#include <tests/api/api.h>
|
||||
#include <tests/api/test_hmac.h>
|
||||
|
||||
@@ -681,3 +682,75 @@ int test_wc_Sha384HmacFinal(void)
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_wc_Sha384HmacFinal */
|
||||
|
||||
/* Test for integer overflow in TLS_hmac size calculation (ZD #21240).
|
||||
*
|
||||
* TLS_hmac() computes sz + hashSz + padSz + 1 and passes the result to
|
||||
* Hmac_UpdateFinal / Hmac_UpdateFinal_CT. When sz (word32) is near
|
||||
* UINT32_MAX, the addition overflows and wraps to a small value, causing
|
||||
* the HMAC routines to operate on an undersized length. The fix adds
|
||||
* WC_SAFE_SUM_WORD32 overflow checks and returns BUFFER_E on overflow.
|
||||
*
|
||||
* This test calls through ssl->hmac (which points to TLS_hmac) with
|
||||
* values that trigger the overflow condition and verifies the function
|
||||
* correctly rejects them.
|
||||
*/
|
||||
int test_tls_hmac_size_overflow(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if !defined(NO_HMAC) && !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_TLS) && \
|
||||
defined(NO_OLD_TLS) && !defined(NO_WOLFSSL_CLIENT)
|
||||
WOLFSSL_CTX* ctx = NULL;
|
||||
WOLFSSL* ssl = NULL;
|
||||
byte digest[WC_MAX_DIGEST_SIZE];
|
||||
byte dummy_in[64];
|
||||
|
||||
XMEMSET(dummy_in, 0xAA, sizeof(dummy_in));
|
||||
XMEMSET(digest, 0, sizeof(digest));
|
||||
|
||||
ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());
|
||||
ExpectNotNull(ctx);
|
||||
ssl = wolfSSL_new(ctx);
|
||||
ExpectNotNull(ssl);
|
||||
|
||||
if (EXPECT_SUCCESS()) {
|
||||
ExpectNotNull(ssl->hmac);
|
||||
|
||||
/* Set a hash size so the verify path in TLS_hmac is exercised. */
|
||||
ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE;
|
||||
|
||||
/* Overflow case 1: sz near UINT32_MAX, padSz pushes sum past limit.
|
||||
* (UINT32_MAX - 300) + 32 + 500 + 1 = UINT32_MAX + 233 -> wraps to 232
|
||||
*/
|
||||
ExpectIntEQ(ssl->hmac(ssl, digest, dummy_in,
|
||||
(word32)(WOLFSSL_MAX_32BIT - 300),
|
||||
500, /* padSz */
|
||||
application_data, 1, PEER_ORDER),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
|
||||
/* Overflow case 2: padSz = 0, hashSz alone causes overflow.
|
||||
* (UINT32_MAX - 10) + 32 + 0 + 1 = UINT32_MAX + 23 -> wraps to 22
|
||||
*/
|
||||
ExpectIntEQ(ssl->hmac(ssl, digest, dummy_in,
|
||||
(word32)(WOLFSSL_MAX_32BIT - 10),
|
||||
0, /* padSz */
|
||||
application_data, 1, PEER_ORDER),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
|
||||
/* Normal case: should NOT return BUFFER_E.
|
||||
* May fail for other reasons (no keys configured) but the overflow
|
||||
* check must not fire for small legitimate values.
|
||||
*/
|
||||
ExpectIntNE(ssl->hmac(ssl, digest, dummy_in,
|
||||
100,
|
||||
10, /* padSz */
|
||||
application_data, 1, PEER_ORDER),
|
||||
WC_NO_ERR_TRACE(BUFFER_E));
|
||||
}
|
||||
|
||||
wolfSSL_free(ssl);
|
||||
wolfSSL_CTX_free(ctx);
|
||||
#endif /* !NO_HMAC && !WOLFSSL_AEAD_ONLY && !NO_TLS && NO_OLD_TLS &&
|
||||
* !NO_WOLFSSL_CLIENT */
|
||||
return EXPECT_RESULT();
|
||||
} /* END test_tls_hmac_size_overflow */
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ int test_wc_Sha256HmacFinal(void);
|
||||
int test_wc_Sha384HmacSetKey(void);
|
||||
int test_wc_Sha384HmacUpdate(void);
|
||||
int test_wc_Sha384HmacFinal(void);
|
||||
int test_tls_hmac_size_overflow(void);
|
||||
|
||||
#define TEST_HMAC_DECLS \
|
||||
TEST_DECL_GROUP("hmac", test_wc_Md5HmacSetKey), \
|
||||
@@ -55,6 +56,7 @@ int test_wc_Sha384HmacFinal(void);
|
||||
TEST_DECL_GROUP("hmac", test_wc_Sha256HmacFinal), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_Sha384HmacSetKey), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_Sha384HmacUpdate), \
|
||||
TEST_DECL_GROUP("hmac", test_wc_Sha384HmacFinal)
|
||||
TEST_DECL_GROUP("hmac", test_wc_Sha384HmacFinal), \
|
||||
TEST_DECL_GROUP("hmac", test_tls_hmac_size_overflow)
|
||||
|
||||
#endif /* WOLFCRYPT_TEST_HMAC_H */
|
||||
|
||||
Reference in New Issue
Block a user