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

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