Blame SOURCES/0078-Add-FIPS-indicator-parameter-to-HKDF.patch

1ac26c
From 0c4aaedf29a1ed1559762515bfeaa5923925e18f Mon Sep 17 00:00:00 2001
22d461
From: Clemens Lang <cllang@redhat.com>
22d461
Date: Thu, 11 Aug 2022 09:27:12 +0200
1ac26c
Subject: [PATCH 1/2] Add FIPS indicator parameter to HKDF
22d461
22d461
NIST considers HKDF only acceptable when used as in TLS 1.3, and
22d461
otherwise unapproved. Add an explicit indicator attached to the
22d461
EVP_KDF_CTX that can be queried using EVP_KDF_CTX_get_params() to
22d461
determine whether the KDF operation was approved after performing it.
22d461
22d461
Signed-off-by: Clemens Lang <cllang@redhat.com>
1ac26c
Related: rhbz#2114772
22d461
---
1ac26c
 include/crypto/evp.h                  |  7 ++++
22d461
 include/openssl/core_names.h          |  1 +
22d461
 include/openssl/kdf.h                 |  4 ++
22d461
 providers/implementations/kdfs/hkdf.c | 53 +++++++++++++++++++++++++++
1ac26c
 4 files changed, 65 insertions(+)
22d461
1ac26c
diff --git a/include/crypto/evp.h b/include/crypto/evp.h
1ac26c
index e70d8e9e84..76fb990de4 100644
1ac26c
--- a/include/crypto/evp.h
1ac26c
+++ b/include/crypto/evp.h
1ac26c
@@ -219,6 +219,13 @@ struct evp_mac_st {
1ac26c
     OSSL_FUNC_mac_set_ctx_params_fn *set_ctx_params;
1ac26c
 };
1ac26c
 
