|
6 | 6 | from typing import Dict, List, Optional, Set, Tuple, Union
|
7 | 7 |
|
8 | 8 | from asn1crypto import cms, crl, x509
|
| 9 | +from asn1crypto.crl import CRLEntryExtensionId |
9 | 10 | from cryptography.exceptions import InvalidSignature
|
10 | 11 |
|
11 | 12 | from pyhanko_certvalidator._state import ValProcState
|
@@ -1387,9 +1388,20 @@ def find_cert_in_list(
|
1387 | 1388 | cert_serial = cert['ac_info']['serial_number'].dump()
|
1388 | 1389 |
|
1389 | 1390 | last_issuer_name = crl_authority_name
|
| 1391 | + |
| 1392 | + cert_issuer_extension_id = CRLEntryExtensionId('certificate_issuer').dump() |
| 1393 | + |
1390 | 1394 | for revoked_cert in revoked_certificates:
|
1391 |
| - if revoked_cert.issuer_name: |
1392 |
| - last_issuer_name = revoked_cert.issuer_name |
| 1395 | + # This looks like a hack, but we have to look up the certificate_issuer |
| 1396 | + # extension for every entry, since its value remains in effect for |
| 1397 | + # future entries as well! (and PKITS has a test case for that...) |
| 1398 | + # Since parsing those extensions every time is expensive for large CRLs, |
| 1399 | + # we guard it with a dumb heuristic check: does the binary encoding |
| 1400 | + # of that extension's OID appear anywhere in the entry's payload? |
| 1401 | + # If not, we move on. If it does appear, we parse the extensions. |
| 1402 | + if cert_issuer_extension_id in revoked_cert.dump(): |
| 1403 | + if revoked_cert.issuer_name: |
| 1404 | + last_issuer_name = revoked_cert.issuer_name |
1393 | 1405 | if revoked_cert['user_certificate'].dump() != cert_serial:
|
1394 | 1406 | continue
|
1395 | 1407 | if last_issuer_name != cert_issuer_name:
|
|
0 commit comments