Commit dea5c521a6 for openssl.org
commit dea5c521a6a78a1caed451e53a149d327d2a928d
Author: Neil Horman <nhorman@openssl.org>
Date: Mon Mar 16 13:49:07 2026 -0400
Fix NULL deref in [ec]dh_cms_set_shared_info
Multiple independent reports indicated a SIGSEGV was possible in CMS
processing when a crafted CMS EnvelopedData message using A Key
Agreement Recipient Info field. If the
KeyEncryptionAlgorithmIdentifier omits the optional parameter field, the
referenced functions above will attempt to dereference the
alg->parameter data prior to checking if the parameter field is NULL.
Confirmed to resolve the issues using the reproducers provided in the
security reports.
Co-authored-by: Tomas Mraz <tomas@openssl.foundation>
Fixes CVE-2026-28389
Reviewed-by: Saša NedvÄ›dický <sashan@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.foundation>
MergeDate: Mon Apr 6 18:58:28 2026
diff --git a/crypto/cms/cms_dh.c b/crypto/cms/cms_dh.c
index a10df73b10..659ff38b61 100644
--- a/crypto/cms/cms_dh.c
+++ b/crypto/cms/cms_dh.c
@@ -89,16 +89,21 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
int keylen, plen;
EVP_CIPHER *kekcipher = NULL;
EVP_CIPHER_CTX *kekctx;
+ const ASN1_OBJECT *aoid;
+ const void *parameter = NULL;
+ int ptype = 0;
char name[OSSL_MAX_NAME_SIZE];
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
goto err;
+ X509_ALGOR_get0(&aoid, &ptype, ¶meter, alg);
+
/*
* For DH we only have one OID permissible. If ever any more get defined
* we will need something cleverer.
*/
- if (OBJ_obj2nid(alg->algorithm) != NID_id_smime_alg_ESDH) {
+ if (OBJ_obj2nid(aoid) != NID_id_smime_alg_ESDH) {
ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
goto err;
}
@@ -107,11 +112,11 @@ static int dh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
|| EVP_PKEY_CTX_set_dh_kdf_md(pctx, EVP_sha1()) <= 0)
goto err;
- if (alg->parameter->type != V_ASN1_SEQUENCE)
+ if (ptype != V_ASN1_SEQUENCE)
goto err;
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
+ p = ASN1_STRING_get0_data(parameter);
+ plen = ASN1_STRING_length(parameter);
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
if (kekalg == NULL)
goto err;
diff --git a/crypto/cms/cms_ec.c b/crypto/cms/cms_ec.c
index ff8adad616..e60d0a786e 100644
--- a/crypto/cms/cms_ec.c
+++ b/crypto/cms/cms_ec.c
@@ -166,21 +166,27 @@ static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
int plen, keylen;
EVP_CIPHER *kekcipher = NULL;
EVP_CIPHER_CTX *kekctx;
+ const ASN1_OBJECT *aoid = NULL;
+ int ptype = 0;
+ const void *parameter = NULL;
+
char name[OSSL_MAX_NAME_SIZE];
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
return 0;
- if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
+ X509_ALGOR_get0(&aoid, &ptype, ¶meter, alg);
+
+ if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(aoid))) {
ERR_raise(ERR_LIB_CMS, CMS_R_KDF_PARAMETER_ERROR);
return 0;
}
- if (alg->parameter->type != V_ASN1_SEQUENCE)
+ if (ptype != V_ASN1_SEQUENCE)
return 0;
- p = alg->parameter->value.sequence->data;
- plen = alg->parameter->value.sequence->length;
+ p = ASN1_STRING_get0_data(parameter);
+ plen = ASN1_STRING_length(parameter);
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
if (kekalg == NULL)
goto err;