]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add option to FIPS module to enforce EMS check during KDF TLS1_PRF.
authorslontis <shane.lontis@oracle.com>
Wed, 8 Feb 2023 07:22:43 +0000 (17:22 +1000)
committerTomas Mraz <tomas@openssl.org>
Tue, 7 Mar 2023 17:24:45 +0000 (18:24 +0100)
Fixes #19989

Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/20241)

18 files changed:
CHANGES.md
apps/fipsinstall.c
crypto/err/openssl.txt
doc/man1/openssl-fipsinstall.pod.in
doc/man7/OSSL_PROVIDER-FIPS.pod
include/openssl/core_names.h
include/openssl/fips_names.h
include/openssl/proverr.h
providers/common/include/prov/proverr.h
providers/common/include/prov/securitycheck.h
providers/common/provider_err.c
providers/common/securitycheck_default.c
providers/common/securitycheck_fips.c
providers/fips/fipsprov.c
providers/implementations/kdfs/tls1_prf.c
test/recipes/03-test_fipsinstall.t
test/recipes/90-test_sslapi.t
test/sslapitest.c

index b5381e9847bc58edc5fafbbd01d2c5b002de66dc..711454ec43d7199de300e945fbcda6df1dc68412 100644 (file)
@@ -237,6 +237,13 @@ OpenSSL 3.1
 
 ### Changes between 3.0 and 3.1.0 [xx XXX xxxx]
 
+ * Add FIPS provider configuration option to enforce the
+   Extended Master Secret (EMS) check during the TLS1_PRF KDF.
+   The option '-ems-check' can optionally be supplied to
+   'openssl fipsinstall'.
+
+   *Shane Lontis*
+
  * The FIPS provider includes a few non-approved algorithms for
    backward compatibility purposes and the "fips=yes" property query
    must be used for all algorithm fetches to ensure FIPS compliance.
index 5198e0863e291b00aaf61228e3bfbda14061575d..2e6edc007a3a7860aaa1e9243bbd068350d87c5c 100644 (file)
@@ -38,6 +38,7 @@ typedef enum OPTION_choice {
     OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG,
     OPT_NO_CONDITIONAL_ERRORS,
     OPT_NO_SECURITY_CHECKS,
+    OPT_TLS_PRF_EMS_CHECK,
     OPT_SELF_TEST_ONLOAD, OPT_SELF_TEST_ONINSTALL
 } OPTION_CHOICE;
 
@@ -50,15 +51,17 @@ const OPTIONS fipsinstall_options[] = {
     {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"},
     {"section_name", OPT_SECTION_NAME, 's',
      "FIPS Provider config section name (optional)"},
-     {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-',
-      "Disable the ability of the fips module to enter an error state if"
-      " any conditional self tests fail"},
+    {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-',
+     "Disable the ability of the fips module to enter an error state if"
+     " any conditional self tests fail"},
     {"no_security_checks", OPT_NO_SECURITY_CHECKS, '-',
      "Disable the run-time FIPS security checks in the module"},
     {"self_test_onload", OPT_SELF_TEST_ONLOAD, '-',
      "Forces self tests to always run on module load"},
     {"self_test_oninstall", OPT_SELF_TEST_ONINSTALL, '-',
      "Forces self tests to run once on module installation"},
+    {"ems_check", OPT_TLS_PRF_EMS_CHECK, '-',
+     "Enable the run-time FIPS check for EMS during TLS1_PRF"},
     OPT_SECTION("Input"),
     {"in", OPT_IN, '<', "Input config file, used when verifying"},
 
@@ -171,6 +174,7 @@ static int write_config_fips_section(BIO *out, const char *section,
                                      size_t module_mac_len,
                                      int conditional_errors,
                                      int security_checks,
+                                     int ems_check,
                                      unsigned char *install_mac,
                                      size_t install_mac_len)
 {
@@ -184,6 +188,8 @@ static int write_config_fips_section(BIO *out, const char *section,
                       conditional_errors ? "1" : "0") <= 0
         || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
                       security_checks ? "1" : "0") <= 0
+        || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK,
+                      ems_check ? "1" : "0") <= 0
         || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,
                       module_mac_len))
         goto end;
