]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add HMAC FIPS keysize check.
authorslontis <shane.lontis@oracle.com>
Wed, 31 Jul 2024 04:56:44 +0000 (14:56 +1000)
committerTomas Mraz <tomas@openssl.org>
Wed, 21 Aug 2024 13:34:40 +0000 (15:34 +0200)
HMAC has been changed to use a FIPS indicator for its key check.

HKDF and Single Step use a salt rather than a key when using HMAC,
so we need a mechanism to bypass this check in HMAC.

A seperate 'internal' query table has been added to the FIPS provider
for MACS. Giving HMAC a seprate dispatch table allows KDF's to ignore
the key check. If a KDF requires the key check then it must do the
check itself. The normal MAC dipatch table is used if the user fetches
HMAC directly.

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/25049)

17 files changed:
apps/fipsinstall.c
doc/man1/openssl-fipsinstall.pod.in
doc/man7/EVP_MAC-HMAC.pod
doc/man7/provider-mac.pod
include/openssl/fips_names.h
providers/common/include/prov/fipscommon.h
providers/common/include/prov/fipsindicator.h
providers/common/include/prov/securitycheck.h
providers/common/securitycheck.c
providers/fips/fipsprov.c
providers/implementations/include/prov/implementations.h
providers/implementations/kdfs/hkdf.c
providers/implementations/macs/hmac_prov.c
test/evp_test.c
test/recipes/30-test_evp_data/evpmac_common.txt
util/mk-fipsmodule-cnf.pl
util/perl/OpenSSL/paramnames.pm

