diff --git a/tests/api/test_evp_pkey.c b/tests/api/test_evp_pkey.c index 6a1912ced9..adf381dcad 100644 --- a/tests/api/test_evp_pkey.c +++ b/tests/api/test_evp_pkey.c @@ -382,6 +382,76 @@ int test_wolfSSL_EVP_MD_hmac_signing(void) return EXPECT_RESULT(); } +/* Verify that EVP_DigestVerifyFinal rejects zero-length HMAC tags. */ +int test_wolfSSL_EVP_DigestVerify_HMAC_zero_len_forgery(void) +{ + EXPECT_DECLS; +#if defined(OPENSSL_EXTRA) && !defined(NO_HMAC) && !defined(NO_SHA256) + static const unsigned char key[] = { + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, + 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b + }; + static const char message[] = "wolfSSL DigestVerifyFinal forgery probe"; + static const unsigned char zeros[WC_MAX_DIGEST_SIZE] = { 0 }; + + WOLFSSL_EVP_PKEY* pkey = NULL; + WOLFSSL_EVP_MD_CTX mdCtx; + unsigned char tag[WC_MAX_DIGEST_SIZE]; + size_t tagLen = sizeof(tag); + + wolfSSL_EVP_MD_CTX_init(&mdCtx); + + ExpectNotNull(pkey = wolfSSL_EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, + key, (int)sizeof(key))); + + /* Compute the genuine HMAC-SHA256 tag for the message. */ + ExpectIntEQ(wolfSSL_EVP_DigestSignInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pkey), 1); + ExpectIntEQ(wolfSSL_EVP_DigestSignUpdate(&mdCtx, message, + (unsigned int)XSTRLEN(message)), + 1); + ExpectIntEQ(wolfSSL_EVP_DigestSignFinal(&mdCtx, tag, &tagLen), 1); + ExpectIntEQ((int)tagLen, WC_SHA256_DIGEST_SIZE); + ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + /* Full-length genuine tag verifies. */ + wolfSSL_EVP_MD_CTX_init(&mdCtx); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pkey), 1); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, message, + (unsigned int)XSTRLEN(message)), + 1); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, tag, tagLen), 1); + ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + /* Wrong full-length tag is rejected. */ + wolfSSL_EVP_MD_CTX_init(&mdCtx); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pkey), 1); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, message, + (unsigned int)XSTRLEN(message)), + 1); + ExpectIntNE(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, zeros, + WC_SHA256_DIGEST_SIZE), 1); + ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + /* Zero-length tag must be rejected. */ + wolfSSL_EVP_MD_CTX_init(&mdCtx); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyInit(&mdCtx, NULL, wolfSSL_EVP_sha256(), + NULL, pkey), 1); + ExpectIntEQ(wolfSSL_EVP_DigestVerifyUpdate(&mdCtx, message, + (unsigned int)XSTRLEN(message)), + 1); + ExpectIntNE(wolfSSL_EVP_DigestVerifyFinal(&mdCtx, zeros, 0), 1); + ExpectIntEQ(wolfSSL_EVP_MD_CTX_cleanup(&mdCtx), 1); + + wolfSSL_EVP_PKEY_free(pkey); +#endif + return EXPECT_RESULT(); +} + int test_wolfSSL_EVP_PKEY_new_mac_key(void) { EXPECT_DECLS; diff --git a/tests/api/test_evp_pkey.h b/tests/api/test_evp_pkey.h index e11d5b9c8c..7062e922a2 100644 --- a/tests/api/test_evp_pkey.h +++ b/tests/api/test_evp_pkey.h @@ -32,6 +32,7 @@ int test_wolfSSL_EVP_PKEY_base_id(void); int test_wolfSSL_EVP_PKEY_id(void); int test_wolfSSL_EVP_MD_pkey_type(void); int test_wolfSSL_EVP_MD_hmac_signing(void); +int test_wolfSSL_EVP_DigestVerify_HMAC_zero_len_forgery(void); int test_wolfSSL_EVP_PKEY_new_mac_key(void); int test_wolfSSL_EVP_PKEY_hkdf(void); int test_wolfSSL_EVP_PBE_scrypt(void); @@ -70,6 +71,8 @@ int test_wolfSSL_EVP_PKEY_print_public(void); TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_id), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_pkey_type), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_MD_hmac_signing), \ + TEST_DECL_GROUP("evp_pkey", \ + test_wolfSSL_EVP_DigestVerify_HMAC_zero_len_forgery), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_new_mac_key), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PKEY_hkdf), \ TEST_DECL_GROUP("evp_pkey", test_wolfSSL_EVP_PBE_scrypt), \ diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 997abc308d..a5ed4eda9d 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -4992,9 +4992,8 @@ int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); - if (siglen > hashLen || siglen > INT_MAX) + if (hashLen == 0 || siglen != hashLen) return WOLFSSL_FAILURE; - /* May be a truncated signature. */ } if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0)