@@ -205,7 +211,8 @@ static CONF *generate_config_and_load(const char *prov_name,
                                       unsigned char *module_mac,
                                       size_t module_mac_len,
                                       int conditional_errors,
-                                      int security_checks)
+                                      int security_checks,
+                                      int ems_check)
 {
     BIO *mem_bio = NULL;
     CONF *conf = NULL;
@@ -218,6 +225,7 @@ static CONF *generate_config_and_load(const char *prov_name,
                                        module_mac, module_mac_len,
                                        conditional_errors,
                                        security_checks,
+                                       ems_check,
                                        NULL, 0))
         goto end;
 
@@ -315,6 +323,7 @@ int fipsinstall_main(int argc, char **argv)
 {
     int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, self_test_onload = 1;
     int enable_conditional_errors = 1, enable_security_checks = 1;
+    int enable_tls_prf_ems_check = 0; /* This is off by default */
     const char *section_name = "fips_sect";
     const char *mac_name = "HMAC";
     const char *prov_name = "fips";
@@ -360,6 +369,9 @@ opthelp:
         case OPT_NO_SECURITY_CHECKS:
             enable_security_checks = 0;
             break;
+        case OPT_TLS_PRF_EMS_CHECK:
+            enable_tls_prf_ems_check = 1;
+            break;
         case OPT_QUIET:
             quiet = 1;
             /* FALLTHROUGH */
@@ -523,7 +535,8 @@ opthelp:
         conf = generate_config_and_load(prov_name, section_name, module_mac,
                                         module_mac_len,
                                         enable_conditional_errors,
-                                        enable_security_checks);
+                                        enable_security_checks,
+                                        enable_tls_prf_ems_check);
         if (conf == NULL)
             goto end;
         if (!load_fips_prov_and_run_self_test(prov_name))
@@ -540,6 +553,7 @@ opthelp:
                                        module_mac, module_mac_len,
                                        enable_conditional_errors,
                                        enable_security_checks,
+                                       enable_tls_prf_ems_check,
                                        install_mac, install_mac_len))
             goto end;
         if (!quiet)
index e90e5dc033397c5076eda5de149855e1db399db2..f391e756475cb9a6ff7a615684c2587f9a9c7c22 100644 (file)
@@ -1006,6 +1006,7 @@ PROV_R_BN_ERROR:160:bn error
 PROV_R_CIPHER_OPERATION_FAILED:102:cipher operation failed
 PROV_R_DERIVATION_FUNCTION_INIT_FAILED:205:derivation function init failed
 PROV_R_DIGEST_NOT_ALLOWED:174:digest not allowed
+PROV_R_EMS_NOT_ENABLED:233:ems not enabled
 PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK:186:entropy source strength too weak
 PROV_R_ERROR_INSTANTIATING_DRBG:188:error instantiating drbg
 PROV_R_ERROR_RETRIEVING_ENTROPY:189:error retrieving entropy
index af18f361e6c1afc37dd8de8e194fd03a095ac008..8b066453f92567e7756049aeb6436d9db8945ea9 100644 (file)
@@ -21,6 +21,7 @@ B<openssl fipsinstall>
 [B<-quiet>]
 [B<-no_conditional_errors>]
 [B<-no_security_checks>]
+[B<-ems_check>]
 [B<-self_test_onload>]
 [B<-self_test_oninstall>]
 [B<-corrupt_desc> I<selftest_description>]
@@ -165,6 +166,15 @@ fails as described above.
 
 Configure the module to not perform run-time security checks as described above.
 
+Enabling the configuration option "no-fips-securitychecks" provides another way to
+turn off the check at compile time.
+
+=item B<-ems_check>
+
+Configure the module to enable a run-time Extended Master Secret (EMS) check
+when using the TLS1_PRF KDF algorithm. This check is disabled by default.
+See RFC 7627 for information related to EMS.
+
 =item B<-self_test_onload>
 
 Do not write the two fields related to the "test status indicator" and
index 1e1601cef1bf3e1565732a6da5c10e8871a05433..a18703f568fc55f195f772bb38ad72e0927cab56 100644 (file)
@@ -41,6 +41,21 @@ query.  Including C<provider=fips> in your property query guarantees
 that the OpenSSL FIPS provider is used for cryptographic operations
 rather than other FIPS capable providers.
 
