aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/_cffi_src/openssl/x509.py2
-rw-r--r--src/_cffi_src/openssl/x509v3.py3
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py30
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py1
-rw-r--r--src/cryptography/x509.py2
-rw-r--r--tests/test_x509.py23
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)