From df38700f360811c1ee25f79f2cef5d08ea50b5e0 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 27 Jul 2015 15:19:57 +0100 Subject: support encoding certificate policies in CertificateBuilder --- .../hazmat/backends/openssl/backend.py | 90 ++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 58587b94..e1ef63be 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -94,6 +94,20 @@ def _encode_asn1_str(backend, data, length): return s +def _encode_asn1_utf8_str(backend, string): + """ + Create an ASN1_UTF8STRING from a Python unicode string. + This object will be a ASN1_STRING with UTF8 type in OpenSSL and + can be decoded with ASN1_STRING_to_UTF8. + """ + s = backend._lib.ASN1_UTF8STRING_new() + res = backend._lib.ASN1_STRING_set( + s, string.encode("utf8"), len(string.encode("utf8")) + ) + 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) @@ -136,6 +150,81 @@ def _encode_name_gc(backend, attributes): return subject +def _encode_certificate_policies(backend, certificate_policies): + cp = backend._lib.sk_POLICYINFO_new_null() + assert cp != backend._ffi.NULL + cp = backend._ffi.gc(cp, backend._lib.sk_POLICYINFO_free) + for policy_info in certificate_policies: + pi = backend._lib.POLICYINFO_new() + assert pi != backend._ffi.NULL + res = backend._lib.sk_POLICYINFO_push(cp, pi) + assert res >= 1 + oid = _txt2obj(backend, policy_info.policy_identifier.dotted_string) + pi.policyid = oid + if policy_info.policy_qualifiers: + pqis = backend._lib.sk_POLICYQUALINFO_new_null() + assert pqis != backend._ffi.NULL + for qualifier in policy_info.policy_qualifiers: + pqi = backend._lib.POLICYQUALINFO_new() + assert pqi != backend._ffi.NULL + res = backend._lib.sk_POLICYQUALINFO_push(pqis, pqi) + assert res >= 1 + if isinstance(qualifier, six.text_type): + pqi.pqualid = _txt2obj( + backend, x509.OID_CPS_QUALIFIER.dotted_string + ) + pqi.d.cpsuri = _encode_asn1_str( + backend, + qualifier.encode("ascii"), + len(qualifier.encode("ascii")) + ) + else: + assert isinstance(qualifier, x509.UserNotice) + pqi.pqualid = _txt2obj( + backend, x509.OID_CPS_USER_NOTICE.dotted_string + ) + un = backend._lib.USERNOTICE_new() + assert un != backend._ffi.NULL + pqi.d.usernotice = un + if qualifier.explicit_text: + un.exptext = _encode_asn1_utf8_str( + backend, qualifier.explicit_text + ) + + un.noticeref = _encode_notice_reference( + backend, qualifier.notice_reference + ) + + pi.qualifiers = pqis + + pp = backend._ffi.new('unsigned char **') + r = backend._lib.i2d_CERTIFICATEPOLICIES(cp, pp) + assert r > 0 + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + +def _encode_notice_reference(backend, notice): + if notice is None: + return backend._ffi.NULL + else: + nr = backend._lib.NOTICEREF_new() + assert nr != backend._ffi.NULL + # organization is a required field + nr.organization = _encode_asn1_utf8_str(backend, notice.organization) + + notice_stack = backend._lib.sk_ASN1_INTEGER_new_null() + nr.noticenos = notice_stack + for number in notice.notice_numbers: + num = _encode_asn1_int(backend, number) + res = backend._lib.sk_ASN1_INTEGER_push(notice_stack, num) + assert res >= 1 + + return nr + + def _txt2obj(backend, name): """ Converts a Python string with an ASN.1 object ID in dotted form to a @@ -487,6 +576,7 @@ _EXTENSION_ENCODE_HANDLERS = { ExtensionOID.ISSUER_ALTERNATIVE_NAME: _encode_alt_name, ExtensionOID.EXTENDED_KEY_USAGE: _encode_extended_key_usage, ExtensionOID.AUTHORITY_KEY_IDENTIFIER: _encode_authority_key_identifier, + x509.OID_CERTIFICATE_POLICIES: _encode_certificate_policies, ExtensionOID.AUTHORITY_INFORMATION_ACCESS: ( _encode_authority_information_access ), -- cgit v1.2.3