aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/__about__.py2
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py614
-rw-r--r--src/cryptography/hazmat/bindings/openssl/asn1.py2
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ec.py15
-rw-r--r--src/cryptography/hazmat/bindings/openssl/evp.py4
-rw-r--r--src/cryptography/hazmat/bindings/openssl/ssl.py31
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509.py24
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509_vfy.py16
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509name.py7
-rw-r--r--src/cryptography/hazmat/bindings/openssl/x509v3.py74
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/dsa.py22
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/ec.py29
-rw-r--r--src/cryptography/hazmat/primitives/asymmetric/rsa.py22
-rw-r--r--src/cryptography/hazmat/primitives/interfaces/__init__.py351
-rw-r--r--src/cryptography/utils.py3
-rw-r--r--src/cryptography/x509.py507
16 files changed, 1098 insertions, 625 deletions
diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py
index 0f8d4871..9c28be2e 100644
--- a/src/cryptography/__about__.py
+++ b/src/cryptography/__about__.py
@@ -14,7 +14,7 @@ __summary__ = ("cryptography is a package which provides cryptographic recipes"
" and primitives to Python developers.")
__uri__ = "https://github.com/pyca/cryptography"
-__version__ = "0.9.dev1"
+__version__ = "1.0.dev1"
__author__ = "The cryptography developers"
__email__ = "cryptography-dev@python.org"
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 42ca138d..f46dd1b7 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -1,15 +1,6 @@
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-# implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
from __future__ import absolute_import, division, print_function
@@ -25,7 +16,7 @@ from six.moves import urllib_parse
from cryptography import utils, x509
from cryptography.exceptions import UnsupportedAlgorithm
-from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives import hashes, serialization
def _obj2txt(backend, obj):
@@ -38,34 +29,57 @@ def _obj2txt(backend, obj):
return backend._ffi.buffer(buf, res)[:].decode()
-def _build_x509_name(backend, x509_name):
+def _asn1_integer_to_int(backend, asn1_int):
+ bn = backend._lib.ASN1_INTEGER_to_BN(asn1_int, backend._ffi.NULL)
+ assert bn != backend._ffi.NULL
+ bn = backend._ffi.gc(bn, backend._lib.BN_free)
+ return backend._bn_to_int(bn)
+
+
+def _asn1_string_to_utf8(backend, asn1_string):
+ buf = backend._ffi.new("unsigned char **")
+ res = backend._lib.ASN1_STRING_to_UTF8(buf, asn1_string)
+ assert res >= 0
+ assert buf[0] != backend._ffi.NULL
+ buf = backend._ffi.gc(
+ buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0])
+ )
+ return backend._ffi.buffer(buf[0], res)[:].decode('utf8')
+
+
+def _decode_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 _decode_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
- buf = backend._ffi.new("unsigned char **")
- res = backend._lib.ASN1_STRING_to_UTF8(buf, data)
- assert res >= 0
- assert buf[0] != backend._ffi.NULL
- buf = backend._ffi.gc(
- buf, lambda buffer: backend._lib.OPENSSL_free(buffer[0])
- )
- value = backend._ffi.buffer(buf[0], res)[:].decode('utf8')
- oid = _obj2txt(backend, obj)
- attributes.append(
- x509.NameAttribute(
- x509.ObjectIdentifier(oid), value
- )
- )
+ attributes.append(_decode_x509_name_entry(backend, entry))
return x509.Name(attributes)
-def _build_general_name(backend, gn):
+def _decode_general_names(backend, gns):
+ num = backend._lib.sk_GENERAL_NAME_num(gns)
+ names = []
+ for i in range(num):
+ gn = backend._lib.sk_GENERAL_NAME_value(gns, i)
+ assert gn != backend._ffi.NULL
+ names.append(_decode_general_name(backend, gn))
+
+ return names
+
+
+def _decode_general_name(backend, gn):
if gn.type == backend._lib.GEN_DNS:
data = backend._ffi.buffer(gn.d.dNSName.data, gn.d.dNSName.length)[:]
return x509.DNSName(idna.decode(data))
@@ -106,7 +120,7 @@ def _build_general_name(backend, gn):
)
elif gn.type == backend._lib.GEN_DIRNAME:
return x509.DirectoryName(
- _build_x509_name(backend, gn.d.directoryName)
+ _decode_x509_name(backend, gn.d.directoryName)
)
elif gn.type == backend._lib.GEN_EMAIL:
data = backend._ffi.buffer(
@@ -182,12 +196,7 @@ class _Certificate(object):
def serial(self):
asn1_int = self._backend._lib.X509_get_serialNumber(self._x509)
assert asn1_int != self._backend._ffi.NULL
- bn = self._backend._lib.ASN1_INTEGER_to_BN(
- asn1_int, self._backend._ffi.NULL
- )
- assert bn != self._backend._ffi.NULL
- bn = self._backend._ffi.gc(bn, self._backend._lib.BN_free)
- return self._backend._bn_to_int(bn)
+ return _asn1_integer_to_int(self._backend, asn1_int)
def public_key(self):
pkey = self._backend._lib.X509_get_pubkey(self._x509)
@@ -226,13 +235,13 @@ class _Certificate(object):
def issuer(self):
issuer = self._backend._lib.X509_get_issuer_name(self._x509)
assert issuer != self._backend._ffi.NULL
- return _build_x509_name(self._backend, issuer)
+ return _decode_x509_name(self._backend, issuer)
@property
def subject(self):
subject = self._backend._lib.X509_get_subject_name(self._x509)
assert subject != self._backend._ffi.NULL
- return _build_x509_name(self._backend, subject)
+ return _decode_x509_name(self._backend, subject)
@property
def signature_hash_algorithm(self):
@@ -260,19 +269,25 @@ class _Certificate(object):
"Duplicate {0} extension found".format(oid), oid
)
elif oid == x509.OID_BASIC_CONSTRAINTS:
- value = self._build_basic_constraints(ext)
+ value = _decode_basic_constraints(self._backend, ext)
elif oid == x509.OID_SUBJECT_KEY_IDENTIFIER:
- value = self._build_subject_key_identifier(ext)
+ value = _decode_subject_key_identifier(self._backend, ext)
elif oid == x509.OID_KEY_USAGE:
- value = self._build_key_usage(ext)
+ value = _decode_key_usage(self._backend, ext)
elif oid == x509.OID_SUBJECT_ALTERNATIVE_NAME:
- value = self._build_subject_alt_name(ext)
+ value = _decode_subject_alt_name(self._backend, ext)
elif oid == x509.OID_EXTENDED_KEY_USAGE:
- value = self._build_extended_key_usage(ext)
+ value = _decode_extended_key_usage(self._backend, ext)
elif oid == x509.OID_AUTHORITY_KEY_IDENTIFIER:
- value = self._build_authority_key_identifier(ext)
+ value = _decode_authority_key_identifier(self._backend, ext)
elif oid == x509.OID_AUTHORITY_INFORMATION_ACCESS:
- value = self._build_authority_information_access(ext)
+ value = _decode_authority_information_access(
+ self._backend, ext
+ )
+ elif oid == x509.OID_CERTIFICATE_POLICIES:
+ value = _decode_certificate_policies(self._backend, ext)
+ elif oid == x509.OID_CRL_DISTRIBUTION_POINTS:
+ value = _decode_crl_distribution_points(self._backend, ext)
elif critical:
raise x509.UnsupportedExtension(
"{0} is not currently supported".format(oid), oid
@@ -287,168 +302,335 @@ class _Certificate(object):
return x509.Extensions(extensions)
- def _build_basic_constraints(self, ext):
- bc_st = self._backend._lib.X509V3_EXT_d2i(ext)
- assert bc_st != self._backend._ffi.NULL
- basic_constraints = self._backend._ffi.cast(
- "BASIC_CONSTRAINTS *", bc_st
- )
- basic_constraints = self._backend._ffi.gc(
- basic_constraints, self._backend._lib.BASIC_CONSTRAINTS_free
- )
- # The byte representation of an ASN.1 boolean true is \xff. OpenSSL
- # chooses to just map this to its ordinal value, so true is 255 and
- # false is 0.
- ca = basic_constraints.ca == 255
- if basic_constraints.pathlen == self._backend._ffi.NULL:
- path_length = None
- else:
- bn = self._backend._lib.ASN1_INTEGER_to_BN(
- basic_constraints.pathlen, self._backend._ffi.NULL
- )
- assert bn != self._backend._ffi.NULL
- bn = self._backend._ffi.gc(bn, self._backend._lib.BN_free)
- path_length = self._backend._bn_to_int(bn)
-
- return x509.BasicConstraints(ca, path_length)
-
- def _build_subject_key_identifier(self, ext):
- asn1_string = self._backend._lib.X509V3_EXT_d2i(ext)
- assert asn1_string != self._backend._ffi.NULL
- asn1_string = self._backend._ffi.cast(
- "ASN1_OCTET_STRING *", asn1_string
- )
- asn1_string = self._backend._ffi.gc(
- asn1_string, self._backend._lib.ASN1_OCTET_STRING_free
- )
- return x509.SubjectKeyIdentifier(
- self._backend._ffi.buffer(asn1_string.data, asn1_string.length)[:]
- )
+ def public_bytes(self, encoding):
+ if not isinstance(encoding, serialization.Encoding):
+ raise TypeError("encoding must be an item from the Encoding enum")
- def _build_authority_key_identifier(self, ext):
- akid = self._backend._lib.X509V3_EXT_d2i(ext)
- assert akid != self._backend._ffi.NULL
- akid = self._backend._ffi.cast("AUTHORITY_KEYID *", akid)
- akid = self._backend._ffi.gc(
- akid, self._backend._lib.AUTHORITY_KEYID_free
+ bio = self._backend._create_mem_bio()
+ if encoding is serialization.Encoding.PEM:
+ res = self._backend._lib.PEM_write_bio_X509(bio, self._x509)
+ elif encoding is serialization.Encoding.DER:
+ res = self._backend._lib.i2d_X509_bio(bio, self._x509)
+ assert res == 1
+ return self._backend._read_mem_bio(bio)
+
+
+def _decode_certificate_policies(backend, ext):
+ cp = backend._ffi.cast(
+ "Cryptography_STACK_OF_POLICYINFO *",
+ backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert cp != backend._ffi.NULL
+ cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free)
+ num = backend._lib.sk_POLICYINFO_num(cp)
+ certificate_policies = []
+ for i in range(num):
+ qualifiers = None
+ pi = backend._lib.sk_POLICYINFO_value(cp, i)
+ oid = x509.ObjectIdentifier(_obj2txt(backend, pi.policyid))
+ if pi.qualifiers != backend._ffi.NULL:
+ qnum = backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers)
+ qualifiers = []
+ for j in range(qnum):
+ pqi = backend._lib.sk_POLICYQUALINFO_value(
+ pi.qualifiers, j
+ )
+ pqualid = x509.ObjectIdentifier(
+ _obj2txt(backend, pqi.pqualid)
+ )
+ if pqualid == x509.OID_CPS_QUALIFIER:
+ cpsuri = backend._ffi.buffer(
+ pqi.d.cpsuri.data, pqi.d.cpsuri.length
+ )[:].decode('ascii')
+ qualifiers.append(cpsuri)
+ elif pqualid == x509.OID_CPS_USER_NOTICE:
+ user_notice = _decode_user_notice(
+ backend, pqi.d.usernotice
+ )
+ qualifiers.append(user_notice)
+
+ certificate_policies.append(
+ x509.PolicyInformation(oid, qualifiers)
)
- key_identifier = None
- authority_cert_issuer = None
- authority_cert_serial_number = None
-
- if akid.keyid != self._backend._ffi.NULL:
- key_identifier = self._backend._ffi.buffer(
- akid.keyid.data, akid.keyid.length
- )[:]
- if akid.issuer != self._backend._ffi.NULL:
- authority_cert_issuer = []
+ return x509.CertificatePolicies(certificate_policies)
- num = self._backend._lib.sk_GENERAL_NAME_num(akid.issuer)
- for i in range(num):
- gn = self._backend._lib.sk_GENERAL_NAME_value(akid.issuer, i)
- assert gn != self._backend._ffi.NULL
- value = _build_general_name(self._backend, gn)
- authority_cert_issuer.append(value)
+def _decode_user_notice(backend, un):
+ explicit_text = None
+ notice_reference = None
- if akid.serial != self._backend._ffi.NULL:
- bn = self._backend._lib.ASN1_INTEGER_to_BN(
- akid.serial, self._backend._ffi.NULL
- )
- assert bn != self._backend._ffi.NULL
- bn = self._backend._ffi.gc(bn, self._backend._lib.BN_free)
- authority_cert_serial_number = self._backend._bn_to_int(bn)
+ if un.exptext != backend._ffi.NULL:
+ explicit_text = _asn1_string_to_utf8(backend, un.exptext)
- return x509.AuthorityKeyIdentifier(
- key_identifier, authority_cert_issuer, authority_cert_serial_number
+ if un.noticeref != backend._ffi.NULL:
+ organization = _asn1_string_to_utf8(
+ backend, un.noticeref.organization
)
- def _build_authority_information_access(self, ext):
- aia = self._backend._lib.X509V3_EXT_d2i(ext)
- assert aia != self._backend._ffi.NULL
- aia = self._backend._ffi.cast(
- "Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia
- )
- aia = self._backend._ffi.gc(
- aia, self._backend._lib.sk_ACCESS_DESCRIPTION_free
+ num = backend._lib.sk_ASN1_INTEGER_num(
+ un.noticeref.noticenos
)
- num = self._backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
- access_descriptions = []
+ notice_numbers = []
for i in range(num):
- ad = self._backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i)
- assert ad.method != self._backend._ffi.NULL
- oid = x509.ObjectIdentifier(_obj2txt(self._backend, ad.method))
- assert ad.location != self._backend._ffi.NULL
- gn = _build_general_name(self._backend, ad.location)
- access_descriptions.append(x509.AccessDescription(oid, gn))
-
- return x509.AuthorityInformationAccess(access_descriptions)
-
- def _build_key_usage(self, ext):
- bit_string = self._backend._lib.X509V3_EXT_d2i(ext)
- assert bit_string != self._backend._ffi.NULL
- bit_string = self._backend._ffi.cast("ASN1_BIT_STRING *", bit_string)
- bit_string = self._backend._ffi.gc(
- bit_string, self._backend._lib.ASN1_BIT_STRING_free
- )
- get_bit = self._backend._lib.ASN1_BIT_STRING_get_bit
- digital_signature = get_bit(bit_string, 0) == 1
- content_commitment = get_bit(bit_string, 1) == 1
- key_encipherment = get_bit(bit_string, 2) == 1
- data_encipherment = get_bit(bit_string, 3) == 1
- key_agreement = get_bit(bit_string, 4) == 1
- key_cert_sign = get_bit(bit_string, 5) == 1
- crl_sign = get_bit(bit_string, 6) == 1
- encipher_only = get_bit(bit_string, 7) == 1
- decipher_only = get_bit(bit_string, 8) == 1
- return x509.KeyUsage(
- digital_signature,
- content_commitment,
- key_encipherment,
- data_encipherment,
- key_agreement,
- key_cert_sign,
- crl_sign,
- encipher_only,
- decipher_only
- )
+ asn1_int = backend._lib.sk_ASN1_INTEGER_value(
+ un.noticeref.noticenos, i
+ )
+ notice_num = _asn1_integer_to_int(
+ backend, asn1_int
+ )
+ notice_numbers.append(notice_num)
- def _build_subject_alt_name(self, ext):
- gns = self._backend._ffi.cast(
- "GENERAL_NAMES *", self._backend._lib.X509V3_EXT_d2i(ext)
+ notice_reference = x509.NoticeReference(
+ organization, notice_numbers
)
- assert gns != self._backend._ffi.NULL
- gns = self._backend._ffi.gc(gns, self._backend._lib.GENERAL_NAMES_free)
- num = self._backend._lib.sk_GENERAL_NAME_num(gns)
- general_names = []
-
- for i in range(num):
- gn = self._backend._lib.sk_GENERAL_NAME_value(gns, i)
- assert gn != self._backend._ffi.NULL
- value = _build_general_name(self._backend, gn)
- general_names.append(value)
+ return x509.UserNotice(notice_reference, explicit_text)
+
+
+def _decode_basic_constraints(backend, ext):
+ bc_st = backend._lib.X509V3_EXT_d2i(ext)
+ assert bc_st != backend._ffi.NULL
+ basic_constraints = backend._ffi.cast(
+ "BASIC_CONSTRAINTS *", bc_st
+ )
+ basic_constraints = backend._ffi.gc(
+ basic_constraints, backend._lib.BASIC_CONSTRAINTS_free
+ )
+ # The byte representation of an ASN.1 boolean true is \xff. OpenSSL
+ # chooses to just map this to its ordinal value, so true is 255 and
+ # false is 0.
+ ca = basic_constraints.ca == 255
+ if basic_constraints.pathlen == backend._ffi.NULL:
+ path_length = None
+ else:
+ path_length = _asn1_integer_to_int(
+ backend, basic_constraints.pathlen
+ )
- return x509.SubjectAlternativeName(general_names)
+ return x509.BasicConstraints(ca, path_length)
+
+
+def _decode_subject_key_identifier(backend, ext):
+ asn1_string = backend._lib.X509V3_EXT_d2i(ext)
+ assert asn1_string != backend._ffi.NULL
+ asn1_string = backend._ffi.cast(
+ "ASN1_OCTET_STRING *", asn1_string
+ )
+ asn1_string = backend._ffi.gc(
+ asn1_string, backend._lib.ASN1_OCTET_STRING_free
+ )
+ return x509.SubjectKeyIdentifier(
+ backend._ffi.buffer(asn1_string.data, asn1_string.length)[:]
+ )
+
+
+def _decode_authority_key_identifier(backend, ext):
+ akid = backend._lib.X509V3_EXT_d2i(ext)
+ assert akid != backend._ffi.NULL
+ akid = backend._ffi.cast("AUTHORITY_KEYID *", akid)
+ akid = backend._ffi.gc(
+ akid, backend._lib.AUTHORITY_KEYID_free
+ )
+ key_identifier = None
+ authority_cert_issuer = None
+ authority_cert_serial_number = None
+
+ if akid.keyid != backend._ffi.NULL:
+ key_identifier = backend._ffi.buffer(
+ akid.keyid.data, akid.keyid.length
+ )[:]
+
+ if akid.issuer != backend._ffi.NULL:
+ authority_cert_issuer = _decode_general_names(
+ backend, akid.issuer
+ )
- def _build_extended_key_usage(self, ext):
- sk = self._backend._ffi.cast(
- "Cryptography_STACK_OF_ASN1_OBJECT *",
- self._backend._lib.X509V3_EXT_d2i(ext)
+ if akid.serial != backend._ffi.NULL:
+ authority_cert_serial_number = _asn1_integer_to_int(
+ backend, akid.serial
)
- assert sk != self._backend._ffi.NULL
- sk = self._backend._ffi.gc(sk, self._backend._lib.sk_ASN1_OBJECT_free)
- num = self._backend._lib.sk_ASN1_OBJECT_num(sk)
- ekus = []
- for i in range(num):
- obj = self._backend._lib.sk_ASN1_OBJECT_value(sk, i)
- assert obj != self._backend._ffi.NULL
- oid = x509.ObjectIdentifier(_obj2txt(self._backend, obj))
- ekus.append(oid)
+ return x509.AuthorityKeyIdentifier(
+ key_identifier, authority_cert_issuer, authority_cert_serial_number
+ )
+
+
+def _decode_authority_information_access(backend, ext):
+ aia = backend._lib.X509V3_EXT_d2i(ext)
+ assert aia != backend._ffi.NULL
+ aia = backend._ffi.cast(
+ "Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia
+ )
+ aia = backend._ffi.gc(
+ aia, backend._lib.sk_ACCESS_DESCRIPTION_free
+ )
+ num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia)
+ access_descriptions = []
+ for i in range(num):
+ ad = backend._lib.sk_ACCESS_DESCRIPTION_value(aia, i)
+ assert ad.method != backend._ffi.NULL
+ oid = x509.ObjectIdentifier(_obj2txt(backend, ad.method))
+ assert ad.location != backend._ffi.NULL
+ gn = _decode_general_name(backend, ad.location)
+ access_descriptions.append(x509.AccessDescription(oid, gn))
+
+ return x509.AuthorityInformationAccess(access_descriptions)
+
+
+def _decode_key_usage(backend, ext):
+ bit_string = backend._lib.X509V3_EXT_d2i(ext)
+ assert bit_string != backend._ffi.NULL
+ bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string)
+ bit_string = backend._ffi.gc(
+ bit_string, backend._lib.ASN1_BIT_STRING_free
+ )
+ get_bit = backend._lib.ASN1_BIT_STRING_get_bit
+ digital_signature = get_bit(bit_string, 0) == 1
+ content_commitment = get_bit(bit_string, 1) == 1
+ key_encipherment = get_bit(bit_string, 2) == 1
+ data_encipherment = get_bit(bit_string, 3) == 1
+ key_agreement = get_bit(bit_string, 4) == 1
+ key_cert_sign = get_bit(bit_string, 5) == 1
+ crl_sign = get_bit(bit_string, 6) == 1
+ encipher_only = get_bit(bit_string, 7) == 1
+ decipher_only = get_bit(bit_string, 8) == 1
+ return x509.KeyUsage(
+ digital_signature,
+ content_commitment,
+ key_encipherment,
+ data_encipherment,
+ key_agreement,
+ key_cert_sign,
+ crl_sign,
+ encipher_only,
+ decipher_only
+ )
+
+
+def _decode_subject_alt_name(backend, ext):
+ gns = backend._ffi.cast(
+ "GENERAL_NAMES *", backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert gns != backend._ffi.NULL
+ gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free)
+ general_names = _decode_general_names(backend, gns)
+
+ return x509.SubjectAlternativeName(general_names)
+
+
+def _decode_extended_key_usage(backend, ext):
+ sk = backend._ffi.cast(
+ "Cryptography_STACK_OF_ASN1_OBJECT *",
+ backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert sk != backend._ffi.NULL
+ sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free)
+ num = backend._lib.sk_ASN1_OBJECT_num(sk)
+ ekus = []
+
+ for i in range(num):
+ obj = backend._lib.sk_ASN1_OBJECT_value(sk, i)
+ assert obj != backend._ffi.NULL
+ oid = x509.ObjectIdentifier(_obj2txt(backend, obj))
+ ekus.append(oid)
+
+ return x509.ExtendedKeyUsage(ekus)
+
+
+def _decode_crl_distribution_points(backend, ext):
+ cdps = backend._ffi.cast(
+ "Cryptography_STACK_OF_DIST_POINT *",
+ backend._lib.X509V3_EXT_d2i(ext)
+ )
+ assert cdps != backend._ffi.NULL
+ cdps = backend._ffi.gc(
+ cdps, backend._lib.sk_DIST_POINT_free)
+ num = 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 = backend._lib.sk_DIST_POINT_value(cdps, i)
+ if cdp.reasons != 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 = 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 != backend._ffi.NULL:
+ crl_issuer = _decode_general_names(backend, cdp.CRLissuer)
+
+ # Certificates may have a crl_issuer/reasons and no distribution
+ # point so make sure it's not null.
+ if cdp.distpoint != backend._ffi.NULL:
+ # Type 0 is fullName, there is no #define for it in the code.
+ if cdp.distpoint.type == 0:
+ full_name = _decode_general_names(
+ 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 = backend._lib.sk_X509_NAME_ENTRY_num(rns)
+ attributes = []
+ for i in range(rnum):
+ rn = backend._lib.sk_X509_NAME_ENTRY_value(
+ rns, i
+ )
+ assert rn != backend._ffi.NULL
+ attributes.append(
+ _decode_x509_name_entry(backend, rn)
+ )
+
+ relative_name = x509.Name(attributes)
+
+ dist_points.append(
+ x509.DistributionPoint(
+ full_name, relative_name, reasons, crl_issuer
+ )
+ )
- return x509.ExtendedKeyUsage(ekus)
+ return x509.CRLDistributionPoints(dist_points)
@utils.register_interface(x509.CertificateSigningRequest)
@@ -467,7 +649,7 @@ class _CertificateSigningRequest(object):
def subject(self):
subject = self._backend._lib.X509_REQ_get_subject_name(self._x509_req)
assert subject != self._backend._ffi.NULL
- return _build_x509_name(self._backend, subject)
+ return _decode_x509_name(self._backend, subject)
@property
def signature_hash_algorithm(self):
@@ -478,3 +660,49 @@ class _CertificateSigningRequest(object):
raise UnsupportedAlgorithm(
"Signature algorithm OID:{0} not recognized".format(oid)
)
+
+ @property
+ def extensions(self):
+ extensions = []
+ seen_oids = set()
+ x509_exts = self._backend._lib.X509_REQ_get_extensions(self._x509_req)
+ extcount = self._backend._lib.sk_X509_EXTENSION_num(x509_exts)
+ for i in range(0, extcount):
+ ext = self._backend._lib.sk_X509_EXTENSION_value(x509_exts, i)
+ assert ext != self._backend._ffi.NULL
+ crit = self._backend._lib.X509_EXTENSION_get_critical(ext)
+ critical = crit == 1
+ oid = x509.ObjectIdentifier(_obj2txt(self._backend, ext.object))
+ if oid in seen_oids:
+ raise x509.DuplicateExtension(
+ "Duplicate {0} extension found".format(oid), oid
+ )
+ elif oid == x509.OID_BASIC_CONSTRAINTS:
+ value = _decode_basic_constraints(self._backend, ext)
+ elif critical:
+ raise x509.UnsupportedExtension(
+ "{0} is not currently supported".format(oid), oid
+ )
+ else:
+ # Unsupported non-critical extension, silently skipping for now
+ seen_oids.add(oid)
+ continue
+
+ seen_oids.add(oid)
+ extensions.append(x509.Extension(oid, critical, value))
+
+ return x509.Extensions(extensions)
+
+ def public_bytes(self, encoding):
+ if not isinstance(encoding, serialization.Encoding):
+ raise TypeError("encoding must be an item from the Encoding enum")
+
+ bio = self._backend._create_mem_bio()
+ if encoding is serialization.Encoding.PEM:
+ res = self._backend._lib.PEM_write_bio_X509_REQ(
+ bio, self._x509_req
+ )
+ elif encoding is serialization.Encoding.DER:
+ res = self._backend._lib.i2d_X509_REQ_bio(bio, self._x509_req)
+ assert res == 1
+ return self._backend._read_mem_bio(bio)
diff --git a/src/cryptography/hazmat/bindings/openssl/asn1.py b/src/cryptography/hazmat/bindings/openssl/asn1.py
index 475bd052..c18708c5 100644
--- a/src/cryptography/hazmat/bindings/openssl/asn1.py
+++ b/src/cryptography/hazmat/bindings/openssl/asn1.py
@@ -98,6 +98,7 @@ ASN1_TIME *ASN1_TIME_new(void);
void ASN1_TIME_free(ASN1_TIME *);
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *,
ASN1_GENERALIZEDTIME **);
+ASN1_TIME *ASN1_TIME_set(ASN1_TIME *, time_t);
/* ASN1 UTCTIME */
ASN1_UTCTIME *ASN1_UTCTIME_new(void);
@@ -113,6 +114,7 @@ void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME *);
ASN1_ENUMERATED *ASN1_ENUMERATED_new(void);
void ASN1_ENUMERATED_free(ASN1_ENUMERATED *);
int ASN1_ENUMERATED_set(ASN1_ENUMERATED *, long);
+long ASN1_ENUMERATED_get(ASN1_ENUMERATED *);
ASN1_VALUE *ASN1_item_d2i(ASN1_VALUE **, const unsigned char **, long,
const ASN1_ITEM *);
diff --git a/src/cryptography/hazmat/bindings/openssl/ec.py b/src/cryptography/hazmat/bindings/openssl/ec.py
index 84a596eb..c5052d36 100644
--- a/src/cryptography/hazmat/bindings/openssl/ec.py
+++ b/src/cryptography/hazmat/bindings/openssl/ec.py
@@ -17,6 +17,7 @@ static const int Cryptography_HAS_EC;
static const int Cryptography_HAS_EC_1_0_1;
static const int Cryptography_HAS_EC_NISTP_64_GCC_128;
static const int Cryptography_HAS_EC2M;
+static const int Cryptography_HAS_EC_1_0_2;
static const int OPENSSL_EC_NAMED_CURVE;
@@ -188,6 +189,8 @@ const EC_METHOD *EC_GFp_nistp521_method();
const EC_METHOD *EC_GF2m_simple_method();
int EC_METHOD_get_field_type(const EC_METHOD *);
+
+const char *EC_curve_nid2nist(int);
"""
CUSTOMIZATIONS = """
@@ -385,6 +388,14 @@ EC_GROUP *(*EC_GROUP_new_curve_GF2m)(
#else
static const long Cryptography_HAS_EC2M = 1;
#endif
+
+#if defined(OPENSSL_NO_EC) || OPENSSL_VERSION_NUMBER < 0x1000200f || \
+ defined(LIBRESSL_VERSION_NUMBER)
+static const long Cryptography_HAS_EC_1_0_2 = 0;
+const char *(*EC_curve_nid2nist)(int) = NULL;
+#else
+static const long Cryptography_HAS_EC_1_0_2 = 1;
+#endif
"""
CONDITIONAL_NAMES = {
@@ -478,4 +489,8 @@ CONDITIONAL_NAMES = {
"EC_GROUP_get_curve_GF2m",
"EC_GROUP_new_curve_GF2m",
],
+
+ "Cryptography_HAS_EC_1_0_2": [
+ "EC_curve_nid2nist",
+ ],
}
diff --git a/src/cryptography/hazmat/bindings/openssl/evp.py b/src/cryptography/hazmat/bindings/openssl/evp.py
index 780ce900..93aa83de 100644
--- a/src/cryptography/hazmat/bindings/openssl/evp.py
+++ b/src/cryptography/hazmat/bindings/openssl/evp.py
@@ -28,6 +28,7 @@ typedef struct evp_pkey_st {
typedef ... EVP_PKEY_CTX;
static const int EVP_PKEY_RSA;
static const int EVP_PKEY_DSA;
+static const int EVP_PKEY_DH;
static const int EVP_PKEY_EC;
static const int EVP_MAX_MD_SIZE;
static const int EVP_CTRL_GCM_SET_IVLEN;
@@ -154,6 +155,7 @@ int EVP_PKEY_verify(EVP_PKEY_CTX *, const unsigned char *, size_t,
const unsigned char *, size_t);
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *);
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *);
+int EVP_PKEY_id(const EVP_PKEY *);
/* The following were macros in 0.9.8e. Once we drop support for RHEL/CentOS 5
we should move these back to FUNCTIONS. */
@@ -221,6 +223,7 @@ int (*Cryptography_EVP_PKEY_encrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *,
const unsigned char *, size_t) = NULL;
int (*Cryptography_EVP_PKEY_decrypt)(EVP_PKEY_CTX *, unsigned char *, size_t *,
const unsigned char *, size_t) = NULL;
+int (*EVP_PKEY_id)(const EVP_PKEY *) = NULL;
#endif
#ifdef OPENSSL_NO_EC
int (*EVP_PKEY_assign_EC_KEY)(EVP_PKEY *, EC_KEY *) = NULL;
@@ -252,6 +255,7 @@ CONDITIONAL_NAMES = {
"Cryptography_EVP_PKEY_decrypt",
"EVP_PKEY_decrypt_init",
"EVP_PKEY_CTX_set_signature_md",
+ "EVP_PKEY_id",
],
"Cryptography_HAS_EC": [
"EVP_PKEY_assign_EC_KEY",
diff --git a/src/cryptography/hazmat/bindings/openssl/ssl.py b/src/cryptography/hazmat/bindings/openssl/ssl.py
index 22ff9bf0..3754773b 100644
--- a/src/cryptography/hazmat/bindings/openssl/ssl.py
+++ b/src/cryptography/hazmat/bindings/openssl/ssl.py
@@ -23,6 +23,7 @@ static const long Cryptography_HAS_COMPRESSION;
static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB;
static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP;
static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE;
+static const long Cryptography_HAS_GET_SERVER_TMP_KEY;
/* Internally invented symbol to tell us if SNI is supported */
static const long Cryptography_HAS_TLSEXT_HOSTNAME;
@@ -123,12 +124,9 @@ static const long SSL_MODE_ENABLE_PARTIAL_WRITE;
static const long SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER;
static const long SSL_MODE_AUTO_RETRY;
static const long SSL3_RANDOM_SIZE;
+
typedef ... SSL_METHOD;
-typedef struct ssl_st {
- int version;
- int type;
- ...;
-} SSL_CTX;
+typedef ... SSL_CTX;
typedef struct {
int master_key_length;
@@ -143,9 +141,10 @@ typedef struct {
} SSL3_STATE;
typedef struct {
+ int version;
+ int type;
SSL3_STATE *s3;
SSL_SESSION *session;
- int type;
...;
} SSL;
@@ -165,6 +164,7 @@ const char *SSL_state_string_long(const SSL *);
SSL_SESSION *SSL_get1_session(SSL *);
int SSL_set_session(SSL *, SSL_SESSION *);
int SSL_get_verify_mode(const SSL *);
+void SSL_set_verify(SSL *, int, int (*)(int, X509_STORE_CTX *));
void SSL_set_verify_depth(SSL *, int);
int SSL_get_verify_depth(const SSL *);
int (*SSL_get_verify_callback(const SSL *))(int, X509_STORE_CTX *);
@@ -329,6 +329,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 *);
@@ -382,6 +383,8 @@ void SSL_CTX_set_alpn_select_cb(SSL_CTX *,
void *),
void *);
void SSL_get0_alpn_selected(const SSL *, const unsigned char **, unsigned *);
+
+long SSL_get_server_tmp_key(SSL *, EVP_PKEY **);
"""
CUSTOMIZATIONS = """
@@ -430,6 +433,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
@@ -583,6 +587,7 @@ static const long Cryptography_HAS_ALPN = 0;
#else
static const long Cryptography_HAS_ALPN = 1;
#endif
+
#if defined(OPENSSL_NO_COMP) || defined(LIBRESSL_VERSION_NUMBER)
static const long Cryptography_HAS_COMPRESSION = 0;
typedef void COMP_METHOD;
@@ -590,6 +595,13 @@ typedef void COMP_METHOD;
static const long Cryptography_HAS_COMPRESSION = 1;
#endif
+#if defined(SSL_CTRL_GET_SERVER_TMP_KEY)
+static const long Cryptography_HAS_GET_SERVER_TMP_KEY = 1;
+#else
+static const long Cryptography_HAS_GET_SERVER_TMP_KEY = 0;
+long (*SSL_get_server_tmp_key)(SSL *, EVP_PKEY **) = NULL;
+#endif
+
"""
CONDITIONAL_NAMES = {
@@ -627,6 +639,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": [
@@ -691,5 +704,9 @@ CONDITIONAL_NAMES = {
"SSL_get_current_compression",
"SSL_get_current_expansion",
"SSL_COMP_get_name",
- ]
+ ],
+
+ "Cryptography_HAS_GET_SERVER_TMP_KEY": [
+ "SSL_get_server_tmp_key",
+ ],
}
diff --git a/src/cryptography/hazmat/bindings/openssl/x509.py b/src/cryptography/hazmat/bindings/openssl/x509.py
index fa6a16b3..e0f42fbb 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509.py
@@ -64,6 +64,7 @@ typedef struct {
typedef struct {
X509_CRL_INFO *crl;
+ X509_ALGOR *sig_alg;
...;
} X509_CRL;
@@ -145,9 +146,13 @@ X509_EXTENSION *X509_delete_ext(X509 *, int);
X509_EXTENSION *X509_EXTENSION_dup(X509_EXTENSION *);
X509_EXTENSION *X509_get_ext(X509 *, int);
int X509_get_ext_by_NID(X509 *, int, int);
+
int X509_EXTENSION_get_critical(X509_EXTENSION *);
ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *);
void X509_EXTENSION_free(X509_EXTENSION *);
+X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **,
+ ASN1_OBJECT *, int,
+ ASN1_OCTET_STRING *);
int i2d_X509(X509 *, unsigned char **);
@@ -155,11 +160,13 @@ int X509_REQ_set_version(X509_REQ *, long);
X509_REQ *X509_REQ_new(void);
void X509_REQ_free(X509_REQ *);
int X509_REQ_set_pubkey(X509_REQ *, EVP_PKEY *);
+int X509_REQ_set_subject_name(X509_REQ *, X509_NAME *);
int X509_REQ_sign(X509_REQ *, EVP_PKEY *, const EVP_MD *);
int X509_REQ_verify(X509_REQ *, EVP_PKEY *);
int X509_REQ_digest(const X509_REQ *, const EVP_MD *,
unsigned char *, unsigned int *);
EVP_PKEY *X509_REQ_get_pubkey(X509_REQ *);
+int X509_REQ_print(BIO *, X509_REQ *);
int X509_REQ_print_ex(BIO *, X509_REQ *, unsigned long, unsigned long);
int X509V3_EXT_print(BIO *, X509_EXTENSION *, unsigned long, int);
@@ -183,9 +190,11 @@ int i2d_X509_CRL_bio(BIO *, X509_CRL *);
int X509_CRL_print(BIO *, X509_CRL *);
int X509_CRL_set_issuer_name(X509_CRL *, X509_NAME *);
int X509_CRL_sign(X509_CRL *, EVP_PKEY *, const EVP_MD *);
+int X509_CRL_verify(X509_CRL *, EVP_PKEY *);
int X509_CRL_get_ext_count(X509_CRL *);
X509_EXTENSION *X509_CRL_get_ext(X509_CRL *, int);
int X509_CRL_add_ext(X509_CRL *, X509_EXTENSION *, int);
+int X509_CRL_cmp(const X509_CRL *, const X509_CRL *);
int NETSCAPE_SPKI_verify(NETSCAPE_SPKI *, EVP_PKEY *);
int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *, EVP_PKEY *, const EVP_MD *);
@@ -285,6 +294,7 @@ int X509_CRL_get_version(X509_CRL *);
ASN1_TIME *X509_CRL_get_lastUpdate(X509_CRL *);
ASN1_TIME *X509_CRL_get_nextUpdate(X509_CRL *);
X509_NAME *X509_CRL_get_issuer(X509_CRL *);
+Cryptography_STACK_OF_X509_REVOKED *X509_CRL_get_REVOKED(X509_CRL *);
/* These aren't macros these arguments are all const X on openssl > 1.0.x */
int X509_CRL_set_lastUpdate(X509_CRL *, ASN1_TIME *);
@@ -301,9 +311,14 @@ int i2d_EC_PUBKEY(EC_KEY *, unsigned char **);
EC_KEY *d2i_EC_PUBKEY(EC_KEY **, const unsigned char **, long);
EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **);
int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *);
+EC_KEY *d2i_ECPrivateKey(EC_KEY **, const unsigned char **, long);
EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **);
+int i2d_ECPrivateKey(EC_KEY *, unsigned char **);
int i2d_ECPrivateKey_bio(BIO *, EC_KEY *);
+EC_KEY *o2i_ECPublicKey(EC_KEY **, const unsigned char **, long);
+int i2o_ECPublicKey(EC_KEY *, unsigned char **);
+
// declared in safestack
int sk_ASN1_OBJECT_num(Cryptography_STACK_OF_ASN1_OBJECT *);
ASN1_OBJECT *sk_ASN1_OBJECT_value(Cryptography_STACK_OF_ASN1_OBJECT *, int);
@@ -320,8 +335,13 @@ int (*i2d_EC_PUBKEY)(EC_KEY *, unsigned char **) = NULL;
EC_KEY *(*d2i_EC_PUBKEY)(EC_KEY **, const unsigned char **, long) = NULL;
EC_KEY *(*d2i_EC_PUBKEY_bio)(BIO *, EC_KEY **) = NULL;
int (*i2d_EC_PUBKEY_bio)(BIO *, EC_KEY *) = NULL;
+EC_KEY *(*d2i_ECPrivateKey)(EC_KEY **, const unsigned char **, long) = NULL;
EC_KEY *(*d2i_ECPrivateKey_bio)(BIO *, EC_KEY **) = NULL;
+int (*i2d_ECPrivateKey)(EC_KEY *, unsigned char **) = NULL;
int (*i2d_ECPrivateKey_bio)(BIO *, EC_KEY *) = NULL;
+
+EC_KEY *(*o2i_ECPublicKey)(EC_KEY **, const unsigned char **, long) = NULL;
+int (*i2o_ECPublicKey)(EC_KEY *, unsigned char **) = NULL;
#endif
"""
@@ -331,7 +351,11 @@ CONDITIONAL_NAMES = {
"d2i_EC_PUBKEY",
"d2i_EC_PUBKEY_bio",
"i2d_EC_PUBKEY_bio",
+ "d2i_ECPrivateKey",
"d2i_ECPrivateKey_bio",
+ "i2d_ECPrivateKey",
"i2d_ECPrivateKey_bio",
+ "i2o_ECPublicKey",
+ "o2i_ECPublicKey",
]
}
diff --git a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py
index 1f75b86f..02631409 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509_vfy.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509_vfy.py
@@ -29,9 +29,23 @@ static const long Cryptography_HAS_X509_V_FLAG_CHECK_SS_SIGNATURE;
typedef ... Cryptography_STACK_OF_ASN1_OBJECT;
typedef ... X509_STORE;
-typedef ... X509_STORE_CTX;
typedef ... X509_VERIFY_PARAM;
+typedef struct x509_store_ctx_st X509_STORE_CTX;
+struct x509_store_ctx_st {
+ X509_STORE *ctx;
+ int current_method;
+ X509 *cert;
+ Cryptography_STACK_OF_X509 *untrusted;
+ Cryptography_STACK_OF_X509_CRL *crls;
+ X509_VERIFY_PARAM *param;
+ void *other_ctx;
+ int (*verify)(X509_STORE_CTX *);
+ int (*verify_cb)(int, X509_STORE_CTX *);
+ int (*get_issuer)(X509 **, X509_STORE_CTX *, X509 *);
+ ...;
+};
+
/* While these are defined in the source as ints, they're tagged here
as longs, just in case they ever grow to large, such as what we saw
with OP_ALL. */
diff --git a/src/cryptography/hazmat/bindings/openssl/x509name.py b/src/cryptography/hazmat/bindings/openssl/x509name.py
index bda92eb7..be5b3a75 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509name.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509name.py
@@ -11,12 +11,14 @@ INCLUDES = """
* See the comment above Cryptography_STACK_OF_X509 in x509.py
*/
typedef STACK_OF(X509_NAME) Cryptography_STACK_OF_X509_NAME;
+typedef STACK_OF(X509_NAME_ENTRY) Cryptography_STACK_OF_X509_NAME_ENTRY;
"""
TYPES = """
typedef ... X509_NAME;
typedef ... X509_NAME_ENTRY;
typedef ... Cryptography_STACK_OF_X509_NAME;
+typedef ... Cryptography_STACK_OF_X509_NAME_ENTRY;
"""
FUNCTIONS = """
@@ -32,6 +34,8 @@ unsigned long X509_NAME_hash(X509_NAME *);
int i2d_X509_NAME(X509_NAME *, unsigned char **);
int X509_NAME_add_entry_by_txt(X509_NAME *, const char *, int,
const unsigned char *, int, int, int);
+int X509_NAME_add_entry_by_OBJ(X509_NAME *, ASN1_OBJECT *, int,
+ unsigned char *, int, int, int);
int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *,
int, int, int);
X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *, int);
@@ -48,6 +52,9 @@ int sk_X509_NAME_num(Cryptography_STACK_OF_X509_NAME *);
int sk_X509_NAME_push(Cryptography_STACK_OF_X509_NAME *, X509_NAME *);
X509_NAME *sk_X509_NAME_value(Cryptography_STACK_OF_X509_NAME *, int);
void sk_X509_NAME_free(Cryptography_STACK_OF_X509_NAME *);
+int sk_X509_NAME_ENTRY_num(Cryptography_STACK_OF_X509_NAME_ENTRY *);
+X509_NAME_ENTRY *sk_X509_NAME_ENTRY_value(
+ Cryptography_STACK_OF_X509_NAME_ENTRY *, int);
"""
CUSTOMIZATIONS = """
diff --git a/src/cryptography/hazmat/bindings/openssl/x509v3.py b/src/cryptography/hazmat/bindings/openssl/x509v3.py
index c2b6860f..e9bc461a 100644
--- a/src/cryptography/hazmat/bindings/openssl/x509v3.py
+++ b/src/cryptography/hazmat/bindings/openssl/x509v3.py
@@ -20,10 +20,17 @@ typedef LHASH_OF(CONF_VALUE) Cryptography_LHASH_OF_CONF_VALUE;
typedef LHASH Cryptography_LHASH_OF_CONF_VALUE;
#endif
typedef STACK_OF(ACCESS_DESCRIPTION) Cryptography_STACK_OF_ACCESS_DESCRIPTION;
+typedef STACK_OF(DIST_POINT) Cryptography_STACK_OF_DIST_POINT;
+typedef STACK_OF(POLICYQUALINFO) Cryptography_STACK_OF_POLICYQUALINFO;
+typedef STACK_OF(POLICYINFO) Cryptography_STACK_OF_POLICYINFO;
+typedef STACK_OF(ASN1_INTEGER) Cryptography_STACK_OF_ASN1_INTEGER;
"""
TYPES = """
typedef ... Cryptography_STACK_OF_ACCESS_DESCRIPTION;
+typedef ... Cryptography_STACK_OF_POLICYQUALINFO;
+typedef ... Cryptography_STACK_OF_POLICYINFO;
+typedef ... Cryptography_STACK_OF_ASN1_INTEGER;
typedef struct {
X509 *issuer_cert;
@@ -101,6 +108,49 @@ typedef struct {
} ACCESS_DESCRIPTION;
typedef ... Cryptography_LHASH_OF_CONF_VALUE;
+
+
+typedef ... Cryptography_STACK_OF_DIST_POINT;
+
+typedef struct {
+ int type;
+ union {
+ GENERAL_NAMES *fullname;
+ Cryptography_STACK_OF_X509_NAME_ENTRY *relativename;
+ } name;
+ ...;
+} DIST_POINT_NAME;
+
+typedef struct {
+ DIST_POINT_NAME *distpoint;
+ ASN1_BIT_STRING *reasons;
+ GENERAL_NAMES *CRLissuer;
+ ...;
+} DIST_POINT;
+
+typedef struct {
+ ASN1_STRING *organization;
+ Cryptography_STACK_OF_ASN1_INTEGER *noticenos;
+} NOTICEREF;
+
+typedef struct {
+ NOTICEREF *noticeref;
+ ASN1_STRING *exptext;
+} USERNOTICE;
+
+typedef struct {
+ ASN1_OBJECT *pqualid;
+ union {
+ ASN1_IA5STRING *cpsuri;
+ USERNOTICE *usernotice;
+ ASN1_TYPE *other;
+ } d;
+} POLICYQUALINFO;
+
+typedef struct {
+ ASN1_OBJECT *policyid;
+ Cryptography_STACK_OF_POLICYQUALINFO *qualifiers;
+} POLICYINFO;
"""
@@ -116,20 +166,26 @@ void *X509V3_EXT_d2i(X509_EXTENSION *);
MACROS = """
/* This is a macro defined by a call to DECLARE_ASN1_FUNCTIONS in the
x509v3.h header. */
+int i2d_BASIC_CONSTRAINTS(BASIC_CONSTRAINTS *, unsigned char **);
+BASIC_CONSTRAINTS *BASIC_CONSTRAINTS_new(void);
void BASIC_CONSTRAINTS_free(BASIC_CONSTRAINTS *);
/* This is a macro defined by a call to DECLARE_ASN1_FUNCTIONS in the
x509v3.h header. */
void AUTHORITY_KEYID_free(AUTHORITY_KEYID *);
+
void *X509V3_set_ctx_nodb(X509V3_CTX *);
int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *);
int sk_GENERAL_NAME_push(struct stack_st_GENERAL_NAME *, GENERAL_NAME *);
GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int);
+Cryptography_STACK_OF_ACCESS_DESCRIPTION *sk_ACCESS_DESCRIPTION_new_null(void);
int sk_ACCESS_DESCRIPTION_num(Cryptography_STACK_OF_ACCESS_DESCRIPTION *);
ACCESS_DESCRIPTION *sk_ACCESS_DESCRIPTION_value(
Cryptography_STACK_OF_ACCESS_DESCRIPTION *, int
);
void sk_ACCESS_DESCRIPTION_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *);
+int sk_ACCESS_DESCRIPTION_push(Cryptography_STACK_OF_ACCESS_DESCRIPTION *,
+ ACCESS_DESCRIPTION *);
X509_EXTENSION *X509V3_EXT_conf_nid(Cryptography_LHASH_OF_CONF_VALUE *,
X509V3_CTX *, int, char *);
@@ -138,6 +194,24 @@ X509_EXTENSION *X509V3_EXT_conf_nid(Cryptography_LHASH_OF_CONF_VALUE *,
const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *);
const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int);
+void sk_DIST_POINT_free(Cryptography_STACK_OF_DIST_POINT *);
+int sk_DIST_POINT_num(Cryptography_STACK_OF_DIST_POINT *);
+DIST_POINT *sk_DIST_POINT_value(Cryptography_STACK_OF_DIST_POINT *, int);
+
+void sk_POLICYINFO_free(Cryptography_STACK_OF_POLICYINFO *);
+int sk_POLICYINFO_num(Cryptography_STACK_OF_POLICYINFO *);
+POLICYINFO *sk_POLICYINFO_value(Cryptography_STACK_OF_POLICYINFO *, int);
+
+void sk_POLICYQUALINFO_free(Cryptography_STACK_OF_POLICYQUALINFO *);
+int sk_POLICYQUALINFO_num(Cryptography_STACK_OF_POLICYQUALINFO *);
+POLICYQUALINFO *sk_POLICYQUALINFO_value(Cryptography_STACK_OF_POLICYQUALINFO *,
+ int);
+
+void sk_ASN1_INTEGER_free(Cryptography_STACK_OF_ASN1_INTEGER *);
+int sk_ASN1_INTEGER_num(Cryptography_STACK_OF_ASN1_INTEGER *);
+ASN1_INTEGER *sk_ASN1_INTEGER_value(Cryptography_STACK_OF_ASN1_INTEGER *, int);
+
+X509_EXTENSION *X509V3_EXT_i2d(int, int, void *);
"""
CUSTOMIZATIONS = """
diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
index 4d332f2a..733a967c 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py
@@ -71,17 +71,6 @@ class DSAPrivateKeyWithSerialization(DSAPrivateKey):
"""
-DSAPrivateKeyWithNumbers = utils.deprecated(
- DSAPrivateKeyWithSerialization,
- __name__,
- (
- "The DSAPrivateKeyWithNumbers interface has been renamed to "
- "DSAPrivateKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-
@six.add_metaclass(abc.ABCMeta)
class DSAPublicKey(object):
@abc.abstractproperty
@@ -118,17 +107,6 @@ class DSAPublicKeyWithSerialization(DSAPublicKey):
"""
-DSAPublicKeyWithNumbers = utils.deprecated(
- DSAPublicKeyWithSerialization,
- __name__,
- (
- "The DSAPublicKeyWithNumbers interface has been renamed to "
- "DSAPublicKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-
def generate_parameters(key_size, backend):
return backend.generate_dsa_parameters(key_size)
diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py
index bf1705db..631fcbf7 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/ec.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py
@@ -71,17 +71,6 @@ class EllipticCurvePrivateKeyWithSerialization(EllipticCurvePrivateKey):
"""
-EllipticCurvePrivateKeyWithNumbers = utils.deprecated(
- EllipticCurvePrivateKeyWithSerialization,
- __name__,
- (
- "The EllipticCurvePrivateKeyWithNumbers interface has been renamed to "
- "EllipticCurvePrivateKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-
@six.add_metaclass(abc.ABCMeta)
class EllipticCurvePublicKey(object):
@abc.abstractmethod
@@ -112,17 +101,6 @@ class EllipticCurvePublicKeyWithSerialization(EllipticCurvePublicKey):
"""
-EllipticCurvePublicKeyWithNumbers = utils.deprecated(
- EllipticCurvePublicKeyWithSerialization,
- __name__,
- (
- "The EllipticCurvePublicKeyWithNumbers interface has been renamed to "
- "EllipticCurvePublicKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-
@utils.register_interface(EllipticCurve)
class SECT571R1(object):
name = "sect571r1"
@@ -202,6 +180,12 @@ class SECP256R1(object):
@utils.register_interface(EllipticCurve)
+class SECP256K1(object):
+ name = "secp256k1"
+ key_size = 256
+
+
+@utils.register_interface(EllipticCurve)
class SECP224R1(object):
name = "secp224r1"
key_size = 224
@@ -222,6 +206,7 @@ _CURVE_TYPES = {
"secp256r1": SECP256R1,
"secp384r1": SECP384R1,
"secp521r1": SECP521R1,
+ "secp256k1": SECP256K1,
"sect163k1": SECT163K1,
"sect233k1": SECT233K1,
diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
index ae00184f..772473fd 100644
--- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py
+++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py
@@ -56,17 +56,6 @@ class RSAPrivateKeyWithSerialization(RSAPrivateKey):
"""
-RSAPrivateKeyWithNumbers = utils.deprecated(
- RSAPrivateKeyWithSerialization,
- __name__,
- (
- "The RSAPrivateKeyWithNumbers interface has been renamed to "
- "RSAPrivateKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-
@six.add_metaclass(abc.ABCMeta)
class RSAPublicKey(object):
@abc.abstractmethod
@@ -103,17 +92,6 @@ class RSAPublicKeyWithSerialization(RSAPublicKey):
"""
-RSAPublicKeyWithNumbers = utils.deprecated(
- RSAPublicKeyWithSerialization,
- __name__,
- (
- "The RSAPublicKeyWithNumbers interface has been renamed to "
- "RSAPublicKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-
def generate_private_key(public_exponent, key_size, backend):
if not isinstance(backend, RSABackend):
raise UnsupportedAlgorithm(
diff --git a/src/cryptography/hazmat/primitives/interfaces/__init__.py b/src/cryptography/hazmat/primitives/interfaces/__init__.py
index c980e5a5..4c95190b 100644
--- a/src/cryptography/hazmat/primitives/interfaces/__init__.py
+++ b/src/cryptography/hazmat/primitives/interfaces/__init__.py
@@ -8,357 +8,6 @@ import abc
import six
-from cryptography import utils
-from cryptography.hazmat.primitives import ciphers, hashes
-from cryptography.hazmat.primitives.asymmetric import (
- AsymmetricSignatureContext, AsymmetricVerificationContext, dsa, ec,
- padding, rsa
-)
-from cryptography.hazmat.primitives.ciphers import modes
-from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
-from cryptography.hazmat.primitives.padding import PaddingContext
-
-
-BlockCipherAlgorithm = utils.deprecated(
- ciphers.BlockCipherAlgorithm,
- __name__,
- (
- "The BlockCipherAlgorithm interface has moved to the "
- "cryptography.hazmat.primitives.ciphers module"
- ),
- utils.DeprecatedIn08
-)
-
-
-CipherAlgorithm = utils.deprecated(
- ciphers.CipherAlgorithm,
- __name__,
- (
- "The CipherAlgorithm interface has moved to the "
- "cryptography.hazmat.primitives.ciphers module"
- ),
- utils.DeprecatedIn08
-)
-
-
-Mode = utils.deprecated(
- modes.Mode,
- __name__,
- (
- "The Mode interface has moved to the "
- "cryptography.hazmat.primitives.ciphers.modes module"
- ),
- utils.DeprecatedIn08
-)
-
-
-ModeWithAuthenticationTag = utils.deprecated(
- modes.ModeWithAuthenticationTag,
- __name__,
- (
- "The ModeWithAuthenticationTag interface has moved to the "
- "cryptography.hazmat.primitives.ciphers.modes module"
- ),
- utils.DeprecatedIn08
-)
-
-
-ModeWithInitializationVector = utils.deprecated(
- modes.ModeWithInitializationVector,
- __name__,
- (
- "The ModeWithInitializationVector interface has moved to the "
- "cryptography.hazmat.primitives.ciphers.modes module"
- ),
- utils.DeprecatedIn08
-)
-
-
-ModeWithNonce = utils.deprecated(
- modes.ModeWithNonce,
- __name__,
- (
- "The ModeWithNonce interface has moved to the "
- "cryptography.hazmat.primitives.ciphers.modes module"
- ),
- utils.DeprecatedIn08
-)
-
-
-CipherContext = utils.deprecated(
- ciphers.CipherContext,
- __name__,
- (
- "The CipherContext interface has moved to the "
- "cryptography.hazmat.primitives.ciphers module"
- ),
- utils.DeprecatedIn08
-)
-
-
-AEADCipherContext = utils.deprecated(
- ciphers.AEADCipherContext,
- __name__,
- (
- "The AEADCipherContext interface has moved to the "
- "cryptography.hazmat.primitives.ciphers module"
- ),
- utils.DeprecatedIn08
-)
-
-
-AEADEncryptionContext = utils.deprecated(
- ciphers.AEADEncryptionContext,
- __name__,
- (
- "The AEADEncryptionContext interface has moved to the "
- "cryptography.hazmat.primitives.ciphers module"
- ),
- utils.DeprecatedIn08
-)
-
-
-EllipticCurve = utils.deprecated(
- ec.EllipticCurve,
- __name__,
- (
- "The EllipticCurve interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.ec module"
- ),
- utils.DeprecatedIn08
-)
-
-
-EllipticCurvePrivateKey = utils.deprecated(
- ec.EllipticCurvePrivateKey,
- __name__,
- (
- "The EllipticCurvePrivateKey interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.ec module"
- ),
- utils.DeprecatedIn08
-)
-
-
-EllipticCurvePrivateKeyWithNumbers = utils.deprecated(
- ec.EllipticCurvePrivateKeyWithSerialization,
- __name__,
- (
- "The EllipticCurvePrivateKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.ec module"
- ),
- utils.DeprecatedIn08
-)
-
-
-EllipticCurvePublicKey = utils.deprecated(
- ec.EllipticCurvePublicKey,
- __name__,
- (
- "The EllipticCurvePublicKey interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.ec module"
- ),
- utils.DeprecatedIn08
-)
-
-
-EllipticCurvePublicKeyWithNumbers = utils.deprecated(
- ec.EllipticCurvePublicKeyWithSerialization,
- __name__,
- (
- "The EllipticCurvePublicKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.ec module"
- ),
- utils.DeprecatedIn08
-)
-
-
-EllipticCurveSignatureAlgorithm = utils.deprecated(
- ec.EllipticCurveSignatureAlgorithm,
- __name__,
- (
- "The EllipticCurveSignatureAlgorithm interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.ec module"
- ),
- utils.DeprecatedIn08
-)
-
-
-DSAParameters = utils.deprecated(
- dsa.DSAParameters,
- __name__,
- (
- "The DSAParameters interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.dsa.module"
- ),
- utils.DeprecatedIn08
-)
-
-DSAParametersWithNumbers = utils.deprecated(
- dsa.DSAParametersWithNumbers,
- __name__,
- (
- "The DSAParametersWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.dsa.module"
- ),
- utils.DeprecatedIn08
-)
-
-DSAPrivateKey = utils.deprecated(
- dsa.DSAPrivateKey,
- __name__,
- (
- "The DSAPrivateKey interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.dsa.module"
- ),
- utils.DeprecatedIn08
-)
-
-DSAPrivateKeyWithNumbers = utils.deprecated(
- dsa.DSAPrivateKeyWithSerialization,
- __name__,
- (
- "The DSAPrivateKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.dsa.module"
- ),
- utils.DeprecatedIn08
-)
-
-DSAPublicKey = utils.deprecated(
- dsa.DSAPublicKey,
- __name__,
- (
- "The DSAPublicKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.dsa.module"
- ),
- utils.DeprecatedIn08
-)
-
-DSAPublicKeyWithNumbers = utils.deprecated(
- dsa.DSAPublicKeyWithSerialization,
- __name__,
- (
- "The DSAPublicKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.dsa.module"
- ),
- utils.DeprecatedIn08
-)
-
-
-PaddingContext = utils.deprecated(
- PaddingContext,
- __name__,
- (
- "The PaddingContext interface has moved to the "
- "cryptography.hazmat.primitives.padding module"
- ),
- utils.DeprecatedIn08
-)
-
-
-HashContext = utils.deprecated(
- hashes.HashContext,
- __name__,
- (
- "The HashContext interface has moved to the "
- "cryptography.hazmat.primitives.hashes module"
- ),
- utils.DeprecatedIn08
-)
-
-
-HashAlgorithm = utils.deprecated(
- hashes.HashAlgorithm,
- __name__,
- (
- "The HashAlgorithm interface has moved to the "
- "cryptography.hazmat.primitives.hashes module"
- ),
- utils.DeprecatedIn08
-)
-
-
-RSAPrivateKey = utils.deprecated(
- rsa.RSAPrivateKey,
- __name__,
- (
- "The RSAPrivateKey interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.rsa module"
- ),
- utils.DeprecatedIn08
-)
-
-RSAPrivateKeyWithNumbers = utils.deprecated(
- rsa.RSAPrivateKeyWithSerialization,
- __name__,
- (
- "The RSAPrivateKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.rsa module and has been "
- "renamed RSAPrivateKeyWithSerialization"
- ),
- utils.DeprecatedIn08
-)
-
-RSAPublicKey = utils.deprecated(
- rsa.RSAPublicKey,
- __name__,
- (
- "The RSAPublicKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.rsa module"
- ),
- utils.DeprecatedIn08
-)
-
-RSAPublicKeyWithNumbers = utils.deprecated(
- rsa.RSAPublicKeyWithSerialization,
- __name__,
- (
- "The RSAPublicKeyWithNumbers interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.rsa module"
- ),
- utils.DeprecatedIn08
-)
-
-AsymmetricPadding = utils.deprecated(
- padding.AsymmetricPadding,
- __name__,
- (
- "The AsymmetricPadding interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric.padding module"
- ),
- utils.DeprecatedIn08
-)
-
-AsymmetricSignatureContext = utils.deprecated(
- AsymmetricSignatureContext,
- __name__,
- (
- "The AsymmetricPadding interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric module"
- ),
- utils.DeprecatedIn08
-)
-
-AsymmetricVerificationContext = utils.deprecated(
- AsymmetricVerificationContext,
- __name__,
- (
- "The AsymmetricVerificationContext interface has moved to the "
- "cryptography.hazmat.primitives.asymmetric module"
- ),
- utils.DeprecatedIn08
-)
-
-KeyDerivationFunction = utils.deprecated(
- KeyDerivationFunction,
- __name__,
- (
- "The KeyDerivationFunction interface has moved to the "
- "cryptography.hazmat.primitives.kdf module"
- ),
- utils.DeprecatedIn08
-)
-
@six.add_metaclass(abc.ABCMeta)
class MACContext(object):
diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py
index 445554ec..0bf8c0ea 100644
--- a/src/cryptography/utils.py
+++ b/src/cryptography/utils.py
@@ -10,8 +10,7 @@ import sys
import warnings
-DeprecatedIn08 = DeprecationWarning
-DeprecatedIn09 = PendingDeprecationWarning
+DeprecatedIn09 = DeprecationWarning
def read_only_property(name):
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 0d87cd51..6592684b 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -55,6 +55,9 @@ _OID_NAMES = {
"2.5.29.17": "subjectAltName",
"2.5.29.18": "issuerAltName",
"2.5.29.19": "basicConstraints",
+ "2.5.29.21": "cRLReason",
+ "2.5.29.24": "invalidityDate",
+ "2.5.29.29": "certificateIssuer",
"2.5.29.30": "nameConstraints",
"2.5.29.31": "cRLDistributionPoints",
"2.5.29.32": "certificatePolicies",
@@ -69,6 +72,8 @@ _OID_NAMES = {
"1.3.6.1.5.5.7.48.1.5": "OCSPNoCheck",
"1.3.6.1.5.5.7.48.1": "OCSP",
"1.3.6.1.5.5.7.48.2": "caIssuers",
+ "1.3.6.1.5.5.7.2.1": "id-qt-cps",
+ "1.3.6.1.5.5.7.2.2": "id-qt-unotice",
}
@@ -222,6 +227,9 @@ OID_KEY_USAGE = ObjectIdentifier("2.5.29.15")
OID_SUBJECT_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.17")
OID_ISSUER_ALTERNATIVE_NAME = ObjectIdentifier("2.5.29.18")
OID_BASIC_CONSTRAINTS = ObjectIdentifier("2.5.29.19")
+OID_CRL_REASON = ObjectIdentifier("2.5.29.21")
+OID_INVALIDITY_DATE = ObjectIdentifier("2.5.29.24")
+OID_CERTIFICATE_ISSUER = ObjectIdentifier("2.5.29.29")
OID_NAME_CONSTRAINTS = ObjectIdentifier("2.5.29.30")
OID_CRL_DISTRIBUTION_POINTS = ObjectIdentifier("2.5.29.31")
OID_CERTIFICATE_POLICIES = ObjectIdentifier("2.5.29.32")
@@ -276,6 +284,19 @@ class Extension(object):
return ("<Extension(oid={0.oid}, critical={0.critical}, "
"value={0.value})>").format(self)
+ def __eq__(self, other):
+ if not isinstance(other, Extension):
+ return NotImplemented
+
+ return (
+ self.oid == other.oid and
+ self.critical == other.critical and
+ self.value == other.value
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
class ExtendedKeyUsage(object):
def __init__(self, usages):
@@ -305,6 +326,10 @@ class ExtendedKeyUsage(object):
return not self == other
+class OCSPNoCheck(object):
+ pass
+
+
class BasicConstraints(object):
def __init__(self, ca, path_length):
if not isinstance(ca, bool):
@@ -331,6 +356,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,
@@ -395,6 +429,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):
@@ -460,6 +513,143 @@ class AccessDescription(object):
access_location = utils.read_only_property("_access_location")
+class CertificatePolicies(object):
+ def __init__(self, policies):
+ if not all(isinstance(x, PolicyInformation) for x in policies):
+ raise TypeError(
+ "Every item in the policies list must be a "
+ "PolicyInformation"
+ )
+
+ self._policies = policies
+
+ def __iter__(self):
+ return iter(self._policies)
+
+ def __len__(self):
+ return len(self._policies)
+
+ def __repr__(self):
+ return "<CertificatePolicies({0})>".format(self._policies)
+
+ def __eq__(self, other):
+ if not isinstance(other, CertificatePolicies):
+ return NotImplemented
+
+ return self._policies == other._policies
+
+ def __ne__(self, other):
+ return not self == other
+
+
+class PolicyInformation(object):
+ def __init__(self, policy_identifier, policy_qualifiers):
+ if not isinstance(policy_identifier, ObjectIdentifier):
+ raise TypeError("policy_identifier must be an ObjectIdentifier")
+
+ self._policy_identifier = policy_identifier
+ if policy_qualifiers and not all(
+ isinstance(
+ x, (six.text_type, UserNotice)
+ ) for x in policy_qualifiers
+ ):
+ raise TypeError(
+ "policy_qualifiers must be a list of strings and/or UserNotice"
+ " objects or None"
+ )
+
+ self._policy_qualifiers = policy_qualifiers
+
+ def __repr__(self):
+ return (
+ "<PolicyInformation(policy_identifier={0.policy_identifier}, polic"
+ "y_qualifiers={0.policy_qualifiers})>".format(self)
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, PolicyInformation):
+ return NotImplemented
+
+ return (
+ self.policy_identifier == other.policy_identifier and
+ self.policy_qualifiers == other.policy_qualifiers
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
+ policy_identifier = utils.read_only_property("_policy_identifier")
+ policy_qualifiers = utils.read_only_property("_policy_qualifiers")
+
+
+class UserNotice(object):
+ def __init__(self, notice_reference, explicit_text):
+ if notice_reference and not isinstance(
+ notice_reference, NoticeReference
+ ):
+ raise TypeError(
+ "notice_reference must be None or a NoticeReference"
+ )
+
+ self._notice_reference = notice_reference
+ self._explicit_text = explicit_text
+
+ def __repr__(self):
+ return (
+ "<UserNotice(notice_reference={0.notice_reference}, explicit_text="
+ "{0.explicit_text!r})>".format(self)
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, UserNotice):
+ return NotImplemented
+
+ return (
+ self.notice_reference == other.notice_reference and
+ self.explicit_text == other.explicit_text
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
+ notice_reference = utils.read_only_property("_notice_reference")
+ explicit_text = utils.read_only_property("_explicit_text")
+
+
+class NoticeReference(object):
+ def __init__(self, organization, notice_numbers):
+ self._organization = organization
+ if not isinstance(notice_numbers, list) or not all(
+ isinstance(x, int) for x in notice_numbers
+ ):
+ raise TypeError(
+ "notice_numbers must be a list of integers"
+ )
+
+ self._notice_numbers = notice_numbers
+
+ def __repr__(self):
+ return (
+ "<NoticeReference(organization={0.organization!r}, notice_numbers="
+ "{0.notice_numbers})>".format(self)
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, NoticeReference):
+ return NotImplemented
+
+ return (
+ self.organization == other.organization and
+ self.notice_numbers == other.notice_numbers
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
+ organization = utils.read_only_property("_organization")
+ notice_numbers = utils.read_only_property("_notice_numbers")
+
+
class SubjectKeyIdentifier(object):
def __init__(self, digest):
self._digest = digest
@@ -481,6 +671,151 @@ class SubjectKeyIdentifier(object):
return not self == other
+class CRLDistributionPoints(object):
+ def __init__(self, distribution_points):
+ if not all(
+ isinstance(x, DistributionPoint) for x in distribution_points
+ ):
+ raise TypeError(
+ "distribution_points must be a list of DistributionPoint "
+ "objects"
+ )
+
+ self._distribution_points = distribution_points
+
+ def __iter__(self):
+ return iter(self._distribution_points)
+
+ def __len__(self):
+ return len(self._distribution_points)
+
+ def __repr__(self):
+ return "<CRLDistributionPoints({0})>".format(self._distribution_points)
+
+ def __eq__(self, other):
+ if not isinstance(other, CRLDistributionPoints):
+ return NotImplemented
+
+ return self._distribution_points == other._distribution_points
+
+ def __ne__(self, other):
+ return not self == other
+
+
+class DistributionPoint(object):
+ def __init__(self, full_name, relative_name, reasons, crl_issuer):
+ if full_name and relative_name:
+ raise ValueError(
+ "At least one of full_name and relative_name must be None"
+ )
+
+ if full_name and not all(
+ isinstance(x, GeneralName) for x in full_name
+ ):
+ raise TypeError(
+ "full_name must be a list of GeneralName objects"
+ )
+
+ if relative_name and not isinstance(relative_name, Name):
+ raise TypeError("relative_name must be a Name")
+
+ if crl_issuer and not all(
+ isinstance(x, GeneralName) for x in crl_issuer
+ ):
+ raise TypeError(
+ "crl_issuer must be None or a list of general names"
+ )
+
+ if reasons and (not isinstance(reasons, frozenset) or not all(
+ isinstance(x, ReasonFlags) for x in reasons
+ )):
+ raise TypeError("reasons must be None or frozenset of ReasonFlags")
+
+ if reasons and (
+ ReasonFlags.unspecified in reasons or
+ ReasonFlags.remove_from_crl in reasons
+ ):
+ raise ValueError(
+ "unspecified and remove_from_crl are not valid reasons in a "
+ "DistributionPoint"
+ )
+
+ if reasons and not crl_issuer and not (full_name or relative_name):
+ raise ValueError(
+ "You must supply crl_issuer, full_name, or relative_name when "
+ "reasons is not None"
+ )
+
+ self._full_name = full_name
+ self._relative_name = relative_name
+ self._reasons = reasons
+ self._crl_issuer = crl_issuer
+
+ def __repr__(self):
+ return (
+ "<DistributionPoint(full_name={0.full_name}, relative_name={0.rela"
+ "tive_name}, reasons={0.reasons}, crl_issuer={0.crl_is"
+ "suer})>".format(self)
+ )
+
+ def __eq__(self, other):
+ if not isinstance(other, DistributionPoint):
+ return NotImplemented
+
+ return (
+ self.full_name == other.full_name and
+ self.relative_name == other.relative_name and
+ self.reasons == other.reasons and
+ self.crl_issuer == other.crl_issuer
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
+ full_name = utils.read_only_property("_full_name")
+ relative_name = utils.read_only_property("_relative_name")
+ reasons = utils.read_only_property("_reasons")
+ crl_issuer = utils.read_only_property("_crl_issuer")
+
+
+class ReasonFlags(Enum):
+ unspecified = "unspecified"
+ key_compromise = "keyCompromise"
+ ca_compromise = "cACompromise"
+ affiliation_changed = "affiliationChanged"
+ superseded = "superseded"
+ cessation_of_operation = "cessationOfOperation"
+ certificate_hold = "certificateHold"
+ privilege_withdrawn = "privilegeWithdrawn"
+ aa_compromise = "aACompromise"
+ remove_from_crl = "removeFromCRL"
+
+
+class InhibitAnyPolicy(object):
+ def __init__(self, skip_certs):
+ if not isinstance(skip_certs, six.integer_types):
+ raise TypeError("skip_certs must be an integer")
+
+ if skip_certs < 0:
+ raise ValueError("skip_certs must be a non-negative integer")
+
+ self._skip_certs = skip_certs
+
+ def __repr__(self):
+ return "<InhibitAnyPolicy(skip_certs={0.skip_certs})>".format(self)
+
+ def __eq__(self, other):
+ if not isinstance(other, InhibitAnyPolicy):
+ return NotImplemented
+
+ return self.skip_certs == other.skip_certs
+
+ def __ne__(self, other):
+ return not self == other
+
+ skip_certs = utils.read_only_property("_skip_certs")
+
+
@six.add_metaclass(abc.ABCMeta)
class GeneralName(object):
@abc.abstractproperty
@@ -609,11 +944,18 @@ class RegisteredID(object):
class IPAddress(object):
def __init__(self, value):
if not isinstance(
- value, (ipaddress.IPv4Address, ipaddress.IPv6Address)
+ value,
+ (
+ ipaddress.IPv4Address,
+ ipaddress.IPv6Address,
+ ipaddress.IPv4Network,
+ ipaddress.IPv6Network
+ )
):
raise TypeError(
- "value must be an instance of ipaddress.IPv4Address or "
- "ipaddress.IPv6Address"
+ "value must be an instance of ipaddress.IPv4Address, "
+ "ipaddress.IPv6Address, ipaddress.IPv4Network, or "
+ "ipaddress.IPv6Network"
)
self._value = value
@@ -633,7 +975,7 @@ class IPAddress(object):
return not self == other
-class SubjectAlternativeName(object):
+class GeneralNames(object):
def __init__(self, general_names):
if not all(isinstance(x, GeneralName) for x in general_names):
raise TypeError(
@@ -653,8 +995,43 @@ class SubjectAlternativeName(object):
return [i.value for i in self if isinstance(i, type)]
def __repr__(self):
+ return "<GeneralNames({0})>".format(self._general_names)
+
+ def __eq__(self, other):
+ if not isinstance(other, GeneralNames):
+ return NotImplemented
+
+ return self._general_names == other._general_names
+
+ def __ne__(self, other):
+ return not self == other
+
+
+class SubjectAlternativeName(object):
+ def __init__(self, general_names):
+ self._general_names = GeneralNames(general_names)
+
+ def __iter__(self):
+ return iter(self._general_names)
+
+ def __len__(self):
+ return len(self._general_names)
+
+ def get_values_for_type(self, type):
+ return self._general_names.get_values_for_type(type)
+
+ 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,
@@ -691,6 +1068,20 @@ class AuthorityKeyIdentifier(object):
")>".format(self)
)
+ def __eq__(self, other):
+ if not isinstance(other, AuthorityKeyIdentifier):
+ return NotImplemented
+
+ return (
+ self.key_identifier == other.key_identifier and
+ self.authority_cert_issuer == other.authority_cert_issuer and
+ self.authority_cert_serial_number ==
+ other.authority_cert_serial_number
+ )
+
+ def __ne__(self, other):
+ return not self == other
+
key_identifier = utils.read_only_property("_key_identifier")
authority_cert_issuer = utils.read_only_property("_authority_cert_issuer")
authority_cert_serial_number = utils.read_only_property(
@@ -754,6 +1145,10 @@ OID_OCSP_SIGNING = ObjectIdentifier("1.3.6.1.5.5.7.3.9")
OID_CA_ISSUERS = ObjectIdentifier("1.3.6.1.5.5.7.48.2")
OID_OCSP = ObjectIdentifier("1.3.6.1.5.5.7.48.1")
+OID_CPS_QUALIFIER = ObjectIdentifier("1.3.6.1.5.5.7.2.1")
+OID_CPS_USER_NOTICE = ObjectIdentifier("1.3.6.1.5.5.7.2.2")
+OID_ANY_POLICY = ObjectIdentifier("2.5.29.32.0")
+
@six.add_metaclass(abc.ABCMeta)
class Certificate(object):
@@ -812,6 +1207,77 @@ class Certificate(object):
in the certificate.
"""
+ @abc.abstractproperty
+ def extensions(self):
+ """
+ Returns an Extensions object.
+ """
+
+ @abc.abstractmethod
+ def __eq__(self, other):
+ """
+ Checks equality.
+ """
+
+ @abc.abstractmethod
+ def __ne__(self, other):
+ """
+ Checks not equal.
+ """
+
+ @abc.abstractmethod
+ def public_bytes(self, encoding):
+ """
+ Serializes the certificate to PEM or DER format.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class CertificateRevocationList(object):
+
+ @abc.abstractmethod
+ def fingerprint(self, algorithm):
+ """
+ Returns bytes using digest passed.
+ """
+
+ @abc.abstractproperty
+ def signature_hash_algorithm(self):
+ """
+ Returns a HashAlgorithm corresponding to the type of the digest signed
+ in the certificate.
+ """
+
+ @abc.abstractproperty
+ def issuer(self):
+ """
+ Returns the X509Name with the issuer of this CRL.
+ """
+
+ @abc.abstractproperty
+ def next_update(self):
+ """
+ Returns the date of next update for this CRL.
+ """
+
+ @abc.abstractproperty
+ def last_update(self):
+ """
+ Returns the date of last update for this CRL.
+ """
+
+ @abc.abstractproperty
+ def revoked_certificates(self):
+ """
+ Returns a list of RevokedCertificate objects for this CRL.
+ """
+
+ @abc.abstractproperty
+ def extensions(self):
+ """
+ Returns an Extensions object containing a list of CRL extensions.
+ """
+
@abc.abstractmethod
def __eq__(self, other):
"""
@@ -845,3 +1311,36 @@ class CertificateSigningRequest(object):
Returns a HashAlgorithm corresponding to the type of the digest signed
in the certificate.
"""
+
+ @abc.abstractproperty
+ def extensions(self):
+ """
+ Returns the extensions in the signing request.
+ """
+
+ @abc.abstractmethod
+ def public_bytes(self, encoding):
+ """
+ Encodes the request to PEM or DER format.
+ """
+
+
+@six.add_metaclass(abc.ABCMeta)
+class RevokedCertificate(object):
+ @abc.abstractproperty
+ def serial_number(self):
+ """
+ Returns the serial number of the revoked certificate.
+ """
+
+ @abc.abstractproperty
+ def revocation_date(self):
+ """
+ Returns the date of when this certificate was revoked.
+ """
+
+ @abc.abstractproperty
+ def extensions(self):
+ """
+ Returns an Extensions object containing a list of Revoked extensions.
+ """