]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
kdfs: implement key length check in X9.42
authorDimitri John Ledkov <dimitri.ledkov@surgut.co.uk>
Sat, 21 Sep 2024 14:25:53 +0000 (15:25 +0100)
committerTomas Mraz <tomas@openssl.org>
Mon, 30 Sep 2024 18:03:49 +0000 (20:03 +0200)
Similar to other KDFs, the input key should be 112 bits long.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25529)

apps/fipsinstall.c
doc/man1/openssl-fipsinstall.pod.in
doc/man5/fips_config.pod
doc/man7/EVP_KDF-X942-ASN1.pod
providers/fips/include/fips_indicator_params.inc
providers/implementations/kdfs/x942kdf.c
test/recipes/03-test_fipsinstall.t
test/recipes/30-test_evp_data/evpkdf_x942.txt
util/mk-fipsmodule-cnf.pl
util/perl/OpenSSL/paramnames.pm

index 94ca7656c61abd70c62f773e55343e81fbda2458..203f397a481dac8bd9377834c7bd5be7012ef45a 100644 (file)
@@ -59,6 +59,7 @@ typedef enum OPTION_choice {
     OPT_SSHKDF_KEY_CHECK,
     OPT_SSKDF_KEY_CHECK,
     OPT_X963KDF_KEY_CHECK,
+    OPT_X942KDF_KEY_CHECK,
     OPT_NO_PBKDF2_LOWER_BOUND_CHECK,
     OPT_ECDH_COFACTOR_CHECK,
     OPT_SELF_TEST_ONLOAD, OPT_SELF_TEST_ONINSTALL
@@ -128,6 +129,8 @@ const OPTIONS fipsinstall_options[] = {
      "Enable key check for SSKDF"},
     {"x963kdf_key_check", OPT_X963KDF_KEY_CHECK, '-',
      "Enable key check for X963KDF"},
+    {"x942kdf_key_check", OPT_X942KDF_KEY_CHECK, '-',
+     "Enable key check for X942KDF"},
     {"no_pbkdf2_lower_bound_check", OPT_NO_PBKDF2_LOWER_BOUND_CHECK, '-',
      "Disable lower bound check for PBKDF2"},
     {"ecdh_cofactor_check", OPT_ECDH_COFACTOR_CHECK, '-',
@@ -176,6 +179,7 @@ typedef struct {
     unsigned int sshkdf_key_check : 1;
     unsigned int sskdf_key_check : 1;
     unsigned int x963kdf_key_check : 1;
+    unsigned int x942kdf_key_check : 1;
     unsigned int pbkdf2_lower_bound_check : 1;
     unsigned int ecdh_cofactor_check : 1;
 } FIPS_OPTS;
@@ -209,6 +213,7 @@ static const FIPS_OPTS pedantic_opts = {
     1,      /* sshkdf_key_check */
     1,      /* sskdf_key_check */
     1,      /* x963kdf_key_check */
+    1,      /* x942kdf_key_check */
     1,      /* pbkdf2_lower_bound_check */
     1,      /* ecdh_cofactor_check */
 };
@@ -242,6 +247,7 @@ static FIPS_OPTS fips_opts = {
     0,      /* sshkdf_key_check */
     0,      /* sskdf_key_check */
     0,      /* x963kdf_key_check */
+    0,      /* x942kdf_key_check */
     1,      /* pbkdf2_lower_bound_check */
     0,      /* ecdh_cofactor_check */
 };
@@ -419,6 +425,8 @@ static int write_config_fips_section(BIO *out, const char *section,
                       opts->sskdf_key_check ? "1": "0") <= 0
         || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_X963KDF_KEY_CHECK,
                       opts->x963kdf_key_check ? "1": "0") <= 0
+        || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_X942KDF_KEY_CHECK,
+                      opts->x942kdf_key_check ? "1": "0") <= 0
         || BIO_printf(out, "%s = %s\n",
                       OSSL_PROV_PARAM_PBKDF2_LOWER_BOUND_CHECK,
                       opts->pbkdf2_lower_bound_check ? "1" : "0") <= 0
@@ -676,6 +684,9 @@ int fipsinstall_main(int argc, char **argv)
         case OPT_X963KDF_KEY_CHECK:
             fips_opts.x963kdf_key_check = 1;
             break;
+        case OPT_X942KDF_KEY_CHECK:
+            fips_opts.x942kdf_key_check = 1;
+            break;
         case OPT_NO_PBKDF2_LOWER_BOUND_CHECK:
             if (!check_non_pedantic_fips(pedantic, "no_pbkdf2_lower_bound_check"))
                 goto end;
