From 8b399b77b127870b82caddcaa1008d07fcca7ebf Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 2 Dec 2015 22:53:40 -0600 Subject: implement support for encoding name constraints --- src/_cffi_src/openssl/x509v3.py | 12 +++++++ .../hazmat/backends/openssl/backend.py | 37 ++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'src') diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 8e163dc2..51c8410a 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -195,6 +195,7 @@ int i2d_AUTHORITY_KEYID(AUTHORITY_KEYID *, unsigned char **); NAME_CONSTRAINTS *NAME_CONSTRAINTS_new(void); void NAME_CONSTRAINTS_free(NAME_CONSTRAINTS *); +int Cryptography_i2d_NAME_CONSTRAINTS(NAME_CONSTRAINTS *, unsigned char **); OTHERNAME *OTHERNAME_new(void); void OTHERNAME_free(OTHERNAME *); @@ -277,6 +278,8 @@ GENERAL_SUBTREE *sk_GENERAL_SUBTREE_value( int sk_GENERAL_SUBTREE_push(Cryptography_STACK_OF_GENERAL_SUBTREE *, GENERAL_SUBTREE *); +GENERAL_SUBTREE *GENERAL_SUBTREE_new(void); + void sk_ASN1_INTEGER_free(Cryptography_STACK_OF_ASN1_INTEGER *); int sk_ASN1_INTEGER_num(Cryptography_STACK_OF_ASN1_INTEGER *); ASN1_INTEGER *sk_ASN1_INTEGER_value(Cryptography_STACK_OF_ASN1_INTEGER *, int); @@ -295,4 +298,13 @@ int i2d_CRL_DIST_POINTS(Cryptography_STACK_OF_DIST_POINT *, unsigned char **); """ CUSTOMIZATIONS = """ +/* i2d_NAME_CONSTRAINTS doesn't exist, but this is the way the macros in + asn1t.h would implement it. We're not using those macros in case + OpenSSL exposes this function in the future. */ +int Cryptography_i2d_NAME_CONSTRAINTS(NAME_CONSTRAINTS *nc, + unsigned char **out) { + return ASN1_item_i2d((ASN1_VALUE *)nc, out, + ASN1_ITEM_rptr(NAME_CONSTRAINTS)); +} + """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 8cf67551..9811e3ba 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -58,6 +58,42 @@ from cryptography.x509.oid import ExtensionOID, NameOID _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) +def _encode_name_constraints(backend, name_constraints): + nc = backend._lib.NAME_CONSTRAINTS_new() + assert nc != backend._ffi.NULL + nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) + permitted = _encode_general_subtree( + backend, name_constraints.permitted_subtrees + ) + nc.permittedSubtrees = permitted + excluded = _encode_general_subtree( + backend, name_constraints.excluded_subtrees + ) + nc.excludedSubtrees = excluded + + pp = backend._ffi.new('unsigned char **') + r = backend._lib.Cryptography_i2d_NAME_CONSTRAINTS(nc, pp) + assert r > 0 + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + +def _encode_general_subtree(backend, subtrees): + if subtrees is None: + return backend._ffi.NULL + else: + general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null() + for name in subtrees: + gs = backend._lib.GENERAL_SUBTREE_new() + gs.base = _encode_general_name(backend, name) + res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) + assert res >= 1 + + return general_subtrees + + def _encode_asn1_int(backend, x): """ Converts a python integer to an ASN1_INTEGER. The returned ASN1_INTEGER @@ -585,6 +621,7 @@ _EXTENSION_ENCODE_HANDLERS = { ExtensionOID.CRL_DISTRIBUTION_POINTS: _encode_crl_distribution_points, ExtensionOID.INHIBIT_ANY_POLICY: _encode_inhibit_any_policy, ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck, + ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints, } -- cgit v1.2.3 From c65393798c1b22cd39542d5ca10e0023b84537b2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 2 Dec 2015 23:43:20 -0600 Subject: move _encode_name_constraints and _encode_general_subtrees --- .../hazmat/backends/openssl/backend.py | 72 +++++++++++----------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 9811e3ba..8d9e5e0e 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -58,42 +58,6 @@ from cryptography.x509.oid import ExtensionOID, NameOID _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) -def _encode_name_constraints(backend, name_constraints): - nc = backend._lib.NAME_CONSTRAINTS_new() - assert nc != backend._ffi.NULL - nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) - permitted = _encode_general_subtree( - backend, name_constraints.permitted_subtrees - ) - nc.permittedSubtrees = permitted - excluded = _encode_general_subtree( - backend, name_constraints.excluded_subtrees - ) - nc.excludedSubtrees = excluded - - pp = backend._ffi.new('unsigned char **') - r = backend._lib.Cryptography_i2d_NAME_CONSTRAINTS(nc, pp) - assert r > 0 - pp = backend._ffi.gc( - pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) - ) - return pp, r - - -def _encode_general_subtree(backend, subtrees): - if subtrees is None: - return backend._ffi.NULL - else: - general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null() - for name in subtrees: - gs = backend._lib.GENERAL_SUBTREE_new() - gs.base = _encode_general_name(backend, name) - res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) - assert res >= 1 - - return general_subtrees - - def _encode_asn1_int(backend, x): """ Converts a python integer to an ASN1_INTEGER. The returned ASN1_INTEGER @@ -606,6 +570,42 @@ def _encode_crl_distribution_points(backend, crl_distribution_points): return pp, r +def _encode_name_constraints(backend, name_constraints): + nc = backend._lib.NAME_CONSTRAINTS_new() + assert nc != backend._ffi.NULL + nc = backend._ffi.gc(nc, backend._lib.NAME_CONSTRAINTS_free) + permitted = _encode_general_subtree( + backend, name_constraints.permitted_subtrees + ) + nc.permittedSubtrees = permitted + excluded = _encode_general_subtree( + backend, name_constraints.excluded_subtrees + ) + nc.excludedSubtrees = excluded + + pp = backend._ffi.new('unsigned char **') + r = backend._lib.Cryptography_i2d_NAME_CONSTRAINTS(nc, pp) + assert r > 0 + pp = backend._ffi.gc( + pp, lambda pointer: backend._lib.OPENSSL_free(pointer[0]) + ) + return pp, r + + +def _encode_general_subtree(backend, subtrees): + if subtrees is None: + return backend._ffi.NULL + else: + general_subtrees = backend._lib.sk_GENERAL_SUBTREE_new_null() + for name in subtrees: + gs = backend._lib.GENERAL_SUBTREE_new() + gs.base = _encode_general_name(backend, name) + res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) + assert res >= 1 + + return general_subtrees + + _EXTENSION_ENCODE_HANDLERS = { ExtensionOID.BASIC_CONSTRAINTS: _encode_basic_constraints, ExtensionOID.SUBJECT_KEY_IDENTIFIER: _encode_subject_key_identifier, -- cgit v1.2.3 From ab209394e8df273763132a44a5690b551493e94a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 1 Dec 2015 14:50:31 -0600 Subject: expose tbs_certrequest_bytes and signature on CertificateSigningRequest --- src/_cffi_src/openssl/x509.py | 4 ++++ src/cryptography/hazmat/backends/openssl/x509.py | 15 +++++++++++++++ src/cryptography/x509/base.py | 13 +++++++++++++ 3 files changed, 32 insertions(+) (limited to 'src') diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py index b5d461ab..0fc49ac5 100644 --- a/src/_cffi_src/openssl/x509.py +++ b/src/_cffi_src/openssl/x509.py @@ -43,9 +43,12 @@ typedef struct { } X509_EXTENSION; typedef ... X509_EXTENSIONS; +typedef ... X509_REQ_INFO; typedef struct { + X509_REQ_INFO *req_info; X509_ALGOR *sig_alg; + ASN1_BIT_STRING *signature; ...; } X509_REQ; @@ -267,6 +270,7 @@ void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *); MACROS = """ int i2d_X509_CINF(X509_CINF *, unsigned char **); int i2d_X509_CRL_INFO(X509_CRL_INFO *, unsigned char **); +int i2d_X509_REQ_INFO(X509_REQ_INFO *, unsigned char **); long X509_get_version(X509 *); diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 8fa43ea8..01232df2 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -921,6 +921,21 @@ class _CertificateSigningRequest(object): self._backend.openssl_assert(res == 1) return self._backend._read_mem_bio(bio) + @property + def tbs_certrequest_bytes(self): + pp = self._backend._ffi.new("unsigned char **") + # the X509_CINF struct holds the tbsCertificate data + res = self._backend._lib.i2d_X509_REQ_INFO(self._x509_req.req_info, pp) + self._backend.openssl_assert(res > 0) + pp = self._backend._ffi.gc( + pp, lambda pointer: self._backend._lib.OPENSSL_free(pointer[0]) + ) + return self._backend._ffi.buffer(pp[0], res)[:] + + @property + def signature(self): + return self._backend._asn1_string_to_bytes(self._x509_req.signature) + _EXTENSION_HANDLERS = { ExtensionOID.BASIC_CONSTRAINTS: _decode_basic_constraints, diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 6c2386f6..c56ca5ee 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -270,6 +270,19 @@ class CertificateSigningRequest(object): Encodes the request to PEM or DER format. """ + @abc.abstractproperty + def signature(self): + """ + Returns the signature bytes. + """ + + @abc.abstractproperty + def tbs_certrequest_bytes(self): + """ + Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC + 2986. + """ + @six.add_metaclass(abc.ABCMeta) class RevokedCertificate(object): -- cgit v1.2.3 From ceedfcde29d7654f2aae1fbbcb0bf89d0f30ad0d Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 3 Dec 2015 22:25:15 -0600 Subject: fix the comment so that it is no longer nonsense --- src/cryptography/hazmat/backends/openssl/x509.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py index 01232df2..4e91bf43 100644 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ b/src/cryptography/hazmat/backends/openssl/x509.py @@ -924,7 +924,7 @@ class _CertificateSigningRequest(object): @property def tbs_certrequest_bytes(self): pp = self._backend._ffi.new("unsigned char **") - # the X509_CINF struct holds the tbsCertificate data + # the X509_REQ_INFO struct holds the CertificateRequestInfo data res = self._backend._lib.i2d_X509_REQ_INFO(self._x509_req.req_info, pp) self._backend.openssl_assert(res > 0) pp = self._backend._ffi.gc( -- cgit v1.2.3