Skip to content

Commit 967e13e

Browse files
committed
fix: EVP_DigestSignUpdate accept size_t not unsigned int
EVP_DigestSignUpdate was declared with unsigned int for the count parameter, unlike OpenSSL's size_t. EVP_DigestVerifyUpdate had the right declaration but cast the size_t to unsigned int before passing it to the internal helper, silently truncating counts > UINT_MAX. Fix all three sites: - wolfssl_evp_digest_pk_update internal helper: unsigned int -> size_t - wolfSSL_EVP_DigestSignUpdate: unsigned int -> size_t in decl + defn - wolfSSL_EVP_DigestVerifyUpdate: remove (unsigned int) cast - Add overflow guard before narrowing to word32 for wc_HmacUpdate Refs: ZD-21734
1 parent c098e53 commit 967e13e

4 files changed

Lines changed: 84 additions & 6 deletions

File tree

tests/api/test_evp_pkey.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2429,3 +2429,77 @@ int test_wolfSSL_EVP_PKEY_print_public(void)
24292429
return EXPECT_RESULT();
24302430
}
24312431

2432+
/*
2433+
* Regression test: EVP_DigestSignUpdate and EVP_DigestVerifyUpdate must both
2434+
* accept size_t for the byte count.
2435+
*
2436+
* Before the fix:
2437+
* - DigestSignUpdate declared unsigned int (not size_t), breaking FFI parity.
2438+
* - DigestVerifyUpdate declared size_t but immediately cast to unsigned int
2439+
* internally, silently truncating any count > UINT_MAX.
2440+
*
2441+
* Test vector: RFC 4231 §4.2 HMAC-SHA256 (independent oracle).
2442+
* Key : "Jefe"
2443+
* Data : "what do ya want for nothing?" (28 bytes)
2444+
* HMAC : 5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843
2445+
*/
2446+
int test_wolfSSL_EVP_DigestSign_size_t_cnt(void)
2447+
{
2448+
EXPECT_DECLS;
2449+
#if defined(OPENSSL_EXTRA) && !defined(NO_HMAC) && !defined(NO_SHA256)
2450+
static const byte kKey[] = "Jefe";
2451+
static const byte kMsg[] = "what do ya want for nothing?";
2452+
static const byte kExpected[] = {
2453+
0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e,
2454+
0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7,
2455+
0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83,
2456+
0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43
2457+
};
2458+
WOLFSSL_EVP_PKEY *key = NULL;
2459+
WOLFSSL_EVP_MD_CTX mdCtx;
2460+
unsigned char sig[WC_MAX_DIGEST_SIZE];
2461+
size_t sigSz = sizeof(sig);
2462+
/* Deliberately size_t — not unsigned int — to verify both APIs accept it
2463+
* without a cast. This was the type mismatch caught by ZD-21734. */
2464+
size_t msgSz = sizeof(kMsg) - 1;
2465+
2466+
ExpectNotNull(key = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL,
2467+
kKey,
2468+
(int)sizeof(kKey) - 1));
2469+
wolfSSL_EVP_MD_CTX_init(&mdCtx);
2470+
2471+
/* Sign: passes size_t count directly — regression for unsigned int decl */
2472+
ExpectIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, EVP_sha256(),
2473+
NULL, key), 1);
2474+
ExpectIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, kMsg, msgSz), 1);
2475+
ExpectIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, sig, &sigSz), 1);
2476+
ExpectIntEQ((int)sigSz, (int)sizeof(kExpected));
2477+
ExpectIntEQ(XMEMCMP(sig, kExpected, sizeof(kExpected)), 0);
2478+
ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1);
2479+
2480+
/* Verify: passes size_t count directly — regression for silent truncation */
2481+
wolfSSL_EVP_MD_CTX_init(&mdCtx);
2482+
ExpectIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, EVP_sha256(),
2483+
NULL, key), 1);
2484+
ExpectIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, kMsg, msgSz), 1);
2485+
ExpectIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, kExpected,
2486+
sizeof(kExpected)), 1);
2487+
ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1);
2488+
2489+
/* Overflow guard: cnt > UINT_MAX must fail, not silently truncate.
2490+
* Only reachable on 64-bit platforms where size_t exceeds word32. */
2491+
if (sizeof(size_t) > sizeof(word32)) {
2492+
size_t oversized = (size_t)(word32)-1 + 1; /* UINT_MAX + 1 */
2493+
wolfSSL_EVP_MD_CTX_init(&mdCtx);
2494+
ExpectIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, EVP_sha256(),
2495+
NULL, key), 1);
2496+
ExpectIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, kMsg, oversized),
2497+
WOLFSSL_FAILURE);
2498+
ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1);
2499+
}
2500+
2501+
wolfSSL_EVP_PKEY_free(key);
2502+
#endif
2503+
return EXPECT_RESULT();
2504+
} /* END test_wolfSSL_EVP_DigestSign_size_t_cnt */
2505+

