Index: openssl-3.5.0/crypto/context.c =================================================================== --- openssl-3.5.0.orig/crypto/context.c +++ openssl-3.5.0/crypto/context.c @@ -85,6 +85,8 @@ struct ossl_lib_ctx_st { #endif STACK_OF(SSL_COMP) *comp_methods; + void *legacy_digest_signatures; + int ischild; int conf_diagnostics; }; @@ -119,6 +121,23 @@ int ossl_lib_ctx_is_child(OSSL_LIB_CTX * return ctx->ischild; } +static void ossl_ctx_legacy_digest_signatures_free(void *vldsigs) +{ + OSSL_LEGACY_DIGEST_SIGNATURES *ldsigs = vldsigs; + + if (ldsigs != NULL) { + OPENSSL_free(ldsigs); + } +} + +static void *ossl_ctx_legacy_digest_signatures_new(OSSL_LIB_CTX *ctx) +{ + OSSL_LEGACY_DIGEST_SIGNATURES* ldsigs = OPENSSL_zalloc(sizeof(OSSL_LEGACY_DIGEST_SIGNATURES)); + /* Default to allow SHA-1 and support disabling it via config. */ + ldsigs->allowed = 1; + return ldsigs; +} + static void context_deinit_objs(OSSL_LIB_CTX *ctx); static int context_init(OSSL_LIB_CTX *ctx) @@ -235,6 +256,10 @@ static int context_init(OSSL_LIB_CTX *ct goto err; #endif + ctx->legacy_digest_signatures = ossl_ctx_legacy_digest_signatures_new(ctx); + if (ctx->legacy_digest_signatures == NULL) + goto err; + /* Low priority. */ #ifndef FIPS_MODULE ctx->child_provider = ossl_child_prov_ctx_new(ctx); @@ -382,6 +407,11 @@ static void context_deinit_objs(OSSL_LIB } #endif + if (ctx->legacy_digest_signatures != NULL) { + ossl_ctx_legacy_digest_signatures_free(ctx->legacy_digest_signatures); + ctx->legacy_digest_signatures = NULL; + } + /* Low priority. */ #ifndef FIPS_MODULE if (ctx->child_provider != NULL) { @@ -660,6 +690,9 @@ void *ossl_lib_ctx_get_data(OSSL_LIB_CTX case OSSL_LIB_CTX_COMP_METHODS: return (void *)&ctx->comp_methods; + case OSSL_LIB_CTX_LEGACY_DIGEST_SIGNATURES_INDEX: + return ctx->legacy_digest_signatures; + default: return NULL; } @@ -714,3 +747,44 @@ void OSSL_LIB_CTX_set_conf_diagnostics(O return; libctx->conf_diagnostics = value; } + +static OSSL_LEGACY_DIGEST_SIGNATURES *ossl_ctx_legacy_digest_signatures( + OSSL_LIB_CTX *libctx, int loadconfig) +{ +#ifndef FIPS_MODULE + if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL)) + return NULL; +#endif + + return ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_LEGACY_DIGEST_SIGNATURES_INDEX); +} + +int ossl_ctx_legacy_digest_signatures_allowed(OSSL_LIB_CTX *libctx, int loadconfig) +{ + OSSL_LEGACY_DIGEST_SIGNATURES *ldsigs + = ossl_ctx_legacy_digest_signatures(libctx, loadconfig); + + #ifndef FIPS_MODULE + if (ossl_safe_getenv("OPENSSL_ENABLE_SHA1_SIGNATURES") != NULL) + /* This is to be used in tests if SHA-1 is disabled. */ + return 1; + #endif + + /* Default to allow SHA-1 and support disabling it via config. */ + return ldsigs != NULL ? ldsigs->allowed : 1; +} + +int ossl_ctx_legacy_digest_signatures_allowed_set(OSSL_LIB_CTX *libctx, int allow, + int loadconfig) +{ + OSSL_LEGACY_DIGEST_SIGNATURES *ldsigs + = ossl_ctx_legacy_digest_signatures(libctx, loadconfig); + + if (ldsigs == NULL) { + ERR_raise(ERR_LIB_EVP, ERR_R_INTERNAL_ERROR); + return 0; + } + + ldsigs->allowed = allow; + return 1; +} Index: openssl-3.5.0/crypto/evp/evp_cnf.c =================================================================== --- openssl-3.5.0.orig/crypto/evp/evp_cnf.c +++ openssl-3.5.0/crypto/evp/evp_cnf.c @@ -10,6 +10,7 @@ #include #include #include "internal/cryptlib.h" +#include "internal/sslconf.h" #include #include #include @@ -57,6 +58,18 @@ static int alg_module_init(CONF_IMODULE ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE); return 0; } + } else if (strcmp(oval->name, "rh-allow-sha1-signatures") == 0) { + int m; + + /* Detailed error already reported. */ + if (!X509V3_get_value_bool(oval, &m)) + return 0; + + if (!ossl_ctx_legacy_digest_signatures_allowed_set( + NCONF_get0_libctx((CONF *)cnf), m > 0, 0)) { + ERR_raise(ERR_LIB_EVP, EVP_R_SET_DEFAULT_PROPERTY_FAILURE); + return 0; + } } else { ERR_raise_data(ERR_LIB_EVP, EVP_R_UNKNOWN_OPTION, "name=%s, value=%s", oval->name, oval->value); Index: openssl-3.5.0/crypto/evp/m_sigver.c =================================================================== --- openssl-3.5.0.orig/crypto/evp/m_sigver.c +++ openssl-3.5.0/crypto/evp/m_sigver.c @@ -15,6 +15,7 @@ #include "internal/provider.h" #include "internal/numbers.h" /* includes SIZE_MAX */ #include "evp_local.h" +#include "internal/sslconf.h" static int update(EVP_MD_CTX *ctx, const void *data, size_t datalen) { @@ -251,6 +252,18 @@ static int do_sigver_init(EVP_MD_CTX *ct } } + if (ctx->reqdigest != NULL + && !EVP_PKEY_is_a(locpctx->pkey, SN_hmac) + && !EVP_PKEY_is_a(locpctx->pkey, SN_tls1_prf) + && !EVP_PKEY_is_a(locpctx->pkey, SN_hkdf)) { + int mdnid = EVP_MD_nid(ctx->reqdigest); + if (!ossl_ctx_legacy_digest_signatures_allowed(locpctx->libctx, 0) + && (mdnid == NID_sha1 || mdnid == NID_md5_sha1)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST); + goto err; + } + } + if (ver) { if (signature->digest_verify_init == NULL) { ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR); Index: openssl-3.5.0/crypto/evp/pmeth_lib.c =================================================================== --- openssl-3.5.0.orig/crypto/evp/pmeth_lib.c +++ openssl-3.5.0/crypto/evp/pmeth_lib.c @@ -33,6 +33,7 @@ #include "internal/ffc.h" #include "internal/numbers.h" #include "internal/provider.h" +#include "internal/sslconf.h" #include "evp_local.h" #ifndef FIPS_MODULE @@ -954,6 +955,20 @@ static int evp_pkey_ctx_set_md(EVP_PKEY_ return -2; } + if (EVP_PKEY_CTX_IS_SIGNATURE_OP(ctx) + && md != NULL + && ctx->pkey != NULL + && !EVP_PKEY_is_a(ctx->pkey, SN_hmac) + && !EVP_PKEY_is_a(ctx->pkey, SN_tls1_prf) + && !EVP_PKEY_is_a(ctx->pkey, SN_hkdf)) { + int mdnid = EVP_MD_nid(md); + if ((mdnid == NID_sha1 || mdnid == NID_md5_sha1) + && !ossl_ctx_legacy_digest_signatures_allowed(ctx->libctx, 0)) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_DIGEST); + return -1; + } + } + if (fallback) return EVP_PKEY_CTX_ctrl(ctx, -1, op, ctrl, 0, (void *)(md)); Index: openssl-3.5.0/doc/man5/config.pod =================================================================== --- openssl-3.5.0.orig/doc/man5/config.pod +++ openssl-3.5.0/doc/man5/config.pod @@ -315,6 +315,21 @@ Within the algorithm properties section, The value may be anything that is acceptable as a property query string for EVP_set_default_properties(). +=item B + +The value is a boolean that can be B or B. If the value is not set, +it behaves as if it was set to B. + +When set to B, any attempt to create or verify a signature with a SHA1 +digest will fail. To test whether your software will work with future versions +of OpenSSL, set this option to B. This setting also affects TLS, where +signature algorithms that use SHA1 as digest will no longer be supported if +this option is set to B. Because TLS 1.1 or lower use MD5-SHA1 as +pseudorandom function (PRF) to derive key material, disabling +B requires the use of TLS 1.2 or newer. + +This is a downstream specific option, and normally it should be set up via crypto-policies. + =item B (deprecated) The value is a boolean that can be B or B. If the value is Index: openssl-3.5.0/include/crypto/context.h =================================================================== --- openssl-3.5.0.orig/include/crypto/context.h +++ openssl-3.5.0/include/crypto/context.h @@ -48,3 +48,11 @@ void ossl_release_default_drbg_ctx(void) #if defined(OPENSSL_THREADS) void ossl_threads_ctx_free(void *); #endif + +#ifndef OSSL_LEGACY_DIGEST_SIGNATURES_STRUCT +#define OSSL_LEGACY_DIGEST_SIGNATURES_STRUCT +typedef struct ossl_legacy_digest_signatures_st { + int allowed; +} OSSL_LEGACY_DIGEST_SIGNATURES; +#endif + Index: openssl-3.5.0/include/internal/cryptlib.h =================================================================== --- openssl-3.5.0.orig/include/internal/cryptlib.h +++ openssl-3.5.0/include/internal/cryptlib.h @@ -120,7 +120,8 @@ typedef struct ossl_ex_data_global_st { # define OSSL_LIB_CTX_DECODER_CACHE_INDEX 20 # define OSSL_LIB_CTX_COMP_METHODS 21 # define OSSL_LIB_CTX_INDICATOR_CB_INDEX 22 -# define OSSL_LIB_CTX_MAX_INDEXES 22 +# define OSSL_LIB_CTX_LEGACY_DIGEST_SIGNATURES_INDEX 23 +# define OSSL_LIB_CTX_MAX_INDEXES 23 OSSL_LIB_CTX *ossl_lib_ctx_get_concrete(OSSL_LIB_CTX *ctx); int ossl_lib_ctx_is_default(OSSL_LIB_CTX *ctx); Index: openssl-3.5.0/include/internal/sslconf.h =================================================================== --- openssl-3.5.0.orig/include/internal/sslconf.h +++ openssl-3.5.0/include/internal/sslconf.h @@ -18,4 +18,8 @@ int conf_ssl_name_find(const char *name, void conf_ssl_get_cmd(const SSL_CONF_CMD *cmd, size_t idx, char **cmdstr, char **arg); +/* Methods to support disabling all signatures with legacy digests */ +int ossl_ctx_legacy_digest_signatures_allowed(OSSL_LIB_CTX *libctx, int loadconfig); +int ossl_ctx_legacy_digest_signatures_allowed_set(OSSL_LIB_CTX *libctx, int allow, + int loadconfig); #endif Index: openssl-3.5.0/providers/common/include/prov/securitycheck.h =================================================================== --- openssl-3.5.0.orig/providers/common/include/prov/securitycheck.h +++ openssl-3.5.0/providers/common/include/prov/securitycheck.h @@ -37,3 +37,5 @@ int ossl_digest_get_approved_nid(const E /* Functions that have different implementations for the FIPS_MODULE */ int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md); int ossl_fips_config_securitycheck_enabled(OSSL_LIB_CTX *libctx); + +int rh_digest_signatures_allowed(OSSL_LIB_CTX *libctx, int mdnid); Index: openssl-3.5.0/providers/common/securitycheck.c =================================================================== --- openssl-3.5.0.orig/providers/common/securitycheck.c +++ openssl-3.5.0/providers/common/securitycheck.c @@ -19,6 +19,7 @@ #include #include #include "prov/securitycheck.h" +#include "internal/sslconf.h" #define OSSL_FIPS_MIN_SECURITY_STRENGTH_BITS 112 @@ -220,3 +221,16 @@ int ossl_dh_check_key(const DH *dh) return (L == 2048 && (N == 224 || N == 256)); } #endif /* OPENSSL_NO_DH */ + +int rh_digest_signatures_allowed(OSSL_LIB_CTX *libctx, int mdnid) +{ +#ifndef FIPS_MODULE + if (!ossl_ctx_legacy_digest_signatures_allowed(libctx, 0)) + /* SHA1 is globally disabled, check whether we want to locally allow + * it. */ +#endif + if (mdnid == NID_sha1) + mdnid = -1; + + return mdnid; +} Index: openssl-3.5.0/providers/common/securitycheck_default.c =================================================================== --- openssl-3.5.0.orig/providers/common/securitycheck_default.c +++ openssl-3.5.0/providers/common/securitycheck_default.c @@ -15,6 +15,7 @@ #include #include "prov/securitycheck.h" #include "internal/nelem.h" +#include "internal/sslconf.h" /* Disable the security checks in the default provider */ int ossl_fips_config_securitycheck_enabled(OSSL_LIB_CTX *libctx) Index: openssl-3.5.0/providers/implementations/signature/dsa_sig.c =================================================================== --- openssl-3.5.0.orig/providers/implementations/signature/dsa_sig.c +++ openssl-3.5.0/providers/implementations/signature/dsa_sig.c @@ -163,6 +163,7 @@ static int dsa_setup_md(PROV_DSA_CTX *ct md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); md_nid = ossl_digest_get_approved_nid(md); + md_nid = rh_digest_signatures_allowed(ctx->libctx, md_nid); if (md == NULL) { ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, Index: openssl-3.5.0/providers/implementations/signature/ecdsa_sig.c =================================================================== --- openssl-3.5.0.orig/providers/implementations/signature/ecdsa_sig.c +++ openssl-3.5.0/providers/implementations/signature/ecdsa_sig.c @@ -197,13 +197,16 @@ static int ecdsa_setup_md(PROV_ECDSA_CTX goto err; } md_nid = ossl_digest_get_approved_nid(md); + #ifdef FIPS_MODULE - if (md_nid == NID_undef) { + md_nid = rh_digest_signatures_allowed(ctx->libctx, md_nid); + if (md_nid <= 0) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest=%s", mdname); goto err; } #endif + /* XOF digests don't work */ if (EVP_MD_xof(md)) { ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED); Index: openssl-3.5.0/providers/implementations/signature/rsa_sig.c =================================================================== --- openssl-3.5.0.orig/providers/implementations/signature/rsa_sig.c +++ openssl-3.5.0/providers/implementations/signature/rsa_sig.c @@ -26,6 +26,7 @@ #include "internal/cryptlib.h" #include "internal/nelem.h" #include "internal/sizes.h" +#include "internal/sslconf.h" #include "crypto/rsa.h" #include "prov/providercommon.h" #include "prov/implementations.h" @@ -34,6 +35,7 @@ #include "prov/securitycheck.h" #define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1 +#define RSA_DEFAULT_DIGEST_NAME_NONLEGACY OSSL_DIGEST_NAME_SHA2_256 OSSL_FUNC_signature_newctx_fn rsa_newctx; static OSSL_FUNC_signature_sign_init_fn rsa_sign_init; @@ -387,7 +389,8 @@ static int rsa_setup_md(PROV_RSA_CTX *ct goto err; } md_nid = ossl_digest_rsa_sign_get_md_nid(md); - if (md_nid == NID_undef) { + md_nid = rh_digest_signatures_allowed(ctx->libctx, md_nid); + if (md_nid <= 0) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest=%s", mdname); goto err; @@ -475,8 +478,9 @@ static int rsa_setup_mgf1_md(PROV_RSA_CT "%s could not be fetched", mdname); return 0; } - /* The default for mgf1 is SHA1 - so allow SHA1 */ + /* The default for mgf1 is SHA1 - so check if we allow SHA1 */ if ((mdnid = ossl_digest_rsa_sign_get_md_nid(md)) <= 0 + || (mdnid = rh_digest_signatures_allowed(ctx->libctx, mdnid)) <= 0 || !rsa_check_padding(ctx, NULL, mdname, mdnid)) { if (mdnid <= 0) ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, @@ -1765,8 +1769,13 @@ static int rsa_set_ctx_params(void *vprs prsactx->pad_mode = pad_mode; if (prsactx->md == NULL && pmdname == NULL - && pad_mode == RSA_PKCS1_PSS_PADDING) - pmdname = RSA_DEFAULT_DIGEST_NAME; + && pad_mode == RSA_PKCS1_PSS_PADDING) { + if (ossl_ctx_legacy_digest_signatures_allowed(prsactx->libctx, 0)) { + pmdname = RSA_DEFAULT_DIGEST_NAME; + } else { + pmdname = RSA_DEFAULT_DIGEST_NAME_NONLEGACY; + } + } if (pmgf1mdname != NULL && !rsa_setup_mgf1_md(prsactx, pmgf1mdname, pmgf1mdprops)) Index: openssl-3.5.0/ssl/t1_lib.c =================================================================== --- openssl-3.5.0.orig/ssl/t1_lib.c +++ openssl-3.5.0/ssl/t1_lib.c @@ -21,6 +21,7 @@ #include #include #include +#include "internal/sslconf.h" #include "internal/nelem.h" #include "internal/sizes.h" #include "internal/tlsgroups.h" @@ -2176,6 +2177,7 @@ int ssl_setup_sigalgs(SSL_CTX *ctx) EVP_PKEY *tmpkey = EVP_PKEY_new(); int istls; int ret = 0; + int ldsigs_allowed; if (ctx == NULL) goto err; @@ -2193,6 +2195,7 @@ int ssl_setup_sigalgs(SSL_CTX *ctx) goto err; ERR_set_mark(); + ldsigs_allowed = ossl_ctx_legacy_digest_signatures_allowed(ctx->libctx, 0); /* First fill cache and tls12_sigalgs list from legacy algorithm list */ for (i = 0, lu = sigalg_lookup_tbl; i < OSSL_NELEM(sigalg_lookup_tbl); lu++, i++) { @@ -2213,6 +2216,11 @@ int ssl_setup_sigalgs(SSL_CTX *ctx) cache[i].available = 0; continue; } + if ((lu->hash == NID_sha1 || lu->hash == NID_md5_sha1) + && !ldsigs_allowed) { + cache[i].available = 0; + continue; + } if (!EVP_PKEY_set_type(tmpkey, lu->sig)) { cache[i].available = 0; Index: openssl-3.5.0/util/libcrypto.num =================================================================== --- openssl-3.5.0.orig/util/libcrypto.num +++ openssl-3.5.0/util/libcrypto.num @@ -5925,3 +5925,5 @@ OSSL_AA_DIST_POINT_free OSSL_AA_DIST_POINT_new 6052 3_5_0 EXIST::FUNCTION: OSSL_AA_DIST_POINT_it 6053 3_5_0 EXIST::FUNCTION: PEM_ASN1_write_bio_ctx 6054 3_5_0 EXIST::FUNCTION: +ossl_ctx_legacy_digest_signatures_allowed ? 3_0_1 EXIST::FUNCTION: +ossl_ctx_legacy_digest_signatures_allowed_set ? 3_0_1 EXIST::FUNCTION: