163057e
From 2000eaead63732669283e6b54c8ef02e268eaeb8 Mon Sep 17 00:00:00 2001
163057e
From: rpm-build <rpm-build>
163057e
Date: Mon, 31 Jul 2023 09:41:29 +0200
163057e
Subject: [PATCH 34/48] 0078-Add-FIPS-indicator-parameter-to-HKDF.patch
163057e
163057e
Patch-name: 0078-Add-FIPS-indicator-parameter-to-HKDF.patch
163057e
Patch-id: 78
163057e
Patch-status: |
163057e
    # https://bugzilla.redhat.com/show_bug.cgi?id=2114772
163057e
From-dist-git-commit: 9409bc7044cf4b5773639cce20f51399888c45fd
163057e
---
163057e
 include/crypto/evp.h                      |   7 ++
163057e
 include/openssl/core_names.h              |   1 +
163057e
 include/openssl/kdf.h                     |   4 +
163057e
 providers/implementations/kdfs/hkdf.c     | 100 +++++++++++++++++++++-
163057e
 providers/implementations/kdfs/kbkdf.c    |  82 ++++++++++++++++--
163057e
 providers/implementations/kdfs/sshkdf.c   |  75 +++++++++++++++-
163057e
 providers/implementations/kdfs/sskdf.c    | 100 +++++++++++++++++++++-
163057e
 providers/implementations/kdfs/tls1_prf.c |  74 +++++++++++++++-
163057e
 providers/implementations/kdfs/x942kdf.c  |  66 +++++++++++++-
163057e
 9 files changed, 487 insertions(+), 22 deletions(-)
163057e
163057e
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
163057e
index dbbdcccbda..aa07153441 100644
163057e
--- a/include/crypto/evp.h
163057e
+++ b/include/crypto/evp.h
163057e
@@ -219,6 +219,13 @@ struct evp_mac_st {
163057e
     OSSL_FUNC_mac_set_ctx_params_fn *set_ctx_params;
163057e
 };
163057e
 