index 4d0f9168791d9e399773de9d91efb2735ac16f2e..237a0bba84c551733a657c53c3ff156ae0b11fbf 100644 (file)
@@ -41,6 +41,7 @@ typedef enum OPTION_choice {
     OPT_TLS_PRF_EMS_CHECK, OPT_NO_SHORT_MAC,
     OPT_DISALLOW_PKCS15_PADDING, OPT_RSA_PSS_SALTLEN_CHECK,
     OPT_DISALLOW_SIGNATURE_X931_PADDING,
+    OPT_HMAC_KEY_CHECK,
     OPT_DISALLOW_DRGB_TRUNC_DIGEST,
     OPT_SIGNATURE_DIGEST_CHECK,
     OPT_HKDF_DIGEST_CHECK,
@@ -89,6 +90,7 @@ const OPTIONS fipsinstall_options[] = {
      "Disallow truncated digests with Hash and HMAC DRBGs"},
     {"signature_digest_check", OPT_SIGNATURE_DIGEST_CHECK, '-',
      "Enable checking for approved digests for signatures"},
+    {"hmac_key_check", OPT_HMAC_KEY_CHECK, '-', "Enable key check for HMAC"},
     {"hkdf_digest_check", OPT_HKDF_DIGEST_CHECK, '-',
      "Enable digest check for HKDF"},
     {"tls13_kdf_digest_check", OPT_TLS13_KDF_DIGEST_CHECK, '-',
@@ -149,6 +151,7 @@ typedef struct {
     unsigned int self_test_onload : 1;
     unsigned int conditional_errors : 1;
     unsigned int security_checks : 1;
+    unsigned int hmac_key_check : 1;
     unsigned int tls_prf_ems_check : 1;
     unsigned int no_short_mac : 1;
     unsigned int drgb_no_trunc_dgst : 1;
@@ -180,6 +183,7 @@ static const FIPS_OPTS pedantic_opts = {
     1,      /* self_test_onload */
     1,      /* conditional_errors */
     1,      /* security_checks */
+    1,      /* hmac_key_check */
     1,      /* tls_prf_ems_check */
     1,      /* no_short_mac */
     1,      /* drgb_no_trunc_dgst */
@@ -211,6 +215,7 @@ static FIPS_OPTS fips_opts = {
     1,      /* self_test_onload */
     1,      /* conditional_errors */
     1,      /* security_checks */
+    0,      /* hmac_key_check */
     0,      /* tls_prf_ems_check */
     0,      /* no_short_mac */
     0,      /* drgb_no_trunc_dgst */
@@ -354,6 +359,8 @@ static int write_config_fips_section(BIO *out, const char *section,
                       opts->conditional_errors ? "1" : "0") <= 0
         || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
                       opts->security_checks ? "1" : "0") <= 0
+        || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_HMAC_KEY_CHECK,
+                      opts->hmac_key_check ? "1": "0") <= 0
         || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK,
                       opts->tls_prf_ems_check ? "1" : "0") <= 0
         || BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_NO_SHORT_MAC,
@@ -591,6 +598,9 @@ int fipsinstall_main(int argc, char **argv)
                 goto end;
             fips_opts.security_checks = 0;
             break;
+        case OPT_HMAC_KEY_CHECK:
+            fips_opts.hmac_key_check = 1;
+            break;
         case OPT_TLS_PRF_EMS_CHECK:
             fips_opts.tls_prf_ems_check = 1;
             break;
index d601544b60cc73b022d5cb395bad839083494af0..413c49032931ec04f42eaf850470dfab5126a174 100644 (file)
@@ -22,6 +22,7 @@ B<openssl fipsinstall>
 [B<-pedantic>]
 [B<-no_conditional_errors>]
 [B<-no_security_checks>]
+[B<-hmac_key_check>]
 [B<-ems_check>]
 [B<-no_drbg_truncated_digests>]
 [B<-signature_digest_check>]
@@ -212,6 +213,11 @@ See RFC 7627 for information related to EMS.
 Configure the module to not allow short MAC outputs.
 See SP 800-185 8.4.2 and FIPS 140-3 ID C.D for details.
 
+=item B<-hmac_key_check>
+
+Configure the module to not allow small keys sizes when using HMAC.
+See SP 800-131Ar2 for details.
+
 =item B<-no_drbg_truncated_digests>
 
 Configure the module to not allow truncated digests to be used with Hash and
index 474f62bb493eb84579b19d55d63ec0bda3d93adf..69342c630cb2b3c478334cfb13903b677bd529cb 100644 (file)
@@ -27,7 +27,7 @@ used with EVP_MAC_fetch():
 The general description of these parameters can be found in
 L<EVP_MAC(3)/PARAMETERS>.
 
-The following parameter can be set with EVP_MAC_CTX_set_params():
+The following parameters can be set with EVP_MAC_CTX_set_params():
 
 =over 4
 
@@ -63,11 +63,15 @@ It may be set but is currently ignored.
 
 =item "tls-data-size" (B<OSSL_MAC_PARAM_TLS_DATA_SIZE>) <unsigned integer>
 
+=item "key-check" (B<OSSL_MAC_PARAM_FIPS_KEY_CHECK>) <integer>
+
+See L<provider-mac(7)/Mac Parameters>.
+
 =back
 
 =for comment The "flags" parameter is passed directly to HMAC_CTX_set_flags().
 
-The following parameter can be retrieved with EVP_MAC_CTX_get_params():
+The following parameters can be retrieved with EVP_MAC_CTX_get_params():
 
 =over 4
 
@@ -76,15 +80,15 @@ The following parameter can be retrieved with EVP_MAC_CTX_get_params():
 The "size" parameter can also be retrieved with EVP_MAC_CTX_get_mac_size().
 The length of the "size" parameter is equal to that of an B<unsigned int>.
 
-=back
-
-=over 4
-
 =item "block-size" (B<OSSL_MAC_PARAM_BLOCK_SIZE>) <unsigned integer>
 
 Gets the MAC block size.  The "block-size" parameter can also be retrieved with
 EVP_MAC_CTX_get_block_size().
 
+=item "fips-indicator" (B<OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR>) <integer>
+
+See L<provider-mac(7)/Mac Parameters>.
+
 =back
 
 =head1 SEE ALSO
index 13be4a7fc0889ad987a09478a12f6ee3a63107b5..15a86f51b4d0861ddd1551ae4ee6bf7224928f36 100644 (file)
@@ -196,9 +196,9 @@ Can be used to get the MAC block size (if supported by the algorithm).
 =item "fips-indicator" (B<OSSL_MAC_PARAM_FIPS_APPROVED_INDICATOR>) <int>
 
 A getter that returns 1 if the operation is FIPS approved, or 0 otherwise.
-This may be used after calling the final function.  It may return 0 if
-"no-short-mac" are set to 0.  This option is used by the OpenSSL FIPS
-provider.
+This may be used after calling the final function. It may return 0 if
+either "no-short-mac" or "key-check" are set to 0.
+This option is used by the OpenSSL FIPS provider.
 
 =back
 
@@ -212,6 +212,14 @@ asked for.  Setting this to 0 will ignore the error and set the approved
 "fips-indicator" to 0.  This option is used by the OpenSSL FIPS provider,
 and breaks FIPS compliance if set to 0.
 
+=item "key-check" (B<OSSL_MAC_PARAM_FIPS_KEY_CHECK>) <integer>
+
+If required this parameter should be set before OSSL_FUNC_mac_init.
+The default value of 1 causes an error when small key sizes are
+asked for.  Setting this to 0 will ignore the error and set the approved
+"fips-indicator" to 0.  This option is used by the OpenSSL FIPS provider,
+and breaks FIPS compliance if set to 0.
+
 =back
 
 =back
index a94c4d2b1d7fc04407eab36e9d65c68770752601..203ef54fe90205df8417848993362dfd2b745490 100644 (file)
@@ -67,7 +67,15 @@ extern "C" {
  * This is enabled by default.
  * Type: OSSL_PARAM_UTF8_STRING
  */
-#define OSSL_PROV_FIPS_PARAM_NO_SHORT_MAC "no-short-mac"
+# define OSSL_PROV_FIPS_PARAM_NO_SHORT_MAC "no-short-mac"
+
+/*
+ * A boolean that determines if the runtime FIPS key check for HMAC is
+ * performed.
+ * This is enabled by default.
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_HMAC_KEY_CHECK "hmac-key-check"
 
 /*
  * A boolean that determines if truncated digests can be used with Hash and HMAC
index 44e8c2ecf81b03dce20522afa5469115bb6ca0b3..40e09f946e7b7a7ed201f80f4023ba272609d2d6 100644 (file)
@@ -13,6 +13,7 @@
 int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
 int FIPS_tls_prf_ems_check(OSSL_LIB_CTX *libctx);
 int FIPS_no_short_mac(OSSL_LIB_CTX *libctx);
+int FIPS_hmac_key_check(OSSL_LIB_CTX *libctx);
 int FIPS_restricted_drbg_digests_enabled(OSSL_LIB_CTX *libctx);
 int FIPS_fips_signature_digest_check(OSSL_LIB_CTX *libctx);
 int FIPS_hkdf_digest_check(OSSL_LIB_CTX *libctx);
index 4d674643b14d8e7f028700fe96379f571e29b98a..8f97bc35d9060122ab9b4ebacaea521e93633056 100644 (file)
@@ -114,12 +114,12 @@ void ossl_FIPS_IND_copy(OSSL_FIPS_IND *dst, const OSSL_FIPS_IND *src);
 # define OSSL_FIPS_IND_GET_CTX_PARAM(ctx, prms) \
     ossl_FIPS_IND_get_ctx_param(&((ctx)->indicator), prms)
 
-# define OSSL_FIPS_IND_GET(ctx) &((ctx)->indicator)
+# define OSSL_FIPS_IND_GET(ctx) (&((ctx)->indicator))
 
 # define OSSL_FIPS_IND_GET_PARAM(ctx, p, settable, id, name)                   \
     *settable = ossl_FIPS_IND_get_settable(&((ctx)->indicator), id);           \
     if (*settable != OSSL_FIPS_IND_STATE_UNKNOWN)                              \
-        *p = OSSL_PARAM_construct_int(name, settable);                         \
+        *p = OSSL_PARAM_construct_int(name, settable);
 
 int ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx,
                                 const RSA *rsa, const char *desc, int protect);
index a9cb3c570db3b5b227071e3569e6b33d1bd8b30e..a932c7771de081237c036d63bbf5f40a14f48589 100644 (file)
@@ -18,6 +18,7 @@
 int ossl_rsa_key_op_get_protect(const RSA *rsa, int operation, int *outprotect);
 int ossl_rsa_check_key_size(const RSA *rsa, int protect);
 int ossl_kdf_check_key_size(size_t keylen);
+int ossl_mac_check_key_size(size_t keylen);
 
 #ifndef OPENSSL_NO_EC
 int ossl_ec_check_curve_allowed(const EC_GROUP *group);
index 0831ef32043545b394ac6d795441ad72a8953bcf..fc22d5c3a094a03f6808c8cda4162f7f33898c33 100644 (file)
@@ -21,6 +21,8 @@
 #include "prov/securitycheck.h"
 #include "prov/fipsindicator.h"
 
+#define OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS 112
+
 int ossl_rsa_key_op_get_protect(const RSA *rsa, int operation, int *outprotect)
 {
     int protect = 0;
@@ -78,7 +80,12 @@ int ossl_rsa_check_key_size(const RSA *rsa, int protect)
  */
 int ossl_kdf_check_key_size(size_t keylen)
 {
-    return (keylen * 8) >= 112;
+    return (keylen * 8) >= OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS;
+}
+
+int ossl_mac_check_key_size(size_t keylen)
+{
+    return ossl_kdf_check_key_size(keylen);
 }
 
 #ifndef OPENSSL_NO_EC
@@ -126,7 +133,7 @@ int ossl_ec_check_security_strength(const EC_GROUP *group, int protect)
      * For signing or key agreement only allow curves with at least 112 bits of
      * security strength
      */
-    if (protect && strength < 112)
+    if (protect && strength < OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS)
         return 0;
     return 1;
 }
index 5a016f70c021884a878269775e427c9c9a741525..e72faf417389de7e49e799fe23d804f3634ee58a 100644 (file)
@@ -40,6 +40,7 @@ static OSSL_FUNC_provider_teardown_fn fips_teardown;
 static OSSL_FUNC_provider_gettable_params_fn fips_gettable_params;
 static OSSL_FUNC_provider_get_params_fn fips_get_params;
 static OSSL_FUNC_provider_query_operation_fn fips_query;
+static OSSL_FUNC_provider_query_operation_fn fips_query_internal;
 
 #define ALGC(NAMES, FUNC, CHECK)                \
     { { NAMES, FIPS_DEFAULT_PROPERTIES, FUNC }, CHECK }
@@ -89,6 +90,7 @@ typedef struct fips_global_st {
     FIPS_OPTION fips_security_checks;
     FIPS_OPTION fips_tls1_prf_ems_check;
     FIPS_OPTION fips_no_short_mac;
+    FIPS_OPTION fips_hmac_key_check;
     FIPS_OPTION fips_restricted_drgb_digests;
     FIPS_OPTION fips_signature_digest_check;
     FIPS_OPTION fips_hkdf_digest_check;
@@ -128,6 +130,7 @@ void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
     init_fips_option(&fgbl->fips_security_checks, 1);
     init_fips_option(&fgbl->fips_tls1_prf_ems_check, 0); /* Disabled by default */
     init_fips_option(&fgbl->fips_no_short_mac, 1);
+    init_fips_option(&fgbl->fips_hmac_key_check, 0);
     init_fips_option(&fgbl->fips_restricted_drgb_digests, 0);
     init_fips_option(&fgbl->fips_signature_digest_check, 0);
     init_fips_option(&fgbl->fips_hkdf_digest_check, 0);
@@ -167,6 +170,7 @@ static const OSSL_PARAM fips_param_types[] = {
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_SECURITY_CHECKS, OSSL_PARAM_INTEGER, NULL, 0),
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK, OSSL_PARAM_INTEGER, NULL, 0),
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_NO_SHORT_MAC, OSSL_PARAM_INTEGER, NULL, 0),
+    OSSL_PARAM_DEFN(OSSL_PROV_PARAM_HMAC_KEY_CHECK, OSSL_PARAM_INTEGER, NULL, 0),
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST, OSSL_PARAM_INTEGER, NULL, 0),
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_HKDF_DIGEST_CHECK, OSSL_PARAM_INTEGER, NULL,
                     0),
