aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2017-09-22 21:29:36 +0800
committerAlex Gaynor <alex.gaynor@gmail.com>2017-09-22 09:29:36 -0400
commit5e3cc98473ad54db390736ac81bb74210e85056d (patch)
treed8e0d5e03aee005dc0205661e55d785625b9a71f
parent2fc5849960032a246f869ed1a5d7597d64169cfa (diff)
downloadcryptography-5e3cc98473ad54db390736ac81bb74210e85056d.tar.gz
cryptography-5e3cc98473ad54db390736ac81bb74210e85056d.tar.bz2
cryptography-5e3cc98473ad54db390736ac81bb74210e85056d.zip
support delta crl indicator extension (#3936)
This is an extension for CRLs
-rw-r--r--CHANGELOG.rst1
-rw-r--r--docs/x509/reference.rst32
-rw-r--r--src/cryptography/hazmat/backends/openssl/decode_asn1.py7
-rw-r--r--src/cryptography/hazmat/backends/openssl/encode_asn1.py7
-rw-r--r--src/cryptography/x509/__init__.py5
-rw-r--r--src/cryptography/x509/extensions.py28
-rw-r--r--src/cryptography/x509/oid.py2
-rw-r--r--tests/x509/test_x509.py13
-rw-r--r--tests/x509/test_x509_crlbuilder.py1
-rw-r--r--tests/x509/test_x509_ext.py30
10 files changed, 121 insertions, 5 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 51488ce7..d239d754 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -41,6 +41,7 @@ Changelog
* Added support for using labels with
:class:`~cryptography.hazmat.primitives.asymmetric.padding.OAEP` when using
OpenSSL 1.0.2 or greater.
+* Add support for the :class:`~cryptography.x509.DeltaCRLIndicator` extension.
* Add support for the :class:`~cryptography.x509.TLSFeature`
extension. This is commonly used for enabling ``OCSP Must-Staple`` in
certificates.
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 71ac9d99..dea7ee3b 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -1954,6 +1954,30 @@ X.509 Extensions
:attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS`.
+.. class:: DeltaCRLIndicator(crl_number)
+
+ .. versionadded:: 2.1
+
+ The delta CRL indicator is a CRL extension that identifies a CRL as being
+ a delta CRL. Delta CRLs contain updates to revocation information
+ previously distributed, rather than all the information that would appear
+ in a complete CRL.
+
+ :param int crl_number: The CRL number of the complete CRL that the
+ delta CRL is updating.
+
+ .. attribute:: oid
+
+ :type: :class:`ObjectIdentifier`
+
+ Returns
+ :attr:`~cryptography.x509.oid.ExtensionOID.DELTA_CRL_INDICATOR`.
+
+ .. attribute:: crl_number
+
+ :type: int
+
+
.. class:: AuthorityInformationAccess(descriptions)
.. versionadded:: 0.9
@@ -2749,6 +2773,14 @@ instances. The following common OIDs are available as constants.
the ``CRLNumber`` extension type. This extension only has meaning
for certificate revocation lists.
+ .. attribute:: DELTA_CRL_INDICATOR
+
+ .. versionadded:: 2.1
+
+ Corresponds to the dotted string ``"2.5.29.27"``. The identifier for
+ the ``DeltaCRLIndicator`` extension type. This extension only has
+ meaning for certificate revocation lists.
+
.. attribute:: PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS
.. versionadded:: 1.9
diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
index 6ed4aeb7..1326a94e 100644
--- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py
@@ -152,6 +152,12 @@ def _decode_crl_number(backend, ext):
return x509.CRLNumber(_asn1_integer_to_int(backend, asn1_int))
+def _decode_delta_crl_indicator(backend, ext):
+ asn1_int = backend._ffi.cast("ASN1_INTEGER *", ext)
+ asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free)
+ return x509.DeltaCRLIndicator(_asn1_integer_to_int(backend, asn1_int))
+
+
class _X509ExtensionParser(object):
def __init__(self, ext_count, get_ext, handlers):
self.ext_count = ext_count
@@ -742,6 +748,7 @@ _REVOKED_EXTENSION_HANDLERS = {
_CRL_EXTENSION_HANDLERS = {
ExtensionOID.CRL_NUMBER: _decode_crl_number,
+ ExtensionOID.DELTA_CRL_INDICATOR: _decode_delta_crl_indicator,
ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier,
ExtensionOID.ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name,
ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index 6d9f9567..5ceb29c0 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -133,8 +133,8 @@ def _encode_name_entry(backend, attribute):
return name_entry
-def _encode_crl_number(backend, crl_number):
- return _encode_asn1_int_gc(backend, crl_number.crl_number)
+def _encode_crl_number_delta_crl_indicator(backend, ext):
+ return _encode_asn1_int_gc(backend, ext.crl_number)
def _encode_crl_reason(backend, crl_reason):
@@ -598,7 +598,8 @@ _CRL_EXTENSION_ENCODE_HANDLERS = {
ExtensionOID.AUTHORITY_INFORMATION_ACCESS: (
_encode_authority_information_access
),
- ExtensionOID.CRL_NUMBER: _encode_crl_number,
+ ExtensionOID.CRL_NUMBER: _encode_crl_number_delta_crl_indicator,
+ ExtensionOID.DELTA_CRL_INDICATOR: _encode_crl_number_delta_crl_indicator,
}
_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = {
diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py
index 176ed8ca..e168adb7 100644
--- a/src/cryptography/x509/__init__.py
+++ b/src/cryptography/x509/__init__.py
@@ -18,8 +18,8 @@ from cryptography.x509.extensions import (
AccessDescription, AuthorityInformationAccess,
AuthorityKeyIdentifier, BasicConstraints, CRLDistributionPoints,
CRLNumber, CRLReason, CertificateIssuer, CertificatePolicies,
- DistributionPoint, DuplicateExtension, ExtendedKeyUsage, Extension,
- ExtensionNotFound, ExtensionType, Extensions, GeneralNames,
+ DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage,
+ Extension, ExtensionNotFound, ExtensionType, Extensions, GeneralNames,
InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName, KeyUsage,
NameConstraints, NoticeReference, OCSPNoCheck, PolicyConstraints,
PolicyInformation, PrecertificateSignedCertificateTimestamps, ReasonFlags,
@@ -119,6 +119,7 @@ __all__ = [
"load_der_x509_crl",
"random_serial_number",
"InvalidVersion",
+ "DeltaCRLIndicator",
"DuplicateExtension",
"ExtensionNotFound",
"UnsupportedGeneralNameType",
diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py
index 442000e3..beb20bad 100644
--- a/src/cryptography/x509/extensions.py
+++ b/src/cryptography/x509/extensions.py
@@ -376,6 +376,34 @@ class BasicConstraints(object):
@utils.register_interface(ExtensionType)
+class DeltaCRLIndicator(object):
+ oid = ExtensionOID.DELTA_CRL_INDICATOR
+
+ def __init__(self, crl_number):
+ if not isinstance(crl_number, six.integer_types):
+ raise TypeError("crl_number must be an integer")
+
+ self._crl_number = crl_number
+
+ crl_number = utils.read_only_property("_crl_number")
+
+ def __eq__(self, other):
+ if not isinstance(other, DeltaCRLIndicator):
+ return NotImplemented
+
+ return self.crl_number == other.crl_number
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __hash__(self):
+ return hash(self.crl_number)
+
+ def __repr__(self):
+ return "<DeltaCRLIndicator(crl_number={0.crl_number})>".format(self)
+
+
+@utils.register_interface(ExtensionType)
class CRLDistributionPoints(object):
oid = ExtensionOID.CRL_DISTRIBUTION_POINTS
diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py
index 7f8c9031..fedea310 100644
--- a/src/cryptography/x509/oid.py
+++ b/src/cryptography/x509/oid.py
@@ -87,6 +87,7 @@ class ExtensionOID(object):
OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5")
TLS_FEATURE = ObjectIdentifier("1.3.6.1.5.5.7.1.24")
CRL_NUMBER = ObjectIdentifier("2.5.29.20")
+ DELTA_CRL_INDICATOR = ObjectIdentifier("2.5.29.27")
PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = (
ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2")
)
@@ -256,6 +257,7 @@ _OID_NAMES = {
ExtensionOID.SUBJECT_INFORMATION_ACCESS: "subjectInfoAccess",
ExtensionOID.OCSP_NO_CHECK: "OCSPNoCheck",
ExtensionOID.CRL_NUMBER: "cRLNumber",
+ ExtensionOID.DELTA_CRL_INDICATOR: "deltaCRLIndicator",
ExtensionOID.TLS_FEATURE: "TLSFeature",
AuthorityInformationAccessOID.OCSP: "OCSP",
AuthorityInformationAccessOID.CA_ISSUERS: "caIssuers",
diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py
index 1833a4a2..d0ce46d8 100644
--- a/tests/x509/test_x509.py
+++ b/tests/x509/test_x509.py
@@ -232,6 +232,19 @@ class TestCertificateRevocationList(object):
x509.UniformResourceIdentifier(b"https://cryptography.io"),
])
+ def test_delta_crl_indicator(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_delta_crl_indicator.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ dci = crl.extensions.get_extension_for_oid(
+ ExtensionOID.DELTA_CRL_INDICATOR
+ )
+ assert dci.value == x509.DeltaCRLIndicator(12345678901234567890)
+ assert dci.critical is False
+
def test_signature(self, backend):
crl = _load_cert(
os.path.join("x509", "custom", "crl_all_reasons.pem"),
diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py
index b90805ff..e90fd3fd 100644
--- a/tests/x509/test_x509_crlbuilder.py
+++ b/tests/x509/test_x509_crlbuilder.py
@@ -209,6 +209,7 @@ class TestCertificateRevocationListBuilder(object):
"extension",
[
x509.CRLNumber(13),
+ x509.DeltaCRLIndicator(12345678901234567890),
x509.AuthorityKeyIdentifier(
b"\xc3\x9c\xf3\xfc\xd3F\x084\xbb\xceF\x7f\xa0|[\xf3\xe2\x08"
b"\xcbY",
diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py
index b9400b64..9f0b1b0b 100644
--- a/tests/x509/test_x509_ext.py
+++ b/tests/x509/test_x509_ext.py
@@ -326,6 +326,36 @@ class TestCRLReason(object):
)
+class TestDeltaCRLIndicator(object):
+ def test_not_int(self):
+ with pytest.raises(TypeError):
+ x509.DeltaCRLIndicator("notanint")
+
+ def test_eq(self):
+ delta1 = x509.DeltaCRLIndicator(1)
+ delta2 = x509.DeltaCRLIndicator(1)
+ assert delta1 == delta2
+
+ def test_ne(self):
+ delta1 = x509.DeltaCRLIndicator(1)
+ delta2 = x509.DeltaCRLIndicator(2)
+ assert delta1 != delta2
+ assert delta1 != object()
+
+ def test_repr(self):
+ delta1 = x509.DeltaCRLIndicator(2)
+ assert repr(delta1) == (
+ "<DeltaCRLIndicator(crl_number=2)>"
+ )
+
+ def test_hash(self):
+ delta1 = x509.DeltaCRLIndicator(1)
+ delta2 = x509.DeltaCRLIndicator(1)
+ delta3 = x509.DeltaCRLIndicator(2)
+ assert hash(delta1) == hash(delta2)
+ assert hash(delta1) != hash(delta3)
+
+
class TestInvalidityDate(object):
def test_invalid_invalidity_date(self):
with pytest.raises(TypeError):