163057e
+#ifdef FIPS_MODULE
163057e
+/* According to NIST Special Publication 800-131Ar2, Section 8: Deriving
163057e
+ * Additional Keys from a Cryptographic Key, "[t]he length of the
163057e
+ * key-derivation key [i.e., the input key] shall be at least 112 bits". */
163057e
+# define EVP_KDF_FIPS_MIN_KEY_LEN (112 / 8)
163057e
+#endif
163057e
+
163057e
 struct evp_kdf_st {
163057e
     OSSL_PROVIDER *prov;
163057e
     int name_id;
163057e
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
163057e
index c0cce14297..b431b9f871 100644
163057e
--- a/include/openssl/core_names.h
163057e
+++ b/include/openssl/core_names.h
163057e
@@ -226,6 +226,7 @@ extern "C" {
163057e
 #define OSSL_KDF_PARAM_X942_SUPP_PUBINFO    "supp-pubinfo"
163057e
 #define OSSL_KDF_PARAM_X942_SUPP_PRIVINFO   "supp-privinfo"
163057e
 #define OSSL_KDF_PARAM_X942_USE_KEYBITS     "use-keybits"
163057e
+#define OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR "redhat-fips-indicator"
163057e
 
163057e
 /* Known KDF names */
163057e
 #define OSSL_KDF_NAME_HKDF           "HKDF"
163057e
diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h
163057e
index 0983230a48..86171635ea 100644
163057e
--- a/include/openssl/kdf.h
163057e
+++ b/include/openssl/kdf.h
163057e
@@ -63,6 +63,10 @@ int EVP_KDF_names_do_all(const EVP_KDF *kdf,
163057e
 # define EVP_KDF_HKDF_MODE_EXTRACT_ONLY        1
163057e
 # define EVP_KDF_HKDF_MODE_EXPAND_ONLY         2
163057e
 
163057e
+# define EVP_KDF_REDHAT_FIPS_INDICATOR_UNDETERMINED 0
163057e
+# define EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED     1
163057e
+# define EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED 2
163057e
+
163057e
 #define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV     65
163057e
 #define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI     66
163057e
 #define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV 67
163057e
diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c
163057e
index 5304baa6c9..f9c77f4236 100644
163057e
--- a/providers/implementations/kdfs/hkdf.c
163057e
+++ b/providers/implementations/kdfs/hkdf.c
163057e
@@ -43,6 +43,7 @@ static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params;
163057e
 static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params;
163057e
 static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params;
163057e
 static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params;
163057e
+static OSSL_FUNC_kdf_newctx_fn kdf_tls1_3_new;
163057e
 static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive;
163057e
 static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params;
163057e
 static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params;
163057e
@@ -86,6 +87,10 @@ typedef struct {
163057e
     size_t data_len;
163057e
     unsigned char *info;
163057e
     size_t info_len;
163057e
+    int is_tls13;
163057e
+#ifdef FIPS_MODULE
163057e
+    int fips_indicator;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 } KDF_HKDF;
163057e
 
163057e
 static void *kdf_hkdf_new(void *provctx)
163057e
@@ -201,6 +206,11 @@ static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         return 0;
163057e
     }
163057e
 
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
     switch (ctx->mode) {
163057e
     case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
163057e
     default:
163057e
@@ -363,15 +373,78 @@ static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
163057e
 {
163057e
     KDF_HKDF *ctx = (KDF_HKDF *)vctx;
163057e
     OSSL_PARAM *p;
163057e
+    int any_valid = 0; /* set to 1 when at least one parameter was valid */
163057e
 
163057e
     if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
163057e
         size_t sz = kdf_hkdf_size(ctx);
163057e
 
163057e
-        if (sz == 0)
163057e
+        any_valid = 1;
163057e
+
163057e
+        if (sz == 0 || !OSSL_PARAM_set_size_t(p, sz))
163057e
             return 0;
163057e
-        return OSSL_PARAM_set_size_t(p, sz);
163057e
     }
163057e
-    return -2;
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR))
163057e
+            != NULL) {
163057e
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
163057e
+        const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
163057e
+
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* According to NIST Special Publication 800-131Ar2, Section 8:
163057e
+         * Deriving Additional Keys from a Cryptographic Key, "[t]he length of
163057e
+         * the key-derivation key [i.e., the input key] shall be at least 112
163057e
+         * bits". */
163057e
+        if (ctx->key_len < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Verification Program, Section D.B and NIST Special Publication
163057e
+         * 800-131Ar2, Section 1.2.2 say that any algorithm at a security
163057e
+         * strength < 112 bits is legacy use only, so all derived keys should
163057e
+         * be longer than that. If a derived key has ever been shorter than
163057e
+         * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we
163057e
+         * should also set the returned FIPS indicator to unapproved. */
163057e
+        if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        if (ctx->is_tls13) {
163057e
+            if (md != NULL
163057e
+                    && !EVP_MD_is_a(md, "SHA2-256")
163057e
+                    && !EVP_MD_is_a(md, "SHA2-384")) {
163057e
+                /* Implementation Guidance for FIPS 140-3 and the Cryptographic
163057e
+                 * Module Validation Program, Section 2.4.B, (5): "The TLS 1.3
163057e
+                 * key derivation function documented in Section 7.1 of RFC
163057e
+                 * 8446. This is considered an approved CVL because the
163057e
+                 * underlying functions performed within the TLS 1.3 KDF map to
163057e
+                 * NIST approved standards, namely: SP 800-133rev2 (Section 6.3
163057e
+                 * Option #3), SP 800-56Crev2, and SP 800-108."
163057e
+                 *
163057e
+                 * RFC 8446 appendix B.4 only lists SHA-256 and SHA-384. */
163057e
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+            }
163057e
+        } else {
163057e
+            if (md != NULL
163057e
+                    && (EVP_MD_is_a(md, "SHAKE-128") ||
163057e
+                        EVP_MD_is_a(md, "SHAKE-256"))) {
163057e
+                /* HKDF is a SP 800-56Cr2 TwoStep KDF, for which all SHA-1,
163057e
+                 * SHA-2 and SHA-3 are approved. SHAKE is not approved, because
163057e
+                 * of FIPS 140-3 IG, section C.C: "The SHAKE128 and SHAKE256
163057e
+                 * extendable-output functions may only be used as the
163057e
+                 * standalone algorithms." */
163057e
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+            }
163057e
+        }
163057e
+        if (!OSSL_PARAM_set_int(p, fips_indicator))
163057e
+            return 0;
163057e
+    }
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
+    if (!any_valid)
163057e
+        return -2;
163057e
+
163057e
+    return 1;
163057e
 }
163057e
 
163057e
 static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
