From 9b02ad7225b74a5b9088b361caead0a41e570e93 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 21 Aug 2023 16:40:56 +0200 Subject: [PATCH 48/48] 0114-FIPS-enforce-EMS-support.patch Patch-name: 0114-FIPS-enforce-EMS-support.patch Patch-id: 114 Patch-status: | # We believe that some changes present in CentOS are not necessary # because ustream has a check for FIPS version --- doc/man3/SSL_CONF_cmd.pod | 3 +++ doc/man5/fips_config.pod | 13 +++++++++++ include/openssl/fips_names.h | 8 +++++++ include/openssl/ssl.h.in | 1 + providers/fips/fipsprov.c | 2 +- providers/implementations/kdfs/tls1_prf.c | 22 +++++++++++++++++++ ssl/ssl_conf.c | 1 + ssl/statem/extensions_srvr.c | 8 ++++++- ssl/t1_enc.c | 11 ++++++++-- .../30-test_evp_data/evpkdf_tls12_prf.txt | 10 +++++++++ test/sslapitest.c | 2 +- 11 files changed, 76 insertions(+), 5 deletions(-) Index: openssl-3.1.4/doc/man3/SSL_CONF_cmd.pod =================================================================== --- openssl-3.1.4.orig/doc/man3/SSL_CONF_cmd.pod +++ openssl-3.1.4/doc/man3/SSL_CONF_cmd.pod @@ -524,6 +524,9 @@ B: use extended ma default. Inverse of B: that is, B<-ExtendedMasterSecret> is the same as setting B. +B: allow establishing connections without EMS in FIPS mode. +This is a downstream specific option, and normally it should be set up via crypto-policies. + B: use CA names extension, enabled by default. Inverse of B: that is, B<-CANames> is the same as setting B. Index: openssl-3.1.4/doc/man5/fips_config.pod =================================================================== --- openssl-3.1.4.orig/doc/man5/fips_config.pod +++ openssl-3.1.4/doc/man5/fips_config.pod @@ -15,6 +15,19 @@ See the documentation for more informati This functionality was added in OpenSSL 3.0. +SUSE Linux Enterprise uses a supplementary downstream config for FIPS module located +in OpenSSL configuration directory and managed by crypto-policies. If present, it +should have the following format: + + [fips_sect] + tls1-prf-ems-check = 0 + activate = 1 + +The B option specifies whether FIPS module will require the +presence of extended master secret or not. + +The B option enforces FIPS provider activation. + =head1 COPYRIGHT Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. Index: openssl-3.1.4/include/openssl/fips_names.h =================================================================== --- openssl-3.1.4.orig/include/openssl/fips_names.h +++ openssl-3.1.4/include/openssl/fips_names.h @@ -70,6 +70,14 @@ extern "C" { */ # define OSSL_PROV_FIPS_PARAM_DRBG_TRUNC_DIGEST "drbg-no-trunc-md" +/* + * 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: openssl-3.1.4/include/openssl/ssl.h.in =================================================================== --- openssl-3.1.4.orig/include/openssl/ssl.h.in +++ openssl-3.1.4/include/openssl/ssl.h.in @@ -420,6 +420,7 @@ typedef int (*SSL_async_callback_fn)(SSL * interoperability with CryptoPro CSP 3.x */ # define SSL_OP_CRYPTOPRO_TLSEXT_BUG SSL_OP_BIT(31) +# define SSL_OP_PERMIT_NOEMS_FIPS SSL_OP_BIT(48) /* * Option "collections." Index: openssl-3.1.4/providers/fips/fipsprov.c =================================================================== --- openssl-3.1.4.orig/providers/fips/fipsprov.c +++ openssl-3.1.4/providers/fips/fipsprov.c @@ -105,7 +105,7 @@ void *ossl_fips_prov_ossl_ctx_new(OSSL_L if (fgbl == NULL) return NULL; 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_tls1_prf_ems_check, 1); /* Enabled by default */ init_fips_option(&fgbl->fips_restricted_drgb_digests, 0); return fgbl; } Index: openssl-3.1.4/providers/implementations/kdfs/tls1_prf.c =================================================================== --- openssl-3.1.4.orig/providers/implementations/kdfs/tls1_prf.c +++ openssl-3.1.4/providers/implementations/kdfs/tls1_prf.c @@ -222,6 +222,27 @@ static int kdf_tls1_prf_derive(void *vct } } + /* + * 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". + */ +#ifdef FIPS_MODULE + if (ctx->seedlen >= TLS_MD_MASTER_SECRET_CONST_SIZE + && memcmp(ctx->seed, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) + ctx->fips_indicator = EVP_KDF_SUSE_FIPS_INDICATOR_NOT_APPROVED; +#endif /* defined(FIPS_MODULE) */ + 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: openssl-3.1.4/ssl/ssl_conf.c =================================================================== --- openssl-3.1.4.orig/ssl/ssl_conf.c +++ openssl-3.1.4/ssl/ssl_conf.c @@ -389,6 +389,7 @@ static int cmd_Options(SSL_CONF_CTX *cct SSL_FLAG_TBL("ClientRenegotiation", SSL_OP_ALLOW_CLIENT_RENEGOTIATION), SSL_FLAG_TBL_INV("EncryptThenMac", SSL_OP_NO_ENCRYPT_THEN_MAC), + SSL_FLAG_TBL("RHNoEnforceEMSinFIPS", SSL_OP_PERMIT_NOEMS_FIPS), SSL_FLAG_TBL("NoRenegotiation", SSL_OP_NO_RENEGOTIATION), SSL_FLAG_TBL("AllowNoDHEKEX", SSL_OP_ALLOW_NO_DHE_KEX), SSL_FLAG_TBL("PrioritizeChaCha", SSL_OP_PRIORITIZE_CHACHA), Index: openssl-3.1.4/ssl/statem/extensions_srvr.c =================================================================== --- openssl-3.1.4.orig/ssl/statem/extensions_srvr.c +++ openssl-3.1.4/ssl/statem/extensions_srvr.c @@ -11,6 +11,7 @@ #include "../ssl_local.h" #include "statem_local.h" #include "internal/cryptlib.h" +#include #define COOKIE_STATE_FORMAT_VERSION 1 @@ -1552,8 +1553,13 @@ EXT_RETURN tls_construct_stoc_etm(SSL *s EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context, X509 *x, size_t chainidx) { - if ((s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0) + if ((s->s3.flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0) { + if (FIPS_mode() && !(SSL_get_options(s) & SSL_OP_PERMIT_NOEMS_FIPS) ) { + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_UNSUPPORTED); + return EXT_RETURN_FAIL; + } return EXT_RETURN_NOT_SENT; + } if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret) || !WPACKET_put_bytes_u16(pkt, 0)) { Index: openssl-3.1.4/ssl/t1_enc.c =================================================================== --- openssl-3.1.4.orig/ssl/t1_enc.c +++ openssl-3.1.4/ssl/t1_enc.c @@ -20,6 +20,7 @@ #include #include #include +#include /* seed1 through seed5 are concatenated */ static int tls1_PRF(SSL *s, @@ -75,8 +76,14 @@ static int tls1_PRF(SSL *s, } err: - if (fatal) - SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + if (fatal) { + /* The calls to this function are local so it's safe to implement the check */ + if (FIPS_mode() && seed1_len >= TLS_MD_MASTER_SECRET_CONST_SIZE + && memcmp(seed1, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) + SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, ERR_R_UNSUPPORTED); + else + SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR); + } else ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); EVP_KDF_CTX_free(kctx); Index: openssl-3.1.4/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt =================================================================== --- openssl-3.1.4.orig/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt +++ openssl-3.1.4/test/recipes/30-test_evp_data/evpkdf_tls12_prf.txt @@ -22,6 +22,16 @@ Ctrl.client_random = hexseed:36c129d01a3 Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf +Availablein = fips +KDF = TLS1-PRF +Ctrl.digest = digest:SHA256 +Ctrl.Secret = hexsecret:f8938ecc9edebc5030c0c6a441e213cd24e6f770a50dda07876f8d55da062bcadb386b411fd4fe4313a604fce6c17fbc +Ctrl.label = seed:master secret +Ctrl.client_random = hexseed:36c129d01a3200894b9179faac589d9835d58775f9b5ea3587cb8fd0364cae8c +Ctrl.server_random = hexseed:f6c9575ed7ddd73e1f7d16eca115415812a43c2b747daaaae043abfb50053fce +Output = 202c88c00f84a17a20027079604787461176455539e705be730890602c289a5001e34eeb3a043e5d52a65e66125188bf +Result = KDF_DERIVE_ERROR + FIPSversion = <=3.1.0 KDF = TLS1-PRF Ctrl.digest = digest:SHA256