+=head2 Provider parameters
+
+See L<provider-base(7)/Provider parameters> for a list of base parameters.
+Additionally the OpenSSL FIPS provider also supports the following gettable
+parameters:
+
+=over 4
+
+=item "security-checks" (B<OSSL_OSSL_PROV_PARAM_SECURITY_CHECKS>) <unsigned integer>
+
+For further information refer to the L<openssl-fipsinstall(1)> option
+B<-no_security_checks>.
+
+=back
+
 =head1 OPERATIONS AND ALGORITHMS
 
 The OpenSSL FIPS provider supports these operations and algorithms:
index 173a81d28bbe843b0289aa7243d3a01a75ff9803..5e5be567a578156b0d2e398a9943d7edbb6fbb4c 100644 (file)
@@ -21,11 +21,12 @@ extern "C" {
 #define OSSL_PROV_PARAM_CORE_MODULE_FILENAME "module-filename" /* utf8_ptr */
 
 /* Well known parameter names that Providers can define */
-#define OSSL_PROV_PARAM_NAME            "name"                /* utf8_ptr */
-#define OSSL_PROV_PARAM_VERSION         "version"             /* utf8_ptr */
-#define OSSL_PROV_PARAM_BUILDINFO       "buildinfo"           /* utf8_ptr */
-#define OSSL_PROV_PARAM_STATUS          "status"              /* uint */
-#define OSSL_PROV_PARAM_SECURITY_CHECKS "security-checks"     /* uint */
+#define OSSL_PROV_PARAM_NAME               "name"                /* utf8_ptr */
+#define OSSL_PROV_PARAM_VERSION            "version"             /* utf8_ptr */
+#define OSSL_PROV_PARAM_BUILDINFO          "buildinfo"           /* utf8_ptr */
+#define OSSL_PROV_PARAM_STATUS             "status"              /* uint */
+#define OSSL_PROV_PARAM_SECURITY_CHECKS    "security-checks"     /* uint */
+#define OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK "tls1-prf-ems-check"  /* uint */
 
 /* Self test callback parameters */
 #define OSSL_PROV_PARAM_SELF_TEST_PHASE  "st-phase" /* utf8_string */
index 0fdf5440c7cb38fef4342bc7c5827f09adf5e8ea..3f29369b3f9296724915c9caacbbffdc95806d56 100644 (file)
@@ -53,6 +53,14 @@ extern "C" {
  */
 # define OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS "security-checks"
 
+/*
+ * A boolean that determines if the runtime FIPS check for TLS1_PRF EMS is performed.
+ * This is disabled by default.
+ *
+ * Type: OSSL_PARAM_UTF8_STRING
+ */
+# define OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK "tls1-prf-ems-check"
+
 # ifdef __cplusplus
 }
 # endif
index 3685430f5d3ea3034067ecd4e6a81fe32165a2fb..bf4dc135f5921547166f278c20a3cc96a4981e2c 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -32,6 +32,7 @@
 # define PROV_R_CIPHER_OPERATION_FAILED                   102
 # define PROV_R_DERIVATION_FUNCTION_INIT_FAILED           205
 # define PROV_R_DIGEST_NOT_ALLOWED                        174
+# define PROV_R_EMS_NOT_ENABLED                           233
 # define PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK          186
 # define PROV_R_ERROR_INSTANTIATING_DRBG                  188
 # define PROV_R_ERROR_RETRIEVING_ENTROPY                  189
index 8ad6cc048d6dda21a3f9dee99476a612d2552418..69e14465c752a55e828f4cb9f8da14ea35652c28 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
index 4a7f85f71186ec95df424a6751348a5209960a1f..62e60cc0103f0f3b21ee3e2fbfc5eb3f8038de73 100644 (file)
@@ -28,3 +28,4 @@ int ossl_digest_get_approved_nid(const EVP_MD *md);
 int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
                                     int sha1_allowed);
 int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx);
+int ossl_tls1_prf_ems_check_enabled(OSSL_LIB_CTX *libctx);
index f6144072aa049bb85d74841044b856a1d384c19b..954aabe80cfcf07da54066ea77313bfb7f7fe482 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2022 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2023 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the Apache License 2.0 (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -33,6 +33,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
     "derivation function init failed"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_DIGEST_NOT_ALLOWED),
     "digest not allowed"},
+    {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_EMS_NOT_ENABLED), "ems not enabled"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ENTROPY_SOURCE_STRENGTH_TOO_WEAK),
     "entropy source strength too weak"},
     {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ERROR_INSTANTIATING_DRBG),
