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