1ac26c
+#ifdef FIPS_MODULE
1ac26c
+/* According to NIST Special Publication 800-131Ar2, Section 8: Deriving
1ac26c
+ * Additional Keys from a Cryptographic Key, "[t]he length of the
1ac26c
+ * key-derivation key [i.e., the input key] shall be at least 112 bits". */
1ac26c
+# define EVP_KDF_FIPS_MIN_KEY_LEN (112 / 8)
1ac26c
+#endif
1ac26c
+
1ac26c
 struct evp_kdf_st {
1ac26c
     OSSL_PROVIDER *prov;
1ac26c
     int name_id;
22d461
diff --git a/include/openssl/core_names.h b/include/openssl/core_names.h
1ac26c
index 21c94d0488..c019afbbb0 100644
22d461
--- a/include/openssl/core_names.h
22d461
+++ b/include/openssl/core_names.h
22d461
@@ -223,6 +223,7 @@ extern "C" {
22d461
 #define OSSL_KDF_PARAM_X942_SUPP_PUBINFO    "supp-pubinfo"
22d461
 #define OSSL_KDF_PARAM_X942_SUPP_PRIVINFO   "supp-privinfo"
22d461
 #define OSSL_KDF_PARAM_X942_USE_KEYBITS     "use-keybits"
1ac26c
+#define OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR "redhat-fips-indicator"
22d461
 
22d461
 /* Known KDF names */
22d461
 #define OSSL_KDF_NAME_HKDF           "HKDF"
22d461
diff --git a/include/openssl/kdf.h b/include/openssl/kdf.h
1ac26c
index 0983230a48..86171635ea 100644
22d461
--- a/include/openssl/kdf.h
22d461
+++ b/include/openssl/kdf.h
22d461
@@ -63,6 +63,10 @@ int EVP_KDF_names_do_all(const EVP_KDF *kdf,
22d461
 # define EVP_KDF_HKDF_MODE_EXTRACT_ONLY        1
22d461
 # define EVP_KDF_HKDF_MODE_EXPAND_ONLY         2
22d461
 
1ac26c
+# define EVP_KDF_REDHAT_FIPS_INDICATOR_UNDETERMINED 0
1ac26c
+# define EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED     1
1ac26c
+# define EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED 2
22d461
+
22d461
 #define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_CLI_TO_SRV     65
22d461
 #define EVP_KDF_SSHKDF_TYPE_INITIAL_IV_SRV_TO_CLI     66
22d461
 #define EVP_KDF_SSHKDF_TYPE_ENCRYPTION_KEY_CLI_TO_SRV 67
22d461
diff --git a/providers/implementations/kdfs/hkdf.c b/providers/implementations/kdfs/hkdf.c
1ac26c
index afdb7138e1..6f06fa58fe 100644
22d461
--- a/providers/implementations/kdfs/hkdf.c
22d461
+++ b/providers/implementations/kdfs/hkdf.c
22d461
@@ -298,6 +298,56 @@ static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
22d461
             return 0;
22d461
         return OSSL_PARAM_set_size_t(p, sz);
22d461
     }
22d461
+
22d461
+#ifdef FIPS_MODULE
1ac26c
+    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR))
1ac26c
+            != NULL) {
1ac26c
+        int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_UNDETERMINED;
22d461
+        switch (ctx->mode) {
22d461
+        case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND:
22d461
+            /* TLS 1.3 never uses extract-and-expand */
1ac26c
+            fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
22d461
+            break;
22d461
+        case EVP_KDF_HKDF_MODE_EXTRACT_ONLY:
22d461
+            {
22d461
+                /* When TLS 1.3 uses extract, the following holds:
22d461
+                 * 1. The salt length matches the hash length, and either
22d461
+                 * 2.1. the key is all zeroes and matches the hash length, or
22d461
+                 * 2.2. the key originates from a PSK (resumption_master_secret
22d461
+                 *   or some externally esablished key), or an ECDH or DH key
22d461
+                 *   derivation. See
22d461
+                 *   https://www.rfc-editor.org/rfc/rfc8446#section-7.1.
22d461
+                 * Unfortunately at this point, we cannot verify where the key
22d461
+                 * comes from, so all we can do is check the salt length.
22d461
+                 */
22d461
+                const EVP_MD *md = ossl_prov_digest_md(&ctx->digest);
1ac26c
+                if (md != NULL && ctx->salt_len == (size_t) EVP_MD_get_size(md))
1ac26c
+                    fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
22d461
+                else
1ac26c
+                    fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
22d461
+            }
22d461
+            break;
22d461
+        case EVP_KDF_HKDF_MODE_EXPAND_ONLY:
22d461
+            /* When TLS 1.3 uses expand, it always provides a label that
22d461
+             * contains an uint16 for the length, followed by between 7 and 255
22d461
+             * bytes for a label string that starts with "tls13 " or "dtls13".
22d461
+             * For compatibility with future versions, we only check for "tls"
22d461
+             * or "dtls". See
22d461
+             * https://www.rfc-editor.org/rfc/rfc8446#section-7.1 and
22d461
+             * https://www.rfc-editor.org/rfc/rfc9147#section-5.9. */
22d461
+            if (ctx->label != NULL
22d461
+                    && ctx->label_len >= 2 /* length */ + 4 /* "dtls" */
22d461
+                    && (strncmp("tls", (const char *)ctx->label + 2, 3) == 0 ||
22d461
+                        strncmp("dtls", (const char *)ctx->label + 2, 4) == 0))
1ac26c
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED;
22d461
+            else
1ac26c
+                fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED;
22d461
+            break;
22d461
+        }
22d461
+        return OSSL_PARAM_set_int(p, fips_indicator);
22d461
+    }
22d461
+#endif /* defined(FIPS_MODULE) */
22d461
+
22d461
     return -2;
22d461
 }
22d461
 
22d461
@@ -306,6 +356,9 @@ static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx,
22d461
 {
22d461
     static const OSSL_PARAM known_gettable_ctx_params[] = {
22d461
         OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL),
22d461
+#ifdef FIPS_MODULE
1ac26c
+        OSSL_PARAM_int(OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR, NULL),
22d461
+#endif /* defined(FIPS_MODULE) */
22d461
         OSSL_PARAM_END
22d461
     };
22d461
     return known_gettable_ctx_params;
22d461
-- 
1ac26c
2.38.1
22d461