diff options
Diffstat (limited to 'src/cryptography')
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 267 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/rsa.py | 5 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 152 | ||||
-rw-r--r-- | src/cryptography/x509.py | 4 |
4 files changed, 238 insertions, 190 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index c190f591..0176de21 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -108,7 +108,7 @@ def _encode_name(backend, attributes): subject = backend._lib.X509_NAME_new() for attribute in attributes: value = attribute.value.encode('utf8') - obj = _txt2obj(backend, attribute.oid.dotted_string) + obj = _txt2obj_gc(backend, attribute.oid.dotted_string) res = backend._lib.X509_NAME_add_entry_by_OBJ( subject, obj, @@ -134,10 +134,53 @@ def _txt2obj(backend, name): name = name.encode('ascii') obj = backend._lib.OBJ_txt2obj(name, 1) assert obj != backend._ffi.NULL + return obj + + +def _txt2obj_gc(backend, name): + obj = _txt2obj(backend, name) obj = backend._ffi.gc(obj, backend._lib.ASN1_OBJECT_free) return obj +def _encode_key_usage(backend, key_usage): + set_bit = backend._lib.ASN1_BIT_STRING_set_bit + ku = backend._lib.ASN1_BIT_STRING_new() + ku = backend._ffi.gc(ku, backend._lib.ASN1_BIT_STRING_free) + res = set_bit(ku, 0, key_usage.digital_signature) + assert res == 1 + res = set_bit(ku, 1, key_usage.content_commitment) + assert res == 1 + res = set_bit(ku, 2, key_usage.key_encipherment) + assert res == 1 + res = set_bit(ku, 3, key_usage.data_encipherment) + assert res == 1 + res = set_bit(ku, 4, key_usage.key_agreement) + assert res == 1 + res = set_bit(ku, 5, key_usage.key_cert_sign) + assert res == 1 + res = set_bit(ku, 6, key_usage.crl_sign) + assert res == 1 + if key_usage.key_agreement: + res = set_bit(ku, 7, key_usage.encipher_only) + assert res == 1 + res = set_bit(ku, 8, key_usage.decipher_only) + assert res == 1 + else: + res = set_bit(ku, 7, 0) + assert res == 1 + res = set_bit(ku, 8, 0) + assert res == 1 + + pp = backend._ffi.new('unsigned char **') + r = backend._lib.i2d_ASN1_BIT_STRING(ku, pp) + assert r > 0 + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + def _encode_basic_constraints(backend, basic_constraints): constraints = backend._lib.BASIC_CONSTRAINTS_new() constraints = backend._ffi.gc( @@ -167,94 +210,118 @@ def _encode_subject_alt_name(backend, san): ) for alt_name in san: - if isinstance(alt_name, x509.DNSName): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - gn.type = backend._lib.GEN_DNS + gn = _encode_general_name(backend, alt_name) + res = backend._lib.sk_GENERAL_NAME_push(general_names, gn) + assert res != 0 - ia5 = backend._lib.ASN1_IA5STRING_new() - assert ia5 != backend._ffi.NULL + pp = backend._ffi.new("unsigned char **") + r = backend._lib.i2d_GENERAL_NAMES(general_names, pp) + assert r > 0 + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r - if alt_name.value.startswith(u"*."): - value = b"*." + idna.encode(alt_name.value[2:]) - else: - value = idna.encode(alt_name.value) - res = backend._lib.ASN1_STRING_set(ia5, value, len(value)) - assert res == 1 - gn.d.dNSName = ia5 - elif isinstance(alt_name, x509.RegisteredID): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - gn.type = backend._lib.GEN_RID - obj = backend._lib.OBJ_txt2obj( - alt_name.value.dotted_string.encode('ascii'), 1 - ) - assert obj != backend._ffi.NULL - gn.d.registeredID = obj - elif isinstance(alt_name, x509.DirectoryName): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - name = _encode_name(backend, alt_name.value) - gn.type = backend._lib.GEN_DIRNAME - gn.d.directoryName = name - elif isinstance(alt_name, x509.IPAddress): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - ipaddr = _encode_asn1_str( - backend, alt_name.value.packed, len(alt_name.value.packed) - ) - gn.type = backend._lib.GEN_IPADD - gn.d.iPAddress = ipaddr - elif isinstance(alt_name, x509.OtherName): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - other_name = backend._lib.OTHERNAME_new() - assert other_name != backend._ffi.NULL - - type_id = backend._lib.OBJ_txt2obj( - alt_name.type_id.dotted_string.encode('ascii'), 1 - ) - assert type_id != backend._ffi.NULL - data = backend._ffi.new("unsigned char[]", alt_name.value) - data_ptr_ptr = backend._ffi.new("unsigned char **") - data_ptr_ptr[0] = data - value = backend._lib.d2i_ASN1_TYPE( - backend._ffi.NULL, data_ptr_ptr, len(alt_name.value) - ) - if value == backend._ffi.NULL: - backend._consume_errors() - raise ValueError("Invalid ASN.1 data") - other_name.type_id = type_id - other_name.value = value - gn.type = backend._lib.GEN_OTHERNAME - gn.d.otherName = other_name - elif isinstance(alt_name, x509.RFC822Name): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - asn1_str = _encode_asn1_str( - backend, alt_name._encoded, len(alt_name._encoded) - ) - gn.type = backend._lib.GEN_EMAIL - gn.d.rfc822Name = asn1_str - elif isinstance(alt_name, x509.UniformResourceIdentifier): - gn = backend._lib.GENERAL_NAME_new() - assert gn != backend._ffi.NULL - asn1_str = _encode_asn1_str( - backend, alt_name._encoded, len(alt_name._encoded) - ) - gn.type = backend._lib.GEN_URI - gn.d.uniformResourceIdentifier = asn1_str +def _encode_general_name(backend, name): + if isinstance(name, x509.DNSName): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + gn.type = backend._lib.GEN_DNS + + ia5 = backend._lib.ASN1_IA5STRING_new() + assert ia5 != backend._ffi.NULL + + if name.value.startswith(u"*."): + value = b"*." + idna.encode(name.value[2:]) else: - raise ValueError( - "{0} is an unknown GeneralName type".format(alt_name) - ) + value = idna.encode(name.value) - res = backend._lib.sk_GENERAL_NAME_push(general_names, gn) - assert res != 0 + res = backend._lib.ASN1_STRING_set(ia5, value, len(value)) + assert res == 1 + gn.d.dNSName = ia5 + elif isinstance(name, x509.RegisteredID): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + gn.type = backend._lib.GEN_RID + obj = backend._lib.OBJ_txt2obj( + name.value.dotted_string.encode('ascii'), 1 + ) + assert obj != backend._ffi.NULL + gn.d.registeredID = obj + elif isinstance(name, x509.DirectoryName): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + dir_name = _encode_name(backend, name.value) + gn.type = backend._lib.GEN_DIRNAME + gn.d.directoryName = dir_name + elif isinstance(name, x509.IPAddress): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + ipaddr = _encode_asn1_str( + backend, name.value.packed, len(name.value.packed) + ) + gn.type = backend._lib.GEN_IPADD + gn.d.iPAddress = ipaddr + elif isinstance(name, x509.OtherName): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + other_name = backend._lib.OTHERNAME_new() + assert other_name != backend._ffi.NULL + + type_id = backend._lib.OBJ_txt2obj( + name.type_id.dotted_string.encode('ascii'), 1 + ) + assert type_id != backend._ffi.NULL + data = backend._ffi.new("unsigned char[]", name.value) + data_ptr_ptr = backend._ffi.new("unsigned char **") + data_ptr_ptr[0] = data + value = backend._lib.d2i_ASN1_TYPE( + backend._ffi.NULL, data_ptr_ptr, len(name.value) + ) + if value == backend._ffi.NULL: + backend._consume_errors() + raise ValueError("Invalid ASN.1 data") + other_name.type_id = type_id + other_name.value = value + gn.type = backend._lib.GEN_OTHERNAME + gn.d.otherName = other_name + elif isinstance(name, x509.RFC822Name): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + asn1_str = _encode_asn1_str( + backend, name._encoded, len(name._encoded) + ) + gn.type = backend._lib.GEN_EMAIL + gn.d.rfc822Name = asn1_str + elif isinstance(name, x509.UniformResourceIdentifier): + gn = backend._lib.GENERAL_NAME_new() + assert gn != backend._ffi.NULL + asn1_str = _encode_asn1_str( + backend, name._encoded, len(name._encoded) + ) + gn.type = backend._lib.GEN_URI + gn.d.uniformResourceIdentifier = asn1_str + else: + raise ValueError( + "{0} is an unknown GeneralName type".format(name) + ) - pp = backend._ffi.new("unsigned char **") - r = backend._lib.i2d_GENERAL_NAMES(general_names, pp) + return gn + + +def _encode_extended_key_usage(backend, extended_key_usage): + eku = backend._lib.sk_ASN1_OBJECT_new_null() + eku = backend._ffi.gc(eku, backend._lib.sk_ASN1_OBJECT_free) + for oid in extended_key_usage: + obj = _txt2obj(backend, oid.dotted_string) + res = backend._lib.sk_ASN1_OBJECT_push(eku, obj) + assert res >= 1 + + pp = backend._ffi.new('unsigned char **') + r = backend._lib.i2d_EXTENDED_KEY_USAGE( + backend._ffi.cast("EXTENDED_KEY_USAGE *", eku), pp + ) assert r > 0 pp = backend._ffi.gc( pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) @@ -971,10 +1038,14 @@ class Backend(object): pp, r = _encode_basic_constraints(self, extension.value) elif isinstance(extension.value, x509.SubjectAlternativeName): pp, r = _encode_subject_alt_name(self, extension.value) + elif isinstance(extension.value, x509.KeyUsage): + pp, r = _encode_key_usage(self, extension.value) + elif isinstance(extension.value, x509.ExtendedKeyUsage): + pp, r = _encode_extended_key_usage(self, extension.value) else: raise NotImplementedError('Extension not yet supported.') - obj = _txt2obj(self, extension.oid.dotted_string) + obj = _txt2obj_gc(self, extension.oid.dotted_string) extension = self._lib.X509_EXTENSION_create_by_OBJ( self._ffi.NULL, obj, @@ -983,7 +1054,7 @@ class Backend(object): ) assert extension != self._ffi.NULL res = self._lib.sk_X509_EXTENSION_push(extensions, extension) - assert res == 1 + assert res >= 1 res = self._lib.X509_REQ_add_extensions(x509_req, extensions) assert res == 1 @@ -991,7 +1062,11 @@ class Backend(object): res = self._lib.X509_REQ_sign( x509_req, private_key._evp_pkey, evp_md ) - assert res > 0 + if res == 0: + errors = self._consume_errors() + assert errors[0][1] == self._lib.ERR_LIB_RSA + assert errors[0][3] == self._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY + raise ValueError("Digest too big for RSA key") return _CertificateSigningRequest(self, x509_req) @@ -1609,13 +1684,15 @@ class Backend(object): if format is serialization.PrivateFormat.PKCS8: write_bio = self._lib.PEM_write_bio_PKCS8PrivateKey key = evp_pkey - elif format is serialization.PrivateFormat.TraditionalOpenSSL: + else: + assert format is serialization.PrivateFormat.TraditionalOpenSSL if evp_pkey.type == self._lib.EVP_PKEY_RSA: write_bio = self._lib.PEM_write_bio_RSAPrivateKey elif evp_pkey.type == self._lib.EVP_PKEY_DSA: write_bio = self._lib.PEM_write_bio_DSAPrivateKey - elif (self._lib.Cryptography_HAS_EC == 1 and - evp_pkey.type == self._lib.EVP_PKEY_EC): + else: + assert self._lib.Cryptography_HAS_EC == 1 + assert evp_pkey.type == self._lib.EVP_PKEY_EC write_bio = self._lib.PEM_write_bio_ECPrivateKey key = cdata @@ -1632,7 +1709,8 @@ class Backend(object): return self._private_key_bytes_traditional_der( evp_pkey.type, cdata ) - elif format is serialization.PrivateFormat.PKCS8: + else: + assert format is serialization.PrivateFormat.PKCS8 write_bio = self._lib.i2d_PKCS8PrivateKey_bio key = evp_pkey else: @@ -1657,7 +1735,8 @@ class Backend(object): elif (self._lib.Cryptography_HAS_EC == 1 and key_type == self._lib.EVP_PKEY_EC): write_bio = self._lib.i2d_ECPrivateKey_bio - elif key_type == self._lib.EVP_PKEY_DSA: + else: + assert key_type == self._lib.EVP_PKEY_DSA write_bio = self._lib.i2d_DSAPrivateKey_bio bio = self._create_mem_bio() @@ -1672,7 +1751,8 @@ class Backend(object): if format is serialization.PublicFormat.SubjectPublicKeyInfo: if encoding is serialization.Encoding.PEM: write_bio = self._lib.PEM_write_bio_PUBKEY - elif encoding is serialization.Encoding.DER: + else: + assert encoding is serialization.Encoding.DER write_bio = self._lib.i2d_PUBKEY_bio key = evp_pkey @@ -1681,7 +1761,8 @@ class Backend(object): assert evp_pkey.type == self._lib.EVP_PKEY_RSA if encoding is serialization.Encoding.PEM: write_bio = self._lib.PEM_write_bio_RSAPublicKey - elif encoding is serialization.Encoding.DER: + else: + assert encoding is serialization.Encoding.DER write_bio = self._lib.i2d_RSAPublicKey_bio key = cdata diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 21414c05..822c7304 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -268,8 +268,9 @@ class _RSASignatureContext(object): self._backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE): reason = ("Salt length too long for key size. Try using " "MAX_LENGTH instead.") - elif (errors[0].reason == - self._backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY): + else: + assert (errors[0].reason == + self._backend._lib.RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY) reason = "Digest too large for key size. Use a larger key." assert reason is not None raise ValueError(reason) diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 472d8a70..ee9a3bbf 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -234,7 +234,15 @@ class _X509ExtensionParser(object): "{0} is not currently supported".format(oid), oid ) else: - value = handler(backend, ext) + d2i = backend._lib.X509V3_EXT_d2i(ext) + if d2i == backend._ffi.NULL: + backend._consume_errors() + raise ValueError( + "The {0} extension is invalid and can't be " + "parsed".format(oid) + ) + + value = handler(backend, d2i) extensions.append(x509.Extension(oid, critical, value)) seen_oids.add(oid) @@ -358,12 +366,8 @@ class _Certificate(object): 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 +def _decode_certificate_policies(backend, cp): + cp = backend._ffi.cast("Cryptography_STACK_OF_POLICYINFO *", cp) cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free) num = backend._lib.sk_POLICYINFO_num(cp) certificate_policies = [] @@ -386,7 +390,8 @@ def _decode_certificate_policies(backend, ext): pqi.d.cpsuri.data, pqi.d.cpsuri.length )[:].decode('ascii') qualifiers.append(cpsuri) - elif pqualid == x509.OID_CPS_USER_NOTICE: + else: + assert pqualid == x509.OID_CPS_USER_NOTICE user_notice = _decode_user_notice( backend, pqi.d.usernotice ) @@ -431,12 +436,8 @@ def _decode_user_notice(backend, un): 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 - ) +def _decode_basic_constraints(backend, bc_st): + basic_constraints = backend._ffi.cast("BASIC_CONSTRAINTS *", bc_st) basic_constraints = backend._ffi.gc( basic_constraints, backend._lib.BASIC_CONSTRAINTS_free ) @@ -447,19 +448,13 @@ def _decode_basic_constraints(backend, ext): if basic_constraints.pathlen == backend._ffi.NULL: path_length = None else: - path_length = _asn1_integer_to_int( - backend, basic_constraints.pathlen - ) + path_length = _asn1_integer_to_int(backend, basic_constraints.pathlen) 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 - ) +def _decode_subject_key_identifier(backend, asn1_string): + asn1_string = backend._ffi.cast("ASN1_OCTET_STRING *", asn1_string) asn1_string = backend._ffi.gc( asn1_string, backend._lib.ASN1_OCTET_STRING_free ) @@ -468,13 +463,9 @@ def _decode_subject_key_identifier(backend, ext): ) -def _decode_authority_key_identifier(backend, ext): - akid = backend._lib.X509V3_EXT_d2i(ext) - assert akid != backend._ffi.NULL +def _decode_authority_key_identifier(backend, akid): akid = backend._ffi.cast("AUTHORITY_KEYID *", akid) - akid = backend._ffi.gc( - akid, backend._lib.AUTHORITY_KEYID_free - ) + akid = backend._ffi.gc(akid, backend._lib.AUTHORITY_KEYID_free) key_identifier = None authority_cert_issuer = None authority_cert_serial_number = None @@ -499,15 +490,9 @@ def _decode_authority_key_identifier(backend, ext): ) -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 - ) +def _decode_authority_information_access(backend, aia): + 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): @@ -521,13 +506,9 @@ def _decode_authority_information_access(backend, ext): 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 +def _decode_key_usage(backend, bit_string): bit_string = backend._ffi.cast("ASN1_BIT_STRING *", bit_string) - bit_string = backend._ffi.gc( - bit_string, backend._lib.ASN1_BIT_STRING_free - ) + 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 @@ -551,11 +532,8 @@ def _decode_key_usage(backend, ext): ) -def _decode_general_names_extension(backend, ext): - gns = backend._ffi.cast( - "GENERAL_NAMES *", backend._lib.X509V3_EXT_d2i(ext) - ) - assert gns != backend._ffi.NULL +def _decode_general_names_extension(backend, gns): + gns = backend._ffi.cast("GENERAL_NAMES *", gns) gns = backend._ffi.gc(gns, backend._lib.GENERAL_NAMES_free) general_names = _decode_general_names(backend, gns) return general_names @@ -573,11 +551,8 @@ def _decode_issuer_alt_name(backend, ext): ) -def _decode_name_constraints(backend, ext): - nc = backend._ffi.cast( - "NAME_CONSTRAINTS *", backend._lib.X509V3_EXT_d2i(ext) - ) - assert nc != backend._ffi.NULL +def _decode_name_constraints(backend, nc): + nc = backend._ffi.cast("NAME_CONSTRAINTS *", nc) nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) permitted = _decode_general_subtrees(backend, nc.permittedSubtrees) excluded = _decode_general_subtrees(backend, nc.excludedSubtrees) @@ -602,12 +577,8 @@ def _decode_general_subtrees(backend, stack_subtrees): return subtrees -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 +def _decode_extended_key_usage(backend, sk): + sk = backend._ffi.cast("Cryptography_STACK_OF_ASN1_OBJECT *", sk) sk = backend._ffi.gc(sk, backend._lib.sk_ASN1_OBJECT_free) num = backend._lib.sk_ASN1_OBJECT_num(sk) ekus = [] @@ -621,14 +592,9 @@ def _decode_extended_key_usage(backend, ext): 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) +def _decode_crl_distribution_points(backend, cdps): + cdps = backend._ffi.cast("Cryptography_STACK_OF_DIST_POINT *", cdps) + cdps = backend._ffi.gc(cdps, backend._lib.sk_DIST_POINT_free) num = backend._lib.sk_DIST_POINT_num(cdps) dist_points = [] @@ -716,12 +682,8 @@ def _decode_crl_distribution_points(backend, ext): return x509.CRLDistributionPoints(dist_points) -def _decode_inhibit_any_policy(backend, ext): - asn1_int = backend._ffi.cast( - "ASN1_INTEGER *", - backend._lib.X509V3_EXT_d2i(ext) - ) - assert asn1_int != backend._ffi.NULL +def _decode_inhibit_any_policy(backend, asn1_int): + asn1_int = backend._ffi.cast("ASN1_INTEGER *", asn1_int) asn1_int = backend._ffi.gc(asn1_int, backend._lib.ASN1_INTEGER_free) skip_certs = _asn1_integer_to_int(backend, asn1_int) return x509.InhibitAnyPolicy(skip_certs) @@ -789,33 +751,33 @@ class _CertificateSigningRequest(object): return self._backend._read_mem_bio(bio) +_EXTENSION_HANDLERS = { + x509.OID_BASIC_CONSTRAINTS: _decode_basic_constraints, + x509.OID_SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, + x509.OID_KEY_USAGE: _decode_key_usage, + x509.OID_SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, + x509.OID_EXTENDED_KEY_USAGE: _decode_extended_key_usage, + x509.OID_AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, + x509.OID_AUTHORITY_INFORMATION_ACCESS: ( + _decode_authority_information_access + ), + x509.OID_CERTIFICATE_POLICIES: _decode_certificate_policies, + x509.OID_CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, + x509.OID_OCSP_NO_CHECK: _decode_ocsp_no_check, + x509.OID_INHIBIT_ANY_POLICY: _decode_inhibit_any_policy, + x509.OID_ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, + x509.OID_NAME_CONSTRAINTS: _decode_name_constraints, +} + + _CERTIFICATE_EXTENSION_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.X509_get_ext_count(x), get_ext=lambda backend, x, i: backend._lib.X509_get_ext(x, i), - handlers={ - x509.OID_BASIC_CONSTRAINTS: _decode_basic_constraints, - x509.OID_SUBJECT_KEY_IDENTIFIER: _decode_subject_key_identifier, - x509.OID_KEY_USAGE: _decode_key_usage, - x509.OID_SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, - x509.OID_EXTENDED_KEY_USAGE: _decode_extended_key_usage, - x509.OID_AUTHORITY_KEY_IDENTIFIER: _decode_authority_key_identifier, - x509.OID_AUTHORITY_INFORMATION_ACCESS: ( - _decode_authority_information_access - ), - x509.OID_CERTIFICATE_POLICIES: _decode_certificate_policies, - x509.OID_CRL_DISTRIBUTION_POINTS: _decode_crl_distribution_points, - x509.OID_OCSP_NO_CHECK: _decode_ocsp_no_check, - x509.OID_INHIBIT_ANY_POLICY: _decode_inhibit_any_policy, - x509.OID_ISSUER_ALTERNATIVE_NAME: _decode_issuer_alt_name, - x509.OID_NAME_CONSTRAINTS: _decode_name_constraints, - } + handlers=_EXTENSION_HANDLERS ) _CSR_EXTENSION_PARSER = _X509ExtensionParser( ext_count=lambda backend, x: backend._lib.sk_X509_EXTENSION_num(x), get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i), - handlers={ - x509.OID_BASIC_CONSTRAINTS: _decode_basic_constraints, - x509.OID_SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name, - } + handlers=_EXTENSION_HANDLERS ) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 9f6cda13..a831506e 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -1575,12 +1575,16 @@ class CertificateSigningRequestBuilder(object): """ if isinstance(extension, BasicConstraints): extension = Extension(OID_BASIC_CONSTRAINTS, critical, extension) + elif isinstance(extension, ExtendedKeyUsage): + extension = Extension(OID_EXTENDED_KEY_USAGE, critical, extension) elif isinstance(extension, SubjectAlternativeName): extension = Extension( OID_SUBJECT_ALTERNATIVE_NAME, critical, extension ) elif isinstance(extension, KeyUsage): extension = Extension(OID_KEY_USAGE, critical, extension) + elif isinstance(extension, InhibitAnyPolicy): + extension = Extension(OID_INHIBIT_ANY_POLICY, critical, extension) else: raise NotImplementedError('Unsupported X.509 extension.') # TODO: This is quadratic in the number of extensions |