@@ -379,6 +452,9 @@ static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
 {
163057e
     static const OSSL_PARAM known_gettable_ctx_params[] = {
163057e
         OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
163057e
+#ifdef FIPS_MODULE
163057e
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, NULL),
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
         OSSL_PARAM_END
163057e
     };
163057e
     return known_gettable_ctx_params;
163057e
@@ -709,6 +785,17 @@ static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx,
163057e
     return ret;
163057e
 }
163057e
 
163057e
+static void *kdf_tls1_3_new(void *provctx)
163057e
+{
163057e
+    KDF_HKDF *hkdf = kdf_hkdf_new(provctx);
163057e
+
163057e
+    if (hkdf != NULL)
163057e
+        hkdf->is_tls13 = 1;
163057e
+
163057e
+    return hkdf;
163057e
+}
163057e
+
163057e
+
163057e
 static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
                              const OSSL_PARAM params[])
163057e
 {
163057e
@@ -724,6 +811,11 @@ static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         return 0;
163057e
     }
163057e
 
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
     switch (ctx->mode) {
163057e
     default:
163057e
         return 0;
163057e
@@ -801,7 +893,7 @@ static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx,
163057e
 }
163057e
 
163057e
 const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = {
163057e
-    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new },
163057e
+    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_3_new },
163057e
     { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))kdf_hkdf_dup },
163057e
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free },
163057e
     { OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset },
163057e
diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c
163057e
index aa3df15bc7..3f82710061 100644
163057e
--- a/providers/implementations/kdfs/kbkdf.c
163057e
+++ b/providers/implementations/kdfs/kbkdf.c
163057e
@@ -59,6 +59,9 @@ typedef struct {
163057e
     kbkdf_mode mode;
163057e
     EVP_MAC_CTX *ctx_init;
163057e
 
163057e
+    /* HMAC digest algorithm, if any; used to compute FIPS indicator */
163057e
+    PROV_DIGEST digest;
163057e
+
163057e
     /* Names are lowercased versions of those found in SP800-108. */
163057e
     int r;
163057e
     unsigned char *ki;
163057e
@@ -72,6 +75,9 @@ typedef struct {
163057e
     int use_l;
163057e
     int is_kmac;
163057e
     int use_separator;
163057e
+#ifdef FIPS_MODULE
163057e
+    int fips_indicator;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 } KBKDF;
163057e
 
163057e
 /* Definitions needed for typechecking. */
163057e
@@ -143,6 +149,7 @@ static void kbkdf_reset(void *vctx)
163057e
     void *provctx = ctx->provctx;
163057e
 
163057e
     EVP_MAC_CTX_free(ctx->ctx_init);
163057e
+    ossl_prov_digest_reset(&ctx->digest);
163057e
     OPENSSL_clear_free(ctx->context, ctx->context_len);
163057e
     OPENSSL_clear_free(ctx->label, ctx->label_len);
163057e
     OPENSSL_clear_free(ctx->ki, ctx->ki_len);
163057e
@@ -308,6 +315,11 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         goto done;
163057e
     }
163057e
 
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
     h = EVP_MAC_CTX_get_mac_size(ctx->ctx_init);
163057e
     if (h == 0)
163057e
         goto done;
163057e
@@ -381,6 +393,9 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
163057e
         }
163057e
     }
163057e
 
163057e
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
163057e
+        return 0;
163057e
+
163057e
     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE);
