diff options
-rw-r--r-- | CHANGELOG.rst | 1 | ||||
-rw-r--r-- | docs/x509/reference.rst | 23 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 6 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/decode_asn1.py | 21 | ||||
-rw-r--r-- | src/cryptography/x509/__init__.py | 4 | ||||
-rw-r--r-- | src/cryptography/x509/extensions.py | 5 | ||||
-rw-r--r-- | src/cryptography/x509/oid.py | 3 | ||||
-rw-r--r-- | tests/x509/test_x509_ext.py | 29 |
8 files changed, 86 insertions, 6 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst index a614df84..8c08fcbc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -13,6 +13,7 @@ Changelog support, however we strongly encourage all users to upgrade or install ``cryptography`` from a wheel. * Added initial :doc:`OCSP </x509/ocsp>` support. +* Added support for :class:`~cryptography.x509.PrecertPoison`. .. _v2-3-1: diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 5fa8471b..ede08aa5 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -1944,6 +1944,23 @@ X.509 Extensions :attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS`. +.. class:: PrecertPoison() + + .. versionadded:: 2.4 + + This extension indicates that the certificate should not be treated as a + certificate for the purposes of validation, but is instead for submission + to a certificate transparency log in order to obtain SCTs which will be + embedded in a :class:`PrecertificateSignedCertificateTimestamps` extension + on the final certificate. + + .. attribute:: oid + + :type: :class:`ObjectIdentifier` + + Returns :attr:`~cryptography.x509.oid.ExtensionOID.PRECERT_POISON`. + + .. class:: DeltaCRLIndicator(crl_number) .. versionadded:: 2.1 @@ -2804,6 +2821,12 @@ instances. The following common OIDs are available as constants. Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.2"``. + .. attribute:: PRECERT_POISON + + .. versionadded:: 2.4 + + Corresponds to the dotted string ``"1.3.6.1.4.1.11129.2.4.3"``. + .. attribute:: POLICY_CONSTRAINTS Corresponds to the dotted string ``"2.5.29.36"``. The identifier for the diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 64d26afd..58fe492f 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -11,6 +11,8 @@ import contextlib import itertools from contextlib import contextmanager +import asn1crypto.core + import six from cryptography import utils, x509 @@ -965,6 +967,10 @@ class Backend(object): asn1 = _Integers([x.value for x in extension.value]).dump() value = _encode_asn1_str_gc(self, asn1, len(asn1)) return self._create_raw_x509_extension(extension, value) + elif isinstance(extension.value, x509.PrecertPoison): + asn1 = asn1crypto.core.Null().dump() + value = _encode_asn1_str_gc(self, asn1, len(asn1)) + return self._create_raw_x509_extension(extension, value) else: try: encode = handlers[extension.oid] diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 31fb8cfc..47fa911e 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -7,7 +7,7 @@ from __future__ import absolute_import, division, print_function import datetime import ipaddress -from asn1crypto.core import Integer, SequenceOf +import asn1crypto.core from cryptography import x509 from cryptography.x509.extensions import _TLS_FEATURE_TYPE_TO_ENUM @@ -17,8 +17,8 @@ from cryptography.x509.oid import ( ) -class _Integers(SequenceOf): - _child_spec = Integer +class _Integers(asn1crypto.core.SequenceOf): + _child_spec = asn1crypto.core.Integer def _obj2txt(backend, obj): @@ -202,8 +202,8 @@ class _X509ExtensionParser(object): "Duplicate {0} extension found".format(oid), oid ) - # This OID is only supported in OpenSSL 1.1.0+ but we want - # to support it in all versions of OpenSSL so we decode it + # These OIDs are only supported in OpenSSL 1.1.0+ but we want + # to support them in all versions of OpenSSL so we decode them # ourselves. if oid == ExtensionOID.TLS_FEATURE: data = backend._lib.X509_EXTENSION_get_data(ext) @@ -214,6 +214,17 @@ class _X509ExtensionParser(object): extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) continue + elif oid == ExtensionOID.PRECERT_POISON: + data = backend._lib.X509_EXTENSION_get_data(ext) + parsed = asn1crypto.core.Null.load( + _asn1_string_to_bytes(backend, data) + ) + assert parsed == asn1crypto.core.Null() + extensions.append(x509.Extension( + oid, critical, x509.PrecertPoison() + )) + seen_oids.add(oid) + continue try: handler = self.handlers[oid] diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index d2f9b049..15459a12 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -22,7 +22,8 @@ from cryptography.x509.extensions import ( Extension, ExtensionNotFound, ExtensionType, Extensions, FreshestCRL, GeneralNames, InhibitAnyPolicy, InvalidityDate, IssuerAlternativeName, KeyUsage, NameConstraints, NoticeReference, OCSPNoCheck, PolicyConstraints, - PolicyInformation, PrecertificateSignedCertificateTimestamps, ReasonFlags, + PolicyInformation, PrecertPoison, + PrecertificateSignedCertificateTimestamps, ReasonFlags, SubjectAlternativeName, SubjectKeyIdentifier, TLSFeature, TLSFeatureType, UnrecognizedExtension, UserNotice ) @@ -182,4 +183,5 @@ __all__ = [ "UnrecognizedExtension", "PolicyConstraints", "PrecertificateSignedCertificateTimestamps", + "PrecertPoison", ] diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index eb4b927f..08af03c8 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -855,6 +855,11 @@ class OCSPNoCheck(object): @utils.register_interface(ExtensionType) +class PrecertPoison(object): + oid = ExtensionOID.PRECERT_POISON + + +@utils.register_interface(ExtensionType) class TLSFeature(object): oid = ExtensionOID.TLS_FEATURE diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 90003d79..77e3fa63 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -91,6 +91,9 @@ class ExtensionOID(object): PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS = ( ObjectIdentifier("1.3.6.1.4.1.11129.2.4.2") ) + PRECERT_POISON = ( + ObjectIdentifier("1.3.6.1.4.1.11129.2.4.3") + ) class CRLEntryExtensionOID(object): diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index c052f859..7e0ae220 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -4442,6 +4442,35 @@ class TestInhibitAnyPolicyExtension(object): @pytest.mark.requires_backend_interface(interface=RSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) +class TestPrecertPoisonExtension(object): + def test_load(self, backend): + cert = _load_cert( + os.path.join("x509", "cryptography.io.precert.pem"), + x509.load_pem_x509_certificate, + backend + ) + poison = cert.extensions.get_extension_for_oid( + ExtensionOID.PRECERT_POISON + ).value + assert isinstance(poison, x509.PrecertPoison) + poison = cert.extensions.get_extension_for_class( + x509.PrecertPoison + ).value + assert isinstance(poison, x509.PrecertPoison) + + def test_generate(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + cert = _make_certbuilder(private_key).add_extension( + x509.PrecertPoison(), critical=True + ).sign(private_key, hashes.SHA256(), backend) + poison = cert.extensions.get_extension_for_oid( + ExtensionOID.PRECERT_POISON + ).value + assert isinstance(poison, x509.PrecertPoison) + + +@pytest.mark.requires_backend_interface(interface=RSABackend) +@pytest.mark.requires_backend_interface(interface=X509Backend) class TestPrecertificateSignedCertificateTimestampsExtension(object): def test_init(self): with pytest.raises(TypeError): |