Commit 45c8f381b5 for openssl.org

commit 45c8f381b5513feaead63e294e901a5a58566bcb
Author: mzfr <github@mzfr.in>
Date:   Wed Sep 23 23:14:19 2026 +0800

    Preserve SNMPKDF password after rejected updates

    Validate password length before modifying the context and raise an error for invalid lengths. Add regression coverage for rejected updates.

    Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
    Reviewed-by: Igor Ustinov <igus@openssl.foundation>
    Merge-date: Fri Nov 13 15:15:28 2026
    Merged-from: https://github.com/openssl/openssl/pull/32960

diff --git a/providers/implementations/kdfs/snmpkdf.c b/providers/implementations/kdfs/snmpkdf.c
index e857abc1e8..11dff38653 100644
--- a/providers/implementations/kdfs/snmpkdf.c
+++ b/providers/implementations/kdfs/snmpkdf.c
@@ -163,6 +163,13 @@ static int kdf_snmpkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     if (ctx == NULL || !snmp_set_ctx_params_decoder(params, &p))
         return 0;

+    if (p.pw != NULL
+        && (p.pw->data_size < KDF_SNMP_MIN_PASSWORD_LEN
+            || p.pw->data_size > KDF_SNMP_PASSWORD_HASH_AMOUNT)) {
+        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_INPUT_LENGTH);
+        return 0;
+    }
+
     libctx = PROV_LIBCTX_OF(ctx->provctx);
     if (p.digest != NULL) {
         if (!ossl_prov_digest_load(&ctx->digest, p.digest, p.propq, libctx))
@@ -181,8 +188,6 @@ static int kdf_snmpkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     if (p.pw != NULL) {
         if (!snmpkdf_set_membuf(&ctx->password, &ctx->password_len, p.pw))
             return 0;
-        if ((ctx->password_len > KDF_SNMP_PASSWORD_HASH_AMOUNT) || (ctx->password_len < KDF_SNMP_MIN_PASSWORD_LEN))
-            return 0;
     }

     if (p.eid != NULL && !snmpkdf_set_membuf(&ctx->eid, &ctx->eid_len, p.eid))
diff --git a/test/evp_kdf_test.c b/test/evp_kdf_test.c
index ec77564699..155f093d95 100644
--- a/test/evp_kdf_test.c
+++ b/test/evp_kdf_test.c
@@ -2099,6 +2099,39 @@ err:
 }
 #endif /* OPENSSL_NO_SRTPKDF */

+#ifndef OPENSSL_NO_SNMPKDF
+static int test_kdf_snmpkdf_rejected_password(void)
+{
+    int ret;
+    EVP_KDF_CTX *kctx = NULL;
+    OSSL_PARAM params[4], rejected[2];
+    unsigned char password[] = "password";
+    unsigned char eid[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+    unsigned char dummy = 0;
+    unsigned char expected[32], out[sizeof(expected)];
+
+    params[0] = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST,
+        "SHA256", 0);
+    params[1] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+        password, sizeof(password) - 1);
+    params[2] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SNMPKDF_EID,
+        eid, sizeof(eid));
+    params[3] = OSSL_PARAM_construct_end();
+    rejected[0] = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD,
+        &dummy, 0);
+    rejected[1] = OSSL_PARAM_construct_end();
+
+    ret = TEST_ptr(kctx = get_kdfbyname(OSSL_KDF_NAME_SNMPKDF))
+        && TEST_true(EVP_KDF_derive(kctx, expected, sizeof(expected), params))
+        && TEST_false(EVP_KDF_CTX_set_params(kctx, rejected))
+        && TEST_true(EVP_KDF_derive(kctx, out, sizeof(out), NULL))
+        && TEST_mem_eq(out, sizeof(out), expected, sizeof(expected));
+
+    EVP_KDF_CTX_free(kctx);
+    return ret;
+}
+#endif /* OPENSSL_NO_SNMPKDF */
+
 #ifndef OPENSSL_NO_SSHKDF
 static int test_kdf_sshkdf(void)
 {
@@ -2591,6 +2624,9 @@ int setup_tests(void)
 #ifndef OPENSSL_NO_SRTPKDF
     ADD_TEST(test_kdf_srtpkdf_size);
 #endif
+#ifndef OPENSSL_NO_SNMPKDF
+    ADD_TEST(test_kdf_snmpkdf_rejected_password);
+#endif
 #ifndef OPENSSL_NO_SSHKDF
     ADD_TEST(test_kdf_sshkdf);
 #endif