aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py119
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ssl.py3
-rw-r--r--src/cryptography/x509.py37
3 files changed, 148 insertions, 11 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 9d70d72f..07e54baa 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -56,22 +56,23 @@ def _asn1_string_to_utf8(backend, asn1_string):
return backend._ffi.buffer(buf[0], res)[:].decode('utf8')
+def _build_x509_name_entry(backend, x509_name_entry):
+ obj = backend._lib.X509_NAME_ENTRY_get_object(x509_name_entry)
+ assert obj != backend._ffi.NULL
+ data = backend._lib.X509_NAME_ENTRY_get_data(x509_name_entry)
+ assert data != backend._ffi.NULL
+ value = _asn1_string_to_utf8(backend, data)
+ oid = _obj2txt(backend, obj)
+
+ return x509.NameAttribute(x509.ObjectIdentifier(oid), value)
+
+
def _build_x509_name(backend, x509_name):
count = backend._lib.X509_NAME_entry_count(x509_name)
attributes = []
for x in range(count):
entry = backend._lib.X509_NAME_get_entry(x509_name, x)
- obj = backend._lib.X509_NAME_ENTRY_get_object(entry)
- assert obj != backend._ffi.NULL
- data = backend._lib.X509_NAME_ENTRY_get_data(entry)
- assert data != backend._ffi.NULL
- value = _asn1_string_to_utf8(backend, data)
- oid = _obj2txt(backend, obj)
- attributes.append(
- x509.NameAttribute(
- x509.ObjectIdentifier(oid), value
- )
- )
+ attributes.append(_build_x509_name_entry(backend, entry))
return x509.Name(attributes)
@@ -292,6 +293,8 @@ class _Certificate(object):
value = self._build_authority_information_access(ext)
elif oid == x509.OID_CERTIFICATE_POLICIES:
value = self._build_certificate_policies(ext)
+ elif oid == x509.OID_CRL_DISTRIBUTION_POINTS:
+ value = self._build_crl_distribution_points(ext)
elif critical:
raise x509.UnsupportedExtension(
"{0} is not currently supported".format(oid), oid
@@ -518,6 +521,100 @@ class _Certificate(object):
return x509.ExtendedKeyUsage(ekus)
+ def _build_crl_distribution_points(self, ext):
+ cdps = self._backend._ffi.cast(
+ "Cryptography_STACK_OF_DIST_POINT *",
+ self._backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert cdps != self._backend._ffi.NULL
+ cdps = self._backend._ffi.gc(
+ cdps, self._backend._lib.sk_DIST_POINT_free)
+ num = self._backend._lib.sk_DIST_POINT_num(cdps)
+
+ dist_points = []
+ for i in range(num):
+ full_name = None
+ relative_name = None
+ crl_issuer = None
+ reasons = None
+ cdp = self._backend._lib.sk_DIST_POINT_value(cdps, i)
+ if cdp.reasons != self._backend._ffi.NULL:
+ # We will check each bit from RFC 5280
+ # ReasonFlags ::= BIT STRING {
+ # unused (0),
+ # keyCompromise (1),
+ # cACompromise (2),
+ # affiliationChanged (3),
+ # superseded (4),
+ # cessationOfOperation (5),
+ # certificateHold (6),
+ # privilegeWithdrawn (7),
+ # aACompromise (8) }
+ reasons = []
+ get_bit = self._backend._lib.ASN1_BIT_STRING_get_bit
+ if get_bit(cdp.reasons, 1):
+ reasons.append(x509.ReasonFlags.key_compromise)
+
+ if get_bit(cdp.reasons, 2):
+ reasons.append(x509.ReasonFlags.ca_compromise)
+
+ if get_bit(cdp.reasons, 3):
+ reasons.append(x509.ReasonFlags.affiliation_changed)
+
+ if get_bit(cdp.reasons, 4):
+ reasons.append(x509.ReasonFlags.superseded)
+
+ if get_bit(cdp.reasons, 5):
+ reasons.append(x509.ReasonFlags.cessation_of_operation)
+
+ if get_bit(cdp.reasons, 6):
+ reasons.append(x509.ReasonFlags.certificate_hold)
+
+ if get_bit(cdp.reasons, 7):
+ reasons.append(x509.ReasonFlags.privilege_withdrawn)
+
+ if get_bit(cdp.reasons, 8):
+ reasons.append(x509.ReasonFlags.aa_compromise)
+
+ reasons = frozenset(reasons)
+
+ if cdp.CRLissuer != self._backend._ffi.NULL:
+ crl_issuer = _build_general_names(self._backend, cdp.CRLissuer)
+
+ # Certificates may have a crl_issuer/reasons and no distribution
+ # point so make sure it's not null.
+ if cdp.distpoint != self._backend._ffi.NULL:
+ # Type 0 is fullName, there is no #define for it in the code.
+ if cdp.distpoint.type == 0:
+ full_name = _build_general_names(
+ self._backend, cdp.distpoint.name.fullname
+ )
+ # OpenSSL code doesn't test for a specific type for
+ # relativename, everything that isn't fullname is considered
+ # relativename.
+ else:
+ rns = cdp.distpoint.name.relativename
+ rnum = self._backend._lib.sk_X509_NAME_ENTRY_num(rns)
+ attributes = []
+ for i in range(rnum):
+ rn = self._backend._lib.sk_X509_NAME_ENTRY_value(
+ rns, i
+ )
+ assert rn != self._backend._ffi.NULL
+ attributes.append(
+ _build_x509_name_entry(self._backend, rn)
+ )
+
+ relative_name = x509.Name(attributes)
+
+ dist_points.append(
+ x509.DistributionPoint(
+ full_name, relative_name, reasons, crl_issuer
+ )
+ )
+
+ return x509.CRLDistributionPoints(dist_points)
+
@utils.register_interface(x509.CertificateSigningRequest)
class _CertificateSigningRequest(object):
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index c12624bc..5445f3c9 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -331,6 +331,7 @@ long SSL_set_tlsext_status_ocsp_resp(SSL *, unsigned char *, int);
long SSL_get_tlsext_status_ocsp_resp(SSL *, const unsigned char **);
long SSL_set_tlsext_status_type(SSL *, long);
long SSL_CTX_set_tlsext_status_cb(SSL_CTX *, int(*)(SSL *, void *));
+long SSL_CTX_set_tlsext_status_arg(SSL_CTX *, void *);
long SSL_session_reused(SSL *);
@@ -434,6 +435,7 @@ static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB = 1;
#else
static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB = 0;
long (*SSL_CTX_set_tlsext_status_cb)(SSL_CTX *, int(*)(SSL *, void *)) = NULL;
+long (*SSL_CTX_set_tlsext_status_arg)(SSL_CTX *, void *) = NULL;
#endif
#ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP
@@ -639,6 +641,7 @@ CONDITIONAL_NAMES = {
"Cryptography_HAS_TLSEXT_STATUS_REQ_CB": [
"SSL_CTX_set_tlsext_status_cb",
+ "SSL_CTX_set_tlsext_status_arg"
],
"Cryptography_HAS_STATUS_REQ_OCSP_RESP": [
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index b0a4a352..71ba9042 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -333,6 +333,15 @@ class BasicConstraints(object):
return ("<BasicConstraints(ca={0.ca}, "
"path_length={0.path_length})>").format(self)
+ def __eq__(self, other):
+ if not isinstance(other, BasicConstraints):
+ return NotImplemented
+
+ return self.ca == other.ca and self.path_length == other.path_length
+
+ def __ne__(self, other):
+ return not self == other
+
class KeyUsage(object):
def __init__(self, digital_signature, content_commitment, key_encipherment,
@@ -397,6 +406,25 @@ class KeyUsage(object):
"encipher_only={1}, decipher_only={2})>").format(
self, encipher_only, decipher_only)
+ def __eq__(self, other):
+ if not isinstance(other, KeyUsage):
+ return NotImplemented
+
+ return (
+ self.digital_signature == other.digital_signature and
+ self.content_commitment == other.content_commitment and
+ self.key_encipherment == other.key_encipherment and
+ self.data_encipherment == other.data_encipherment and
+ self.key_agreement == other.key_agreement and
+ self.key_cert_sign == other.key_cert_sign and
+ self.crl_sign == other.crl_sign and
+ self._encipher_only == other._encipher_only and
+ self._decipher_only == other._decipher_only
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
class AuthorityInformationAccess(object):
def __init__(self, descriptions):
@@ -914,6 +942,15 @@ class SubjectAlternativeName(object):
def __repr__(self):
return "<SubjectAlternativeName({0})>".format(self._general_names)
+ def __eq__(self, other):
+ if not isinstance(other, SubjectAlternativeName):
+ return NotImplemented
+
+ return self._general_names == other._general_names
+
+ def __ne__(self, other):
+ return not self == other
+
class AuthorityKeyIdentifier(object):
def __init__(self, key_identifier, authority_cert_issuer,