Commit 614296c786 for openssl.org

commit 614296c786e7e88c98d0c86e76e831657f7233f1
Author: Bob Beck <beck@openssl.org>
Date:   Fri Sep 4 14:13:34 2026 -0600

    Decode CMP responses in the CMP context's library context

    OSSL_CMP_MSG_http_perform() decoded responses with a NULL library
    context, so the certificates in them, and the public keys decoded
    from those, belonged to the default context. Setting the CMP context
    on newCert afterwards reached the X509 but not its public key.
    Decode in the CMP context instead.

    Add internal ossl_x509_digest_sig_ex() taking the library context
    explicitly and use it with the CMP context's when hashing newCert
    for certConf. X509_digest_sig() is unchanged.

    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
    Merge-date: Mon Oct 26 19:04:41 2026
    Merged-from: https://github.com/openssl/openssl/pull/32690

diff --git a/crypto/cmp/cmp_http.c b/crypto/cmp/cmp_http.c
index cb2d5d8340..ee1396ea6d 100644
--- a/crypto/cmp/cmp_http.c
+++ b/crypto/cmp/cmp_http.c
@@ -89,8 +89,13 @@ OSSL_CMP_MSG *OSSL_CMP_MSG_http_perform(OSSL_CMP_CTX *ctx,
         ctx->msg_timeout,
         keep_alive(ctx->keep_alive, req->body->type, bios));
     BIO_free(req_mem);
-    res = (OSSL_CMP_MSG *)ASN1_item_d2i_bio(it, rsp, NULL);
+    res = (OSSL_CMP_MSG *)ASN1_item_d2i_bio_ex(it, rsp, NULL,
+        ctx->libctx, ctx->propq);
     BIO_free(rsp);
+    if (res != NULL && !ossl_cmp_msg_set0_libctx(res, ctx->libctx, ctx->propq)) {
+        OSSL_CMP_MSG_free(res);
+        res = NULL;
+    }

     if (ctx->http_ctx == NULL)
         ossl_cmp_debug(ctx, "disconnected from CMP server");
diff --git a/crypto/cmp/cmp_msg.c b/crypto/cmp/cmp_msg.c
index abea670ce9..044cf83979 100644
--- a/crypto/cmp/cmp_msg.c
+++ b/crypto/cmp/cmp_msg.c
@@ -900,7 +900,9 @@ OSSL_CMP_MSG *ossl_cmp_certConf_new(OSSL_CMP_CTX *ctx, int certReqId,
      * as is used to create and verify the certificate signature.
      * If not available, a fallback hash algorithm is used.
      */
-    if ((certHash = X509_digest_sig(ctx->newCert, &md, &is_fallback)) == NULL)
+    if ((certHash = ossl_x509_digest_sig_ex(ctx->newCert, &md, &is_fallback,
+             ctx->libctx, ctx->propq))
+        == NULL)
         goto err;
     if (is_fallback) {
         if (!ossl_cmp_hdr_set_pvno(msg->header, OSSL_CMP_PVNO_3))
diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c
index f358119332..243ecc461c 100644
--- a/crypto/x509/x_all.c
+++ b/crypto/x509/x_all.c
@@ -676,9 +676,9 @@ int X509_digest(const X509 *cert, const EVP_MD *md, unsigned char *data,
         data, len, cert->libctx, cert->propq);
 }

-/* calculate cert digest using the same hash algorithm as in its signature */
-ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
-    EVP_MD **md_used, int *md_is_fallback)
+ASN1_OCTET_STRING *ossl_x509_digest_sig_ex(const X509 *cert,
+    EVP_MD **md_used, int *md_is_fallback,
+    OSSL_LIB_CTX *libctx, const char *propq)
 {
     unsigned int len;
     unsigned char hash[EVP_MAX_MD_SIZE];
@@ -692,11 +692,6 @@ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
     if (md_is_fallback != NULL)
         *md_is_fallback = 0;

-    if (cert == NULL) {
-        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
-        return NULL;
-    }
-
     if (!OBJ_find_sigid_algs(X509_get_signature_nid(cert), &mdnid, &pknid)) {
         ERR_raise(ERR_LIB_X509, X509_R_UNKNOWN_SIGID_ALGS);
         return NULL;
@@ -719,8 +714,8 @@ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
             }
             RSA_PSS_PARAMS_free(pss);
             /* Fetch explicitly and do not fallback */
-            if ((md = EVP_MD_fetch(cert->libctx, EVP_MD_get0_name(mmd),
-                     cert->propq))
+            if ((md = EVP_MD_fetch(libctx, EVP_MD_get0_name(mmd),
+                     propq))
                 == NULL)
                 /* Error code from fetch is sufficient */
                 return NULL;
@@ -737,8 +732,8 @@ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
                 md_name = "SHA256";
                 break;
             }
-            if ((md = EVP_MD_fetch(cert->libctx, md_name,
-                     cert->propq))
+            if ((md = EVP_MD_fetch(libctx, md_name,
+                     propq))
                 == NULL)
                 return NULL;
             if (md_is_fallback != NULL)
@@ -748,8 +743,8 @@ ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
             ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
             return NULL;
         }
-    } else if ((md = EVP_MD_fetch(cert->libctx, OBJ_nid2sn(mdnid),
-                    cert->propq))
+    } else if ((md = EVP_MD_fetch(libctx, OBJ_nid2sn(mdnid),
+                    propq))
         == NULL) {
         ERR_raise(ERR_LIB_X509, X509_R_UNSUPPORTED_ALGORITHM);
         return NULL;
@@ -770,6 +765,22 @@ err:
     return NULL;
 }