index de7f0d3a0a5718bd06a55d3d92236c27ffb7d0d5..63c875ecd0b7170484c011d2cbca45ea39a03a9c 100644 (file)
@@ -22,6 +22,12 @@ int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
     return 0;
 }
 
+/* Disable the ems check in the default provider */
+int ossl_tls1_prf_ems_check_enabled(OSSL_LIB_CTX *libctx)
+{
+    return 0;
+}
+
 int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
                                     ossl_unused int sha1_allowed)
 {
index b7659bd395c3eb76a348d67bbccea06e63b1951e..2bc8a5992685a68aa72bfac880e5a529520682fc 100644 (file)
@@ -20,6 +20,7 @@
 #include "prov/securitycheck.h"
 
 int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
+int FIPS_tls_prf_ems_check(OSSL_LIB_CTX *libctx);
 
 int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
 {
@@ -30,6 +31,11 @@ int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx)
 #endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */
 }
 
+int ossl_tls1_prf_ems_check_enabled(OSSL_LIB_CTX *libctx)
+{
+    return FIPS_tls_prf_ems_check(libctx);
+}
+
 int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md,
                                     int sha1_allowed)
 {
index ab58ab891d94feff5838cb8a2bd76e511b249248..a16c379fba9529ee3dca5126ee8104c168897e1b 100644 (file)
@@ -47,6 +47,7 @@ static OSSL_FUNC_provider_query_operation_fn fips_query;
 
 extern OSSL_FUNC_core_thread_start_fn *c_thread_start;
 int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx);
+int FIPS_tls_prf_ems_check(OSSL_LIB_CTX *libctx);
 
 /*
  * Should these function pointers be stored in the provider side provctx? Could
@@ -82,7 +83,9 @@ typedef struct fips_global_st {
     const OSSL_CORE_HANDLE *handle;
     SELF_TEST_POST_PARAMS selftest_params;
     int fips_security_checks;
+    int fips_tls1_prf_ems_check;
     const char *fips_security_check_option;
+    const char *fips_tls1_prf_ems_check_option;
 } FIPS_GLOBAL;
 
 void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
@@ -94,6 +97,9 @@ void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
     fgbl->fips_security_checks = 1;
     fgbl->fips_security_check_option = "1";
 
+    fgbl->fips_tls1_prf_ems_check = 0; /* Disabled by default */
+    fgbl->fips_tls1_prf_ems_check_option = "0";
+
     return fgbl;
 }
 
@@ -109,6 +115,7 @@ static const OSSL_PARAM fips_param_types[] = {
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
     OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
     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_END
 };
 
@@ -119,9 +126,10 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
     * NOTE: inside core_get_params() these will be loaded from config items
     * stored inside prov->parameters (except for
     * OSSL_PROV_PARAM_CORE_MODULE_FILENAME).
-    * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS is not a self test parameter.
+    * OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS and
+    * OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK are not self test parameters.
     */
-    OSSL_PARAM core_params[8], *p = core_params;
+    OSSL_PARAM core_params[9], *p = core_params;
 
     *p++ = OSSL_PARAM_construct_utf8_ptr(
             OSSL_PROV_PARAM_CORE_MODULE_FILENAME,
@@ -151,6 +159,10 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
             OSSL_PROV_FIPS_PARAM_SECURITY_CHECKS,
             (char **)&fgbl->fips_security_check_option,
             sizeof(fgbl->fips_security_check_option));
+    *p++ = OSSL_PARAM_construct_utf8_ptr(
+            OSSL_PROV_FIPS_PARAM_TLS1_PRF_EMS_CHECK,
+            (char **)&fgbl->fips_tls1_prf_ems_check_option,
+            sizeof(fgbl->fips_tls1_prf_ems_check_option));
     *p = OSSL_PARAM_construct_end();
 
     if (!c_get_params(fgbl->handle, core_params)) {
@@ -187,6 +199,9 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[])
     p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_SECURITY_CHECKS);
     if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->fips_security_checks))
         return 0;
+    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK);
+    if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->fips_tls1_prf_ems_check))
+        return 0;
     return 1;
 }
 
@@ -698,6 +713,11 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
         && strcmp(fgbl->fips_security_check_option, "0") == 0)
         fgbl->fips_security_checks = 0;
 
