Commit 403dbe58ca for openssl.org

commit 403dbe58caa08b30ed2c63dca42db5d952a6ae32
Author: Bob Beck <beck@openssl.org>
Date:   Thu Sep 3 17:28:44 2026 -0600

    Compute X509_get_signature_info() on demand, not in the cache

    The signature info was computed once by ossl_x509v3_cache_extensions()
    and stored in X509::siginf. Its security bits depend on a digest fetch
    under the certificate's libctx/propq, so the cached answer was frozen
    to the context the certificate was parsed in.

    Compute it in X509_get_signature_info() instead. The siginf field and
    ossl_x509_init_sig_info() are removed.

    Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    Merge-date: Thu Sep 17 16:44:34 2026
    Merged-from: https://github.com/openssl/openssl/pull/32686

diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index 8e685103c5..e49ac312f5 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -519,7 +519,6 @@ static void scan_ext_flags(const X509 *x509, uint32_t *flags)
  * Cache info on various X.509v3 extensions and further derived information,
  * e.g., if cert 'x' is self-issued, in x->ex_flags and other internal fields.
  * x->fingerprint is filled in, or else EXFLAG_NO_FINGERPRINT is set in x->flags.
- * X509_SIG_INFO_VALID is set in x->flags if x->siginf was filled successfully.
  * Set EXFLAG_INVALID and return 0 in case the certificate is invalid.
  *
  * This is usually called by side-effect on objects, and forces us to keep
@@ -548,7 +547,6 @@ int ossl_x509v3_cache_extensions(const X509 *const_x)
     STACK_OF(GENERAL_NAME) *tmp_altname;
     NAME_CONSTRAINTS *tmp_nc;
     STACK_OF(DIST_POINT) *tmp_crldp = NULL;
-    X509_SIG_INFO tmp_siginf;

 #ifdef tsan_ld_acq
     /* Fast lock-free check, see end of the function for details. */
@@ -751,9 +749,6 @@ int ossl_x509v3_cache_extensions(const X509 *const_x)

     scan_ext_flags(const_x, &tmp_ex_flags);

-    /* Set x->siginf, ignoring errors due to unsupported algos */
-    (void)ossl_x509_init_sig_info(const_x, &tmp_siginf);
-
     tmp_ex_flags |= EXFLAG_SET; /* Indicate that cert has been processed */
     ERR_pop_to_mark();

@@ -790,7 +785,6 @@ int ossl_x509v3_cache_extensions(const X509 *const_x)
     ASIdentifiers_free(((X509 *)const_x)->rfc3779_asid);
     ((X509 *)const_x)->rfc3779_asid = tmp_rfc3779_asid;
 #endif
-    ((X509 *)const_x)->siginf = tmp_siginf;

 #ifdef tsan_st_rel
     tsan_st_rel((TSAN_QUALIFIER int *)&const_x->ex_cached, 1);
diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c
index 8b36ea6bd7..9096c0915d 100644
--- a/crypto/x509/x509_set.c
+++ b/crypto/x509/x509_set.c
@@ -202,13 +202,6 @@ void X509_SIG_INFO_set(X509_SIG_INFO *siginf, int mdnid, int pknid,
     siginf->flags = flags;
 }

-int X509_get_signature_info(const X509 *x, int *mdnid, int *pknid, int *secbits,
-    uint32_t *flags)
-{
-    X509_check_purpose(x, -1, -1);
-    return X509_SIG_INFO_get(&x->siginf, mdnid, pknid, secbits, flags);
-}
-
 /* 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,
@@ -312,9 +305,18 @@ static int x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
     return 1;
 }

-/* Returns 1 on success, 0 on failure */
-int ossl_x509_init_sig_info(const X509 *x, X509_SIG_INFO *info)
+int X509_get_signature_info(const X509 *x, int *mdnid, int *pknid, int *secbits,
+    uint32_t *flags)
 {
-    return x509_sig_info_init(info, &x->sig_alg, &x->signature,
+    X509_SIG_INFO siginf;
+
+    if (x == NULL) {
+        ERR_raise(ERR_LIB_X509, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    ERR_set_mark();
+    (void)x509_sig_info_init(&siginf, &x->sig_alg, &x->signature,
         X509_PUBKEY_get0(x->cert_info.key), x->libctx, x->propq);
+    ERR_pop_to_mark();
+    return X509_SIG_INFO_get(&siginf, mdnid, pknid, secbits, flags);
 }
diff --git a/doc/internal/man3/x509v3_cache_extensions.pod b/doc/internal/man3/x509v3_cache_extensions.pod
index 8f3dffc859..ecd7818f17 100644
--- a/doc/internal/man3/x509v3_cache_extensions.pod
+++ b/doc/internal/man3/x509v3_cache_extensions.pod
@@ -23,8 +23,6 @@ and stores the result in x->fingerprint;
 on failure (the certificate cannot be DER encoded, for instance because it is
 still under construction, or memory allocation failed) it sets
 B<EXFLAG_NO_FINGERPRINT> in x->flags instead.
-It sets B<X509_SIG_INFO_VALID> in x->flags if x->siginf was filled successfully,
-which may not be possible if a referenced algorithm is unknown or not available.
 Many OpenSSL functions that use an X509 object call this function implicitly.

 =head1 RETURN VALUES
diff --git a/include/crypto/x509.h b/include/crypto/x509.h
index bb575b57a5..515ea15530 100644
--- a/include/crypto/x509.h
+++ b/include/crypto/x509.h
@@ -178,7 +178,6 @@ struct x509_st {
     X509_CINF cert_info;
     X509_ALGOR sig_alg;
     ASN1_BIT_STRING signature;
-    X509_SIG_INFO siginf;
     CRYPTO_REF_COUNT references;
     CRYPTO_EX_DATA ex_data;
     /* These contain copies of various extension values */
@@ -318,7 +317,6 @@ int ossl_a2i_ipadd(unsigned char *ipout, const char *ipasc);
 int ossl_x509_set1_time(int *modified, ASN1_TIME **ptm, const ASN1_TIME *tm);
 int ossl_x509_print_ex_brief(BIO *bio, const X509 *cert, unsigned long neg_cflags);
 int ossl_x509v3_cache_extensions(const X509 *x);
-int ossl_x509_init_sig_info(const X509 *x, X509_SIG_INFO *info);

 /**
  * @brief Compute the internal-use fingerprint of a DER-encodable object.