+/* calculate cert digest using the same hash algorithm as in its signature */
+ASN1_OCTET_STRING *X509_digest_sig(const X509 *cert,
+    EVP_MD **md_used, int *md_is_fallback)
+{
+    if (cert == NULL) {
+        if (md_used != NULL)
+            *md_used = NULL;
+        if (md_is_fallback != NULL)
+            *md_is_fallback = 0;
+        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+        return NULL;
+    }
+    return ossl_x509_digest_sig_ex(cert, md_used, md_is_fallback,
+        cert->libctx, cert->propq);
+}
+
 int X509_CRL_digest(const X509_CRL *data, const EVP_MD *type,
     unsigned char *md, unsigned int *len)
 {
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index 6fd4716769..7c9c1967ec 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -418,6 +418,26 @@ int ossl_x509_crl_verify_ex(X509_CRL *crl, EVP_PKEY *r, OSSL_LIB_CTX *libctx,
 int ossl_x509_get_signature_info_ex(const X509 *x, int *mdnid, int *pknid,
     int *secbits, uint32_t *flags, OSSL_LIB_CTX *libctx, const char *propq);

+/**
+ * @brief Digest a certificate with its own signature digest, fetching from
+ *        @p libctx.
+ *
+ * Like X509_digest_sig(), but the digest is fetched from the given library
+ * context and property query rather than the certificate's own.
+ *
+ * @param cert the certificate to digest
+ * @param md_used where to store the digest used, owned by the caller;
+ *                may be NULL
+ * @param md_is_fallback where to store whether a fallback digest was used
+ *                       because the signature algorithm has none; may be NULL
+ * @param libctx the library context to fetch from, NULL for the default
+ * @param propq the property query to fetch with, may be NULL
+ * @returns the digest as a new ASN1_OCTET_STRING, or NULL on error
+ */
+ASN1_OCTET_STRING *ossl_x509_digest_sig_ex(const X509 *cert,
+    EVP_MD **md_used, int *md_is_fallback,
+    OSSL_LIB_CTX *libctx, const char *propq);
+
 int ossl_x509_set0_libctx(X509 *x, OSSL_LIB_CTX *libctx, const char *propq);
 int ossl_x509_crl_set0_libctx(X509_CRL *x, OSSL_LIB_CTX *libctx,
     const char *propq);