+    /* Enable the ems check if it's enabled in the fips config file. */
+    if (fgbl->fips_tls1_prf_ems_check_option != NULL
+        && strcmp(fgbl->fips_tls1_prf_ems_check_option, "1") == 0)
+        fgbl->fips_tls1_prf_ems_check = 1;
+
     ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);
 
     if (!SELF_TEST_post(&fgbl->selftest_params, 0)) {
@@ -893,6 +913,14 @@ int FIPS_security_check_enabled(OSSL_LIB_CTX *libctx)
     return fgbl->fips_security_checks;
 }
 
+int FIPS_tls_prf_ems_check(OSSL_LIB_CTX *libctx)
+{
+    FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx,
+                                              OSSL_LIB_CTX_FIPS_PROV_INDEX);
+
+    return fgbl->fips_tls1_prf_ems_check;
+}
+
 void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
                                  void **cbarg)
 {
index 8a3807308408ac8e354ee442d9713884fc77fb91..2c2dbf31cc0b35850d5bb367176aaee02a4280b2 100644 (file)
  *     A(0) = seed
  *     A(i) = HMAC_<hash>(secret, A(i-1))
  */
+
+/*
+ * Low level APIs (such as DH) are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
@@ -60,6 +67,7 @@
 #include "prov/providercommon.h"
 #include "prov/implementations.h"
 #include "prov/provider_util.h"
+#include "prov/securitycheck.h"
 #include "internal/e_os.h"
 
 static OSSL_FUNC_kdf_newctx_fn kdf_tls1_prf_new;
@@ -78,6 +86,8 @@ static int tls1_prf_alg(EVP_MAC_CTX *mdctx, EVP_MAC_CTX *sha1ctx,
                         unsigned char *out, size_t olen);
 
 #define TLS1_PRF_MAXBUF 1024
+#define TLS_MD_MASTER_SECRET_CONST        "\x6d\x61\x73\x74\x65\x72\x20\x73\x65\x63\x72\x65\x74"
+#define TLS_MD_MASTER_SECRET_CONST_SIZE   13
 
 /* TLS KDF kdf context structure */
 typedef struct {
@@ -160,6 +170,7 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
                                const OSSL_PARAM params[])
 {
     TLS1_PRF *ctx = (TLS1_PRF *)vctx;
+    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
 
     if (!ossl_prov_is_running() || !kdf_tls1_prf_set_ctx_params(ctx, params))
         return 0;
@@ -181,6 +192,21 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen,
         return 0;
     }
 
+    /*
+     * The seed buffer is prepended with a label.
+     * If EMS mode is enforced then the label "master secret" is not allowed,
+     * We do the check this way since the PRF is used for other purposes, as well
+     * as "extended master secret".
+     */
+    if (ossl_tls1_prf_ems_check_enabled(libctx)) {
+        if (ctx->seedlen >= TLS_MD_MASTER_SECRET_CONST_SIZE
+                && memcmp(ctx->seed, TLS_MD_MASTER_SECRET_CONST,
+                          TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_EMS_NOT_ENABLED);
+            return 0;
+        }
+    }
+
     return tls1_prf_alg(ctx->P_hash, ctx->P_sha1,
                         ctx->sec, ctx->seclen,
                         ctx->seed, ctx->seedlen,
index 812210e471fe2c223bace0f355c5a27d6bbd65d6..10a2fcaffa44ecf5b1408c1e3066d04b63532c17 100644 (file)
@@ -347,6 +347,7 @@ SKIP: {
     ok(!run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
                 '-provider_name', 'fips', '-mac_name', 'HMAC',
                 '-macopt', 'digest:SHA256', '-macopt', "hexkey:$fipskey",
-                '-section_name', 'fips_sect', '-self_test_oninstall'])),
+                '-section_name', 'fips_sect', '-self_test_oninstall',
+                '-ems_check'])),
        "fipsinstall fails when attempting to run self tests on install");
 }
index 70fa7e50e2d2921d2babf36653ecd18f23c37e79..70d789d6c405313172286feb53bcdf041acb0e8c 100644 (file)
@@ -1,12 +1,11 @@
 #! /usr/bin/env perl
-# Copyright 2016-2022 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
 #
 # Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
 # in the file LICENSE in the source distribution or at
 # https://www.openssl.org/source/license.html
 
