Commit 053374bc48 for openssl.org

commit 053374bc481c7bf7a19ef49314621fa66d761ac9
Author: Jan Luebbe <jlu@pengutronix.de>
Date:   Thu Sep 17 15:39:50 2026 +0200

    CMS_verify(): avoid queued errors on successful return

    When partial verification returns 1, an error produced only by a signer
    whose failure was tolerated shouldn't remain on the error queue. An
    error that was already queued before CMS_verify should remain untouched.

    This matters because the leftover entry can later be reported as the
    reason for an unrelated failure. It also makes a successful CMS_verify
    call look as though it failed when the queue is inspected for
    diagnostics.

    Add an error queue mark so that we can drop tolerated errors if the
    overall verification due to CMS_VERIFY_PARTIAL. Keep the queued errors
    (but remove the mark) when return we return with an error status.

    Fixes #32611

    Reviewed-by: Todd Short <todd.short@me.com>
    Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
    Reviewed-by: Tomas Mraz <tomas@openssl.foundation>
    Merge-date: Tue Sep 29 16:21:44 2026
    Merged-from: https://github.com/openssl/openssl/pull/32870

diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c
index ae99d1b27f..5ca8e6606c 100644
--- a/crypto/cms/cms_smime.c
+++ b/crypto/cms/cms_smime.c
@@ -357,6 +357,8 @@ int CMS_verify(CMS_ContentInfo *cms, const STACK_OF(X509) *certs,

     if (dcont == NULL && !check_content(cms))
         return 0;
+    /* Set a mark so that we can clear any new errors on success. */
+    (void)ERR_set_mark();
     if (dcont != NULL && !(flags & CMS_BINARY)) {
         const ASN1_OBJECT *coid = CMS_get0_eContentType(cms);

@@ -563,6 +565,15 @@ err2:
     sk_X509_pop_free(untrusted, X509_free);
     sk_X509_CRL_pop_free(crls, X509_CRL_free);

+    /*
+     * On error, keep internal errors for inspection by the caller. Otherwise
+     * clear any new errors queued since the mark.
+     */
+    if (!ret)
+        ERR_clear_last_mark();
+    else
+        ERR_pop_to_mark();
+
     return ret;
 }