aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/_cffi_src/openssl/asn1.py2
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py40
-rw-r--r--src/cryptography/hazmat/backends/openssl/x509.py1
-rw-r--r--src/cryptography/x509.py2
-rw-r--r--tests/test_x509.py66
5 files changed, 109 insertions, 2 deletions
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py
index 5f8ca697..96eff7d3 100644
--- a/src/_cffi_src/openssl/asn1.py
+++ b/src/_cffi_src/openssl/asn1.py
@@ -125,7 +125,9 @@ int ASN1_BIT_STRING_set_bit(ASN1_BIT_STRING *, int, int);
"""
MACROS = """
+ASN1_BIT_STRING *ASN1_BIT_STRING_new(void);
void ASN1_BIT_STRING_free(ASN1_BIT_STRING *);
+int i2d_ASN1_BIT_STRING(ASN1_BIT_STRING *, unsigned char **);
/* This is not a macro, but is const on some versions of OpenSSL */
int ASN1_BIT_STRING_get_bit(ASN1_BIT_STRING *, int);
ASN1_TIME *M_ASN1_TIME_dup(void *);
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 9cfe73c1..046a1739 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -131,6 +131,44 @@ def _txt2obj(backend, name):
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(
@@ -964,6 +1002,8 @@ 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)
else:
raise NotImplementedError('Extension not yet supported.')
diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py
index 472d8a70..943cfd78 100644
--- a/src/cryptography/hazmat/backends/openssl/x509.py
+++ b/src/cryptography/hazmat/backends/openssl/x509.py
@@ -816,6 +816,7 @@ _CSR_EXTENSION_PARSER = _X509ExtensionParser(
get_ext=lambda backend, x, i: backend._lib.sk_X509_EXTENSION_value(x, i),
handlers={
x509.OID_BASIC_CONSTRAINTS: _decode_basic_constraints,
+ x509.OID_KEY_USAGE: _decode_key_usage,
x509.OID_SUBJECT_ALTERNATIVE_NAME: _decode_subject_alt_name,
}
)
diff --git a/src/cryptography/x509.py b/src/cryptography/x509.py
index 58e1a37c..5d108ee6 100644
--- a/src/cryptography/x509.py
+++ b/src/cryptography/x509.py
@@ -1577,6 +1577,8 @@ class CertificateSigningRequestBuilder(object):
)
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
diff --git a/tests/test_x509.py b/tests/test_x509.py
index b2262c71..af7d9421 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -962,6 +962,20 @@ class TestCertificateSigningRequestBuilder(object):
x509.SubjectAlternativeName([x509.DNSName(u"cryptography.io")]),
critical=False,
).add_extension(
+ x509.InhibitAnyPolicy(0),
+ critical=False
+ )
+ with pytest.raises(NotImplementedError):
+ builder.sign(private_key, hashes.SHA256(), backend)
+
+ def test_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.KeyUsage(
digital_signature=True,
content_commitment=True,
@@ -974,9 +988,57 @@ class TestCertificateSigningRequestBuilder(object):
decipher_only=False
),
critical=False
+ ).sign(private_key, hashes.SHA256(), backend)
+ assert len(request.extensions) == 1
+ ext = request.extensions.get_extension_for_oid(x509.OID_KEY_USAGE)
+ assert ext.critical is False
+ assert ext.value == x509.KeyUsage(
+ digital_signature=True,
+ content_commitment=True,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=False,
+ key_cert_sign=True,
+ crl_sign=False,
+ encipher_only=False,
+ decipher_only=False
+ )
+
+ def test_key_usage_key_agreement_bit(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.KeyUsage(
+ digital_signature=False,
+ content_commitment=False,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=True,
+ key_cert_sign=True,
+ crl_sign=False,
+ encipher_only=False,
+ decipher_only=True
+ ),
+ critical=False
+ ).sign(private_key, hashes.SHA256(), backend)
+ assert len(request.extensions) == 1
+ ext = request.extensions.get_extension_for_oid(x509.OID_KEY_USAGE)
+ assert ext.critical is False
+ assert ext.value == x509.KeyUsage(
+ digital_signature=False,
+ content_commitment=False,
+ key_encipherment=False,
+ data_encipherment=False,
+ key_agreement=True,
+ key_cert_sign=True,
+ crl_sign=False,
+ encipher_only=False,
+ decipher_only=True
)
- with pytest.raises(NotImplementedError):
- builder.sign(private_key, hashes.SHA256(), backend)
def test_add_two_extensions(self, backend):
private_key = RSA_KEY_2048.private_key(backend)