aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2015-11-19 14:59:06 -0600
committerPaul Kehrer <paul.l.kehrer@gmail.com>2015-11-19 14:59:06 -0600
commitcc1962d9ece2496548032074499e2aed475b5271 (patch)
tree5fe5150bfc4313b610a416491f259fd3aca80d7c
parenta06e0cf66906a723682731af53e295179d5c9f4d (diff)
parent569aa6a847cf6f533d41240d574c8f56512d2324 (diff)
downloadcryptography-cc1962d9ece2496548032074499e2aed475b5271.tar.gz
cryptography-cc1962d9ece2496548032074499e2aed475b5271.tar.bz2
cryptography-cc1962d9ece2496548032074499e2aed475b5271.zip
Merge pull request #2489 from etrauschke/crl_verify
add tbsCertList and signature interfaces to CRLs
-rw-r--r--docs/x509/reference.rst20
-rw-r--r--src/_cffi_src/openssl/x509.py3
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py15
-rw-r--r--src/cryptography/x509/base.py12
-rw-r--r--tests/test_x509.py38
5 files changed, 88 insertions, 0 deletions
diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst
index 10ba9ec3..35c00e61 100644
--- a/docs/x509/reference.rst
+++ b/docs/x509/reference.rst
@@ -504,6 +504,26 @@ X.509 CRL (Certificate Revocation List) Object
The extensions encoded in the CRL.
+ .. attribute:: signature
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The bytes of the CRL's signature.
+
+ .. attribute:: tbs_certlist_bytes
+
+ .. versionadded:: 1.2
+
+ :type: bytes
+
+ The DER encoded bytes payload (as defined by :rfc:`5280`) that is hashed
+ and then signed by the private key of the CRL's issuer. This data may be
+ used to validate a signature, but use extreme caution as CRL validation
+ is a complex problem that involves much more than just signature checks.
+
+
X.509 Certificate Builder
~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py
index 2024101b..ebb78a31 100644
--- a/src/_cffi_src/openssl/x509.py
+++ b/src/_cffi_src/openssl/x509.py
@@ -65,6 +65,7 @@ typedef struct {
typedef struct {
X509_CRL_INFO *crl;
X509_ALGOR *sig_alg;
+ ASN1_BIT_STRING *signature;
...;
} X509_CRL;
@@ -259,6 +260,8 @@ void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *);
MACROS = """
int i2d_X509_CINF(X509_CINF *, unsigned char **);
+int i2d_X509_CRL_INFO(X509_CRL_INFO *, unsigned char **);
+
long X509_get_version(X509 *);
ASN1_TIME *X509_get_notBefore(X509 *);
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 3afbc40f..8fa43ea8 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -818,6 +818,21 @@ class _CertificateRevocationList(object):
self._backend.openssl_assert(lu != self._backend._ffi.NULL)
return self._backend._parse_asn1_time(lu)
+ @property
+ def signature(self):
+ return self._backend._asn1_string_to_bytes(self._x509_crl.signature)
+
+ @property
+ def tbs_certlist_bytes(self):
+ pp = self._backend._ffi.new("unsigned char **")
+ # the X509_CRL_INFO struct holds the tbsCertList data
+ res = self._backend._lib.i2d_X509_CRL_INFO(self._x509_crl.crl, pp)
+ self._backend.openssl_assert(res > 0)
+ pp = self._backend._ffi.gc(
+ pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0])
+ )
+ return self._backend._ffi.buffer(pp[0], res)[:]
+
def _revoked_certificates(self):
revoked = self._backend._lib.X509_CRL_get_REVOKED(self._x509_crl)
self._backend.openssl_assert(revoked != self._backend._ffi.NULL)
diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py
index ad561b94..6c2386f6 100644
--- a/src/cryptography/x509/base.py
+++ b/src/cryptography/x509/base.py
@@ -194,6 +194,18 @@ class CertificateRevocationList(object):
Returns an Extensions object containing a list of CRL extensions.
"""
+ @abc.abstractproperty
+ def signature(self):
+ """
+ Returns the signature bytes.
+ """
+
+ @abc.abstractproperty
+ def tbs_certlist_bytes(self):
+ """
+ Returns the tbsCertList payload bytes as defined in RFC 5280.
+ """
+
@abc.abstractmethod
def __eq__(self, other):
"""
diff --git a/tests/test_x509.py b/tests/test_x509.py
index c4457239..9b5dda69 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -184,6 +184,44 @@ class TestCertificateRevocationList(object):
with pytest.raises(NotImplementedError):
crl.extensions
+ def test_signature(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "custom", "crl_all_reasons.pem"),
+ x509.load_pem_x509_crl,
+ backend
+ )
+
+ assert crl.signature == binascii.unhexlify(
+ b"536a5a0794f68267361e7bc2f19167a3e667a2ab141535616855d8deb2ba1af"
+ b"9fd4546b1fe76b454eb436af7b28229fedff4634dfc9dd92254266219ae0ea8"
+ b"75d9ff972e9a2da23d5945f073da18c50a4265bfed9ca16586347800ef49dd1"
+ b"6856d7265f4f3c498a57f04dc04404e2bd2e2ada1f5697057aacef779a18371"
+ b"c621edc9a5c2b8ec1716e8fa22feeb7fcec0ce9156c8d344aa6ae8d1a5d99d0"
+ b"9386df36307df3b63c83908f4a61a0ff604c1e292ad63b349d1082ddd7ae1b7"
+ b"c178bba995523ec6999310c54da5706549797bfb1230f5593ba7b4353dade4f"
+ b"d2be13a57580a6eb20b5c4083f000abac3bf32cd8b75f23e4c8f4b3a79e1e2d"
+ b"58a472b0"
+ )
+
+ def test_tbs_certlist_bytes(self, backend):
+ crl = _load_cert(
+ os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"),
+ x509.load_der_x509_crl,
+ backend
+ )
+
+ ca_cert = _load_cert(
+ os.path.join("x509", "PKITS_data", "certs", "GoodCACert.crt"),
+ x509.load_der_x509_certificate,
+ backend
+ )
+
+ verifier = ca_cert.public_key().verifier(
+ crl.signature, padding.PKCS1v15(), crl.signature_hash_algorithm
+ )
+ verifier.update(crl.tbs_certlist_bytes)
+ verifier.verify()
+
@pytest.mark.requires_backend_interface(interface=X509Backend)
class TestRevokedCertificate(object):