163057e
     if (p != NULL
163057e
         && OPENSSL_strncasecmp("counter", p->data, p->data_size) == 0) {
163057e
@@ -461,20 +476,77 @@ static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *ctx,
163057e
 static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
163057e
 {
163057e
     OSSL_PARAM *p;
163057e
+    int any_valid = 0; /* set to 1 when at least one parameter was valid */
163057e
 
163057e
     p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE);
163057e
-    if (p == NULL)
163057e
+    if (p != NULL) {
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* KBKDF can produce results as large as you like. */
163057e
+        if (!OSSL_PARAM_set_size_t(p, SIZE_MAX))
163057e
+            return 0;
163057e
+    }
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR);
163057e
+    if (p != NULL) {
163057e
+        KBKDF *ctx = (KBKDF *)vctx;
163057e
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
163057e
+
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* According to NIST Special Publication 800-131Ar2, Section 8:
163057e
+         * Deriving Additional Keys from a Cryptographic Key, "[t]he length of
163057e
+         * the key-derivation key [i.e., the input key] shall be at least 112
163057e
+         * bits". */
163057e
+        if (ctx->ki_len < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Verification Program, Section D.B and NIST Special Publication
163057e
+         * 800-131Ar2, Section 1.2.2 say that any algorithm at a security
163057e
+         * strength < 112 bits is legacy use only, so all derived keys should
163057e
+         * be longer than that. If a derived key has ever been shorter than
163057e
+         * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we
163057e
+         * should also set the returned FIPS indicator to unapproved. */
163057e
+        if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Validation Program, Section C.C: "The SHAKE128 and SHAKE256
163057e
+         * extendable-output functions may only be used as the standalone
163057e
+         * algorithms." Note that the digest is only used when the MAC
163057e
+         * algorithm is HMAC. */
163057e
+        if (ctx->ctx_init != NULL
163057e
+                && EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), OSSL_MAC_NAME_HMAC)) {
163057e
+            const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
163057e
+            if (md != NULL
163057e
+                    && (EVP_MD_is_a(md, "SHAKE-128") || EVP_MD_is_a(md, "SHAKE-256"))) {
163057e
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+            }
163057e
+        }
163057e
+
163057e
+        if (!OSSL_PARAM_set_int(p, fips_indicator))
163057e
+            return 0;
163057e
+    }
163057e
+#endif
163057e
+
163057e
+    if (!any_valid)
163057e
         return -2;
163057e
 
163057e
-    /* KBKDF can produce results as large as you like. */
163057e
-    return OSSL_PARAM_set_size_t(p, SIZE_MAX);
163057e
+    return 1;
163057e
 }
163057e
 
163057e
 static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
                                                    ossl_unused void *provctx)
163057e
 {
163057e
-    static const OSSL_PARAM known_gettable_ctx_params[] =
163057e
-        { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), OSSL_PARAM_END };
163057e
+    static const OSSL_PARAM known_gettable_ctx_params[] = {
163057e
+        OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
163057e
+#ifdef FIPS_MODULE
163057e
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, NULL),
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+        OSSL_PARAM_END
163057e
+    };
163057e
     return known_gettable_ctx_params;
163057e
 }
163057e
 
163057e
diff --git a/providers/implementations/kdfs/sshkdf.c b/providers/implementations/kdfs/sshkdf.c
163057e
index 1afac4e477..389b82b714 100644
163057e
--- a/providers/implementations/kdfs/sshkdf.c
163057e
+++ b/providers/implementations/kdfs/sshkdf.c
163057e
@@ -49,6 +49,9 @@ typedef struct {
163057e
     char type; /* X */
163057e
     unsigned char *session_id;
163057e
     size_t session_id_len;
163057e
+#ifdef FIPS_MODULE
163057e
+    int fips_indicator;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 } KDF_SSHKDF;
163057e
 
163057e
 static void *kdf_sshkdf_new(void *provctx)
163057e
@@ -151,6 +154,12 @@ static int kdf_sshkdf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE);
163057e
         return 0;
