From 84e78ea1d131ef2ea43089dc760f4b3bd04459cf Mon Sep 17 00:00:00 2001 From: Yosuke Shimizu Date: Wed, 8 Jul 2026 11:12:18 +0900 Subject: [PATCH] tls1_prf: reject unsupported digests instead of coercing to SHA-384 --- src/wp_tls1_prf.c | 7 ++++ test/test_tls1_prf.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/src/wp_tls1_prf.c b/src/wp_tls1_prf.c index 6d99db77..103345b1 100644 --- a/src/wp_tls1_prf.c +++ b/src/wp_tls1_prf.c @@ -157,6 +157,13 @@ static int wp_kdf_tls1_prf_derive(wp_Tls1Prf_Ctx* ctx, unsigned char* key, if (ok && (ctx->mdType == WC_HASH_TYPE_NONE)) { ok = 0; } + /* Only MD5-SHA1 (TLS 1.0/1.1), SHA-256 and SHA-384 (TLS 1.2) + * are supported. */ + if (ok && (ctx->mdType != WC_HASH_TYPE_MD5_SHA) && + (ctx->mdType != WC_HASH_TYPE_SHA256) && + (ctx->mdType != WC_HASH_TYPE_SHA384)) { + ok = 0; + } if (ok && (ctx->secret == NULL)) { ok = 0; } diff --git a/test/test_tls1_prf.c b/test/test_tls1_prf.c index 3bdc2896..eab715c1 100644 --- a/test/test_tls1_prf.c +++ b/test/test_tls1_prf.c @@ -287,6 +287,92 @@ static int test_tls1_prf_str_md(const char *md) } #endif +#if defined(WP_HAVE_SHA1) || defined(WP_HAVE_SHA224) || defined(WP_HAVE_SHA512) +/* A digest outside MD5-SHA1, SHA-256 and SHA-384 must be rejected, not + * silently computed with SHA-384. Only wolfProvider is exercised; the OpenSSL + * default provider accepts these digests for the TLS 1.2 PRF. */ +static int test_tls1_prf_unsupported_md_calc(const EVP_MD *md, const char *name) +{ + int err = 0; + int rejected = 0; + EVP_PKEY_CTX *ctx = NULL; + unsigned char key[128]; + unsigned char secret[32] = { 0, }; + unsigned char seed[32] = { 0, }; + size_t len = sizeof(key); + + PRINT_MSG("Unsupported digest %s rejected by wolfProvider", name); + + ctx = EVP_PKEY_CTX_new_from_name(wpLibCtx, "TLS1-PRF", NULL); + if (ctx == NULL) { + err = 1; + } + if (err == 0) { + if (EVP_PKEY_derive_init(ctx) != 1) { + err = 1; + } + } + if (err == 0) { + /* Rejecting the digest here is a pass too - nothing gets derived. */ + if (EVP_PKEY_CTX_set_tls1_prf_md(ctx, md) != 1) { + rejected = 1; + } + } + if ((err == 0) && (!rejected)) { + if (EVP_PKEY_CTX_set1_tls1_prf_secret(ctx, secret, + sizeof(secret)) != 1) { + err = 1; + } + } + if ((err == 0) && (!rejected)) { + if (EVP_PKEY_CTX_add1_tls1_prf_seed(ctx, seed, sizeof(seed)) != 1) { + err = 1; + } + } + if ((err == 0) && (!rejected)) { + /* Derivation must fail for the unsupported digest. */ + if (EVP_PKEY_derive(ctx, key, &len) == 1) { + PRINT_MSG("FAILED unsupported digest %s was accepted", name); + err = 1; + } + } + + EVP_PKEY_CTX_free(ctx); + return err; +} + +static int test_tls1_prf_unsupported_md(void) +{ + int err = 0; + const EVP_MD *md[3]; + const char *name[3]; + int cnt = 0; + int i; + +#ifdef WP_HAVE_SHA1 + md[cnt] = EVP_sha1(); + name[cnt] = "SHA-1"; + cnt++; +#endif +#ifdef WP_HAVE_SHA224 + md[cnt] = EVP_sha224(); + name[cnt] = "SHA-224"; + cnt++; +#endif +#ifdef WP_HAVE_SHA512 + md[cnt] = EVP_sha512(); + name[cnt] = "SHA-512"; + cnt++; +#endif + + for (i = 0; (err == 0) && (i < cnt); i++) { + err = test_tls1_prf_unsupported_md_calc(md[i], name[i]); + } + + return err; +} +#endif /* WP_HAVE_SHA1 || WP_HAVE_SHA224 || WP_HAVE_SHA512 */ + static int test_tls1_prf_fail_calc(OSSL_LIB_CTX* libCtx) { int err = 0; @@ -379,6 +465,11 @@ int test_tls1_prf(void *data) if (err == 0) { err = test_tls1_prf_str_md("sha384"); } +#endif +#if defined(WP_HAVE_SHA1) || defined(WP_HAVE_SHA224) || defined(WP_HAVE_SHA512) + if (err == 0) { + err = test_tls1_prf_unsupported_md(); + } #endif if (err == 0) { err = test_tls1_prf_fail();