From 50ea5cdcb735916591e35a04c1f5a659bf253ddc Mon Sep 17 00:00:00 2001 From: slontis Date: Wed, 8 Feb 2023 17:22:43 +1000 Subject: Add option to FIPS module to enforce EMS check during KDF TLS1_PRF. Fixes #19989 Reviewed-by: Paul Dale Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/20241) --- providers/common/include/prov/proverr.h | 2 +- providers/common/include/prov/securitycheck.h | 1 + providers/common/provider_err.c | 3 ++- providers/common/securitycheck_default.c | 6 +++++ providers/common/securitycheck_fips.c | 6 +++++ providers/fips/fipsprov.c | 32 +++++++++++++++++++++++++-- providers/implementations/kdfs/tls1_prf.c | 26 ++++++++++++++++++++++ 7 files changed, 72 insertions(+), 4 deletions(-) (limited to 'providers') diff --git a/providers/common/include/prov/proverr.h b/providers/common/include/prov/proverr.h index 8ad6cc048d..69e14465c7 100644 --- a/providers/common/include/prov/proverr.h +++ b/providers/common/include/prov/proverr.h @@ -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 diff --git a/providers/common/include/prov/securitycheck.h b/providers/common/include/prov/securitycheck.h index 4a7f85f711..62e60cc010 100644 --- a/providers/common/include/prov/securitycheck.h +++ b/providers/common/include/prov/securitycheck.h @@ -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); diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index f6144072aa..954aabe80c 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -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), diff --git a/providers/common/securitycheck_default.c b/providers/common/securitycheck_default.c index de7f0d3a0a..63c875ecd0 100644 --- a/providers/common/securitycheck_default.c +++ b/providers/common/securitycheck_default.c @@ -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) { diff --git a/providers/common/securitycheck_fips.c b/providers/common/securitycheck_fips.c index b7659bd395..2bc8a59926 100644 --- a/providers/common/securitycheck_fips.c +++ b/providers/common/securitycheck_fips.c @@ -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) { diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index ab58ab891d..a16c379fba 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -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) { diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c index 8a38073084..2c2dbf31cc 100644 --- a/providers/implementations/kdfs/tls1_prf.c +++ b/providers/implementations/kdfs/tls1_prf.c @@ -45,6 +45,13 @@ * A(0) = seed * A(i) = HMAC_(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 #include #include @@ -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, -- cgit v1.2.1