-
 use OpenSSL::Test::Utils;
 use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir bldtop_dir bldtop_file/;
 use File::Temp qw(tempfile);
@@ -19,13 +18,22 @@ use lib srctop_dir('Configurations');
 use lib bldtop_dir('.');
 
 my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
+my $fipsmodcfg_filename = "fipsmodule.cnf";
+my $fipsmodcfg = bldtop_file("providers", $fipsmodcfg_filename);
+
+my $provconf = srctop_file("test", "fips-and-base.cnf");
+
+# A modified copy of "fipsmodule.cnf"
+my $fipsmodcfgnew_filename = "fipsmodule_mod.cnf";
+my $fipsmodcfgnew = bldtop_file("test", $fipsmodcfgnew_filename);
+
+# A modified copy of "fips-and-base.cnf"
+my $provconfnew = bldtop_file("test", "temp.cnf");
 
 plan skip_all => "No TLS/SSL protocols are supported by this OpenSSL build"
     if alldisabled(grep { $_ ne "ssl3" } available_protocols("tls"));
 
-plan tests =>
-    ($no_fips ? 0 : 1)          # sslapitest with fips
-    + 1;                        # sslapitest with default provider
+plan tests => 3;
 
 (undef, my $tmpfilename) = tempfile();
 
@@ -39,16 +47,97 @@ ok(run(test(["sslapitest", srctop_dir("test", "certs"),
                          "dhparams.pem")])),
              "running sslapitest");
 
