Commit c955a435e6 for openssl.org
commit c955a435e603b9b8d7f7b60603d787819e9f50f8
Author: Dr. David von Oheimb <David.von.Oheimb@siemens.com>
Date: Thu Sep 1 18:11:45 2022 +0200
ossl_x509_likely_issued(): fix self-signature check in case issuer equals subject
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
MergeDate: Wed Mar 11 11:22:35 2026
(Merged from https://github.com/openssl/openssl/pull/28373)
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index fb08bac4dd..7b548e32f5 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -615,7 +615,7 @@ int ossl_x509v3_cache_extensions(const X509 *const_x)
if (tmp_akid == NULL && i != -1)
tmp_ex_flags |= EXFLAG_INVALID;
- /* This is very similar to ossl_x509_likely_issued(const_x, const_x) == X509_V_OK */
+ /* Setting EXFLAG_SS is equivalent to ossl_x509_likely_issued(const_x, const_x) == X509_V_OK */
if (X509_NAME_cmp(X509_get_subject_name(const_x), X509_get_issuer_name(const_x)) == 0) {
tmp_ex_flags |= EXFLAG_SI; /* Certificate is self-issued: subject == issuer */
/*
@@ -1049,7 +1049,12 @@ int X509_check_issued(const X509 *issuer, const X509 *subject)
return ossl_x509_signing_allowed(issuer, subject);
}
-/* do the checks 1., 2., and 3. as described above for X509_check_issued() */
+/*
+ * Do the checks 1., 2., and 3. as described above for X509_check_issued().
+ * These are very similar to a section of ossl_x509v3_cache_extensions().
+ * If |issuer| equals |subject| (such that self-signature should be checked),
+ * use the EXFLAG_SS result of ossl_x509v3_cache_extensions().
+ */
int ossl_x509_likely_issued(const X509 *issuer, const X509 *subject)
{
int ret;
@@ -1059,11 +1064,29 @@ int ossl_x509_likely_issued(const X509 *issuer, const X509 *subject)
!= 0)
return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
- /* set issuer->skid and subject->akid */
+ /* set issuer->skid, subject->akid, and subject->ex_flags */
if (!ossl_x509v3_cache_extensions(issuer)
|| !ossl_x509v3_cache_extensions(subject))
return X509_V_ERR_UNSPECIFIED;
+ if (issuer == subject
+ || (X509_NAME_cmp(X509_get_issuer_name(issuer), X509_get_issuer_name(subject)) == 0
+ && ASN1_INTEGER_cmp(X509_get0_serialNumber(issuer), X509_get0_serialNumber(subject)) == 0))
+ /*
+ * At this point, we can assume that issuer and subject
+ * are semantically the same cert because they are identical
+ * or at least have the same issuer and serial number,
+ * which (for any sane cert issuer) implies equality of the two certs.
+ * In this case, for consistency with chain building and validation,
+ * we make our issuance judgment depend on the presence of EXFLAG_SS.
+ * This is used for corrected chain building in the corner case of
+ * a self-issued but not actually self-signed trust anchor cert
+ * without subject and issuer key identifiers (i.e., no SKID and AKID).
+ */
+ return (issuer->ex_flags & EXFLAG_SS) != 0
+ ? X509_V_OK
+ : X509_V_ERR_CERT_SIGNATURE_FAILURE;
+
ret = X509_check_akid(issuer, subject->akid);
if (ret != X509_V_OK)
return ret;
diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t
index 1f4cb803b5..e37b36104c 100644
--- a/test/recipes/25-test_req.t
+++ b/test/recipes/25-test_req.t
@@ -15,7 +15,7 @@ use OpenSSL::Test qw/:DEFAULT srctop_file/;
setup("test_req");
-plan tests => 121;
+plan tests => 125;
require_ok(srctop_file('test', 'recipes', 'tconversion.pl'));
@@ -694,6 +694,14 @@ has_SKID($cert, 1);
has_AKID($cert, 0);
strict_verify($cert, 1);
+$cert = "self-issued_v3_CA_no_KIDs.pem";
+generate_cert($cert, "-addext", "subjectKeyIdentifier = none",
+ "-addext", "authorityKeyIdentifier = none",
+ "-in", srctop_file(@certs, "x509-check.csr"));
+has_SKID($cert, 0);
+has_AKID($cert, 0);
+strict_verify($cert, 1);
+
$cert = "self-issued_v3_CA_explicit_AKID.pem";
generate_cert($cert, "-addext", "authorityKeyIdentifier = keyid",
"-in", srctop_file(@certs, "x509-check.csr"));