From e5f152b0a93b105cc32fe5adf06899f4f5cd0936 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 25 Dec 2015 23:55:47 -0600 Subject: support CRL entry extension encoding in the RevokedCertificateBuilder --- .../hazmat/backends/openssl/backend.py | 80 +++++++++++++++++++++- src/cryptography/x509/base.py | 15 ++++ 2 files changed, 92 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index c0c9ebe2..6c7a6840 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -53,7 +53,7 @@ from cryptography.hazmat.primitives.ciphers.algorithms import ( from cryptography.hazmat.primitives.ciphers.modes import ( CBC, CFB, CFB8, CTR, ECB, GCM, OFB ) -from cryptography.x509.oid import ExtensionOID, NameOID +from cryptography.x509.oid import CRLEntryExtensionOID, ExtensionOID, NameOID _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) @@ -164,6 +164,68 @@ def _encode_crl_number(backend, crl_number): return pp, r +_CRL_ENTRY_REASONFLAGS = { + x509.ReasonFlags.unspecified: 0, + x509.ReasonFlags.key_compromise: 1, + x509.ReasonFlags.ca_compromise: 2, + x509.ReasonFlags.affiliation_changed: 3, + x509.ReasonFlags.superseded: 4, + x509.ReasonFlags.cessation_of_operation: 5, + x509.ReasonFlags.certificate_hold: 6, + x509.ReasonFlags.remove_from_crl: 8, + x509.ReasonFlags.privilege_withdrawn: 9, + x509.ReasonFlags.aa_compromise: 10 +} + + +def _encode_crl_reason(backend, crl_reason): + asn1enum = backend._lib.ASN1_ENUMERATED_new() + backend.openssl_assert(asn1enum != backend._ffi.NULL) + asn1enum = backend._ffi.gc(asn1enum, backend._lib.ASN1_ENUMERATED_free) + res = backend._lib.ASN1_ENUMERATED_set( + asn1enum, _CRL_ENTRY_REASONFLAGS[crl_reason.reason] + ) + backend.openssl_assert(res == 1) + pp = backend._ffi.new('unsigned char **') + r = backend._lib.i2d_ASN1_ENUMERATED(asn1enum, pp) + backend.openssl_assert(r > 0) + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + +def _encode_invalidity_date(backend, invalidity_date): + time = backend._lib.ASN1_GENERALIZEDTIME_set( + backend._ffi.NULL, calendar.timegm( + invalidity_date.invalidity_date.timetuple() + ) + ) + backend.openssl_assert(time != backend._ffi.NULL) + time = backend._ffi.gc(time, backend._lib.ASN1_GENERALIZEDTIME_free) + pp = backend._ffi.new('unsigned char **') + r = backend._lib.i2d_ASN1_GENERALIZEDTIME(time, pp) + backend.openssl_assert(r > 0) + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + +def _encode_certificate_issuer(backend, certificate_issuer): + general_names = _encode_general_names(backend, certificate_issuer) + general_names = backend._ffi.gc( + general_names, backend._lib.GENERAL_NAMES_free + ) + pp = backend._ffi.new("unsigned char **") + r = backend._lib.i2d_GENERAL_NAMES(general_names, pp) + backend.openssl_assert(r > 0) + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + def _encode_certificate_policies(backend, certificate_policies): cp = backend._lib.sk_POLICYINFO_new_null() backend.openssl_assert(cp != backend._ffi.NULL) @@ -645,6 +707,12 @@ _CRL_EXTENSION_ENCODE_HANDLERS = { ExtensionOID.CRL_NUMBER: _encode_crl_number, } +_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = { + CRLEntryExtensionOID.CERTIFICATE_ISSUER: _encode_certificate_issuer, + CRLEntryExtensionOID.CRL_REASON: _encode_crl_reason, + CRLEntryExtensionOID.INVALIDITY_DATE: _encode_invalidity_date, +} + class _PasswordUserdata(object): def __init__(self, password): @@ -1505,7 +1573,6 @@ class Backend(object): next_update = self._ffi.gc(next_update, self._lib.ASN1_TIME_free) res = self._lib.X509_CRL_set_nextUpdate(x509_crl, next_update) self.openssl_assert(res == 1) - # TODO: support revoked certificates # Add extensions. self._create_x509_extensions( @@ -1583,7 +1650,14 @@ class Backend(object): calendar.timegm(builder._revocation_date.timetuple()) ) self.openssl_assert(res != self._ffi.NULL) - # TODO: add crl entry extensions + # add CRL entry extensions + self._create_x509_extensions( + extensions=builder._extensions, + handlers=_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS, + x509_obj=x509_revoked, + add_func=self._lib.X509_REVOKED_add_ext, + gc=True + ) return _RevokedCertificate(self, None, x509_revoked) def load_pem_private_key(self, data, password): diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index bc927e87..55e965f7 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -650,6 +650,21 @@ class RevokedCertificateBuilder(object): self._serial_number, time, self._extensions ) + def add_extension(self, extension, critical): + if not isinstance(extension, ExtensionType): + raise TypeError("extension must be an ExtensionType") + + extension = Extension(extension.oid, critical, extension) + + # TODO: This is quadratic in the number of extensions + for e in self._extensions: + if e.oid == extension.oid: + raise ValueError('This extension has already been set.') + return RevokedCertificateBuilder( + self._serial_number, self._revocation_date, + self._extensions + [extension] + ) + def build(self, backend): if self._serial_number is None: raise ValueError("A revoked certificate must have a serial number") -- cgit v1.2.3 From 2fb641232f2bac7d95fc76e34f27d9f29434bbb1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 26 Dec 2015 14:25:37 -0600 Subject: move around a dict --- src/cryptography/hazmat/backends/openssl/backend.py | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 6c7a6840..ca07fe70 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -37,8 +37,9 @@ from cryptography.hazmat.backends.openssl.rsa import ( _RSAPrivateKey, _RSAPublicKey ) from cryptography.hazmat.backends.openssl.x509 import ( - _Certificate, _CertificateRevocationList, _CertificateSigningRequest, - _DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME, _RevokedCertificate + _CRL_ENTRY_REASON_ENUM_TO_CODE, _Certificate, _CertificateRevocationList, + _CertificateSigningRequest, _DISTPOINT_TYPE_FULLNAME, + _DISTPOINT_TYPE_RELATIVENAME, _RevokedCertificate ) from cryptography.hazmat.bindings._openssl import ffi as _ffi from cryptography.hazmat.bindings.openssl import binding @@ -164,26 +165,12 @@ def _encode_crl_number(backend, crl_number): return pp, r -_CRL_ENTRY_REASONFLAGS = { - x509.ReasonFlags.unspecified: 0, - x509.ReasonFlags.key_compromise: 1, - x509.ReasonFlags.ca_compromise: 2, - x509.ReasonFlags.affiliation_changed: 3, - x509.ReasonFlags.superseded: 4, - x509.ReasonFlags.cessation_of_operation: 5, - x509.ReasonFlags.certificate_hold: 6, - x509.ReasonFlags.remove_from_crl: 8, - x509.ReasonFlags.privilege_withdrawn: 9, - x509.ReasonFlags.aa_compromise: 10 -} - - def _encode_crl_reason(backend, crl_reason): asn1enum = backend._lib.ASN1_ENUMERATED_new() backend.openssl_assert(asn1enum != backend._ffi.NULL) asn1enum = backend._ffi.gc(asn1enum, backend._lib.ASN1_ENUMERATED_free) res = backend._lib.ASN1_ENUMERATED_set( - asn1enum, _CRL_ENTRY_REASONFLAGS[crl_reason.reason] + asn1enum, _CRL_ENTRY_REASON_ENUM_TO_CODE[crl_reason.reason] ) backend.openssl_assert(res == 1) pp = backend._ffi.new('unsigned char **') -- cgit v1.2.3 From 3a03d7ba193b07d1146a6ff7615721598f05bfe0 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 27 Dec 2015 09:11:08 -0600 Subject: _encode_alt_name already does this --- src/cryptography/hazmat/backends/openssl/backend.py | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index ca07fe70..109993f2 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -199,20 +199,6 @@ def _encode_invalidity_date(backend, invalidity_date): return pp, r -def _encode_certificate_issuer(backend, certificate_issuer): - general_names = _encode_general_names(backend, certificate_issuer) - general_names = backend._ffi.gc( - general_names, backend._lib.GENERAL_NAMES_free - ) - pp = backend._ffi.new("unsigned char **") - r = backend._lib.i2d_GENERAL_NAMES(general_names, pp) - backend.openssl_assert(r > 0) - pp = backend._ffi.gc( - pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) - ) - return pp, r - - def _encode_certificate_policies(backend, certificate_policies): cp = backend._lib.sk_POLICYINFO_new_null() backend.openssl_assert(cp != backend._ffi.NULL) @@ -695,7 +681,7 @@ _CRL_EXTENSION_ENCODE_HANDLERS = { } _CRL_ENTRY_EXTENSION_ENCODE_HANDLERS = { - CRLEntryExtensionOID.CERTIFICATE_ISSUER: _encode_certificate_issuer, + CRLEntryExtensionOID.CERTIFICATE_ISSUER: _encode_alt_name, CRLEntryExtensionOID.CRL_REASON: _encode_crl_reason, CRLEntryExtensionOID.INVALIDITY_DATE: _encode_invalidity_date, } -- cgit v1.2.3