You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
906 lines
36 KiB
906 lines
36 KiB
From 2290280617183863eb15425b8925765966723725 Mon Sep 17 00:00:00 2001 |
|
From: Clemens Lang <cllang@redhat.com> |
|
Date: Thu, 11 Aug 2022 09:27:12 +0200 |
|
Subject: KDF: Add FIPS indicators |
|
|
|
FIPS requires a number of restrictions on the parameters of the various |
|
key derivation functions implemented in OpenSSL. The KDFs that use |
|
digest algorithms usually should not allow SHAKE (due to FIPS 140-3 IG |
|
C.C). Additionally, some application-specific KDFs have further |
|
restrictions defined in SP 800-135r1. |
|
|
|
Generally, all KDFs shall use a key-derivation key length of at least |
|
112 bits due to SP 800-131Ar2 section 8. Additionally any use of a KDF |
|
to generate and output length of less than 112 bits will also set the |
|
indicator to unapproved. |
|
|
|
Add explicit indicators to all KDFs usable in FIPS mode except for |
|
PBKDF2 (which has its specific FIPS limits already implemented). The |
|
indicator can be queried using EVP_KDF_CTX_get_params() after setting |
|
the required parameters and keys for the KDF. |
|
|
|
Our FIPS provider implements SHA1, SHA2 (both -256 and -512, and the |
|
truncated variants -224 and -384) and SHA3 (-256 and -512, and the |
|
truncated versions -224 and -384), as well as SHAKE-128 and -256. |
|
|
|
The SHAKE functions are generally not allowed in KDFs. For the rest, the |
|
support matrix is: |
|
|
|
KDF | SHA-1 | SHA-2 | SHA-2 truncated | SHA-3 | SHA-3 truncated |
|
========================================================================== |
|
KBKDF | x | x | x | x | x |
|
HKDF | x | x | x | x | x |
|
TLS1PRF | | SHA-{256,384,512} only | | |
|
SSHKDF | x | x | x | | |
|
SSKDF | x | x | x | x | x |
|
X9.63KDF | | x | x | x | x |
|
X9.42-ASN1 | x | x | x | x | x |
|
TLS1.3PRF | | SHA-{256,384} only | | |
|
|
|
Signed-off-by: Clemens Lang <cllang@redhat.com> |
|
Resolves: rhbz#2160733 rhbz#2164763 |
|
Related: rhbz#2114772 rhbz#2141695 |
|
--- |
|
include/crypto/evp.h | 7 ++ |
|
include/openssl/core_names.h | 1 + |
|
include/openssl/kdf.h | 4 + |
|
providers/implementations/kdfs/hkdf.c | 100 +++++++++++++++++++++- |
|
providers/implementations/kdfs/kbkdf.c | 82 ++++++++++++++++-- |
|
providers/implementations/kdfs/sshkdf.c | 75 +++++++++++++++- |
|
providers/implementations/kdfs/sskdf.c | 100 +++++++++++++++++++++- |
|
providers/implementations/kdfs/tls1_prf.c | 74 +++++++++++++++- |
|
providers/implementations/kdfs/x942kdf.c | 67 ++++++++++++++- |
|
9 files changed, 488 insertions(+), 22 deletions(-) |
|
|
|
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 6bed5a8a67..680bfbc7cc 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 dfa7786bde..f01e40ff5a 100644 |
|
--- a/providers/implementations/kdfs/hkdf.c |
|
+++ b/providers/implementations/kdfs/hkdf.c |
|
@@ -42,6 +42,7 @@ static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_hkdf_settable_ctx_params; |
|
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_hkdf_set_ctx_params; |
|
static OSSL_FUNC_kdf_gettable_ctx_params_fn kdf_hkdf_gettable_ctx_params; |
|
static OSSL_FUNC_kdf_get_ctx_params_fn kdf_hkdf_get_ctx_params; |
|
+static OSSL_FUNC_kdf_newctx_fn kdf_tls1_3_new; |
|
static OSSL_FUNC_kdf_derive_fn kdf_tls1_3_derive; |
|
static OSSL_FUNC_kdf_settable_ctx_params_fn kdf_tls1_3_settable_ctx_params; |
|
static OSSL_FUNC_kdf_set_ctx_params_fn kdf_tls1_3_set_ctx_params; |
|
@@ -85,6 +86,10 @@ typedef struct { |
|
size_t data_len; |
|
unsigned char info[HKDF_MAXBUF]; |
|
size_t info_len; |
|
+ int is_tls13; |
|
+#ifdef FIPS_MODULE |
|
+ int fips_indicator; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
} KDF_HKDF; |
|
|
|
static void *kdf_hkdf_new(void *provctx) |
|
@@ -170,6 +175,11 @@ static int kdf_hkdf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
return 0; |
|
} |
|
|
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
switch (ctx->mode) { |
|
case EVP_KDF_HKDF_MODE_EXTRACT_AND_EXPAND: |
|
default: |
|
@@ -332,15 +342,78 @@ static int kdf_hkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
|
{ |
|
KDF_HKDF *ctx = (KDF_HKDF *)vctx; |
|
OSSL_PARAM *p; |
|
+ int any_valid = 0; /* set to 1 when at least one parameter was valid */ |
|
|
|
if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) { |
|
size_t sz = kdf_hkdf_size(ctx); |
|
|
|
- if (sz == 0) |
|
+ any_valid = 1; |
|
+ |
|
+ if (sz == 0 || !OSSL_PARAM_set_size_t(p, sz)) |
|
return 0; |
|
- return OSSL_PARAM_set_size_t(p, sz); |
|
} |
|
- return -2; |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR)) |
|
+ != NULL) { |
|
+ int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED; |
|
+ const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
|
+ |
|
+ any_valid = 1; |
|
+ |
|
+ /* 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". */ |
|
+ if (ctx->key_len < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Verification Program, Section D.B and NIST Special Publication |
|
+ * 800-131Ar2, Section 1.2.2 say that any algorithm at a security |
|
+ * strength < 112 bits is legacy use only, so all derived keys should |
|
+ * be longer than that. If a derived key has ever been shorter than |
|
+ * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we |
|
+ * should also set the returned FIPS indicator to unapproved. */ |
|
+ if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ if (ctx->is_tls13) { |
|
+ if (md != NULL |
|
+ && !EVP_MD_is_a(md, "SHA2-256") |
|
+ && !EVP_MD_is_a(md, "SHA2-384")) { |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic |
|
+ * Module Validation Program, Section 2.4.B, (5): "The TLS 1.3 |
|
+ * key derivation function documented in Section 7.1 of RFC |
|
+ * 8446. This is considered an approved CVL because the |
|
+ * underlying functions performed within the TLS 1.3 KDF map to |
|
+ * NIST approved standards, namely: SP 800-133rev2 (Section 6.3 |
|
+ * Option #3), SP 800-56Crev2, and SP 800-108." |
|
+ * |
|
+ * RFC 8446 appendix B.4 only lists SHA-256 and SHA-384. */ |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ } else { |
|
+ if (md != NULL |
|
+ && (EVP_MD_is_a(md, "SHAKE-128") || |
|
+ EVP_MD_is_a(md, "SHAKE-256"))) { |
|
+ /* HKDF is a SP 800-56Cr2 TwoStep KDF, for which all SHA-1, |
|
+ * SHA-2 and SHA-3 are approved. SHAKE is not approved, because |
|
+ * of FIPS 140-3 IG, section C.C: "The SHAKE128 and SHAKE256 |
|
+ * extendable-output functions may only be used as the |
|
+ * standalone algorithms." */ |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ } |
|
+ if (!OSSL_PARAM_set_int(p, fips_indicator)) |
|
+ return 0; |
|
+ } |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
+ if (!any_valid) |
|
+ return -2; |
|
+ |
|
+ return 1; |
|
} |
|
|
|
static const OSSL_PARAM *kdf_hkdf_gettable_ctx_params(ossl_unused void *ctx, |
|
@@ -348,6 +421,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; |
|
@@ -677,6 +753,17 @@ static int prov_tls13_hkdf_generate_secret(OSSL_LIB_CTX *libctx, |
|
return ret; |
|
} |
|
|
|
+static void *kdf_tls1_3_new(void *provctx) |
|
+{ |
|
+ KDF_HKDF *hkdf = kdf_hkdf_new(provctx); |
|
+ |
|
+ if (hkdf != NULL) |
|
+ hkdf->is_tls13 = 1; |
|
+ |
|
+ return hkdf; |
|
+} |
|
+ |
|
+ |
|
static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen, |
|
const OSSL_PARAM params[]) |
|
{ |
|
@@ -692,6 +779,11 @@ static int kdf_tls1_3_derive(void *vctx, unsigned char *key, size_t keylen, |
|
return 0; |
|
} |
|
|
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
switch (ctx->mode) { |
|
default: |
|
return 0; |
|
@@ -769,7 +861,7 @@ static const OSSL_PARAM *kdf_tls1_3_settable_ctx_params(ossl_unused void *ctx, |
|
} |
|
|
|
const OSSL_DISPATCH ossl_kdf_tls1_3_kdf_functions[] = { |
|
- { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_hkdf_new }, |
|
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))kdf_tls1_3_new }, |
|
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))kdf_hkdf_free }, |
|
{ OSSL_FUNC_KDF_RESET, (void(*)(void))kdf_hkdf_reset }, |
|
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))kdf_tls1_3_derive }, |
|
diff --git a/providers/implementations/kdfs/kbkdf.c b/providers/implementations/kdfs/kbkdf.c |
|
index a542f84dfa..6b6dfb94ac 100644 |
|
--- a/providers/implementations/kdfs/kbkdf.c |
|
+++ b/providers/implementations/kdfs/kbkdf.c |
|
@@ -59,6 +59,9 @@ typedef struct { |
|
kbkdf_mode mode; |
|
EVP_MAC_CTX *ctx_init; |
|
|
|
+ /* HMAC digest algorithm, if any; used to compute FIPS indicator */ |
|
+ PROV_DIGEST digest; |
|
+ |
|
/* Names are lowercased versions of those found in SP800-108. */ |
|
int r; |
|
unsigned char *ki; |
|
@@ -70,6 +73,9 @@ typedef struct { |
|
size_t iv_len; |
|
int use_l; |
|
int use_separator; |
|
+#ifdef FIPS_MODULE |
|
+ int fips_indicator; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
} KBKDF; |
|
|
|
/* Definitions needed for typechecking. */ |
|
@@ -138,6 +144,7 @@ static void kbkdf_reset(void *vctx) |
|
void *provctx = ctx->provctx; |
|
|
|
EVP_MAC_CTX_free(ctx->ctx_init); |
|
+ ossl_prov_digest_reset(&ctx->digest); |
|
OPENSSL_clear_free(ctx->context, ctx->context_len); |
|
OPENSSL_clear_free(ctx->label, ctx->label_len); |
|
OPENSSL_clear_free(ctx->ki, ctx->ki_len); |
|
@@ -240,6 +247,11 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
return 0; |
|
} |
|
|
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
h = EVP_MAC_CTX_get_mac_size(ctx->ctx_init); |
|
if (h == 0) |
|
goto done; |
|
@@ -297,6 +309,9 @@ static int kbkdf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) |
|
return 0; |
|
} |
|
|
|
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) |
|
+ return 0; |
|
+ |
|
p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_MODE); |
|
if (p != NULL |
|
&& OPENSSL_strncasecmp("counter", p->data, p->data_size) == 0) { |
|
@@ -363,20 +378,77 @@ static const OSSL_PARAM *kbkdf_settable_ctx_params(ossl_unused void *ctx, |
|
static int kbkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
|
{ |
|
OSSL_PARAM *p; |
|
+ int any_valid = 0; /* set to 1 when at least one parameter was valid */ |
|
|
|
p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE); |
|
- if (p == NULL) |
|
+ if (p != NULL) { |
|
+ any_valid = 1; |
|
+ |
|
+ /* KBKDF can produce results as large as you like. */ |
|
+ if (!OSSL_PARAM_set_size_t(p, SIZE_MAX)) |
|
+ return 0; |
|
+ } |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR); |
|
+ if (p != NULL) { |
|
+ KBKDF *ctx = (KBKDF *)vctx; |
|
+ int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED; |
|
+ |
|
+ any_valid = 1; |
|
+ |
|
+ /* 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". */ |
|
+ if (ctx->ki_len < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Verification Program, Section D.B and NIST Special Publication |
|
+ * 800-131Ar2, Section 1.2.2 say that any algorithm at a security |
|
+ * strength < 112 bits is legacy use only, so all derived keys should |
|
+ * be longer than that. If a derived key has ever been shorter than |
|
+ * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we |
|
+ * should also set the returned FIPS indicator to unapproved. */ |
|
+ if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Validation Program, Section C.C: "The SHAKE128 and SHAKE256 |
|
+ * extendable-output functions may only be used as the standalone |
|
+ * algorithms." Note that the digest is only used when the MAC |
|
+ * algorithm is HMAC. */ |
|
+ if (ctx->ctx_init != NULL |
|
+ && EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->ctx_init), OSSL_MAC_NAME_HMAC)) { |
|
+ const EVP_MD *md = ossl_prov_digest_md(&ctx->digest); |
|
+ if (md != NULL |
|
+ && (EVP_MD_is_a(md, "SHAKE-128") || EVP_MD_is_a(md, "SHAKE-256"))) { |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ } |
|
+ |
|
+ if (!OSSL_PARAM_set_int(p, fips_indicator)) |
|
+ return 0; |
|
+ } |
|
+#endif |
|
+ |
|
+ if (!any_valid) |
|
return -2; |
|
|
|
- /* KBKDF can produce results as large as you like. */ |
|
- return OSSL_PARAM_set_size_t(p, SIZE_MAX); |
|
+ return 1; |
|
} |
|
|
|
static const OSSL_PARAM *kbkdf_gettable_ctx_params(ossl_unused void *ctx, |
|
ossl_unused void *provctx) |
|
{ |
|
- static const OSSL_PARAM known_gettable_ctx_params[] = |
|
- { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), OSSL_PARAM_END }; |
|
+ 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; |
|
} |
|
|
|
diff --git a/providers/implementations/kdfs/sshkdf.c b/providers/implementations/kdfs/sshkdf.c |
|
index c592ba72f1..4a52b38266 100644 |
|
--- a/providers/implementations/kdfs/sshkdf.c |
|
+++ b/providers/implementations/kdfs/sshkdf.c |
|
@@ -48,6 +48,9 @@ typedef struct { |
|
char type; /* X */ |
|
unsigned char *session_id; |
|
size_t session_id_len; |
|
+#ifdef FIPS_MODULE |
|
+ int fips_indicator; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
} KDF_SSHKDF; |
|
|
|
static void *kdf_sshkdf_new(void *provctx) |
|
@@ -126,6 +129,12 @@ static int kdf_sshkdf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_TYPE); |
|
return 0; |
|
} |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
return SSHKDF(md, ctx->key, ctx->key_len, |
|
ctx->xcghash, ctx->xcghash_len, |
|
ctx->session_id, ctx->session_id_len, |
|
@@ -194,10 +203,67 @@ static const OSSL_PARAM *kdf_sshkdf_settable_ctx_params(ossl_unused void *ctx, |
|
static int kdf_sshkdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
|
{ |
|
OSSL_PARAM *p; |
|
+ int any_valid = 0; /* set to 1 when at least one parameter was valid */ |
|
|
|
- if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) |
|
- return OSSL_PARAM_set_size_t(p, SIZE_MAX); |
|
- return -2; |
|
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) { |
|
+ any_valid = 1; |
|
+ |
|
+ if (!OSSL_PARAM_set_size_t(p, SIZE_MAX)) |
|
+ return 0; |
|
+ } |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR); |
|
+ if (p != NULL) { |
|
+ KDF_SSHKDF *ctx = vctx; |
|
+ int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED; |
|
+ |
|
+ any_valid = 1; |
|
+ |
|
+ /* 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". */ |
|
+ if (ctx->key_len < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Verification Program, Section D.B and NIST Special Publication |
|
+ * 800-131Ar2, Section 1.2.2 say that any algorithm at a security |
|
+ * strength < 112 bits is legacy use only, so all derived keys should |
|
+ * be longer than that. If a derived key has ever been shorter than |
|
+ * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we |
|
+ * should also set the returned FIPS indicator to unapproved. */ |
|
+ if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Validation Program, Section C.C: "The SHAKE128 and SHAKE256 |
|
+ * extendable-output functions may only be used as the standalone |
|
+ * algorithms." |
|
+ * |
|
+ * Additionally, SP 800-135r1 section 5.2 specifies that the hash |
|
+ * function used in SSHKDF "is one of the hash functions specified in |
|
+ * FIPS 180-3.", which rules out SHA-3 and truncated variants of SHA-2. |
|
+ * */ |
|
+ if (ctx->digest.md != NULL |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA-1") |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-224") |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-256") |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-384") |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-512")) { |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ |
|
+ if (!OSSL_PARAM_set_int(p, fips_indicator)) |
|
+ return 0; |
|
+ } |
|
+#endif |
|
+ |
|
+ if (!any_valid) |
|
+ return -2; |
|
+ |
|
+ return 1; |
|
} |
|
|
|
static const OSSL_PARAM *kdf_sshkdf_gettable_ctx_params(ossl_unused void *ctx, |
|
@@ -205,6 +271,9 @@ static const OSSL_PARAM *kdf_sshkdf_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; |
|
diff --git a/providers/implementations/kdfs/sskdf.c b/providers/implementations/kdfs/sskdf.c |
|
index eb54972e1c..23865cd70f 100644 |
|
--- a/providers/implementations/kdfs/sskdf.c |
|
+++ b/providers/implementations/kdfs/sskdf.c |
|
@@ -62,6 +62,10 @@ typedef struct { |
|
unsigned char *salt; |
|
size_t salt_len; |
|
size_t out_len; /* optional KMAC parameter */ |
|
+ int is_x963kdf; |
|
+#ifdef FIPS_MODULE |
|
+ int fips_indicator; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
} KDF_SSKDF; |
|
|
|
#define SSKDF_MAX_INLEN (1<<30) |
|
@@ -73,6 +77,7 @@ typedef struct { |
|
static const unsigned char kmac_custom_str[] = { 0x4B, 0x44, 0x46 }; |
|
|
|
static OSSL_FUNC_kdf_newctx_fn sskdf_new; |
|
+static OSSL_FUNC_kdf_newctx_fn x963kdf_new; |
|
static OSSL_FUNC_kdf_freectx_fn sskdf_free; |
|
static OSSL_FUNC_kdf_reset_fn sskdf_reset; |
|
static OSSL_FUNC_kdf_derive_fn sskdf_derive; |
|
@@ -296,6 +301,16 @@ static void *sskdf_new(void *provctx) |
|
return ctx; |
|
} |
|
|
|
+static void *x963kdf_new(void *provctx) |
|
+{ |
|
+ KDF_SSKDF *ctx = sskdf_new(provctx); |
|
+ |
|
+ if (ctx) |
|
+ ctx->is_x963kdf = 1; |
|
+ |
|
+ return ctx; |
|
+} |
|
+ |
|
static void sskdf_reset(void *vctx) |
|
{ |
|
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
|
@@ -361,6 +376,11 @@ static int sskdf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
} |
|
md = ossl_prov_digest_md(&ctx->digest); |
|
|
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
if (ctx->macctx != NULL) { |
|
/* H(x) = KMAC or H(x) = HMAC */ |
|
int ret; |
|
@@ -442,6 +462,11 @@ static int x963kdf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
return 0; |
|
} |
|
|
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ |
|
return SSKDF_hash_kdm(md, ctx->secret, ctx->secret_len, |
|
ctx->info, ctx->info_len, 1, key, keylen); |
|
} |
|
@@ -514,10 +539,74 @@ static int sskdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
|
{ |
|
KDF_SSKDF *ctx = (KDF_SSKDF *)vctx; |
|
OSSL_PARAM *p; |
|
+ int any_valid = 0; /* set to 1 when at least one parameter was valid */ |
|
+ |
|
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) { |
|
+ any_valid = 1; |
|
+ |
|
+ if (!OSSL_PARAM_set_size_t(p, sskdf_size(ctx))) |
|
+ return 0; |
|
+ } |
|
|
|
- if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) |
|
- return OSSL_PARAM_set_size_t(p, sskdf_size(ctx)); |
|
- return -2; |
|
+#ifdef FIPS_MODULE |
|
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR); |
|
+ if (p != NULL) { |
|
+ int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED; |
|
+ |
|
+ any_valid = 1; |
|
+ |
|
+ /* 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". */ |
|
+ if (ctx->secret_len < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Verification Program, Section D.B and NIST Special Publication |
|
+ * 800-131Ar2, Section 1.2.2 say that any algorithm at a security |
|
+ * strength < 112 bits is legacy use only, so all derived keys should |
|
+ * be longer than that. If a derived key has ever been shorter than |
|
+ * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we |
|
+ * should also set the returned FIPS indicator to unapproved. */ |
|
+ if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Validation Program, Section C.C: "The SHAKE128 and SHAKE256 |
|
+ * extendable-output functions may only be used as the standalone |
|
+ * algorithms." */ |
|
+ if (ctx->macctx == NULL |
|
+ || (ctx->macctx != NULL && |
|
+ EVP_MAC_is_a(EVP_MAC_CTX_get0_mac(ctx->macctx), OSSL_MAC_NAME_HMAC))) { |
|
+ if (ctx->digest.md != NULL |
|
+ && (EVP_MD_is_a(ctx->digest.md, "SHAKE-128") || |
|
+ EVP_MD_is_a(ctx->digest.md, "SHAKE-256"))) { |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ |
|
+ /* Table H-3 in ANS X9.63-2001 says that 160-bit hash functions |
|
+ * should only be used for 80-bit key agreement, but FIPS 140-3 |
|
+ * requires a security strength of 112 bits, so SHA-1 cannot be |
|
+ * used with X9.63. See the discussion in |
|
+ * https://github.com/usnistgov/ACVP/issues/1403#issuecomment-1435300395. |
|
+ */ |
|
+ if (ctx->is_x963kdf |
|
+ && ctx->digest.md != NULL |
|
+ && EVP_MD_is_a(ctx->digest.md, "SHA-1")) { |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ } |
|
+ |
|
+ if (!OSSL_PARAM_set_int(p, fips_indicator)) |
|
+ return 0; |
|
+ } |
|
+#endif |
|
+ |
|
+ if (!any_valid) |
|
+ return -2; |
|
+ |
|
+ return 1; |
|
} |
|
|
|
static const OSSL_PARAM *sskdf_gettable_ctx_params(ossl_unused void *ctx, |
|
@@ -525,6 +614,9 @@ static const OSSL_PARAM *sskdf_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, 0), |
|
+#endif /* defined(FIPS_MODULE) */ |
|
OSSL_PARAM_END |
|
}; |
|
return known_gettable_ctx_params; |
|
@@ -545,7 +637,7 @@ const OSSL_DISPATCH ossl_kdf_sskdf_functions[] = { |
|
}; |
|
|
|
const OSSL_DISPATCH ossl_kdf_x963_kdf_functions[] = { |
|
- { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))sskdf_new }, |
|
+ { OSSL_FUNC_KDF_NEWCTX, (void(*)(void))x963kdf_new }, |
|
{ OSSL_FUNC_KDF_FREECTX, (void(*)(void))sskdf_free }, |
|
{ OSSL_FUNC_KDF_RESET, (void(*)(void))sskdf_reset }, |
|
{ OSSL_FUNC_KDF_DERIVE, (void(*)(void))x963kdf_derive }, |
|
diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c |
|
index a4d64b9352..f6782a6ca2 100644 |
|
--- a/providers/implementations/kdfs/tls1_prf.c |
|
+++ b/providers/implementations/kdfs/tls1_prf.c |
|
@@ -93,6 +93,13 @@ typedef struct { |
|
/* Buffer of concatenated seed data */ |
|
unsigned char seed[TLS1_PRF_MAXBUF]; |
|
size_t seedlen; |
|
+ |
|
+ /* MAC digest algorithm; used to compute FIPS indicator */ |
|
+ PROV_DIGEST digest; |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ int fips_indicator; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
} TLS1_PRF; |
|
|
|
static void *kdf_tls1_prf_new(void *provctx) |
|
@@ -129,6 +136,7 @@ static void kdf_tls1_prf_reset(void *vctx) |
|
EVP_MAC_CTX_free(ctx->P_sha1); |
|
OPENSSL_clear_free(ctx->sec, ctx->seclen); |
|
OPENSSL_cleanse(ctx->seed, ctx->seedlen); |
|
+ ossl_prov_digest_reset(&ctx->digest); |
|
memset(ctx, 0, sizeof(*ctx)); |
|
ctx->provctx = provctx; |
|
} |
|
@@ -157,6 +165,10 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); |
|
return 0; |
|
} |
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
|
|
return tls1_prf_alg(ctx->P_hash, ctx->P_sha1, |
|
ctx->sec, ctx->seclen, |
|
@@ -191,6 +203,9 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) |
|
} |
|
} |
|
|
|
+ if (!ossl_prov_digest_load_from_params(&ctx->digest, params, libctx)) |
|
+ return 0; |
|
+ |
|
if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET)) != NULL) { |
|
OPENSSL_clear_free(ctx->sec, ctx->seclen); |
|
ctx->sec = NULL; |
|
@@ -232,10 +247,60 @@ static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params( |
|
static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
|
{ |
|
OSSL_PARAM *p; |
|
+#ifdef FIPS_MODULE |
|
+ TLS1_PRF *ctx = vctx; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
+ int any_valid = 0; /* set to 1 when at least one parameter was valid */ |
|
+ |
|
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) { |
|
+ any_valid = 1; |
|
+ |
|
+ if (!OSSL_PARAM_set_size_t(p, SIZE_MAX)) |
|
+ return 0; |
|
+ } |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR); |
|
+ if (p != NULL) { |
|
+ int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED; |
|
+ |
|
+ any_valid = 1; |
|
+ |
|
+ /* 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". */ |
|
+ if (ctx->seclen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Verification Program, Section D.B and NIST Special Publication |
|
+ * 800-131Ar2, Section 1.2.2 say that any algorithm at a security |
|
+ * strength < 112 bits is legacy use only, so all derived keys should |
|
+ * be longer than that. If a derived key has ever been shorter than |
|
+ * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we |
|
+ * should also set the returned FIPS indicator to unapproved. */ |
|
+ if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* SP 800-135r1 section 4.2.2 says TLS 1.2 KDF is approved when "(3) |
|
+ * P_HASH uses either SHA-256, SHA-384 or SHA-512." */ |
|
+ if (ctx->digest.md != NULL |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-256") |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-384") |
|
+ && !EVP_MD_is_a(ctx->digest.md, "SHA2-512")) { |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ |
|
+ if (!OSSL_PARAM_set_int(p, fips_indicator)) |
|
+ return 0; |
|
+ } |
|
+#endif |
|
|
|
- if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) |
|
- return OSSL_PARAM_set_size_t(p, SIZE_MAX); |
|
- return -2; |
|
+ if (!any_valid) |
|
+ return -2; |
|
+ |
|
+ return 1; |
|
} |
|
|
|
static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params( |
|
@@ -243,6 +308,9 @@ static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params( |
|
{ |
|
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, 0), |
|
+#endif /* defined(FIPS_MODULE) */ |
|
OSSL_PARAM_END |
|
}; |
|
return known_gettable_ctx_params; |
|
diff --git a/providers/implementations/kdfs/x942kdf.c b/providers/implementations/kdfs/x942kdf.c |
|
index b1bc6f7e1b..8173fc2cc7 100644 |
|
--- a/providers/implementations/kdfs/x942kdf.c |
|
+++ b/providers/implementations/kdfs/x942kdf.c |
|
@@ -13,10 +13,13 @@ |
|
#include <openssl/core_dispatch.h> |
|
#include <openssl/err.h> |
|
#include <openssl/evp.h> |
|
+#include <openssl/kdf.h> |
|
#include <openssl/params.h> |
|
#include <openssl/proverr.h> |
|
#include "internal/packet.h" |
|
#include "internal/der.h" |
|
+#include "internal/nelem.h" |
|
+#include "crypto/evp.h" |
|
#include "prov/provider_ctx.h" |
|
#include "prov/providercommon.h" |
|
#include "prov/implementations.h" |
|
@@ -47,6 +50,9 @@ typedef struct { |
|
const unsigned char *cek_oid; |
|
size_t cek_oid_len; |
|
int use_keybits; |
|
+#ifdef FIPS_MODULE |
|
+ int fips_indicator; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
} KDF_X942; |
|
|
|
/* |
|
@@ -460,6 +466,10 @@ static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen, |
|
ERR_raise(ERR_LIB_PROV, PROV_R_BAD_ENCODING); |
|
return 0; |
|
} |
|
+#ifdef FIPS_MODULE |
|
+ if (keylen < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ ctx->fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+#endif /* defined(FIPS_MODULE) */ |
|
ret = x942kdf_hash_kdm(md, ctx->secret, ctx->secret_len, |
|
der, der_len, ctr, key, keylen); |
|
OPENSSL_free(der); |
|
@@ -563,10 +573,58 @@ static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[]) |
|
{ |
|
KDF_X942 *ctx = (KDF_X942 *)vctx; |
|
OSSL_PARAM *p; |
|
+ int any_valid = 0; /* set to 1 when at least one parameter was valid */ |
|
|
|
- if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) |
|
- return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx)); |
|
- return -2; |
|
+ if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) { |
|
+ any_valid = 1; |
|
+ |
|
+ if (!OSSL_PARAM_set_size_t(p, x942kdf_size(ctx))) |
|
+ return 0; |
|
+ } |
|
+ |
|
+#ifdef FIPS_MODULE |
|
+ p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_REDHAT_FIPS_INDICATOR); |
|
+ if (p != NULL) { |
|
+ int fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_APPROVED; |
|
+ |
|
+ any_valid = 1; |
|
+ |
|
+ /* 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". */ |
|
+ if (ctx->secret_len < EVP_KDF_FIPS_MIN_KEY_LEN) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Verification Program, Section D.B and NIST Special Publication |
|
+ * 800-131Ar2, Section 1.2.2 say that any algorithm at a security |
|
+ * strength < 112 bits is legacy use only, so all derived keys should |
|
+ * be longer than that. If a derived key has ever been shorter than |
|
+ * that, ctx->output_keyelen_indicator will be NOT_APPROVED, and we |
|
+ * should also set the returned FIPS indicator to unapproved. */ |
|
+ if (ctx->fips_indicator == EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED) |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ |
|
+ /* Implementation Guidance for FIPS 140-3 and the Cryptographic Module |
|
+ * Validation Program, Section C.C: "The SHAKE128 and SHAKE256 |
|
+ * extendable-output functions may only be used as the standalone |
|
+ * algorithms." */ |
|
+ if (ctx->digest.md != NULL |
|
+ && (EVP_MD_is_a(ctx->digest.md, "SHAKE-128") || |
|
+ EVP_MD_is_a(ctx->digest.md, "SHAKE-256"))) { |
|
+ fips_indicator = EVP_KDF_REDHAT_FIPS_INDICATOR_NOT_APPROVED; |
|
+ } |
|
+ |
|
+ if (!OSSL_PARAM_set_int(p, fips_indicator)) |
|
+ return 0; |
|
+ } |
|
+#endif |
|
+ |
|
+ if (!any_valid) |
|
+ return -2; |
|
+ |
|
+ return 1; |
|
} |
|
|
|
static const OSSL_PARAM *x942kdf_gettable_ctx_params(ossl_unused void *ctx, |
|
@@ -574,6 +632,9 @@ static const OSSL_PARAM *x942kdf_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, 0), |
|
+#endif /* defined(FIPS_MODULE) */ |
|
OSSL_PARAM_END |
|
}; |
|
return known_gettable_ctx_params; |
|
-- |
|
2.39.2 |
|
|
|
|