index 6057aa5316e9e1ab060b752fc261659f5c4c4cf9..165179395b85bf362bb730ce0b1f921217c2b1d6 100644 (file)
@@ -47,6 +47,7 @@ B<openssl fipsinstall>
 [B<-sshkdf_key_check>]
 [B<-sskdf_key_check>]
 [B<-x963kdf_key_check>]
+[B<-x942kdf_key_check>]
 [B<-ecdh_cofactor_check>]
 [B<-self_test_onload>]
 [B<-self_test_oninstall>]
@@ -340,6 +341,12 @@ Configure the module to enable a run-time short key-derivation key check when
 deriving a key by X963KDF.
 See NIST SP 800-131Ar2 for details.
 
+=item B<-x942kdf_key_check>
+
+Configure the module to enable a run-time short key-derivation key check when
+deriving a key by X942KDF.
+See NIST SP 800-131Ar2 for details.
+
 =item B<-no_pbkdf2_lower_bound_check>
 
 Configure the module to not perform run-time lower bound check for PBKDF2.
index ef6f591184ffc2a7bd723cd52a659d6f9030e880..a25ced3383937aebf19773bd981411ac77c16004 100644 (file)
@@ -182,6 +182,10 @@ See L<openssl-fipsinstall(1)/OPTIONS> B<-sskdf_key_check>
 
 See L<openssl-fipsinstall(1)/OPTIONS> B<-x963kdf_key_check>
 
+=item B<x942kdf-key-check>
+
+See L<openssl-fipsinstall(1)/OPTIONS> B<-x942kdf_key_check>
+
 =item B<pbkdf2-lower-bound-check>
 
 See L<openssl-fipsinstall(1)/OPTIONS> B<-no_pbkdf2_lower_bound_check>
index b13610dc032f2035e024fae5efb29a940e987495..3f62b8b82e7004f2454c0005478c567cd03422f3 100644 (file)
@@ -77,6 +77,28 @@ Valid values are "AES-128-WRAP", "AES-192-WRAP", "AES-256-WRAP" and "DES3-WRAP".
 
 =back
 
+The OpenSSL FIPS provider also supports the following parameters:
+
+=over 4
+
+=item "fips-indicator" (B<OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR>) <integer>
+
+A getter that returns 1 if the operation is FIPS approved, or 0 otherwise.
+This may be used after calling EVP_KDF_derive. It returns 0 if "key-check"
+parameter is set to 0 and the check fails.
+
+=item "key-check" (B<OSSL_KDF_PARAM_FIPS_KEY_CHECK>) <integer>
+
+The default value of 1 causes an error during EVP_KDF_CTX_set_params() if the
+length of used key-derivation key (B<OSSL_KDF_PARAM_KEY>) is shorter than 112
+bits.
+Setting this to zero will ignore the error and set the approved
+"fips-indicator" to 0.
+This option breaks FIPS compliance if it causes the approved "fips-indicator"
+to return 0.
+
+=back
+
 =head1 NOTES
 
 A context for X942KDF can be obtained by calling:
index c1d12c32a649598b60d9b35d6540ad09d9356b89..78f9fc06551bf58d8569d889e48bc7d74a78b606 100644 (file)
@@ -23,5 +23,6 @@ OSSL_FIPS_PARAM(tls1_prf_key_check, TLS1_PRF_KEY_CHECK, 0)
 OSSL_FIPS_PARAM(sshkdf_key_check, SSHKDF_KEY_CHECK, 0)
 OSSL_FIPS_PARAM(sskdf_key_check, SSKDF_KEY_CHECK, 0)
 OSSL_FIPS_PARAM(x963kdf_key_check, X963KDF_KEY_CHECK, 0)
+OSSL_FIPS_PARAM(x942kdf_key_check, X942KDF_KEY_CHECK, 0)
 OSSL_FIPS_PARAM(pbkdf2_lower_bound_check, PBKDF2_LOWER_BOUND_CHECK, 1)
 OSSL_FIPS_PARAM(ecdh_cofactor_check, ECDH_COFACTOR_CHECK, 0)
index 51117c530f962a2a699696992f72f852882ad0b7..8b72a6a9f257936c013ee8fbd574455ac7e564ee 100644 (file)
@@ -22,6 +22,7 @@
 #include "prov/providercommon.h"
 #include "prov/implementations.h"
 #include "prov/provider_util.h"
+#include "prov/securitycheck.h"
 #include "prov/der_wrap.h"
 
 #define X942KDF_MAX_INLEN (1 << 30)