163057e
     }
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
     return SSHKDF(md, ctx->key, ctx->key_len,
163057e
                   ctx->xcghash, ctx->xcghash_len,
163057e
                   ctx->session_id, ctx->session_id_len,
163057e
@@ -219,10 +228,67 @@ static const OSSL_PARAM *kdf_sshkdf_settable_ctx_params(ossl_unused void *ctx,
163057e
 static int kdf_sshkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
163057e
 {
163057e
     OSSL_PARAM *p;
163057e
+    int any_valid = 0; /* set to 1 when at least one parameter was valid */
163057e
 
163057e
-    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
163057e
-        return OSSL_PARAM_set_size_t(p, SIZE_MAX);
163057e
-    return -2;
163057e
+    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
163057e
+        any_valid = 1;
163057e
+
163057e
+        if (!OSSL_PARAM_set_size_t(p, SIZE_MAX))
163057e
+            return 0;
163057e
+    }
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR);
163057e
+    if (p != NULL) {
163057e
+        KDF_SSHKDF *ctx = vctx;
163057e
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
163057e
+
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* According to NIST Special Publication 800-131Ar2, Section 8:
163057e
+         * Deriving Additional Keys from a Cryptographic Key, "[t]he length of
163057e
+         * the key-derivation key [i.e., the input key] shall be at least 112
163057e
+         * bits". */
163057e
+        if (ctx->key_len < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Verification Program, Section D.B and NIST Special Publication
163057e
+         * 800-131Ar2, Section 1.2.2 say that any algorithm at a security
163057e
+         * strength < 112 bits is legacy use only, so all derived keys should
163057e
+         * be longer than that. If a derived key has ever been shorter than
163057e
+         * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we
163057e
+         * should also set the returned FIPS indicator to unapproved. */
163057e
+        if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Validation Program, Section C.C: "The SHAKE128 and SHAKE256
163057e
+         * extendable-output functions may only be used as the standalone
163057e
+         * algorithms."
163057e
+         *
163057e
+         * Additionally, SP 800-135r1 section 5.2 specifies that the hash
163057e
+         * function used in SSHKDF "is one of the hash functions specified in
163057e
+         * FIPS 180-3.", which rules out SHA-3 and truncated variants of SHA-2.
163057e
+         * */
163057e
+        if (ctx->digest.md != NULL
163057e
+            && !EVP_MD_is_a(ctx->digest.md, "SHA-1")
163057e
+            && !EVP_MD_is_a(ctx->digest.md, "SHA2-224")
163057e
+            && !EVP_MD_is_a(ctx->digest.md, "SHA2-256")
163057e
+            && !EVP_MD_is_a(ctx->digest.md, "SHA2-384")
163057e
+            && !EVP_MD_is_a(ctx->digest.md, "SHA2-512")) {
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+        }
163057e
+
163057e
+        if (!OSSL_PARAM_set_int(p, fips_indicator))
163057e
+            return 0;
163057e
+    }
163057e
+#endif
163057e
+
163057e
+    if (!any_valid)
163057e
+        return -2;
163057e
+
163057e
+    return 1;
163057e
 }
163057e
 
163057e
 static const OSSL_PARAM *kdf_sshkdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
@@ -230,6 +296,9 @@ static const OSSL_PARAM *kdf_sshkdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
 {
163057e
     static const OSSL_PARAM known_gettable_ctx_params[] = {
163057e
         OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
163057e
+#ifdef FIPS_MODULE
163057e
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, NULL),
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
         OSSL_PARAM_END
163057e
     };
163057e
     return known_gettable_ctx_params;
163057e
diff --git a/providers/implementations/kdfs/sskdf.c b/providers/implementations/kdfs/sskdf.c
163057e
index ecb98de6fd..98fcc583d8 100644
163057e
--- a/providers/implementations/kdfs/sskdf.c
163057e
+++ b/providers/implementations/kdfs/sskdf.c
163057e
@@ -63,6 +63,10 @@ typedef struct {
163057e
     size_t salt_len;
163057e
     size_t out_len; /* optional KMAC parameter */
163057e
     int is_kmac;
163057e
+    int is_x963kdf;
163057e
+#ifdef FIPS_MODULE
163057e
+    int fips_indicator;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 } KDF_SSKDF;
163057e
 
163057e
 #define SSKDF_MAX_INLEN (1<<30)
163057e
@@ -73,6 +77,7 @@ typedef struct {
163057e
 static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 };
163057e
 
163057e
 static OSSL_FUNC_kdf_newctx_fn sskdf_new;
163057e
+static OSSL_FUNC_kdf_newctx_fn x963kdf_new;
163057e
 static OSSL_FUNC_kdf_dupctx_fn sskdf_dup;
163057e
 static OSSL_FUNC_kdf_freectx_fn sskdf_free;
163057e
 static OSSL_FUNC_kdf_reset_fn sskdf_reset;
163057e
@@ -297,6 +302,16 @@ static void *sskdf_new(void *provctx)
163057e
     return ctx;
163057e
 }
163057e
 
163057e
+static void *x963kdf_new(void *provctx)
163057e
+{
163057e
+    KDF_SSKDF *ctx = sskdf_new(provctx);
163057e
+
163057e
+    if (ctx)
163057e
+        ctx->is_x963kdf = 1;
163057e
+
163057e
+    return ctx;
163057e
+}
163057e
+
163057e
 static void sskdf_reset(void *vctx)
163057e
 {
163057e
     KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
163057e
@@ -392,6 +407,11 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
     }
163057e
     md = ossl_prov_digest_md(&ctx->digest);
163057e
 
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
     if (ctx->macctx != NULL) {
163057e
         /* H(x) = KMAC or H(x) = HMAC */
163057e
         int ret;
163057e
@@ -473,6 +493,11 @@ static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         return 0;
163057e
     }
163057e
 
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+
163057e
     return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len,
