diff options
author | Alex Gaynor <alex.gaynor@gmail.com> | 2015-07-23 18:44:27 -0400 |
---|---|---|
committer | Alex Gaynor <alex.gaynor@gmail.com> | 2015-07-23 18:44:27 -0400 |
commit | ba0b3589fd4f65c691849a79228cdc9bc6d0601c (patch) | |
tree | c51ad27b2c23bf03c4976f404d43e29d391ff6ee | |
parent | ef8a72273d639be239d3d7c2380a0912083811da (diff) | |
parent | 0b8f327f59b5a890f2d2ad9101391a0b818e186a (diff) | |
download | cryptography-ba0b3589fd4f65c691849a79228cdc9bc6d0601c.tar.gz cryptography-ba0b3589fd4f65c691849a79228cdc9bc6d0601c.tar.bz2 cryptography-ba0b3589fd4f65c691849a79228cdc9bc6d0601c.zip |
Merge pull request #2169 from reaperhulk/encode-eku
Support encoding ExtendedKeyUsage into certificate signing requests
-rw-r--r-- | src/_cffi_src/openssl/x509.py | 2 | ||||
-rw-r--r-- | src/_cffi_src/openssl/x509v3.py | 3 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 30 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/x509.py | 1 | ||||
-rw-r--r-- | src/cryptography/x509.py | 2 | ||||
-rw-r--r-- | tests/test_x509.py | 23 |
6 files changed, 59 insertions, 2 deletions
diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py index 6bd117b0..bdcc1719 100644 --- a/src/_cffi_src/openssl/x509.py +++ b/src/_cffi_src/openssl/x509.py @@ -325,6 +325,8 @@ int i2o_ECPublicKey(EC_KEY *, unsigned char **); 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 *); +Cryptography_STACK_OF_ASN1_OBJECT *sk_ASN1_OBJECT_new_null(void); +int sk_ASN1_OBJECT_push(Cryptography_STACK_OF_ASN1_OBJECT *, ASN1_OBJECT *); """ CUSTOMIZATIONS = """ diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 8e42b65d..148cd64b 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -33,6 +33,7 @@ typedef ... Cryptography_STACK_OF_POLICYQUALINFO; typedef ... Cryptography_STACK_OF_POLICYINFO; typedef ... Cryptography_STACK_OF_ASN1_INTEGER; typedef ... Cryptography_STACK_OF_GENERAL_SUBTREE; +typedef ... EXTENDED_KEY_USAGE; typedef struct { X509 *issuer_cert; @@ -200,6 +201,8 @@ void *X509V3_set_ctx_nodb(X509V3_CTX *); int i2d_GENERAL_NAMES(GENERAL_NAMES *, unsigned char **); +int i2d_EXTENDED_KEY_USAGE(EXTENDED_KEY_USAGE *, unsigned char **); + 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); diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 046a1739..64d518a1 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -101,7 +101,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, @@ -127,6 +127,11 @@ 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 @@ -293,6 +298,25 @@ def _encode_subject_alt_name(backend, san): return pp, r +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]) + ) + return pp, r + + @utils.register_interface(CipherBackend) @utils.register_interface(CMACBackend) @utils.register_interface(DERSerializationBackend) @@ -1004,10 +1028,12 @@ class Backend(object): 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, diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 943cfd78..493abc83 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -818,5 +818,6 @@ _CSR_EXTENSION_PARSER = _X509ExtensionParser( x509.OID_BASIC_CONSTRAINTS: _decode_basic_constraints, 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, } ) diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py index 5d108ee6..75552fc1 100644 --- a/src/cryptography/x509.py +++ b/src/cryptography/x509.py @@ -1571,6 +1571,8 @@ 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 diff --git a/tests/test_x509.py b/tests/test_x509.py index af7d9421..cacf3c88 100644 --- a/tests/test_x509.py +++ b/tests/test_x509.py @@ -1183,6 +1183,29 @@ class TestCertificateSigningRequestBuilder(object): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) + def test_extended_key_usage(self, backend): + private_key = RSA_KEY_2048.private_key(backend) + builder = x509.CertificateSigningRequestBuilder() + request = builder.subject_name( + x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')]) + ).add_extension( + x509.ExtendedKeyUsage([ + x509.OID_CLIENT_AUTH, + x509.OID_SERVER_AUTH, + x509.OID_CODE_SIGNING, + ]), critical=False + ).sign(private_key, hashes.SHA256(), backend) + + eku = request.extensions.get_extension_for_oid( + x509.OID_EXTENDED_KEY_USAGE + ) + assert eku.critical is False + assert eku.value == x509.ExtendedKeyUsage([ + x509.OID_CLIENT_AUTH, + x509.OID_SERVER_AUTH, + x509.OID_CODE_SIGNING, + ]) + @pytest.mark.requires_backend_interface(interface=DSABackend) @pytest.mark.requires_backend_interface(interface=X509Backend) |