@@ -49,6 +50,7 @@ typedef struct {
     const unsigned char *cek_oid;
     size_t cek_oid_len;
     int use_keybits;
+    OSSL_FIPS_IND_DECLARE
 } KDF_X942;
 
 /*
@@ -336,9 +338,12 @@ static void *x942kdf_new(void *provctx)
     if (!ossl_prov_is_running())
         return NULL;
 
-    if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) == NULL)
+    ctx = OPENSSL_zalloc(sizeof(*ctx));
+    if (ctx == NULL)
         return NULL;
+
     ctx->provctx = provctx;
+    OSSL_FIPS_IND_INIT(ctx)
     ctx->use_keybits = 1;
     return ctx;
 }
@@ -397,6 +402,7 @@ static void *x942kdf_dup(void *vctx)
         dest->cek_oid_len = src->cek_oid_len;
         dest->dkm_len = src->dkm_len;
         dest->use_keybits = src->use_keybits;
+        OSSL_FIPS_IND_COPY(dest, src)
     }
     return dest;
 
@@ -429,6 +435,24 @@ static size_t x942kdf_size(KDF_X942 *ctx)
     return (len <= 0) ? 0 : (size_t)len;
 }
 
+#ifdef FIPS_MODULE
+static int fips_x942kdf_key_check_passed(KDF_X942 *ctx)
+{
+    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
+    int key_approved = ossl_kdf_check_key_size(ctx->secret_len);
+
+    if (!key_approved) {
+        if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0,
+                                         libctx, "X942KDF", "Key size",
+                                         ossl_fips_config_x942kdf_key_check)) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+            return 0;
+        }
+    }
+    return 1;
+}
+#endif
+
 static int x942kdf_derive(void *vctx, unsigned char *key, size_t keylen,
                           const OSSL_PARAM params[])
 {
@@ -513,6 +537,10 @@ static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     if (params == NULL)
         return 1;
 
+    if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params,
+                                     OSSL_KDF_PARAM_FIPS_KEY_CHECK))
+        return 0;
+
     if (OSSL_PARAM_locate_const(params, OSSL_ALG_PARAM_DIGEST) != NULL) {
         if (!ossl_prov_digest_load_from_params(&ctx->digest, params, provctx))
             return 0;
@@ -526,8 +554,14 @@ static int x942kdf_set_ctx_params(void *vctx, const OSSL_PARAM params[])
     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_SECRET);
     if (p == NULL)
         p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_KEY);
-    if (p != NULL && !x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p))
-        return 0;
+    if (p != NULL) {
+        if (!x942kdf_set_buffer(&ctx->secret, &ctx->secret_len, p))
+            return 0;
+#ifdef FIPS_MODULE
+        if (!fips_x942kdf_key_check_passed(ctx))
+            return 0;
+#endif
+    }
 
     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_X942_ACVPINFO);
     if (p != NULL
@@ -598,6 +632,7 @@ static const OSSL_PARAM *x942kdf_settable_ctx_params(ossl_unused void *ctx,
         OSSL_PARAM_octet_string(OSSL_KDF_PARAM_X942_SUPP_PRIVINFO, NULL, 0),
         OSSL_PARAM_int(OSSL_KDF_PARAM_X942_USE_KEYBITS, NULL),
         OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0),
+        OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_KEY_CHECK)
         OSSL_PARAM_END
     };
     return known_settable_ctx_params;
@@ -608,9 +643,13 @@ static int x942kdf_get_ctx_params(void *vctx, OSSL_PARAM params[])
     KDF_X942 *ctx = (KDF_X942 *)vctx;
     OSSL_PARAM *p;
 
-    if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL)
-        return OSSL_PARAM_set_size_t(p, x942kdf_size(ctx));
-    return -2;
+    p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE);
+    if (p != NULL && !OSSL_PARAM_set_size_t(p, x942kdf_size(ctx)))
+        return 0;
+
+    if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params))
+        return 0;
+    return 1;
 }
 
 static const OSSL_PARAM *x942kdf_gettable_ctx_params(ossl_unused void *ctx,
@@ -618,6 +657,7 @@ 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),
+        OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
         OSSL_PARAM_END
     };
     return known_gettable_ctx_params;
index f4dcb4bda026ee1480185f7826487ad1cae37192..4965b9e63dbbd26f5703ce17ff7eadf8e39f98b1 100644 (file)
@@ -59,7 +59,8 @@ my @commandline =
         ( 'tls1_prf_key_check',             'tls1-prf-key-check' ),
         ( 'sshkdf_key_check',               'sshkdf-key-check' ),
         ( 'sskdf_key_check',                'sskdf-key-check' ),
-        ( 'x963kdf_key_check',              'x963kdf-key-check' )
+        ( 'x963kdf_key_check',              'x963kdf-key-check' ),
+        ( 'x942kdf_key_check',              'x942kdf-key-check' )
     );
 
 plan tests => 35 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
index 3cf2fffe12f390a865dfcfedb5b13177a0194c68..b1774592e92818877342c4a0e4ea4a438ddb90a7 100644 (file)
@@ -77,6 +77,7 @@ Output = 2c5c1f028c6d1fc9ba752e41fdb9edb2ea936f1b2449f214acd56d31
 
 Title = X9.42 KDF tests (ACVP test vectors)
 
+FIPSversion = <3.4.0
 KDF = X942KDF-ASN1
 Ctrl.digest = digest:SHA256
 Ctrl.hexsecret = hexsecret:6B
@@ -88,6 +89,7 @@ Output = C2E6A0978C24AF3932F478583ADBFB5F57D491822592EAD3C538875F46EB057A
 # Negative tests
 
 # Fail if both acvp and ukm values are specified.
+FIPSversion = <3.4.0
 KDF = X942KDF-ASN1
 Ctrl.digest = digest:SHA256
 Ctrl.hexsecret = hexsecret:6B
@@ -118,3 +120,15 @@ Ctrl.cekalg = cekalg:id-aes128-wrap
 Ctrl.hexacvp-info = hexacvp-info:a020299D468D60BC6A257E0B6523D691A3FC1602453B35F308C762FBBAC6069A88BCa12080D49BFE5BE01C7D56489AB017663C22B8CBB34C3174D1D71F00CB7505AC759Aa2203C21A5EA5988562C007986E0503D039E7231D9F152FE72A231A1FD98C59BCA6Aa320FD47477542989B51E4A0845DFABD6EEAA465F69B3D75349B2520051782C7F3FC
 Result = KDF_CTRL_ERROR
 Reason = xof digests not allowed
+
+Availablein = fips
+FIPSversion = >=3.4.0
+KDF = X942KDF-ASN1
+Ctrl.digest = digest:SHA256
+Ctrl.hexsecret = hexsecret:6B
+Ctrl.use-keybits = use-keybits:0
+Ctrl.cekalg = cekalg:id-aes128-wrap
+Ctrl.hexacvp-info = hexacvp-info:a020299D468D60BC6A257E0B6523D691A3FC1602453B35F308C762FBBAC6069A88BCa12080D49BFE5BE01C7D56489AB017663C22B8CBB34C3174D1D71F00CB7505AC759Aa2203C21A5EA5988562C007986E0503D039E7231D9F152FE72A231A1FD98C59BCA6Aa320FD47477542989B51E4A0845DFABD6EEAA465F69B3D75349B2520051782C7F3FC
+Output = C2E6A0978C24AF3932F478583ADBFB5F57D491822592EAD3C538875F46EB057A
+Result = KDF_CTRL_ERROR
+Reason = invalid key length
index 2c63e5a51a45f43b0fabb996e51e90a923e82e86..6908592fc5bf65e63000f3ce3e365b017fbfb319 100644 (file)
@@ -81,6 +81,7 @@ tls1-prf-key-check = $kdf_key_check
 sshkdf-key-check = $kdf_key_check
 sskdf-key-check = $kdf_key_check
 x963kdf-key-check = $kdf_key_check
+x942kdf-key-check = $kdf_key_check
 pbkdf2-lower-bound-check = $pbkdf2_lower_bound_check
 ecdh-cofactor-check = $ec_cofactor_check
 hmac-key-check = $mac_key_check
index 0701064ccfcd67a36ae4809f48d7c76ad7caa8a3..e67f0f2beb29bf0ccb04ee3e33aaf54ee349893c 100644 (file)
@@ -54,6 +54,7 @@ my %params = (
     'PROV_PARAM_SSHKDF_KEY_CHECK' =>       "sshkdf-key-check",       # uint
     'PROV_PARAM_SSKDF_KEY_CHECK' =>        "sskdf-key-check",        # uint
     'PROV_PARAM_X963KDF_KEY_CHECK' =>      "x963kdf-key-check",      # uint
+    'PROV_PARAM_X942KDF_KEY_CHECK' =>      "x942kdf-key-check",      # uint
     'PROV_PARAM_PBKDF2_LOWER_BOUND_CHECK' => "pbkdf2-lower-bound-check", # uint
     'PROV_PARAM_ECDH_COFACTOR_CHECK' =>    "ecdh-cofactor-check",    # uint
     'PROV_PARAM_SIGNATURE_DIGEST_CHECK' => "signature-digest-check", # uint