aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2015-12-25 10:59:22 -0600
committerPaul Kehrer <paul.l.kehrer@gmail.com>2015-12-25 13:01:47 -0600
commitc33ffd7527a4ce77010425fedfbeed27856c8aa8 (patch)
tree701630292bc8f0dd698487d7b95ef262fca834b4 /src
parentef5f9fc339a7137f5a9761f8c27a08c554c27b1c (diff)
downloadcryptography-c33ffd7527a4ce77010425fedfbeed27856c8aa8.tar.gz
cryptography-c33ffd7527a4ce77010425fedfbeed27856c8aa8.tar.bz2
cryptography-c33ffd7527a4ce77010425fedfbeed27856c8aa8.zip
RevokedCertificateBuilder
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py21
-rw-r--r--src/cryptography/x509/__init__.py3
-rw-r--r--src/cryptography/x509/base.py44
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)