@@ -243,6 +247,8 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
                         fips_tls1_prf_ems_check);
     FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_NO_SHORT_MAC,
                         fips_no_short_mac);
+    FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_HMAC_KEY_CHECK,
+                        fips_hmac_key_check);
     FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_DRBG_TRUNC_DIGEST,
                         fips_restricted_drgb_digests);
     FIPS_FEATURE_OPTION(fgbl, OSSL_PROV_FIPS_PARAM_SIGNATURE_DIGEST_CHECK,
@@ -334,6 +340,8 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[])
                      fips_tls1_prf_ems_check);
     FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_NO_SHORT_MAC,
                      fips_no_short_mac);
+    FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_HMAC_KEY_CHECK,
+                     fips_hmac_key_check);
     FIPS_FEATURE_GET(fgbl, OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST,
                      fips_restricted_drgb_digests);
     FIPS_FEATURE_GET(fgbl, OSSL_PROV_FIPS_PARAM_SIGNATURE_DIGEST_CHECK,
@@ -534,6 +542,15 @@ static const OSSL_ALGORITHM fips_macs[] = {
     { NULL, NULL, NULL }
 };
 
+static const OSSL_ALGORITHM fips_macs_internal[] = {
+#ifndef OPENSSL_NO_CMAC
+    { PROV_NAMES_CMAC, FIPS_DEFAULT_PROPERTIES, ossl_cmac_functions },
+#endif
+    { PROV_NAMES_HMAC, FIPS_DEFAULT_PROPERTIES, ossl_hmac_internal_functions },
+    { PROV_NAMES_KMAC_128, FIPS_DEFAULT_PROPERTIES, ossl_kmac128_functions },
+    { PROV_NAMES_KMAC_256, FIPS_DEFAULT_PROPERTIES, ossl_kmac256_functions },
+};
+
 static const OSSL_ALGORITHM fips_kdfs[] = {
     { PROV_NAMES_HKDF, FIPS_DEFAULT_PROPERTIES, ossl_kdf_hkdf_functions },
     { PROV_NAMES_TLS1_3_KDF, FIPS_DEFAULT_PROPERTIES,
@@ -705,6 +722,39 @@ static const OSSL_ALGORITHM *fips_query(void *provctx, int operation_id,
     return NULL;
 }
 
+static const OSSL_ALGORITHM *fips_query_internal(void *provctx, int operation_id,
+                                                 int *no_cache)
+{
+    *no_cache = 0;
+
+    if (!ossl_prov_is_running())
+        return NULL;
+
+    switch (operation_id) {
+    case OSSL_OP_DIGEST:
+        return fips_digests;
+    case OSSL_OP_CIPHER:
+        return exported_fips_ciphers;
+    case OSSL_OP_MAC:
+        return fips_macs_internal;
+    case OSSL_OP_KDF:
+        return fips_kdfs;
+    case OSSL_OP_RAND:
+        return fips_rands;
+    case OSSL_OP_KEYMGMT:
+        return fips_keymgmt;
+    case OSSL_OP_KEYEXCH:
+        return fips_keyexch;
+    case OSSL_OP_SIGNATURE:
+        return fips_signature;
+    case OSSL_OP_ASYM_CIPHER:
+        return fips_asym_cipher;
+    case OSSL_OP_KEM:
+        return fips_asym_kem;
+    }
+    return NULL;
+}
+
 static void fips_teardown(void *provctx)
 {
     OSSL_LIB_CTX_free(PROV_LIBCTX_OF(provctx));
@@ -735,7 +785,7 @@ static const OSSL_DISPATCH fips_dispatch_table[] = {
 /* Functions we provide to ourself */
 static const OSSL_DISPATCH intern_dispatch_table[] = {
     { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))fips_intern_teardown },
-    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query },
+    { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query_internal },
     OSSL_DISPATCH_END
 };
 
@@ -934,6 +984,7 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
     FIPS_SET_OPTION(fgbl, fips_security_checks);
     FIPS_SET_OPTION(fgbl, fips_tls1_prf_ems_check);
     FIPS_SET_OPTION(fgbl, fips_no_short_mac);
+    FIPS_SET_OPTION(fgbl, fips_hmac_key_check);
     FIPS_SET_OPTION(fgbl, fips_restricted_drgb_digests);
     FIPS_SET_OPTION(fgbl, fips_signature_digest_check);
     FIPS_SET_OPTION(fgbl, fips_hkdf_digest_check);
@@ -1162,6 +1213,7 @@ int BIO_snprintf(char *buf, size_t n, const char *format, ...)
 FIPS_FEATURE_CHECK(FIPS_security_check_enabled, fips_security_checks)
 FIPS_FEATURE_CHECK(FIPS_tls_prf_ems_check, fips_tls1_prf_ems_check)
 FIPS_FEATURE_CHECK(FIPS_no_short_mac, fips_no_short_mac)
+FIPS_FEATURE_CHECK(FIPS_hmac_key_check, fips_hmac_key_check)
 FIPS_FEATURE_CHECK(FIPS_restricted_drbg_digests_enabled,
                    fips_restricted_drgb_digests)
 FIPS_FEATURE_CHECK(FIPS_fips_signature_digest_check, fips_signature_digest_check)
index a2da68ed02e5c458c12ad608d13e2584af2c301b..6199292c53a33cbba3f6504cffa2769ad19f4436 100644 (file)
@@ -258,6 +258,9 @@ extern const OSSL_DISPATCH ossl_blake2smac_functions[];
 extern const OSSL_DISPATCH ossl_cmac_functions[];
 extern const OSSL_DISPATCH ossl_gmac_functions[];
 extern const OSSL_DISPATCH ossl_hmac_functions[];
+#ifdef FIPS_MODULE
+extern const OSSL_DISPATCH ossl_hmac_internal_functions[];
+#endif
 extern const OSSL_DISPATCH ossl_kmac128_functions[];
 extern const OSSL_DISPATCH ossl_kmac256_functions[];
 extern const OSSL_DISPATCH ossl_siphash_functions[];
index 64a3e8f05e0fd86be264eede8ef0857ac4c12522..e2bf3d5c3a6f3f7e586ee6b4ed3d933e0914bb26 100644 (file)
@@ -519,10 +519,9 @@ static int HKDF_Extract(OSSL_LIB_CTX *libctx, const EVP_MD *evp_md,
         return 0;
     }
     /* calc: PRK = HMAC-Hash(salt, IKM) */
-    return
-        EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt,
-                  salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL)
-        != NULL;
+    return EVP_Q_mac(libctx, "HMAC", NULL, EVP_MD_get0_name(evp_md), NULL, salt,
+                     salt_len, ikm, ikm_len, prk, EVP_MD_get_size(evp_md), NULL)
+           != NULL;
 }
 
 /*
index c72c1e6c0fca81545ca6c9aa926a0bddc8a4871d..d871a85033c898526eab6bee21db3a0da7daf180 100644 (file)
@@ -20,6 +20,8 @@
 #include <openssl/params.h>
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
+#include <openssl/proverr.h>
+#include <openssl/err.h>
 
 #include "internal/ssl3_cbc.h"
 
@@ -27,6 +29,9 @@
 #include "prov/provider_ctx.h"
 #include "prov/provider_util.h"
 #include "prov/providercommon.h"
+#include "prov/fipsindicator.h"
+#include "prov/securitycheck.h"
+#include "prov/fipscommon.h"
 
 /*
  * Forward declaration of everything implemented here.  This is not strictly
@@ -59,6 +64,15 @@ struct hmac_data_st {
     int tls_header_set;
     unsigned char tls_mac_out[EVP_MAX_MD_SIZE];
     size_t tls_mac_out_size;
+#ifdef FIPS_MODULE
+    /*
+     * 'internal' is set to 1 if HMAC is used inside another algorithm such as a
+     * KDF. In this case it is the parent algorithm that is responsible for
+     * performing any conditional FIPS indicator related checks for the HMAC.
+     */
+    int internal;
+#endif
+    OSSL_FIPS_IND_DECLARE
 };
 
 static void *hmac_new(void *provctx)