163057e
                           ctx->info, ctx->info_len, 1, key, keylen);
163057e
 }
163057e
@@ -545,10 +570,74 @@ static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
163057e
 {
163057e
     KDF_SSKDF *ctx = (KDF_SSKDF *)vctx;
163057e
     OSSL_PARAM *p;
163057e
+    int any_valid = 0; /* set to 1 when at least one parameter was valid */
163057e
+
163057e
+    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
163057e
+        any_valid = 1;
163057e
+
163057e
+        if (!OSSL_PARAM_set_size_t(p, sskdf_size(ctx)))
163057e
+            return 0;
163057e
+    }
163057e
 
163057e
-    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
163057e
-        return OSSL_PARAM_set_size_t(p, sskdf_size(ctx));
163057e
-    return -2;
163057e
+#ifdef FIPS_MODULE
163057e
+    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR);
163057e
+    if (p != NULL) {
163057e
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
163057e
+
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* According to NIST Special Publication 800-131Ar2, Section 8:
163057e
+         * Deriving Additional Keys from a Cryptographic Key, "[t]he length of
163057e
+         * the key-derivation key [i.e., the input key] shall be at least 112
163057e
+         * bits". */
163057e
+        if (ctx->secret_len < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Verification Program, Section D.B and NIST Special Publication
163057e
+         * 800-131Ar2, Section 1.2.2 say that any algorithm at a security
163057e
+         * strength < 112 bits is legacy use only, so all derived keys should
163057e
+         * be longer than that. If a derived key has ever been shorter than
163057e
+         * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we
163057e
+         * should also set the returned FIPS indicator to unapproved. */
163057e
+        if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Validation Program, Section C.C: "The SHAKE128 and SHAKE256
163057e
+         * extendable-output functions may only be used as the standalone
163057e
+         * algorithms." */
163057e
+        if (ctx->macctx == NULL
163057e
+                || (ctx->macctx != NULL &&
163057e
+                    EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx), OSSL_MAC_NAME_HMAC))) {
163057e
+            if (ctx->digest.md != NULL
163057e
+                && (EVP_MD_is_a(ctx->digest.md, "SHAKE-128") ||
163057e
+                    EVP_MD_is_a(ctx->digest.md, "SHAKE-256"))) {
163057e
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+            }
163057e
+
163057e
+            /* Table H-3 in ANS X9.63-2001 says that 160-bit hash functions
163057e
+             * should only be used for 80-bit key agreement, but FIPS 140-3
163057e
+             * requires a security strength of 112 bits, so SHA-1 cannot be
163057e
+             * used with X9.63. See the discussion in
163057e
+             * https://github.com/usnistgov/ACVP/issues/1403#issuecomment-1435300395.
163057e
+             */
163057e
+            if (ctx->is_x963kdf
163057e
+                    && ctx->digest.md != NULL
163057e
+                    && EVP_MD_is_a(ctx->digest.md, "SHA-1")) {
163057e
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+            }
163057e
+        }
163057e
+
163057e
+        if (!OSSL_PARAM_set_int(p, fips_indicator))
163057e
+            return 0;
163057e
+    }
163057e
+#endif
163057e
+
163057e
+    if (!any_valid)
163057e
+        return -2;
163057e
+
163057e
+    return 1;
163057e
 }
163057e
 
163057e
 static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
@@ -556,6 +645,9 @@ static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
 {
163057e
     static const OSSL_PARAM known_gettable_ctx_params[] = {
163057e
         OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
163057e
+#ifdef FIPS_MODULE
163057e
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, 0),
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
         OSSL_PARAM_END
163057e
     };
163057e
     return known_gettable_ctx_params;
163057e
@@ -577,7 +669,7 @@ const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = {
163057e
 };
163057e
 
163057e
 const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = {
163057e
-    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new },
163057e
+    { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x963kdf_new },
163057e
     { OSSL_FUNC_KDF_DUPCTX, (void(*)(void))sskdf_dup },
163057e
     { OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free },
163057e
     { OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset },
163057e
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c
163057e
index 54124ad4cb..25a6c79a2e 100644
163057e
--- a/providers/implementations/kdfs/tls1_prf.c
163057e
+++ b/providers/implementations/kdfs/tls1_prf.c
163057e
@@ -104,6 +104,13 @@ typedef struct {
163057e
     /* Buffer of concatenated seed data */
163057e
     unsigned char seed[TLS1_PRF_MAXBUF];
163057e
     size_t seedlen;
163057e
+
163057e
+    /* MAC digest algorithm; used to compute FIPS indicator */
163057e
+    PROV_DIGEST digest;
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    int fips_indicator;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 } TLS1_PRF;
163057e
 
