diff options
-rw-r--r-- | .travis.yml | 2 | ||||
-rwxr-xr-x | .travis/install.sh | 6 | ||||
-rwxr-xr-x | .travis/openssl_config.sh | 13 | ||||
-rwxr-xr-x | .travis/run.sh | 11 | ||||
-rw-r--r-- | CHANGELOG.rst | 5 | ||||
-rw-r--r-- | src/_cffi_src/openssl/engine.py | 68 | ||||
-rw-r--r-- | src/_cffi_src/openssl/ssl.py | 1 | ||||
-rw-r--r-- | src/cryptography/hazmat/backends/openssl/backend.py | 17 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/_conditional.py | 42 | ||||
-rw-r--r-- | src/cryptography/hazmat/bindings/openssl/binding.py | 5 | ||||
-rw-r--r-- | tests/hazmat/backends/test_openssl.py | 3 |
11 files changed, 155 insertions, 18 deletions
diff --git a/.travis.yml b/.travis.yml index 7ed660a8..fa45f134 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,6 +52,8 @@ matrix: - python: 3.7 env: TOXENV=py37 OPENSSL=1.1.1a - python: 3.7 + env: TOXENV=py37 OPENSSL=1.1.1a OPENSSL_CONFIG_FLAGS=no-engine + - python: 3.7 env: TOXENV=py37 LIBRESSL=2.6.5 - python: 3.7 env: TOXENV=py37 LIBRESSL=2.7.5 diff --git a/.travis/install.sh b/.travis/install.sh index a4bc3c97..ed69e468 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -3,6 +3,8 @@ set -e set -x +SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") + shlib_sed() { # modify the shlib version to a unique one to make sure the dynamic # linker doesn't load the system one. @@ -14,12 +16,12 @@ shlib_sed() { # download, compile, and install if it's not already present via travis # cache if [ -n "${OPENSSL}" ]; then - OPENSSL_DIR="ossl-2/${OPENSSL}" + . "$SCRIPT_DIR/openssl_config.sh" if [[ ! -f "$HOME/$OPENSSL_DIR/bin/openssl" ]]; then curl -O "https://www.openssl.org/source/openssl-${OPENSSL}.tar.gz" tar zxf "openssl-${OPENSSL}.tar.gz" pushd "openssl-${OPENSSL}" - ./config shared no-ssl2 no-ssl3 -fPIC --prefix="$HOME/$OPENSSL_DIR" + ./config $OPENSSL_CONFIG_FLAGS -fPIC --prefix="$HOME/$OPENSSL_DIR" shlib_sed make depend make -j"$(nproc)" diff --git a/.travis/openssl_config.sh b/.travis/openssl_config.sh new file mode 100755 index 00000000..83f16d2b --- /dev/null +++ b/.travis/openssl_config.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +set -e +set -x + +DEFAULT_CONFIG_FLAGS="shared no-ssl2 no-ssl3" +if [ -n "${OPENSSL_CONFIG_FLAGS}" ]; then + OPENSSL_CONFIG_FLAGS="$DEFAULT_CONFIG_FLAGS $OPENSSL_CONFIG_FLAGS" +else + OPENSSL_CONFIG_FLAGS=$DEFAULT_CONFIG_FLAGS +fi +CONFIG_HASH=$(echo "$OPENSSL_CONFIG_FLAGS" | sha1sum | sed 's/ .*$//') +OPENSSL_DIR="ossl-2/${OPENSSL}${CONFIG_HASH}" diff --git a/.travis/run.sh b/.travis/run.sh index 8f8dd687..ab12ac3c 100755 --- a/.travis/run.sh +++ b/.travis/run.sh @@ -1,18 +1,21 @@ #!/bin/bash -ex +SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") + if [[ "${TOXENV}" == "pypy" ]]; then PYENV_ROOT="$HOME/.pyenv" PATH="$PYENV_ROOT/bin:$PATH" eval "$(pyenv init -)" fi if [ -n "${LIBRESSL}" ]; then - OPENSSL=$LIBRESSL - export CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=discarded-qualifiers -Wno-error=unused-function" + LIBRESSL_DIR="ossl-2/${LIBRESSL}" + export CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=discarded-qualifiers -Wno-error=unused-function -I$HOME/$LIBRESSL_DIR/include" + export PATH="$HOME/$LIBRESSL_DIR/bin:$PATH" + export LDFLAGS="-L$HOME/$LIBRESSL_DIR/lib -Wl,-rpath=$HOME/$LIBRESSL_DIR/lib" fi if [ -n "${OPENSSL}" ]; then - OPENSSL_DIR="ossl-2/${OPENSSL}" - + . "$SCRIPT_DIR/openssl_config.sh" export PATH="$HOME/$OPENSSL_DIR/bin:$PATH" export CFLAGS="${CFLAGS} -I$HOME/$OPENSSL_DIR/include" # rpath on linux will cause it to use an absolute path so we don't need to diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e4c747c8..7c3f3bfe 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -21,7 +21,10 @@ Changelog which had been deprecated for nearly 3 years. Use :attr:`~cryptography.x509.Certificate.serial_number` instead. * Add support for easily mapping an object identifier to its elliptic curve - class via :func:`~cryptography.hazmat.primitives.asymmetric.ec.get_curve_for_oid`. + class via + :func:`~cryptography.hazmat.primitives.asymmetric.ec.get_curve_for_oid`. +* Add support for OpenSSL when compiled with the ``no-engine`` + (``OPENSSL_NO_ENGINE``) flag. .. _v2-5: diff --git a/src/_cffi_src/openssl/engine.py b/src/_cffi_src/openssl/engine.py index c255bbbc..8996f0c8 100644 --- a/src/_cffi_src/openssl/engine.py +++ b/src/_cffi_src/openssl/engine.py @@ -27,6 +27,7 @@ typedef ... UI_METHOD; static const unsigned int ENGINE_METHOD_RAND; static const int ENGINE_R_CONFLICTING_ENGINE_ID; +static const long Cryptography_HAS_ENGINE; """ FUNCTIONS = """ @@ -69,4 +70,71 @@ void ENGINE_cleanup(void); """ CUSTOMIZATIONS = """ +#ifdef OPENSSL_NO_ENGINE +static const long Cryptography_HAS_ENGINE = 0; +typedef int (*ENGINE_GEN_INT_FUNC_PTR)(ENGINE *); +typedef void *ENGINE_CTRL_FUNC_PTR; +typedef void *ENGINE_LOAD_KEY_PTR; +typedef void *ENGINE_CIPHERS_PTR; +typedef void *ENGINE_DIGESTS_PTR; +typedef struct ENGINE_CMD_DEFN_st { + unsigned int cmd_num; + const char *cmd_name; + const char *cmd_desc; + unsigned int cmd_flags; +} ENGINE_CMD_DEFN; + +/* This section is so osrandom_engine.c can successfully compile even + when engine support is disabled */ +#define ENGINE_CMD_BASE 0 +#define ENGINE_CMD_FLAG_NO_INPUT 0 +#define ENGINE_F_ENGINE_CTRL 0 +#define ENGINE_R_INVALID_ARGUMENT 0 +#define ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED 0 +int (*ENGINE_set_cmd_defns)(ENGINE *, const ENGINE_CMD_DEFN *) = NULL; + +static const unsigned int ENGINE_METHOD_RAND = 0; +static const int ENGINE_R_CONFLICTING_ENGINE_ID = 0; + +ENGINE *(*ENGINE_get_first)(void) = NULL; +ENGINE *(*ENGINE_get_last)(void) = NULL; +int (*ENGINE_add)(ENGINE *) = NULL; +int (*ENGINE_remove)(ENGINE *) = NULL; +ENGINE *(*ENGINE_by_id)(const char *) = NULL; +int (*ENGINE_init)(ENGINE *) = NULL; +int (*ENGINE_finish)(ENGINE *) = NULL; +void (*ENGINE_load_builtin_engines)(void) = NULL; +ENGINE *(*ENGINE_get_default_RAND)(void) = NULL; +int (*ENGINE_set_default_RAND)(ENGINE *) = NULL; +int (*ENGINE_register_RAND)(ENGINE *) = NULL; +void (*ENGINE_unregister_RAND)(ENGINE *) = NULL; +void (*ENGINE_register_all_RAND)(void) = NULL; +int (*ENGINE_ctrl)(ENGINE *, int, long, void *, void (*)(void)) = NULL; +int (*ENGINE_ctrl_cmd)(ENGINE *, const char *, long, void *, + void (*)(void), int) = NULL; +int (*ENGINE_ctrl_cmd_string)(ENGINE *, const char *, const char *, + int) = NULL; + +ENGINE *(*ENGINE_new)(void) = NULL; +int (*ENGINE_free)(ENGINE *) = NULL; +int (*ENGINE_up_ref)(ENGINE *) = NULL; +int (*ENGINE_set_id)(ENGINE *, const char *) = NULL; +int (*ENGINE_set_name)(ENGINE *, const char *) = NULL; +int (*ENGINE_set_RAND)(ENGINE *, const RAND_METHOD *) = NULL; +int (*ENGINE_set_destroy_function)(ENGINE *, ENGINE_GEN_INT_FUNC_PTR) = NULL; +int (*ENGINE_set_init_function)(ENGINE *, ENGINE_GEN_INT_FUNC_PTR) = NULL; +int (*ENGINE_set_finish_function)(ENGINE *, ENGINE_GEN_INT_FUNC_PTR) = NULL; +int (*ENGINE_set_ctrl_function)(ENGINE *, ENGINE_CTRL_FUNC_PTR) = NULL; +const char *(*ENGINE_get_id)(const ENGINE *) = NULL; +const char *(*ENGINE_get_name)(const ENGINE *) = NULL; +const RAND_METHOD *(*ENGINE_get_RAND)(const ENGINE *) = NULL; + +void (*ENGINE_add_conf_module)(void) = NULL; +/* these became macros in 1.1.0 */ +void (*ENGINE_load_openssl)(void) = NULL; +void (*ENGINE_load_dynamic)(void) = NULL; +void (*ENGINE_cleanup)(void) = NULL; +#else +static const long Cryptography_HAS_ENGINE = 1; +#endif """ diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 2218095c..92fd1e3e 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -334,7 +334,6 @@ int SSL_SESSION_print(BIO *, const SSL_SESSION *); const COMP_METHOD *SSL_get_current_compression(SSL *); const COMP_METHOD *SSL_get_current_expansion(SSL *); const char *SSL_COMP_get_name(const COMP_METHOD *); -int SSL_CTX_set_client_cert_engine(SSL_CTX *, ENGINE *); unsigned long SSL_set_mode(SSL *, unsigned long); unsigned long SSL_get_mode(SSL *); diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 73491726..d7bba224 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -150,14 +150,15 @@ class Backend(object): self.openssl_assert(res == 1) def activate_osrandom_engine(self): - # Unregister and free the current engine. - self.activate_builtin_random() - with self._get_osurandom_engine() as e: - # Set the engine as the default RAND provider. - res = self._lib.ENGINE_set_default_RAND(e) - self.openssl_assert(res == 1) - # Reset the RNG to use the new engine. - self._lib.RAND_cleanup() + if self._lib.Cryptography_HAS_ENGINE: + # Unregister and free the current engine. + self.activate_builtin_random() + with self._get_osurandom_engine() as e: + # Set the engine as the default RAND provider. + res = self._lib.ENGINE_set_default_RAND(e) + self.openssl_assert(res == 1) + # Reset the RNG to use the new engine. + self._lib.RAND_cleanup() def osrandom_engine_implementation(self): buf = self._ffi.new("char[]", 64) diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index c0238dcc..3fecfe59 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -341,6 +341,47 @@ def cryptography_has_evp_r_memory_limit_exceeded(): ] +def cryptography_has_engine(): + return [ + "ENGINE_get_first", + "ENGINE_get_last", + "ENGINE_add", + "ENGINE_remove", + "ENGINE_by_id", + "ENGINE_init", + "ENGINE_finish", + "ENGINE_load_builtin_engines", + "ENGINE_get_default_RAND", + "ENGINE_set_default_RAND", + "ENGINE_register_RAND", + "ENGINE_unregister_RAND", + "ENGINE_register_all_RAND", + "ENGINE_ctrl", + "ENGINE_ctrl_cmd", + "ENGINE_ctrl_cmd_string", + "ENGINE_new", + "ENGINE_free", + "ENGINE_up_ref", + "ENGINE_set_id", + "ENGINE_set_name", + "ENGINE_set_RAND", + "ENGINE_set_destroy_function", + "ENGINE_set_init_function", + "ENGINE_set_finish_function", + "ENGINE_set_ctrl_function", + "ENGINE_get_id", + "ENGINE_get_name", + "ENGINE_get_RAND", + "ENGINE_add_conf_module", + "ENGINE_load_openssl", + "ENGINE_load_dynamic", + "ENGINE_cleanup", + "ENGINE_METHOD_RAND", + "ENGINE_R_CONFLICTING_ENGINE_ID", + "Cryptography_add_osrandom_engine", + ] + + # This is a mapping of # {condition: function-returning-names-dependent-on-that-condition} so we can # loop over them and delete unsupported names at runtime. It will be removed @@ -412,4 +453,5 @@ CONDITIONAL_NAMES = { "Cryptography_HAS_EVP_R_MEMORY_LIMIT_EXCEEDED": ( cryptography_has_evp_r_memory_limit_exceeded ), + "Cryptography_HAS_ENGINE": cryptography_has_engine, } diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index c937afd4..ca4e33fa 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -115,8 +115,9 @@ class Binding(object): # reliably clear the error queue. Once we clear it here we will # error on any subsequent unexpected item in the stack. cls.lib.ERR_clear_error() - result = cls.lib.Cryptography_add_osrandom_engine() - _openssl_assert(cls.lib, result in (1, 2)) + if cls.lib.Cryptography_HAS_ENGINE: + result = cls.lib.Cryptography_add_osrandom_engine() + _openssl_assert(cls.lib, result in (1, 2)) @classmethod def _ensure_ffi_initialized(cls): diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 6768e70f..20923792 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -170,6 +170,9 @@ class TestOpenSSL(object): assert backend._bn_to_int(bn) == 0 +@pytest.mark.skipif( + backend._lib.Cryptography_HAS_ENGINE == 0, + reason="Requires OpenSSL with ENGINE support") class TestOpenSSLRandomEngine(object): def setup(self): # The default RAND engine is global and shared between |