diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/_cffi_src/openssl/asn1.py | 1 | ||||
-rw-r--r-- | src/_cffi_src/openssl/x509v3.py | 3 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 58 |
3 files changed, 58 insertions, 4 deletions
diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 01d6f4c2..5f8ca697 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -157,6 +157,7 @@ int ASN1_UTCTIME_check(ASN1_UTCTIME *); int ASN1_STRING_set_default_mask_asc(char *); int i2d_ASN1_TYPE(ASN1_TYPE *, unsigned char **); +ASN1_TYPE *d2i_ASN1_TYPE(ASN1_TYPE **, const unsigned char **, long); """ CUSTOMIZATIONS = """ diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 0f5306d0..8e42b65d 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -193,6 +193,9 @@ void AUTHORITY_KEYID_free(AUTHORITY_KEYID *); NAME_CONSTRAINTS *NAME_CONSTRAINTS_new(void); void NAME_CONSTRAINTS_free(NAME_CONSTRAINTS *); +OTHERNAME *OTHERNAME_new(void); +void OTHERNAME_free(OTHERNAME *); + void *X509V3_set_ctx_nodb(X509V3_CTX *); int i2d_GENERAL_NAMES(GENERAL_NAMES *, unsigned char **); diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index d6493778..637b28cc 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -83,14 +83,22 @@ def _encode_asn1_str(backend, data, length): Create an ASN1_OCTET_STRING from a Python byte string. """ s = backend._lib.ASN1_OCTET_STRING_new() + res = backend._lib.ASN1_OCTET_STRING_set(s, data, length) + assert res == 1 + return s + + +def _encode_asn1_str_gc(backend, data, length): + s = _encode_asn1_str(backend, data, length) s = backend._ffi.gc(s, backend._lib.ASN1_OCTET_STRING_free) - backend._lib.ASN1_OCTET_STRING_set(s, data, length) return s def _encode_name(backend, attributes): + """ + The X509_NAME created will not be gc'd. Use _encode_name_gc if needed. + """ subject = backend._lib.X509_NAME_new() - subject = backend._ffi.gc(subject, backend._lib.X509_NAME_free) for attribute in attributes: value = attribute.value.encode('utf8') obj = _txt2obj(backend, attribute.oid.dotted_string) @@ -105,6 +113,12 @@ def _encode_name(backend, attributes): return subject +def _encode_name_gc(backend, attributes): + subject = _encode_name(backend, attributes) + subject = backend._ffi.gc(subject, backend._lib.X509_NAME_free) + return subject + + def _txt2obj(backend, name): """ Converts a Python string with an ASN.1 object ID in dotted form to a @@ -171,6 +185,42 @@ def _encode_subject_alt_name(backend, san): ) 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: + 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 else: raise NotImplementedError( "Only DNSName and RegisteredID supported right now" @@ -874,7 +924,7 @@ class Backend(object): # Set subject name. res = self._lib.X509_REQ_set_subject_name( - x509_req, _encode_name(self, builder._subject_name) + x509_req, _encode_name_gc(self, builder._subject_name) ) assert res == 1 @@ -905,7 +955,7 @@ class Backend(object): self._ffi.NULL, obj, 1 if extension.critical else 0, - _encode_asn1_str(self, pp[0], r), + _encode_asn1_str_gc(self, pp[0], r), ) assert extension != self._ffi.NULL res = self._lib.sk_X509_EXTENSION_push(extensions, extension) |