-unless ($no_fips) {
+SKIP: {
+    skip "Skipping FIPS tests", 2
+        if $no_fips;
+
     ok(run(test(["sslapitest", srctop_dir("test", "certs"),
                  srctop_file("test", "recipes", "90-test_sslapi_data",
                              "passwd.txt"), $tmpfilename, "fips",
-                 srctop_file("test", "fips-and-base.cnf"),
+                 $provconf,
                  srctop_file("test",
                              "recipes",
                              "90-test_sslapi_data",
                              "dhparams.pem")])),
                  "running sslapitest");
+
+    run(test(["fips_version_test", "-config", $provconf, ">=3.1.0"]),
+             capture => 1, statusvar => \my $exit);
+
+    skip "FIPS provider version is too old for TLS_PRF EMS option test", 1
+        if !$exit;
+
+    # Read in a text $infile and replace the regular expression in $srch with the
+    # value in $repl and output to a new file $outfile.
+    sub replace_line_file_internal {
+    
+        my ($infile, $srch, $repl, $outfile) = @_;
+        my $msg;
+
+        open(my $in, "<", $infile) or return 0;
+        read($in, $msg, 1024);
+        close $in;
+
+        $msg =~ s/$srch/$repl/;
+
+        open(my $fh, ">", $outfile) or return 0;
+        print $fh $msg;
+        close $fh;
+        return 1;
+    }
+    
+    # Read in the text input file $infile
+    # and replace a single Key = Value line with a new value in $value.
+    # OR remove the Key = Value line if the passed in $value is empty.
+    # and then output a new file $outfile.
+    # $key is the Key to find
+    sub replace_kv_file {
+        my ($infile, $key, $value, $outfile) = @_;
+        my $srch = qr/$key\s*=\s*\S*\n/;
+        my $rep;
+        if ($value eq "") {
+            $rep = "";
+        } else {
+           $rep = "$key = $value\n";
+        }
+        return replace_line_file_internal($infile, $srch, $rep, $outfile);
+    }
+    
+    # Read in the text $input file
+    # and search for the $key and replace with $newkey
+    # and then output a new file $outfile.
+    sub replace_line_file {
+        my ($infile, $key, $newkey, $outfile) = @_;
+        my $srch = qr/$key/;
+        my $rep = "$newkey";
+        return replace_line_file_internal($infile,
+                                          $srch, $rep, $outfile);
+    }
+
+    # In order to enable the tls1-prf-ems-check=1 in a fips config file
+    # copy the existing fipsmodule.cnf and modify it.
+    # Then copy fips-and-base.cfg to make a file that includes the changed file
+    # NOTE that this just runs test_no_ems() to check that the connection
+    # fails if ems is not used and the fips check is enabled.
+    ok(replace_kv_file($fipsmodcfg,
+                       'tls1-prf-ems-check', '1',
+                       $fipsmodcfgnew)
+       && replace_line_file($provconf,
+                            $fipsmodcfg_filename, $fipsmodcfgnew_filename,
+                            $provconfnew)
+       && run(test(["sslapitest", srctop_dir("test", "certs"),
+                    srctop_file("test", "recipes", "90-test_sslapi_data",
+                                "passwd.txt"),
+                    $tmpfilename, "fips",
+                    $provconfnew,
+                    srctop_file("test",
+                                "recipes",
+                                "90-test_sslapi_data",
+                                "dhparams.pem")])),
+       "running sslapitest");
+
+    unlink $fipsmodcfgnew;
+    unlink $provconfnew;
 }
 
 unlink $tmpfilename;
index 585260950acc3c958e74759b9fe02436890f01ad..102b590aaee5fed1466312d511af0661405c9c41 100644 (file)
@@ -99,6 +99,7 @@ static char *tmpfilename = NULL;
 static char *dhfile = NULL;
 
 static int is_fips = 0;
+static int fips_ems_check = 0;
 
 #define LOG_BUFFER_SIZE 2048
 static char server_log_buffer[LOG_BUFFER_SIZE + 1] = {0};
@@ -796,7 +797,7 @@ static int test_no_ems(void)
 {
     SSL_CTX *cctx = NULL, *sctx = NULL;
     SSL *clientssl = NULL, *serverssl = NULL;
-    int testresult = 0;
+    int testresult = 0, status;
 
     if (!create_ssl_ctx_pair(libctx, TLS_server_method(), TLS_client_method(),
                              TLS1_VERSION, TLS1_2_VERSION,
@@ -812,19 +813,25 @@ static int test_no_ems(void)
         goto end;
     }
 
-    if (!create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)) {
-        printf("Creating SSL connection failed\n");
-        goto end;
-    }
-
-    if (SSL_get_extms_support(serverssl)) {
-        printf("Server reports Extended Master Secret support\n");
-        goto end;
-    }
-
-    if (SSL_get_extms_support(clientssl)) {
-        printf("Client reports Extended Master Secret support\n");
-        goto end;
+    status = create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE);
+    if (fips_ems_check) {
+        if (status == 1) {
+            printf("When FIPS uses the EMS check a connection that doesnt use EMS should fail\n");
+            goto end;
+        }
+    } else {
+        if (!status) {
+            printf("Creating SSL connection failed\n");
+            goto end;
+        }
+        if (SSL_get_extms_support(serverssl)) {
+            printf("Server reports Extended Master Secret support\n");
+            goto end;
+        }
+        if (SSL_get_extms_support(clientssl)) {
+            printf("Client reports Extended Master Secret support\n");
+            goto end;
+        }
     }
     testresult = 1;
 
@@ -10848,9 +10855,24 @@ int setup_tests(void)
             && !TEST_false(OSSL_PROVIDER_available(libctx, "default")))
         return 0;
 
-    if (strcmp(modulename, "fips") == 0)
+    if (strcmp(modulename, "fips") == 0) {
+        OSSL_PROVIDER *prov = NULL;
+        OSSL_PARAM params[2];
+
         is_fips = 1;
 
+        prov = OSSL_PROVIDER_load(libctx, "fips");
+        if (prov != NULL) {
+            /* Query the fips provider to check if the check ems option is enabled */
+            params[0] =
+                OSSL_PARAM_construct_int(OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK,
+                                         &fips_ems_check);
+            params[1] = OSSL_PARAM_construct_end();
+            OSSL_PROVIDER_get_params(prov, params);
+            OSSL_PROVIDER_unload(prov);
+        }
+    }
+
     /*
      * We add, but don't load the test "tls-provider". We'll load it when we
      * need it.
@@ -10924,6 +10946,12 @@ int setup_tests(void)
     if (privkey8192 == NULL)
         goto err;
 
+    if (fips_ems_check) {
+#ifndef OPENSSL_NO_TLS1_2
+        ADD_TEST(test_no_ems);
+#endif
+        return 1;
+    }
 #if !defined(OPENSSL_NO_KTLS) && !defined(OPENSSL_NO_SOCK)
 # if !defined(OPENSSL_NO_TLS1_2) || !defined(OSSL_NO_USABLE_TLS1_3)
     ADD_ALL_TESTS(test_ktls, NUM_KTLS_TEST_CIPHERS * 4);