163057e
 static void *kdf_tls1_prf_new(void *provctx)
163057e
@@ -140,6 +147,7 @@ static void kdf_tls1_prf_reset(void *vctx)
163057e
     EVP_MAC_CTX_free(ctx->P_sha1);
163057e
     OPENSSL_clear_free(ctx->sec, ctx->seclen);
163057e
     OPENSSL_cleanse(ctx->seed, ctx->seedlen);
163057e
+    ossl_prov_digest_reset(&ctx->digest);
163057e
     memset(ctx, 0, sizeof(*ctx));
163057e
     ctx->provctx = provctx;
163057e
 }
163057e
@@ -194,6 +202,10 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
163057e
         return 0;
163057e
     }
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 
163057e
     /*
163057e
      * The seed buffer is prepended with a label.
163057e
@@ -243,6 +255,9 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
163057e
         }
163057e
     }
163057e
 
163057e
+    if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx))
163057e
+        return 0;
163057e
+
163057e
     if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) {
163057e
         OPENSSL_clear_free(ctx->sec, ctx->seclen);
163057e
         ctx->sec = NULL;
163057e
@@ -284,10 +299,60 @@ static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params(
163057e
 static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[])
163057e
 {
163057e
     OSSL_PARAM *p;
163057e
+#ifdef FIPS_MODULE
163057e
+    TLS1_PRF *ctx = vctx;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
+    int any_valid = 0; /* set to 1 when at least one parameter was valid */
163057e
+
163057e
+    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
163057e
+        any_valid = 1;
163057e
+
163057e
+        if (!OSSL_PARAM_set_size_t(p, SIZE_MAX))
163057e
+            return 0;
163057e
+    }
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR);
163057e
+    if (p != NULL) {
163057e
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
163057e
+
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* According to NIST Special Publication 800-131Ar2, Section 8:
163057e
+         * Deriving Additional Keys from a Cryptographic Key, "[t]he length of
163057e
+         * the key-derivation key [i.e., the input key] shall be at least 112
163057e
+         * bits". */
163057e
+        if (ctx->seclen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Verification Program, Section D.B and NIST Special Publication
163057e
+         * 800-131Ar2, Section 1.2.2 say that any algorithm at a security
163057e
+         * strength < 112 bits is legacy use only, so all derived keys should
163057e
+         * be longer than that. If a derived key has ever been shorter than
163057e
+         * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we
163057e
+         * should also set the returned FIPS indicator to unapproved. */
163057e
+        if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* SP 800-135r1 section 4.2.2 says TLS 1.2 KDF is approved when "(3)
163057e
+         * P_HASH uses either SHA-256, SHA-384 or SHA-512." */
163057e
+        if (ctx->digest.md != NULL
163057e
+                && !EVP_MD_is_a(ctx->digest.md, "SHA2-256")
163057e
+                && !EVP_MD_is_a(ctx->digest.md, "SHA2-384")
163057e
+                && !EVP_MD_is_a(ctx->digest.md, "SHA2-512")) {
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+        }
163057e
+
163057e
+        if (!OSSL_PARAM_set_int(p, fips_indicator))
163057e
+            return 0;
163057e
+    }
163057e
+#endif
163057e
 
163057e
-    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
163057e
-        return OSSL_PARAM_set_size_t(p, SIZE_MAX);
163057e
-    return -2;
163057e
+    if (!any_valid)
163057e
+        return -2;
163057e
+
163057e
+    return 1;
163057e
 }
163057e
 