@@ -74,6 +88,7 @@ static void *hmac_new(void *provctx)
         return NULL;
     }
     macctx->provctx = provctx;
+    OSSL_FIPS_IND_INIT(macctx)
 
     return macctx;
 }
@@ -144,12 +159,33 @@ static int hmac_setkey(struct hmac_data_st *macctx,
 {
     const EVP_MD *digest;
 
+#ifdef FIPS_MODULE
+    /*
+     * KDF's pass a salt rather than a key,
+     * which is why it skips the key check unless "HMAC" is fetched directly.
+     */
+    if (!macctx->internal) {
+        OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(macctx->provctx);
+        int approved = ossl_mac_check_key_size(keylen);
+
+        if (!approved) {
+            if (!OSSL_FIPS_IND_ON_UNAPPROVED(macctx, OSSL_FIPS_IND_SETTABLE0,
+                                             libctx, "HMAC", "keysize",
+                                             FIPS_hmac_key_check)) {
+                ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH);
+                return 0;
+            }
+        }
+    }
+#endif
+
     if (macctx->key != NULL)
         OPENSSL_secure_clear_free(macctx->key, macctx->keylen);
     /* Keep a copy of the key in case we need it for TLS HMAC */
     macctx->key = OPENSSL_secure_malloc(keylen > 0 ? keylen : 1);
     if (macctx->key == NULL)
         return 0;
+
     memcpy(macctx->key, key, keylen);
     macctx->keylen = keylen;
 
@@ -235,6 +271,7 @@ static int hmac_final(void *vmacctx, unsigned char *out, size_t *outl,
 static const OSSL_PARAM known_gettable_ctx_params[] = {
     OSSL_PARAM_size_t(OSSL_MAC_PARAM_SIZE, NULL),
     OSSL_PARAM_size_t(OSSL_MAC_PARAM_BLOCK_SIZE, NULL),
+    OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
     OSSL_PARAM_END
 };
 static const OSSL_PARAM *hmac_gettable_ctx_params(ossl_unused void *ctx,
@@ -256,6 +293,17 @@ static int hmac_get_ctx_params(void *vmacctx, OSSL_PARAM params[])
             && !OSSL_PARAM_set_int(p, hmac_block_size(macctx)))
         return 0;
 
+#ifdef FIPS_MODULE
+    p = OSSL_PARAM_locate(params, OSSL_MAC_PARAM_FIPS_APPROVED_INDICATOR);
+    if (p != NULL) {
+        int approved = 0;
+
+        if (!macctx->internal)
+            approved = OSSL_FIPS_IND_GET(macctx)->approved;
+        if (!OSSL_PARAM_set_int(p, approved))
+            return 0;
+    }
+#endif
     return 1;
 }
 
@@ -266,6 +314,7 @@ static const OSSL_PARAM known_settable_ctx_params[] = {
     OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_NOINIT, NULL),
     OSSL_PARAM_int(OSSL_MAC_PARAM_DIGEST_ONESHOT, NULL),
     OSSL_PARAM_size_t(OSSL_MAC_PARAM_TLS_DATA_SIZE, NULL),
+    OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_MAC_PARAM_FIPS_KEY_CHECK)
     OSSL_PARAM_END
 };
 static const OSSL_PARAM *hmac_settable_ctx_params(ossl_unused void *ctx,
@@ -286,12 +335,17 @@ static int hmac_set_ctx_params(void *vmacctx, const OSSL_PARAM params[])
     if (params == NULL)
         return 1;
 
+    if (!OSSL_FIPS_IND_SET_CTX_PARAM(macctx, OSSL_FIPS_IND_SETTABLE0, params,
+                                     OSSL_MAC_PARAM_FIPS_KEY_CHECK))
+        return 0;
+
     if (!ossl_prov_digest_load_from_params(&macctx->digest, params, ctx))
         return 0;
 
     if ((p = OSSL_PARAM_locate_const(params, OSSL_MAC_PARAM_KEY)) != NULL) {
         if (p->data_type != OSSL_PARAM_OCTET_STRING)
             return 0;
+
         if (!hmac_setkey(macctx, p->data, p->data_size))
             return 0;
     }
@@ -319,3 +373,33 @@ const OSSL_DISPATCH ossl_hmac_functions[] = {
     { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params },
     OSSL_DISPATCH_END
 };
+
+#ifdef FIPS_MODULE
+static OSSL_FUNC_mac_newctx_fn hmac_internal_new;
+
+static void *hmac_internal_new(void *provctx)
+{
+    struct hmac_data_st *macctx = hmac_new(provctx);
+
+    if (macctx != NULL)
+        macctx->internal = 1;
+    return macctx;
+}
+
+const OSSL_DISPATCH ossl_hmac_internal_functions[] = {
+    { OSSL_FUNC_MAC_NEWCTX, (void (*)(void))hmac_internal_new },
+    { OSSL_FUNC_MAC_DUPCTX, (void (*)(void))hmac_dup },
+    { OSSL_FUNC_MAC_FREECTX, (void (*)(void))hmac_free },
+    { OSSL_FUNC_MAC_INIT, (void (*)(void))hmac_init },
+    { OSSL_FUNC_MAC_UPDATE, (void (*)(void))hmac_update },
+    { OSSL_FUNC_MAC_FINAL, (void (*)(void))hmac_final },
+    { OSSL_FUNC_MAC_GETTABLE_CTX_PARAMS,
+      (void (*)(void))hmac_gettable_ctx_params },
+    { OSSL_FUNC_MAC_GET_CTX_PARAMS, (void (*)(void))hmac_get_ctx_params },
+    { OSSL_FUNC_MAC_SETTABLE_CTX_PARAMS,
+      (void (*)(void))hmac_settable_ctx_params },
+    { OSSL_FUNC_MAC_SET_CTX_PARAMS, (void (*)(void))hmac_set_ctx_params },
+    OSSL_DISPATCH_END
+};
+
+#endif /* FIPS_MODULE */
index 47894388465955dd1346187c649d03a90209a592..84e589cc7eaec69d954aa90c426fcea9cd36418d 100644 (file)
@@ -1937,8 +1937,12 @@ static int mac_test_run_mac(EVP_TEST *t)
         t->err = "MAC_CREATE_ERROR";
         goto err;
     }
