Commit b9ab1f3c01 for openssl.org
commit b9ab1f3c013090ff18d0c65b39216e16d66ac903
Author: Samaresh Kumar Singh <ssam3003@gmail.com>
Date: Fri Apr 17 18:51:08 2026 -0500
Use EVP_MD_fetch() instead of EVP_get_digestbynid() in X509/TLS paths
EVP_get_digestbynid() only searches the legacy built-in digest table and
cannot resolve provider-only digests, which breaks X509 signature info
computation, GOST TLS handshakes, and OCSP cert ID matching when the
digest is loaded exclusively through a provider. Switch the three affected
sites to use EVP_MD_fetch() (with the appropriate libctx/propq).
x509_sig_info_init() gains libctx/propq parameters propagated
from the X509 struct by its caller.
Resolves: https://github.com/openssl/openssl/issues/30604
Reviewed-by: Matt Caswell <matt@openssl.foundation>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
MergeDate: Sun Apr 26 13:13:14 2026
(Merged from https://github.com/openssl/openssl/pull/30888)
diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c
index 18c1f9c8a6..8a2a12e4b6 100644
--- a/crypto/x509/x509_set.c
+++ b/crypto/x509/x509_set.c
@@ -211,10 +211,11 @@ int X509_get_signature_info(const X509 *x, int *mdnid, int *pknid, int *secbits,
/* Modify *siginf according to alg and sig. Return 1 on success, else 0. */
static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
- const ASN1_STRING *sig, const EVP_PKEY *pubkey)
+ const ASN1_STRING *sig, const EVP_PKEY *pubkey,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int pknid, mdnid, md_size;
- const EVP_MD *md;
+ EVP_MD *md;
const EVP_PKEY_ASN1_METHOD *ameth;
siginf->mdnid = NID_undef;
@@ -276,11 +277,25 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
break;
default:
/* Security bits: half number of bits in digest */
- if ((md = EVP_get_digestbynid(mdnid)) == NULL) {
- ERR_raise(ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID);
- return 0;
+ {
+ char md_name[80];
+ ASN1_OBJECT *md_obj = OBJ_nid2obj(mdnid);
+
+ if (md_obj == NULL
+ || i2t_ASN1_OBJECT(md_name, sizeof(md_name), md_obj) <= 0) {
+ ERR_raise_data(ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID,
+ "nid=%d", mdnid);
+ return 0;
+ }
+ md = EVP_MD_fetch(libctx, md_name, propq);
+ if (md == NULL) {
+ ERR_raise_data(ERR_LIB_X509, X509_R_ERROR_GETTING_MD_BY_NID,
+ "nid=%d name=%s", mdnid, md_name);
+ return 0;
+ }
}
md_size = EVP_MD_get_size(md);
+ EVP_MD_free(md);
if (md_size <= 0)
return 0;
siginf->secbits = md_size * 4;
@@ -301,5 +316,5 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
int ossl_x509_init_sig_info(const X509 *x, X509_SIG_INFO *info)
{
return x509_sig_info_init(info, &x->sig_alg, &x->signature,
- X509_PUBKEY_get0(x->cert_info.key));
+ X509_PUBKEY_get0(x->cert_info.key), x->libctx, x->propq);
}
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c
index d1848142b8..3ec7f69104 100644
--- a/crypto/x509/x509_vfy.c
+++ b/crypto/x509/x509_vfy.c
@@ -1284,7 +1284,7 @@ static int check_cert_ocsp_resp(X509_STORE_CTX *ctx)
OCSP_CERTID *sr_cert_id = NULL;
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
ASN1_OBJECT *cert_id_md_oid;
- EVP_MD *cert_id_md;
+ EVP_MD *cert_id_md = NULL;
OCSP_CERTID *cert_id = NULL;
int ret = V_OCSP_CERTSTATUS_UNKNOWN;
int num;
@@ -1317,13 +1317,17 @@ static int check_cert_ocsp_resp(X509_STORE_CTX *ctx)
/* determine the md algorithm which was used to create cert id */
sr_cert_id = (OCSP_CERTID *)OCSP_SINGLERESP_get0_id(sr);
OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, sr_cert_id);
- if (cert_id_md_oid != NULL)
- cert_id_md = (EVP_MD *)EVP_get_digestbyobj(cert_id_md_oid);
- else
- cert_id_md = NULL;
+ if (cert_id_md_oid != NULL) {
+ char md_name[80];
+
+ if (i2t_ASN1_OBJECT(md_name, sizeof(md_name), cert_id_md_oid) > 0)
+ cert_id_md = EVP_MD_fetch(ctx->libctx, md_name, ctx->propq);
+ }
/* search the stack for the requested OCSP response */
cert_id = OCSP_cert_to_id(cert_id_md, ctx->current_cert, ctx->current_issuer);
+ EVP_MD_free(cert_id_md);
+ cert_id_md = NULL;
if (cert_id == NULL) {
ret = X509_V_ERR_OCSP_RESP_INVALID;
goto end;
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 538094478b..7b955111c8 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -3701,6 +3701,7 @@ static int tls_construct_cke_gost(SSL_CONNECTION *s, WPACKET *pkt)
unsigned int md_len;
unsigned char shared_ukm[32], tmp[256];
EVP_MD_CTX *ukm_hash = NULL;
+ EVP_MD *ukm_md = NULL;
int dgst_nid = NID_id_GostR3411_94;
unsigned char *pms = NULL;
size_t pmslen = 0;
@@ -3751,8 +3752,10 @@ static int tls_construct_cke_gost(SSL_CONNECTION *s, WPACKET *pkt)
* data
*/
ukm_hash = EVP_MD_CTX_new();
+ ukm_md = EVP_MD_fetch(sctx->libctx, OBJ_nid2sn(dgst_nid), sctx->propq);
if (ukm_hash == NULL
- || EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
+ || ukm_md == NULL
+ || EVP_DigestInit_ex(ukm_hash, ukm_md, NULL) <= 0
|| EVP_DigestUpdate(ukm_hash, s->s3.client_random,
SSL3_RANDOM_SIZE)
<= 0
@@ -3760,9 +3763,12 @@ static int tls_construct_cke_gost(SSL_CONNECTION *s, WPACKET *pkt)
SSL3_RANDOM_SIZE)
<= 0
|| EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
+ EVP_MD_free(ukm_md);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
goto err;
}
+ EVP_MD_free(ukm_md);
+ ukm_md = NULL;
EVP_MD_CTX_free(ukm_hash);
ukm_hash = NULL;
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,