tests/api/test_evp_pkey.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ int test_wolfSSL_EVP_MD_ecc_signing(void);
6161
int test_wolfSSL_EVP_PKEY_encrypt(void);
6262
int test_wolfSSL_EVP_PKEY_derive(void);
6363
int test_wolfSSL_EVP_PKEY_print_public(void);
64+
int test_wolfSSL_EVP_DigestSign_size_t_cnt(void);
6465

6566
#define TEST_EVP_PKEY_DECLS \
6667
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_CTX_new_id), \
@@ -100,6 +101,7 @@ int test_wolfSSL_EVP_PKEY_print_public(void);
100101
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_ecc_signing), \
101102
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_encrypt), \
102103
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_derive), \
103-
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_print_public)
104+
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_print_public), \
105+
TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_DigestSign_size_t_cnt)
104106

105107
#endif /* WOLFCRYPT_TEST_EVP_PKEY_H */

wolfcrypt/src/evp.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4697,10 +4697,12 @@ static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx,
46974697
* Update a digest for RSA and ECC keys, or HMAC for HMAC key.
46984698
*/
46994699
static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx,
4700-
const void *d, unsigned int cnt)
4700+
const void *d, size_t cnt)
47014701
{
47024702
if (ctx->isHMAC) {
4703-
if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0)
4703+
if (cnt > (word32)-1)
4704+
return WOLFSSL_FAILURE;
4705+
if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, (word32)cnt) != 0)
47044706
return WOLFSSL_FAILURE;
47054707

47064708
return WOLFSSL_SUCCESS;
@@ -4851,7 +4853,7 @@ int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx,
48514853

48524854

48534855
int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d,
4854-
unsigned int cnt)
4856+
size_t cnt)
48554857
{
48564858
WOLFSSL_ENTER("EVP_DigestSignUpdate");
48574859

@@ -4988,7 +4990,7 @@ int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d,
49884990
if (ctx == NULL || d == NULL)
49894991
return WOLFSSL_FAILURE;
49904992

4991-
return wolfssl_evp_digest_pk_update(ctx, d, (unsigned int)cnt);
4993+
return wolfssl_evp_digest_pk_update(ctx, d, cnt);
49924994
}
49934995

49944996

wolfssl/openssl/evp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -841,7 +841,7 @@ WOLFSSL_API int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx,
841841
WOLFSSL_API int wolfSSL_EVP_DigestFinalXOF(WOLFSSL_EVP_MD_CTX* ctx,
842842
unsigned char* md, size_t sz);
843843
WOLFSSL_API int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx,
844-
const void *d, unsigned int cnt);
844+
const void *d, size_t cnt);
845845
WOLFSSL_API int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx,
846846
unsigned char *sig, size_t *siglen);
847847
WOLFSSL_API int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx,

0 commit comments

Comments
 (0)