From 7db065dd344a88a4797e2de4ff8207c694787920 Mon Sep 17 00:00:00 2001 From: Hayden Roche Date: Sat, 24 Jul 2021 15:54:12 -0700 Subject: [PATCH] Add an OpenSSL compatibility layer. Prior to this commit, some compatibility layer functions were available in wolfssl-py's FFI bindings but only via the wolfSSL names. For example, `wolfSSLv23_server_method` was available, but not `SSLv23_server_method`. This commit adds support for the OpenSSL names. So, a Python module that uses the OpenSSL names can now be more easily ported to using wolfssl-py. For example, the module pyOpenSSL is a Python wrapper around OpenSSL using FFI, very similar to what we're doing with wolfssl-py. These new bindings in wolfssl-py allow us to plug in our wolfSSL FFI to pyOpenSSL, which in turn allows projects using pyOpenSSL to use wolfSSL under the hood. As a proof of concept, I used wolfssl-py with pyOpenSSL to convert the Python module ndg_httpsclient from OpenSSL to wolfSSL. --- README.rst | 5 + src/wolfssl/__about__.py | 2 +- src/wolfssl/__init__.py | 2 +- src/wolfssl/_build_ffi.py | 262 +++++++++++++++++++++++------- src/wolfssl/_build_wolfssl.py | 53 ++++-- src/wolfssl/_openssl.py | 294 ++++++++++++++++++++++++++++++++++ 6 files changed, 539 insertions(+), 79 deletions(-) create mode 100644 src/wolfssl/_openssl.py diff --git a/README.rst b/README.rst index d936e14..f0f0acd 100644 --- a/README.rst +++ b/README.rst @@ -21,6 +21,7 @@ We provide Python wheels (prebuilt binaries) for OSX 64 bits and Linux 64 bits: .. code-block:: bash + $ pip install wheel $ pip install wolfssl To build wolfssl-py from source: @@ -56,6 +57,10 @@ one of the following commands: $ pytest $ py.test tests +Note: If you used USE_LOCAL_WOLFSSL in the installation step or otherwise have +wolfSSL installed in a non-standard location, you'll need to prepend `pytest` +with `USE_LOCAL_WOLFSSL=`. + Support ======= diff --git a/src/wolfssl/__about__.py b/src/wolfssl/__about__.py index 110f8d1..c2474a7 100644 --- a/src/wolfssl/__about__.py +++ b/src/wolfssl/__about__.py @@ -26,7 +26,7 @@ __uri__ = "https://github.com/wolfssl/wolfssl-py" # When bumping the C library version, reset the POST count to 0 -__wolfssl_version__ = "v4.1.0-stable" +__wolfssl_version__ = "v4.8.1-stable" # We're using implicit post releases [PEP 440] to bump package version # while maintaining the C library version intact for better reference. diff --git a/src/wolfssl/__init__.py b/src/wolfssl/__init__.py index 27d1f2c..938d6e6 100644 --- a/src/wolfssl/__init__.py +++ b/src/wolfssl/__init__.py @@ -698,7 +698,7 @@ class SSLSocket(object): eStr = _ffi.string(_lib.wolfSSL_ERR_error_string(err, eBuf)).decode("ascii") - if 'ASN no signer error to confirm' in eStr or err is -188: + if 'ASN no signer error to confirm' in eStr or err == -188: # Some Python ssl consumers explicitly check error message # for 'certificate verify failed' raise SSLError("do_handshake failed with error %d, " diff --git a/src/wolfssl/_build_ffi.py b/src/wolfssl/_build_ffi.py index 6bc4d41..ccb6661 100644 --- a/src/wolfssl/_build_ffi.py +++ b/src/wolfssl/_build_ffi.py @@ -25,47 +25,107 @@ from distutils.util import get_platform from cffi import FFI from wolfssl._build_wolfssl import wolfssl_inc_path, wolfssl_lib_path +import wolfssl._openssl as openssl +import subprocess +import shlex +import os +from ctypes import cdll +from collections import namedtuple + +def make_optional_func_list(libwolfssl_path, funcs): + if libwolfssl_path.endswith(".so"): + libwolfssl = cdll.LoadLibrary(libwolfssl_path) + defined = [] + for func in funcs: + try: + getattr(libwolfssl, func.name) + defined.append(func) + except AttributeError as _: + pass + # Can't discover functions in a static library with ctypes. Need to fall + # back to running nm as a subprocess. + else: + nm_cmd = "nm --defined-only {}".format(libwolfssl_path) + result = subprocess.run(shlex.split(nm_cmd), capture_output=True) + nm_stdout = result.stdout.decode() + defined = [func for func in funcs if func.name in nm_stdout] + + return defined + +libwolfssl_path = os.path.join(wolfssl_lib_path(), "libwolfssl.a") +if not os.path.exists(libwolfssl_path): + libwolfssl_path = os.path.join(wolfssl_lib_path(), "libwolfssl.so") + if not os.path.exists(libwolfssl_path): + err = "Couldn't find libwolfssl under {}.".format(wolfssl_lib_path()) + raise Exception(err) + +WolfFunction = namedtuple("WolfFunction", ["name", "native_sig", "ossl_sig"]) +# Depending on how wolfSSL was configured, the functions below may or may not be +# defined. +optional_funcs = [ + WolfFunction("wolfSSL_ERR_func_error_string", + "const char* wolfSSL_ERR_func_error_string(unsigned long)", + "const char* ERR_func_error_string(unsigned long)"), + WolfFunction("wolfSSL_ERR_lib_error_string", + "const char* wolfSSL_ERR_lib_error_string(unsigned long)", + "const char* ERR_lib_error_string(unsigned long)"), + WolfFunction("wolfSSL_X509_EXTENSION_dup", + "WOLFSSL_X509_EXTENSION* wolfSSL_X509_EXTENSION_dup(WOLFSSL_X509_EXTENSION*)", + "X509_EXTENSION* X509_EXTENSION_dup(X509_EXTENSION*)") +] +optional_funcs = make_optional_func_list(libwolfssl_path, optional_funcs) + +source = """ + #include + #include +""" +ffi_source = source + openssl.source ffi = FFI() ffi.set_source( "wolfssl._ffi", - """ - #include - #include - """, + ffi_source, include_dirs=[wolfssl_inc_path()], library_dirs=[wolfssl_lib_path()], libraries=["wolfssl"], ) -ffi.cdef( - """ - +cdef = """ /** - * Structs + * Constants */ - typedef struct WOLFSSL_ALERT { - int code; - int level; - } WOLFSSL_ALERT; - - typedef struct WOLFSSL_ALERT_HISTORY { - WOLFSSL_ALERT last_rx; - WOLFSSL_ALERT last_tx; - } WOLFSSL_ALERT_HISTORY; + static const long SOCKET_PEER_CLOSED_E; /** * Types */ typedef unsigned char byte; typedef unsigned int word32; + + typedef ... WOLFSSL_CTX; + typedef ... WOLFSSL; + typedef ... WOLFSSL_X509; + typedef ... WOLFSSL_X509_EXTENSION; + typedef ... WOLFSSL_X509_STORE_CTX; + typedef ... WOLFSSL_X509_NAME; + typedef ... WOLFSSL_X509_NAME_ENTRY; + typedef ... WOLFSSL_ALERT_HISTORY; + typedef ... WOLFSSL_METHOD; + typedef ... WOLFSSL_ASN1_TIME; + typedef ... WOLFSSL_ASN1_GENERALIZEDTIME; + typedef ... WOLFSSL_ASN1_STRING; + typedef ... WOLFSSL_ASN1_OBJECT; + + typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); + typedef int pem_password_cb(char*, int, int, void*); + typedef int (*CallbackSniRecv)(WOLFSSL*, int*, void*); - typedef int pem_password_cb(char* passwd, int sz, int rw, void* userdata); /** - * Memory free function + * Memory */ void wolfSSL_Free(void*); + void wolfSSL_OPENSSL_free(void*); /** * Debugging @@ -76,63 +136,145 @@ ffi.cdef( /** * SSL/TLS Method functions */ - void* wolfTLSv1_1_server_method(void); - void* wolfTLSv1_1_client_method(void); + WOLFSSL_METHOD* wolfTLSv1_1_server_method(void); + WOLFSSL_METHOD* wolfTLSv1_1_client_method(void); - void* wolfTLSv1_2_server_method(void); - void* wolfTLSv1_2_client_method(void); + WOLFSSL_METHOD* wolfTLSv1_2_server_method(void); + WOLFSSL_METHOD* wolfTLSv1_2_client_method(void); - void* wolfSSLv23_server_method(void); - void* wolfSSLv23_client_method(void); + WOLFSSL_METHOD* wolfSSLv23_server_method(void); + WOLFSSL_METHOD* wolfSSLv23_client_method(void); + + WOLFSSL_METHOD* wolfSSLv23_method(void); + WOLFSSL_METHOD* wolfTLSv1_1_method(void); + WOLFSSL_METHOD* wolfTLSv1_2_method(void); /** * SSL/TLS Context functions */ - void* wolfSSL_CTX_new(void*); - void wolfSSL_CTX_free(void*); + WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); + void wolfSSL_CTX_free(WOLFSSL_CTX*); - void wolfSSL_CTX_set_verify(void*, int, void*); - int wolfSSL_CTX_set_cipher_list(void*, const char*); - int wolfSSL_CTX_use_PrivateKey_file(void*, const char*, int); - int wolfSSL_CTX_load_verify_locations(void*, const char*, const char*); - int wolfSSL_CTX_load_verify_buffer(void*, const unsigned char*, long,int); - int wolfSSL_CTX_use_certificate_chain_file(void*, const char *); - int wolfSSL_CTX_UseSNI(void*, unsigned char, const void*, unsigned short); - long wolfSSL_CTX_get_options(void*); - long wolfSSL_CTX_set_options(void*, long); - void wolfSSL_CTX_set_default_passwd_cb(void*, pem_password_cb*); + void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, VerifyCallback); + int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*); + int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); + int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, + const char*); + int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*, const unsigned char*, + long,int); + int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX*, const char *); + int wolfSSL_CTX_UseSNI(WOLFSSL_CTX*, unsigned char, const void*, + unsigned short); + long wolfSSL_CTX_get_options(WOLFSSL_CTX*); + long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long); + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, pem_password_cb*); + int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX*, + CallbackSniRecv); + long wolfSSL_CTX_set_mode(WOLFSSL_CTX*, long); /** * SSL/TLS Session functions */ - void* wolfSSL_new(void*); - void wolfSSL_free(void*); + WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); + void wolfSSL_free(WOLFSSL*); - int wolfSSL_set_fd(void*, int); - int wolfSSL_get_error(void*, int); - char* wolfSSL_ERR_error_string(int, char*); - int wolfSSL_negotiate(void*); - int wolfSSL_connect(void*); - int wolfSSL_accept(void*); - int wolfSSL_write(void*, const void*, int); - int wolfSSL_read(void*, void*, int); - int wolfSSL_pending(void*); - int wolfSSL_shutdown(void*); - void* wolfSSL_get_peer_certificate(void*); - int wolfSSL_UseSNI(void*, unsigned char, const void*, unsigned short); - int wolfSSL_check_domain_name(void*, const char*); - int wolfSSL_get_alert_history(void*, WOLFSSL_ALERT_HISTORY*); - const char* wolfSSL_alert_type_string_long(int); - const char* wolfSSL_alert_desc_string_long(int); + int wolfSSL_set_fd(WOLFSSL*, int); + int wolfSSL_get_error(WOLFSSL*, int); + char* wolfSSL_ERR_error_string(int, char*); + int wolfSSL_negotiate(WOLFSSL*); + int wolfSSL_connect(WOLFSSL*); + int wolfSSL_accept(WOLFSSL*); + int wolfSSL_write(WOLFSSL*, const void*, int); + int wolfSSL_read(WOLFSSL*, void*, int); + int wolfSSL_pending(WOLFSSL*); + int wolfSSL_shutdown(WOLFSSL*); + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL*); + int wolfSSL_UseSNI(WOLFSSL*, unsigned char, const void*, + unsigned short); + int wolfSSL_check_domain_name(WOLFSSL*, const char*); + int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY*); + const char* wolfSSL_get_servername(WOLFSSL*, unsigned char); + int wolfSSL_set_tlsext_host_name(WOLFSSL*, const char*); + long wolfSSL_ctrl(WOLFSSL*, int, long, void*); + void wolfSSL_set_connect_state(WOLFSSL*); /** * WOLFSSL_X509 functions */ - char* wolfSSL_X509_get_subjectCN(void*); - char* wolfSSL_X509_get_next_altname(void*); - const unsigned char* wolfSSL_X509_get_der(void*, int*); - """ -) + char* wolfSSL_X509_get_subjectCN(void*); + char* wolfSSL_X509_get_next_altname(void*); + const unsigned char* wolfSSL_X509_get_der(void*, int*); + WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( + WOLFSSL_X509_STORE_CTX*); + int wolfSSL_X509_up_ref(WOLFSSL_X509*); + void wolfSSL_X509_free(WOLFSSL_X509*); + int wolfSSL_X509_STORE_CTX_get_error( + WOLFSSL_X509_STORE_CTX*); + int wolfSSL_X509_STORE_CTX_get_error_depth( + WOLFSSL_X509_STORE_CTX*); + int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void); + void* wolfSSL_X509_STORE_CTX_get_ex_data( + WOLFSSL_X509_STORE_CTX*, int); + void wolfSSL_X509_STORE_CTX_set_error( + WOLFSSL_X509_STORE_CTX*, int); + WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509*); + char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, + char*, int); + WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notBefore(const WOLFSSL_X509*); + WOLFSSL_ASN1_TIME* wolfSSL_X509_get_notAfter(const WOLFSSL_X509*); + int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*); + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME*, int); + WOLFSSL_ASN1_OBJECT* wolfSSL_X509_NAME_ENTRY_get_object( + WOLFSSL_X509_NAME_ENTRY*); + WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*); + int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME*, int, + int); + int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME*, + const WOLFSSL_X509_NAME*); + int wolfSSL_X509_get_ext_count(const WOLFSSL_X509*); + WOLFSSL_X509_EXTENSION* wolfSSL_X509_get_ext(const WOLFSSL_X509*, int); + void wolfSSL_X509_EXTENSION_free( + WOLFSSL_X509_EXTENSION*); + WOLFSSL_ASN1_OBJECT* wolfSSL_X509_EXTENSION_get_object( + WOLFSSL_X509_EXTENSION*); + WOLFSSL_ASN1_STRING* wolfSSL_X509_EXTENSION_get_data( + WOLFSSL_X509_EXTENSION*); + WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509*); + + /** + * ASN.1 + */ + int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*); + int wolfSSL_ASN1_STRING_type(const WOLFSSL_ASN1_STRING*); + unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*); + WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME*, + WOLFSSL_ASN1_TIME**); + void wolfSSL_ASN1_GENERALIZEDTIME_free( + WOLFSSL_ASN1_GENERALIZEDTIME*); + void wolfSSL_ASN1_TIME_free(WOLFSSL_ASN1_TIME*); + int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME*); + unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME*); + int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **, + WOLFSSL_ASN1_STRING*); + + /** + * Misc. + */ + int wolfSSL_library_init(void); + const char* wolfSSL_alert_type_string_long(int); + const char* wolfSSL_alert_desc_string_long(int); + unsigned long wolfSSL_ERR_get_error(void); + const char* wolfSSL_ERR_reason_error_string(unsigned long); + int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT*); + const char* wolfSSL_OBJ_nid2sn(int n); + int wolfSSL_OBJ_txt2nid(const char*); +""" + +for func in optional_funcs: + cdef += "{};".format(func.native_sig) + +ffi_cdef = cdef + openssl.construct_cdef(optional_funcs) +ffi.cdef(ffi_cdef) if __name__ == "__main__": ffi.compile(verbose=True) diff --git a/src/wolfssl/_build_wolfssl.py b/src/wolfssl/_build_wolfssl.py index b600aae..1d5380c 100644 --- a/src/wolfssl/_build_wolfssl.py +++ b/src/wolfssl/_build_wolfssl.py @@ -21,6 +21,7 @@ import os import subprocess +import argparse from contextlib import contextmanager from distutils.util import get_platform from wolfssl.__about__ import __wolfssl_version__ as version @@ -86,14 +87,14 @@ def chdir(new_path, mkdir=False): os.chdir(old_path) -def clone_wolfssl(version): +def clone_wolfssl(ref): """ Clone wolfSSL C library repository """ call("git clone --depth=1 --branch={} {} {}".format( - version, WOLFSSL_GIT_ADDR, WOLFSSL_SRC_PATH)) + ref, WOLFSSL_GIT_ADDR, WOLFSSL_SRC_PATH)) -def checkout_version(version): +def checkout_ref(ref): """ Ensure that we have the right version """ with chdir(WOLFSSL_SRC_PATH): @@ -101,32 +102,32 @@ def checkout_version(version): ["git", "describe", "--all", "--exact-match"] ).strip().decode().split('/')[-1] - if current != version: + if current != ref: tags = subprocess.check_output( ["git", "tag"] ).strip().decode().split("\n") - if version != "master" and version not in tags: - call("git fetch --depth=1 origin tag {}".format(version)) + if ref != "master" and ref not in tags: + call("git fetch --depth=1 origin tag {}".format(ref)) - call("git checkout --force {}".format(version)) + call("git checkout --force {}".format(ref)) return True # rebuild needed return False -def ensure_wolfssl_src(version): +def ensure_wolfssl_src(ref): """ Ensure that wolfssl sources are presents and up-to-date """ if not os.path.isdir(WOLFSSL_SRC_PATH): - clone_wolfssl(version) + clone_wolfssl(ref) return True - return checkout_version(version) + return checkout_ref(ref) -def make_flags(prefix): +def make_flags(prefix, debug): """ Returns compilation flags """ flags = [] @@ -150,6 +151,16 @@ def make_flags(prefix): flags.append("--enable-opensslextra") cflags.append("-DKEEP_PEER_CERT") + # for pyOpenSSL + flags.append("--enable-secure-renegotiation") + flags.append("--enable-opensslall") + cflags.append("-DFP_MAX_BITS=8192") + cflags.append("-DHAVE_EX_DATA") + cflags.append("-DOPENSSL_COMPATIBLE_DEFAULTS") + + if debug: + flags.append("--enable-debug") + # Note: websocket-client test server (echo.websocket.org) only supports # TLS 1.2 with TLS_RSA_WITH_AES_128_CBC_SHA # If compiling for use with websocket-client, must enable static RSA suites. @@ -175,19 +186,27 @@ def make(configure_flags): call("./configure {}".format(configure_flags)) call("make") - call("make install-exec") + call("make install") -def build_wolfssl(version="master"): +def build_wolfssl(ref, debug=False): prefix = local_path("lib/wolfssl/{}/{}".format( - get_platform(), version)) + get_platform(), ref)) libfile = os.path.join(prefix, 'lib/libwolfssl.la') - rebuild = ensure_wolfssl_src(version) + rebuild = ensure_wolfssl_src(ref) if rebuild or not os.path.isfile(libfile): - make(make_flags(prefix)) + make(make_flags(prefix, debug)) if __name__ == "__main__": - build_wolfssl() + parser = argparse.ArgumentParser( + description="Build underlying wolfSSL library (libwolfssl).") + parser.add_argument("-d", "--debug", action="store_true", + help="Build libwolfssl with debug enabled.") + parser.add_argument("-r", '--ref', default="master", + help="Git ref to check out when cloning wolfSSL.") + args = parser.parse_args() + build_wolfssl(args.ref, args.debug) + diff --git a/src/wolfssl/_openssl.py b/src/wolfssl/_openssl.py new file mode 100644 index 0000000..2e09519 --- /dev/null +++ b/src/wolfssl/_openssl.py @@ -0,0 +1,294 @@ +# -*- coding: utf-8 -*- +# +# _openssl.py +# +# Copyright (C) 2006-2020 wolfSSL Inc. +# +# This file is part of wolfSSL. (formerly known as CyaSSL) +# +# wolfSSL is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# wolfSSL is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + +# pylint: disable=missing-docstring, invalid-name + +source = """ + #include + #include + #include + #include + #include + #include +""" + +def construct_cdef(optional_funcs): + cdef = """ + /** + * Constants + */ + static const long OPENSSL_VERSION_NUMBER; + static const long SSLEAY_VERSION; + + static const long SSL_FILETYPE_PEM; + static const long SSL_FILETYPE_ASN1; + + static const long EVP_PKEY_RSA; + static const long EVP_PKEY_DSA; + static const long EVP_PKEY_DH; + static const long EVP_PKEY_EC; + + static const long GEN_EMAIL; + static const long GEN_DNS; + static const long GEN_URI; + + static const long X509_V_FLAG_CRL_CHECK; + static const long X509_V_FLAG_CRL_CHECK_ALL; + static const long X509_V_OK; + + static const long SSL_SENT_SHUTDOWN; + static const long SSL_RECEIVED_SHUTDOWN; + + static const long SSL_OP_NO_SSLv2; + static const long SSL_OP_NO_SSLv3; + static const long SSL_OP_NO_TLSv1; + static const long SSL_OP_NO_TLSv1_1; + static const long SSL_OP_NO_TLSv1_2; + static const long SSL_MODE_RELEASE_BUFFERS; + static const long SSL_OP_SINGLE_DH_USE; + static const long SSL_OP_SINGLE_ECDH_USE; + static const long SSL_OP_EPHEMERAL_RSA; + static const long SSL_OP_MICROSOFT_SESS_ID_BUG; + static const long SSL_OP_NETSCAPE_CHALLENGE_BUG; + static const long SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; + static const long SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; + static const long SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; + static const long SSL_OP_MSIE_SSLV2_RSA_PADDING; + static const long SSL_OP_SSLEAY_080_CLIENT_DH_BUG; + static const long SSL_OP_TLS_D5_BUG; + static const long SSL_OP_TLS_BLOCK_PADDING_BUG; + static const long SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + static const long SSL_OP_CIPHER_SERVER_PREFERENCE; + static const long SSL_OP_TLS_ROLLBACK_BUG; + static const long SSL_OP_PKCS1_CHECK_1; + static const long SSL_OP_PKCS1_CHECK_2; + static const long SSL_OP_NETSCAPE_CA_DN_BUG; + static const long SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG; + static const long SSL_OP_NO_COMPRESSION; + static const long SSL_OP_NO_QUERY_MTU; + static const long SSL_OP_COOKIE_EXCHANGE; + static const long SSL_OP_NO_TICKET; + static const long SSL_OP_ALL; + static const long SSL_VERIFY_PEER; + static const long SSL_VERIFY_FAIL_IF_NO_PEER_CERT; + static const long SSL_VERIFY_CLIENT_ONCE; + static const long SSL_VERIFY_NONE; + static const long SSL_SESS_CACHE_OFF; + static const long SSL_SESS_CACHE_CLIENT; + static const long SSL_SESS_CACHE_SERVER; + static const long SSL_SESS_CACHE_BOTH; + static const long SSL_SESS_CACHE_NO_AUTO_CLEAR; + static const long SSL_SESS_CACHE_NO_INTERNAL_LOOKUP; + static const long SSL_SESS_CACHE_NO_INTERNAL_STORE; + static const long SSL_SESS_CACHE_NO_INTERNAL; + static const long SSL_ST_CONNECT; + static const long SSL_ST_ACCEPT; + static const long SSL_ST_MASK; + static const long SSL_CB_LOOP; + static const long SSL_CB_EXIT; + static const long SSL_CB_READ; + static const long SSL_CB_WRITE; + static const long SSL_CB_ALERT; + static const long SSL_CB_READ_ALERT; + static const long SSL_CB_WRITE_ALERT; + static const long SSL_CB_ACCEPT_LOOP; + static const long SSL_CB_ACCEPT_EXIT; + static const long SSL_CB_CONNECT_LOOP; + static const long SSL_CB_CONNECT_EXIT; + static const long SSL_CB_HANDSHAKE_START; + static const long SSL_CB_HANDSHAKE_DONE; + static const long SSL_MODE_ENABLE_PARTIAL_WRITE; + static const long SSL_MODE_AUTO_RETRY; + static const long SSL_ERROR_WANT_READ; + static const long SSL_ERROR_WANT_WRITE; + static const long SSL_ERROR_ZERO_RETURN; + static const long SSL_ERROR_WANT_X509_LOOKUP; + static const long SSL_ERROR_SYSCALL; + static const long SSL_ERROR_NONE; + + static const long V_ASN1_GENERALIZEDTIME; + + static const int NID_undef; + + /** + * Types + */ + typedef ... SSL_CTX; + typedef ... SSL; + typedef ... SSL_METHOD; + typedef ... X509; + typedef ... X509_EXTENSION; + typedef ... X509_STORE_CTX; + typedef ... X509_NAME; + typedef ... X509_NAME_ENTRY; + typedef ... BIO; + typedef ... BIO_METHOD; + typedef ... ASN1_TIME; + typedef ... ASN1_GENERALIZEDTIME; + typedef ... ASN1_STRING; + typedef ... ASN1_OCTET_STRING; + typedef ... ASN1_OBJECT; + + typedef int (*SSL_verify_cb)(int, X509_STORE_CTX*); + + /** + * ASN.1 + */ + int ASN1_STRING_set_default_mask_asc(const char*); + int ASN1_STRING_length(ASN1_STRING*); + int ASN1_STRING_type(const ASN1_STRING*); + unsigned char* ASN1_STRING_data(ASN1_STRING*); + ASN1_TIME* ASN1_TIME_to_generalizedtime(ASN1_TIME *t, + ASN1_GENERALIZEDTIME**); + void ASN1_GENERALIZEDTIME_free(ASN1_GENERALIZEDTIME*); + void ASN1_TIME_free(ASN1_TIME*); + int ASN1_STRING_to_UTF8(unsigned char**, ASN1_STRING*); + + /** + * Memory + */ + void OPENSSL_free(void*); + + /** + * SSL/TLS Method functions + */ + SSL_METHOD* TLSv1_1_server_method(void); + SSL_METHOD* TLSv1_1_client_method(void); + SSL_METHOD* TLSv1_2_server_method(void); + SSL_METHOD* TLSv1_2_client_method(void); + SSL_METHOD* SSLv23_server_method(void); + SSL_METHOD* SSLv23_client_method(void); + SSL_METHOD* SSLv23_method(void); + SSL_METHOD* TLSv1_1_method(void); + SSL_METHOD* TLSv1_2_method(void); + + /** + * SSL/TLS Context functions + */ + SSL_CTX* SSL_CTX_new(SSL_METHOD*); + void SSL_CTX_free(SSL_CTX*); + + int SSL_CTX_set_cipher_list(SSL_CTX*, const char*); + int SSL_CTX_use_PrivateKey_file(SSL_CTX*, const char*, int); + int SSL_CTX_load_verify_locations(SSL_CTX*, const char*, const char*); + void SSL_CTX_set_verify(SSL_CTX*, int, SSL_verify_cb); + void SSL_CTX_set_verify_depth(SSL_CTX*, int); + int SSL_CTX_get_verify_mode(const SSL_CTX*); + int SSL_CTX_use_certificate_file(SSL_CTX*, const char*, int); + int SSL_CTX_use_certificate_chain_file(SSL_CTX*, const char*); + long SSL_CTX_get_options(SSL_CTX*); + long SSL_CTX_set_options(SSL_CTX*, long); + void SSL_CTX_set_default_passwd_cb(SSL_CTX*, pem_password_cb*); + void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX*, void*); + void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX*, int (*)(SSL*, + const unsigned char **, unsigned int*, void*), void*); + void SSL_CTX_set_next_proto_select_cb(SSL_CTX*, int (*)(SSL*, unsigned char**, + unsigned char*, const unsigned char*, unsigned int, void*), void*); + int SSL_CTX_set_alpn_protos(SSL_CTX*, const unsigned char*, unsigned int); + void SSL_CTX_set_alpn_select_cb(SSL_CTX*, int (*)(SSL*, + const unsigned char**, unsigned char*, const unsigned char*, + unsigned int, void*), void*); + int SSL_CTX_set_tlsext_servername_callback(SSL_CTX*, CallbackSniRecv); + long SSL_CTX_set_mode(SSL_CTX*, long); + + /** + * SSL/TLS Session functions + */ + SSL* SSL_new(SSL_CTX*); + void SSL_free(SSL*); + int SSL_set_fd(SSL*, int); + int SSL_get_error(SSL*, int); + char* ERR_error_string(int, char*); + int SSL_connect(SSL*); + int SSL_accept(SSL*); + int SSL_write(SSL*, const void*, int); + int SSL_read(SSL*, void*, int); + int SSL_peek(SSL*, void*, int); + int SSL_pending(SSL*); + int SSL_shutdown(SSL*); + void SSL_set_shutdown(SSL*, int); + int SSL_get_shutdown(const SSL*); + X509* SSL_get_peer_certificate(SSL*); + const char* SSL_alert_type_string_long(int); + const char* SSL_alert_desc_string_long(int); + int SSL_renegotiate(SSL*); + void SSL_get0_next_proto_negotiated(const SSL*, + const unsigned char**, unsigned*); + const char* SSL_get_servername(SSL*, unsigned char); + int SSL_set_tlsext_host_name(SSL*, const char*); + int SSL_set_alpn_protos(SSL*, const unsigned char*, unsigned int); + void SSL_get0_alpn_selected(const SSL*, const unsigned char**, + unsigned int*); + unsigned long SSL_set_mode(SSL*, unsigned long); + void SSL_set_connect_state(SSL*); + + /** + * X509 functions + */ + X509* X509_STORE_CTX_get_current_cert(X509_STORE_CTX*); + int X509_up_ref(X509*); + void X509_free(X509*); + int X509_STORE_CTX_get_error(X509_STORE_CTX*); + int X509_STORE_CTX_get_error_depth(X509_STORE_CTX*); + int SSL_get_ex_data_X509_STORE_CTX_idx(void); + void* X509_STORE_CTX_get_ex_data(X509_STORE_CTX*, int); + void X509_STORE_CTX_set_error(X509_STORE_CTX*, int); + X509_NAME* X509_get_subject_name(X509*); + char* X509_NAME_oneline(X509_NAME*, char*, int); + ASN1_TIME* X509_get_notBefore(const X509*); + ASN1_TIME* X509_get_notAfter(const X509*); + int X509_NAME_entry_count(X509_NAME*); + X509_NAME_ENTRY* X509_NAME_get_entry(X509_NAME*, int); + ASN1_OBJECT* X509_NAME_ENTRY_get_object(X509_NAME_ENTRY*); + ASN1_STRING* X509_NAME_ENTRY_get_data(X509_NAME_ENTRY*); + int X509_NAME_get_index_by_NID(X509_NAME*, int, int); + int X509_NAME_cmp(const X509_NAME*, const X509_NAME*); + int X509_get_ext_count(const X509 *x); + X509_EXTENSION* X509_get_ext(const X509*, int loc); + void X509_EXTENSION_free(X509_EXTENSION*); + ASN1_OBJECT* X509_EXTENSION_get_object(X509_EXTENSION*); + ASN1_OCTET_STRING* X509_EXTENSION_get_data(X509_EXTENSION*); + X509* X509_dup(X509*); + + /** + * BIO functions + */ + BIO* BIO_new(BIO_METHOD*); + BIO_METHOD* BIO_s_mem(void); + + /** + * Misc. + */ + int OpenSSL_add_all_algorithms(void); + void SSL_load_error_strings(void); + int SSL_library_init(void); + unsigned long ERR_get_error(void); + const char* ERR_reason_error_string(unsigned long); + int OBJ_obj2nid(const ASN1_OBJECT*); + const char* OBJ_nid2sn(int n); + int OBJ_txt2nid(const char*); + """ + + for func in optional_funcs: + cdef += "{};".format(func.ossl_sig) + + return cdef