aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2016-03-14 21:01:18 -0400
committerAlex Gaynor <alex.gaynor@gmail.com>2016-03-14 21:01:18 -0400
commit1e03463638a785b229bf518ef7c9997d8f9a52ec (patch)
tree485abed149fdd4e37921d4620d6ee6243d4c27ea
parente8d6a9c262950b8dd6f7671b61383e8c5fe396f7 (diff)
downloadcryptography-1e03463638a785b229bf518ef7c9997d8f9a52ec.tar.gz
cryptography-1e03463638a785b229bf518ef7c9997d8f9a52ec.tar.bz2
cryptography-1e03463638a785b229bf518ef7c9997d8f9a52ec.zip
Fixed #2747 -- allow creating x509 exts with unknown extensions
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py84
-rw-r--r--src/cryptography/hazmat/backends/openssl/encode_asn1.py4
-rw-r--r--tests/test_x509.py33
3 files changed, 88 insertions, 33 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index c6ede932..ab1dcae9 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -32,7 +32,7 @@ from cryptography.hazmat.backends.openssl.encode_asn1 import (
_CRL_ENTRY_EXTENSION_ENCODE_HANDLERS,
_CRL_EXTENSION_ENCODE_HANDLERS, _EXTENSION_ENCODE_HANDLERS,
_encode_asn1_int_gc, _encode_asn1_str_gc, _encode_name_gc,
- _txt2obj_gc,
+ _encode_unrecognized_extension, _txt2obj_gc,
)
from cryptography.hazmat.backends.openssl.hashes import _HashContext
from cryptography.hazmat.backends.openssl.hmac import _HMACContext
@@ -968,42 +968,47 @@ class Backend(object):
def _create_x509_extensions(self, extensions, handlers, x509_obj,
add_func, gc):
for i, extension in enumerate(extensions):
- try:
- encode = handlers[extension.oid]
- except KeyError:
- raise NotImplementedError(
- 'Extension not supported: {0}'.format(extension.oid)
+ if isinstance(extension.value, x509.UnrecognizedExtension):
+ x509_extension = self._create_unrecognized_x509_extension(
+ extension
)
+ else:
+ try:
+ encode = handlers[extension.oid]
+ except KeyError:
+ raise NotImplementedError(
+ 'Extension not supported: {0}'.format(extension.oid)
+ )
- ext_struct = encode(self, extension.value)
- nid = self._lib.OBJ_txt2nid(
- extension.oid.dotted_string.encode("ascii")
- )
- backend.openssl_assert(nid != self._lib.NID_undef)
- x509_extension = self._lib.X509V3_EXT_i2d(
- nid, 1 if extension.critical else 0, ext_struct
- )
- if (
- x509_extension == self._ffi.NULL and
- extension.oid == x509.OID_CERTIFICATE_ISSUER
- ):
- # This path exists to support OpenSSL 0.9.8, which does
- # not know how to encode a CERTIFICATE_ISSUER for CRLs. Once we
- # drop 0.9.8 support we can remove this.
- self._consume_errors()
- pp = backend._ffi.new("unsigned char **")
- r = self._lib.i2d_GENERAL_NAMES(ext_struct, pp)
- backend.openssl_assert(r > 0)
- pp = backend._ffi.gc(
- pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+ ext_struct = encode(self, extension.value)
+ nid = self._lib.OBJ_txt2nid(
+ extension.oid.dotted_string.encode("ascii")
)
- obj = _txt2obj_gc(self, extension.oid.dotted_string)
- x509_extension = self._lib.X509_EXTENSION_create_by_OBJ(
- self._ffi.NULL,
- obj,
- 1 if extension.critical else 0,
- _encode_asn1_str_gc(self, pp[0], r)
+ backend.openssl_assert(nid != self._lib.NID_undef)
+ x509_extension = self._lib.X509V3_EXT_i2d(
+ nid, 1 if extension.critical else 0, ext_struct
)
+ if (
+ x509_extension == self._ffi.NULL and
+ extension.oid == x509.OID_CERTIFICATE_ISSUER
+ ):
+ # This path exists to support OpenSSL 0.9.8, which does not
+ # know how to encode a CERTIFICATE_ISSUER for CRLs. Once we
+ # drop 0.9.8 support we can remove this.
+ self._consume_errors()
+ pp = backend._ffi.new("unsigned char **")
+ r = self._lib.i2d_GENERAL_NAMES(ext_struct, pp)
+ backend.openssl_assert(r > 0)
+ pp = backend._ffi.gc(
+ pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0])
+ )
+ obj = _txt2obj_gc(self, extension.oid.dotted_string)
+ x509_extension = self._lib.X509_EXTENSION_create_by_OBJ(
+ self._ffi.NULL,
+ obj,
+ 1 if extension.critical else 0,
+ _encode_asn1_str_gc(self, pp[0], r)
+ )
self.openssl_assert(x509_extension != self._ffi.NULL)
@@ -1014,6 +1019,19 @@ class Backend(object):
res = add_func(x509_obj, x509_extension, i)
self.openssl_assert(res >= 1)
+ def _create_unrecognized_x509_extension(self, extension):
+ obj = _txt2obj_gc(self, extension.oid.dotted_string)
+ value = _encode_asn1_str_gc(
+ self, extension.value.value, len(extension.value.value)
+ )
+ return self._lib.X509_EXTENSION_create_by_OBJ(
+ self._ffi.NULL,
+ obj,
+ 1 if extension.critical else 0,
+ value
+ )
+
+
def create_x509_revoked_certificate(self, builder):
if not isinstance(builder, x509.RevokedCertificateBuilder):
raise TypeError('Builder type mismatch.')
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index b0e2e73e..5394c2db 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -557,6 +557,10 @@ def _encode_general_subtree(backend, subtrees):
return general_subtrees
+def _encode_unrecognized_extension(backend, ext):
+ return ext.value
+
+
_EXTENSION_ENCODE_HANDLERS = {
ExtensionOID.BASIC_CONSTRAINTS: _encode_basic_constraints,
ExtensionOID.SUBJECT_KEY_IDENTIFIER: _encode_subject_key_identifier,
diff --git a/tests/test_x509.py b/tests/test_x509.py
index a6398bb3..aaeefae9 100644
--- a/tests/test_x509.py
+++ b/tests/test_x509.py
@@ -2382,6 +2382,39 @@ class TestCertificateBuilder(object):
)
assert basic_constraints.value.path_length is None
+ @pytest.mark.parametrize(
+ "unrecognized", [
+ x509.UnrecognizedExtension(
+ x509.ObjectIdentifier("1.2.3.4.5"),
+ b"abcdef",
+ )
+ ]
+ )
+ @pytest.mark.requires_backend_interface(interface=RSABackend)
+ @pytest.mark.requires_backend_interface(interface=X509Backend)
+ def test_unrecognized_extension(self, backend, unrecognized):
+ private_key = RSA_KEY_2048.private_key(backend)
+
+ cert = x509.CertificateBuilder().subject_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+ ).issuer_name(
+ x509.Name([x509.NameAttribute(x509.OID_COUNTRY_NAME, u'US')])
+ ).not_valid_before(
+ datetime.datetime(2002, 1, 1, 12, 1)
+ ).not_valid_after(
+ datetime.datetime(2030, 12, 31, 8, 30)
+ ).public_key(
+ private_key.public_key()
+ ).serial_number(
+ 123
+ ).add_extension(
+ unrecognized, critical=False
+ ).sign(private_key, hashes.SHA256(), backend)
+
+ ext = cert.extensions.get_extension_for_oid(unrecognized.oid)
+
+ assert ext.value == unrecognized
+
@pytest.mark.requires_backend_interface(interface=X509Backend)
class TestCertificateSigningRequestBuilder(object):