Commit 8a6dffc063 for openssl.org

commit 8a6dffc063b2c9cfc7b96fc0ba296e576c73aa84
Author: Daniel Kubec <kubec@openssl.org>
Date:   Wed Feb 25 10:51:08 2026 +0100

    CRL: Reject CRLs with malformed Issuing Distribution Point

    CRLs with a malformed Issuing Distribution Point are now rejected.
    ASN.1 parsing errors from the IDP extension are propagated instead
    of being suppressed.

    Fixes #27251

    Reviewed-by: Neil Horman <nhorman@openssl.org>
    Reviewed-by: Tomas Mraz <tomas@openssl.org>
    MergeDate: Fri Feb 27 20:06:59 2026
    (Merged from https://github.com/openssl/openssl/pull/30171)

diff --git a/CHANGES.md b/CHANGES.md
index 5ca61c80e7..9fe41d3177 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -177,6 +177,10 @@ OpenSSL 4.0

    *Igor Ustinov*

+ * CRLs with a malformed Issuing Distribution Point are now rejected.
+
+   *Daniel Kubec*
+
  * Added configure options to disable KDF algorithms for
    hmac-drbg-kdf, kbkdf, krb5kdf, pvkkdf, snmpkdf, sskdf, sshkdf, x942kdf and x963kdf.

diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index 89a64fec03..f11e7b018b 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -247,9 +247,12 @@ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
     case ASN1_OP_D2I_POST:
         if (!X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL))
             crl->flags |= EXFLAG_NO_FINGERPRINT;
-        crl->idp = X509_CRL_get_ext_d2i(crl,
-            NID_issuing_distribution_point, &i,
-            NULL);
+        crl->idp = X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, &i, NULL);
+        if (crl->idp == NULL && i != -1) {
+            ERR_raise_data(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT,
+                "CRL: malformed CRL issuing distribution point");
+            return 0;
+        }
         if (crl->idp != NULL) {
             if (!setup_idp(crl, crl->idp))
                 crl->flags |= EXFLAG_INVALID;
diff --git a/test/crltest.c b/test/crltest.c
index b13d5977ce..245d2205f4 100644
--- a/test/crltest.c
+++ b/test/crltest.c
@@ -266,10 +266,6 @@ static const char *kUnknownCriticalCRL2[] = {
     NULL
 };

-static const char **unknown_critical_crls[] = {
-    kUnknownCriticalCRL, kUnknownCriticalCRL2
-};
-
 /*
  * RFC 5280 states that only CRL files with the Indirect CRL flag set to True in
  * the IDP extension require the certificate_issuer extension.
@@ -403,6 +399,45 @@ static const char *kCrlNumberString[] = {
     NULL
 };

+/* https://github.com/openssl/openssl/issues/27251 */
+static const char *kCrlIDPWrongTag[] = {
+    "-----BEGIN X509 CRL-----\n",
+    "MIICZzCCAU8CAQEwDQYJKoZIhvcNAQELBQAweTELMAkGA1UEBhMCVVMxEzARBgNV\n",
+    "BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoM\n",
+    "Ck15IENvbXBhbnkxEzARBgNVBAMMCk15IFJvb3QgQ0ExEzARBgNVBAsMCk15IFJv\n",
+    "b3QgQ0EXDTI1MDEwMTAwMDAwMFoXDTI1MTIwMTAwMDAwMFowJzAlAhQcgAIu+B8k\n",
+    "Be6WphLcth/grHAeXhcNMjUwNDE3MTAxNjUxWqB5MHcwGAYDVR0UBBECDxnP/97a\n",
+    "dO3y9qRGDM7hQDAfBgNVHSMEGDAWgBTXYYkfk5aLdlQW6eV33Hy3ZRuAJDA6BgNV\n",
+    "HRwBAf8EMDAuoCagJKQihiBodHRwOi8vbG9jYWxob3N0OjgwMDAvY2FfY3JsLmRl\n",
+    "coEB/4IB/zANBgkqhkiG9w0BAQsFAAOCAQEANovDW2ry+y17K8CgjoD6C1Mwf8Je\n",
+    "uJiSw4kZnbtO/+/Benl3nWumMIH9liV6BSJnWZU3staGQaUyk+qou5udzSwh0Tw/\n",
+    "iGu/xygDlEBiJ/vFt0Bt6ImHCsNrd7UjNRGRJI7neeJdq6YlMOJ27JvKt9isRJIM\n",
+    "KsHBuqBs8G8g6XU0TfgoHYAPxtPF9uuFmC7k0Fs7z142C9/Im8m1CqqYet/kd/Hz\n",
+    "IErMxdvr1NfL7WHBIArW0BqjaR1E05ur8fPIHItVJtPV9V5UbRM1eeQiOfDCyZRJ\n",
+    "x9A/quodFMH781MsLnTktHqMmbOesiDycl0OehyrfXDEXLWIOH/EvqkyIA==\n",
+    "-----END X509 CRL-----\n",
+    NULL
+};
+
+static const char *kCrlIDPWrongTag2[] = {
+    "-----BEGIN X509 CRL-----\n",
+    "MIICZzCCAU8CAQEwDQYJKoZIhvcNAQELBQAweTELMAkGA1UEBhMCVVMxEzARBgNV\n",
+    "BAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuY2lzY28xEzARBgNVBAoM\n",
+    "Ck15IENvbXBhbnkxEzARBgNVBAMMCk15IFJvb3QgQ0ExEzARBgNVBAsMCk15IFJv\n",
+    "b3QgQ0EXDTI1MDEwMTAwMDAwMFoXDTI1MTIwMTAwMDAwMFowJzAlAhQcgAIu+B8k\n",
+    "Be6WphLcth/grHAeXhcNMjUwNDE3MTAxNjUxWqB5MHcwGAYDVR0UBBECDxnP/97a\n",
+    "dO3y9qRGDM7hQDAfBgNVHSMEGDAWgBTXYYkfk5aLdlQW6eV33Hy3ZRuAJDA6BgNV\n",
+    "HRwBAf8EMDAuoCagJKUihiBodHRwOi8vbG9jYWxob3N0OjgwMDAvY2FfY3JsLmRl\n",
+    "coEB/4IB/zANBgkqhkiG9w0BAQsFAAOCAQEAyLXs3RfVDDjTvvni2EyKRdnpODpY\n",
+    "hH5Q26NtA0S6/hXUOntR3N6jrqZQNo1Eg2iL9v6IzWnHEeWs4jSzMaOdAHW+iASY\n",
+    "COMIuNKY51E7dezIyY1Gjl3L9S/laGb0zPsgziAq8PFKP/FBC0uQbLmpbfvFSf0D\n",
+    "bZQzB0THvc3OjixEeRQPNkEApHPqmZpvr6ysQBpvzSQJhYaVT2JfUjAGBu1B6iIO\n",
+    "bwfzsFriiMUdnHp6I3mQ0LtzcxuzEDVifcE4dkl2PROsgwxiAbKXCYTDYGSTQ3Li\n",
+    "4ijLXcQYIZ3ZP6xs6qiYqphBF2ICGtMpD2XUxOSMfO42S2FYs/wZ38lnHg==\n",
+    "-----END X509 CRL-----\n",
+    NULL
+};
+
 static X509 *test_root = NULL;
 static X509 *test_leaf = NULL;
 static X509 *test_root2 = NULL;
@@ -571,32 +606,45 @@ static int test_crl_empty_idp(void)

 static int test_known_critical_crl(void)
 {
-    X509_CRL *known_critical_crl = CRL_from_strings(kKnownCriticalCRL);
-    int r;
+    X509_CRL *crl = CRL_from_strings(kKnownCriticalCRL);
+    int test;

-    r = TEST_ptr(known_critical_crl)
-        && TEST_int_eq(verify(test_leaf, test_root,
-                           make_CRL_stack(known_critical_crl, NULL),
-                           X509_V_FLAG_CRL_CHECK, PARAM_TIME),
-            X509_V_OK);
-    X509_CRL_free(known_critical_crl);
-    return r;
+    test = TEST_ptr_null(crl)
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE)
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT)
+        && TEST_err_s("CRL: malformed CRL issuing distribution point");
+
+    X509_CRL_free(crl);
+    return test;
 }

