diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2015-12-25 15:04:52 -0500 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2015-12-25 15:04:52 -0500 |
commit | cad8ae268c5009c989b765021404ff8c86df1d8b (patch) | |
tree | 701630292bc8f0dd698487d7b95ef262fca834b4 /src | |
parent | ef5f9fc339a7137f5a9761f8c27a08c554c27b1c (diff) | |
parent | c33ffd7527a4ce77010425fedfbeed27856c8aa8 (diff) | |
download | cryptography-cad8ae268c5009c989b765021404ff8c86df1d8b.tar.gz cryptography-cad8ae268c5009c989b765021404ff8c86df1d8b.tar.bz2 cryptography-cad8ae268c5009c989b765021404ff8c86df1d8b.zip |
Merge pull request #2571 from reaperhulk/revokedcertificatebuilder
RevokedCertificateBuilder
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 21 | ||||
-rw-r--r-- | src/cryptography/x509/__init__.py | 3 | ||||
-rw-r--r-- | src/cryptography/x509/base.py | 44 |
3 files changed, 65 insertions, 3 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index a60bf82b..81316da5 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -38,7 +38,7 @@ from cryptography.hazmat.backends.openssl.rsa import ( ) from cryptography.hazmat.backends.openssl.x509 import ( _Certificate, _CertificateRevocationList, _CertificateSigningRequest, - _DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME + _DISTPOINT_TYPE_FULLNAME, _DISTPOINT_TYPE_RELATIVENAME, _RevokedCertificate ) from cryptography.hazmat.bindings._openssl import ffi as _ffi from cryptography.hazmat.bindings.openssl import binding @@ -1559,7 +1559,24 @@ class Backend(object): self.openssl_assert(res >= 1) def create_x509_revoked_certificate(self, builder): - raise NotImplementedError("Not yet implemented") + if not isinstance(builder, x509.RevokedCertificateBuilder): + raise TypeError('Builder type mismatch.') + + x509_revoked = self._lib.X509_REVOKED_new() + self.openssl_assert(x509_revoked != self._ffi.NULL) + x509_revoked = self._ffi.gc(x509_revoked, self._lib.X509_REVOKED_free) + serial_number = _encode_asn1_int_gc(self, builder._serial_number) + res = self._lib.X509_REVOKED_set_serialNumber( + x509_revoked, serial_number + ) + self.openssl_assert(res == 1) + res = self._lib.ASN1_TIME_set( + x509_revoked.revocationDate, + calendar.timegm(builder._revocation_date.timetuple()) + ) + self.openssl_assert(res != self._ffi.NULL) + # TODO: add crl entry extensions + return _RevokedCertificate(self, None, x509_revoked) def load_pem_private_key(self, data, password): return self._load_key( diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 4978b199..5653144c 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -8,7 +8,7 @@ from cryptography.x509.base import ( Certificate, CertificateBuilder, CertificateRevocationList, CertificateRevocationListBuilder, CertificateSigningRequest, CertificateSigningRequestBuilder, - InvalidVersion, RevokedCertificate, + InvalidVersion, RevokedCertificate, RevokedCertificateBuilder, Version, load_der_x509_certificate, load_der_x509_crl, load_der_x509_csr, load_pem_x509_certificate, load_pem_x509_crl, load_pem_x509_csr, ) @@ -156,6 +156,7 @@ __all__ = [ "CertificateRevocationListBuilder", "CertificateSigningRequest", "RevokedCertificate", + "RevokedCertificateBuilder", "CertificateSigningRequestBuilder", "CertificateBuilder", "Version", diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 49cbcf75..e29a3105 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -602,3 +602,47 @@ class CertificateRevocationListBuilder(object): raise ValueError("A CRL must have a next update time") return backend.create_x509_crl(self, private_key, algorithm) + + +class RevokedCertificateBuilder(object): + def __init__(self, serial_number=None, revocation_date=None, + extensions=[]): + self._serial_number = serial_number + self._revocation_date = revocation_date + self._extensions = extensions + + def serial_number(self, number): + if not isinstance(number, six.integer_types): + raise TypeError('Serial number must be of integral type.') + if self._serial_number is not None: + raise ValueError('The serial number may only be set once.') + if number < 0: + raise ValueError('The serial number should be non-negative.') + if utils.bit_length(number) > 160: # As defined in RFC 5280 + raise ValueError('The serial number should not be more than 160 ' + 'bits.') + return RevokedCertificateBuilder( + number, self._revocation_date, self._extensions + ) + + def revocation_date(self, time): + if not isinstance(time, datetime.datetime): + raise TypeError('Expecting datetime object.') + if self._revocation_date is not None: + raise ValueError('The revocation date may only be set once.') + if time <= _UNIX_EPOCH: + raise ValueError('The revocation date must be after the unix' + ' epoch (1970 January 1).') + return RevokedCertificateBuilder( + self._serial_number, time, self._extensions + ) + + def build(self, backend): + if self._serial_number is None: + raise ValueError("A revoked certificate must have a serial number") + if self._revocation_date is None: + raise ValueError( + "A revoked certificate must have a revocation date" + ) + + return backend.create_x509_revoked_certificate(self) |