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, &parameter, 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, &parameter, 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;