aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/_cffi_src/openssl/x509v3.py2
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py107
-rw-r--r--src/cryptography/x509/__init__.py10
-rw-r--r--src/cryptography/x509/oid.py8
-rw-r--r--tests/test_x509.py37
-rw-r--r--vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem11
6 files changed, 80 insertions, 95 deletions
diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py
index 84e49640..51cac62b 100644
--- a/src/_cffi_src/openssl/x509v3.py
+++ b/src/_cffi_src/openssl/x509v3.py
@@ -290,6 +290,8 @@ DIST_POINT_NAME *DIST_POINT_NAME_new(void);
void DIST_POINT_NAME_free(DIST_POINT_NAME *);
int i2d_CRL_DIST_POINTS(Cryptography_STACK_OF_DIST_POINT *, unsigned char **);
+GENERAL_NAMES *d2i_GENERAL_NAMES(GENERAL_NAMES **, const unsigned char **,
+ long);
"""
CUSTOMIZATIONS = """
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 7f7be545..073dfb1e 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -19,7 +19,7 @@ from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.x509.oid import (
- CertificatePoliciesOID, ExtensionOID, RevokedExtensionOID
+ CRLExtensionOID, CertificatePoliciesOID, ExtensionOID
)
@@ -175,11 +175,11 @@ def _decode_ocsp_no_check(backend, ext):
class _X509ExtensionParser(object):
- def __init__(self, ext_count, get_ext, handlers, supported_versions=None):
+ def __init__(self, ext_count, get_ext, handlers, unsupported_exts=None):
self.ext_count = ext_count
self.get_ext = get_ext
self.handlers = handlers
- self.supported_versions = supported_versions
+ self.unsupported_exts = unsupported_exts
def parse(self, backend, x509_obj):
extensions = []
@@ -190,13 +190,6 @@ class _X509ExtensionParser(object):
crit = backend._lib.X509_EXTENSION_get_critical(ext)
critical = crit == 1
oid = x509.ObjectIdentifier(_obj2txt(backend, ext.object))
-
- # Filter out extensions we know are not supported by the backend
- if (self.supported_versions and oid in self.supported_versions and
- self.supported_versions[oid] >
- backend._lib.OPENSSL_VERSION_NUMBER):
- self.handlers.pop(oid, None)
-
if oid in seen_oids:
raise x509.DuplicateExtension(
"Duplicate {0} extension found".format(oid), oid
@@ -210,15 +203,18 @@ class _X509ExtensionParser(object):
.format(oid), oid
)
else:
- d2i = backend._lib.X509V3_EXT_d2i(ext)
- if d2i == backend._ffi.NULL:
- backend._consume_errors()
- raise ValueError(
- "The {0} extension is invalid and can't be "
- "parsed".format(oid)
- )
-
- value = handler(backend, d2i)
+ if self.unsupported_exts and oid in self.unsupported_exts:
+ ext_data = ext
+ else:
+ ext_data = backend._lib.X509V3_EXT_d2i(ext)
+ if ext_data == backend._ffi.NULL:
+ backend._consume_errors()
+ raise ValueError(
+ "The {0} extension is invalid and can't be "
+ "parsed".format(oid)
+ )
+
+ value = handler(backend, ext_data)
extensions.append(x509.Extension(oid, critical, value))
seen_oids.add(oid)
@@ -687,8 +683,18 @@ def _decode_invalidity_date(backend, inv_date):
return datetime.datetime.strptime(time, "%Y%m%d%H%M%SZ")
-def _decode_cert_issuer(backend, issuer):
- gns = backend._ffi.cast("GENERAL_NAMES *", issuer)
+def _decode_cert_issuer(backend, ext):
+ data_ptr_ptr = backend._ffi.new("const unsigned char **")
+ data_ptr_ptr[0] = ext.value.data
+ gns = backend._lib.d2i_GENERAL_NAMES(
+ backend._ffi.NULL, data_ptr_ptr, ext.value.length
+ )
+ if gns == backend._ffi.NULL:
+ backend._consume_errors()
+ raise ValueError(
+ "The {0} extension is corrupted and can't be parsed".format(
+ CRLExtensionOID.CERTIFICATE_ISSUER))
+
gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free)
return x509.GeneralNames(_decode_general_names(backend, gns))
@@ -699,28 +705,16 @@ class _RevokedCertificate(object):
self._backend = backend
self._x509_revoked = x509_revoked
- self._serial_number = None
- self._revocation_date = None
- self._extensions = None
-
@property
def serial_number(self):
- if self._serial_number:
- return self._serial_number
-
asn1_int = self._x509_revoked.serialNumber
self._backend.openssl_assert(asn1_int != self._backend._ffi.NULL)
- self._serial_number = self._backend._asn1_integer_to_int(asn1_int)
- return self._serial_number
+ return self._backend._asn1_integer_to_int(asn1_int)
@property
def revocation_date(self):
- if self._revocation_date:
- return self._revocation_date
-
- self._revocation_date = self._backend._parse_asn1_time(
+ return self._backend._parse_asn1_time(
self._x509_revoked.revocationDate)
- return self._revocation_date
@property
def extensions(self):
@@ -765,11 +759,6 @@ class _CertificateRevocationList(object):
self._backend = backend
self._x509_crl = x509_crl
- self._revoked = None
- self._issuer = None
- self._next_update = None
- self._last_update = None
-
def __eq__(self, other):
if not isinstance(other, x509.CertificateRevocationList):
return NotImplemented
@@ -803,38 +792,23 @@ class _CertificateRevocationList(object):
@property
def issuer(self):
- if self._issuer:
- return self._issuer
-
issuer = self._backend._lib.X509_CRL_get_issuer(self._x509_crl)
self._backend.openssl_assert(issuer != self._backend._ffi.NULL)
- self._issuer = _decode_x509_name(self._backend, issuer)
- return self._issuer
+ return _decode_x509_name(self._backend, issuer)
@property
def next_update(self):
- if self._next_update:
- return self._next_update
-
nu = self._backend._lib.X509_CRL_get_nextUpdate(self._x509_crl)
self._backend.openssl_assert(nu != self._backend._ffi.NULL)
- self._next_update = self._backend._parse_asn1_time(nu)
- return self._next_update
+ return self._backend._parse_asn1_time(nu)
@property
def last_update(self):
- if self._last_update:
- return self._last_update
-
lu = self._backend._lib.X509_CRL_get_lastUpdate(self._x509_crl)
self._backend.openssl_assert(lu != self._backend._ffi.NULL)
- self._last_update = self._backend._parse_asn1_time(lu)
- return self._last_update
+ return self._backend._parse_asn1_time(lu)
def _revoked_certificates(self):
- if self._revoked:
- return self._revoked
-
revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl)
self._backend.openssl_assert(revoked != self._backend._ffi.NULL)
@@ -845,8 +819,7 @@ class _CertificateRevocationList(object):
self._backend.openssl_assert(r != self._backend._ffi.NULL)
revoked_list.append(_RevokedCertificate(self._backend, r))
- self._revoked = revoked_list
- return self._revoked
+ return revoked_list
def __iter__(self):
return iter(self._revoked_certificates())
@@ -943,14 +916,14 @@ _EXTENSION_HANDLERS = {
}
_REVOKED_EXTENSION_HANDLERS = {
- RevokedExtensionOID.CRL_REASON: _decode_crl_reason,
- RevokedExtensionOID.INVALIDITY_DATE: _decode_invalidity_date,
- RevokedExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer,
+ CRLExtensionOID.CRL_REASON: _decode_crl_reason,
+ CRLExtensionOID.INVALIDITY_DATE: _decode_invalidity_date,
+ CRLExtensionOID.CERTIFICATE_ISSUER: _decode_cert_issuer,
}
-_REVOKED_SUPPORTED_VERSIONS = {
- RevokedExtensionOID.CERTIFICATE_ISSUER: 0x10000000,
-}
+_REVOKED_UNSUPPORTED_EXTENSIONS = set([
+ CRLExtensionOID.CERTIFICATE_ISSUER,
+])
_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x),
@@ -968,5 +941,5 @@ _REVOKED_CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser(
ext_count=lambda backend, x: backend._lib.X509_REVOKED_get_ext_count(x),
get_ext=lambda backend, x, i: backend._lib.X509_REVOKED_get_ext(x, i),
handlers=_REVOKED_EXTENSION_HANDLERS,
- supported_versions=_REVOKED_SUPPORTED_VERSIONS
+ unsupported_exts=_REVOKED_UNSUPPORTED_EXTENSIONS
)
diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py
index 6438da9c..70e1d3da 100644
--- a/src/cryptography/x509/__init__.py
+++ b/src/cryptography/x509/__init__.py
@@ -28,8 +28,8 @@ from cryptography.x509.general_name import (
)
from cryptography.x509.name import Name, NameAttribute
from cryptography.x509.oid import (
- AuthorityInformationAccessOID, CertificatePoliciesOID, ExtendedKeyUsageOID,
- ExtensionOID, NameOID, ObjectIdentifier, RevokedExtensionOID,
+ AuthorityInformationAccessOID, CRLExtensionOID, CertificatePoliciesOID,
+ ExtendedKeyUsageOID, ExtensionOID, NameOID, ObjectIdentifier,
SignatureAlgorithmOID, _SIG_OIDS_TO_HASH
)
@@ -95,9 +95,9 @@ OID_ANY_POLICY = CertificatePoliciesOID.ANY_POLICY
OID_CPS_QUALIFIER = CertificatePoliciesOID.CPS_QUALIFIER
OID_CPS_USER_NOTICE = CertificatePoliciesOID.CPS_USER_NOTICE
-OID_CERTIFICATE_ISSUER = RevokedExtensionOID.CERTIFICATE_ISSUER
-OID_CRL_REASON = RevokedExtensionOID.CRL_REASON
-OID_INVALIDITY_DATE = RevokedExtensionOID.INVALIDITY_DATE
+OID_CERTIFICATE_ISSUER = CRLExtensionOID.CERTIFICATE_ISSUER
+OID_CRL_REASON = CRLExtensionOID.CRL_REASON
+OID_INVALIDITY_DATE = CRLExtensionOID.INVALIDITY_DATE
OID_CA_ISSUERS = AuthorityInformationAccessOID.CA_ISSUERS
OID_OCSP = AuthorityInformationAccessOID.OCSP
diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py
index 667045af..ead40169 100644
--- a/src/cryptography/x509/oid.py
+++ b/src/cryptography/x509/oid.py
@@ -58,7 +58,7 @@ class ExtensionOID(object):
OCSP_NO_CHECK = ObjectIdentifier("1.3.6.1.5.5.7.48.1.5")
-class RevokedExtensionOID(object):
+class CRLExtensionOID(object):
CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29")
CRL_REASON = ObjectIdentifier("2.5.29.21")
INVALIDITY_DATE = ObjectIdentifier("2.5.29.24")
@@ -177,9 +177,9 @@ _OID_NAMES = {
ExtensionOID.SUBJECT_ALTERNATIVE_NAME: "subjectAltName",
ExtensionOID.ISSUER_ALTERNATIVE_NAME: "issuerAltName",
ExtensionOID.BASIC_CONSTRAINTS: "basicConstraints",
- RevokedExtensionOID.CRL_REASON: "cRLReason",
- RevokedExtensionOID.INVALIDITY_DATE: "invalidityDate",
- RevokedExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer",
+ CRLExtensionOID.CRL_REASON: "cRLReason",
+ CRLExtensionOID.INVALIDITY_DATE: "invalidityDate",
+ CRLExtensionOID.CERTIFICATE_ISSUER: "certificateIssuer",
ExtensionOID.NAME_CONSTRAINTS: "nameConstraints",
ExtensionOID.CRL_DISTRIBUTION_POINTS: "cRLDistributionPoints",
ExtensionOID.CERTIFICATE_POLICIES: "certificatePolicies",
diff --git a/tests/test_x509.py b/tests/test_x509.py
index 347ed1a6..ded2f0ee 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -204,6 +204,13 @@ class TestRevokedCertificate(object):
backend
)
+ exp_issuer = x509.GeneralNames([
+ x509.DirectoryName(x509.Name([
+ x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
+ x509.NameAttribute(x509.OID_COMMON_NAME, u"cryptography.io"),
+ ]))
+ ])
+
# First revoked cert doesn't have extensions, test if it is handled
# correctly.
rev0 = crl[0]
@@ -225,6 +232,10 @@ class TestRevokedCertificate(object):
x509.OID_CRL_REASON).value
assert reason == x509.ReasonFlags.unspecified
+ issuer = rev1.extensions.get_extension_for_oid(
+ x509.OID_CERTIFICATE_ISSUER).value
+ assert issuer == exp_issuer
+
date = rev1.extensions.get_extension_for_oid(
x509.OID_INVALIDITY_DATE).value
assert isinstance(date, datetime.datetime)
@@ -232,6 +243,7 @@ class TestRevokedCertificate(object):
# Test convenience function.
assert rev1.get_invalidity_date().isoformat() == "2015-01-01T00:00:00"
+ assert rev1.get_certificate_issuer() == exp_issuer
# Check if all reason flags can be found in the CRL.
flags = set(x509.ReasonFlags)
@@ -273,30 +285,17 @@ class TestRevokedCertificate(object):
with pytest.raises(ValueError):
crl[0].extensions
- def test_cert_issuer_ext(self, backend):
- if backend._lib.OPENSSL_VERSION_NUMBER < 0x10000000:
- pytest.skip("Requires a newer OpenSSL. Must be at least 1.0.0")
-
+ def test_invalid_cert_issuer_ext(self, backend):
crl = _load_cert(
- os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ os.path.join(
+ "x509", "custom", "crl_inval_cert_issuer_entry_ext.pem"
+ ),
x509.load_pem_x509_crl,
backend
)
- exp_issuer = x509.GeneralNames([
- x509.DirectoryName(x509.Name([
- x509.NameAttribute(x509.OID_COUNTRY_NAME, u"US"),
- x509.NameAttribute(x509.OID_COMMON_NAME, u"cryptography.io"),
- ]))
- ])
-
- rev = crl[1]
- issuer = rev.extensions.get_extension_for_oid(
- x509.OID_CERTIFICATE_ISSUER).value
- assert issuer == exp_issuer
-
- # Test convenience function.
- assert rev.get_certificate_issuer() == exp_issuer
+ with pytest.raises(ValueError):
+ crl[0].extensions
@pytest.mark.requires_backend_interface(interface=RSABackend)
diff --git a/vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem b/vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem
new file mode 100644
index 00000000..a54f2409
--- /dev/null
+++ b/vectors/cryptography_vectors/x509/custom/crl_inval_cert_issuer_entry_ext.pem
@@ -0,0 +1,11 @@
+-----BEGIN X509 CRL-----
+MIIBlzCBgAIBAjANBgkqhkiG9w0BAQsFADAnMQswCQYDVQQGEwJVUzEYMBYGA1UE
+AwwPY3J5cHRvZ3JhcGh5LmlvGA8yMDE1MDEwMTAwMDAwMFoYDzIwMTYwMTAxMDAw
+MDAwWjAhMB8CAQAYDzIwMTUwMTAxMDAwMDAwWjAJMAcGA1UdHQQAMA0GCSqGSIb3
+DQEBCwUAA4IBAQCRSNP2LfnpubvOrZ8/UsETlVTvMNc38xM6dqzYKQV8vN+fcMXP
+1z/nTMBGNvnp7u7S+Dx/1Klq/iArtP5oOdNDeVuapfUdDgFJryXkvgX+2B0g/l9+
+/fiH9YNTEG6Yj2XC3lsVwXhid1Sx+A+b8ZXBdyjyZSJSoejPhzO5p/SQAk+ahY3I
+FZeL3CXlUUi1v3MtVLBPUQZvepZ9mIv5uRsEmHXFf6uTLmMdV/j7cQn4/K53Qb1N
+e+2WpNJOv0UIDugn2DKACF108T1YgZTcx2F4TYpnVDDkyjK4J1IMBrNie8hWA/R3
+y/9oP0PihPDhi4jcVBpDW7pRPqee+4z1KqXg
+-----END X509 CRL-----