-    if (fips_provider_version_gt(libctx, 3, 2, 0))
+    if (fips_provider_version_gt(libctx, 3, 2, 0)) {
+        /* HMAC will put an error on the stack here (digest is not set yet) */
+        ERR_set_mark();
         size_before_init = EVP_MAC_CTX_get_mac_size(ctx);
+        ERR_pop_to_mark();
+    }
     if (!EVP_MAC_init(ctx, expected->key, expected->key_len, params)) {
         t->err = "MAC_INIT_ERROR";
         goto err;
index a7c8426dd7daed4c672e036b65335d5e0efbf43a..d2caddbcea0ca3ab318f5a89ee8db91433c06c7b 100644 (file)
@@ -262,6 +262,30 @@ Input = "Test that SHAKE128 fails"
 Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f
 Result = MAC_INIT_ERROR
 
+Title = HMAC FIPS short key test
+
+# Test HMAC with key < 112 bits is not allowed
+Availablein = fips
+FIPSversion = >=3.4.0
+MAC = HMAC
+Algorithm = SHA256
+Input = "Test Input"
+Key = 0001020304
+Result = MAC_INIT_ERROR
+
+Title = HMAC FIPS short key indicator test
+
+# Test HMAC with key < 112 bits is unapproved
+Availablein = fips
+FIPSversion = >=3.4.0
+MAC = HMAC
+Algorithm = SHA256
+Unapproved = 1
+Ctrl = key-check:0
+Input = "Test Input"
+Key = 0001020304
+Output = db70da6176d87813b059879ccc27bc53e295c6eca74db8bdc4e77d7e951d894b
+
 Title = CMAC tests (from FIPS module)
 
 MAC = CMAC
index 5ff5c2de6671698ef4eeceecb79839229cc42efe..3fd7ee67fa78a3868ca7b446c97be9211c8b5a62 100644 (file)
@@ -14,6 +14,7 @@ my $conditional_errors = 1;
 my $security_checks = 1;
 my $ems_check = 1;
 my $no_short_mac = 1;
+my $key_check = 1;
 my $drgb_no_trunc_dgst = 1;
 my $digest_check = 1;
 my $dsa_sign_disabled = 1;
@@ -60,6 +61,7 @@ security-checks = $security_checks
 module-mac = $module_mac
 tls1-prf-ems-check = $ems_check
 no-short-mac = $no_short_mac
+hmac-key-check = $key_check
 drbg-no-trunc-md = $drgb_no_trunc_dgst
 signature-digest-check = $digest_check
 dsa-sign-disabled = $dsa_sign_disabled
index 9117b621523fe6cbe24ccc2b4c04c908e9014bcf..ccff1670c82fac25242572d7e5d19e642f3c0eda 100644 (file)
@@ -31,6 +31,7 @@ my %params = (
     'PROV_PARAM_BUILDINFO' =>          "buildinfo",          # utf8_ptr
     'PROV_PARAM_STATUS' =>             "status",             # uint
     'PROV_PARAM_SECURITY_CHECKS' =>    "security-checks",    # uint
+    'PROV_PARAM_HMAC_KEY_CHECK' =>     "hmac-key-check",     # uint
     'PROV_PARAM_TLS1_PRF_EMS_CHECK' => "tls1-prf-ems-check", # uint
     'PROV_PARAM_NO_SHORT_MAC' =>       "no-short-mac",       # uint
     'PROV_PARAM_DRBG_TRUNC_DIGEST' =>  "drbg-no-trunc-md",   # uint
@@ -168,6 +169,7 @@ my %params = (
     'MAC_PARAM_SIZE' =>             "size",                     # size_t
     'MAC_PARAM_BLOCK_SIZE' =>       "block-size",               # size_t
     'MAC_PARAM_TLS_DATA_SIZE' =>    "tls-data-size",            # size_t
+    'MAC_PARAM_FIPS_KEY_CHECK' =>   '*PKEY_PARAM_FIPS_KEY_CHECK',
     'MAC_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR',
 
 # KDF / PRF parameters