diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 504acdb56bd0..1824b269aa9b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -136,7 +136,6 @@ jobs: - {IMAGE: "bullseye", TOXENV: "py39", RUNNER: "ubuntu-latest"} - {IMAGE: "bookworm", TOXENV: "py311", RUNNER: "ubuntu-latest"} - {IMAGE: "sid", TOXENV: "py311", RUNNER: "ubuntu-latest"} - - {IMAGE: "ubuntu-bionic", TOXENV: "py36", RUNNER: "ubuntu-latest"} - {IMAGE: "ubuntu-focal", TOXENV: "py38", RUNNER: "ubuntu-latest"} - {IMAGE: "ubuntu-jammy", TOXENV: "py310", RUNNER: "ubuntu-latest"} - {IMAGE: "ubuntu-rolling", TOXENV: "py310", RUNNER: "ubuntu-latest"} @@ -182,7 +181,6 @@ jobs: run: mkdir -p "${HOME}/.cache/pip" - run: | echo "OPENSSL_FORCE_FIPS_MODE=1" >> $GITHUB_ENV - echo "CFLAGS=-DUSE_OSRANDOM_RNG_FOR_TESTING" >> $GITHUB_ENV if: matrix.IMAGE.FIPS - run: /venv/bin/python -m pip install -c ci-constraints-requirements.txt 'tox>3' coverage - run: '/venv/bin/tox -vvv --notest' @@ -373,11 +371,11 @@ jobs: - {OS: 'macos-12', ARCH: 'x86_64'} - {OS: [self-hosted, macos, ARM64, tart], ARCH: 'arm64'} PYTHON: - - {VERSION: "3.6", TOXENV: "py36-nocoverage", EXTRA_CFLAGS: ""} - - {VERSION: "3.11", TOXENV: "py311", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} + - {VERSION: "3.6", TOXENV: "py36-nocoverage"} + - {VERSION: "3.11", TOXENV: "py311"} exclude: # We only test latest Python on arm64. The py36 won't work since there's no universal2 binary - - PYTHON: {VERSION: "3.6", TOXENV: "py36-nocoverage", EXTRA_CFLAGS: ""} + - PYTHON: {VERSION: "3.6", TOXENV: "py36-nocoverage"} RUNNER: {OS: [self-hosted, macos, ARM64, tart], ARCH: 'arm64'} name: "${{ matrix.PYTHON.TOXENV }} on macOS ${{ matrix.RUNNER.ARCH }}" timeout-minutes: 15 @@ -420,11 +418,10 @@ jobs: run: | OPENSSL_DIR=$(readlink -f ../openssl-macos-universal2/) \ OPENSSL_STATIC=1 \ - CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -mmacosx-version-min=10.12 $EXTRA_CFLAGS" \ + CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -mmacosx-version-min=10.12" \ tox -vvv --notest env: TOXENV: ${{ matrix.PYTHON.TOXENV }} - EXTRA_CFLAGS: ${{ matrix.PYTHON.EXTRA_CFLAGS }} CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - name: Tests run: tox --skip-pkg-install -- --color=yes --wycheproof-root=wycheproof @@ -443,8 +440,8 @@ jobs: - {ARCH: 'x86', WINDOWS: 'win32'} - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - - {VERSION: "3.6", TOXENV: "py36-nocoverage", CL_FLAGS: ""} - - {VERSION: "3.11", TOXENV: "py311", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} + - {VERSION: "3.6", TOXENV: "py36-nocoverage"} + - {VERSION: "3.11", TOXENV: "py311"} JOB_NUMBER: [0, 1] name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 15 @@ -481,7 +478,6 @@ jobs: - name: Configure run: | echo "OPENSSL_DIR=C:/openssl-${{ matrix.WINDOWS.WINDOWS }}" >> $GITHUB_ENV - echo "CL=${{ matrix.PYTHON.CL_FLAGS }}" >> $GITHUB_ENV shell: bash - name: Clone wycheproof diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 5afb57d52a33..40426a6745a0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,9 @@ Changelog .. note:: This version is not yet released and is under active development. +* **BACKWARDS INCOMPATIBLE:** Support for OpenSSL less than 1.1.1d has been + removed. Users on older version of OpenSSL will need to upgrade. + .. _v40-0-0: 40.0.0 - 2023-03-24 diff --git a/LICENSE b/LICENSE index 07074259b61a..b11f379efe15 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,3 @@ This software is made available under the terms of *either* of the licenses found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made under the terms of *both* these licenses. - -The code used in the OS random engine is derived from CPython, and is licensed -under the terms of the PSF License Agreement. diff --git a/LICENSE.PSF b/LICENSE.PSF deleted file mode 100644 index 4d3a4f57dea9..000000000000 --- a/LICENSE.PSF +++ /dev/null @@ -1,41 +0,0 @@ -1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and - the Individual or Organization ("Licensee") accessing and otherwise using Python - 2.7.12 software in source or binary form and its associated documentation. - -2. Subject to the terms and conditions of this License Agreement, PSF hereby - grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, - analyze, test, perform and/or display publicly, prepare derivative works, - distribute, and otherwise use Python 2.7.12 alone or in any derivative - version, provided, however, that PSF's License Agreement and PSF's notice of - copyright, i.e., "Copyright © 2001-2016 Python Software Foundation; All Rights - Reserved" are retained in Python 2.7.12 alone or in any derivative version - prepared by Licensee. - -3. In the event Licensee prepares a derivative work that is based on or - incorporates Python 2.7.12 or any part thereof, and wants to make the - derivative work available to others as provided herein, then Licensee hereby - agrees to include in any such work a brief summary of the changes made to Python - 2.7.12. - -4. PSF is making Python 2.7.12 available to Licensee on an "AS IS" basis. - PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF - EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR - WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE - USE OF PYTHON 2.7.12 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. - -5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 2.7.12 - FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF - MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 2.7.12, OR ANY DERIVATIVE - THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. - -6. This License Agreement will automatically terminate upon a material breach of - its terms and conditions. - -7. Nothing in this License Agreement shall be deemed to create any relationship - of agency, partnership, or joint venture between PSF and Licensee. This License - Agreement does not grant permission to use PSF trademarks or trade name in a - trademark sense to endorse or promote products or services of Licensee, or any - third party. - -8. By copying, installing or otherwise using Python 2.7.12, Licensee agrees - to be bound by the terms and conditions of this License Agreement. diff --git a/MANIFEST.in b/MANIFEST.in index 995e3b0cedc2..c171033124b4 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,7 +3,6 @@ include CONTRIBUTING.rst include LICENSE include LICENSE.APACHE include LICENSE.BSD -include LICENSE.PSF include README.rst include tox.ini diff --git a/docs/openssl.rst b/docs/openssl.rst index edf185d2e10e..d4e69f4c86f6 100644 --- a/docs/openssl.rst +++ b/docs/openssl.rst @@ -10,8 +10,8 @@ A list of supported versions can be found in our :doc:`/installation` documentation. In general the backend should be considered an internal implementation detail -of the project, but there are some public methods available for more advanced -control. +of the project, but there are some public methods available for debugging +purposes. .. data:: cryptography.hazmat.backends.openssl.backend @@ -29,21 +29,6 @@ control. typically shown in hexadecimal (e.g. ``0x1010003f``). This is not necessarily the same version as it was compiled against. - .. method:: activate_osrandom_engine() - - Activates the OS random engine. This will effectively disable OpenSSL's - default CSPRNG. - - .. method:: osrandom_engine_implementation() - - .. versionadded:: 1.7 - - Returns the implementation of OS random engine. - - .. method:: activate_builtin_random() - - This will activate the default OpenSSL CSPRNG. - .. _legacy-provider: Legacy provider in OpenSSL 3.x @@ -56,68 +41,5 @@ disable the legacy provider in OpenSSL 3.x. This will disable legacy cryptographic algorithms, including ``Blowfish``, ``CAST5``, ``SEED``, ``ARC4``, and ``RC2`` (which is used by some encrypted serialization formats). -OS random engine ----------------- - -.. note:: - - As of OpenSSL 1.1.1d its CSPRNG is fork-safe by default. - ``cryptography`` does not compile or load the custom engine on - >= 1.1.1d. - -By default OpenSSL uses a user-space CSPRNG that is seeded from system random ( -``/dev/urandom`` or ``CryptGenRandom``). This CSPRNG is not reseeded -automatically when a process calls ``fork()``. This can result in situations -where two different processes can return similar or identical keys and -compromise the security of the system. - -The approach this project has chosen to mitigate this vulnerability is to -include an engine that replaces the OpenSSL default CSPRNG with one that -sources its entropy from ``/dev/urandom`` on UNIX-like operating systems and -uses ``CryptGenRandom`` on Windows. This method of pulling from the system pool -allows us to avoid potential issues with `initializing the RNG`_ as well as -protecting us from the ``fork()`` weakness. - -This engine is **active** by default when importing the OpenSSL backend. When -active this engine will be used to generate all the random data OpenSSL -requests. - -When importing only the binding it is added to the engine list but -**not activated**. - - -OS random sources ------------------ - -On macOS and FreeBSD ``/dev/urandom`` is an alias for ``/dev/random``. The -implementation on macOS uses the `Yarrow`_ algorithm. FreeBSD uses the -`Fortuna`_ algorithm. - -On Windows the implementation of ``CryptGenRandom`` depends on which version of -the operation system you are using. See the `Microsoft documentation`_ for more -details. - -Linux uses its own PRNG design. ``/dev/urandom`` is a non-blocking source -seeded from the same pool as ``/dev/random``. - -+------------------------------------------+------------------------------+ -| Windows | ``CryptGenRandom()`` | -+------------------------------------------+------------------------------+ -| Linux >= 3.17 with working | ``getrandom()`` | -| ``SYS_getrandom`` syscall | | -+------------------------------------------+------------------------------+ -| OpenBSD >= 5.6 | ``getentropy()`` | -+------------------------------------------+------------------------------+ -| BSD family (including macOS 10.12+) with | ``getentropy()`` | -| ``SYS_getentropy`` in ``sys/syscall.h`` | | -+------------------------------------------+------------------------------+ -| fallback | ``/dev/urandom`` with | -| | cached file descriptor | -+------------------------------------------+------------------------------+ - .. _`OpenSSL`: https://www.openssl.org/ -.. _`initializing the RNG`: https://en.wikipedia.org/wiki/OpenSSL#Predictable_private_keys_.28Debian-specific.29 -.. _`Fortuna`: https://en.wikipedia.org/wiki/Fortuna_(PRNG) -.. _`Yarrow`: https://en.wikipedia.org/wiki/Yarrow_algorithm -.. _`Microsoft documentation`: https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom diff --git a/setup.cfg b/setup.cfg index 172ac932ae31..416206fb271a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -4,7 +4,7 @@ version = attr: cryptography.__version__ description = cryptography is a package which provides cryptographic recipes and primitives to Python developers. long_description = file: README.rst long_description_content_type = text/x-rst -license = (Apache-2.0 OR BSD-3-Clause) AND PSF-2.0 +license = Apache-2.0 OR BSD-3-Clause url = https://github.com/pyca/cryptography author = The Python Cryptographic Authority and individual contributors author_email = cryptography-dev@python.org diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 5f191ce2ed40..e971fd955882 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -100,7 +100,6 @@ def _extra_compile_args(platform): "nid", "objects", "opensslv", - "osrandom_engine", "pem", "pkcs12", "rand", diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 6a79091c81c4..40e6ce9846fd 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -52,40 +52,25 @@ #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370 (0) #endif -#if OPENSSL_VERSION_NUMBER < 0x10101000 - #error "pyca/cryptography MUST be linked with Openssl 1.1.1 or later" +#if OPENSSL_VERSION_NUMBER < 0x10101040 + #error "pyca/cryptography MUST be linked with Openssl 1.1.1d or later" #endif -#define CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER \ - (OPENSSL_VERSION_NUMBER >= 0x10101040 && !CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_300_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x30000000 && !CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B \ - (OPENSSL_VERSION_NUMBER < 0x10101020 || CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D \ - (OPENSSL_VERSION_NUMBER < 0x10101040 || CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111E \ (OPENSSL_VERSION_NUMBER < 0x10101050 || CRYPTOGRAPHY_IS_LIBRESSL) -#if (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D && !CRYPTOGRAPHY_IS_LIBRESSL && \ - !defined(OPENSSL_NO_ENGINE)) || defined(USE_OSRANDOM_RNG_FOR_TESTING) -#define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 1 -#else -#define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 0 -#endif -/* Ed25519 support is available from OpenSSL 1.1.1b and LibreSSL 3.7.0. */ +/* Ed25519 support is in all supported OpenSSLs as well as LibreSSL 3.7.0. */ #define CRYPTOGRAPHY_HAS_WORKING_ED25519 \ - (!CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B || \ + (!CRYPTOGRAPHY_IS_LIBRESSL || \ (CRYPTOGRAPHY_IS_LIBRESSL && !CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370)) """ TYPES = """ -static const int CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER; static const int CRYPTOGRAPHY_OPENSSL_300_OR_GREATER; -static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111E; -static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE; static const int CRYPTOGRAPHY_HAS_WORKING_ED25519; static const int CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370; diff --git a/src/_cffi_src/openssl/err.py b/src/_cffi_src/openssl/err.py index be8c0774c945..ebe6c3559837 100644 --- a/src/_cffi_src/openssl/err.py +++ b/src/_cffi_src/openssl/err.py @@ -49,7 +49,7 @@ #define ERR_LIB_PROV 0 #endif -#if !CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER || CRYPTOGRAPHY_IS_BORINGSSL +#ifndef EVP_R_XTS_DUPLICATED_KEYS static const int EVP_R_XTS_DUPLICATED_KEYS = 0; #endif diff --git a/src/_cffi_src/openssl/osrandom_engine.py b/src/_cffi_src/openssl/osrandom_engine.py deleted file mode 100644 index dbc304b399c7..000000000000 --- a/src/_cffi_src/openssl/osrandom_engine.py +++ /dev/null @@ -1,23 +0,0 @@ -# This file is dual licensed under the terms of the Apache License, Version -# 2.0, and the BSD License. See the LICENSE file in the root of this repository -# for complete details. - - -import os - -HERE = os.path.dirname(os.path.abspath(__file__)) - -with open(os.path.join(HERE, "src/osrandom_engine.h")) as f: - INCLUDES = f.read() - -TYPES = """ -static const char *const Cryptography_osrandom_engine_name; -static const char *const Cryptography_osrandom_engine_id; -""" - -FUNCTIONS = """ -int Cryptography_add_osrandom_engine(void); -""" - -with open(os.path.join(HERE, "src/osrandom_engine.c")) as f: - CUSTOMIZATIONS = f.read() diff --git a/src/_cffi_src/openssl/src/osrandom_engine.c b/src/_cffi_src/openssl/src/osrandom_engine.c deleted file mode 100644 index 257fcd50968f..000000000000 --- a/src/_cffi_src/openssl/src/osrandom_engine.c +++ /dev/null @@ -1,627 +0,0 @@ -/* osurandom engine - * - * Windows CryptGenRandom() - * macOS >= 10.12 getentropy() - * OpenBSD 5.6+ getentropy() - * other BSD getentropy() if SYS_getentropy is defined - * Linux 3.17+ getrandom() with fallback to /dev/urandom - * other /dev/urandom with cached fd - * - * The /dev/urandom, getrandom and getentropy code is derived from Python's - * Python/random.c, written by Antoine Pitrou and Victor Stinner. - * - * Copyright 2001-2016 Python Software Foundation; All Rights Reserved. - */ - -#ifdef __linux__ -#include -#endif - -#if CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE -/* OpenSSL has ENGINE support and is older than 1.1.1d (the first version that - * properly implements fork safety in its RNG) so build the engine. */ -static const char *Cryptography_osrandom_engine_id = "osrandom"; - -/**************************************************************************** - * Windows - */ -#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM -static const char *Cryptography_osrandom_engine_name = "osrandom_engine CryptGenRandom()"; -static HCRYPTPROV hCryptProv = 0; - -static int osrandom_init(ENGINE *e) { - if (hCryptProv != 0) { - return 1; - } - if (CryptAcquireContext(&hCryptProv, NULL, NULL, - PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - return 1; - } else { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_INIT, - CRYPTOGRAPHY_OSRANDOM_R_CRYPTACQUIRECONTEXT, - __FILE__, __LINE__ - ); - return 0; - } -} - -static int osrandom_rand_bytes(unsigned char *buffer, int size) { - if (hCryptProv == 0) { - return 0; - } - - if (!CryptGenRandom(hCryptProv, (DWORD)size, buffer)) { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, - CRYPTOGRAPHY_OSRANDOM_R_CRYPTGENRANDOM, - __FILE__, __LINE__ - ); - return 0; - } - return 1; -} - -static int osrandom_finish(ENGINE *e) { - if (CryptReleaseContext(hCryptProv, 0)) { - hCryptProv = 0; - return 1; - } else { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_FINISH, - CRYPTOGRAPHY_OSRANDOM_R_CRYPTRELEASECONTEXT, - __FILE__, __LINE__ - ); - return 0; - } -} - -static int osrandom_rand_status(void) { - return hCryptProv != 0; -} - -static const char *osurandom_get_implementation(void) { - return "CryptGenRandom"; -} - -#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM */ - -/**************************************************************************** - * /dev/urandom helpers for all non-BSD Unix platforms - */ -#ifdef CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM - -static struct { - int fd; - dev_t st_dev; - ino_t st_ino; -} urandom_cache = { -1 }; - -static int open_cloexec(const char *path) { - int open_flags = O_RDONLY; -#ifdef O_CLOEXEC - open_flags |= O_CLOEXEC; -#endif - - int fd = open(path, open_flags); - if (fd == -1) { - return -1; - } - -#ifndef O_CLOEXEC - int flags = fcntl(fd, F_GETFD); - if (flags == -1) { - return -1; - } - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) { - return -1; - } -#endif - return fd; -} - -#ifdef __linux__ -/* On Linux, we open("/dev/random") and use poll() to wait until it's readable - * before we read from /dev/urandom, this ensures that we don't read from - * /dev/urandom before the kernel CSPRNG is initialized. This isn't necessary on - * other platforms because they don't have the same _bug_ as Linux does with - * /dev/urandom and early boot. */ -static int wait_on_devrandom(void) { - struct pollfd pfd = {}; - int ret = 0; - int random_fd = open_cloexec("/dev/random"); - if (random_fd < 0) { - return -1; - } - pfd.fd = random_fd; - pfd.events = POLLIN; - pfd.revents = 0; - do { - ret = poll(&pfd, 1, -1); - } while (ret < 0 && (errno == EINTR || errno == EAGAIN)); - close(random_fd); - return ret; -} -#endif - -/* return -1 on error */ -static int dev_urandom_fd(void) { - int fd = -1; - struct stat st; - - /* Check that fd still points to the correct device */ - if (urandom_cache.fd >= 0) { - if (fstat(urandom_cache.fd, &st) - || st.st_dev != urandom_cache.st_dev - || st.st_ino != urandom_cache.st_ino) { - /* Somebody replaced our FD. Invalidate our cache but don't - * close the fd. */ - urandom_cache.fd = -1; - } - } - if (urandom_cache.fd < 0) { -#ifdef __linux__ - if (wait_on_devrandom() < 0) { - goto error; - } -#endif - - fd = open_cloexec("/dev/urandom"); - if (fd < 0) { - goto error; - } - if (fstat(fd, &st)) { - goto error; - } - /* Another thread initialized the fd */ - if (urandom_cache.fd >= 0) { - close(fd); - return urandom_cache.fd; - } - urandom_cache.st_dev = st.st_dev; - urandom_cache.st_ino = st.st_ino; - urandom_cache.fd = fd; - } - return urandom_cache.fd; - - error: - if (fd != -1) { - close(fd); - } - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_FD, - CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_OPEN_FAILED, - __FILE__, __LINE__ - ); - return -1; -} - -static int dev_urandom_read(unsigned char *buffer, int size) { - int fd; - int n; - - fd = dev_urandom_fd(); - if (fd < 0) { - return 0; - } - - while (size > 0) { - do { - n = (int)read(fd, buffer, (size_t)size); - } while (n < 0 && errno == EINTR); - - if (n <= 0) { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_READ, - CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_READ_FAILED, - __FILE__, __LINE__ - ); - return 0; - } - buffer += n; - size -= n; - } - return 1; -} - -static void dev_urandom_close(void) { - if (urandom_cache.fd >= 0) { - int fd; - struct stat st; - - if (fstat(urandom_cache.fd, &st) - && st.st_dev == urandom_cache.st_dev - && st.st_ino == urandom_cache.st_ino) { - fd = urandom_cache.fd; - urandom_cache.fd = -1; - close(fd); - } - } -} -#endif /* CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM */ - -/**************************************************************************** - * BSD getentropy - */ -#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY -static const char *Cryptography_osrandom_engine_name = "osrandom_engine getentropy()"; - -static int osrandom_init(ENGINE *e) { - return 1; -} - -static int osrandom_rand_bytes(unsigned char *buffer, int size) { - int len; - int res; - - while (size > 0) { - /* OpenBSD and macOS restrict maximum buffer size to 256. */ - len = size > 256 ? 256 : size; - res = getentropy(buffer, (size_t)len); - if (res < 0) { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, - CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED, - __FILE__, __LINE__ - ); - return 0; - } - buffer += len; - size -= len; - } - return 1; -} - -static int osrandom_finish(ENGINE *e) { - return 1; -} - -static int osrandom_rand_status(void) { - return 1; -} - -static const char *osurandom_get_implementation(void) { - return "getentropy"; -} -#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY */ - -/**************************************************************************** - * Linux getrandom engine with fallback to dev_urandom - */ - -#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM -static const char *Cryptography_osrandom_engine_name = "osrandom_engine getrandom()"; - -static int getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT; - -static int osrandom_init(ENGINE *e) { - /* We try to detect working getrandom until we succeed. */ - if (getrandom_works != CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS) { - long n; - char dest[1]; - /* if the kernel CSPRNG is not initialized this will block */ - n = syscall(SYS_getrandom, dest, sizeof(dest), 0); - if (n == sizeof(dest)) { - getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS; - } else { - int e = errno; - switch(e) { - case ENOSYS: - /* Fallback: Kernel does not support the syscall. */ - getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK; - break; - case EPERM: - /* Fallback: seccomp prevents syscall */ - getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK; - break; - default: - /* EINTR cannot occur for buflen < 256. */ - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_INIT, - CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED, - "errno", e - ); - getrandom_works = CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED; - break; - } - } - } - - /* fallback to dev urandom */ - if (getrandom_works == CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK) { - int fd = dev_urandom_fd(); - if (fd < 0) { - return 0; - } - } - return 1; -} - -static int osrandom_rand_bytes(unsigned char *buffer, int size) { - long n; - - switch(getrandom_works) { - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED: - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, - CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED, - __FILE__, __LINE__ - ); - return 0; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT: - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, - CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT, - __FILE__, __LINE__ - ); - return 0; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK: - return dev_urandom_read(buffer, size); - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS: - while (size > 0) { - do { - n = syscall(SYS_getrandom, buffer, size, 0); - } while (n < 0 && errno == EINTR); - - if (n <= 0) { - ERR_Cryptography_OSRandom_error( - CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES, - CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED, - __FILE__, __LINE__ - ); - return 0; - } - buffer += n; - size -= (int)n; - } - return 1; - } - __builtin_unreachable(); -} - -static int osrandom_finish(ENGINE *e) { - dev_urandom_close(); - return 1; -} - -static int osrandom_rand_status(void) { - switch(getrandom_works) { - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED: - return 0; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT: - return 0; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK: - return urandom_cache.fd >= 0; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS: - return 1; - } - __builtin_unreachable(); -} - -static const char *osurandom_get_implementation(void) { - switch(getrandom_works) { - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED: - return ""; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT: - return ""; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK: - return "/dev/urandom"; - case CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS: - return "getrandom"; - } - __builtin_unreachable(); -} -#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM */ - -/**************************************************************************** - * dev_urandom engine for all remaining platforms - */ - -#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM -static const char *Cryptography_osrandom_engine_name = "osrandom_engine /dev/urandom"; - -static int osrandom_init(ENGINE *e) { - int fd = dev_urandom_fd(); - if (fd < 0) { - return 0; - } - return 1; -} - -static int osrandom_rand_bytes(unsigned char *buffer, int size) { - return dev_urandom_read(buffer, size); -} - -static int osrandom_finish(ENGINE *e) { - dev_urandom_close(); - return 1; -} - -static int osrandom_rand_status(void) { - return urandom_cache.fd >= 0; -} - -static const char *osurandom_get_implementation(void) { - return "/dev/urandom"; -} -#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM */ - -/**************************************************************************** - * ENGINE boiler plate - */ - -/* This replicates the behavior of the OpenSSL FIPS RNG, which returns a - -1 in the event that there is an error when calling RAND_pseudo_bytes. */ -static int osrandom_pseudo_rand_bytes(unsigned char *buffer, int size) { - int res = osrandom_rand_bytes(buffer, size); - if (res == 0) { - return -1; - } else { - return res; - } -} - -static RAND_METHOD osrandom_rand = { - NULL, - osrandom_rand_bytes, - NULL, - NULL, - osrandom_pseudo_rand_bytes, - osrandom_rand_status, -}; - -static const ENGINE_CMD_DEFN osrandom_cmd_defns[] = { - {CRYPTOGRAPHY_OSRANDOM_GET_IMPLEMENTATION, - "get_implementation", - "Get CPRNG implementation.", - ENGINE_CMD_FLAG_NO_INPUT}, - {0, NULL, NULL, 0} -}; - -static int osrandom_ctrl(ENGINE *e, int cmd, long i, void *p, void (*f) (void)) { - const char *name; - size_t len; - - switch (cmd) { - case CRYPTOGRAPHY_OSRANDOM_GET_IMPLEMENTATION: - /* i: buffer size, p: char* buffer */ - name = osurandom_get_implementation(); - len = strlen(name); - if ((p == NULL) && (i == 0)) { - /* return required buffer len */ - return (int)len; - } - if ((p == NULL) || i < 0 || ((size_t)i <= len)) { - /* no buffer or buffer too small */ - ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_INVALID_ARGUMENT); - return 0; - } - strcpy((char *)p, name); - return (int)len; - default: - ENGINEerr(ENGINE_F_ENGINE_CTRL, ENGINE_R_CTRL_COMMAND_NOT_IMPLEMENTED); - return 0; - } -} - -/* error reporting */ -#define ERR_FUNC(func) ERR_PACK(0, func, 0) -#define ERR_REASON(reason) ERR_PACK(0, 0, reason) - -static ERR_STRING_DATA CRYPTOGRAPHY_OSRANDOM_lib_name[] = { - {0, "osrandom_engine"}, - {0, NULL} -}; - -static ERR_STRING_DATA CRYPTOGRAPHY_OSRANDOM_str_funcs[] = { - {ERR_FUNC(CRYPTOGRAPHY_OSRANDOM_F_INIT), - "osrandom_init"}, - {ERR_FUNC(CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES), - "osrandom_rand_bytes"}, - {ERR_FUNC(CRYPTOGRAPHY_OSRANDOM_F_FINISH), - "osrandom_finish"}, - {ERR_FUNC(CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_FD), - "dev_urandom_fd"}, - {ERR_FUNC(CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_READ), - "dev_urandom_read"}, - {0, NULL} -}; - -static ERR_STRING_DATA CRYPTOGRAPHY_OSRANDOM_str_reasons[] = { - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_CRYPTACQUIRECONTEXT), - "CryptAcquireContext() failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_CRYPTGENRANDOM), - "CryptGenRandom() failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_CRYPTRELEASECONTEXT), - "CryptReleaseContext() failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED), - "getentropy() failed"}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_OPEN_FAILED), - "open('/dev/urandom') failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_READ_FAILED), - "Reading from /dev/urandom fd failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED), - "getrandom() initialization failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED), - "getrandom() initialization failed with unexpected errno."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED), - "getrandom() syscall failed."}, - {ERR_REASON(CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT), - "getrandom() engine was not properly initialized."}, - {0, NULL} -}; - -static int Cryptography_OSRandom_lib_error_code = 0; - -static void ERR_load_Cryptography_OSRandom_strings(void) -{ - if (Cryptography_OSRandom_lib_error_code == 0) { - Cryptography_OSRandom_lib_error_code = ERR_get_next_error_library(); - ERR_load_strings(Cryptography_OSRandom_lib_error_code, - CRYPTOGRAPHY_OSRANDOM_lib_name); - ERR_load_strings(Cryptography_OSRandom_lib_error_code, - CRYPTOGRAPHY_OSRANDOM_str_funcs); - ERR_load_strings(Cryptography_OSRandom_lib_error_code, - CRYPTOGRAPHY_OSRANDOM_str_reasons); - } -} - -static void ERR_Cryptography_OSRandom_error(int function, int reason, - char *file, int line) -{ - ERR_PUT_error(Cryptography_OSRandom_lib_error_code, function, reason, - file, line); -} - -/* Returns 1 if successfully added, 2 if engine has previously been added, - and 0 for error. */ -int Cryptography_add_osrandom_engine(void) { - ENGINE *e; - - ERR_load_Cryptography_OSRandom_strings(); - - e = ENGINE_by_id(Cryptography_osrandom_engine_id); - if (e != NULL) { - ENGINE_free(e); - return 2; - } else { - ERR_clear_error(); - } - - e = ENGINE_new(); - if (e == NULL) { - return 0; - } - if (!ENGINE_set_id(e, Cryptography_osrandom_engine_id) || - !ENGINE_set_name(e, Cryptography_osrandom_engine_name) || - !ENGINE_set_RAND(e, &osrandom_rand) || - !ENGINE_set_init_function(e, osrandom_init) || - !ENGINE_set_finish_function(e, osrandom_finish) || - !ENGINE_set_cmd_defns(e, osrandom_cmd_defns) || - !ENGINE_set_ctrl_function(e, osrandom_ctrl)) { - ENGINE_free(e); - return 0; - } - if (!ENGINE_add(e)) { - ENGINE_free(e); - return 0; - } - if (!ENGINE_free(e)) { - return 0; - } - - return 1; -} - -#else -/* If OpenSSL has no ENGINE support then we don't want - * to compile the osrandom engine, but we do need some - * placeholders */ -static const char *Cryptography_osrandom_engine_id = "no-engine-support"; -static const char *Cryptography_osrandom_engine_name = "osrandom_engine disabled"; - -int Cryptography_add_osrandom_engine(void) { - return 0; -} - -#endif diff --git a/src/_cffi_src/openssl/src/osrandom_engine.h b/src/_cffi_src/openssl/src/osrandom_engine.h deleted file mode 100644 index 89e45265186f..000000000000 --- a/src/_cffi_src/openssl/src/osrandom_engine.h +++ /dev/null @@ -1,116 +0,0 @@ -#if CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE -/* OpenSSL has ENGINE support so include all of this. */ -#ifdef _WIN32 - #include -#else - #include - #include - /* for defined(BSD) */ - #ifndef __MVS__ - #include - #endif - - #ifdef BSD - /* for SYS_getentropy */ - #include - #endif - - #ifdef __APPLE__ - #include - /* To support weak linking we need to declare this as a weak import even if - * it's not present in sys/random (e.g. macOS < 10.12). */ - extern int getentropy(void *buffer, size_t size) __attribute((weak_import)); - #endif - - #ifdef __linux__ - /* for SYS_getrandom */ - #include - #ifndef GRND_NONBLOCK - #define GRND_NONBLOCK 0x0001 - #endif /* GRND_NONBLOCK */ - - #ifndef SYS_getrandom - /* We only bother to define the constants for platforms where we ship - * wheels, since that's the predominant way you get a situation where - * you don't have SYS_getrandom at compile time but do have the syscall - * at runtime */ - #if defined(__x86_64__) - #define SYS_getrandom 318 - #elif defined(__i386__) - #define SYS_getrandom 355 - #elif defined(__aarch64__) - #define SYS_getrandom 278 - #endif - #endif - #endif /* __linux__ */ -#endif /* _WIN32 */ - -#define CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM 1 -#define CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY 2 -#define CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM 3 -#define CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM 4 - -#ifndef CRYPTOGRAPHY_OSRANDOM_ENGINE - #if defined(_WIN32) - /* Windows */ - #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_CRYPTGENRANDOM - #elif defined(BSD) && defined(SYS_getentropy) - /* OpenBSD 5.6+ & macOS with SYS_getentropy defined, although < 10.12 will fallback - * to urandom */ - #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY - #elif defined(__linux__) && defined(SYS_getrandom) - /* Linux 3.17+ */ - #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM - #else - /* Keep this as last entry, fall back to /dev/urandom */ - #define CRYPTOGRAPHY_OSRANDOM_ENGINE CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM - #endif -#endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE */ - -/* Fallbacks need /dev/urandom helper functions. */ -#if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM || \ - CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM - #define CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM 1 -#endif - -enum { - CRYPTOGRAPHY_OSRANDOM_GETRANDOM_INIT_FAILED = -2, - CRYPTOGRAPHY_OSRANDOM_GETRANDOM_NOT_INIT, - CRYPTOGRAPHY_OSRANDOM_GETRANDOM_FALLBACK, - CRYPTOGRAPHY_OSRANDOM_GETRANDOM_WORKS -}; - -enum { - CRYPTOGRAPHY_OSRANDOM_GETENTROPY_NOT_INIT, - CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK, - CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS -}; - -/* engine ctrl */ -#define CRYPTOGRAPHY_OSRANDOM_GET_IMPLEMENTATION ENGINE_CMD_BASE - -/* error reporting */ -static void ERR_load_Cryptography_OSRandom_strings(void); -static void ERR_Cryptography_OSRandom_error(int function, int reason, - char *file, int line); - -#define CRYPTOGRAPHY_OSRANDOM_F_INIT 100 -#define CRYPTOGRAPHY_OSRANDOM_F_RAND_BYTES 101 -#define CRYPTOGRAPHY_OSRANDOM_F_FINISH 102 -#define CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_FD 300 -#define CRYPTOGRAPHY_OSRANDOM_F_DEV_URANDOM_READ 301 - -#define CRYPTOGRAPHY_OSRANDOM_R_CRYPTACQUIRECONTEXT 100 -#define CRYPTOGRAPHY_OSRANDOM_R_CRYPTGENRANDOM 101 -#define CRYPTOGRAPHY_OSRANDOM_R_CRYPTRELEASECONTEXT 102 - -#define CRYPTOGRAPHY_OSRANDOM_R_GETENTROPY_FAILED 200 - -#define CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_OPEN_FAILED 300 -#define CRYPTOGRAPHY_OSRANDOM_R_DEV_URANDOM_READ_FAILED 301 - -#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED 400 -#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_INIT_FAILED_UNEXPECTED 402 -#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_FAILED 403 -#define CRYPTOGRAPHY_OSRANDOM_R_GETRANDOM_NOT_INIT 404 -#endif diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 53e3486c0da2..facdb48a03a8 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -7,7 +7,6 @@ import contextlib import itertools import typing -import warnings from contextlib import contextmanager from cryptography import utils, x509 @@ -185,13 +184,6 @@ def __init__(self) -> None: typing.Callable, ] = {} self._register_default_ciphers() - if self._fips_enabled and self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: - warnings.warn( - "OpenSSL FIPS mode is enabled. Can't enable DRBG fork safety.", - UserWarning, - ) - else: - self.activate_osrandom_engine() self._dh_types = [self._lib.EVP_PKEY_DH] if self._lib.Cryptography_HAS_EVP_PKEY_DHX: self._dh_types.append(self._lib.EVP_PKEY_DHX) @@ -230,60 +222,6 @@ def _enable_fips(self) -> None: assert self._is_fips_enabled() self._fips_enabled = self._is_fips_enabled() - def activate_builtin_random(self) -> None: - if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: - # Obtain a new structural reference. - e = self._lib.ENGINE_get_default_RAND() - if e != self._ffi.NULL: - self._lib.ENGINE_unregister_RAND(e) - # Reset the RNG to use the built-in. - res = self._lib.RAND_set_rand_method(self._ffi.NULL) - self.openssl_assert(res == 1) - # decrement the structural reference from get_default_RAND - res = self._lib.ENGINE_finish(e) - self.openssl_assert(res == 1) - - @contextlib.contextmanager - def _get_osurandom_engine(self): - # Fetches an engine by id and returns it. This creates a structural - # reference. - e = self._lib.ENGINE_by_id(self._lib.Cryptography_osrandom_engine_id) - self.openssl_assert(e != self._ffi.NULL) - # Initialize the engine for use. This adds a functional reference. - res = self._lib.ENGINE_init(e) - self.openssl_assert(res == 1) - - try: - yield e - finally: - # Decrement the structural ref incremented by ENGINE_by_id. - res = self._lib.ENGINE_free(e) - self.openssl_assert(res == 1) - # Decrement the functional ref incremented by ENGINE_init. - res = self._lib.ENGINE_finish(e) - self.openssl_assert(res == 1) - - def activate_osrandom_engine(self) -> None: - if self._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_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 engine - res = self._lib.RAND_set_rand_method(self._ffi.NULL) - self.openssl_assert(res == 1) - - def osrandom_engine_implementation(self) -> str: - buf = self._ffi.new("char[]", 64) - with self._get_osurandom_engine() as e: - res = self._lib.ENGINE_ctrl_cmd( - e, b"get_implementation", len(buf), buf, self._ffi.NULL, 0 - ) - self.openssl_assert(res > 0) - return self._ffi.string(buf).decode("ascii") - def openssl_version_text(self) -> str: """ Friendly string name of the loaded OpenSSL library. This is not @@ -1968,7 +1906,7 @@ def ed448_supported(self) -> bool: if self._fips_enabled: return False return ( - not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B + not self._lib.CRYPTOGRAPHY_IS_LIBRESSL and not self._lib.CRYPTOGRAPHY_IS_BORINGSSL ) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 075d68fb9057..8d4b8dc3bbf1 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -119,7 +119,7 @@ def __init__( lib = self._backend._lib if res == 0 and ( ( - lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER + not lib.CRYPTOGRAPHY_IS_LIBRESSL and errors[0]._lib_reason_match( lib.ERR_LIB_EVP, lib.EVP_R_XTS_DUPLICATED_KEYS ) diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index c34fc3ae6960..35829a2821da 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -162,7 +162,6 @@ def cryptography_has_engine() -> typing.List[str]: "ENGINE_ctrl_cmd", "ENGINE_free", "ENGINE_get_name", - "Cryptography_add_osrandom_engine", "ENGINE_ctrl_cmd_string", "ENGINE_load_builtin_engines", "ENGINE_load_private_key", diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 7327157fd8d5..99061e21b421 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -10,7 +10,6 @@ import warnings import cryptography -from cryptography import utils from cryptography.exceptions import InternalError from cryptography.hazmat.bindings._rust import _openssl, openssl from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES @@ -98,18 +97,6 @@ def _enable_fips(self) -> None: res = self.lib.EVP_default_properties_enable_fips(self.ffi.NULL, 1) _openssl_assert(self.lib, res == 1) - @classmethod - def _register_osrandom_engine(cls) -> None: - # Clear any errors extant in the queue before we start. In many - # scenarios other things may be interacting with OpenSSL in the same - # process space and it has proven untenable to assume that they will - # 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() - if cls.lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE: - result = cls.lib.Cryptography_add_osrandom_engine() - _openssl_assert(cls.lib, result in (1, 2)) - @classmethod def _ensure_ffi_initialized(cls) -> None: with cls._init_lock: @@ -118,7 +105,6 @@ def _ensure_ffi_initialized(cls) -> None: _openssl.lib, CONDITIONAL_NAMES ) cls._lib_loaded = True - cls._register_osrandom_engine() # As of OpenSSL 3.0.0 we must register a legacy cipher provider # to get RC2 (needed for junk asymmetric private key # serialization), RC4, Blowfish, IDEA, SEED, etc. These things @@ -189,20 +175,3 @@ def _verify_package_version(version: str) -> None: UserWarning, stacklevel=2, ) - - -def _verify_openssl_version(lib): - if ( - not lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER - and not lib.CRYPTOGRAPHY_IS_LIBRESSL - and not lib.CRYPTOGRAPHY_IS_BORINGSSL - ): - warnings.warn( - "Support for OpenSSL less than version 1.1.1d is deprecated and " - "the next release of cryptography will drop support. Please " - "upgrade your OpenSSL to version 1.1.1d or newer.", - utils.DeprecatedIn40, - ) - - -_verify_openssl_version(Binding.lib) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 6f3f4a2bf508..572431ebbd4a 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -5,9 +5,6 @@ import itertools import os -import subprocess -import sys -import textwrap import pytest @@ -179,158 +176,6 @@ def test_bn_to_int(self): assert backend._bn_to_int(bn) == 0 -@pytest.mark.skipif( - not backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE, - reason="Requires OpenSSL with ENGINE support and OpenSSL < 1.1.1d", -) -@pytest.mark.skip_fips(reason="osrandom engine disabled for FIPS") -class TestOpenSSLRandomEngine: - def setup_method(self): - # The default RAND engine is global and shared between - # tests. We make sure that the default engine is osrandom - # before we start each test and restore the global state to - # that engine in teardown. - current_default = backend._lib.ENGINE_get_default_RAND() - name = backend._lib.ENGINE_get_name(current_default) - assert name == backend._lib.Cryptography_osrandom_engine_name - - def teardown_method(self): - # we need to reset state to being default. backend is a shared global - # for all these tests. - backend.activate_osrandom_engine() - current_default = backend._lib.ENGINE_get_default_RAND() - name = backend._lib.ENGINE_get_name(current_default) - assert name == backend._lib.Cryptography_osrandom_engine_name - - @pytest.mark.skipif( - sys.executable is None, reason="No Python interpreter available." - ) - def test_osrandom_engine_is_default(self, tmpdir): - engine_printer = textwrap.dedent( - """ - import sys - from cryptography.hazmat.backends.openssl.backend import backend - - e = backend._lib.ENGINE_get_default_RAND() - name = backend._lib.ENGINE_get_name(e) - sys.stdout.write(backend._ffi.string(name).decode('ascii')) - res = backend._lib.ENGINE_free(e) - assert res == 1 - """ - ) - engine_name = tmpdir.join("engine_name") - - # If we're running tests via ``python setup.py test`` in a clean - # environment then all of our dependencies are going to be installed - # into either the current directory or the .eggs directory. However the - # subprocess won't know to activate these dependencies, so we'll get it - # to do so by passing our entire sys.path into the subprocess via the - # PYTHONPATH environment variable. - env = os.environ.copy() - env["PYTHONPATH"] = os.pathsep.join(sys.path) - - with engine_name.open("w") as out: - subprocess.check_call( - [sys.executable, "-c", engine_printer], - env=env, - stdout=out, - stderr=subprocess.PIPE, - ) - - osrandom_engine_name = backend._ffi.string( - backend._lib.Cryptography_osrandom_engine_name - ) - - assert engine_name.read().encode("ascii") == osrandom_engine_name - - def test_osrandom_sanity_check(self): - # This test serves as a check against catastrophic failure. - buf = backend._ffi.new("unsigned char[]", 500) - res = backend._lib.RAND_bytes(buf, 500) - assert res == 1 - assert backend._ffi.buffer(buf)[:] != "\x00" * 500 - - def test_activate_osrandom_no_default(self): - backend.activate_builtin_random() - e = backend._lib.ENGINE_get_default_RAND() - assert e == backend._ffi.NULL - backend.activate_osrandom_engine() - e = backend._lib.ENGINE_get_default_RAND() - name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name - res = backend._lib.ENGINE_free(e) - assert res == 1 - - def test_activate_builtin_random(self): - e = backend._lib.ENGINE_get_default_RAND() - assert e != backend._ffi.NULL - name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name - res = backend._lib.ENGINE_free(e) - assert res == 1 - backend.activate_builtin_random() - e = backend._lib.ENGINE_get_default_RAND() - assert e == backend._ffi.NULL - - def test_activate_builtin_random_already_active(self): - backend.activate_builtin_random() - e = backend._lib.ENGINE_get_default_RAND() - assert e == backend._ffi.NULL - backend.activate_builtin_random() - e = backend._lib.ENGINE_get_default_RAND() - assert e == backend._ffi.NULL - - def test_osrandom_engine_implementation(self): - name = backend.osrandom_engine_implementation() - assert name in [ - "/dev/urandom", - "CryptGenRandom", - "getentropy", - "getrandom", - ] - if sys.platform.startswith("linux"): - assert name in ["getrandom", "/dev/urandom"] - if sys.platform == "darwin": - assert name in ["getentropy"] - if sys.platform == "win32": - assert name == "CryptGenRandom" - - def test_activate_osrandom_already_default(self): - e = backend._lib.ENGINE_get_default_RAND() - name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name - res = backend._lib.ENGINE_free(e) - assert res == 1 - backend.activate_osrandom_engine() - e = backend._lib.ENGINE_get_default_RAND() - name = backend._lib.ENGINE_get_name(e) - assert name == backend._lib.Cryptography_osrandom_engine_name - res = backend._lib.ENGINE_free(e) - assert res == 1 - - -@pytest.mark.skipif( - backend._lib.CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE, - reason="Requires OpenSSL without ENGINE support or OpenSSL >=1.1.1d", -) -class TestOpenSSLNoEngine: - def test_no_engine_support(self): - assert ( - backend._ffi.string(backend._lib.Cryptography_osrandom_engine_id) - == b"no-engine-support" - ) - assert ( - backend._ffi.string(backend._lib.Cryptography_osrandom_engine_name) - == b"osrandom_engine disabled" - ) - - def test_activate_builtin_random_does_nothing(self): - backend.activate_builtin_random() - - def test_activate_osrandom_does_nothing(self): - backend.activate_osrandom_engine() - - class TestOpenSSLRSA: def test_generate_rsa_parameters_supported(self): assert backend.generate_rsa_parameters_supported(1, 1024) is False diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 118b850ee3ff..c061c9bf11b0 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -21,11 +21,6 @@ def test_binding_loads(self): assert binding.lib assert binding.ffi - def test_add_engine_more_than_once(self): - b = Binding() - b._register_osrandom_engine() - assert b.lib.ERR_get_error() == 0 - def test_ssl_ctx_options(self): # Test that we're properly handling 32-bit unsigned on all platforms. b = Binding() @@ -85,18 +80,6 @@ def test_openssl_assert_error_on_stack(self): if not b.lib.CRYPTOGRAPHY_IS_BORINGSSL: assert b"data not multiple of block length" in error.reason_text - def test_check_startup_errors_are_allowed(self): - b = Binding() - b.lib.ERR_put_error( - b.lib.ERR_LIB_EVP, - b.lib.EVP_F_EVP_ENCRYPTFINAL_EX, - b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH, - b"", - -1, - ) - b._register_osrandom_engine() - assert rust_openssl.capture_error_stack() == [] - def test_version_mismatch(self): with pytest.raises(ImportError): _verify_package_version("nottherightversion") diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 5322f8f4afea..1f3dfd0014b4 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -61,9 +61,7 @@ def test_xts_too_short(self, backend): enc.update(b"0" * 15) @pytest.mark.supported( - only_if=lambda backend: ( - backend._lib.CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER - ), + only_if=lambda backend: (not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL), skip_message="duplicate key encryption error added in OpenSSL 1.1.1d", ) def test_xts_no_duplicate_keys_encryption(self, backend):