aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.rst3
-rw-r--r--docs/x509/reference.rst9
-rw-r--r--src/_cffi_src/openssl/x509.py2
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py19
-rw-r--r--src/cryptography/x509/base.py7
-rw-r--r--tests/x509/test_x509.py12
6 files changed, 52 insertions, 0 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 8b4e9743..c8db7e7d 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -16,6 +16,9 @@ Changelog
``cryptography`` release.
* Fixed multiple issues preventing ``cryptography`` from compiling against
LibreSSL 2.7.x.
+* Added
+ :class:`~cryptography.x509.CertificateRevocationList.get_revoked_certificate_by_serial_number`
+ for quick serial number searches in CRLs.
* The :class:`~cryptography.x509.RelativeDistinguishedName` class now
preserves the order of attributes. Duplicate attributes now raise an error
instead of silently discarding duplicates.
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 64097bf2..bc3dd556 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -463,6 +463,15 @@ X.509 CRL (Certificate Revocation List) Object
>>> crl.fingerprint(hashes.SHA256())
b'e\xcf.\xc4:\x83?1\xdc\xf3\xfc\x95\xd7\xb3\x87\xb3\x8e\xf8\xb93!\x87\x07\x9d\x1b\xb4!\xb9\xe4W\xf4\x1f'
+ .. method:: get_revoked_certificate_by_serial_number(serial_number)
+
+ .. versionadded:: 2.3
+
+ :param serial_number: The serial as a Python integer.
+ :returns: :class:`~cryptography.x509.RevokedCertificate` if the
+ ``serial_number`` is present in the CRL or ``None`` if it
+ is not.
+
.. attribute:: signature_hash_algorithm
:type: :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py
index 97ade5bc..59fdbf7e 100644
--- a/src/_cffi_src/openssl/x509.py
+++ b/src/_cffi_src/openssl/x509.py
@@ -238,6 +238,8 @@ X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *, int);
X509_EXTENSION *X509_CRL_get_ext(X509_CRL *, int);
int X509_CRL_get_ext_count(X509_CRL *);
+int X509_CRL_get0_by_serial(X509_CRL *, X509_REVOKED **, ASN1_INTEGER *);
+
/* these CRYPTO_EX_DATA functions became macros in 1.1.0 */
int X509_get_ex_new_index(long, void *, CRYPTO_EX_new *, CRYPTO_EX_dup *,
CRYPTO_EX_free *);
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 9637fc0e..b870eeb7 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -16,6 +16,9 @@ from cryptography.hazmat.backends.openssl.decode_asn1 import (
_REVOKED_CERTIFICATE_EXTENSION_PARSER, _asn1_integer_to_int,
_asn1_string_to_bytes, _decode_x509_name, _obj2txt, _parse_asn1_time
)
+from cryptography.hazmat.backends.openssl.encode_asn1 import (
+ _encode_asn1_int_gc
+)
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import dsa, ec, rsa
@@ -235,6 +238,22 @@ class _CertificateRevocationList(object):
h.update(der)
return h.finalize()
+ def get_revoked_certificate_by_serial_number(self, serial_number):
+ revoked = self._backend._ffi.new("X509_REVOKED **")
+ asn1_int = _encode_asn1_int_gc(self._backend, serial_number)
+ res = self._backend._lib.X509_CRL_get0_by_serial(
+ self._x509_crl, revoked, asn1_int
+ )
+ if res == 0:
+ return None
+ else:
+ self._backend.openssl_assert(
+ revoked[0] != self._backend._ffi.NULL
+ )
+ return _RevokedCertificate(
+ self._backend, self._x509_crl, revoked[0]
+ )
+
@property
def signature_hash_algorithm(self):
oid = self.signature_algorithm_oid
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index 45b603f0..b14499c9 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -189,6 +189,13 @@ class CertificateRevocationList(object):
Returns bytes using digest passed.
"""
+ @abc.abstractmethod
+ def get_revoked_certificate_by_serial_number(self, serial_number):
+ """
+ Returns an instance of RevokedCertificate or None if the serial_number
+ is not in the CRL.
+ """
+
@abc.abstractproperty
def signature_hash_algorithm(self):
"""
diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py
index fe57784a..5905e335 100644
--- a/tests/x509/test_x509.py
+++ b/tests/x509/test_x509.py
@@ -181,6 +181,18 @@ class TestCertificateRevocationList(object):
# Check that len() works for CRLs.
assert len(crl) == 12
+ def test_get_revoked_certificate_by_serial_number(self, backend):
+ crl = _load_cert(
+ os.path.join(
+ "x509", "PKITS_data", "crls", "LongSerialNumberCACRL.crl"),
+ x509.load_der_x509_crl,
+ backend
+ )
+ serial_number = 725064303890588110203033396814564464046290047507
+ revoked = crl.get_revoked_certificate_by_serial_number(serial_number)
+ assert revoked.serial_number == serial_number
+ assert crl.get_revoked_certificate_by_serial_number(500) is None
+
def test_revoked_cert_retrieval_retain_only_revoked(self, backend):
"""
This test attempts to trigger the crash condition described in