diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/cryptography/__about__.py | 2 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 343 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/ec.py | 15 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/evp.py | 4 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/ssl.py | 37 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509.py | 14 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509_vfy.py | 16 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509name.py | 5 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/x509v3.py | 85 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/dsa.py | 22 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/ec.py | 29 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/asymmetric/rsa.py | 22 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/interfaces/__init__.py | 351 | ||||
-rw-r--r-- | src/cryptography/hazmat/primitives/kdf/hkdf.py | 4 | ||||
-rw-r--r-- | src/cryptography/utils.py | 3 | ||||
-rw-r--r-- | src/cryptography/x509.py | 409 |
16 files changed, 894 insertions, 467 deletions
diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 0f8d4871..359cd819 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__ = "0.10.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 7f633c76..07e54baa 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -15,6 +15,7 @@ from __future__ import absolute_import, division, print_function import datetime import ipaddress +from email.utils import parseaddr import idna @@ -37,33 +38,56 @@ def _obj2txt(backend, obj): return backend._ffi.buffer(buf, res)[:].decode() +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 _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 - 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(_build_x509_name_entry(backend, entry)) return x509.Name(attributes) +def _build_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(_build_general_name(backend, gn)) + + return names + + def _build_general_name(backend, gn): if gn.type == backend._lib.GEN_DNS: data = backend._ffi.buffer(gn.d.dNSName.data, gn.d.dNSName.length)[:] @@ -107,6 +131,27 @@ def _build_general_name(backend, gn): return x509.DirectoryName( _build_x509_name(backend, gn.d.directoryName) ) + elif gn.type == backend._lib.GEN_EMAIL: + data = backend._ffi.buffer( + gn.d.rfc822Name.data, gn.d.rfc822Name.length + )[:].decode("ascii") + name, address = parseaddr(data) + parts = address.split(u"@") + if name or len(parts) > 2 or not address: + # parseaddr has found a name (e.g. Name <email>) or the split + # has found more than 2 parts (which means more than one @ sign) + # or the entire value is an empty string. + raise ValueError("Invalid rfc822name value") + elif len(parts) == 1: + # Single label email name. This is valid for local delivery. No + # IDNA decoding can be done since there is no domain component. + return x509.RFC822Name(address) + else: + # A normal email of the form user@domain.com. Let's attempt to + # decode the domain component and return the entire address. + return x509.RFC822Name( + parts[0] + u"@" + idna.decode(parts[1]) + ) else: # otherName, x400Address or ediPartyName raise x509.UnsupportedGeneralNameType( @@ -160,12 +205,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) @@ -245,6 +285,16 @@ class _Certificate(object): value = self._build_key_usage(ext) elif oid == x509.OID_SUBJECT_ALTERNATIVE_NAME: value = self._build_subject_alt_name(ext) + elif oid == x509.OID_EXTENDED_KEY_USAGE: + value = self._build_extended_key_usage(ext) + elif oid == x509.OID_AUTHORITY_KEY_IDENTIFIER: + value = self._build_authority_key_identifier(ext) + elif oid == x509.OID_AUTHORITY_INFORMATION_ACCESS: + 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 @@ -259,6 +309,75 @@ class _Certificate(object): return x509.Extensions(extensions) + def _build_certificate_policies(self, ext): + cp = self._backend._ffi.cast( + "Cryptography_STACK_OF_POLICYINFO *", + self._backend._lib.X509V3_EXT_d2i(ext) + ) + assert cp != self._backend._ffi.NULL + cp = self._backend._ffi.gc(cp, self._backend._lib.sk_POLICYINFO_free) + num = self._backend._lib.sk_POLICYINFO_num(cp) + certificate_policies = [] + for i in range(num): + qualifiers = None + pi = self._backend._lib.sk_POLICYINFO_value(cp, i) + oid = x509.ObjectIdentifier(_obj2txt(self._backend, pi.policyid)) + if pi.qualifiers != self._backend._ffi.NULL: + qnum = self._backend._lib.sk_POLICYQUALINFO_num(pi.qualifiers) + qualifiers = [] + for j in range(qnum): + pqi = self._backend._lib.sk_POLICYQUALINFO_value( + pi.qualifiers, j + ) + pqualid = x509.ObjectIdentifier( + _obj2txt(self._backend, pqi.pqualid) + ) + if pqualid == x509.OID_CPS_QUALIFIER: + cpsuri = self._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 = self._build_user_notice(pqi.d.usernotice) + qualifiers.append(user_notice) + + certificate_policies.append( + x509.PolicyInformation(oid, qualifiers) + ) + + return x509.CertificatePolicies(certificate_policies) + + def _build_user_notice(self, un): + explicit_text = None + notice_reference = None + + if un.exptext != self._backend._ffi.NULL: + explicit_text = _asn1_string_to_utf8(self._backend, un.exptext) + + if un.noticeref != self._backend._ffi.NULL: + organization = _asn1_string_to_utf8( + self._backend, un.noticeref.organization + ) + + num = self._backend._lib.sk_ASN1_INTEGER_num( + un.noticeref.noticenos + ) + notice_numbers = [] + for i in range(num): + asn1_int = self._backend._lib.sk_ASN1_INTEGER_value( + un.noticeref.noticenos, i + ) + notice_num = _asn1_integer_to_int( + self._backend, asn1_int + ) + notice_numbers.append(notice_num) + + notice_reference = x509.NoticeReference( + organization, notice_numbers + ) + + return x509.UserNotice(notice_reference, explicit_text) + def _build_basic_constraints(self, ext): bc_st = self._backend._lib.X509V3_EXT_d2i(ext) assert bc_st != self._backend._ffi.NULL @@ -275,12 +394,9 @@ class _Certificate(object): 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 + path_length = _asn1_integer_to_int( + self._backend, basic_constraints.pathlen ) - 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) @@ -297,6 +413,57 @@ class _Certificate(object): self._backend._ffi.buffer(asn1_string.data, asn1_string.length)[:] ) + 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 + ) + 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 = _build_general_names( + self._backend, akid.issuer + ) + + if akid.serial != self._backend._ffi.NULL: + authority_cert_serial_number = _asn1_integer_to_int( + self._backend, akid.serial + ) + + return x509.AuthorityKeyIdentifier( + key_identifier, authority_cert_issuer, authority_cert_serial_number + ) + + 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 = self._backend._lib.sk_ACCESS_DESCRIPTION_num(aia) + access_descriptions = [] + 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 @@ -332,17 +499,121 @@ class _Certificate(object): ) 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 = [] + general_names = _build_general_names(self._backend, gns) + + return x509.SubjectAlternativeName(general_names) + + def _build_extended_key_usage(self, ext): + sk = self._backend._ffi.cast( + "Cryptography_STACK_OF_ASN1_OBJECT *", + self._backend._lib.X509V3_EXT_d2i(ext) + ) + 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): - gn = self._backend._lib.sk_GENERAL_NAME_value(gns, i) - assert gn != self._backend._ffi.NULL - value = _build_general_name(self._backend, gn) + 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) - general_names.append(value) + return x509.ExtendedKeyUsage(ekus) - return x509.SubjectAlternativeName(general_names) + 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) 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 4a824ae5..5445f3c9 100644 --- a/src/cryptography/hazmat/bindings/openssl/ssl.py +++ b/src/cryptography/hazmat/bindings/openssl/ssl.py @@ -22,6 +22,8 @@ static const long Cryptography_HAS_SECURE_RENEGOTIATION; 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; @@ -164,6 +166,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 *); @@ -325,7 +328,10 @@ void SSL_CTX_set_tlsext_servername_callback( is fraught with peril thanks to OS distributions we check some constants to determine if they are supported or not */ 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 *); @@ -379,6 +385,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 = """ @@ -427,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 @@ -434,6 +443,14 @@ static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP = 1; #else static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP = 0; long (*SSL_set_tlsext_status_ocsp_resp)(SSL *, unsigned char *, int) = NULL; +long (*SSL_get_tlsext_status_ocsp_resp)(SSL *, const unsigned char **) = NULL; +#endif + +#ifdef SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE +static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE = 1; +#else +static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE = 0; +long (*SSL_set_tlsext_status_type)(SSL *, long) = NULL; #endif #ifdef SSL_MODE_RELEASE_BUFFERS @@ -572,6 +589,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; @@ -579,6 +597,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 = { @@ -616,10 +641,16 @@ 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": [ "SSL_set_tlsext_status_ocsp_resp", + "SSL_get_tlsext_status_ocsp_resp", + ], + + "Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE": [ + "SSL_set_tlsext_status_type", ], "Cryptography_HAS_RELEASE_BUFFERS": [ @@ -675,5 +706,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 a1fb7ffb..caa33969 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,6 +190,7 @@ 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); @@ -285,6 +293,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 *); @@ -303,6 +312,11 @@ EC_KEY *d2i_EC_PUBKEY_bio(BIO *, EC_KEY **); int i2d_EC_PUBKEY_bio(BIO *, EC_KEY *); EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **); int i2d_ECPrivateKey_bio(BIO *, EC_KEY *); + +// 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); +void sk_ASN1_OBJECT_free(Cryptography_STACK_OF_ASN1_OBJECT *); """ CUSTOMIZATIONS = """ 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..a7dde87c 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 = """ @@ -48,6 +50,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 28dd7f32..054ab624 100644 --- a/src/cryptography/hazmat/bindings/openssl/x509v3.py +++ b/src/cryptography/hazmat/bindings/openssl/x509v3.py @@ -19,9 +19,19 @@ typedef LHASH_OF(CONF_VALUE) Cryptography_LHASH_OF_CONF_VALUE; #else 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; X509 *subject_cert; @@ -92,7 +102,55 @@ typedef struct { ASN1_INTEGER *serial; } AUTHORITY_KEYID; +typedef struct { + ASN1_OBJECT *method; + GENERAL_NAME *location; +} 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; """ @@ -108,12 +166,23 @@ 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); +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 *); + X509_EXTENSION *X509V3_EXT_conf_nid(Cryptography_LHASH_OF_CONF_VALUE *, X509V3_CTX *, int, char *); @@ -121,6 +190,22 @@ 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); """ 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/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 65b7091a..f738bbdc 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -26,7 +26,7 @@ class HKDF(object): self._algorithm = algorithm - if not isinstance(salt, bytes) and salt is not None: + if not (salt is None or isinstance(salt, bytes)): raise TypeError("salt must be bytes.") if salt is None: @@ -77,7 +77,7 @@ class HKDFExpand(object): self._length = length - if not isinstance(info, bytes) and info is not None: + if not (info is None or isinstance(info, bytes)): raise TypeError("info must be bytes.") if info is None: 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 b22ac8be..71ba9042 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -67,6 +67,10 @@ _OID_NAMES = { "1.3.6.1.5.5.7.1.1": "authorityInfoAccess", "1.3.6.1.5.5.7.1.11": "subjectInfoAccess", "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", } @@ -277,11 +281,10 @@ class Extension(object): class ExtendedKeyUsage(object): def __init__(self, usages): - for oid in usages: - if not isinstance(oid, ObjectIdentifier): - raise TypeError( - "Every item in the usages list must be an ObjectIdentifier" - ) + if not all(isinstance(x, ObjectIdentifier) for x in usages): + raise TypeError( + "Every item in the usages list must be an ObjectIdentifier" + ) self._usages = usages @@ -294,6 +297,15 @@ class ExtendedKeyUsage(object): def __repr__(self): return "<ExtendedKeyUsage({0})>".format(self._usages) + def __eq__(self, other): + if not isinstance(other, ExtendedKeyUsage): + return NotImplemented + + return self._usages == other._usages + + def __ne__(self, other): + return not self == other + class BasicConstraints(object): def __init__(self, ca, path_length): @@ -321,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, @@ -385,6 +406,226 @@ 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): + if not all(isinstance(x, AccessDescription) for x in descriptions): + raise TypeError( + "Every item in the descriptions list must be an " + "AccessDescription" + ) + + self._descriptions = descriptions + + def __iter__(self): + return iter(self._descriptions) + + def __len__(self): + return len(self._descriptions) + + def __repr__(self): + return "<AuthorityInformationAccess({0})>".format(self._descriptions) + + def __eq__(self, other): + if not isinstance(other, AuthorityInformationAccess): + return NotImplemented + + return self._descriptions == other._descriptions + + def __ne__(self, other): + return not self == other + + +class AccessDescription(object): + def __init__(self, access_method, access_location): + if not (access_method == OID_OCSP or access_method == OID_CA_ISSUERS): + raise ValueError( + "access_method must be OID_OCSP or OID_CA_ISSUERS" + ) + + if not isinstance(access_location, GeneralName): + raise TypeError("access_location must be a GeneralName") + + self._access_method = access_method + self._access_location = access_location + + def __repr__(self): + return ( + "<AccessDescription(access_method={0.access_method}, access_locati" + "on={0.access_location})>".format(self) + ) + + def __eq__(self, other): + if not isinstance(other, AccessDescription): + return NotImplemented + + return ( + self.access_method == other.access_method and + self.access_location == other.access_location + ) + + def __ne__(self, other): + return not self == other + + access_method = utils.read_only_property("_access_method") + 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): @@ -407,6 +648,126 @@ 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" + + @six.add_metaclass(abc.ABCMeta) class GeneralName(object): @abc.abstractproperty @@ -581,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, @@ -592,8 +962,13 @@ class AuthorityKeyIdentifier(object): "must both be present or both None" ) - if not isinstance(authority_cert_issuer, Name): - raise TypeError("authority_cert_issuer must be a Name") + if not all( + isinstance(x, GeneralName) for x in authority_cert_issuer + ): + raise TypeError( + "authority_cert_issuer must be a list of GeneralName " + "objects" + ) if not isinstance(authority_cert_serial_number, six.integer_types): raise TypeError( @@ -612,6 +987,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( @@ -672,6 +1061,12 @@ OID_EMAIL_PROTECTION = ObjectIdentifier("1.3.6.1.5.5.7.3.4") OID_TIME_STAMPING = ObjectIdentifier("1.3.6.1.5.5.7.3.8") 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") + @six.add_metaclass(abc.ABCMeta) class Certificate(object): |