|
30 | 30 |
|
31 | 31 | #include <wolfssl/wolfcrypt/hmac.h> |
32 | 32 | #include <wolfssl/wolfcrypt/types.h> |
| 33 | +#include <wolfssl/internal.h> |
33 | 34 | #include <tests/api/api.h> |
34 | 35 | #include <tests/api/test_hmac.h> |
35 | 36 |
|
@@ -681,3 +682,75 @@ int test_wc_Sha384HmacFinal(void) |
681 | 682 | return EXPECT_RESULT(); |
682 | 683 | } /* END test_wc_Sha384HmacFinal */ |
683 | 684 |
|
| 685 | +/* Test for integer overflow in TLS_hmac size calculation (ZD #21240). |
| 686 | + * |
| 687 | + * TLS_hmac() computes sz + hashSz + padSz + 1 and passes the result to |
| 688 | + * Hmac_UpdateFinal / Hmac_UpdateFinal_CT. When sz (word32) is near |
| 689 | + * UINT32_MAX, the addition overflows and wraps to a small value, causing |
| 690 | + * the HMAC routines to operate on an undersized length. The fix adds |
| 691 | + * WC_SAFE_SUM_WORD32 overflow checks and returns BUFFER_E on overflow. |
| 692 | + * |
| 693 | + * This test calls through ssl->hmac (which points to TLS_hmac) with |
| 694 | + * values that trigger the overflow condition and verifies the function |
| 695 | + * correctly rejects them. |
| 696 | + */ |
| 697 | +int test_tls_hmac_size_overflow(void) |
| 698 | +{ |
| 699 | + EXPECT_DECLS; |
| 700 | +#if !defined(NO_HMAC) && !defined(WOLFSSL_AEAD_ONLY) && !defined(NO_TLS) && \ |
| 701 | + defined(NO_OLD_TLS) && !defined(NO_WOLFSSL_CLIENT) |
| 702 | + WOLFSSL_CTX* ctx = NULL; |
| 703 | + WOLFSSL* ssl = NULL; |
| 704 | + byte digest[WC_MAX_DIGEST_SIZE]; |
| 705 | + byte dummy_in[64]; |
| 706 | + |
| 707 | + XMEMSET(dummy_in, 0xAA, sizeof(dummy_in)); |
| 708 | + XMEMSET(digest, 0, sizeof(digest)); |
| 709 | + |
| 710 | + ctx = wolfSSL_CTX_new(wolfSSLv23_client_method()); |
| 711 | + ExpectNotNull(ctx); |
| 712 | + ssl = wolfSSL_new(ctx); |
| 713 | + ExpectNotNull(ssl); |
| 714 | + |
| 715 | + if (EXPECT_SUCCESS()) { |
| 716 | + ExpectNotNull(ssl->hmac); |
| 717 | + |
| 718 | + /* Set a hash size so the verify path in TLS_hmac is exercised. */ |
| 719 | + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; |
| 720 | + |
| 721 | + /* Overflow case 1: sz near UINT32_MAX, padSz pushes sum past limit. |
| 722 | + * (UINT32_MAX - 300) + 32 + 500 + 1 = UINT32_MAX + 233 -> wraps to 232 |
| 723 | + */ |
| 724 | + ExpectIntEQ(ssl->hmac(ssl, digest, dummy_in, |
| 725 | + (word32)(WOLFSSL_MAX_32BIT - 300), |
| 726 | + 500, /* padSz */ |
| 727 | + application_data, 1, PEER_ORDER), |
| 728 | + WC_NO_ERR_TRACE(BUFFER_E)); |
| 729 | + |
| 730 | + /* Overflow case 2: padSz = 0, hashSz alone causes overflow. |
| 731 | + * (UINT32_MAX - 10) + 32 + 0 + 1 = UINT32_MAX + 23 -> wraps to 22 |
| 732 | + */ |
| 733 | + ExpectIntEQ(ssl->hmac(ssl, digest, dummy_in, |
| 734 | + (word32)(WOLFSSL_MAX_32BIT - 10), |
| 735 | + 0, /* padSz */ |
| 736 | + application_data, 1, PEER_ORDER), |
| 737 | + WC_NO_ERR_TRACE(BUFFER_E)); |
| 738 | + |
| 739 | + /* Normal case: should NOT return BUFFER_E. |
| 740 | + * May fail for other reasons (no keys configured) but the overflow |
| 741 | + * check must not fire for small legitimate values. |
| 742 | + */ |
| 743 | + ExpectIntNE(ssl->hmac(ssl, digest, dummy_in, |
| 744 | + 100, |
| 745 | + 10, /* padSz */ |
| 746 | + application_data, 1, PEER_ORDER), |
| 747 | + WC_NO_ERR_TRACE(BUFFER_E)); |
| 748 | + } |
| 749 | + |
| 750 | + wolfSSL_free(ssl); |
| 751 | + wolfSSL_CTX_free(ctx); |
| 752 | +#endif /* !NO_HMAC && !WOLFSSL_AEAD_ONLY && !NO_TLS && NO_OLD_TLS && |
| 753 | + * !NO_WOLFSSL_CLIENT */ |
| 754 | + return EXPECT_RESULT(); |
| 755 | +} /* END test_tls_hmac_size_overflow */ |
| 756 | + |
0 commit comments