163057e
 static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(
163057e
@@ -295,6 +360,9 @@ static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params(
163057e
 {
163057e
     static const OSSL_PARAM known_gettable_ctx_params[] = {
163057e
         OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
163057e
+#ifdef FIPS_MODULE
163057e
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, 0),
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
         OSSL_PARAM_END
163057e
     };
163057e
     return known_gettable_ctx_params;
163057e
diff --git a/providers/implementations/kdfs/x942kdf.c b/providers/implementations/kdfs/x942kdf.c
163057e
index 4c274fe27a..5ce23c8eb9 100644
163057e
--- a/providers/implementations/kdfs/x942kdf.c
163057e
+++ b/providers/implementations/kdfs/x942kdf.c
163057e
@@ -13,11 +13,13 @@
163057e
 #include <openssl/core_dispatch.h>
163057e
 #include <openssl/err.h>
163057e
 #include <openssl/evp.h>
163057e
+#include <openssl/kdf.h>
163057e
 #include <openssl/params.h>
163057e
 #include <openssl/proverr.h>
163057e
 #include "internal/packet.h"
163057e
 #include "internal/der.h"
163057e
 #include "internal/nelem.h"
163057e
+#include "crypto/evp.h"
163057e
 #include "prov/provider_ctx.h"
163057e
 #include "prov/providercommon.h"
163057e
 #include "prov/implementations.h"
163057e
@@ -49,6 +51,9 @@ typedef struct {
163057e
     const unsigned char *cek_oid;
163057e
     size_t cek_oid_len;
163057e
     int use_keybits;
163057e
+#ifdef FIPS_MODULE
163057e
+    int fips_indicator;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
 } KDF_X942;
163057e
 
163057e
 /*
163057e
@@ -497,6 +502,10 @@ static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen,
163057e
         ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING);
163057e
         return 0;
163057e
     }
163057e
+#ifdef FIPS_MODULE
163057e
+    if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+        ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
     ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len,
163057e
                            der, der_len, ctr, key, keylen);
163057e
     OPENSSL_free(der);
163057e
@@ -600,10 +609,58 @@ static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
163057e
 {
163057e
     KDF_X942 *ctx = (KDF_X942 *)vctx;
163057e
     OSSL_PARAM *p;
163057e
+    int any_valid = 0; /* set to 1 when at least one parameter was valid */
163057e
 
163057e
-    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
163057e
-        return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx));
163057e
-    return -2;
163057e
+    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) {
163057e
+        any_valid = 1;
163057e
+
163057e
+        if (!OSSL_PARAM_set_size_t(p, x942kdf_size(ctx)))
163057e
+            return 0;
163057e
+    }
163057e
+
163057e
+#ifdef FIPS_MODULE
163057e
+    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR);
163057e
+    if (p != NULL) {
163057e
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
163057e
+
163057e
+        any_valid = 1;
163057e
+
163057e
+        /* According to NIST Special Publication 800-131Ar2, Section 8:
163057e
+         * Deriving Additional Keys from a Cryptographic Key, "[t]he length of
163057e
+         * the key-derivation key [i.e., the input key] shall be at least 112
163057e
+         * bits". */
163057e
+        if (ctx->secret_len < EVP_KDF_FIPS_MIN_KEY_LEN)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Verification Program, Section D.B and NIST Special Publication
163057e
+         * 800-131Ar2, Section 1.2.2 say that any algorithm at a security
163057e
+         * strength < 112 bits is legacy use only, so all derived keys should
163057e
+         * be longer than that. If a derived key has ever been shorter than
163057e
+         * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we
163057e
+         * should also set the returned FIPS indicator to unapproved. */
163057e
+        if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED)
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+
163057e
+        /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module
163057e
+         * Validation Program, Section C.C: "The SHAKE128 and SHAKE256
163057e
+         * extendable-output functions may only be used as the standalone
163057e
+         * algorithms." */
163057e
+        if (ctx->digest.md != NULL
163057e
+                && (EVP_MD_is_a(ctx->digest.md, "SHAKE-128") ||
163057e
+                    EVP_MD_is_a(ctx->digest.md, "SHAKE-256"))) {
163057e
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
163057e
+        }
163057e
+
163057e
+        if (!OSSL_PARAM_set_int(p, fips_indicator))
163057e
+            return 0;
163057e
+    }
163057e
+#endif
163057e
+
163057e
+    if (!any_valid)
163057e
+        return -2;
163057e
+
163057e
+    return 1;
163057e
 }
163057e
 
163057e
 static const OSSL_PARAM *x942kdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
@@ -611,6 +668,9 @@ static const OSSL_PARAM *x942kdf_gettable_ctx_params(ossl_unused void *ctx,
163057e
 {
163057e
     static const OSSL_PARAM known_gettable_ctx_params[] = {
163057e
         OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
163057e
+#ifdef FIPS_MODULE
163057e
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, 0),
163057e
+#endif /* defined(FIPS_MODULE) */
163057e
         OSSL_PARAM_END
163057e
     };
163057e
     return known_gettable_ctx_params;
163057e
-- 
163057e
2.41.0
163057e