-static int test_unknown_critical_crl(int n)
+static int test_unknown_critical_crl1(void)
 {
-    X509_CRL *unknown_critical_crl = CRL_from_strings(unknown_critical_crls[n]);
+    X509_CRL *unknown_critical_crl = CRL_from_strings(kUnknownCriticalCRL);
     int r;
-
     r = TEST_ptr(unknown_critical_crl)
         && TEST_int_eq(verify(test_leaf, test_root,
                            make_CRL_stack(unknown_critical_crl, NULL),
                            X509_V_FLAG_CRL_CHECK, PARAM_TIME),
             X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION);
+
     X509_CRL_free(unknown_critical_crl);
     return r;
 }

+static int test_unknown_critical_crl2(void)
+{
+    X509_CRL *crl;
+    int test;
+
+    test = TEST_ptr_null((crl = CRL_from_strings(kUnknownCriticalCRL2)))
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_TYPE_NOT_PRIMITIVE)
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT)
+        && TEST_err_s("CRL: malformed CRL issuing distribution point");
+
+    return test;
+}
+
 static int test_reuse_crl(int idx)
 {
     X509_CRL *result, *reused_crl = CRL_from_strings(kBasicCRL);
@@ -779,6 +827,34 @@ static int test_crl_number(void)
     return test;
 }

+static int test_crl_idp_malformed(void)
+{
+    X509_CRL *crl;
+    int test;
+
+    test = TEST_ptr_null((crl = CRL_from_strings(kCrlIDPWrongTag)))
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_WRONG_TAG)
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT)
+        && TEST_err_s("CRL: malformed CRL issuing distribution point");
+
+    X509_CRL_free(crl);
+    return test;
+}
+
+static int test_crl_idp_malformed2(void)
+{
+    X509_CRL *crl;
+    int test;
+
+    test = TEST_ptr_null((crl = CRL_from_strings(kCrlIDPWrongTag2)))
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_WRONG_TAG)
+        && TEST_err_r(ERR_LIB_ASN1, ASN1_R_ILLEGAL_OBJECT)
+        && TEST_err_s("CRL: malformed CRL issuing distribution point");
+
+    X509_CRL_free(crl);
+    return test;
+}
+
 int setup_tests(void)
 {
     if (!TEST_ptr(test_root = X509_from_strings(kCRLTestRoot))
@@ -797,7 +873,10 @@ int setup_tests(void)
     ADD_TEST(test_get_crl_fn_score);
     ADD_TEST(test_crl_delta_indicator);
     ADD_TEST(test_crl_number);
-    ADD_ALL_TESTS(test_unknown_critical_crl, OSSL_NELEM(unknown_critical_crls));
+    ADD_TEST(test_crl_idp_malformed);
+    ADD_TEST(test_crl_idp_malformed2);
+    ADD_TEST(test_unknown_critical_crl1);
+    ADD_TEST(test_unknown_critical_crl2);
     ADD_ALL_TESTS(test_reuse_crl, 6);

     return 1;