From 33c75539ff3f834f72ba9703b64df6d4888c2abc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 7 Sep 2022 08:18:30 +0800 Subject: [PATCH 001/298] reopen main for 39 dev (#7568) --- CHANGELOG.rst | 8 ++++++++ src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 66be5e417ef9..bfca9438cd50 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,14 @@ Changelog ========= +.. _v39-0-0: + +39.0.0 - `main`_ +~~~~~~~~~~~~~~~~ + +.. note:: This version is not yet released and is under active development. + + .. _v38-0-0: 38.0.0 - 2022-09-06 diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 24aeeac1de55..7adbc40005ef 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -9,7 +9,7 @@ "__copyright__", ] -__version__ = "38.0.0" +__version__ = "39.0.0.dev1" __author__ = "The Python Cryptographic Authority and individual contributors" __copyright__ = "Copyright 2013-2022 {}".format(__author__) diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index e80fa3c1d674..95eb6b9919a8 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -6,4 +6,4 @@ "__version__", ] -__version__ = "38.0.0" +__version__ = "39.0.0.dev1" From 8bb67c468d7ca4f7422ba97c06c5d9e7667079b5 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 7 Sep 2022 08:31:58 +0800 Subject: [PATCH 002/298] Bump BoringSSL version to 2e295b91a3c441d32f985bef0dcff5e639f1f448 (#7569) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d08dc9700fcc..58893772c9a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,8 +45,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 02, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "8462a367bb57e9524c3d8eca9c62733c63a63cf4"}} + # Latest commit on the master branch, as of Sep 07, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "2e295b91a3c441d32f985bef0dcff5e639f1f448"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 2cae24a93b5c680c2b51e2c44a32ee922cb99d3e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 6 Sep 2022 22:36:23 -0400 Subject: [PATCH 003/298] Drop OpenSSL 1.1.0 (#7570) There's still a few TODOs for cleanup. Refs #7109 --- .github/workflows/ci.yml | 1 - CHANGELOG.rst | 2 ++ docs/faq.rst | 16 +++++------ docs/installation.rst | 5 ---- src/_cffi_src/openssl/cryptography.py | 7 ++--- src/_cffi_src/openssl/evp.py | 5 ++-- src/_cffi_src/openssl/ssl.py | 27 ++++--------------- .../hazmat/backends/openssl/backend.py | 2 +- .../hazmat/bindings/openssl/_conditional.py | 10 ------- .../hazmat/bindings/openssl/binding.py | 18 ------------- 10 files changed, 20 insertions(+), 73 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58893772c9a7..c178435a6fa6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,6 @@ jobs: - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bfca9438cd50..9c5bc83538bc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,8 @@ Changelog .. note:: This version is not yet released and is under active development. +* Support for OpenSSL 1.1.0 has been removed. Users on older version of + OpenSSL will need to upgrade. .. _v38-0-0: diff --git a/docs/faq.rst b/docs/faq.rst index f9f35c149dd3..640ec9e3aeb5 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -111,14 +111,14 @@ earlier the default compiler is extremely old. Use ``pkg_add`` to install a newer ``gcc`` and then install ``cryptography`` using ``CC=/path/to/newer/gcc pip install cryptography``. -Installing cryptography with OpenSSL 0.9.8, 1.0.0, 1.0.1, 1.0.2 fails ---------------------------------------------------------------------- - -The OpenSSL project has dropped support for the 0.9.8, 1.0.0, 1.0.1, and 1.0.2 -release series. Since they are no longer receiving security patches from -upstream, ``cryptography`` is also dropping support for them. To fix this issue -you should upgrade to a newer version of OpenSSL (1.1.0 or later). This may -require you to upgrade to a newer operating system. +Installing cryptography with OpenSSL 0.9.8, 1.0.0, 1.0.1, 1.0.2, 1.1.0 fails +---------------------------------------------------------------------------- + +The OpenSSL project has dropped support for the 0.9.8, 1.0.0, 1.0.1, 1.0.2, +and 1.1.0 release series. Since they are no longer receiving security patches +from upstream, ``cryptography`` is also dropping support for them. To fix this +issue you should upgrade to a newer version of OpenSSL (1.1.1 or later). This +may require you to upgrade to a newer operating system. Installing ``cryptography`` fails with ``error: Can not find Rust compiler`` ---------------------------------------------------------------------------- diff --git a/docs/installation.rst b/docs/installation.rst index 361ed5a07d15..44dc9519bf12 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -31,17 +31,12 @@ operating systems. We test compiling with ``clang`` as well as ``gcc`` and use the following OpenSSL releases: -* ``OpenSSL 1.1.0-latest`` * ``OpenSSL 1.1.1-latest`` * ``OpenSSL 3.0-latest`` In addition we test against several versions of LibreSSL and the latest commit in BoringSSL. -.. warning:: - - Cryptography 37.0.0 has deprecated support for OpenSSL 1.1.0. - Building cryptography on Windows -------------------------------- diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index f92dd2a0a2d9..b5d4eb3cbd2f 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -55,8 +55,8 @@ #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 (0) #endif -#if OPENSSL_VERSION_NUMBER < 0x10100000 - #error "pyca/cryptography MUST be linked with Openssl 1.1.0 or later" +#if OPENSSL_VERSION_NUMBER < 0x10101000 + #error "pyca/cryptography MUST be linked with Openssl 1.1.1 or later" #endif #define CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER \ @@ -64,8 +64,6 @@ #define CRYPTOGRAPHY_OPENSSL_300_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x30000000 && !CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 \ - (OPENSSL_VERSION_NUMBER < 0x10101000 || CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B \ (OPENSSL_VERSION_NUMBER < 0x10101020 || CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D \ @@ -84,7 +82,6 @@ static const int CRYPTOGRAPHY_OPENSSL_111D_OR_GREATER; static const int CRYPTOGRAPHY_OPENSSL_300_OR_GREATER; -static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111E; static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE; diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index f4d9fb953cd5..91f61a77e2e9 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -203,8 +203,7 @@ size_t) = NULL; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 || \ - (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL) +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 static const long Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY = 0; int (*EVP_DigestSign)(EVP_MD_CTX *, unsigned char *, size_t *, const unsigned char *tbs, size_t) = NULL; @@ -214,7 +213,7 @@ static const long Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY = 1; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 +#if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_RAW_KEY = 0; static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 0; int (*EVP_DigestFinalXOF)(EVP_MD_CTX *, unsigned char *, size_t) = NULL; diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 61f83ef8ad99..cd1a789521c3 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -25,7 +25,6 @@ static const long Cryptography_HAS_PSK_TLSv1_3; static const long Cryptography_HAS_VERIFIED_CHAIN; static const long Cryptography_HAS_KEYLOG; -static const long Cryptography_HAS_GET_PROTO_VERSION; static const long Cryptography_HAS_TLSEXT_HOSTNAME; static const long Cryptography_HAS_SSL_COOKIE; @@ -566,8 +565,7 @@ static const long Cryptography_HAS_VERIFIED_CHAIN = 1; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 || \ - (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL) +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 static const long Cryptography_HAS_KEYLOG = 0; void (*SSL_CTX_set_keylog_callback)(SSL_CTX *, void (*) (const SSL *, const char *) @@ -653,7 +651,7 @@ long (*DTLS_get_link_min_mtu)(SSL *) = NULL; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 || CRYPTOGRAPHY_IS_BORINGSSL +#if CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_IS_BORINGSSL static const long Cryptography_HAS_DTLS_GET_DATA_MTU = 0; size_t (*DTLS_get_data_mtu)(SSL *) = NULL; #else @@ -747,8 +745,7 @@ SRTP_PROTECTION_PROFILE * (*SSL_get_selected_srtp_profile)(SSL *) = NULL; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 || \ - (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL) +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 static const long Cryptography_HAS_TLSv1_3 = 0; static const long TLS1_3_VERSION = 0; static const long SSL_OP_NO_TLSv1_3 = 0; @@ -756,9 +753,7 @@ static const long Cryptography_HAS_TLSv1_3 = 1; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 || \ - (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL) || \ - CRYPTOGRAPHY_IS_BORINGSSL +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 || CRYPTOGRAPHY_IS_BORINGSSL static const long Cryptography_HAS_TLSv1_3_FUNCTIONS = 0; static const long SSL_VERIFY_POST_HANDSHAKE = 0; @@ -774,17 +769,6 @@ static const long Cryptography_HAS_TLSv1_3_FUNCTIONS = 1; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 && !CRYPTOGRAPHY_IS_LIBRESSL -static const long Cryptography_HAS_GET_PROTO_VERSION = 0; - -long (*SSL_CTX_get_min_proto_version)(SSL_CTX *) = NULL; -long (*SSL_CTX_get_max_proto_version)(SSL_CTX *) = NULL; -long (*SSL_get_min_proto_version)(SSL *) = NULL; -long (*SSL_get_max_proto_version)(SSL *) = NULL; -#else -static const long Cryptography_HAS_GET_PROTO_VERSION = 1; -#endif - #if CRYPTOGRAPHY_IS_BORINGSSL static const long Cryptography_HAS_SSL_COOKIE = 0; @@ -805,8 +789,7 @@ #else static const long Cryptography_HAS_SSL_COOKIE = 1; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 || \ - CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_IS_BORINGSSL +#if CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_IS_BORINGSSL static const long Cryptography_HAS_PSK_TLSv1_3 = 0; void (*SSL_CTX_set_psk_find_session_callback)(SSL_CTX *, int (*)( diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 7cc7f97bb52b..e1bcb398b8c0 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1980,7 +1980,7 @@ def x448_supported(self) -> bool: if self._fips_enabled: return False return ( - not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 + not self._lib.CRYPTOGRAPHY_IS_LIBRESSL and not self._lib.CRYPTOGRAPHY_IS_BORINGSSL ) diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 10f307af7960..24a8871f0c1c 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -230,15 +230,6 @@ def cryptography_has_srtp() -> typing.List[str]: ] -def cryptography_has_get_proto_version() -> typing.List[str]: - return [ - "SSL_CTX_get_min_proto_version", - "SSL_CTX_get_max_proto_version", - "SSL_get_min_proto_version", - "SSL_get_max_proto_version", - ] - - def cryptography_has_providers() -> typing.List[str]: return [ "OSSL_PROVIDER_load", @@ -366,7 +357,6 @@ def cryptography_has_ssl_op_ignore_unexpected_eof() -> typing.List[str]: "Cryptography_HAS_ENGINE": cryptography_has_engine, "Cryptography_HAS_VERIFIED_CHAIN": cryptography_has_verified_chain, "Cryptography_HAS_SRTP": cryptography_has_srtp, - "Cryptography_HAS_GET_PROTO_VERSION": cryptography_has_get_proto_version, "Cryptography_HAS_PROVIDERS": cryptography_has_providers, "Cryptography_HAS_OP_NO_RENEGOTIATION": ( cryptography_has_op_no_renegotiation diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 2b4c574b4c34..9949ce33ac23 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -6,10 +6,8 @@ import threading import types import typing -import warnings import cryptography -from cryptography import utils from cryptography.exceptions import InternalError from cryptography.hazmat.bindings._openssl import ffi, lib from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES @@ -188,20 +186,6 @@ def init_static_locks(cls): cls._ensure_ffi_initialized() -def _verify_openssl_version(lib): - if ( - lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 - and not lib.CRYPTOGRAPHY_IS_LIBRESSL - and not lib.CRYPTOGRAPHY_IS_BORINGSSL - ): - warnings.warn( - "OpenSSL version 1.1.0 is no longer supported by the OpenSSL " - "project, please upgrade. The next release of cryptography will " - "drop support for OpenSSL 1.1.0.", - utils.DeprecatedIn37, - ) - - def _verify_package_version(version): # Occasionally we run into situations where the version of the Python # package does not match the version of the shared object that is loaded. @@ -226,5 +210,3 @@ def _verify_package_version(version): _verify_package_version(cryptography.__version__) Binding.init_static_locks() - -_verify_openssl_version(Binding.lib) From 9547b311ff84807db63cb7c0044f55209eeb5e79 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 6 Sep 2022 23:04:09 -0400 Subject: [PATCH 004/298] Increase our minimum LibreSSL. (#7571) OpenBSD 7.0 ships 3.4, and Alpine 3.14 ships 3.3.6 --- .github/workflows/ci.yml | 2 -- CHANGELOG.rst | 2 ++ src/_cffi_src/openssl/cryptography.py | 6 ------ src/_cffi_src/openssl/ssl.py | 4 ---- src/_cffi_src/openssl/x509_vfy.py | 10 ---------- .../hazmat/bindings/openssl/_conditional.py | 7 ------- 6 files changed, 2 insertions(+), 29 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c178435a6fa6..9f913f3b2bc3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,8 +37,6 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.1.5"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.2.7"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.3.6"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 9c5bc83538bc..700475814e94 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,8 @@ Changelog * Support for OpenSSL 1.1.0 has been removed. Users on older version of OpenSSL will need to upgrade. +* **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL 3.1.x, 3.2.x, + 3.3.0, and 3.3.1. The new minimum LibreSSL version is 3.3.2+. .. _v38-0-0: diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index b5d4eb3cbd2f..e8b4489ca231 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -39,18 +39,12 @@ #endif #if CRYPTOGRAPHY_IS_LIBRESSL -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_322 \ - (LIBRESSL_VERSION_NUMBER < 0x3020200f) -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 \ - (LIBRESSL_VERSION_NUMBER < 0x3030200f) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 \ (LIBRESSL_VERSION_NUMBER < 0x3040000f) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 \ (LIBRESSL_VERSION_NUMBER < 0x3050000f) #else -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_322 (0) -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 (0) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 (0) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 (0) #endif diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index cd1a789521c3..66305bca9fce 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -643,10 +643,6 @@ #endif #if CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_IS_BORINGSSL -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_332 -static const long SSL_OP_NO_DTLSv1 = 0; -static const long SSL_OP_NO_DTLSv1_2 = 0; -#endif long (*DTLS_set_link_mtu)(SSL *, long) = NULL; long (*DTLS_get_link_min_mtu)(SSL *) = NULL; #endif diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index 799751548a7c..5cb6a3f33dad 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -18,7 +18,6 @@ """ TYPES = """ -static const long Cryptography_HAS_110_VERIFICATION_PARAMS; static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER; typedef ... Cryptography_STACK_OF_ASN1_OBJECT; @@ -218,15 +217,6 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_IS_LIBRESSL && CRYPTOGRAPHY_LIBRESSL_LESS_THAN_322 -static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 0; -#ifndef X509_CHECK_FLAG_NEVER_CHECK_SUBJECT -static const long X509_CHECK_FLAG_NEVER_CHECK_SUBJECT = 0; -#endif -#else -static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 1; -#endif - #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER = 0; typedef void *X509_STORE_CTX_get_issuer_fn; diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 24a8871f0c1c..549bb50e07c0 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -19,10 +19,6 @@ def cryptography_has_ssl3_method() -> typing.List[str]: ] -def cryptography_has_110_verification_params() -> typing.List[str]: - return ["X509_CHECK_FLAG_NEVER_CHECK_SUBJECT"] - - def cryptography_has_set_cert_cb() -> typing.List[str]: return [ "SSL_CTX_set_cert_cb", @@ -320,9 +316,6 @@ def cryptography_has_ssl_op_ignore_unexpected_eof() -> typing.List[str]: CONDITIONAL_NAMES = { "Cryptography_HAS_EC2M": cryptography_has_ec2m, "Cryptography_HAS_SSL3_METHOD": cryptography_has_ssl3_method, - "Cryptography_HAS_110_VERIFICATION_PARAMS": ( - cryptography_has_110_verification_params - ), "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, From 2b6e463c786e767a7ce50e88b2577148c4764a01 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 6 Sep 2022 23:43:45 -0400 Subject: [PATCH 005/298] fixes #7179 -- remove deprecated from_encoded_point (#7572) --- CHANGELOG.rst | 12 +++- .../hazmat/primitives/asymmetric/ec.py | 45 ------------ src/cryptography/utils.py | 1 - tests/hazmat/primitives/test_ec.py | 70 +------------------ 4 files changed, 11 insertions(+), 117 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 700475814e94..90bdc75fa3c7 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,10 +8,18 @@ Changelog .. note:: This version is not yet released and is under active development. -* Support for OpenSSL 1.1.0 has been removed. Users on older version of - OpenSSL will need to upgrade. +* **BACKWARDS INCOMPATIBLE:** Support for OpenSSL 1.1.0 has been removed. + Users on older version of OpenSSL will need to upgrade. * **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL 3.1.x, 3.2.x, 3.3.0, and 3.3.1. The new minimum LibreSSL version is 3.3.2+. +* **BACKWARDS INCOMPATIBLE:** Removed the ``encode_point`` and + ``from_encoded_point`` methods on + :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`, + which had been deprecated for several years. + :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.public_bytes` + and + :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point` + should be used instead. .. _v38-0-0: diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 3aaa382a81d1..4d949da5ee16 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -5,7 +5,6 @@ import abc import typing -import warnings from cryptography import utils from cryptography.hazmat._oid import ObjectIdentifier @@ -363,50 +362,6 @@ def public_key(self, backend: typing.Any = None) -> EllipticCurvePublicKey: return ossl.load_elliptic_curve_public_numbers(self) - def encode_point(self) -> bytes: - warnings.warn( - "encode_point has been deprecated on EllipticCurvePublicNumbers" - " and will be removed in a future version. Please use " - "EllipticCurvePublicKey.public_bytes to obtain both " - "compressed and uncompressed point encoding.", - utils.PersistentlyDeprecated2019, - stacklevel=2, - ) - # key_size is in bits. Convert to bytes and round up - byte_length = (self.curve.key_size + 7) // 8 - return ( - b"\x04" - + utils.int_to_bytes(self.x, byte_length) - + utils.int_to_bytes(self.y, byte_length) - ) - - @classmethod - def from_encoded_point( - cls, curve: EllipticCurve, data: bytes - ) -> "EllipticCurvePublicNumbers": - if not isinstance(curve, EllipticCurve): - raise TypeError("curve must be an EllipticCurve instance") - - warnings.warn( - "Support for unsafe construction of public numbers from " - "encoded data will be removed in a future version. " - "Please use EllipticCurvePublicKey.from_encoded_point", - utils.PersistentlyDeprecated2019, - stacklevel=2, - ) - - if data.startswith(b"\x04"): - # key_size is in bits. Convert to bytes and round up - byte_length = (curve.key_size + 7) // 8 - if len(data) == 2 * byte_length + 1: - x = int.from_bytes(data[1 : byte_length + 1], "big") - y = int.from_bytes(data[byte_length + 1 :], "big") - return cls(x, y, curve) - else: - raise ValueError("Invalid elliptic curve point data length") - else: - raise ValueError("Unsupported elliptic curve point type") - @property def curve(self) -> EllipticCurve: return self._curve diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 67d813bef768..9c8189ee1d59 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -21,7 +21,6 @@ class CryptographyDeprecationWarning(UserWarning): # Several APIs were deprecated with no specific end-of-life date because of the # ubiquity of their use. They should not be removed until we agree on when that # cycle ends. -PersistentlyDeprecated2019 = CryptographyDeprecationWarning DeprecatedIn35 = CryptographyDeprecationWarning DeprecatedIn36 = CryptographyDeprecationWarning DeprecatedIn37 = CryptographyDeprecationWarning diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 707d23360743..6022b95022f7 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -12,14 +12,13 @@ import pytest -from cryptography import exceptions, utils, x509 +from cryptography import exceptions, x509 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric.utils import ( Prehashed, encode_dss_signature, ) -from cryptography.utils import CryptographyDeprecationWarning from .fixtures_ec import EC_KEY_SECP384R1 from .utils import skip_fips_traditional_openssl @@ -171,73 +170,6 @@ def test_invalid_private_numbers_public_numbers(): ec.EllipticCurvePrivateNumbers(1, None) # type: ignore[arg-type] -def test_encode_point(): - # secp256r1 point - x = int( - "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16 - ) - y = int( - "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16 - ) - pn = ec.EllipticCurvePublicNumbers(x, y, ec.SECP256R1()) - with pytest.warns(utils.PersistentlyDeprecated2019): - data = pn.encode_point() - assert data == binascii.unhexlify( - "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae" - "c3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e" - ) - - -def test_from_encoded_point(): - # secp256r1 point - data = binascii.unhexlify( - "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae" - "c3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e" - ) - with pytest.warns(CryptographyDeprecationWarning): - pn = ec.EllipticCurvePublicNumbers.from_encoded_point( - ec.SECP256R1(), data - ) - assert pn.x == int( - "233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22aec", 16 - ) - assert pn.y == int( - "3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460b35f442e", 16 - ) - - -def test_from_encoded_point_invalid_length(): - bad_data = binascii.unhexlify( - "04233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22ae" - "c3ea2c10a84153862be4ec82940f0543f9ba866af9751a6ee79d38460" - ) - with pytest.raises(ValueError): - with pytest.warns(CryptographyDeprecationWarning): - ec.EllipticCurvePublicNumbers.from_encoded_point( - ec.SECP384R1(), bad_data - ) - - -def test_from_encoded_point_unsupported_point_no_backend(): - # set to point type 2. - unsupported_type = binascii.unhexlify( - "02233ea3b0027127084cd2cd336a13aeef69c598d8af61369a36454a17c6c22a" - ) - with pytest.raises(ValueError): - with pytest.warns(CryptographyDeprecationWarning): - ec.EllipticCurvePublicNumbers.from_encoded_point( - ec.SECP256R1(), unsupported_type - ) - - -def test_from_encoded_point_not_a_curve(): - with pytest.raises(TypeError): - with pytest.warns(CryptographyDeprecationWarning): - ec.EllipticCurvePublicNumbers.from_encoded_point( - "notacurve", b"\x04data" # type: ignore[arg-type] - ) - - def test_ec_public_numbers_repr(): pn = ec.EllipticCurvePublicNumbers(2, 3, ec.SECP256R1()) assert repr(pn) == "" From 7f4b1a151478563011540cc3b03c0725a6d475fc Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 6 Sep 2022 23:58:56 -0400 Subject: [PATCH 006/298] Remove deprecated support for x.509 signing with SHA1 and MD5 (#7573) --- CHANGELOG.rst | 3 ++ src/cryptography/utils.py | 1 - src/rust/src/x509/oid.rs | 4 --- src/rust/src/x509/sign.rs | 47 -------------------------- tests/x509/test_x509.py | 69 +-------------------------------------- 5 files changed, 4 insertions(+), 120 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 90bdc75fa3c7..b209f97028b0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,9 @@ Changelog and :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point` should be used instead. +* **BACKWARDS INCOMPATIBLE:** Support for using MD5 or SHA1 in + :class:`~cryptography.x509.CertificateBuilder` and + other X.509 builders has been removed. .. _v38-0-0: diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 9c8189ee1d59..b3d7195b0efe 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -24,7 +24,6 @@ class CryptographyDeprecationWarning(UserWarning): DeprecatedIn35 = CryptographyDeprecationWarning DeprecatedIn36 = CryptographyDeprecationWarning DeprecatedIn37 = CryptographyDeprecationWarning -DeprecatedIn38 = CryptographyDeprecationWarning def _check_bytes(name: str, value: bytes) -> None: diff --git a/src/rust/src/x509/oid.rs b/src/rust/src/x509/oid.rs index 45cfc15db4ed..55477c60826a 100644 --- a/src/rust/src/x509/oid.rs +++ b/src/rust/src/x509/oid.rs @@ -43,7 +43,6 @@ pub(crate) const FRESHEST_CRL_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, pub(crate) const INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 54); // Signing methods -pub(crate) const ECDSA_WITH_SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 1); pub(crate) const ECDSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 3, 1); pub(crate) const ECDSA_WITH_SHA256_OID: asn1::ObjectIdentifier = @@ -61,8 +60,6 @@ pub(crate) const ECDSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier = pub(crate) const ECDSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 12); -pub(crate) const RSA_WITH_MD5_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 4); -pub(crate) const RSA_WITH_SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 5); pub(crate) const RSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 14); pub(crate) const RSA_WITH_SHA256_OID: asn1::ObjectIdentifier = @@ -80,7 +77,6 @@ pub(crate) const RSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier = pub(crate) const RSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 16); -pub(crate) const DSA_WITH_SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10040, 4, 3); pub(crate) const DSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 1); pub(crate) const DSA_WITH_SHA256_OID: asn1::ObjectIdentifier = diff --git a/src/rust/src/x509/sign.rs b/src/rust/src/x509/sign.rs index 4d9157505b5c..37860c3a5c7c 100644 --- a/src/rust/src/x509/sign.rs +++ b/src/rust/src/x509/sign.rs @@ -24,8 +24,6 @@ enum KeyType { enum HashType { None, - Md5, - Sha1, Sha224, Sha256, Sha384, @@ -97,32 +95,6 @@ fn identify_hash_type( .getattr(crate::intern!(py, "name"))? .extract()? { - "md5" => { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn38"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "MD5 signatures are deprecated and support for them will be removed in the next version.", - 1 - )?; - - Ok(HashType::Md5) - } - "sha1" => { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn38"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "SHA1 signatures are deprecated and support for them will be removed in the next version.", - 1 - )?; - - Ok(HashType::Sha1) - } "sha224" => Ok(HashType::Sha224), "sha256" => Ok(HashType::Sha256), "sha384" => Ok(HashType::Sha384), @@ -161,10 +133,6 @@ pub(crate) fn compute_signature_algorithm<'p>( )) } - (KeyType::Ec, HashType::Sha1) => Ok(x509::AlgorithmIdentifier { - oid: (oid::ECDSA_WITH_SHA1_OID).clone(), - params: None, - }), (KeyType::Ec, HashType::Sha224) => Ok(x509::AlgorithmIdentifier { oid: (oid::ECDSA_WITH_SHA224_OID).clone(), params: None, @@ -198,14 +166,6 @@ pub(crate) fn compute_signature_algorithm<'p>( params: None, }), - (KeyType::Rsa, HashType::Md5) => Ok(x509::AlgorithmIdentifier { - oid: (oid::RSA_WITH_MD5_OID).clone(), - params: Some(*NULL_TLV), - }), - (KeyType::Rsa, HashType::Sha1) => Ok(x509::AlgorithmIdentifier { - oid: (oid::RSA_WITH_SHA1_OID).clone(), - params: Some(*NULL_TLV), - }), (KeyType::Rsa, HashType::Sha224) => Ok(x509::AlgorithmIdentifier { oid: (oid::RSA_WITH_SHA224_OID).clone(), params: Some(*NULL_TLV), @@ -239,10 +199,6 @@ pub(crate) fn compute_signature_algorithm<'p>( params: Some(*NULL_TLV), }), - (KeyType::Dsa, HashType::Sha1) => Ok(x509::AlgorithmIdentifier { - oid: (oid::DSA_WITH_SHA1_OID).clone(), - params: None, - }), (KeyType::Dsa, HashType::Sha224) => Ok(x509::AlgorithmIdentifier { oid: (oid::DSA_WITH_SHA224_OID).clone(), params: None, @@ -269,9 +225,6 @@ pub(crate) fn compute_signature_algorithm<'p>( (_, HashType::None) => Err(pyo3::exceptions::PyTypeError::new_err( "Algorithm must be a registered hash algorithm, not None.", )), - (_, HashType::Md5) => Err(pyo3::exceptions::PyValueError::new_err( - "MD5 hash algorithm is only supported with RSA keys", - )), } } diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 55ecdfb01784..e89627ac0531 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1856,7 +1856,6 @@ def test_hash(self, backend): @pytest.mark.parametrize( ("hashalg", "hashalg_oid"), [ - (hashes.SHA1, x509.SignatureAlgorithmOID.RSA_WITH_SHA1), (hashes.SHA224, x509.SignatureAlgorithmOID.RSA_WITH_SHA224), (hashes.SHA256, x509.SignatureAlgorithmOID.RSA_WITH_SHA256), (hashes.SHA384, x509.SignatureAlgorithmOID.RSA_WITH_SHA384), @@ -2067,7 +2066,7 @@ def test_checks_for_unsupported_extensions(self, backend): ) with pytest.raises(NotImplementedError): - builder.sign(private_key, hashes.SHA1(), backend) + builder.sign(private_key, hashes.SHA256(), backend) def test_encode_nonstandard_aia(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -2640,28 +2639,6 @@ def test_sign_with_unsupported_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - def test_sign_rsa_with_md5(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - builder = x509.CertificateBuilder() - builder = ( - builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .serial_number(1) - .public_key(private_key.public_key()) - .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) - .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1)) - ) - cert = builder.sign(private_key, hashes.MD5(), backend) - assert isinstance(cert.signature_hash_algorithm, hashes.MD5) - @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -2728,7 +2705,6 @@ def test_sign_ec_with_md5(self, backend): @pytest.mark.parametrize( ("hashalg", "hashalg_oid"), [ - (hashes.SHA1, x509.SignatureAlgorithmOID.DSA_WITH_SHA1), (hashes.SHA224, x509.SignatureAlgorithmOID.DSA_WITH_SHA224), (hashes.SHA256, x509.SignatureAlgorithmOID.DSA_WITH_SHA256), (hashes.SHA384, x509.SignatureAlgorithmOID.DSA_WITH_SHA384), @@ -2791,7 +2767,6 @@ def test_build_cert_with_dsa_private_key( @pytest.mark.parametrize( ("hashalg", "hashalg_oid"), [ - (hashes.SHA1, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA1), (hashes.SHA224, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA224), (hashes.SHA256, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA256), (hashes.SHA384, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA384), @@ -3753,48 +3728,6 @@ def test_request_with_unsupported_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - def test_sign_rsa_with_md5(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - - builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) - ) - request = builder.sign(private_key, hashes.MD5(), backend) - assert isinstance(request.signature_hash_algorithm, hashes.MD5) - - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - @pytest.mark.supported( - only_if=lambda backend: backend.dsa_supported(), - skip_message="Does not support DSA.", - ) - def test_sign_dsa_with_md5(self, backend): - private_key = DSA_KEY_2048.private_key(backend) - builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) - ) - with pytest.raises(ValueError): - builder.sign(private_key, hashes.MD5(), backend) - - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - def test_sign_ec_with_md5(self, backend): - _skip_curve_unsupported(backend, ec.SECP256R1()) - private_key = EC_KEY_SECP256R1.private_key(backend) - builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) - ) - with pytest.raises(ValueError): - builder.sign(private_key, hashes.MD5(), backend) - def test_no_subject_name(self, backend): private_key = RSA_KEY_2048.private_key(backend) From d518a183680bc198dd19d316dd723987069c771a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 7 Sep 2022 19:51:25 +0800 Subject: [PATCH 007/298] fix parsing for CRLs with TLVs > 65535 bytes (#7575) * add CRL test vector with 9,999 revoked items * bump rust-asn1 * add large CRL test this tests CRLs larger than 65535 bytes in size. rust-asn1 supports up to 4GiB TLVs now, but we'll avoid putting a test vector that big for now --- docs/development/test-vectors.rst | 1 + src/rust/Cargo.lock | 8 +- src/rust/Cargo.toml | 2 +- tests/x509/test_x509.py | 8 + .../x509/custom/crl_almost_10k.pem | 4382 +++++++++++++++++ 5 files changed, 4396 insertions(+), 5 deletions(-) create mode 100644 vectors/cryptography_vectors/x509/custom/crl_almost_10k.pem diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 979c21f51727..121b2155d51e 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -597,6 +597,7 @@ Custom X.509 Certificate Revocation List Vectors * ``crl_no_next_time.pem`` - Contains a CRL with no ``nextUpdate`` value. The signature on this CRL is invalid. * ``crl_bad_version.pem`` - Contains a CRL with an invalid version. +* ``crl_almost_10k.pem`` - Contains a CRL with 9,999 entries. X.509 OCSP Test Vectors ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index e1fd9558b57b..4a0ecfd58df7 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "asn1" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "570eb4740d127e98f0b6b1b93adf0d2ad054bee6272284fcc029323d902c3095" +checksum = "22c27c85cd71c1bf4373c7c1aa752b73d2df799277c0930af16fffbf3444f210" dependencies = [ "asn1_derive", "chrono", @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56792f155e38317e455b140f625c0e8593af8cb7b072842024c37aae22f087ea" +checksum = "d48d1854a01241e8d22f8f5ae4e2dc332f66c5946e1772f5576886d83e18e1b7" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 271b29032008..49e70a30f7ee 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] once_cell = "1" pyo3 = { version = "0.15.2" } -asn1 = { version = "0.12.1", default-features = false, features = ["derive"] } +asn1 = { version = "0.12.2", default-features = false, features = ["derive"] } pem = "1.1" chrono = { version = "0.4.22", default-features = false, features = ["alloc", "clock"] } ouroboros = "0.15" diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index e89627ac0531..19047c87cb75 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -107,6 +107,14 @@ def test_load_der_crl(self, backend): assert fingerprint == b"dd3db63c50f4c4a13e090f14053227cb1011a5ad" assert isinstance(crl.signature_hash_algorithm, hashes.SHA256) + def test_load_large_crl(self, backend): + crl = _load_cert( + os.path.join("x509", "custom", "crl_almost_10k.pem"), + x509.load_pem_x509_crl, + backend, + ) + assert len(crl) == 9999 + def test_empty_crl_no_sequence(self, backend): # The SEQUENCE for revoked certificates is optional so let's # test that we handle it properly. diff --git a/vectors/cryptography_vectors/x509/custom/crl_almost_10k.pem b/vectors/cryptography_vectors/x509/custom/crl_almost_10k.pem new file mode 100644 index 000000000000..abe89572698b --- /dev/null +++ b/vectors/cryptography_vectors/x509/custom/crl_almost_10k.pem @@ -0,0 +1,4382 @@ +-----BEGIN X509 CRL----- +MIMDNSkwgwM0EAIBATANBgkqhkiG9w0BAQsFADAdMRswGQYDVQQDDBJjcnlwdG9n +cmFwaHkuaW8gQ0EXDTIyMDkwNzE5MDYyM1oXDTIyMDkwODE5MDYyM1owgwMzvDAS +AgEBFw0yMjA5MDcxOTA2MjNaMBICAQIXDTIyMDkwNzE5MDYyM1owEgIBAxcNMjIw +OTA3MTkwNjIzWjASAgEEFw0yMjA5MDcxOTA2MjNaMBICAQUXDTIyMDkwNzE5MDYy +M1owEgIBBhcNMjIwOTA3MTkwNjIzWjASAgEHFw0yMjA5MDcxOTA2MjNaMBICAQgX +DTIyMDkwNzE5MDYyM1owEgIBCRcNMjIwOTA3MTkwNjIzWjASAgEKFw0yMjA5MDcx +OTA2MjNaMBICAQsXDTIyMDkwNzE5MDYyM1owEgIBDBcNMjIwOTA3MTkwNjIzWjAS +AgENFw0yMjA5MDcxOTA2MjNaMBICAQ4XDTIyMDkwNzE5MDYyM1owEgIBDxcNMjIw +OTA3MTkwNjIzWjASAgEQFw0yMjA5MDcxOTA2MjNaMBICAREXDTIyMDkwNzE5MDYy +M1owEgIBEhcNMjIwOTA3MTkwNjIzWjASAgETFw0yMjA5MDcxOTA2MjNaMBICARQX +DTIyMDkwNzE5MDYyM1owEgIBFRcNMjIwOTA3MTkwNjIzWjASAgEWFw0yMjA5MDcx +OTA2MjNaMBICARcXDTIyMDkwNzE5MDYyM1owEgIBGBcNMjIwOTA3MTkwNjIzWjAS +AgEZFw0yMjA5MDcxOTA2MjNaMBICARoXDTIyMDkwNzE5MDYyM1owEgIBGxcNMjIw +OTA3MTkwNjIzWjASAgEcFw0yMjA5MDcxOTA2MjNaMBICAR0XDTIyMDkwNzE5MDYy +M1owEgIBHhcNMjIwOTA3MTkwNjIzWjASAgEfFw0yMjA5MDcxOTA2MjNaMBICASAX +DTIyMDkwNzE5MDYyM1owEgIBIRcNMjIwOTA3MTkwNjIzWjASAgEiFw0yMjA5MDcx +OTA2MjNaMBICASMXDTIyMDkwNzE5MDYyM1owEgIBJBcNMjIwOTA3MTkwNjIzWjAS +AgElFw0yMjA5MDcxOTA2MjNaMBICASYXDTIyMDkwNzE5MDYyM1owEgIBJxcNMjIw +OTA3MTkwNjIzWjASAgEoFw0yMjA5MDcxOTA2MjNaMBICASkXDTIyMDkwNzE5MDYy +M1owEgIBKhcNMjIwOTA3MTkwNjIzWjASAgErFw0yMjA5MDcxOTA2MjNaMBICASwX +DTIyMDkwNzE5MDYyM1owEgIBLRcNMjIwOTA3MTkwNjIzWjASAgEuFw0yMjA5MDcx +OTA2MjNaMBICAS8XDTIyMDkwNzE5MDYyM1owEgIBMBcNMjIwOTA3MTkwNjIzWjAS +AgExFw0yMjA5MDcxOTA2MjNaMBICATIXDTIyMDkwNzE5MDYyM1owEgIBMxcNMjIw +OTA3MTkwNjIzWjASAgE0Fw0yMjA5MDcxOTA2MjNaMBICATUXDTIyMDkwNzE5MDYy +M1owEgIBNhcNMjIwOTA3MTkwNjIzWjASAgE3Fw0yMjA5MDcxOTA2MjNaMBICATgX +DTIyMDkwNzE5MDYyM1owEgIBORcNMjIwOTA3MTkwNjIzWjASAgE6Fw0yMjA5MDcx +OTA2MjNaMBICATsXDTIyMDkwNzE5MDYyM1owEgIBPBcNMjIwOTA3MTkwNjIzWjAS +AgE9Fw0yMjA5MDcxOTA2MjNaMBICAT4XDTIyMDkwNzE5MDYyM1owEgIBPxcNMjIw +OTA3MTkwNjIzWjASAgFAFw0yMjA5MDcxOTA2MjNaMBICAUEXDTIyMDkwNzE5MDYy +M1owEgIBQhcNMjIwOTA3MTkwNjIzWjASAgFDFw0yMjA5MDcxOTA2MjNaMBICAUQX +DTIyMDkwNzE5MDYyM1owEgIBRRcNMjIwOTA3MTkwNjIzWjASAgFGFw0yMjA5MDcx +OTA2MjNaMBICAUcXDTIyMDkwNzE5MDYyM1owEgIBSBcNMjIwOTA3MTkwNjIzWjAS +AgFJFw0yMjA5MDcxOTA2MjNaMBICAUoXDTIyMDkwNzE5MDYyM1owEgIBSxcNMjIw +OTA3MTkwNjIzWjASAgFMFw0yMjA5MDcxOTA2MjNaMBICAU0XDTIyMDkwNzE5MDYy +M1owEgIBThcNMjIwOTA3MTkwNjIzWjASAgFPFw0yMjA5MDcxOTA2MjNaMBICAVAX +DTIyMDkwNzE5MDYyM1owEgIBURcNMjIwOTA3MTkwNjIzWjASAgFSFw0yMjA5MDcx +OTA2MjNaMBICAVMXDTIyMDkwNzE5MDYyM1owEgIBVBcNMjIwOTA3MTkwNjIzWjAS +AgFVFw0yMjA5MDcxOTA2MjNaMBICAVYXDTIyMDkwNzE5MDYyM1owEgIBVxcNMjIw +OTA3MTkwNjIzWjASAgFYFw0yMjA5MDcxOTA2MjNaMBICAVkXDTIyMDkwNzE5MDYy +M1owEgIBWhcNMjIwOTA3MTkwNjIzWjASAgFbFw0yMjA5MDcxOTA2MjNaMBICAVwX +DTIyMDkwNzE5MDYyM1owEgIBXRcNMjIwOTA3MTkwNjIzWjASAgFeFw0yMjA5MDcx +OTA2MjNaMBICAV8XDTIyMDkwNzE5MDYyM1owEgIBYBcNMjIwOTA3MTkwNjIzWjAS +AgFhFw0yMjA5MDcxOTA2MjNaMBICAWIXDTIyMDkwNzE5MDYyM1owEgIBYxcNMjIw +OTA3MTkwNjIzWjASAgFkFw0yMjA5MDcxOTA2MjNaMBICAWUXDTIyMDkwNzE5MDYy +M1owEgIBZhcNMjIwOTA3MTkwNjIzWjASAgFnFw0yMjA5MDcxOTA2MjNaMBICAWgX +DTIyMDkwNzE5MDYyM1owEgIBaRcNMjIwOTA3MTkwNjIzWjASAgFqFw0yMjA5MDcx +OTA2MjNaMBICAWsXDTIyMDkwNzE5MDYyM1owEgIBbBcNMjIwOTA3MTkwNjIzWjAS +AgFtFw0yMjA5MDcxOTA2MjNaMBICAW4XDTIyMDkwNzE5MDYyM1owEgIBbxcNMjIw +OTA3MTkwNjIzWjASAgFwFw0yMjA5MDcxOTA2MjNaMBICAXEXDTIyMDkwNzE5MDYy +M1owEgIBchcNMjIwOTA3MTkwNjIzWjASAgFzFw0yMjA5MDcxOTA2MjNaMBICAXQX +DTIyMDkwNzE5MDYyM1owEgIBdRcNMjIwOTA3MTkwNjIzWjASAgF2Fw0yMjA5MDcx +OTA2MjNaMBICAXcXDTIyMDkwNzE5MDYyM1owEgIBeBcNMjIwOTA3MTkwNjIzWjAS +AgF5Fw0yMjA5MDcxOTA2MjNaMBICAXoXDTIyMDkwNzE5MDYyM1owEgIBexcNMjIw +OTA3MTkwNjIzWjASAgF8Fw0yMjA5MDcxOTA2MjNaMBICAX0XDTIyMDkwNzE5MDYy +M1owEgIBfhcNMjIwOTA3MTkwNjIzWjASAgF/Fw0yMjA5MDcxOTA2MjNaMBMCAgCA +Fw0yMjA5MDcxOTA2MjNaMBMCAgCBFw0yMjA5MDcxOTA2MjNaMBMCAgCCFw0yMjA5 +MDcxOTA2MjNaMBMCAgCDFw0yMjA5MDcxOTA2MjNaMBMCAgCEFw0yMjA5MDcxOTA2 +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 +-----END X509 CRL----- From b376fd2109bab206af9dbd295a8b169b4610aada Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 7 Sep 2022 20:45:22 +0800 Subject: [PATCH 008/298] port 38.0.1 changelog (#7577) --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b209f97028b0..f47164d5d8a4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -24,6 +24,14 @@ Changelog :class:`~cryptography.x509.CertificateBuilder` and other X.509 builders has been removed. +.. _v38-0-1: + +38.0.1 - 2022-09-07 +~~~~~~~~~~~~~~~~~~~ + +* Fixed parsing TLVs in ASN.1 with length greater than 65535 bytes (typically + seen in large CRLs). + .. _v38-0-0: 38.0.0 - 2022-09-06 From 2bda121211f2204d1e1f0704c993ffb252c2b411 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 00:26:55 +0000 Subject: [PATCH 009/298] Bump BoringSSL version to 9f426b60fabf5e5fec0a0a05120de19289ef1fdf (#7580) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9f913f3b2bc3..e6e45f39eb97 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 07, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "2e295b91a3c441d32f985bef0dcff5e639f1f448"}} + # Latest commit on the master branch, as of Sep 08, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "9f426b60fabf5e5fec0a0a05120de19289ef1fdf"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 05c2b78bc8f90e797faf0d97a7dc2bb505e02a4e Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 9 Sep 2022 00:28:23 +0000 Subject: [PATCH 010/298] Bump BoringSSL version to 7b2795a323b41e7b148bcd6f6318d67efccb0ce4 (#7582) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e6e45f39eb97..be23522be496 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 08, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "9f426b60fabf5e5fec0a0a05120de19289ef1fdf"}} + # Latest commit on the master branch, as of Sep 09, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "7b2795a323b41e7b148bcd6f6318d67efccb0ce4"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1bc3d1c43d45980eb520853c45c48973b2c060ca Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 9 Sep 2022 19:07:36 -0400 Subject: [PATCH 011/298] Fix linkcheck -- ignore expired cert on SM3 website (#7583) --- docs/conf.py | 4 ++-- docs/hazmat/primitives/cryptographic-hashes.rst | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 0c38d4dbf598..3e39d80aabd4 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -203,8 +203,8 @@ r"https://www.secg.org/sec1-v2.pdf", # Incomplete cert chain r"https://e-trust.gosuslugi.ru", - # Expired cert (1 week at time of writing) - r"https://www.cosic.esat.kuleuven.be", + # Expired cert (2 days at time of writing) + r"https://www.oscca.gov.cn", ] autosectionlabel_prefix_document = True diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index 572822e400a9..b947455892e1 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -292,5 +292,5 @@ Interfaces .. _`Lifetimes of cryptographic hash functions`: https://valerieaurora.org/hash.html .. _`BLAKE2`: https://blake2.net .. _`length-extension attacks`: https://en.wikipedia.org/wiki/Length_extension_attack -.. _`GM/T 0004-2012`: http://www.oscca.gov.cn/sca/xxgk/2010-12/17/1002389/files/302a3ada057c4a73830536d03e683110.pdf +.. _`GM/T 0004-2012`: https://www.oscca.gov.cn/sca/xxgk/2010-12/17/1002389/files/302a3ada057c4a73830536d03e683110.pdf .. _`draft-sca-cfrg-sm3`: https://datatracker.ietf.org/doc/html/draft-sca-cfrg-sm3 From a76687cc01763743c4b27b7b20271769e88af869 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 10 Sep 2022 00:35:29 +0000 Subject: [PATCH 012/298] Bump BoringSSL version to 1b2b7b2e70ce5ff50df917ee7745403d824155c5 (#7585) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be23522be496..c0871a5bf6f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 09, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "7b2795a323b41e7b148bcd6f6318d67efccb0ce4"}} + # Latest commit on the master branch, as of Sep 10, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "1b2b7b2e70ce5ff50df917ee7745403d824155c5"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 2a7be33bb87217da2e093af07195397945a836a1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 9 Sep 2022 22:22:24 -0400 Subject: [PATCH 013/298] Add a comment explaining why the next MSRV might be 1.49 (#7584) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c0871a5bf6f1..35beb51f93f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -192,6 +192,7 @@ jobs: # the linux-rust-coverage section. Once our MSRV is 1.60 we can # remove this section entirely. - 1.48.0 + # 1.49.0 is the MSRV for parking_lot 0.12 - 1.49.0 name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" timeout-minutes: 15 From 07fa80f151cb3494ff7621cdb8aa7947da36105c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 09:08:56 -0400 Subject: [PATCH 014/298] fixes #7109 -- update final comments for having dropped 1.1.0 (#7591) --- src/cryptography/hazmat/backends/openssl/backend.py | 8 ++++---- src/cryptography/hazmat/backends/openssl/x25519.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index e1bcb398b8c0..5d47d8f11338 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1877,8 +1877,8 @@ def dh_x942_serialization_supported(self) -> bool: return self._lib.Cryptography_HAS_EVP_PKEY_DHX == 1 def x25519_load_public_bytes(self, data: bytes) -> x25519.X25519PublicKey: - # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can - # switch this to EVP_PKEY_new_raw_public_key + # If/when LibreSSL adds support for EVP_PKEY_new_raw_public_key we + # can switch to it (Cryptography_HAS_RAW_KEY) if len(data) != 32: raise ValueError("An X25519 public key is 32 bytes long") @@ -1894,8 +1894,8 @@ def x25519_load_public_bytes(self, data: bytes) -> x25519.X25519PublicKey: def x25519_load_private_bytes( self, data: bytes ) -> x25519.X25519PrivateKey: - # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can - # switch this to EVP_PKEY_new_raw_private_key and drop the + # If/when LibreSSL adds support for EVP_PKEY_new_raw_private_key we + # can switch to it (Cryptography_HAS_RAW_KEY) drop the # zeroed_bytearray garbage. # OpenSSL only has facilities for loading PKCS8 formatted private # keys using the algorithm identifiers specified in diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py index f68501a3488c..c09a50ac59ba 100644 --- a/src/cryptography/hazmat/backends/openssl/x25519.py +++ b/src/cryptography/hazmat/backends/openssl/x25519.py @@ -112,8 +112,8 @@ def private_bytes( ) def _raw_private_bytes(self) -> bytes: - # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 we can - # switch this to EVP_PKEY_new_raw_private_key + # If/when LibreSSL adds support for EVP_PKEY_get_raw_private_key we + # can switch to it (Cryptography_HAS_RAW_KEY) # The trick we use here is serializing to a PKCS8 key and just # using the last 32 bytes, which is the key itself. bio = self._backend._create_mem_bio_gc() From af2222696dc866d95c81dc375927577923a4b040 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 09:34:38 -0400 Subject: [PATCH 015/298] Remove pyOpenSSL fallback. (#7590) We already require pyOpenSSL>=22.0, but pyOpenSSL has not required this fallback since 21.0. --- .../hazmat/backends/openssl/backend.py | 16 ------ .../hazmat/backends/openssl/x509.py | 45 ---------------- src/cryptography/utils.py | 1 - src/rust/src/x509/certificate.rs | 21 -------- src/rust/src/x509/crl.rs | 22 -------- src/rust/src/x509/csr.rs | 22 -------- tests/hazmat/backends/test_openssl.py | 54 ------------------- 7 files changed, 181 deletions(-) delete mode 100644 src/cryptography/hazmat/backends/openssl/x509.py diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 5d47d8f11338..5b4929ae8254 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1084,14 +1084,6 @@ def _csr2ossl(self, csr: x509.CertificateSigningRequest) -> typing.Any: x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) return x509_req - def _ossl2csr( - self, x509_req: typing.Any - ) -> x509.CertificateSigningRequest: - bio = self._create_mem_bio_gc() - res = self._lib.i2d_X509_REQ_bio(bio, x509_req) - self.openssl_assert(res == 1) - return rust_x509.load_der_x509_csr(self._read_mem_bio(bio)) - def _crl2ossl(self, crl: x509.CertificateRevocationList) -> typing.Any: data = crl.public_bytes(serialization.Encoding.DER) mem_bio = self._bytes_to_bio(data) @@ -1100,14 +1092,6 @@ def _crl2ossl(self, crl: x509.CertificateRevocationList) -> typing.Any: x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) return x509_crl - def _ossl2crl( - self, x509_crl: typing.Any - ) -> x509.CertificateRevocationList: - bio = self._create_mem_bio_gc() - res = self._lib.i2d_X509_CRL_bio(bio, x509_crl) - self.openssl_assert(res == 1) - return rust_x509.load_der_x509_crl(self._read_mem_bio(bio)) - def _crl_is_signature_valid( self, crl: x509.CertificateRevocationList, diff --git a/src/cryptography/hazmat/backends/openssl/x509.py b/src/cryptography/hazmat/backends/openssl/x509.py deleted file mode 100644 index aa4ed106cba5..000000000000 --- a/src/cryptography/hazmat/backends/openssl/x509.py +++ /dev/null @@ -1,45 +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 warnings - -from cryptography import utils, x509 - - -# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED -# WE WILL REMOVE THIS VERY SOON. -def _Certificate(backend, x509) -> x509.Certificate: # noqa: N802 - warnings.warn( - "This version of cryptography contains a temporary pyOpenSSL " - "fallback path. Upgrade pyOpenSSL now.", - utils.DeprecatedIn35, - ) - return backend._ossl2cert(x509) - - -# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED -# WE WILL REMOVE THIS VERY SOON. -def _CertificateSigningRequest( # noqa: N802 - backend, x509_req -) -> x509.CertificateSigningRequest: - warnings.warn( - "This version of cryptography contains a temporary pyOpenSSL " - "fallback path. Upgrade pyOpenSSL now.", - utils.DeprecatedIn35, - ) - return backend._ossl2csr(x509_req) - - -# This exists for pyOpenSSL compatibility and SHOULD NOT BE USED -# WE WILL REMOVE THIS VERY SOON. -def _CertificateRevocationList( # noqa: N802 - backend, x509_crl -) -> x509.CertificateRevocationList: - warnings.warn( - "This version of cryptography contains a temporary pyOpenSSL " - "fallback path. Upgrade pyOpenSSL now.", - utils.DeprecatedIn35, - ) - return backend._ossl2crl(x509_crl) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index b3d7195b0efe..75ca8889b07d 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -21,7 +21,6 @@ class CryptographyDeprecationWarning(UserWarning): # Several APIs were deprecated with no specific end-of-life date because of the # ubiquity of their use. They should not be removed until we agree on when that # cycle ends. -DeprecatedIn35 = CryptographyDeprecationWarning DeprecatedIn36 = CryptographyDeprecationWarning DeprecatedIn37 = CryptographyDeprecationWarning diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs index 59841d74a8db..549e89681d42 100644 --- a/src/rust/src/x509/certificate.rs +++ b/src/rust/src/x509/certificate.rs @@ -340,27 +340,6 @@ impl Certificate { }, ) } - // This getter exists for compatibility with pyOpenSSL and will be removed. - // DO NOT RELY ON IT. WE WILL BREAK YOU WHEN WE FEEL LIKE IT. - #[getter] - fn _x509<'p>( - slf: pyo3::PyRef<'_, Self>, - py: pyo3::Python<'p>, - ) -> Result<&'p pyo3::PyAny, PyAsn1Error> { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn35"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "This version of cryptography contains a temporary pyOpenSSL fallback path. Upgrade pyOpenSSL now.", - 1 - )?; - let backend = py - .import("cryptography.hazmat.backends.openssl.backend")? - .getattr(crate::intern!(py, "backend"))?; - Ok(backend.call_method1("_cert2ossl", (slf,))?) - } } fn cert_version(py: pyo3::Python<'_>, version: u8) -> Result<&pyo3::PyAny, PyAsn1Error> { diff --git a/src/rust/src/x509/crl.rs b/src/rust/src/x509/crl.rs index b34de1072462..2152b2f5e6fa 100644 --- a/src/rust/src/x509/crl.rs +++ b/src/rust/src/x509/crl.rs @@ -400,28 +400,6 @@ impl CertificateRevocationList { .getattr(crate::intern!(py, "backend"))?; backend.call_method1("_crl_is_signature_valid", (slf, public_key)) } - - // This getter exists for compatibility with pyOpenSSL and will be removed. - // DO NOT RELY ON IT. WE WILL BREAK YOU WHEN WE FEEL LIKE IT. - #[getter] - fn _x509_crl<'p>( - slf: pyo3::PyRef<'_, Self>, - py: pyo3::Python<'p>, - ) -> Result<&'p pyo3::PyAny, PyAsn1Error> { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn35"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "This version of cryptography contains a temporary pyOpenSSL fallback path. Upgrade pyOpenSSL now.", - 1 - )?; - let backend = py - .import("cryptography.hazmat.backends.openssl.backend")? - .getattr(crate::intern!(py, "backend"))?; - Ok(backend.call_method1("_crl2ossl", (slf,))?) - } } #[pyo3::prelude::pyproto] diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs index 7579bccb9602..80ee8701b6c9 100644 --- a/src/rust/src/x509/csr.rs +++ b/src/rust/src/x509/csr.rs @@ -295,28 +295,6 @@ impl CertificateSigningRequest { .getattr(crate::intern!(py, "backend"))?; backend.call_method1("_csr_is_signature_valid", (slf,)) } - - // This getter exists for compatibility with pyOpenSSL and will be removed. - // DO NOT RELY ON IT. WE WILL BREAK YOU WHEN WE FEEL LIKE IT. - #[getter] - fn _x509_req<'p>( - slf: pyo3::PyRef<'_, Self>, - py: pyo3::Python<'p>, - ) -> Result<&'p pyo3::PyAny, PyAsn1Error> { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn35"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "This version of cryptography contains a temporary pyOpenSSL fallback path. Upgrade pyOpenSSL now.", - 1, - )?; - let backend = py - .import("cryptography.hazmat.backends.openssl.backend")? - .getattr(crate::intern!(py, "backend"))?; - Ok(backend.call_method1("_csr2ossl", (slf,))?) - } } #[pyo3::prelude::pyfunction] diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 6cc4499a9ab7..7830019cac6a 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -11,7 +11,6 @@ import pytest -from cryptography import utils, x509 from cryptography.exceptions import InternalError, _Reasons from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends.openssl.backend import backend @@ -35,7 +34,6 @@ load_vectors_from_file, raises_unsupported_algorithm, ) -from ...x509.test_x509 import _load_cert def skip_if_libre_ssl(openssl_version): @@ -599,55 +597,3 @@ def test_public_load_dhx_unsupported(self, key_path, loader_func, backend): ) with pytest.raises(ValueError): loader_func(key_bytes, backend) - - -def test_pyopenssl_cert_fallback(): - cert = _load_cert( - os.path.join("x509", "cryptography.io.pem"), - x509.load_pem_x509_certificate, - ) - x509_ossl = None - with pytest.warns(utils.CryptographyDeprecationWarning): - x509_ossl = cert._x509 # type:ignore[attr-defined] - assert x509_ossl is not None - - from cryptography.hazmat.backends.openssl.x509 import _Certificate - - with pytest.warns(utils.CryptographyDeprecationWarning): - _Certificate(backend, x509_ossl) - - -def test_pyopenssl_csr_fallback(): - cert = _load_cert( - os.path.join("x509", "requests", "rsa_sha256.pem"), - x509.load_pem_x509_csr, - ) - req_ossl = None - with pytest.warns(utils.CryptographyDeprecationWarning): - req_ossl = cert._x509_req # type:ignore[attr-defined] - assert req_ossl is not None - - from cryptography.hazmat.backends.openssl.x509 import ( - _CertificateSigningRequest, - ) - - with pytest.warns(utils.CryptographyDeprecationWarning): - _CertificateSigningRequest(backend, req_ossl) - - -def test_pyopenssl_crl_fallback(): - cert = _load_cert( - os.path.join("x509", "PKITS_data", "crls", "GoodCACRL.crl"), - x509.load_der_x509_crl, - ) - req_crl = None - with pytest.warns(utils.CryptographyDeprecationWarning): - req_crl = cert._x509_crl # type:ignore[attr-defined] - assert req_crl is not None - - from cryptography.hazmat.backends.openssl.x509 import ( - _CertificateRevocationList, - ) - - with pytest.warns(utils.CryptographyDeprecationWarning): - _CertificateRevocationList(backend, req_crl) From 52a4ff452e67a1474628fd00d9bfdb3a792d37c1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 11:35:33 -0400 Subject: [PATCH 016/298] remove openssl header include that no longer appears required (#7592) --- src/_cffi_src/openssl/cryptography.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index e8b4489ca231..0ffd438c47d1 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -24,13 +24,6 @@ #define CRYPTOGRAPHY_IS_BORINGSSL 0 #endif -/* - LibreSSL removed e_os2.h from the public headers so we'll only include it - if we're using vanilla OpenSSL. -*/ -#if !CRYPTOGRAPHY_IS_LIBRESSL -#include -#endif #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN #include From 7b266ba5b820a11fbdf5971a8a76a96ea42a99b8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 12:01:18 -0400 Subject: [PATCH 017/298] remove outdated comments and simplify code (#7594) --- src/cryptography/hazmat/backends/openssl/backend.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 5b4929ae8254..4c5106d43bb9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -690,8 +690,7 @@ def _evp_pkey_to_private_key(self, evp_pkey) -> PRIVATE_KEY_TYPES: elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 return _X448PrivateKey(self, evp_pkey) - elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None): - # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0 + elif key_type == self._lib.EVP_PKEY_X25519: return _X25519PrivateKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1 @@ -748,11 +747,10 @@ def _evp_pkey_to_public_key(self, evp_pkey) -> PUBLIC_KEY_TYPES: elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 return _X448PublicKey(self, evp_pkey) - elif key_type == getattr(self._lib, "EVP_PKEY_X25519", None): - # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.0 + elif key_type == self._lib.EVP_PKEY_X25519: return _X25519PublicKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): - # EVP_PKEY_X25519 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1 return _Ed448PublicKey(self, evp_pkey) else: raise UnsupportedAlgorithm("Unsupported key type.") From 2c3c6d2f861bfac8de38607429c85fdc6e21a79d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 12:17:36 -0400 Subject: [PATCH 018/298] simplify code now that we're >=1.1.1 only (#7595) --- src/cryptography/hazmat/backends/openssl/backend.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 4c5106d43bb9..10f1d5ed773a 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2446,9 +2446,7 @@ def _load_pkcs7_certificates(self, p7): x509 = self._lib.sk_X509_value(sk_x509, i) self.openssl_assert(x509 != self._ffi.NULL) res = self._lib.X509_up_ref(x509) - # When OpenSSL is less than 1.1.0 up_ref returns the current - # refcount. On 1.1.0+ it returns 1 for success. - self.openssl_assert(res >= 1) + self.openssl_assert(res == 1) x509 = self._ffi.gc(x509, self._lib.X509_free) cert = self._ossl2cert(x509) certs.append(cert) From 8bc691f580836648e977a59c1800e205e926141b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 12:22:15 -0400 Subject: [PATCH 019/298] fix comment, no version of openssl has these (#7596) --- docs/hazmat/primitives/cryptographic-hashes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/cryptographic-hashes.rst b/docs/hazmat/primitives/cryptographic-hashes.rst index b947455892e1..b6c889df4a81 100644 --- a/docs/hazmat/primitives/cryptographic-hashes.rst +++ b/docs/hazmat/primitives/cryptographic-hashes.rst @@ -117,7 +117,7 @@ SHA-family of hashes. .. note:: While the RFC specifies keying, personalization, and salting features, - these are not supported at this time due to limitations in OpenSSL 1.1.0. + these are not supported at this time due to limitations in OpenSSL. .. class:: BLAKE2b(digest_size) From b564cd6725fa09cf19ad8bb132cebdf7a3d7a0be Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sun, 11 Sep 2022 18:26:42 +0200 Subject: [PATCH 020/298] implement __deepcopy__() for ObjectIdentifier (fixes #7587) (#7597) --- src/rust/src/oid.rs | 4 ++++ tests/hazmat/test_oid.py | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/src/rust/src/oid.rs b/src/rust/src/oid.rs index bc65daf4e4cd..724f78eaac32 100644 --- a/src/rust/src/oid.rs +++ b/src/rust/src/oid.rs @@ -35,6 +35,10 @@ impl ObjectIdentifier { .getattr(crate::intern!(py, "_OID_NAMES"))?; oid_names.call_method1("get", (slf, "Unknown OID")) } + + fn __deepcopy__(slf: pyo3::PyRef<'_, Self>, _memo: pyo3::PyObject) -> pyo3::PyRef<'_, Self> { + slf + } } #[pyo3::prelude::pyproto] diff --git a/tests/hazmat/test_oid.py b/tests/hazmat/test_oid.py index 8fa7d2b063f6..f537abcd517a 100644 --- a/tests/hazmat/test_oid.py +++ b/tests/hazmat/test_oid.py @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import copy import pytest @@ -12,6 +13,15 @@ def test_basic_oid(): assert ObjectIdentifier("1.2.3.4").dotted_string == "1.2.3.4" +def test_oid_equal(): + assert ObjectIdentifier("1.2.3.4") == ObjectIdentifier("1.2.3.4") + + +def test_oid_deepcopy(): + oid = ObjectIdentifier("1.2.3.4") + assert oid == copy.deepcopy(oid) + + def test_oid_constraint(): # Too short with pytest.raises(ValueError): From 7989ea6b5213f498859c44c646b0da1ce957243c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 14:06:19 -0400 Subject: [PATCH 021/298] Final set of cleanups to comments and bindings for dropping OpenSSL 1.1.0 (#7598) --- src/_cffi_src/openssl/evp.py | 2 +- src/cryptography/hazmat/backends/openssl/backend.py | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 91f61a77e2e9..1d8026af31ab 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -230,7 +230,7 @@ static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 1; #endif -/* OpenSSL 1.1.0+ does this define for us, but if not present we'll do it */ +/* These defines are needed for CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 */ #if !defined(EVP_CTRL_AEAD_SET_IVLEN) # define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN #endif diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 10f1d5ed773a..0262fe50a635 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -685,15 +685,15 @@ def _evp_pkey_to_private_key(self, evp_pkey) -> PRIVATE_KEY_TYPES: dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHPrivateKey(self, dh_cdata, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None): - # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_ED25519 is not present in CRYPTOGRAPHY_IS_LIBRESSL return _Ed25519PrivateKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): - # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_X448 is not present in CRYPTOGRAPHY_IS_LIBRESSL return _X448PrivateKey(self, evp_pkey) elif key_type == self._lib.EVP_PKEY_X25519: return _X25519PrivateKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): - # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_ED448 is not present in CRYPTOGRAPHY_IS_LIBRESSL return _Ed448PrivateKey(self, evp_pkey) else: raise UnsupportedAlgorithm("Unsupported key type.") @@ -742,15 +742,15 @@ def _evp_pkey_to_public_key(self, evp_pkey) -> PUBLIC_KEY_TYPES: dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHPublicKey(self, dh_cdata, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED25519", None): - # EVP_PKEY_ED25519 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_ED25519 is not present in CRYPTOGRAPHY_IS_LIBRESSL return _Ed25519PublicKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_X448", None): - # EVP_PKEY_X448 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_X448 is not present in CRYPTOGRAPHY_IS_LIBRESSL return _X448PublicKey(self, evp_pkey) elif key_type == self._lib.EVP_PKEY_X25519: return _X25519PublicKey(self, evp_pkey) elif key_type == getattr(self._lib, "EVP_PKEY_ED448", None): - # EVP_PKEY_ED448 is not present in OpenSSL < 1.1.1 + # EVP_PKEY_ED448 is not present in CRYPTOGRAPHY_IS_LIBRESSL return _Ed448PublicKey(self, evp_pkey) else: raise UnsupportedAlgorithm("Unsupported key type.") From 66762b0f8c9e6911a14c15796a9160a13eaa7b1e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 11 Sep 2022 13:24:54 -0500 Subject: [PATCH 022/298] add more benchmarks for AEAD for upcoming optimizations (#7599) * add more benchmarks for AEAD for upcoming optimizations * black --- tests/bench/test_aead.py | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/tests/bench/test_aead.py b/tests/bench/test_aead.py index 9eb3fc12f265..a153818d3535 100644 --- a/tests/bench/test_aead.py +++ b/tests/bench/test_aead.py @@ -4,7 +4,13 @@ import pytest -from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 +from cryptography.hazmat.primitives.ciphers.aead import ( + AESCCM, + AESGCM, + AESOCB3, + AESSIV, + ChaCha20Poly1305, +) from ..hazmat.primitives.test_aead import _aead_supported @@ -16,3 +22,35 @@ def test_chacha20poly1305(benchmark): chacha = ChaCha20Poly1305(b"\x00" * 32) benchmark(chacha.encrypt, b"\x00" * 12, b"hello world plaintext", b"") + + +def test_aesgcm(benchmark): + aes = AESGCM(b"\x00" * 32) + benchmark(aes.encrypt, b"\x00" * 12, b"hello world plaintext", None) + + +@pytest.mark.skipif( + not _aead_supported(AESSIV), + reason="Requires OpenSSL with AES-SIV support", +) +def test_aessiv(benchmark): + aes = AESSIV(b"\x00" * 32) + benchmark(aes.encrypt, b"hello world plaintext", None) + + +@pytest.mark.skipif( + not _aead_supported(AESOCB3), + reason="Requires OpenSSL with AES-OCB3 support", +) +def test_aesocb3(benchmark): + aes = AESOCB3(b"\x00" * 32) + benchmark(aes.encrypt, b"\x00" * 12, b"hello world plaintext", None) + + +@pytest.mark.skipif( + not _aead_supported(AESCCM), + reason="Requires OpenSSL with AES-CCM support", +) +def test_aesccm(benchmark): + aes = AESCCM(b"\x00" * 32) + benchmark(aes.encrypt, b"\x00" * 12, b"hello world plaintext", None) From d480268f294701a4897d0c82a468bc8f16c5dd10 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 11 Sep 2022 14:28:43 -0500 Subject: [PATCH 023/298] benchmark both enc and dec (#7600) --- tests/bench/test_aead.py | 56 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 5 deletions(-) diff --git a/tests/bench/test_aead.py b/tests/bench/test_aead.py index a153818d3535..f93c4e8892eb 100644 --- a/tests/bench/test_aead.py +++ b/tests/bench/test_aead.py @@ -19,38 +19,84 @@ not _aead_supported(ChaCha20Poly1305), reason="Requires OpenSSL with ChaCha20Poly1305 support", ) -def test_chacha20poly1305(benchmark): +def test_chacha20poly1305_encrypt(benchmark): chacha = ChaCha20Poly1305(b"\x00" * 32) benchmark(chacha.encrypt, b"\x00" * 12, b"hello world plaintext", b"") -def test_aesgcm(benchmark): +@pytest.mark.skipif( + not _aead_supported(ChaCha20Poly1305), + reason="Requires OpenSSL with ChaCha20Poly1305 support", +) +def test_chacha20poly1305_decrypt(benchmark): + chacha = ChaCha20Poly1305(b"\x00" * 32) + ct = chacha.encrypt(b"\x00" * 12, b"hello world plaintext", b"") + benchmark(chacha.decrypt, b"\x00" * 12, ct, b"") + + +def test_aesgcm_encrypt(benchmark): aes = AESGCM(b"\x00" * 32) benchmark(aes.encrypt, b"\x00" * 12, b"hello world plaintext", None) +def test_aesgcm_decrypt(benchmark): + aes = AESGCM(b"\x00" * 32) + ct = aes.encrypt(b"\x00" * 12, b"hello world plaintext", None) + benchmark(aes.decrypt, b"\x00" * 12, ct, None) + + @pytest.mark.skipif( not _aead_supported(AESSIV), reason="Requires OpenSSL with AES-SIV support", ) -def test_aessiv(benchmark): +def test_aessiv_encrypt(benchmark): aes = AESSIV(b"\x00" * 32) benchmark(aes.encrypt, b"hello world plaintext", None) +@pytest.mark.skipif( + not _aead_supported(AESSIV), + reason="Requires OpenSSL with AES-SIV support", +) +def test_aessiv_decrypt(benchmark): + aes = AESSIV(b"\x00" * 32) + ct = aes.encrypt(b"hello world plaintext", None) + benchmark(aes.decrypt, ct, None) + + @pytest.mark.skipif( not _aead_supported(AESOCB3), reason="Requires OpenSSL with AES-OCB3 support", ) -def test_aesocb3(benchmark): +def test_aesocb3_encrypt(benchmark): aes = AESOCB3(b"\x00" * 32) benchmark(aes.encrypt, b"\x00" * 12, b"hello world plaintext", None) +@pytest.mark.skipif( + not _aead_supported(AESOCB3), + reason="Requires OpenSSL with AES-OCB3 support", +) +def test_aesocb3_decrypt(benchmark): + aes = AESOCB3(b"\x00" * 32) + ct = aes.encrypt(b"\x00" * 12, b"hello world plaintext", None) + benchmark(aes.decrypt, b"\x00" * 12, ct, None) + + @pytest.mark.skipif( not _aead_supported(AESCCM), reason="Requires OpenSSL with AES-CCM support", ) -def test_aesccm(benchmark): +def test_aesccm_encrypt(benchmark): aes = AESCCM(b"\x00" * 32) benchmark(aes.encrypt, b"\x00" * 12, b"hello world plaintext", None) + + +@pytest.mark.skipif( + not _aead_supported(AESCCM), + reason="Requires OpenSSL with AES-CCM support", +) +def test_aesccm_decrypt(benchmark): + aes = AESCCM(b"\x00" * 32) + ct = aes.encrypt(b"\x00" * 12, b"hello world plaintext", None) + benchmark(aes.decrypt, b"\x00" * 12, ct, None) From 30114c6ea9b8fca98d88bfe90aa2f39b6182820d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 11 Sep 2022 18:45:22 -0400 Subject: [PATCH 024/298] Remove destroy from FixedPool (#7602) turns out we don't need it --- .../hazmat/bindings/_rust/__init__.pyi | 1 - src/rust/src/pool.rs | 24 ++----------------- tests/test_rust_utils.py | 16 ++++--------- 3 files changed, 6 insertions(+), 35 deletions(-) diff --git a/src/cryptography/hazmat/bindings/_rust/__init__.pyi b/src/cryptography/hazmat/bindings/_rust/__init__.pyi index bab90a5aea29..c33769054b40 100644 --- a/src/cryptography/hazmat/bindings/_rust/__init__.pyi +++ b/src/cryptography/hazmat/bindings/_rust/__init__.pyi @@ -20,7 +20,6 @@ class FixedPool(typing.Generic[T]): def __init__( self, create: typing.Callable[[], T], - destroy: typing.Callable[[T], None], ) -> None: ... def acquire(self) -> PoolAcquisition[T]: ... diff --git a/src/rust/src/pool.rs b/src/rust/src/pool.rs index 9dacd7f76d9b..384273a69b57 100644 --- a/src/rust/src/pool.rs +++ b/src/rust/src/pool.rs @@ -10,7 +10,6 @@ use std::cell::Cell; #[pyo3::prelude::pyclass] pub(crate) struct FixedPool { create_fn: pyo3::PyObject, - destroy_fn: pyo3::PyObject, value: Cell>, } @@ -26,16 +25,11 @@ struct PoolAcquisition { #[pyo3::pymethods] impl FixedPool { #[new] - fn new( - py: pyo3::Python<'_>, - create: pyo3::PyObject, - destroy: pyo3::PyObject, - ) -> pyo3::PyResult { + fn new(py: pyo3::Python<'_>, create: pyo3::PyObject) -> pyo3::PyResult { let value = create.call0(py)?; Ok(FixedPool { create_fn: create, - destroy_fn: destroy, value: Cell::new(Some(value)), }) @@ -60,18 +54,6 @@ impl FixedPool { } } -impl Drop for FixedPool { - fn drop(&mut self) { - if let Some(value) = self.value.replace(None) { - let gil = pyo3::Python::acquire_gil(); - let py = gil.python(); - self.destroy_fn - .call1(py, (value,)) - .expect("FixedPool destroy function failed in destructor"); - } - } -} - #[pyo3::pymethods] impl PoolAcquisition { fn __enter__(&self, py: pyo3::Python<'_>) -> pyo3::PyObject { @@ -86,9 +68,7 @@ impl PoolAcquisition { _exc_tb: &pyo3::PyAny, ) -> pyo3::PyResult<()> { let pool = self.pool.as_ref(py).borrow(); - if self.fresh { - pool.destroy_fn.call1(py, (self.value.clone_ref(py),))?; - } else { + if !self.fresh { pool.value.replace(Some(self.value.clone_ref(py))); } Ok(()) diff --git a/tests/test_rust_utils.py b/tests/test_rust_utils.py index 99ddfb01a6eb..1ee68541e7fc 100644 --- a/tests/test_rust_utils.py +++ b/tests/test_rust_utils.py @@ -19,10 +19,7 @@ def create(): events.append(("create", c)) return c - def destroy(c): - events.append(("destroy", c)) - - pool = FixedPool(create, destroy) + pool = FixedPool(create) assert events == [("create", 1)] with pool.acquire() as c: assert c == 1 @@ -32,9 +29,9 @@ def destroy(c): assert c == 2 assert events == [("create", 1), ("create", 2)] - assert events == [("create", 1), ("create", 2), ("destroy", 2)] + assert events == [("create", 1), ("create", 2)] - assert events == [("create", 1), ("create", 2), ("destroy", 2)] + assert events == [("create", 1), ("create", 2)] del pool gc.collect() @@ -44,18 +41,13 @@ def destroy(c): assert events == [ ("create", 1), ("create", 2), - ("destroy", 2), - ("destroy", 1), ] def test_thread_stress(self): def create(): return None - def destroy(c): - pass - - pool = FixedPool(create, destroy) + pool = FixedPool(create) def thread_fn(): with pool.acquire(): From d6382bb0ceac8927efbbf2878d72b8554c144ef6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 11 Sep 2022 22:27:54 -0500 Subject: [PATCH 025/298] use fixed pool to improve perf of aead ChaCha20Poly1305 (#7601) * use fixed pool to improve perf of aead ChaCha20Poly1305 ~35-45% speedup on benchmarks when reusing the same key for multiple operations * remove unneeded call --- .../hazmat/backends/openssl/aead.py | 84 +++++++++++++++---- .../hazmat/primitives/ciphers/aead.py | 15 +++- 2 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py index f7914af5fa45..aa106fc3a3df 100644 --- a/src/cryptography/hazmat/backends/openssl/aead.py +++ b/src/cryptography/hazmat/backends/openssl/aead.py @@ -63,6 +63,29 @@ def _evp_cipher(cipher_name: bytes, backend: "Backend"): return evp_cipher +def _aead_create_ctx( + backend: "Backend", + cipher: "_AEAD_TYPES", + key: bytes, +): + ctx = backend._lib.EVP_CIPHER_CTX_new() + backend.openssl_assert(ctx != backend._ffi.NULL) + ctx = backend._ffi.gc(ctx, backend._lib.EVP_CIPHER_CTX_free) + cipher_name = _aead_cipher_name(cipher) + evp_cipher = _evp_cipher(cipher_name, backend) + key_ptr = backend._ffi.from_buffer(key) + res = backend._lib.EVP_CipherInit_ex( + ctx, + evp_cipher, + backend._ffi.NULL, + key_ptr, + backend._ffi.NULL, + 0, + ) + backend.openssl_assert(res != 0) + return ctx + + def _aead_setup( backend: "Backend", cipher_name: bytes, @@ -84,8 +107,7 @@ def _aead_setup( int(operation == _ENCRYPT), ) backend.openssl_assert(res != 0) - res = backend._lib.EVP_CIPHER_CTX_set_key_length(ctx, len(key)) - backend.openssl_assert(res != 0) + # CCM requires the IVLEN to be set before calling SET_TAG on decrypt res = backend._lib.EVP_CIPHER_CTX_ctrl( ctx, backend._lib.EVP_CTRL_AEAD_SET_IVLEN, @@ -95,10 +117,7 @@ def _aead_setup( backend.openssl_assert(res != 0) if operation == _DECRYPT: assert tag is not None - res = backend._lib.EVP_CIPHER_CTX_ctrl( - ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag - ) - backend.openssl_assert(res != 0) + _set_tag(backend, ctx, tag) elif cipher_name.endswith(b"-ccm"): res = backend._lib.EVP_CIPHER_CTX_ctrl( ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, tag_len, backend._ffi.NULL @@ -119,6 +138,26 @@ def _aead_setup( return ctx +def _set_tag(backend, ctx, tag: bytes) -> None: + res = backend._lib.EVP_CIPHER_CTX_ctrl( + ctx, backend._lib.EVP_CTRL_AEAD_SET_TAG, len(tag), tag + ) + backend.openssl_assert(res != 0) + + +def _set_nonce_operation(backend, ctx, nonce: bytes, operation: int) -> None: + nonce_ptr = backend._ffi.from_buffer(nonce) + res = backend._lib.EVP_CipherInit_ex( + ctx, + backend._ffi.NULL, + backend._ffi.NULL, + backend._ffi.NULL, + nonce_ptr, + int(operation == _ENCRYPT), + ) + backend.openssl_assert(res != 0) + + def _set_length(backend: "Backend", ctx, data_len: int) -> None: intptr = backend._ffi.new("int *") res = backend._lib.EVP_CipherUpdate( @@ -153,13 +192,24 @@ def _encrypt( data: bytes, associated_data: typing.List[bytes], tag_length: int, + ctx: typing.Any = None, ) -> bytes: from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESSIV - cipher_name = _aead_cipher_name(cipher) - ctx = _aead_setup( - backend, cipher_name, cipher._key, nonce, None, tag_length, _ENCRYPT - ) + if ctx is None: + cipher_name = _aead_cipher_name(cipher) + ctx = _aead_setup( + backend, + cipher_name, + cipher._key, + nonce, + None, + tag_length, + _ENCRYPT, + ) + else: + _set_nonce_operation(backend, ctx, nonce, _ENCRYPT) + # CCM requires us to pass the length of the data before processing anything # However calling this with any other AEAD results in an error if isinstance(cipher, AESCCM): @@ -200,6 +250,7 @@ def _decrypt( data: bytes, associated_data: typing.List[bytes], tag_length: int, + ctx: typing.Any = None, ) -> bytes: from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESSIV @@ -215,10 +266,15 @@ def _decrypt( else: tag = data[-tag_length:] data = data[:-tag_length] - cipher_name = _aead_cipher_name(cipher) - ctx = _aead_setup( - backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT - ) + if ctx is None: + cipher_name = _aead_cipher_name(cipher) + ctx = _aead_setup( + backend, cipher_name, cipher._key, nonce, tag, tag_length, _DECRYPT + ) + else: + _set_nonce_operation(backend, ctx, nonce, _DECRYPT) + _set_tag(backend, ctx, tag) + # CCM requires us to pass the length of the data before processing anything # However calling this with any other AEAD results in an error if isinstance(cipher, AESCCM): diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index 3cdb3ebe4d46..b4564cfcc8bb 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -9,6 +9,7 @@ from cryptography import exceptions, utils from cryptography.hazmat.backends.openssl import aead from cryptography.hazmat.backends.openssl.backend import backend +from cryptography.hazmat.bindings._rust import FixedPool class ChaCha20Poly1305: @@ -26,11 +27,15 @@ def __init__(self, key: bytes): raise ValueError("ChaCha20Poly1305 key must be 32 bytes.") self._key = key + self._pool = FixedPool(self._create_fn) @classmethod def generate_key(cls) -> bytes: return os.urandom(32) + def _create_fn(self): + return aead._aead_create_ctx(backend, self, self._key) + def encrypt( self, nonce: bytes, @@ -47,7 +52,10 @@ def encrypt( ) self._check_params(nonce, data, associated_data) - return aead._encrypt(backend, self, nonce, data, [associated_data], 16) + with self._pool.acquire() as ctx: + return aead._encrypt( + backend, self, nonce, data, [associated_data], 16, ctx + ) def decrypt( self, @@ -59,7 +67,10 @@ def decrypt( associated_data = b"" self._check_params(nonce, data, associated_data) - return aead._decrypt(backend, self, nonce, data, [associated_data], 16) + with self._pool.acquire() as ctx: + return aead._decrypt( + backend, self, nonce, data, [associated_data], 16, ctx + ) def _check_params( self, From 6ed65686b3865596804804869b2b9b2963d0f5ca Mon Sep 17 00:00:00 2001 From: gpotter2 <10530980+gpotter2@users.noreply.github.com> Date: Tue, 13 Sep 2022 00:08:45 +0200 Subject: [PATCH 026/298] Add downstream test for scapy (#7604) --- .github/downstream.d/scapy.sh | 18 ++++++++++++++++++ .github/workflows/ci.yml | 1 + 2 files changed, 19 insertions(+) create mode 100755 .github/downstream.d/scapy.sh diff --git a/.github/downstream.d/scapy.sh b/.github/downstream.d/scapy.sh new file mode 100755 index 000000000000..ac1b8f820016 --- /dev/null +++ b/.github/downstream.d/scapy.sh @@ -0,0 +1,18 @@ +#!/bin/bash -ex + +case "${1}" in + install) + git clone --depth=1 https://github.com/secdev/scapy + cd scapy + git rev-parse HEAD + pip install tox + ;; + run) + cd scapy + # this tox case uses sitepackages=true to use local cryptography + tox -qe cryptography + ;; + *) + exit 1 + ;; +esac diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 35beb51f93f1..b562797d7dee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -460,6 +460,7 @@ jobs: - certbot - certbot-josepy - mitmproxy + - scapy PYTHON: - 3.9 name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" From f5974704307a25ff7cf32c3c25e7cba402e5ea6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 12:20:30 +0000 Subject: [PATCH 027/298] Bump js-sys from 0.3.59 to 0.3.60 in /src/rust (#7606) Bumps [js-sys](https://github.com/rustwasm/wasm-bindgen) from 0.3.59 to 0.3.60. - [Release notes](https://github.com/rustwasm/wasm-bindgen/releases) - [Changelog](https://github.com/rustwasm/wasm-bindgen/blob/main/CHANGELOG.md) - [Commits](https://github.com/rustwasm/wasm-bindgen/commits) --- updated-dependencies: - dependency-name: js-sys dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4a0ecfd58df7..828be020a86f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -152,9 +152,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.59" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -433,9 +433,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -443,9 +443,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -458,9 +458,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -468,9 +468,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -481,9 +481,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "winapi" From 7ddc0771b00df28b145259ad887c0034832fb746 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Sep 2022 12:48:17 +0000 Subject: [PATCH 028/298] Bump iana-time-zone from 0.1.47 to 0.1.48 in /src/rust (#7608) Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.47 to 0.1.48. - [Release notes](https://github.com/strawlab/iana-time-zone/releases) - [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md) - [Commits](https://github.com/strawlab/iana-time-zone/compare/v0.1.47...v0.1.48) --- updated-dependencies: - dependency-name: iana-time-zone dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 828be020a86f..968b0aa4900e 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.47" +version = "0.1.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" +checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" dependencies = [ "android_system_properties", "core-foundation-sys", From 984bcb27a6da73bffcef9ccee754bb6e34c02212 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 13 Sep 2022 09:31:54 -0400 Subject: [PATCH 029/298] Move to a libressl policy (#7605) This policy is to support things that are in supported versions of openbsd. the current oldest supported openbsd is 7.0, which included libressl 3.4 --- .github/workflows/ci.yml | 1 - CHANGELOG.rst | 6 ++++-- docs/installation.rst | 5 +++-- src/_cffi_src/openssl/cryptography.py | 4 ---- src/_cffi_src/openssl/evp.py | 11 ----------- src/_cffi_src/openssl/ssl.py | 13 ++----------- .../hazmat/backends/openssl/backend.py | 5 ----- .../hazmat/bindings/openssl/_conditional.py | 18 ------------------ 8 files changed, 9 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b562797d7dee..fa643dd75076 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,6 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.3.6"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f47164d5d8a4..f9f9aece8f3f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,8 +10,10 @@ Changelog * **BACKWARDS INCOMPATIBLE:** Support for OpenSSL 1.1.0 has been removed. Users on older version of OpenSSL will need to upgrade. -* **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL 3.1.x, 3.2.x, - 3.3.0, and 3.3.1. The new minimum LibreSSL version is 3.3.2+. +* **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL < 3.4. The new + minimum LibreSSL version is 3.4.0. Going forward our policy is to support + versions of LibreSSL that are available in versions of OpenBSD that are + still receiving security support. * **BACKWARDS INCOMPATIBLE:** Removed the ``encode_point`` and ``from_encoded_point`` methods on :class:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicNumbers`, diff --git a/docs/installation.rst b/docs/installation.rst index 44dc9519bf12..344c7454e8aa 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -34,8 +34,9 @@ OpenSSL releases: * ``OpenSSL 1.1.1-latest`` * ``OpenSSL 3.0-latest`` -In addition we test against several versions of LibreSSL and the latest commit -in BoringSSL. +In addition we test against versions of LibreSSL that are available in +versions of OpenBSD that are receiving security support at the time of a given +``cryptography`` release, and the latest commit in BoringSSL. Building cryptography on Windows diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 0ffd438c47d1..306eaa9df62c 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -32,13 +32,10 @@ #endif #if CRYPTOGRAPHY_IS_LIBRESSL -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 \ - (LIBRESSL_VERSION_NUMBER < 0x3040000f) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 \ (LIBRESSL_VERSION_NUMBER < 0x3050000f) #else -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 (0) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 (0) #endif @@ -73,7 +70,6 @@ static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111E; static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE; -static const int CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340; static const int CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350; static const int CRYPTOGRAPHY_IS_LIBRESSL; diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 1d8026af31ab..6fd816ff96ff 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -34,7 +34,6 @@ static const int Cryptography_HAS_SCRYPT; static const int Cryptography_HAS_EVP_PKEY_DHX; static const int Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint; -static const int Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY; static const long Cryptography_HAS_RAW_KEY; static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF; static const long Cryptography_HAS_300_FIPS; @@ -203,16 +202,6 @@ size_t) = NULL; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 -static const long Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY = 0; -int (*EVP_DigestSign)(EVP_MD_CTX *, unsigned char *, size_t *, - const unsigned char *tbs, size_t) = NULL; -int (*EVP_DigestVerify)(EVP_MD_CTX *, const unsigned char *, size_t, - const unsigned char *, size_t) = NULL; -#else -static const long Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY = 1; -#endif - #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_RAW_KEY = 0; static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 0; diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 66305bca9fce..e70e15a186a7 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -15,7 +15,6 @@ static const long Cryptography_HAS_SSL3_METHOD; static const long Cryptography_HAS_TLSv1_1; static const long Cryptography_HAS_TLSv1_2; -static const long Cryptography_HAS_TLSv1_3; static const long Cryptography_HAS_TLSv1_3_FUNCTIONS; static const long Cryptography_HAS_SECURE_RENEGOTIATION; static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS; @@ -741,15 +740,7 @@ SRTP_PROTECTION_PROFILE * (*SSL_get_selected_srtp_profile)(SSL *) = NULL; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 -static const long Cryptography_HAS_TLSv1_3 = 0; -static const long TLS1_3_VERSION = 0; -static const long SSL_OP_NO_TLSv1_3 = 0; -#else -static const long Cryptography_HAS_TLSv1_3 = 1; -#endif - -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 || CRYPTOGRAPHY_IS_BORINGSSL +#if CRYPTOGRAPHY_IS_BORINGSSL static const long Cryptography_HAS_TLSv1_3_FUNCTIONS = 0; static const long SSL_VERIFY_POST_HANDSHAKE = 0; @@ -802,7 +793,7 @@ size_t *, SSL_SESSION ** )) = NULL; -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340 || CRYPTOGRAPHY_IS_BORINGSSL +#if CRYPTOGRAPHY_IS_BORINGSSL const SSL_CIPHER *(*SSL_CIPHER_find)(SSL *, const unsigned char *) = NULL; #endif int (*SSL_SESSION_set1_master_key)(SSL_SESSION *, const unsigned char *, diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 0262fe50a635..0ff154d3fdce 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2173,11 +2173,6 @@ def load_pkcs12( p12, password_buf, evp_pkey_ptr, x509_ptr, sk_x509_ptr ) - # Workaround for - # https://github.com/libressl-portable/portable/issues/659 - if self._lib.CRYPTOGRAPHY_LIBRESSL_LESS_THAN_340: - self._consume_errors() - if res == 0: self._consume_errors() raise ValueError("Invalid password or PKCS12 data") diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 549bb50e07c0..8c35ca36ea74 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -88,13 +88,6 @@ def cryptography_has_poly1305() -> typing.List[str]: ] -def cryptography_has_oneshot_evp_digest_sign_verify() -> typing.List[str]: - return [ - "EVP_DigestSign", - "EVP_DigestVerify", - ] - - def cryptography_has_evp_digestfinal_xof() -> typing.List[str]: return [ "EVP_DigestFinalXOF", @@ -155,13 +148,6 @@ def cryptography_has_openssl_cleanup() -> typing.List[str]: ] -def cryptography_has_tlsv13() -> typing.List[str]: - return [ - "TLS1_3_VERSION", - "SSL_OP_NO_TLSv1_3", - ] - - def cryptography_has_tlsv13_functions() -> typing.List[str]: return [ "SSL_VERIFY_POST_HANDSHAKE", @@ -328,9 +314,6 @@ def cryptography_has_ssl_op_ignore_unexpected_eof() -> typing.List[str]: "Cryptography_HAS_ED448": cryptography_has_ed448, "Cryptography_HAS_ED25519": cryptography_has_ed25519, "Cryptography_HAS_POLY1305": cryptography_has_poly1305, - "Cryptography_HAS_ONESHOT_EVP_DIGEST_SIGN_VERIFY": ( - cryptography_has_oneshot_evp_digest_sign_verify - ), "Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint": ( cryptography_has_evp_pkey_get_set_tls_encodedpoint ), @@ -340,7 +323,6 @@ def cryptography_has_ssl_op_ignore_unexpected_eof() -> typing.List[str]: "Cryptography_HAS_PSK_TLSv1_3": cryptography_has_psk_tlsv13, "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup, - "Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13, "Cryptography_HAS_TLSv1_3_FUNCTIONS": cryptography_has_tlsv13_functions, "Cryptography_HAS_KEYLOG": cryptography_has_keylog, "Cryptography_HAS_RAW_KEY": cryptography_has_raw_key, From a6d96615aae41994669529faa761709f6a3078a0 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 00:25:00 +0000 Subject: [PATCH 030/298] Bump BoringSSL version to 91e0b11eba517d83b910b20fe3740eeb39ecb37e (#7609) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa643dd75076..9355dd759ec8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,8 +41,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 10, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "1b2b7b2e70ce5ff50df917ee7745403d824155c5"}} + # Latest commit on the master branch, as of Sep 14, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "91e0b11eba517d83b910b20fe3740eeb39ecb37e"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From ddcdc084255f59c38f351692351453f271062316 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 13 Sep 2022 19:41:04 -0500 Subject: [PATCH 031/298] undef some conflicting macro/types on windows (#7588) related: https://chromium.googlesource.com/chromium/src/+/refs/heads/main/base/win/wincrypt_shim.h this only affects boring on windows as of this commit --- src/_cffi_src/openssl/bio.py | 4 ++++ src/_cffi_src/openssl/cryptography.py | 23 ++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py index 3e83f2fb1905..658cd33362b0 100644 --- a/src/_cffi_src/openssl/bio.py +++ b/src/_cffi_src/openssl/bio.py @@ -43,7 +43,11 @@ CUSTOMIZATIONS = """ #if CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_IS_BORINGSSL + +#if !defined(_WIN32) #include +#endif + #include typedef struct sockaddr BIO_ADDR; diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 306eaa9df62c..605e62db5bde 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -9,6 +9,22 @@ after we drop 1.0.2 support in the distant future. */ #define OPENSSL_API_COMPAT 0x10001000L +#if defined(_WIN32) +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +/* + undef some macros that are defined by wincrypt.h but are also types in + boringssl. openssl has worked around this but boring has not yet. see: + https://chromium.googlesource.com/chromium/src/+/refs/heads/main/base + /win/wincrypt_shim.h +*/ +#undef X509_NAME +#undef X509_EXTENSIONS +#undef PKCS7_SIGNER_INFO +#endif + #include @@ -24,13 +40,6 @@ #define CRYPTOGRAPHY_IS_BORINGSSL 0 #endif -#if defined(_WIN32) -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#endif - #if CRYPTOGRAPHY_IS_LIBRESSL #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 \ (LIBRESSL_VERSION_NUMBER < 0x3050000f) From ed13a1c7ff7cb73f07cb53e071d9bff82c9cb30f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 13 Sep 2022 22:23:24 -0400 Subject: [PATCH 032/298] remove unused branch in bindings (#7610) --- src/_cffi_src/openssl/evp.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 6fd816ff96ff..86b67089dfc7 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -282,10 +282,4 @@ #else static const long Cryptography_HAS_EVP_PKEY_DH = 1; #endif - -// This can be removed when we drop OpenSSL 1.1.0 support -// OPENSSL_LESS_THAN_111 -#if !defined(EVP_PKEY_RSA_PSS) -#define EVP_PKEY_RSA_PSS 912 -#endif """ From 93a7f37535f7f09292b8936289f495e160f77585 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 13 Sep 2022 23:39:40 -0400 Subject: [PATCH 033/298] Remove reimplementation of OpenSSL function in DHX (#7611) --- src/_cffi_src/openssl/dh.py | 19 +++++-------------- .../hazmat/backends/openssl/backend.py | 4 +--- .../hazmat/backends/openssl/dh.py | 2 +- .../hazmat/bindings/openssl/_conditional.py | 2 ++ 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py index c378ad1b4da5..ff13789f0549 100644 --- a/src/_cffi_src/openssl/dh.py +++ b/src/_cffi_src/openssl/dh.py @@ -31,8 +31,8 @@ int DH_generate_parameters_ex(DH *, int, int, BN_GENCB *); DH *d2i_DHparams_bio(BIO *, DH **); int i2d_DHparams_bio(BIO *, DH *); -DH *Cryptography_d2i_DHxparams_bio(BIO *, DH **); -int Cryptography_i2d_DHxparams_bio(BIO *, DH *); +DH *d2i_DHxparams_bio(BIO *, DH **); +int i2d_DHxparams_bio(BIO *, DH *); """ CUSTOMIZATIONS = """ @@ -148,17 +148,8 @@ } #endif -/* These functions were added in OpenSSL 1.1.0f commit d0c50e80a8 */ -/* Define our own to simplify support across all versions. */ -#if defined(EVP_PKEY_DHX) && EVP_PKEY_DHX != -1 -DH *Cryptography_d2i_DHxparams_bio(BIO *bp, DH **x) { - return ASN1_d2i_bio_of(DH, DH_new, d2i_DHxparams, bp, x); -} -int Cryptography_i2d_DHxparams_bio(BIO *bp, DH *x) { - return ASN1_i2d_bio_of_const(DH, i2d_DHxparams, bp, x); -} -#else -DH *(*Cryptography_d2i_DHxparams_bio)(BIO *bp, DH **x) = NULL; -int (*Cryptography_i2d_DHxparams_bio)(BIO *bp, DH *x) = NULL; +#if !(defined(EVP_PKEY_DHX) && EVP_PKEY_DHX != -1) +DH *(*d2i_DHxparams_bio)(BIO *bp, DH **x) = NULL; +int (*i2d_DHxparams_bio)(BIO *bp, DH *x) = NULL; #endif """ diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 0ff154d3fdce..908cf68ffae9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1051,9 +1051,7 @@ def load_der_parameters(self, data: bytes) -> dh.DHParameters: self._consume_errors() res = self._lib.BIO_reset(mem_bio.bio) self.openssl_assert(res == 1) - dh_cdata = self._lib.Cryptography_d2i_DHxparams_bio( - mem_bio.bio, self._ffi.NULL - ) + dh_cdata = self._lib.d2i_DHxparams_bio(mem_bio.bio, self._ffi.NULL) if dh_cdata != self._ffi.NULL: dh_cdata = self._ffi.gc(dh_cdata, self._lib.DH_free) return _DHParameters(self, dh_cdata) diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index 70364a3c6170..33fed6a40394 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -93,7 +93,7 @@ def parameter_bytes( write_bio = self._backend._lib.PEM_write_bio_DHparams elif encoding is serialization.Encoding.DER: if q[0] != self._backend._ffi.NULL: - write_bio = self._backend._lib.Cryptography_i2d_DHxparams_bio + write_bio = self._backend._lib.i2d_DHxparams_bio else: write_bio = self._backend._lib.i2d_DHparams_bio else: diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 8c35ca36ea74..e71319573598 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -51,6 +51,8 @@ def cryptography_has_scrypt() -> typing.List[str]: def cryptography_has_evp_pkey_dhx() -> typing.List[str]: return [ "EVP_PKEY_DHX", + "d2i_DHxparams_bio", + "i2d_DHxparams_bio", ] From 0938abf4fa3dd1ecae7fdc3715f836cef7cbaf00 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 12:20:32 +0000 Subject: [PATCH 034/298] Bump unicode-ident from 1.0.3 to 1.0.4 in /src/rust (#7612) Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.3 to 1.0.4. - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.3...1.0.4) --- updated-dependencies: - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 968b0aa4900e..74f83449a238 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -415,9 +415,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unindent" From b95dd4afc038342ef55a38f25c9eb9004c41cc34 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 14 Sep 2022 21:32:03 -0500 Subject: [PATCH 035/298] Bump BoringSSL version to 04989786e9ab16cef5261bbd05a2b1a8cb312dbf (#7615) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9355dd759ec8..5ff11fbc4f19 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,8 +41,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 14, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "91e0b11eba517d83b910b20fe3740eeb39ecb37e"}} + # Latest commit on the master branch, as of Sep 15, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "04989786e9ab16cef5261bbd05a2b1a8cb312dbf"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1ef786c571b7e5da3748470c2a0f892842be9c96 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 14 Sep 2022 23:12:53 -0400 Subject: [PATCH 036/298] Act on a bunch of comments saying things are const (#7616) --- src/_cffi_src/openssl/asn1.py | 10 ++++------ src/_cffi_src/openssl/bio.py | 1 - src/_cffi_src/openssl/crypto.py | 1 - src/_cffi_src/openssl/dh.py | 1 - src/_cffi_src/openssl/dsa.py | 1 - src/_cffi_src/openssl/evp.py | 4 +--- src/_cffi_src/openssl/rsa.py | 1 - src/_cffi_src/openssl/ssl.py | 3 --- src/_cffi_src/openssl/x509.py | 21 ++++++++------------- src/_cffi_src/openssl/x509name.py | 18 +++++++----------- src/_cffi_src/openssl/x509v3.py | 4 ++-- 11 files changed, 22 insertions(+), 43 deletions(-) diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 17ded38b3151..0e392349ef57 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -71,13 +71,11 @@ void ASN1_ENUMERATED_free(ASN1_ENUMERATED *); int ASN1_ENUMERATED_set(ASN1_ENUMERATED *, long); -/* These became const ASN1_* in 1.1.0 */ -int ASN1_STRING_type(ASN1_STRING *); -int ASN1_STRING_to_UTF8(unsigned char **, ASN1_STRING *); -int i2a_ASN1_INTEGER(BIO *, ASN1_INTEGER *); +int ASN1_STRING_type(const ASN1_STRING *); +int ASN1_STRING_to_UTF8(unsigned char **, const ASN1_STRING *); +int i2a_ASN1_INTEGER(BIO *, const ASN1_INTEGER *); -/* This became const ASN1_TIME in 1.1.0f */ -ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *, +ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(const ASN1_TIME *, ASN1_GENERALIZEDTIME **); int ASN1_STRING_length(ASN1_STRING *); diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py index 658cd33362b0..6207cb2e20be 100644 --- a/src/_cffi_src/openssl/bio.py +++ b/src/_cffi_src/openssl/bio.py @@ -21,7 +21,6 @@ int BIO_read(BIO *, void *, int); int BIO_gets(BIO *, char *, int); int BIO_write(BIO *, const void *, int); -/* Added in 1.1.0 */ int BIO_up_ref(BIO *); BIO *BIO_new(BIO_METHOD *); diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index 4f1d29dcb0a1..5a1ffcc0edbd 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -33,7 +33,6 @@ unsigned long OpenSSL_version_num(void); const char *OpenSSL_version(int); -/* this is a macro in 1.1.0 */ void *OPENSSL_malloc(size_t); void OPENSSL_free(void *); diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py index ff13789f0549..cbf2e9a0a82d 100644 --- a/src/_cffi_src/openssl/dh.py +++ b/src/_cffi_src/openssl/dh.py @@ -20,7 +20,6 @@ int DH_generate_key(DH *); DH *DHparams_dup(DH *); -/* added in 1.1.0 when the DH struct was opaqued */ void DH_get0_pqg(const DH *, const BIGNUM **, const BIGNUM **, const BIGNUM **); int DH_set0_pqg(DH *, BIGNUM *, BIGNUM *, BIGNUM *); diff --git a/src/_cffi_src/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py index 7f3f452eb019..cf34913b530b 100644 --- a/src/_cffi_src/openssl/dsa.py +++ b/src/_cffi_src/openssl/dsa.py @@ -22,7 +22,6 @@ int DSA_verify(int, const unsigned char *, int, const unsigned char *, int, DSA *); -/* added in 1.1.0 to access the opaque struct */ void DSA_get0_pqg(const DSA *, const BIGNUM **, const BIGNUM **, const BIGNUM **); int DSA_set0_pqg(DSA *, BIGNUM *, BIGNUM *, BIGNUM *); diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 86b67089dfc7..efd408cf6606 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -133,13 +133,11 @@ const unsigned char *, size_t); int EVP_DigestVerify(EVP_MD_CTX *, const unsigned char *, size_t, const unsigned char *, size_t); -/* Added in 1.1.0 */ size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *, unsigned char **); int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *, const unsigned char *, size_t); -/* EVP_PKEY * became const in 1.1.0 */ -int EVP_PKEY_bits(EVP_PKEY *); +int EVP_PKEY_bits(const EVP_PKEY *); void OpenSSL_add_all_algorithms(void); int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *); diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py index c8e3e5a9190e..b1f6e4a4d645 100644 --- a/src/_cffi_src/openssl/rsa.py +++ b/src/_cffi_src/openssl/rsa.py @@ -27,7 +27,6 @@ int RSA_blinding_on(RSA *, BN_CTX *); int RSA_print(BIO *, const RSA *, int); -/* added in 1.1.0 when the RSA struct was opaqued */ int RSA_set0_key(RSA *, BIGNUM *, BIGNUM *, BIGNUM *); int RSA_set0_factors(RSA *, BIGNUM *, BIGNUM *); int RSA_set0_crt_params(RSA *, BIGNUM *, BIGNUM *, BIGNUM *); diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index e70e15a186a7..7740b91e8ee8 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -321,9 +321,7 @@ Cryptography_STACK_OF_X509_NAME *SSL_load_client_CA_file(const char *); const char *SSL_get_servername(const SSL *, const int); -/* Function signature changed to const char * in 1.1.0 */ const char *SSL_CIPHER_get_version(const SSL_CIPHER *); -/* These became macros in 1.1.0 */ int SSL_library_init(void); void SSL_load_error_strings(void); @@ -470,7 +468,6 @@ int SSL_SESSION_set1_id_context(SSL_SESSION *, const unsigned char *, unsigned int); -/* Added in 1.1.0 for the great opaquing of structs */ size_t SSL_SESSION_get_master_key(const SSL_SESSION *, unsigned char *, size_t); size_t SSL_get_client_random(const SSL *, unsigned char *, size_t); diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py index 4ba14924ab50..5b06ad772090 100644 --- a/src/_cffi_src/openssl/x509.py +++ b/src/_cffi_src/openssl/x509.py @@ -156,24 +156,20 @@ int i2d_RSAPublicKey_bio(BIO *, RSA *); int i2d_DSAPrivateKey_bio(BIO *, DSA *); -/* These became const X509 in 1.1.0 */ -int X509_get_ext_count(X509 *); -X509_EXTENSION *X509_get_ext(X509 *, int); -X509_NAME *X509_get_subject_name(X509 *); -X509_NAME *X509_get_issuer_name(X509 *); +int X509_get_ext_count(const X509 *); +X509_EXTENSION *X509_get_ext(const X509 *, int); +X509_NAME *X509_get_subject_name(const X509 *); +X509_NAME *X509_get_issuer_name(const X509 *); -/* This became const ASN1_OBJECT * in 1.1.0 */ X509_EXTENSION *X509_EXTENSION_create_by_OBJ(X509_EXTENSION **, - ASN1_OBJECT *, int, + const ASN1_OBJECT *, int, ASN1_OCTET_STRING *); -/* This became const X509_EXTENSION * in 1.1.0 */ -int X509_EXTENSION_get_critical(X509_EXTENSION *); +int X509_EXTENSION_get_critical(const X509_EXTENSION *); -/* This became const X509_REVOKED * in 1.1.0 */ -int X509_REVOKED_get_ext_count(X509_REVOKED *); -X509_EXTENSION *X509_REVOKED_get_ext(X509_REVOKED *, int); +int X509_REVOKED_get_ext_count(const X509_REVOKED *); +X509_EXTENSION *X509_REVOKED_get_ext(const X509_REVOKED *, int); X509_REVOKED *X509_REVOKED_dup(X509_REVOKED *); @@ -219,7 +215,6 @@ EC_KEY *d2i_ECPrivateKey_bio(BIO *, EC_KEY **); int i2d_ECPrivateKey_bio(BIO *, EC_KEY *); -/* these functions were added in 1.1.0 */ const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *); const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *); """ diff --git a/src/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py index 37b0d9e74d42..6fdc2a3c1732 100644 --- a/src/_cffi_src/openssl/x509name.py +++ b/src/_cffi_src/openssl/x509name.py @@ -32,23 +32,19 @@ int X509_NAME_get_index_by_NID(X509_NAME *, int, int); int X509_NAME_cmp(const X509_NAME *, const X509_NAME *); X509_NAME *X509_NAME_dup(X509_NAME *); -/* These became const X509_NAME * in 1.1.0 */ -int X509_NAME_entry_count(X509_NAME *); -X509_NAME_ENTRY *X509_NAME_get_entry(X509_NAME *, int); -char *X509_NAME_oneline(X509_NAME *, char *, int); +int X509_NAME_entry_count(const X509_NAME *); +X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *, int); +char *X509_NAME_oneline(const X509_NAME *, char *, int); -/* These became const X509_NAME_ENTRY * in 1.1.0 */ -ASN1_OBJECT *X509_NAME_ENTRY_get_object(X509_NAME_ENTRY *); -ASN1_STRING *X509_NAME_ENTRY_get_data(X509_NAME_ENTRY *); +ASN1_OBJECT *X509_NAME_ENTRY_get_object(const X509_NAME_ENTRY *); +ASN1_STRING *X509_NAME_ENTRY_get_data(const X509_NAME_ENTRY *); int X509_NAME_add_entry(X509_NAME *, X509_NAME_ENTRY *, int, int); -/* this became const unsigned char * in 1.1.0 */ -int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, unsigned char *, +int X509_NAME_add_entry_by_NID(X509_NAME *, int, int, const unsigned char *, int, int, int); -/* These became const ASN1_OBJECT * in 1.1.0 */ X509_NAME_ENTRY *X509_NAME_ENTRY_create_by_OBJ(X509_NAME_ENTRY **, - ASN1_OBJECT *, int, + const ASN1_OBJECT *, int, const unsigned char *, int); Cryptography_STACK_OF_X509_NAME *sk_X509_NAME_new_null(void); diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 46569bdc0f1d..863973fc0d08 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -48,8 +48,8 @@ int GENERAL_NAME_print(BIO *, GENERAL_NAME *); void GENERAL_NAMES_free(GENERAL_NAMES *); void *X509V3_EXT_d2i(X509_EXTENSION *); -/* The last two char * args became const char * in 1.1.0 */ -X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, char *, char *); +X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, const char *, + const char *); void *X509V3_set_ctx_nodb(X509V3_CTX *); From 2b9e230e5c4be2d140b83b84c74dccb8283a3b62 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 16 Sep 2022 08:59:42 -0400 Subject: [PATCH 037/298] document to do a pyopenssl release after major cryptography version releases (#7618) --- docs/doing-a-release.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/doing-a-release.rst b/docs/doing-a-release.rst index 12d6bb063f18..c1571226e990 100644 --- a/docs/doing-a-release.rst +++ b/docs/doing-a-release.rst @@ -82,18 +82,20 @@ the expected OpenSSL version. Post-release tasks ------------------ +* Send an email to the `mailing list`_ and `python-announce`_ announcing the + release. +* Close the `milestone`_ for the previous release on GitHub. +* For major version releases, send a pull request to pyOpenSSL increasing the + maximum ``cryptography`` version pin and perform a pyOpenSSL release. * Update the version number to the next major (e.g. ``0.5.dev1``) in ``src/cryptography/__about__.py`` and ``vectors/cryptography_vectors/__about__.py``. -* Close the `milestone`_ for the previous release on GitHub. * Add new :doc:`/changelog` entry with next version and note that it is under active development * Send a pull request with these items * Check for any outstanding code undergoing a deprecation cycle by looking in ``cryptography.utils`` for ``DeprecatedIn**`` definitions. If any exist open a ticket to increment them for the next release. -* Send an email to the `mailing list`_ and `python-announce`_ announcing the - release. .. _`CVE from MITRE`: https://cveform.mitre.org/ .. _`oss-security`: https://www.openwall.com/lists/oss-security/ From 6c6163fe1af502890a70158e9a4a762c2d5a1578 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 16 Sep 2022 21:58:00 -0400 Subject: [PATCH 038/298] delete a few more old comments (#7619) --- src/_cffi_src/openssl/evp.py | 1 - src/_cffi_src/openssl/ssl.py | 8 -------- src/_cffi_src/openssl/x509_vfy.py | 1 - 3 files changed, 10 deletions(-) diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index efd408cf6606..fabc455c3ba8 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -128,7 +128,6 @@ EVP_MD_CTX *EVP_MD_CTX_new(void); void EVP_MD_CTX_free(EVP_MD_CTX *); -/* Added in 1.1.1 */ int EVP_DigestSign(EVP_MD_CTX *, unsigned char *, size_t *, const unsigned char *, size_t); int EVP_DigestVerify(EVP_MD_CTX *, const unsigned char *, size_t, diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 7740b91e8ee8..025c6a378300 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -186,7 +186,6 @@ void SSL_set_verify(SSL *, int, int (*)(int, X509_STORE_CTX *)); int SSL_get_verify_mode(const SSL *); -/* Added in 1.0.2 */ X509_VERIFY_PARAM *SSL_get0_param(SSL *); X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *); @@ -393,7 +392,6 @@ const SSL_METHOD *DTLSv1_server_method(void); const SSL_METHOD *DTLSv1_client_method(void); -/* Added in 1.0.2 */ const SSL_METHOD *DTLS_method(void); const SSL_METHOD *DTLS_server_method(void); const SSL_METHOD *DTLS_client_method(void); @@ -443,9 +441,6 @@ int sk_SSL_CIPHER_num(Cryptography_STACK_OF_SSL_CIPHER *); const SSL_CIPHER *sk_SSL_CIPHER_value(Cryptography_STACK_OF_SSL_CIPHER *, int); -/* ALPN APIs were introduced in OpenSSL 1.0.2. To continue to support earlier - * versions some special handling of these is necessary. - */ int SSL_CTX_set_alpn_protos(SSL_CTX *, const unsigned char *, unsigned); int SSL_set_alpn_protos(SSL *, const unsigned char *, unsigned); void SSL_CTX_set_alpn_select_cb(SSL_CTX *, @@ -460,9 +455,6 @@ long SSL_get_server_tmp_key(SSL *, EVP_PKEY **); -/* SSL_CTX_set_cert_cb is introduced in OpenSSL 1.0.2. To continue to support - * earlier versions some special handling of these is necessary. - */ void SSL_CTX_set_cert_cb(SSL_CTX *, int (*)(SSL *, void *), void *); void SSL_set_cert_cb(SSL *, int (*)(SSL *, void *), void *); diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index 5cb6a3f33dad..b311988639ba 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -210,7 +210,6 @@ Cryptography_STACK_OF_X509_OBJECT *X509_STORE_get0_objects(X509_STORE *); X509 *X509_OBJECT_get0_X509(X509_OBJECT *); -/* added in 1.1.0 */ X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *); X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *); void X509_STORE_set_get_issuer(X509_STORE *, X509_STORE_CTX_get_issuer_fn); From 49d1e4f53c18ae5aa8ea8d45e7d02d538d506c88 Mon Sep 17 00:00:00 2001 From: sec00re <95662591+sec00re@users.noreply.github.com> Date: Sun, 18 Sep 2022 15:37:17 +0200 Subject: [PATCH 039/298] docs: update of ChaCha20 specification in hazmat (#7622) * docs: update of ChaCha20 specification in hazmat Clarification of the term nonce, because it is not clear to the user that is the concatenation of 4-byte counter and 12-byte nonce. That is important for compatibility with other implementations. * docs: reformat of ChaCha20 specification * Update docs/hazmat/primitives/symmetric-encryption.rst Co-authored-by: Alex Gaynor Co-authored-by: Alex Gaynor --- docs/hazmat/primitives/symmetric-encryption.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index ec17e731cdfd..37c12f7c3546 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -152,7 +152,9 @@ Algorithms nonce with the same key compromises the security of every message encrypted with that key. The nonce does not need to be kept secret and may be included with the ciphertext. This must be ``128`` - :term:`bits` in length. + :term:`bits` in length. The 128-bit value is a concatenation of 4-byte + little-endian counter and the 12-byte nonce (as described in + :rfc:`7539`). :type nonce: :term:`bytes-like` .. note:: From 9ca1d2393bb0250bf82dc3ac1f132d3391469dfe Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Sep 2022 10:15:58 -0400 Subject: [PATCH 040/298] a new domain has decided to have an expired cert (#7623) the old one finally got fixed --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 3e39d80aabd4..c8bab9afb8b5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -203,8 +203,8 @@ r"https://www.secg.org/sec1-v2.pdf", # Incomplete cert chain r"https://e-trust.gosuslugi.ru", - # Expired cert (2 days at time of writing) - r"https://www.oscca.gov.cn", + # Expired cert + r"https://www.cosic.esat.kuleuven.be", ] autosectionlabel_prefix_document = True From b90c53e34bf60ddd0728133d01c1d2c540fd2985 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Sep 2022 10:55:15 -0400 Subject: [PATCH 041/298] Sigh, attempt to fix linkcheck again (#7624) --- .github/workflows/ci.yml | 2 +- docs/conf.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ff11fbc4f19..b47eb53fed48 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -493,7 +493,7 @@ jobs: - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run docs-linkcheck: - if: github.event_name == 'push' && github.ref == 'refs/heads/main' + if: (github.event_name == 'push' && github.ref == 'refs/heads/main') || (github.event_name == 'pull_request' && contains(github.event.pull_request.title, 'linkcheck')) runs-on: ubuntu-latest name: "linkcheck" timeout-minutes: 15 diff --git a/docs/conf.py b/docs/conf.py index c8bab9afb8b5..07c428f1ebef 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -205,6 +205,8 @@ r"https://e-trust.gosuslugi.ru", # Expired cert r"https://www.cosic.esat.kuleuven.be", + # Incomplete cert chain + r"https://www.oscca.gov.cn", ] autosectionlabel_prefix_document = True From 6ff1f39dbbcd2604b6b860c55e46b6d7f5783506 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Sep 2022 11:02:38 -0400 Subject: [PATCH 042/298] remove consume_errors that are no longer required (#7620) --- src/cryptography/hazmat/backends/openssl/backend.py | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 908cf68ffae9..ae1fec986b11 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1001,11 +1001,6 @@ def load_der_private_key( def _evp_pkey_from_der_traditional_key(self, bio_data, password): key = self._lib.d2i_PrivateKey_bio(bio_data.bio, self._ffi.NULL) if key != self._ffi.NULL: - # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will - # successfully load but errors are still put on the stack. Tracked - # as https://github.com/openssl/openssl/issues/14996 - self._consume_errors() - key = self._ffi.gc(key, self._lib.EVP_PKEY_free) if password is not None: raise TypeError( @@ -1168,11 +1163,6 @@ def _load_key(self, openssl_read_func, convert_func, data, password): else: self._handle_key_loading_error() - # In OpenSSL 3.0.0-alpha15 there exist scenarios where the key will - # successfully load but errors are still put on the stack. Tracked - # as https://github.com/openssl/openssl/issues/14996 - self._consume_errors() - evp_pkey = self._ffi.gc(evp_pkey, self._lib.EVP_PKEY_free) if password is not None and userdata.called == 0: From ab952d05c02d52924e95efcb8829e7be83468523 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 18 Sep 2022 11:27:14 -0400 Subject: [PATCH 043/298] A handful of small internal typing improvements (#7625) --- .../hazmat/bindings/openssl/binding.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 9949ce33ac23..7a55409d94c8 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -97,7 +97,10 @@ def _openssl_assert( ) -def build_conditional_library(lib, conditional_names): +def build_conditional_library( + lib: typing.Any, + conditional_names: typing.Dict[str, typing.Callable[[], typing.List[str]]], +) -> typing.Any: conditional_lib = types.ModuleType("lib") conditional_lib._original_lib = lib # type: ignore[attr-defined] excluded_names = set() @@ -124,7 +127,7 @@ class Binding: _legacy_provider: typing.Any = None _default_provider: typing.Any = None - def __init__(self): + def __init__(self) -> None: self._ensure_ffi_initialized() def _enable_fips(self) -> None: @@ -144,7 +147,7 @@ def _enable_fips(self) -> None: _openssl_assert(self.lib, res == 1) @classmethod - def _register_osrandom_engine(cls): + 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 @@ -156,7 +159,7 @@ def _register_osrandom_engine(cls): _openssl_assert(cls.lib, result in (1, 2)) @classmethod - def _ensure_ffi_initialized(cls): + def _ensure_ffi_initialized(cls) -> None: with cls._init_lock: if not cls._lib_loaded: cls.lib = build_conditional_library(lib, CONDITIONAL_NAMES) @@ -182,11 +185,11 @@ def _ensure_ffi_initialized(cls): ) @classmethod - def init_static_locks(cls): + def init_static_locks(cls) -> None: cls._ensure_ffi_initialized() -def _verify_package_version(version): +def _verify_package_version(version: str) -> None: # Occasionally we run into situations where the version of the Python # package does not match the version of the shared object that is loaded. # This may occur in environments where multiple versions of cryptography From afff2c7415ea036a564aa9bf5e834fbb5fb0e695 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 12:22:55 +0000 Subject: [PATCH 044/298] Bump ouroboros from 0.15.4 to 0.15.5 in /src/rust (#7626) Bumps [ouroboros](https://github.com/joshua-maros/ouroboros) from 0.15.4 to 0.15.5. - [Release notes](https://github.com/joshua-maros/ouroboros/releases) - [Commits](https://github.com/joshua-maros/ouroboros/commits) --- updated-dependencies: - dependency-name: ouroboros dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 74f83449a238..d969619e78a9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -211,9 +211,9 @@ checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0" [[package]] name = "ouroboros" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f56a2b0aa5fc88687aaf63e85a7974422790ce3419a2e1a15870f8a55227822" +checksum = "dfbb50b356159620db6ac971c6d5c9ab788c9cc38a6f49619fca2a27acb062ca" dependencies = [ "aliasable", "ouroboros_macro", @@ -221,9 +221,9 @@ dependencies = [ [[package]] name = "ouroboros_macro" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c40641e27d0eb38cae3dee081d920104d2db47a8e853c1a592ef68d33f5ebf4" +checksum = "4a0d9d1a6191c4f391f87219d1ea42b23f09ee84d64763cd05ee6ea88d9f384d" dependencies = [ "Inflector", "proc-macro-error", From 8b0fbee8530dea38cdf7a88560b5510f64900cf5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Sep 2022 12:33:19 +0000 Subject: [PATCH 045/298] Bump syn from 1.0.99 to 1.0.100 in /src/rust (#7628) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.99 to 1.0.100. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.99...1.0.100) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index d969619e78a9..2993563d4018 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -404,9 +404,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "syn" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" dependencies = [ "proc-macro2", "quote", From e3802d4f7c2f19e53767c150d8557d083b5bfaa0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Sep 2022 12:23:25 +0000 Subject: [PATCH 046/298] Bump libc from 0.2.132 to 0.2.133 in /src/rust (#7630) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.132 to 0.2.133. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.132...0.2.133) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2993563d4018..252163ace33c 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.132" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "lock_api" From 1ceccd92e618a07dcd55504c84cee6e3db18025d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Sep 2022 01:27:56 +0000 Subject: [PATCH 047/298] Bump lock_api from 0.4.8 to 0.4.9 in /src/rust (#7632) Bumps [lock_api](https://github.com/Amanieu/parking_lot) from 0.4.8 to 0.4.9. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/lock_api-0.4.8...lock_api-0.4.9) --- updated-dependencies: - dependency-name: lock_api dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 252163ace33c..328a78aa4f7b 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -167,9 +167,9 @@ checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "lock_api" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", From 7b1460c104df49058c324721deb8c747212fed19 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 20 Sep 2022 21:47:24 -0400 Subject: [PATCH 048/298] document potential future MSRVs in comments (#7633) --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b47eb53fed48..54a8e19c9975 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -193,6 +193,9 @@ jobs: - 1.48.0 # 1.49.0 is the MSRV for parking_lot 0.12 - 1.49.0 + # Potential future MSRVs + # 1.51 - const generics (for rust-asn1) + # 1.56 - new versions of once_cell and bumpalo name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" timeout-minutes: 15 steps: From 4fd171af9d93ec2013d7f138ba0bbe501e374404 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Sep 2022 12:27:05 +0000 Subject: [PATCH 049/298] Bump peter-evans/create-pull-request from 4.1.1 to 4.1.2 (#7634) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.1.1 to 4.1.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/18f90432bedd2afd6a825469ffd38aa24712a91d...171dd555b9ab6b18fa02519fdfacbb8bf671e1b4) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boringssl-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index e9087cbfc208..da274cacfb33 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -37,7 +37,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha.outputs.BORING_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@18f90432bedd2afd6a825469ffd38aa24712a91d + uses: peter-evans/create-pull-request@171dd555b9ab6b18fa02519fdfacbb8bf671e1b4 with: commit-message: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" title: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" From f8d7320deafccd198fb45125e95da37c93a34364 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 22 Sep 2022 08:06:45 -0400 Subject: [PATCH 050/298] linkcheck: this site has renewed its certificate (#7637) --- docs/conf.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 07c428f1ebef..3f8fe68be6a8 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -203,8 +203,6 @@ r"https://www.secg.org/sec1-v2.pdf", # Incomplete cert chain r"https://e-trust.gosuslugi.ru", - # Expired cert - r"https://www.cosic.esat.kuleuven.be", # Incomplete cert chain r"https://www.oscca.gov.cn", ] From 8f47c5a6814396b5a19ca649585c460996a2b5bb Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 22 Sep 2022 09:01:05 -0400 Subject: [PATCH 051/298] linkcheck: small updates (#7638) --- docs/conf.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 3f8fe68be6a8..8dc36102bd9d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -197,11 +197,9 @@ linkcheck_timeout = 5 linkcheck_ignore = [ - # Small DH key results in a TLS failure on modern OpenSSL - r"https://info.isl.ntt.co.jp/crypt/eng/camellia/", # Inconsistent small DH params they seem incapable of fixing r"https://www.secg.org/sec1-v2.pdf", - # Incomplete cert chain + # Cert is issued from an untrusted root r"https://e-trust.gosuslugi.ru", # Incomplete cert chain r"https://www.oscca.gov.cn", From 15033ebafe3976e16d61561913aab6a8da8ca694 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Sep 2022 08:51:36 -0400 Subject: [PATCH 052/298] Bump iana-time-zone from 0.1.48 to 0.1.49 in /src/rust (#7639) Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.48 to 0.1.49. - [Release notes](https://github.com/strawlab/iana-time-zone/releases) - [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md) - [Commits](https://github.com/strawlab/iana-time-zone/compare/v0.1.48...v0.1.49) --- updated-dependencies: - dependency-name: iana-time-zone dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 328a78aa4f7b..401d67978184 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -106,14 +106,13 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.48" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "237a0714f28b1ee39ccec0770ccb544eb02c9ef2c82bb096230eefcffa6468b0" +checksum = "3bbaead50122b06e9a973ac20bc7445074d99ad9a0a0654934876908a9cec82c" dependencies = [ "android_system_properties", "core-foundation-sys", "js-sys", - "once_cell", "wasm-bindgen", "winapi", ] From d7d6b197ae3a67207ce4b0b666d84cb95a5f8a5e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 23 Sep 2022 09:22:54 -0400 Subject: [PATCH 053/298] Error loudly if you somehow run setup.py without CFFI installed (#7640) --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index 320994e69691..4a7866c5ff45 100644 --- a/setup.py +++ b/setup.py @@ -10,6 +10,7 @@ import shutil import subprocess import sys +import warnings from setuptools import setup @@ -30,6 +31,11 @@ raise +# distutils emits this warning if you pass `setup()` an unknown option. This +# is what happens if you somehow run this file without `cffi` installed: +# `cffi_modules` is an unknown option. +warnings.filterwarnings("error", message="Unknown distribution option") + base_dir = os.path.dirname(__file__) src_dir = os.path.join(base_dir, "src") From fa8440fe56ff55a61c8f1d4b758b4021fbba3b7f Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 24 Sep 2022 00:24:50 +0000 Subject: [PATCH 054/298] Bump BoringSSL version to cab31f65f1ad6e6daca62e95b25dd6cd805fce0b (#7642) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54a8e19c9975..6be77de98aec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,8 +41,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 15, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "04989786e9ab16cef5261bbd05a2b1a8cb312dbf"}} + # Latest commit on the master branch, as of Sep 24, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "cab31f65f1ad6e6daca62e95b25dd6cd805fce0b"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1d32f00ab0cf11720cb139e35af557f4a8b9ee36 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Sat, 24 Sep 2022 16:21:15 +0200 Subject: [PATCH 055/298] Replace vendored check job w/ re-actors/alls-green (#7643) * Replace vendored check job w/ re-actors/alls-green Inspired by earlier discoveries @ https://github.com/pyca/cryptography/pull/6512/files#r762373796 * Update .github/workflows/ci.yml Co-authored-by: Sviatoslav Sydorenko * Drop the matching tag comment next to the action Co-authored-by: Alex Gaynor Co-authored-by: Alex Gaynor --- .github/workflows/ci.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6be77de98aec..79bdc3b487b9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -523,12 +523,10 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - run: | - echo "# 😢 😢" >> $GITHUB_STEP_SUMMARY - echo "At least one CI job failed." - exit 1 - if: ${{ needs.linux.result != 'success' || needs.linux-distros.result != 'success' || needs.linux-rust.result != 'success' || needs.linux-rust-coverage.result != 'success' || needs.macos.result != 'success' || needs.windows.result != 'success' || needs.linux-downstream.result != 'success' }} - - run: echo "# 🎉 🎉" >> $GITHUB_STEP_SUMMARY + - name: Decide whether the needed jobs succeeded or failed + uses: re-actors/alls-green@198badcb65a1a44528f27d5da555c4be9f12eac6 + with: + jobs: ${{ toJSON(needs) }} - name: Setup python if: ${{ always() }} uses: actions/setup-python@v4.2.0 From 13500580fa6ae3a2eb4b0b04ce9e4c63f3759a7a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 24 Sep 2022 11:20:11 -0400 Subject: [PATCH 056/298] Warn users on 32-bit Pythons on 64-bit windows. (#7641) They're leaving a ton of performance on the table. --- .../hazmat/bindings/openssl/binding.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 7a55409d94c8..9dc1b1040d91 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -2,10 +2,12 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. - +import os +import sys import threading import types import typing +import warnings import cryptography from cryptography.exceptions import InternalError @@ -213,3 +215,15 @@ def _verify_package_version(version: str) -> None: _verify_package_version(cryptography.__version__) Binding.init_static_locks() + +if ( + sys.platform == "win32" + and os.environ.get("PROCESSOR_ARCHITEW6432") is not None +): + warnings.warn( + "You are using cryptography on a 32-bit Python on a 64-bit Windows " + "Operating System. Cryptography will be significantly faster if you " + "switch to using a 64-bit Python.", + UserWarning, + stacklevel=2, + ) From 4cd73c78a04465806a96bc30aad3ceeadbf40f1a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 24 Sep 2022 10:39:51 -0500 Subject: [PATCH 057/298] handle AESSIV empty byte strings on encrypt/decrypt (#7644) --- src/cryptography/hazmat/primitives/ciphers/aead.py | 2 ++ tests/hazmat/primitives/test_aead.py | 12 +++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index b4564cfcc8bb..16c97a644440 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -366,6 +366,8 @@ def _check_params( associated_data: typing.List, ) -> None: utils._check_bytes("data", data) + if len(data) == 0: + raise ValueError("data must not be zero length") if not isinstance(associated_data, list) or not all( isinstance(x, bytes) for x in associated_data ): diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index dcbf76bd5f4e..b7a4aedf3ad6 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -625,7 +625,17 @@ def test_data_too_large(self): aessiv.encrypt(FakeData(), None) with pytest.raises(OverflowError): - aessiv.encrypt(b"", [FakeData()]) + aessiv.encrypt(b"irrelevant", [FakeData()]) + + def test_no_empty_encryption(self): + key = AESSIV.generate_key(256) + aessiv = AESSIV(key) + + with pytest.raises(ValueError): + aessiv.encrypt(b"", None) + + with pytest.raises(ValueError): + aessiv.decrypt(b"", None) def test_vectors(self, backend, subtests): vectors = load_vectors_from_file( From 76008729bb320de08f455ccc20a8faa46e43d143 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 24 Sep 2022 20:39:59 -0400 Subject: [PATCH 058/298] disallow new sphinx release that's broken with sphinx_rtd_theme (#7646) --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d96bb2d4f581..724b86e657eb 100644 --- a/setup.cfg +++ b/setup.cfg @@ -65,7 +65,7 @@ test = pytz hypothesis>=1.11.4,!=3.79.2 docs = - sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1 + sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1,!=5.2.0,!=5.2.0.post0 sphinx_rtd_theme docstest = pyenchant >= 1.6.11 From 530d8e2fb097060ab323a166049a009f359e5cbc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Sep 2022 01:20:00 +0000 Subject: [PATCH 059/298] Bump iana-time-zone from 0.1.49 to 0.1.50 in /src/rust (#7645) Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.49 to 0.1.50. - [Release notes](https://github.com/strawlab/iana-time-zone/releases) - [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md) - [Commits](https://github.com/strawlab/iana-time-zone/compare/v0.1.49...v0.1.50) --- updated-dependencies: - dependency-name: iana-time-zone dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 401d67978184..e6f980de19ca 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.49" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbaead50122b06e9a973ac20bc7445074d99ad9a0a0654934876908a9cec82c" +checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" dependencies = [ "android_system_properties", "core-foundation-sys", From f6077282dd88c0417a07808ecf278303c06ed9ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 25 Sep 2022 13:17:09 +0000 Subject: [PATCH 060/298] Bump proc-macro2 from 1.0.43 to 1.0.44 in /src/rust (#7647) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.43 to 1.0.44. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.43...1.0.44) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index e6f980de19ca..bdf6f2dc3ad7 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -316,9 +316,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" dependencies = [ "unicode-ident", ] From 7150d4577211367357814140ba59d10c1050ae91 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 25 Sep 2022 13:50:37 -0400 Subject: [PATCH 061/298] Make verify_interface a no-op (#7648) This should be sufficient to keep aws-encryption-sdk working, but let's us delete the code. --- src/cryptography/utils.py | 32 ++------------------ tests/test_interfaces.py | 64 ++------------------------------------- 2 files changed, 5 insertions(+), 91 deletions(-) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 75ca8889b07d..2130d8f3dec6 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -5,7 +5,6 @@ import abc import enum -import inspect import sys import types import typing @@ -47,37 +46,12 @@ class InterfaceNotImplemented(Exception): pass -def strip_annotation(signature: inspect.Signature) -> inspect.Signature: - return inspect.Signature( - [ - param.replace(annotation=inspect.Parameter.empty) - for param in signature.parameters.values() - ] - ) - - def verify_interface( iface: abc.ABCMeta, klass: object, *, check_annotations: bool = False ): - for method in iface.__abstractmethods__: - if not hasattr(klass, method): - raise InterfaceNotImplemented( - "{} is missing a {!r} method".format(klass, method) - ) - if isinstance(getattr(iface, method), abc.abstractproperty): - # Can't properly verify these yet. - continue - sig = inspect.signature(getattr(iface, method)) - actual = inspect.signature(getattr(klass, method)) - if check_annotations: - ok = sig == actual - else: - ok = strip_annotation(sig) == strip_annotation(actual) - if not ok: - raise InterfaceNotImplemented( - "{}.{}'s signature differs from the expected. Expected: " - "{!r}. Received: {!r}".format(klass, method, sig, actual) - ) + # Exists exclusively for `aws-encryption-sdk` which relies on it existing, + # even though it was never a public API. + pass class _DeprecatedValue: diff --git a/tests/test_interfaces.py b/tests/test_interfaces.py index 302edb93e3bf..06c09f32739c 100644 --- a/tests/test_interfaces.py +++ b/tests/test_interfaces.py @@ -4,16 +4,11 @@ import abc -import pytest - -from cryptography.utils import ( - InterfaceNotImplemented, - verify_interface, -) +from cryptography.utils import verify_interface class TestVerifyInterface: - def test_verify_missing_method(self): + def test_noop(self): class SimpleInterface(metaclass=abc.ABCMeta): @abc.abstractmethod def method(self): @@ -22,59 +17,4 @@ def method(self): class NonImplementer: pass - with pytest.raises(InterfaceNotImplemented): - verify_interface(SimpleInterface, NonImplementer) - - def test_different_arguments(self): - class SimpleInterface(metaclass=abc.ABCMeta): - @abc.abstractmethod - def method(self, a): - """Method with one argument""" - - class NonImplementer: - def method(self): - """Method with no arguments""" - - # Invoke this to ensure the line is covered - NonImplementer().method() - with pytest.raises(InterfaceNotImplemented): - verify_interface(SimpleInterface, NonImplementer) - - def test_handles_abstract_property(self): - class SimpleInterface(metaclass=abc.ABCMeta): - @abc.abstractproperty - def property(self): - """An abstract property""" - - class NonImplementer: - @property - def property(self): - """A concrete property""" - - # Invoke this to ensure the line is covered - NonImplementer().property verify_interface(SimpleInterface, NonImplementer) - - def test_signature_mismatch(self): - class SimpleInterface(metaclass=abc.ABCMeta): - @abc.abstractmethod - def method(self, other: object) -> int: - """Method with signature""" - - class ClassWithoutSignature: - def method(self, other): - """Method without signature""" - - class ClassWithSignature: - def method(self, other: object) -> int: - """Method with signature""" - - verify_interface(SimpleInterface, ClassWithoutSignature) - verify_interface(SimpleInterface, ClassWithSignature) - with pytest.raises(InterfaceNotImplemented): - verify_interface( - SimpleInterface, ClassWithoutSignature, check_annotations=True - ) - verify_interface( - SimpleInterface, ClassWithSignature, check_annotations=True - ) From e9590a5215efe5a0627e3e572192796e8ea1e7cb Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 25 Sep 2022 13:12:52 -0500 Subject: [PATCH 062/298] mark verify_interface with a deprecation comment (#7649) this will help us revisit it in the future --- src/cryptography/utils.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 2130d8f3dec6..7f4a4799bf92 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -22,6 +22,7 @@ class CryptographyDeprecationWarning(UserWarning): # cycle ends. DeprecatedIn36 = CryptographyDeprecationWarning DeprecatedIn37 = CryptographyDeprecationWarning +DeprecatedIn39 = CryptographyDeprecationWarning def _check_bytes(name: str, value: bytes) -> None: @@ -46,6 +47,8 @@ class InterfaceNotImplemented(Exception): pass +# DeprecatedIn39 -- Our only known consumer is aws-encryption-sdk, but we've +# made this a no-op to avoid breaking old versions. def verify_interface( iface: abc.ABCMeta, klass: object, *, check_annotations: bool = False ): From b37e4ab5df07391a537208745f80799793a5ceb0 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 26 Sep 2022 16:20:58 -0500 Subject: [PATCH 063/298] support compilation against openssl 3 with no legacy provider (#7650) You must pass CRYPTOGRAPHY_OPENSSL_NO_LEGACY for this to be allowed. Downstreams can easily patch this check out if they want to default to this behavior. --- .github/workflows/ci.yml | 2 + CHANGELOG.rst | 2 + docs/openssl.rst | 12 ++++ .../hazmat/backends/openssl/backend.py | 62 ++++++++++++------- .../hazmat/bindings/openssl/binding.py | 31 +++++++--- tests/hazmat/bindings/test_openssl.py | 8 ++- tox.ini | 2 +- 7 files changed, 87 insertions(+), 32 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 79bdc3b487b9..d5fc1eab2c6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} @@ -113,6 +114,7 @@ jobs: tox -vvv -r -- --color=yes --wycheproof-root=wycheproof ${{ matrix.PYTHON.TOXARGS }} env: TOXENV: ${{ matrix.PYTHON.TOXENV }} + CRYPTOGRAPHY_OPENSSL_NO_LEGACY: ${{ matrix.PYTHON.OPENSSL.NO_LEGACY }} CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} - uses: ./.github/actions/upload-coverage diff --git a/CHANGELOG.rst b/CHANGELOG.rst index f9f9aece8f3f..8a0196bff2d8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,8 @@ Changelog * **BACKWARDS INCOMPATIBLE:** Support for using MD5 or SHA1 in :class:`~cryptography.x509.CertificateBuilder` and other X.509 builders has been removed. +* Added support for + :ref:`disabling the legacy provider in OpenSSL 3.0.x`. .. _v38-0-1: diff --git a/docs/openssl.rst b/docs/openssl.rst index b628d0a94612..edf185d2e10e 100644 --- a/docs/openssl.rst +++ b/docs/openssl.rst @@ -44,6 +44,18 @@ control. This will activate the default OpenSSL CSPRNG. +.. _legacy-provider: + +Legacy provider in OpenSSL 3.x +------------------------------ + +.. versionadded:: 39.0.0 + +Users can set ``CRYPTOGRAPHY_OPENSSL_NO_LEGACY`` environment variable to +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 ---------------- diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index ae1fec986b11..c71bcc9d6862 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -203,8 +203,10 @@ def __init__(self): self._dh_types.append(self._lib.EVP_PKEY_DHX) def __repr__(self) -> str: - return "".format( - self.openssl_version_text(), self._fips_enabled + return "".format( + self.openssl_version_text(), + self._fips_enabled, + self._binding._legacy_provider_loaded, ) def openssl_assert( @@ -403,26 +405,6 @@ def _register_default_ciphers(self) -> None: self.register_cipher_adapter( TripleDES, ECB, GetCipherByName("des-ede3") ) - for mode_cls in [CBC, CFB, OFB, ECB]: - self.register_cipher_adapter( - _BlowfishInternal, mode_cls, GetCipherByName("bf-{mode.name}") - ) - for mode_cls in [CBC, CFB, OFB, ECB]: - self.register_cipher_adapter( - _SEEDInternal, mode_cls, GetCipherByName("seed-{mode.name}") - ) - for cipher_cls, mode_cls in itertools.product( - [_CAST5Internal, _IDEAInternal], - [CBC, OFB, CFB, ECB], - ): - self.register_cipher_adapter( - cipher_cls, - mode_cls, - GetCipherByName("{cipher.name}-{mode.name}"), - ) - self.register_cipher_adapter(ARC4, type(None), GetCipherByName("rc4")) - # We don't actually support RC2, this is just used by some tests. - self.register_cipher_adapter(_RC2, type(None), GetCipherByName("rc2")) self.register_cipher_adapter( ChaCha20, type(None), GetCipherByName("chacha20") ) @@ -431,6 +413,42 @@ def _register_default_ciphers(self) -> None: self.register_cipher_adapter( SM4, mode_cls, GetCipherByName("sm4-{mode.name}") ) + # Don't register legacy ciphers if they're unavailable. Hypothetically + # this wouldn't be necessary because we test availability by seeing if + # we get an EVP_CIPHER * in the _CipherContext __init__, but OpenSSL 3 + # will return a valid pointer even though the cipher is unavailable. + if ( + self._binding._legacy_provider_loaded + or not self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER + ): + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + _BlowfishInternal, + mode_cls, + GetCipherByName("bf-{mode.name}"), + ) + for mode_cls in [CBC, CFB, OFB, ECB]: + self.register_cipher_adapter( + _SEEDInternal, + mode_cls, + GetCipherByName("seed-{mode.name}"), + ) + for cipher_cls, mode_cls in itertools.product( + [_CAST5Internal, _IDEAInternal], + [CBC, OFB, CFB, ECB], + ): + self.register_cipher_adapter( + cipher_cls, + mode_cls, + GetCipherByName("{cipher.name}-{mode.name}"), + ) + self.register_cipher_adapter( + ARC4, type(None), GetCipherByName("rc4") + ) + # We don't actually support RC2, this is just used by some tests. + self.register_cipher_adapter( + _RC2, type(None), GetCipherByName("rc2") + ) def create_symmetric_encryption_ctx( self, cipher: CipherAlgorithm, mode: Mode diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 9dc1b1040d91..a1602164d015 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -99,6 +99,17 @@ def _openssl_assert( ) +def _legacy_provider_error(loaded: bool) -> None: + if not loaded: + raise RuntimeError( + "OpenSSL 3.0's legacy provider failed to load. This is a fatal " + "error by default, but cryptography supports running without " + "legacy algorithms by setting the environment variable " + "CRYPTOGRAPHY_OPENSSL_NO_LEGACY. If you did not expect this error," + " you have likely made a mistake with your OpenSSL configuration." + ) + + def build_conditional_library( lib: typing.Any, conditional_names: typing.Dict[str, typing.Callable[[], typing.List[str]]], @@ -126,8 +137,9 @@ class Binding: ffi = ffi _lib_loaded = False _init_lock = threading.Lock() - _legacy_provider: typing.Any = None - _default_provider: typing.Any = None + _legacy_provider: typing.Any = ffi.NULL + _legacy_provider_loaded = False + _default_provider: typing.Any = ffi.NULL def __init__(self) -> None: self._ensure_ffi_initialized() @@ -173,12 +185,15 @@ def _ensure_ffi_initialized(cls) -> None: # are ugly legacy, but we aren't going to get rid of them # any time soon. if cls.lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: - cls._legacy_provider = cls.lib.OSSL_PROVIDER_load( - cls.ffi.NULL, b"legacy" - ) - _openssl_assert( - cls.lib, cls._legacy_provider != cls.ffi.NULL - ) + if not os.environ.get("CRYPTOGRAPHY_OPENSSL_NO_LEGACY"): + cls._legacy_provider = cls.lib.OSSL_PROVIDER_load( + cls.ffi.NULL, b"legacy" + ) + cls._legacy_provider_loaded = ( + cls._legacy_provider != cls.ffi.NULL + ) + _legacy_provider_error(cls._legacy_provider_loaded) + cls._default_provider = cls.lib.OSSL_PROVIDER_load( cls.ffi.NULL, b"default" ) diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index abc0e15288ad..6204262728f7 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -2,13 +2,13 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. - import pytest from cryptography.exceptions import InternalError from cryptography.hazmat.bindings.openssl.binding import ( Binding, _consume_errors, + _legacy_provider_error, _openssl_assert, _verify_package_version, ) @@ -117,3 +117,9 @@ def test_check_startup_errors_are_allowed(self): def test_version_mismatch(self): with pytest.raises(ImportError): _verify_package_version("nottherightversion") + + def test_legacy_provider_error(self): + with pytest.raises(RuntimeError): + _legacy_provider_error(False) + + _legacy_provider_error(True) diff --git a/tox.ini b/tox.ini index c1c7b9e296ab..655d4d2c222e 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ deps = -e ./vectors pytest-shard>=0.1.2 randomorder: pytest-randomly -passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH RUSTFLAGS CARGO_TARGET_DIR LLVM_PROFILE_FILE OPENSSL_FORCE_FIPS_MODE RUSTUP_TOOLCHAIN +passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH RUSTFLAGS CARGO_TARGET_DIR LLVM_PROFILE_FILE OPENSSL_FORCE_FIPS_MODE RUSTUP_TOOLCHAIN CRYPTOGRAPHY_OPENSSL_NO_LEGACY commands = pip list !nocoverage: pytest -n auto --cov=cryptography --cov=tests --durations=10 {posargs} tests/ From baa1227e4c066d61f0589c753ee9da859e68035c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Sep 2022 12:20:04 +0000 Subject: [PATCH 064/298] Bump syn from 1.0.100 to 1.0.101 in /src/rust (#7652) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.100 to 1.0.101. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.100...1.0.101) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index bdf6f2dc3ad7..4bdd3d2b47e9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -403,9 +403,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "syn" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52205623b1b0f064a4e71182c3b18ae902267282930c6d5462c91b859668426e" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", From 1f3420a0813f4ef6972f2d8d64ca88002b3e1246 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 27 Sep 2022 19:55:50 -0500 Subject: [PATCH 065/298] fixes #7653 -- handle OPENSSL_cleanup existing on LibreSSL 3.6.0 (#7654) --- src/_cffi_src/openssl/crypto.py | 2 +- src/_cffi_src/openssl/cryptography.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index 5a1ffcc0edbd..cbef3880496a 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -74,7 +74,7 @@ # define OPENSSL_DIR SSLEAY_DIR #endif -#if CRYPTOGRAPHY_IS_LIBRESSL +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 static const long Cryptography_HAS_OPENSSL_CLEANUP = 0; void (*OPENSSL_cleanup)(void) = NULL; #else diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 605e62db5bde..c559401ddd05 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -43,9 +43,12 @@ #if CRYPTOGRAPHY_IS_LIBRESSL #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 \ (LIBRESSL_VERSION_NUMBER < 0x3050000f) +#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 \ + (LIBRESSL_VERSION_NUMBER < 0x3060000f) #else #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 (0) +#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 (0) #endif #if OPENSSL_VERSION_NUMBER < 0x10101000 From 46f8899e7f168a2365b106fbce2de2ffc2d9999b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 28 Sep 2022 12:14:56 +0000 Subject: [PATCH 066/298] Bump peter-evans/create-pull-request from 4.1.2 to 4.1.3 (#7656) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.1.2 to 4.1.3. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/171dd555b9ab6b18fa02519fdfacbb8bf671e1b4...671dc9c9e0c2d73f07fa45a3eb0220e1622f0c5f) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boringssl-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index da274cacfb33..19f1d9671f1a 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -37,7 +37,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha.outputs.BORING_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@171dd555b9ab6b18fa02519fdfacbb8bf671e1b4 + uses: peter-evans/create-pull-request@671dc9c9e0c2d73f07fa45a3eb0220e1622f0c5f with: commit-message: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" title: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" From 0a0a9523a2e0b5e9cfae6a781c59f920dae5d3cb Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 00:31:44 +0000 Subject: [PATCH 067/298] Bump BoringSSL version to 80eb8141a245293e2b133c49d5bc81316317d877 (#7657) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5fc1eab2c6e..50933f12327b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 24, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "cab31f65f1ad6e6daca62e95b25dd6cd805fce0b"}} + # Latest commit on the master branch, as of Sep 29, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "80eb8141a245293e2b133c49d5bc81316317d877"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 4213c92953b1e2eccd035d0290803e35a816a8b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:16:10 +0000 Subject: [PATCH 068/298] Bump re-actors/alls-green from 1.2.0 to 1.2.1 (#7658) Bumps [re-actors/alls-green](https://github.com/re-actors/alls-green) from 1.2.0 to 1.2.1. - [Release notes](https://github.com/re-actors/alls-green/releases) - [Commits](https://github.com/re-actors/alls-green/compare/198badcb65a1a44528f27d5da555c4be9f12eac6...13b4244b312e8a314951e03958a2f91519a6a3c9) --- updated-dependencies: - dependency-name: re-actors/alls-green dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 50933f12327b..2891080eeb79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -526,7 +526,7 @@ jobs: with: persist-credentials: false - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@198badcb65a1a44528f27d5da555c4be9f12eac6 + uses: re-actors/alls-green@13b4244b312e8a314951e03958a2f91519a6a3c9 with: jobs: ${{ toJSON(needs) }} - name: Setup python From 99daef00fec2c5c82b72eac95795e47adbdbdc2e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 29 Sep 2022 12:26:56 +0000 Subject: [PATCH 069/298] Bump proc-macro2 from 1.0.44 to 1.0.46 in /src/rust (#7659) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.44 to 1.0.46. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.44...1.0.46) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4bdd3d2b47e9..9ab9a238b96b 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -316,9 +316,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.44" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" +checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" dependencies = [ "unicode-ident", ] From af23139617b83cba7369608b85795ece7d86eb27 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Sep 2022 08:45:08 -0400 Subject: [PATCH 070/298] update docs -- we don't test on stretch (#7660) --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index 344c7454e8aa..b5d3062700ec 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -22,7 +22,7 @@ operating systems. * ARM64 macOS 12 Monterey * x86-64 Ubuntu 18.04, 20.04, 22.04, rolling * ARM64 Ubuntu 20.04 -* x86-64 Debian Stretch (9.x), Buster (10.x), Bullseye (11.x), Bookworm (12.x) +* x86-64 Debian Buster (10.x), Bullseye (11.x), Bookworm (12.x) and Sid (unstable) * x86-64 Alpine (latest) * ARM64 Alpine (latest) From fd36c881b66db9cbdb128c067c72e0da005d479b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Sep 2022 08:49:49 -0400 Subject: [PATCH 071/298] update brew instructions to use openssl 3 (#7661) --- docs/installation.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/installation.rst b/docs/installation.rst index b5d3062700ec..145376f1bee7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -270,8 +270,8 @@ To build cryptography and dynamically link it: .. code-block:: console - $ brew install openssl@1.1 rust - $ env LDFLAGS="-L$(brew --prefix openssl@1.1)/lib" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pip install cryptography + $ brew install openssl@3 rust + $ env LDFLAGS="-L$(brew --prefix openssl@3)/lib" CFLAGS="-I$(brew --prefix openssl@3)/include" pip install cryptography `MacPorts`_: @@ -286,8 +286,8 @@ You can also build cryptography statically: .. code-block:: console - $ brew install openssl@1.1 rust - $ env CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 LDFLAGS="$(brew --prefix openssl@1.1)/lib/libssl.a $(brew --prefix openssl@1.1)/lib/libcrypto.a" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pip install cryptography + $ brew install openssl@3 rust + $ env CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 LDFLAGS="$(brew --prefix openssl@3)/lib/libssl.a $(brew --prefix openssl@3)/lib/libcrypto.a" CFLAGS="-I$(brew --prefix openssl@3)/include" pip install cryptography `MacPorts`_: From 6cc2be26a739e11d3810b6ccced6907e38e5f8b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 12:20:15 +0000 Subject: [PATCH 072/298] Bump libc from 0.2.133 to 0.2.134 in /src/rust (#7663) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.133 to 0.2.134. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.133...0.2.134) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 9ab9a238b96b..35713422644c 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -160,9 +160,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.133" +version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" +checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" [[package]] name = "lock_api" From 6393ec64cf5985277c7431032167112ea8e211f1 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 00:32:05 +0000 Subject: [PATCH 073/298] Bump BoringSSL version to 46a1c7e2334f3fddc7873f35a43c9ad2af9dbe4f (#7664) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2891080eeb79..a11cbe865fd5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Sep 29, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "80eb8141a245293e2b133c49d5bc81316317d877"}} + # Latest commit on the master branch, as of Oct 01, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "46a1c7e2334f3fddc7873f35a43c9ad2af9dbe4f"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From df9c587a151a92f1d37a478608a4108d8d0bc33c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 00:49:33 +0000 Subject: [PATCH 074/298] Bump actions/cache from 3.0.8 to 3.0.9 (#7665) Bumps [actions/cache](https://github.com/actions/cache) from 3.0.8 to 3.0.9. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.0.8...v3.0.9) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/macarm64.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a11cbe865fd5..b55b4dd24df9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: uses: actions/setup-python@v4.2.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 timeout-minutes: 5 with: path: | @@ -89,7 +89,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.0.8 + uses: actions/cache@v3.0.9 id: ossl-cache timeout-minutes: 5 with: @@ -147,7 +147,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 timeout-minutes: 5 with: path: | @@ -205,7 +205,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 timeout-minutes: 5 with: path: | @@ -256,7 +256,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 id: cargo-cache timeout-minutes: 5 with: @@ -342,7 +342,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 timeout-minutes: 5 with: path: | @@ -412,7 +412,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 timeout-minutes: 5 with: path: | @@ -474,7 +474,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 timeout-minutes: 5 with: path: | diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index 0e0844de0546..f81b957219bc 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3.0.2 with: persist-credentials: false - - uses: actions/cache@v3.0.8 + - uses: actions/cache@v3.0.9 with: path: | src/rust/target/ From 9ad715ac53395d42da6a25af8c43b95e063dd5f9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 1 Oct 2022 11:40:48 -0400 Subject: [PATCH 075/298] Handle error generating DH params with very very large key size (#7666) Detected by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=52024 --- src/cryptography/hazmat/backends/openssl/backend.py | 4 +++- tests/hazmat/primitives/test_dh.py | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index c71bcc9d6862..890e2f9521a9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1709,7 +1709,9 @@ def generate_dh_parameters( res = self._lib.DH_generate_parameters_ex( dh_param_cdata, key_size, generator, self._ffi.NULL ) - self.openssl_assert(res == 1) + if res != 1: + errors = self._consume_errors_with_text() + raise ValueError("Unable to generate DH parameters", errors) return _DHParameters(self, dh_param_cdata) diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index b8216a9a79f7..6e708676bd19 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -148,6 +148,10 @@ def test_unsupported_generator_generate_dh(self, backend): with pytest.raises(ValueError): dh.generate_parameters(7, 512, backend) + def test_large_key_generate_dh(self): + with pytest.raises(ValueError): + dh.generate_parameters(2, 1 << 30) + @pytest.mark.skip_fips(reason="non-FIPS parameters") def test_dh_parameters_supported(self, backend): valid_p = int( From 0653cafd343407c26a07c870a01afee74809d043 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 12:19:55 +0000 Subject: [PATCH 076/298] Bump actions/cache from 3.0.9 to 3.0.10 (#7668) Bumps [actions/cache](https://github.com/actions/cache) from 3.0.9 to 3.0.10. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.0.9...v3.0.10) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/macarm64.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b55b4dd24df9..8c1aad752547 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: uses: actions/setup-python@v4.2.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 timeout-minutes: 5 with: path: | @@ -89,7 +89,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.0.9 + uses: actions/cache@v3.0.10 id: ossl-cache timeout-minutes: 5 with: @@ -147,7 +147,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 timeout-minutes: 5 with: path: | @@ -205,7 +205,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 timeout-minutes: 5 with: path: | @@ -256,7 +256,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 id: cargo-cache timeout-minutes: 5 with: @@ -342,7 +342,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 timeout-minutes: 5 with: path: | @@ -412,7 +412,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 timeout-minutes: 5 with: path: | @@ -474,7 +474,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 timeout-minutes: 5 with: path: | diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index f81b957219bc..f799668c6373 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3.0.2 with: persist-credentials: false - - uses: actions/cache@v3.0.9 + - uses: actions/cache@v3.0.10 with: path: | src/rust/target/ From fd6bae730503934917050bea112f4d703fd6b237 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 12:27:18 +0000 Subject: [PATCH 077/298] Bump smallvec from 1.9.0 to 1.10.0 in /src/rust (#7669) Bumps [smallvec](https://github.com/servo/rust-smallvec) from 1.9.0 to 1.10.0. - [Release notes](https://github.com/servo/rust-smallvec/releases) - [Commits](https://github.com/servo/rust-smallvec/compare/v1.9.0...v1.10.0) --- updated-dependencies: - dependency-name: smallvec dependency-type: indirect update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 35713422644c..02184682ebe2 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -397,9 +397,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "smallvec" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" From 01687d63a5cb4475d84feae959bec6dea5fce3f1 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 3 Oct 2022 09:29:45 -0500 Subject: [PATCH 078/298] add unsafe_skip_rsa_key_validation (#7667) * add unsafe_skip_rsa_key_validation This allows users to skip RSA key validation when calling load_pem_private_key, load_der_private_key, and RSAPrivateNumbers.private_key. This is a significant performance improvement but is **only safe if you know the key is valid**. If you use this when the key is invalid OpenSSL makes no guarantees about what might happen. Infinite loops, crashes, and all manner of terrible things become possible if that occurs. Beware, beware, beware. * Apply suggestions from code review Co-authored-by: Alex Gaynor * remove unneeded variable Co-authored-by: Alex Gaynor --- CHANGELOG.rst | 8 +++ docs/glossary.rst | 5 ++ docs/hazmat/primitives/asymmetric/rsa.rst | 16 ++++- .../primitives/asymmetric/serialization.rst | 32 +++++++++- .../hazmat/backends/openssl/backend.py | 58 ++++++++++++++----- .../hazmat/backends/openssl/rsa.py | 9 ++- .../hazmat/primitives/asymmetric/rsa.py | 11 +++- .../hazmat/primitives/serialization/base.py | 12 +++- tests/conftest.py | 9 --- tests/hazmat/backends/test_openssl.py | 8 ++- tests/hazmat/primitives/test_rsa.py | 16 ++--- tests/wycheproof/test_rsa.py | 3 + tests/wycheproof/utils.py | 4 +- 13 files changed, 142 insertions(+), 49 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8a0196bff2d8..3156ee365f8e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -27,6 +27,14 @@ Changelog other X.509 builders has been removed. * Added support for :ref:`disabling the legacy provider in OpenSSL 3.0.x`. +* Added support for disabling RSA key validation checks when loading RSA + keys via + :func:`~cryptography.hazmat.primitives.serialization.load_pem_private_key`, + :func:`~cryptography.hazmat.primitives.serialization.load_der_private_key`, + and + :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers.private_key`. + This speeds up key loading but is :term:`unsafe` if you are loading potentially + attacker supplied keys. .. _v38-0-1: diff --git a/docs/glossary.rst b/docs/glossary.rst index b85a61091e38..0fa40245d1b8 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -100,6 +100,11 @@ Glossary name. U-labels use unicode characters outside the ASCII range and are encoded as A-labels when stored in certificates. + unsafe + This is a term used to describe an operation where the user must + ensure that the input is correct. Failure to do so can result in + crashes, hangs, and other security issues. + .. _`hardware security module`: https://en.wikipedia.org/wiki/Hardware_security_module .. _`idna`: https://pypi.org/project/idna/ .. _`buffer protocol`: https://docs.python.org/3/c-api/buffer.html diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index d21cb801275f..2dfccb1a01a1 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -473,7 +473,21 @@ is unavailable. A `Chinese remainder theorem`_ coefficient used to speed up RSA operations. Calculated as: q\ :sup:`-1` mod p - .. method:: private_key() + .. method:: private_key(*, unsafe_skip_rsa_key_validation=False) + + :param unsafe_skip_rsa_key_validation: + + .. versionadded:: 39.0.0 + + A keyword-only argument that defaults to ``False``. If ``True`` + RSA private keys will not be validated. This significantly speeds up + loading the keys, but is is :term:`unsafe` unless you are certain + the key is valid. User supplied keys should never be loaded with + this parameter set to ``True``. If you do load an invalid key this + way and attempt to use it OpenSSL may hang, crash, or otherwise + misbehave. + + :type unsafe_skip_rsa_key_validation: bool :returns: An instance of :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateKey`. diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index db3271b90d3c..b60102047f2d 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -125,7 +125,7 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END extract the public key with :meth:`Certificate.public_key `. -.. function:: load_pem_private_key(data, password) +.. function:: load_pem_private_key(data, password, *, unsafe_skip_rsa_key_validation=False) .. versionadded:: 0.6 @@ -141,7 +141,20 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END :param password: The password to use to decrypt the data. Should be ``None`` if the private key is not encrypted. - :type data: :term:`bytes-like` + :type password: :term:`bytes-like` + + :param unsafe_skip_rsa_key_validation: + + .. versionadded:: 39.0.0 + + A keyword-only argument that defaults to ``False``. If ``True`` + RSA private keys will not be validated. This significantly speeds up + loading the keys, but is is :term:`unsafe` unless you are certain the + key is valid. User supplied keys should never be loaded with this + parameter set to ``True``. If you do load an invalid key this way and + attempt to use it OpenSSL may hang, crash, or otherwise misbehave. + + :type unsafe_skip_rsa_key_validation: bool :returns: One of :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`, @@ -234,7 +247,7 @@ data is binary. DER keys may be in a variety of formats, but as long as you know whether it is a public or private key the loading functions will handle the rest. -.. function:: load_der_private_key(data, password) +.. function:: load_der_private_key(data, password, *, unsafe_skip_rsa_key_validation=False) .. versionadded:: 0.8 @@ -248,6 +261,19 @@ the rest. be ``None`` if the private key is not encrypted. :type password: :term:`bytes-like` + :param unsafe_skip_rsa_key_validation: + + .. versionadded:: 39.0.0 + + A keyword-only argument that defaults to ``False``. If ``True`` + RSA private keys will not be validated. This significantly speeds up + loading the keys, but is is :term:`unsafe` unless you are certain the + key is valid. User supplied keys should never be loaded with this + parameter set to ``True``. If you do load an invalid key this way and + attempt to use it OpenSSL may hang, crash, or otherwise misbehave. + + :type unsafe_skip_rsa_key_validation: bool + :returns: One of :class:`~cryptography.hazmat.primitives.asymmetric.ed25519.Ed25519PrivateKey`, :class:`~cryptography.hazmat.primitives.asymmetric.x25519.X25519PrivateKey`, diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 890e2f9521a9..b84753758996 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -186,7 +186,6 @@ def __init__(self): self._binding = binding.Binding() self._ffi = self._binding.ffi self._lib = self._binding.lib - self._rsa_skip_check_key = False self._fips_enabled = self._is_fips_enabled() self._cipher_registry = {} @@ -542,8 +541,9 @@ def generate_rsa_private_key( self.openssl_assert(res == 1) evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) + # We can skip RSA key validation here since we just generated the key return _RSAPrivateKey( - self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + self, rsa_cdata, evp_pkey, unsafe_skip_rsa_key_validation=True ) def generate_rsa_parameters_supported( @@ -556,7 +556,9 @@ def generate_rsa_parameters_supported( ) def load_rsa_private_numbers( - self, numbers: rsa.RSAPrivateNumbers + self, + numbers: rsa.RSAPrivateNumbers, + unsafe_skip_rsa_key_validation: bool, ) -> rsa.RSAPrivateKey: rsa._check_private_key_components( numbers.p, @@ -588,7 +590,10 @@ def load_rsa_private_numbers( evp_pkey = self._rsa_cdata_to_evp_pkey(rsa_cdata) return _RSAPrivateKey( - self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + self, + rsa_cdata, + evp_pkey, + unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation, ) def load_rsa_public_numbers( @@ -653,7 +658,9 @@ def _read_mem_bio(self, bio) -> bytes: bio_data = self._ffi.buffer(buf[0], buf_len)[:] return bio_data - def _evp_pkey_to_private_key(self, evp_pkey) -> PRIVATE_KEY_TYPES: + def _evp_pkey_to_private_key( + self, evp_pkey, unsafe_skip_rsa_key_validation: bool + ) -> PRIVATE_KEY_TYPES: """ Return the appropriate type of PrivateKey given an evp_pkey cdata pointer. @@ -666,7 +673,10 @@ def _evp_pkey_to_private_key(self, evp_pkey) -> PRIVATE_KEY_TYPES: self.openssl_assert(rsa_cdata != self._ffi.NULL) rsa_cdata = self._ffi.gc(rsa_cdata, self._lib.RSA_free) return _RSAPrivateKey( - self, rsa_cdata, evp_pkey, self._rsa_skip_check_key + self, + rsa_cdata, + evp_pkey, + unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation, ) elif ( key_type == self._lib.EVP_PKEY_RSA_PSS @@ -685,7 +695,9 @@ def _evp_pkey_to_private_key(self, evp_pkey) -> PRIVATE_KEY_TYPES: res = self._lib.i2d_RSAPrivateKey_bio(bio, rsa_cdata) self.openssl_assert(res == 1) return self.load_der_private_key( - self._read_mem_bio(bio), password=None + self._read_mem_bio(bio), + password=None, + unsafe_skip_rsa_key_validation=unsafe_skip_rsa_key_validation, ) elif key_type == self._lib.EVP_PKEY_DSA: dsa_cdata = self._lib.EVP_PKEY_get1_DSA(evp_pkey) @@ -932,13 +944,16 @@ def create_cmac_ctx(self, algorithm: BlockCipherAlgorithm) -> _CMACContext: return _CMACContext(self, algorithm) def load_pem_private_key( - self, data: bytes, password: typing.Optional[bytes] + self, + data: bytes, + password: typing.Optional[bytes], + unsafe_skip_rsa_key_validation: bool, ) -> PRIVATE_KEY_TYPES: return self._load_key( self._lib.PEM_read_bio_PrivateKey, - self._evp_pkey_to_private_key, data, password, + unsafe_skip_rsa_key_validation, ) def load_pem_public_key(self, data: bytes) -> PUBLIC_KEY_TYPES: @@ -996,7 +1011,10 @@ def load_pem_parameters(self, data: bytes) -> dh.DHParameters: self._handle_key_loading_error() def load_der_private_key( - self, data: bytes, password: typing.Optional[bytes] + self, + data: bytes, + password: typing.Optional[bytes], + unsafe_skip_rsa_key_validation: bool, ) -> PRIVATE_KEY_TYPES: # OpenSSL has a function called d2i_AutoPrivateKey that in theory # handles this automatically, however it doesn't handle encrypted @@ -1005,15 +1023,17 @@ def load_der_private_key( bio_data = self._bytes_to_bio(data) key = self._evp_pkey_from_der_traditional_key(bio_data, password) if key: - return self._evp_pkey_to_private_key(key) + return self._evp_pkey_to_private_key( + key, unsafe_skip_rsa_key_validation + ) else: # Finally we try to load it with the method that handles encrypted # PKCS8 properly. return self._load_key( self._lib.d2i_PKCS8PrivateKey_bio, - self._evp_pkey_to_private_key, data, password, + unsafe_skip_rsa_key_validation, ) def _evp_pkey_from_der_traditional_key(self, bio_data, password): @@ -1146,7 +1166,9 @@ def _check_keys_correspond(self, key1, key2): if self._lib.EVP_PKEY_cmp(key1._evp_pkey, key2._evp_pkey) != 1: raise ValueError("Keys do not correspond") - def _load_key(self, openssl_read_func, convert_func, data, password): + def _load_key( + self, openssl_read_func, data, password, unsafe_skip_rsa_key_validation + ): mem_bio = self._bytes_to_bio(data) userdata = self._ffi.new("CRYPTOGRAPHY_PASSWORD_DATA *") @@ -1192,7 +1214,9 @@ def _load_key(self, openssl_read_func, convert_func, data, password): password is not None and userdata.called == 1 ) or password is None - return convert_func(evp_pkey) + return self._evp_pkey_to_private_key( + evp_pkey, unsafe_skip_rsa_key_validation + ) def _handle_key_loading_error(self) -> typing.NoReturn: errors = self._consume_errors() @@ -2191,7 +2215,11 @@ def load_pkcs12( if evp_pkey_ptr[0] != self._ffi.NULL: evp_pkey = self._ffi.gc(evp_pkey_ptr[0], self._lib.EVP_PKEY_free) - key = self._evp_pkey_to_private_key(evp_pkey) + # We don't support turning off RSA key validation when loading + # PKCS12 keys + key = self._evp_pkey_to_private_key( + evp_pkey, unsafe_skip_rsa_key_validation=False + ) if x509_ptr[0] != self._ffi.NULL: x509 = self._ffi.gc(x509_ptr[0], self._lib.X509_free) diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 31cff1620461..694829d2c5f1 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -367,7 +367,12 @@ class _RSAPrivateKey(RSAPrivateKey): _key_size: int def __init__( - self, backend: "Backend", rsa_cdata, evp_pkey, _skip_check_key: bool + self, + backend: "Backend", + rsa_cdata, + evp_pkey, + *, + unsafe_skip_rsa_key_validation: bool, ): res: int # RSA_check_key is slower in OpenSSL 3.0.0 due to improved @@ -375,7 +380,7 @@ def __init__( # since users don't load new keys constantly, but for TESTING we've # added an init arg that allows skipping the checks. You should not # use this in production code unless you understand the consequences. - if not _skip_check_key: + if not unsafe_skip_rsa_key_validation: res = backend._lib.RSA_check_key(rsa_cdata) if res != 1: errors = backend._consume_errors_with_text() diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 5ffe767cde53..36d360f223df 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -354,12 +354,19 @@ def iqmp(self) -> int: def public_numbers(self) -> "RSAPublicNumbers": return self._public_numbers - def private_key(self, backend: typing.Any = None) -> RSAPrivateKey: + def private_key( + self, + backend: typing.Any = None, + *, + unsafe_skip_rsa_key_validation: bool = False, + ) -> RSAPrivateKey: from cryptography.hazmat.backends.openssl.backend import ( backend as ossl, ) - return ossl.load_rsa_private_numbers(self) + return ossl.load_rsa_private_numbers( + self, unsafe_skip_rsa_key_validation + ) def __eq__(self, other: object) -> bool: if not isinstance(other, RSAPrivateNumbers): diff --git a/src/cryptography/hazmat/primitives/serialization/base.py b/src/cryptography/hazmat/primitives/serialization/base.py index 059b6e40f46d..8a841766404f 100644 --- a/src/cryptography/hazmat/primitives/serialization/base.py +++ b/src/cryptography/hazmat/primitives/serialization/base.py @@ -16,10 +16,14 @@ def load_pem_private_key( data: bytes, password: typing.Optional[bytes], backend: typing.Any = None, + *, + unsafe_skip_rsa_key_validation: bool = False, ) -> PRIVATE_KEY_TYPES: from cryptography.hazmat.backends.openssl.backend import backend as ossl - return ossl.load_pem_private_key(data, password) + return ossl.load_pem_private_key( + data, password, unsafe_skip_rsa_key_validation + ) def load_pem_public_key( @@ -42,10 +46,14 @@ def load_der_private_key( data: bytes, password: typing.Optional[bytes], backend: typing.Any = None, + *, + unsafe_skip_rsa_key_validation: bool = False, ) -> PRIVATE_KEY_TYPES: from cryptography.hazmat.backends.openssl.backend import backend as ossl - return ossl.load_der_private_key(data, password) + return ossl.load_der_private_key( + data, password, unsafe_skip_rsa_key_validation + ) def load_der_public_key( diff --git a/tests/conftest.py b/tests/conftest.py index 9049922ba51f..a85b41ff9a0f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -46,12 +46,3 @@ def backend(request): # Ensure the error stack is clear after the test errors = openssl_backend._consume_errors_with_text() assert not errors - - -@pytest.fixture -def disable_rsa_checks(backend): - # Use this fixture to skip RSA key checks in tests that need the - # performance. - backend._rsa_skip_check_key = True - yield - backend._rsa_skip_check_key = False diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 7830019cac6a..6f3a975bac89 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -477,7 +477,9 @@ def test_pem_password_cb_no_password(self): def test_unsupported_evp_pkey_type(self): key = backend._create_evp_pkey_gc() with raises_unsupported_algorithm(None): - backend._evp_pkey_to_private_key(key) + backend._evp_pkey_to_private_key( + key, unsafe_skip_rsa_key_validation=False + ) with raises_unsupported_algorithm(None): backend._evp_pkey_to_public_key(key) @@ -493,7 +495,9 @@ def test_very_long_pem_serialization_password(self): ), lambda pemfile: ( backend.load_pem_private_key( - pemfile.read().encode(), password + pemfile.read().encode(), + password, + unsafe_skip_rsa_key_validation=False, ) ), ) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 6f083cbcb541..5a9fa19f37b4 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -487,7 +487,7 @@ class TestRSASignature: ), skip_message="Does not support SHA1 signature.", ) - def test_pkcs1v15_signing(self, backend, disable_rsa_checks, subtests): + def test_pkcs1v15_signing(self, backend, subtests): vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15sign-vectors.txt"), @@ -506,7 +506,7 @@ def test_pkcs1v15_signing(self, backend, disable_rsa_checks, subtests): public_numbers=rsa.RSAPublicNumbers( e=private["public_exponent"], n=private["modulus"] ), - ).private_key(backend) + ).private_key(backend, unsafe_skip_rsa_key_validation=True) signature = private_key.sign( binascii.unhexlify(example["message"]), padding.PKCS1v15(), @@ -1682,9 +1682,7 @@ class TestRSADecryption: ), skip_message="Does not support PKCS1v1.5.", ) - def test_decrypt_pkcs1v15_vectors( - self, backend, disable_rsa_checks, subtests - ): + def test_decrypt_pkcs1v15_vectors(self, backend, subtests): vectors = _flatten_pkcs1_examples( load_vectors_from_file( os.path.join("asymmetric", "RSA", "pkcs1v15crypt-vectors.txt"), @@ -1703,7 +1701,7 @@ def test_decrypt_pkcs1v15_vectors( public_numbers=rsa.RSAPublicNumbers( e=private["public_exponent"], n=private["modulus"] ), - ).private_key(backend) + ).private_key(backend, unsafe_skip_rsa_key_validation=True) ciphertext = binascii.unhexlify(example["encryption"]) assert len(ciphertext) == (skey.key_size + 7) // 8 message = skey.decrypt(ciphertext, padding.PKCS1v15()) @@ -1804,9 +1802,7 @@ def test_decrypt_oaep_vectors(self, subtests, backend): "Does not support OAEP using SHA224 MGF1 and SHA224 hash." ), ) - def test_decrypt_oaep_sha2_vectors( - self, backend, disable_rsa_checks, subtests - ): + def test_decrypt_oaep_sha2_vectors(self, backend, subtests): vectors = _build_oaep_sha2_vectors() for private, public, example, mgf1_alg, hash_alg in vectors: with subtests.test(): @@ -1820,7 +1816,7 @@ def test_decrypt_oaep_sha2_vectors( public_numbers=rsa.RSAPublicNumbers( e=private["public_exponent"], n=private["modulus"] ), - ).private_key(backend) + ).private_key(backend, unsafe_skip_rsa_key_validation=True) message = skey.decrypt( binascii.unhexlify(example["encryption"]), padding.OAEP( diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 7925a5bf91b8..0670e1c47c00 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -98,6 +98,7 @@ def test_rsa_pkcs1v15_signature_generation(backend, wycheproof): wycheproof.testgroup["privateKeyPem"].encode(), password=None, backend=backend, + unsafe_skip_rsa_key_validation=True, ) assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] @@ -193,6 +194,7 @@ def test_rsa_oaep_encryption(backend, wycheproof): wycheproof.testgroup["privateKeyPem"].encode("ascii"), password=None, backend=backend, + unsafe_skip_rsa_key_validation=True, ) assert isinstance(key, rsa.RSAPrivateKey) digest = _DIGESTS[wycheproof.testgroup["sha"]] @@ -228,6 +230,7 @@ def test_rsa_pkcs1_encryption(backend, wycheproof): wycheproof.testgroup["privateKeyPem"].encode("ascii"), password=None, backend=backend, + unsafe_skip_rsa_key_validation=True, ) assert isinstance(key, rsa.RSAPrivateKey) diff --git a/tests/wycheproof/utils.py b/tests/wycheproof/utils.py index 3c18e62afa43..eebbe7ce3bf6 100644 --- a/tests/wycheproof/utils.py +++ b/tests/wycheproof/utils.py @@ -3,9 +3,7 @@ def wycheproof_tests(*paths): def wrapper(func): - def run_wycheproof( - backend, disable_rsa_checks, subtests, pytestconfig - ): + def run_wycheproof(backend, subtests, pytestconfig): wycheproof_root = pytestconfig.getoption( "--wycheproof-root", skip=True ) From 9bf29d56f8ce57c26f24b3a9138ec134468ad69f Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 00:28:42 +0000 Subject: [PATCH 079/298] Bump BoringSSL version to 64393b57e8734b92a6ba784bcfc02b1aa01e5ff2 (#7672) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c1aad752547..576c452ffcb8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 01, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "46a1c7e2334f3fddc7873f35a43c9ad2af9dbe4f"}} + # Latest commit on the master branch, as of Oct 04, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "64393b57e8734b92a6ba784bcfc02b1aa01e5ff2"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 37325b77650c91441675d0976ff83e3d3288853d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 4 Oct 2022 12:22:02 +0000 Subject: [PATCH 080/298] Bump actions/checkout from 3.0.2 to 3.1.0 (#7673) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.0.2 to 3.1.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.0.2...v3.1.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark.yml | 4 +-- .github/workflows/boringssl-version-bump.yml | 2 +- .github/workflows/ci.yml | 30 ++++++++++---------- .github/workflows/macarm64.yml | 4 +-- .github/workflows/wheel-builder.yml | 6 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 10e9c8e03a79..dd11581194bf 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -14,12 +14,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false path: "cryptography-pr" - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "pyca/cryptography" diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index 19f1d9671f1a..f1b223c72349 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -13,7 +13,7 @@ jobs: if: github.repository_owner == 'pyca' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 - id: check-sha run: | SHA=$(git ls-remote https://boringssl.googlesource.com/boringssl refs/heads/master | cut -f1) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 576c452ffcb8..d5edfe454bd8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,7 +47,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -69,7 +69,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-${{ steps.setup-python.outputs.python-version }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -143,7 +143,7 @@ jobs: name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -160,7 +160,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -201,7 +201,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -225,7 +225,7 @@ jobs: - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 with: toolchain: ${{ matrix.RUST }} - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -252,7 +252,7 @@ jobs: name: "Rust Coverage" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -281,7 +281,7 @@ jobs: - run: cargo install cargo-binutils if: steps.cargo-cache.outputs.cache-hit != 'true' - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -338,7 +338,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on macOS" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -362,7 +362,7 @@ jobs: - run: python -m pip install tox requests coverage[toml] - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -402,7 +402,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -435,7 +435,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -470,7 +470,7 @@ jobs: name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false @@ -503,7 +503,7 @@ jobs: name: "linkcheck" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 with: persist-credentials: false - name: Setup python @@ -521,7 +521,7 @@ jobs: needs: [linux, linux-distros, linux-rust, linux-rust-coverage, macos, windows, linux-downstream] if: ${{ always() }} steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 timeout-minutes: 3 with: persist-credentials: false diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index f799668c6373..e6ae28ea5f13 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -29,7 +29,7 @@ jobs: steps: - name: "Delete workspace" # self-hosted runners need this, sigh run: gfind ! -name '.' ! -name '..' -delete - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 with: persist-credentials: false - uses: actions/cache@v3.0.10 @@ -38,7 +38,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.PYTHON.TOXENV }}-cargo-macarm64-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 with: repository: "google/wycheproof" path: "wycheproof" diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index ecabcb5529c1..777f3c8d8a0a 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -45,7 +45,7 @@ jobs: MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} @@ -126,7 +126,7 @@ jobs: ARCHFLAGS: '-arch x86_64' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS ${{ matrix.PYTHON.ARCHFLAGS }}" steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} @@ -206,7 +206,7 @@ jobs: PYTHON: {VERSION: "pypy-3.9"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: - - uses: actions/checkout@v3.0.2 + - uses: actions/checkout@v3.1.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} From 623c5291ed77048c0ee2c630a8f69efee923b6e3 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 5 Oct 2022 00:28:20 +0000 Subject: [PATCH 081/298] Bump BoringSSL version to 5a9043a0ff3a5d952a8cc4c8dd24650dd84cf64e (#7675) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d5edfe454bd8..5aede6e16b70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 04, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "64393b57e8734b92a6ba784bcfc02b1aa01e5ff2"}} + # Latest commit on the master branch, as of Oct 05, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "5a9043a0ff3a5d952a8cc4c8dd24650dd84cf64e"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From a0a16dc63cd364fa734810e3ed93e3b05fdb5477 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 6 Oct 2022 21:27:18 -0500 Subject: [PATCH 082/298] Bump BoringSSL version to 1ee71185a2322dc354bee5e5a0abfb1810a27dc6 (#7676) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5aede6e16b70..e979f8444e0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 05, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "5a9043a0ff3a5d952a8cc4c8dd24650dd84cf64e"}} + # Latest commit on the master branch, as of Oct 07, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "1ee71185a2322dc354bee5e5a0abfb1810a27dc6"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 5b2a3497bb62c0637782a0363b50d0bb7ac5ba9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 7 Oct 2022 12:18:55 +0000 Subject: [PATCH 083/298] Bump syn from 1.0.101 to 1.0.102 in /src/rust (#7677) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.101 to 1.0.102. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.101...1.0.102) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 02184682ebe2..7502bbe31449 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -403,9 +403,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" +checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" dependencies = [ "proc-macro2", "quote", From dd9f4a716f04c50f4f6e608a8730dcddc7d3dab7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Oct 2022 17:24:41 -0500 Subject: [PATCH 084/298] Use PyPy binaries from manylinux image instead of our own (#7678) --- .github/workflows/wheel-builder.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 777f3c8d8a0a..41315a55ddff 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -26,10 +26,10 @@ jobs: fail-fast: false matrix: PYTHON: - - { VERSION: "cp36-cp36m", PATH: "/opt/python/cp36-cp36m/bin/python", ABI_VERSION: 'cp36' } - - { VERSION: "pypy3.7", PATH: "/opt/pypy3.7/bin/pypy" } - - { VERSION: "pypy3.8", PATH: "/opt/pypy3.8/bin/pypy" } - - { VERSION: "pypy3.9", PATH: "/opt/pypy3.9/bin/pypy" } + - { VERSION: "cp36-cp36m", ABI_VERSION: 'cp36' } + - { VERSION: "pp37-pypy37_pp73" } + - { VERSION: "pp38-pypy38_pp73" } + - { VERSION: "pp39-pypy39_pp73" } MANYLINUX: - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64" } - { name: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64"} @@ -37,11 +37,11 @@ jobs: - { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} exclude: # There are no readily available musllinux PyPy distributions - - PYTHON: { VERSION: "pypy3.7", PATH: "/opt/pypy3.7/bin/pypy" } + - PYTHON: { VERSION: "pp37-pypy37_pp73" } MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64" } - - PYTHON: { VERSION: "pypy3.8", PATH: "/opt/pypy3.8/bin/pypy" } + - PYTHON: { VERSION: "pp38-pypy38_pp73" } MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} - - PYTHON: { VERSION: "pypy3.9", PATH: "/opt/pypy3.9/bin/pypy" } + - PYTHON: { VERSION: "pp39-pypy39_pp73" } MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: @@ -49,7 +49,7 @@ jobs: with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} - - run: ${{ matrix.PYTHON.PATH }} -m venv .venv + - run: /opt/python/${{ matrix.PYTHON.VERSION }}/bin/python -m venv .venv - name: Install Python dependencies run: .venv/bin/pip install -U pip wheel cffi setuptools-rust - name: Make sdist From 16cf047e46be0370cc58fc0fa186055193be669c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 7 Oct 2022 17:42:52 -0500 Subject: [PATCH 085/298] make casing consistent (#7679) --- .github/workflows/wheel-builder.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 41315a55ddff..29e7a528325f 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -32,17 +32,17 @@ jobs: - { VERSION: "pp39-pypy39_pp73" } MANYLINUX: - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64" } - - { name: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64"} - - { name: "manylinux_2_28_x86_64", CONTAINER: "cryptography-manylinux_2_28:x86_64"} - - { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + - { NAME: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64"} + - { NAME: "manylinux_2_28_x86_64", CONTAINER: "cryptography-manylinux_2_28:x86_64"} + - { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} exclude: # There are no readily available musllinux PyPy distributions - PYTHON: { VERSION: "pp37-pypy37_pp73" } - MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64" } + MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64" } - PYTHON: { VERSION: "pp38-pypy38_pp73" } - MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} - PYTHON: { VERSION: "pp39-pypy39_pp73" } - MANYLINUX: { name: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - uses: actions/checkout@v3.1.0 From ebc4a4aacbafc48284fb730f8ddf379bf76f0b70 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 8 Oct 2022 23:53:00 -0500 Subject: [PATCH 086/298] Bump BoringSSL version to 8927cb8f814ad3cb7cde08f02e826f1eed02bfb0 (#7680) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e979f8444e0f..a05679a4dbb5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 07, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "1ee71185a2322dc354bee5e5a0abfb1810a27dc6"}} + # Latest commit on the master branch, as of Oct 09, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "8927cb8f814ad3cb7cde08f02e826f1eed02bfb0"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 469a51ac6a6d550d5da031993e4914d8aaaf301c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Oct 2022 13:52:42 +0000 Subject: [PATCH 087/298] Bump unicode-ident from 1.0.4 to 1.0.5 in /src/rust (#7681) Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.4 to 1.0.5. - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.4...1.0.5) --- updated-dependencies: - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 7502bbe31449..fc2eb39cf5bc 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -414,9 +414,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" +checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "unindent" From ded6cecc968be16033de97e16c7e5a1bce111811 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 9 Oct 2022 14:00:06 +0000 Subject: [PATCH 088/298] Bump iana-time-zone from 0.1.50 to 0.1.51 in /src/rust (#7682) Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.50 to 0.1.51. - [Release notes](https://github.com/strawlab/iana-time-zone/releases) - [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md) - [Commits](https://github.com/strawlab/iana-time-zone/commits) --- updated-dependencies: - dependency-name: iana-time-zone dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 114 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index fc2eb39cf5bc..5bcd404c2e70 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -68,6 +68,12 @@ version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +[[package]] +name = "cc" +version = "1.0.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" + [[package]] name = "cfg-if" version = "1.0.0" @@ -86,6 +92,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "core-foundation-sys" version = "0.8.3" @@ -104,19 +120,74 @@ dependencies = [ "pyo3", ] +[[package]] +name = "cxx" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4" +dependencies = [ + "cc", + "cxxbridge-flags", + "cxxbridge-macro", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199" +dependencies = [ + "cc", + "codespan-reporting", + "once_cell", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "iana-time-zone" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd911b35d940d2bd0bea0f9100068e5b97b51a1cbe13d13382f132e0365257a0" +checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" dependencies = [ "android_system_properties", "core-foundation-sys", + "iana-time-zone-haiku", "js-sys", "wasm-bindgen", "winapi", ] +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa" +dependencies = [ + "cxx", + "cxx-build", +] + [[package]] name = "indoc" version = "0.3.6" @@ -164,6 +235,15 @@ version = "0.2.134" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" +[[package]] +name = "link-cplusplus" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +dependencies = [ + "cc", +] + [[package]] name = "lock_api" version = "0.4.9" @@ -395,6 +475,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "scratch" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" + [[package]] name = "smallvec" version = "1.10.0" @@ -412,12 +498,27 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +dependencies = [ + "winapi-util", +] + [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +[[package]] +name = "unicode-width" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" + [[package]] name = "unindent" version = "0.1.10" @@ -500,6 +601,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" From 8437559dba0e875498adf2f566d4c2a949b01297 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 9 Oct 2022 14:56:46 -0500 Subject: [PATCH 089/298] test against libressl in CI (#7683) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a05679a4dbb5..2324b1083749 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,6 +40,7 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} # Latest commit on the master branch, as of Oct 09, 2022. From 163f60be99aef7c392db437d961d28d49ef76854 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 9 Oct 2022 15:38:13 -0500 Subject: [PATCH 090/298] fixes #7554 -- unpin poetry in certbot-josepy downstream tests (#7684) --- .github/downstream.d/certbot-josepy.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/downstream.d/certbot-josepy.sh b/.github/downstream.d/certbot-josepy.sh index 8c046b9c33f7..c27568ffe4f1 100755 --- a/.github/downstream.d/certbot-josepy.sh +++ b/.github/downstream.d/certbot-josepy.sh @@ -5,8 +5,8 @@ case "${1}" in git clone --depth=1 https://github.com/certbot/josepy cd josepy git rev-parse HEAD - curl -sSL https://install.python-poetry.org | python3 - --version=1.1.15 - "${HOME}/.local/bin/poetry" export -f requirements.txt --dev --without-hashes -o constraints.txt + curl -sSL https://install.python-poetry.org | python3 - + "${HOME}/.local/bin/poetry" export -f constraints.txt --dev --without-hashes -o constraints.txt pip install -e . pytest -c constraints.txt ;; run) From eebcc5b610cf738832cbe3381e34b422781b37f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 12:20:13 +0000 Subject: [PATCH 091/298] Bump actions/setup-python from 4.2.0 to 4.3.0 (#7685) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.2.0 to 4.3.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.2.0...v4.3.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/wheel-builder.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index dd11581194bf..9ea619b667aa 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -28,7 +28,7 @@ jobs: - name: Setup python id: setup-python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: "3.10" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2324b1083749..e4fdfec7ed1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,7 +54,7 @@ jobs: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: actions/cache@v3.0.10 @@ -220,7 +220,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} - name: Setup python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 @@ -272,7 +272,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-rust-${{ matrix.RUST }}-coverage - name: Setup python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 @@ -357,7 +357,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} @@ -409,7 +409,7 @@ jobs: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} @@ -489,7 +489,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON }} - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install @@ -508,7 +508,7 @@ jobs: with: persist-credentials: false - name: Setup python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: 3.9 - run: python -m pip install -U tox @@ -532,7 +532,7 @@ jobs: jobs: ${{ toJSON(needs) }} - name: Setup python if: ${{ always() }} - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: '3.10' - run: pip install coverage[toml] diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 29e7a528325f..1312a6107f97 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -139,7 +139,7 @@ jobs: PYTHON_DOWNLOAD_URL: ${{ matrix.PYTHON.DOWNLOAD_URL }} if: contains(matrix.PYTHON.VERSION, 'pypy') == false - name: Setup pypy - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} if: contains(matrix.PYTHON.VERSION, 'pypy') @@ -212,7 +212,7 @@ jobs: ref: ${{ github.event.inputs.version || github.ref }} persist-credentials: false - name: Setup python - uses: actions/setup-python@v4.2.0 + uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} From bcb6f24254d26a9d998d69f60552541183510681 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Oct 2022 12:29:17 +0000 Subject: [PATCH 092/298] Bump libc from 0.2.134 to 0.2.135 in /src/rust (#7686) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.134 to 0.2.135. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.134...0.2.135) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 5bcd404c2e70..ae443452cc8c 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.134" +version = "0.2.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329c933548736bc49fd575ee68c89e8be4d260064184389a5b77517cddd99ffb" +checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" [[package]] name = "link-cplusplus" From 34f8637a37814e2515a3ebf3950ef608b123dc58 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 10 Oct 2022 14:16:28 -0700 Subject: [PATCH 093/298] changelog for chacha (#7687) --- CHANGELOG.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3156ee365f8e..133b2b516293 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -35,6 +35,9 @@ Changelog :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers.private_key`. This speeds up key loading but is :term:`unsafe` if you are loading potentially attacker supplied keys. +* Significantly improved performance for + :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305` + when repeatedly calling ``encrypt`` or ``decrypt`` with the same key. .. _v38-0-1: From 07d4603e603fd0e92e0a675745840ca013a3f74b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 10 Oct 2022 15:03:33 -0700 Subject: [PATCH 094/298] centos9 with OPENSSL_ENABLE_SHA1_SIGNATURES (#7688) * centos9 with OPENSSL_ENABLE_SHA1_SIGNATURES * now fips! --- .github/workflows/ci.yml | 3 +++ tox.ini | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e4fdfec7ed1d..1f570f54851a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -141,6 +141,7 @@ jobs: - {IMAGE: "ubuntu-rolling", TOXENV: "py310"} - {IMAGE: "fedora", TOXENV: "py310"} - {IMAGE: "alpine", TOXENV: "py310"} + - {IMAGE: "centos-stream9", TOXENV: "py39"} name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" timeout-minutes: 15 steps: @@ -180,6 +181,8 @@ jobs: TOXENV: ${{ matrix.IMAGE.TOXENV }} RUSTUP_HOME: /root/.rustup CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} + # OPENSSL_ENABLE_SHA1_SIGNATURES is for CentOS 9 Stream + OPENSSL_ENABLE_SHA1_SIGNATURES: 1 - uses: ./.github/actions/upload-coverage linux-rust: diff --git a/tox.ini b/tox.ini index 655d4d2c222e..34ec06889ce7 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,7 @@ deps = -e ./vectors pytest-shard>=0.1.2 randomorder: pytest-randomly -passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH RUSTFLAGS CARGO_TARGET_DIR LLVM_PROFILE_FILE OPENSSL_FORCE_FIPS_MODE RUSTUP_TOOLCHAIN CRYPTOGRAPHY_OPENSSL_NO_LEGACY +passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH RUSTFLAGS CARGO_TARGET_DIR LLVM_PROFILE_FILE OPENSSL_FORCE_FIPS_MODE RUSTUP_TOOLCHAIN CRYPTOGRAPHY_OPENSSL_NO_LEGACY OPENSSL_ENABLE_SHA1_SIGNATURES commands = pip list !nocoverage: pytest -n auto --cov=cryptography --cov=tests --durations=10 {posargs} tests/ From 6578d86ec557e0b4af2ba9d0c0a821fe939044ee Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 11 Oct 2022 09:32:51 -0700 Subject: [PATCH 095/298] upgrade some openssls in CI (#7690) * bump tests to 3.0.6 * qs become rs * fix openssl 3.0.6 error stack bug in pkcs12 * flake * more comment --- .github/workflows/ci.yml | 14 +++++++------- .../hazmat/backends/openssl/backend.py | 6 ++++-- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f570f54851a..be3f1497dd7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,16 +28,16 @@ jobs: PYTHON: - {VERSION: "3.10", TOXENV: "flake"} - {VERSION: "3.10", TOXENV: "rust"} - - {VERSION: "3.10", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} + - {VERSION: "3.10", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.6"}} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1r"}} + - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1r"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1r", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.6"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.6", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} + - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.6"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index b84753758996..ab16a53d56cf 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2204,9 +2204,11 @@ def load_pkcs12( res = self._lib.PKCS12_parse( p12, password_buf, evp_pkey_ptr, x509_ptr, sk_x509_ptr ) - + # OpenSSL 3.0.6 leaves errors on the stack even in success, so + # we consume all errors unconditionally. + # https://github.com/openssl/openssl/issues/19389 + self._consume_errors() if res == 0: - self._consume_errors() raise ValueError("Invalid password or PKCS12 data") cert = None From dabe96395a7de0e125a2bca2e1973b5762ea220a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 11 Oct 2022 15:04:37 -0400 Subject: [PATCH 096/298] Update github output syntax for deprecation (#7692) --- .github/actions/upload-coverage/action.yml | 2 +- .github/workflows/boringssl-version-bump.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/actions/upload-coverage/action.yml b/.github/actions/upload-coverage/action.yml index 785b2814e190..98e88bee40ae 100644 --- a/.github/actions/upload-coverage/action.yml +++ b/.github/actions/upload-coverage/action.yml @@ -7,7 +7,7 @@ runs: steps: - run: | COVERAGE_UUID=$(python3 -c "import uuid; print(uuid.uuid4())") - echo "::set-output name=COVERAGE_UUID::${COVERAGE_UUID}" + echo "COVERAGE_UUID=${COVERAGE_UUID}" >> $GITHUB_OUTPUT if [ -f .coverage ]; then mv .coverage .coverage.${COVERAGE_UUID} fi diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index f1b223c72349..f9a6fca673bf 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -18,10 +18,10 @@ jobs: run: | SHA=$(git ls-remote https://boringssl.googlesource.com/boringssl refs/heads/master | cut -f1) if ! grep -q "$SHA" .github/workflows/ci.yml; then - echo "::set-output name=BORING_SHA::$SHA" + echo "BORING_SHA=${SHA}" >> $GITHUB_OUTPUT fi LAST_COMMIT=$(grep boringssl .github/workflows/ci.yml | grep TYPE | grep -oE '[a-z0-9]{40}') - echo "::set-output name=LAST_COMMIT::$LAST_COMMIT" + echo "LAST_COMMIT=${LAST_COMMIT}" >> $GITHUB_OUTPUT - name: Update boring run: | set -xe From 5301aa4dc7292b028abc6a4ef2068da7908e12d1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 11 Oct 2022 15:23:05 -0400 Subject: [PATCH 097/298] run wheel builder when we update __about__ (#7694) --- .github/workflows/wheel-builder.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 1312a6107f97..d08df988bec8 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -16,6 +16,7 @@ on: - setup.py - setup.cfg - pyproject.toml + - src/cryptography/__about__.py jobs: From 955a14d27263cf400882748136defafdc9df72e6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 11 Oct 2022 12:25:41 -0700 Subject: [PATCH 098/298] port 38.0.2 changelog to main (#7695) --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 133b2b516293..11e38d65f59a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -39,6 +39,14 @@ Changelog :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305` when repeatedly calling ``encrypt`` or ``decrypt`` with the same key. +.. _v38-0-2: + +38.0.2 - 2022-10-11 +~~~~~~~~~~~~~~~~~~~ + +* Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.0.6. + + .. _v38-0-1: 38.0.1 - 2022-09-07 From 85504abb765ff77d34ab2e5c99ca594d928fe102 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 11 Oct 2022 20:46:16 -0400 Subject: [PATCH 099/298] Bump BoringSSL version to 17832275b714570a1c40e6b3a08c27768fc50cf2 (#7696) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index be3f1497dd7c..a3283e3c5067 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 09, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "8927cb8f814ad3cb7cde08f02e826f1eed02bfb0"}} + # Latest commit on the master branch, as of Oct 12, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "17832275b714570a1c40e6b3a08c27768fc50cf2"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From d59dd10cf6b0dbd14e9200ea2eab76987475658a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 12 Oct 2022 10:20:10 -0400 Subject: [PATCH 100/298] fixes #7454 -- added SSL_get_extms_support (#7697) --- src/_cffi_src/openssl/ssl.py | 7 +++++++ src/cryptography/hazmat/bindings/openssl/_conditional.py | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 025c6a378300..ac396302d5ee 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -44,6 +44,7 @@ static const long Cryptography_HAS_ALPN; static const long Cryptography_HAS_NEXTPROTONEG; static const long Cryptography_HAS_SET_CERT_CB; +static const long Cryptography_HAS_GET_EXTMS_SUPPORT; static const long Cryptography_HAS_CUSTOM_EXT; static const long Cryptography_HAS_SRTP; static const long Cryptography_HAS_DTLS_GET_DATA_MTU; @@ -186,6 +187,8 @@ void SSL_set_verify(SSL *, int, int (*)(int, X509_STORE_CTX *)); int SSL_get_verify_mode(const SSL *); +long SSL_get_extms_support(SSL *); + X509_VERIFY_PARAM *SSL_get0_param(SSL *); X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *); @@ -605,8 +608,12 @@ void (*SSL_CTX_set_cert_cb)(SSL_CTX *, int (*)(SSL *, void *), void *) = NULL; void (*SSL_set_cert_cb)(SSL *, int (*)(SSL *, void *), void *) = NULL; static const long Cryptography_HAS_SET_CERT_CB = 0; + +long (*SSL_get_extms_support)(SSL *) = NULL; +static const long Cryptography_HAS_GET_EXTMS_SUPPORT = 0; #else static const long Cryptography_HAS_SET_CERT_CB = 1; +static const long Cryptography_HAS_GET_EXTMS_SUPPORT = 1; #endif static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS = 1; diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index e71319573598..d14e55c0d8ff 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -296,6 +296,10 @@ def cryptography_has_ssl_op_ignore_unexpected_eof() -> typing.List[str]: ] +def cryptography_has_get_extms_support() -> typing.List[str]: + return ["SSL_get_extms_support"] + + # 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 @@ -352,4 +356,5 @@ def cryptography_has_ssl_op_ignore_unexpected_eof() -> typing.List[str]: "Cryptography_HAS_SSL_OP_IGNORE_UNEXPECTED_EOF": ( cryptography_has_ssl_op_ignore_unexpected_eof ), + "Cryptography_HAS_GET_EXTMS_SUPPORT": cryptography_has_get_extms_support, } From 7a22e6262b5760994b1ad663aa33fff2bdf55bcc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 12 Oct 2022 10:49:19 -0400 Subject: [PATCH 101/298] openssl covering itself in glory (#7698) --- CHANGELOG.rst | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 11e38d65f59a..8dce8855f746 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -41,8 +41,12 @@ Changelog .. _v38-0-2: -38.0.2 - 2022-10-11 -~~~~~~~~~~~~~~~~~~~ +38.0.2 - 2022-10-11 (YANKED) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. attention:: + + This release was subsequently yanked from PyPI due to a regression in OpenSSL. * Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.0.6. From 34412de1b28eb268be959a79d754cb64a6c8bb79 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 12 Oct 2022 11:14:56 -0400 Subject: [PATCH 102/298] more warnings and context around RSA online decryption (#7699) --- docs/hazmat/primitives/asymmetric/rsa.rst | 5 +++++ docs/limitations.rst | 16 +++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 2dfccb1a01a1..384cab0736e7 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -555,6 +555,11 @@ Key interfaces .. versionadded:: 0.4 + .. warning:: + + Our implementation of PKCS1 v1.5 decryption is not constant time. See + :doc:`/limitations` for details. + Decrypt data that was encrypted with the public key. :param bytes ciphertext: The ciphertext to decrypt. diff --git a/docs/limitations.rst b/docs/limitations.rst index 227ed6cd7a37..3f43c743c729 100644 --- a/docs/limitations.rst +++ b/docs/limitations.rst @@ -24,21 +24,23 @@ RSA PKCS1 v1.5 constant time decryption --------------------------------------- RSA decryption has several different modes, one of which is PKCS1 v1.5. When -used in online contexts, a secure protocol implementation requires that peers -not be able to tell whether RSA PKCS1 v1.5 decryption failed or succeeded, -even by timing variability. +used in **online contexts**, a secure protocol implementation requires that +peers not be able to tell whether RSA PKCS1 v1.5 decryption failed or +succeeded, even by timing variability. ``cryptography`` does not provide an API that makes this possible, due to the fact that RSA decryption raises an exception on failure, which takes a different amount of time than returning a value in the success case. -For this reason, at present, we recommend not implementing online protocols +Fixing this would require a new API in ``cryptography``, but OpenSSL does +not expose an API for straightforwardly implementing this while reusing +its own constant-time logic. See `issue 6167`_ for more information. + +For this reason we recommend not implementing online protocols that use RSA PKCS1 v1.5 decryption with ``cryptography`` -- independent of this limitation, such protocols generally have poor security properties due to their lack of forward security. -If a constant time RSA PKCS1 v1.5 decryption API is truly required, you should -contribute one to ``cryptography``. - .. _`Memory wiping`: https://devblogs.microsoft.com/oldnewthing/?p=4223 .. _`CERT secure coding guidelines`: https://wiki.sei.cmu.edu/confluence/display/c/MEM03-C.+Clear+sensitive+information+stored+in+reusable+resources +.. _`issue 6167`: https://github.com/pyca/cryptography/issues/6167#issuecomment-1276151799 \ No newline at end of file From ddd16898057274b5e9fc262b566857a7361c51a3 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 12 Oct 2022 21:39:05 -0400 Subject: [PATCH 103/298] Bump BoringSSL version to 9cd85d0b4c3ea8fc0e1a1883bab3a46ffaa18bd9 (#7701) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a3283e3c5067..5afe6dd15ef3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 12, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "17832275b714570a1c40e6b3a08c27768fc50cf2"}} + # Latest commit on the master branch, as of Oct 13, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "9cd85d0b4c3ea8fc0e1a1883bab3a46ffaa18bd9"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 9da9af7988c8564c7974011e6a1a7e741ab52ac6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 12 Oct 2022 22:02:57 -0400 Subject: [PATCH 104/298] Convert basic PKCS7 generation to Rust (#7700) --- .../hazmat/backends/openssl/backend.py | 47 ------- .../hazmat/bindings/_rust/pkcs7.pyi | 9 ++ .../hazmat/primitives/serialization/pkcs7.py | 5 +- src/rust/src/lib.rs | 2 + src/rust/src/pkcs7.rs | 116 ++++++++++++++++++ tests/hazmat/primitives/test_pkcs7.py | 2 +- 6 files changed, 130 insertions(+), 51 deletions(-) create mode 100644 src/cryptography/hazmat/bindings/_rust/pkcs7.pyi create mode 100644 src/rust/src/pkcs7.rs diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index ab16a53d56cf..64be465d4c73 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2486,53 +2486,6 @@ def _load_pkcs7_certificates(self, p7): return certs - def pkcs7_serialize_certificates( - self, - certs: typing.List[x509.Certificate], - encoding: serialization.Encoding, - ): - certs = list(certs) - if not certs or not all( - isinstance(cert, x509.Certificate) for cert in certs - ): - raise TypeError("certs must be a list of certs with length >= 1") - - if encoding not in ( - serialization.Encoding.PEM, - serialization.Encoding.DER, - ): - raise TypeError("encoding must DER or PEM from the Encoding enum") - - certs_sk = self._lib.sk_X509_new_null() - certs_sk = self._ffi.gc(certs_sk, self._lib.sk_X509_free) - # This list is to keep the x509 values alive until end of function - ossl_certs = [] - for cert in certs: - ossl_cert = self._cert2ossl(cert) - ossl_certs.append(ossl_cert) - res = self._lib.sk_X509_push(certs_sk, ossl_cert) - self.openssl_assert(res >= 1) - # We use PKCS7_sign here because it creates the PKCS7 and PKCS7_SIGNED - # structures for us rather than requiring manual assignment. - p7 = self._lib.PKCS7_sign( - self._ffi.NULL, - self._ffi.NULL, - certs_sk, - self._ffi.NULL, - self._lib.PKCS7_PARTIAL, - ) - bio_out = self._create_mem_bio_gc() - if encoding is serialization.Encoding.PEM: - res = self._lib.PEM_write_bio_PKCS7_stream( - bio_out, p7, self._ffi.NULL, 0 - ) - else: - assert encoding is serialization.Encoding.DER - res = self._lib.i2d_PKCS7_bio(bio_out, p7) - - self.openssl_assert(res == 1) - return self._read_mem_bio(bio_out) - def pkcs7_sign( self, builder: pkcs7.PKCS7SignatureBuilder, diff --git a/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi b/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi new file mode 100644 index 000000000000..1a0b5cad5db0 --- /dev/null +++ b/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi @@ -0,0 +1,9 @@ +import typing + +from cryptography.hazmat.primitives import serialization +from cryptography import x509 + +def serialize_certificates( + certs: typing.List[x509.Certificate], + encoding: serialization.Encoding, +) -> bytes: ... diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index 664141682a4a..fb754dff3a0c 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -6,6 +6,7 @@ from cryptography import utils from cryptography import x509 +from cryptography.hazmat.bindings._rust import pkcs7 as rust_pkcs7 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa from cryptography.utils import _check_byteslike @@ -27,9 +28,7 @@ def serialize_certificates( certs: typing.List[x509.Certificate], encoding: serialization.Encoding, ) -> bytes: - from cryptography.hazmat.backends.openssl.backend import backend - - return backend.pkcs7_serialize_certificates(certs, encoding) + return rust_pkcs7.serialize_certificates(certs, encoding) _ALLOWED_PKCS7_HASH_TYPES = typing.Union[ diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index 067af4c949f5..df4cf92e058f 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -11,6 +11,7 @@ mod asn1; mod intern; pub(crate) mod oid; +mod pkcs7; mod pool; mod x509; @@ -85,6 +86,7 @@ fn _rust(py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> m.add_class::()?; m.add_submodule(asn1::create_submodule(py)?)?; + m.add_submodule(pkcs7::create_submodule(py)?)?; let x509_mod = pyo3::prelude::PyModule::new(py, "x509")?; crate::x509::certificate::add_to_module(x509_mod)?; diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs new file mode 100644 index 000000000000..45f436e19d12 --- /dev/null +++ b/src/rust/src/pkcs7.rs @@ -0,0 +1,116 @@ +// 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. + +use crate::asn1::PyAsn1Result; +use crate::x509; + +use once_cell::sync::Lazy; + +const PKCS7_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 7, 1); +const PKCS7_SIGNED_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 7, 2); + +static EMPTY_STRING_DER: Lazy> = Lazy::new(|| { + // TODO: kind of verbose way to say "\x04\x00". + asn1::write_single(&(&[] as &[u8])).unwrap() +}); +pub(crate) static EMPTY_STRING_TLV: Lazy> = + Lazy::new(|| asn1::parse_single(&EMPTY_STRING_DER).unwrap()); + +#[derive(asn1::Asn1Write)] +struct ContentInfo<'a> { + content_type: asn1::ObjectIdentifier, + #[explicit(0)] + content: Option>, +} + +#[derive(asn1::Asn1Write)] +struct SignedData<'a> { + version: u8, + digest_algorithms: asn1::SetOfWriter<'a, asn1::ObjectIdentifier>, + content_info: ContentInfo<'a>, + #[implicit(0)] + certificates: Option>>, + + // Not actually just a Tlv, but these are always empty (and omitted) for + // now. + #[implicit(1)] + crls: Option>>, + + // We don't ever supply any of these, so for now, don't fill out the fields. + signer_infos: asn1::SetOfWriter<'a, asn1::Sequence<'a>>, +} + +#[pyo3::prelude::pyfunction] +fn serialize_certificates<'p>( + py: pyo3::Python<'p>, + py_certs: Vec>, + encoding: &'p pyo3::PyAny, +) -> PyAsn1Result<&'p pyo3::types::PyBytes> { + if py_certs.is_empty() { + return Err(pyo3::exceptions::PyTypeError::new_err( + "certs must be a list of certs with length >= 1", + ) + .into()); + } + + let raw_certs = py_certs + .iter() + .map(|c| c.raw.borrow_value_public()) + .collect::>(); + + let signed_data = SignedData { + version: 1, + digest_algorithms: asn1::SetOfWriter::new(&[]), + content_info: ContentInfo { + content_type: PKCS7_DATA_OID, + content: Some(*EMPTY_STRING_TLV), + }, + certificates: Some(asn1::SetOfWriter::new(&raw_certs)), + crls: None, + signer_infos: asn1::SetOfWriter::new(&[]), + }; + + let signed_data_bytes = asn1::write_single(&signed_data)?; + + let content_info = ContentInfo { + content_type: PKCS7_SIGNED_DATA_OID, + content: Some(asn1::parse_single(&signed_data_bytes).unwrap()), + }; + let content_info_bytes = asn1::write_single(&content_info)?; + + let encoding_class = py + .import("cryptography.hazmat.primitives.serialization")? + .getattr(crate::intern!(py, "Encoding"))?; + + if encoding == encoding_class.getattr(crate::intern!(py, "DER"))? { + Ok(pyo3::types::PyBytes::new(py, &content_info_bytes)) + } else if encoding == encoding_class.getattr(crate::intern!(py, "PEM"))? { + Ok(pyo3::types::PyBytes::new( + py, + &pem::encode_config( + &pem::Pem { + tag: "PKCS7".to_string(), + contents: content_info_bytes, + }, + pem::EncodeConfig { + line_ending: pem::LineEnding::LF, + }, + ) + .into_bytes(), + )) + } else { + Err( + pyo3::exceptions::PyTypeError::new_err("encoding must be Encoding.DER or Encoding.PEM") + .into(), + ) + } +} + +pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { + let submod = pyo3::prelude::PyModule::new(py, "pkcs7")?; + + submod.add_wrapped(pyo3::wrap_pyfunction!(serialize_certificates))?; + + Ok(submod) +} diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 138bc0f3bcd9..d3edc4845b45 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -741,7 +741,7 @@ def test_ordering(self, backend): list(reversed(certs)), serialization.Encoding.DER ) certs2 = pkcs7.load_der_pkcs7_certificates(p7) - assert certs != certs2 + assert certs == certs2 def test_pem_matches_vector(self, backend): p7_pem = load_vectors_from_file( From a45f26ade5bf9f79b1fce7907f76bb003b1df949 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 12 Oct 2022 22:20:28 -0400 Subject: [PATCH 105/298] Cleanup DER/PEM encoding in rust (#7702) --- src/rust/src/asn1.rs | 34 ++++++++++++++++++++++++++++++++ src/rust/src/pkcs7.rs | 29 ++------------------------- src/rust/src/x509/certificate.rs | 31 +++++------------------------ src/rust/src/x509/crl.rs | 31 +++++------------------------ src/rust/src/x509/csr.rs | 30 ++++------------------------ 5 files changed, 50 insertions(+), 105 deletions(-) diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs index 1ca443d21802..522e21ac6222 100644 --- a/src/rust/src/asn1.rs +++ b/src/rust/src/asn1.rs @@ -159,6 +159,40 @@ pub(crate) fn py_uint_to_big_endian_bytes<'p>( v.call_method1("to_bytes", (n, "big"))?.extract() } +pub(crate) fn encode_der_data<'p>( + py: pyo3::Python<'p>, + pem_tag: String, + data: Vec, + encoding: &'p pyo3::PyAny, +) -> PyAsn1Result<&'p pyo3::types::PyBytes> { + let encoding_class = py + .import("cryptography.hazmat.primitives.serialization")? + .getattr(crate::intern!(py, "Encoding"))?; + + if encoding == encoding_class.getattr(crate::intern!(py, "DER"))? { + Ok(pyo3::types::PyBytes::new(py, &data)) + } else if encoding == encoding_class.getattr(crate::intern!(py, "PEM"))? { + Ok(pyo3::types::PyBytes::new( + py, + &pem::encode_config( + &pem::Pem { + tag: pem_tag, + contents: data, + }, + pem::EncodeConfig { + line_ending: pem::LineEnding::LF, + }, + ) + .into_bytes(), + )) + } else { + Err( + pyo3::exceptions::PyTypeError::new_err("encoding must be Encoding.DER or Encoding.PEM") + .into(), + ) + } +} + #[pyo3::prelude::pyfunction] fn encode_dss_signature( py: pyo3::Python<'_>, diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs index 45f436e19d12..28cd08a4e8e0 100644 --- a/src/rust/src/pkcs7.rs +++ b/src/rust/src/pkcs7.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::PyAsn1Result; +use crate::asn1::{encode_der_data, PyAsn1Result}; use crate::x509; use once_cell::sync::Lazy; @@ -79,32 +79,7 @@ fn serialize_certificates<'p>( }; let content_info_bytes = asn1::write_single(&content_info)?; - let encoding_class = py - .import("cryptography.hazmat.primitives.serialization")? - .getattr(crate::intern!(py, "Encoding"))?; - - if encoding == encoding_class.getattr(crate::intern!(py, "DER"))? { - Ok(pyo3::types::PyBytes::new(py, &content_info_bytes)) - } else if encoding == encoding_class.getattr(crate::intern!(py, "PEM"))? { - Ok(pyo3::types::PyBytes::new( - py, - &pem::encode_config( - &pem::Pem { - tag: "PKCS7".to_string(), - contents: content_info_bytes, - }, - pem::EncodeConfig { - line_ending: pem::LineEnding::LF, - }, - ) - .into_bytes(), - )) - } else { - Err( - pyo3::exceptions::PyTypeError::new_err("encoding must be Encoding.DER or Encoding.PEM") - .into(), - ) - } + encode_der_data(py, "PKCS7".to_string(), content_info_bytes, encoding) } pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs index 549e89681d42..a70a9c78039a 100644 --- a/src/rust/src/x509/certificate.rs +++ b/src/rust/src/x509/certificate.rs @@ -3,7 +3,8 @@ // for complete details. use crate::asn1::{ - big_byte_slice_to_py_int, oid_to_py_oid, py_uint_to_big_endian_bytes, PyAsn1Error, PyAsn1Result, + big_byte_slice_to_py_int, encode_der_data, oid_to_py_oid, py_uint_to_big_endian_bytes, + PyAsn1Error, PyAsn1Result, }; use crate::x509; use crate::x509::{crl, extensions, oid, sct, Asn1ReadableOrWritable}; @@ -151,33 +152,11 @@ impl Certificate { fn public_bytes<'p>( &self, py: pyo3::Python<'p>, - encoding: &pyo3::PyAny, + encoding: &'p pyo3::PyAny, ) -> PyAsn1Result<&'p pyo3::types::PyBytes> { - let encoding_class = py - .import("cryptography.hazmat.primitives.serialization")? - .getattr(crate::intern!(py, "Encoding"))?; - let result = asn1::write_single(self.raw.borrow_value())?; - if encoding == encoding_class.getattr(crate::intern!(py, "DER"))? { - Ok(pyo3::types::PyBytes::new(py, &result)) - } else if encoding == encoding_class.getattr(crate::intern!(py, "PEM"))? { - let pem = pem::encode_config( - &pem::Pem { - tag: "CERTIFICATE".to_string(), - contents: result, - }, - pem::EncodeConfig { - line_ending: pem::LineEnding::LF, - }, - ) - .into_bytes(); - Ok(pyo3::types::PyBytes::new(py, &pem)) - } else { - Err(pyo3::exceptions::PyTypeError::new_err( - "encoding must be Encoding.DER or Encoding.PEM", - ) - .into()) - } + + encode_der_data(py, "CERTIFICATE".to_string(), result, encoding) } #[getter] diff --git a/src/rust/src/x509/crl.rs b/src/rust/src/x509/crl.rs index 2152b2f5e6fa..44e3bfd70fc9 100644 --- a/src/rust/src/x509/crl.rs +++ b/src/rust/src/x509/crl.rs @@ -3,7 +3,8 @@ // for complete details. use crate::asn1::{ - big_byte_slice_to_py_int, oid_to_py_oid, py_uint_to_big_endian_bytes, PyAsn1Error, PyAsn1Result, + big_byte_slice_to_py_int, encode_der_data, oid_to_py_oid, py_uint_to_big_endian_bytes, + PyAsn1Error, PyAsn1Result, }; use crate::x509; use crate::x509::{certificate, extensions, oid}; @@ -215,33 +216,11 @@ impl CertificateRevocationList { fn public_bytes<'p>( &self, py: pyo3::Python<'p>, - encoding: &pyo3::PyAny, + encoding: &'p pyo3::PyAny, ) -> PyAsn1Result<&'p pyo3::types::PyBytes> { - let encoding_class = py - .import("cryptography.hazmat.primitives.serialization")? - .getattr(crate::intern!(py, "Encoding"))?; - let result = asn1::write_single(self.raw.borrow_value())?; - if encoding == encoding_class.getattr(crate::intern!(py, "DER"))? { - Ok(pyo3::types::PyBytes::new(py, &result)) - } else if encoding == encoding_class.getattr(crate::intern!(py, "PEM"))? { - let pem = pem::encode_config( - &pem::Pem { - tag: "X509 CRL".to_string(), - contents: result, - }, - pem::EncodeConfig { - line_ending: pem::LineEnding::LF, - }, - ) - .into_bytes(); - Ok(pyo3::types::PyBytes::new(py, &pem)) - } else { - Err(pyo3::exceptions::PyTypeError::new_err( - "encoding must be Encoding.DER or Encoding.PEM", - ) - .into()) - } + + encode_der_data(py, "X509 CRL".to_string(), result, encoding) } #[getter] diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs index 80ee8701b6c9..280176b95d61 100644 --- a/src/rust/src/x509/csr.rs +++ b/src/rust/src/x509/csr.rs @@ -2,7 +2,7 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{oid_to_py_oid, py_oid_to_oid, PyAsn1Error, PyAsn1Result}; +use crate::asn1::{encode_der_data, oid_to_py_oid, py_oid_to_oid, PyAsn1Error, PyAsn1Result}; use crate::x509; use crate::x509::{certificate, oid}; use asn1::SimpleAsn1Readable; @@ -169,33 +169,11 @@ impl CertificateSigningRequest { fn public_bytes<'p>( &self, py: pyo3::Python<'p>, - encoding: &pyo3::PyAny, + encoding: &'p pyo3::PyAny, ) -> PyAsn1Result<&'p pyo3::types::PyBytes> { - let encoding_class = py - .import("cryptography.hazmat.primitives.serialization")? - .getattr(crate::intern!(py, "Encoding"))?; - let result = asn1::write_single(self.raw.borrow_value())?; - if encoding == encoding_class.getattr(crate::intern!(py, "DER"))? { - Ok(pyo3::types::PyBytes::new(py, &result)) - } else if encoding == encoding_class.getattr(crate::intern!(py, "PEM"))? { - let pem = pem::encode_config( - &pem::Pem { - tag: "CERTIFICATE REQUEST".to_string(), - contents: result, - }, - pem::EncodeConfig { - line_ending: pem::LineEnding::LF, - }, - ) - .into_bytes(); - Ok(pyo3::types::PyBytes::new(py, &pem)) - } else { - Err(pyo3::exceptions::PyTypeError::new_err( - "encoding must be Encoding.DER or Encoding.PEM", - ) - .into()) - } + + encode_der_data(py, "CERTIFICATE REQUEST".to_string(), result, encoding) } fn get_attribute_for_oid<'p>( From 25d794e079b44e6fac23791ca51da3a3fb9cb526 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 12:16:05 +0000 Subject: [PATCH 106/298] Bump actions/cache from 3.0.10 to 3.0.11 (#7703) Bumps [actions/cache](https://github.com/actions/cache) from 3.0.10 to 3.0.11. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.0.10...v3.0.11) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/macarm64.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5afe6dd15ef3..0aca55ea5ac2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,7 +57,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 timeout-minutes: 5 with: path: | @@ -90,7 +90,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.0.10 + uses: actions/cache@v3.0.11 id: ossl-cache timeout-minutes: 5 with: @@ -149,7 +149,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 timeout-minutes: 5 with: path: | @@ -209,7 +209,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 timeout-minutes: 5 with: path: | @@ -260,7 +260,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 id: cargo-cache timeout-minutes: 5 with: @@ -346,7 +346,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 timeout-minutes: 5 with: path: | @@ -416,7 +416,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 timeout-minutes: 5 with: path: | @@ -478,7 +478,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 timeout-minutes: 5 with: path: | diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index e6ae28ea5f13..6457d4b5fa56 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3.1.0 with: persist-credentials: false - - uses: actions/cache@v3.0.10 + - uses: actions/cache@v3.0.11 with: path: | src/rust/target/ From e8d19a66e6e342067949de15e593bbd9591a215c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 13 Oct 2022 09:40:38 -0400 Subject: [PATCH 107/298] small cleanups/fixes for pkcs7 (#7704) --- src/rust/src/pkcs7.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs index 28cd08a4e8e0..079419c8f2e4 100644 --- a/src/rust/src/pkcs7.rs +++ b/src/rust/src/pkcs7.rs @@ -27,15 +27,14 @@ struct ContentInfo<'a> { #[derive(asn1::Asn1Write)] struct SignedData<'a> { version: u8, - digest_algorithms: asn1::SetOfWriter<'a, asn1::ObjectIdentifier>, + digest_algorithms: asn1::SetOfWriter<'a, x509::AlgorithmIdentifier<'a>>, content_info: ContentInfo<'a>, #[implicit(0)] certificates: Option>>, - // Not actually just a Tlv, but these are always empty (and omitted) for - // now. + // We don't ever supply any of these, so for now, don't fill out the fields. #[implicit(1)] - crls: Option>>, + crls: Option>>, // We don't ever supply any of these, so for now, don't fill out the fields. signer_infos: asn1::SetOfWriter<'a, asn1::Sequence<'a>>, From 0f2d8303383aa0ec1717ea20685b5d158248df8a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 13 Oct 2022 18:16:48 -0400 Subject: [PATCH 108/298] add support for creating OCSP requests with precomputed hashes (#7706) * add support for creating OCSP requests with precomputed hashes * mypy and clippy fixes * flake, fix MSRV * MSRV this time * feedback --- CHANGELOG.rst | 2 ++ docs/spelling_wordlist.txt | 1 + docs/x509/ocsp.rst | 32 ++++++++++++++++- src/cryptography/x509/ocsp.py | 44 ++++++++++++++++++++--- src/rust/src/x509/ocsp.rs | 21 +++++++++++ src/rust/src/x509/ocsp_req.rs | 39 ++++++++++++++++++-- tests/x509/test_ocsp.py | 67 ++++++++++++++++++++++++++++++++++- 7 files changed, 197 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 8dce8855f746..342c87ef66cc 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -38,6 +38,8 @@ Changelog * Significantly improved performance for :class:`~cryptography.hazmat.primitives.ciphers.aead.ChaCha20Poly1305` when repeatedly calling ``encrypt`` or ``decrypt`` with the same key. +* Added support for creating OCSP requests with precomputed hashes using + :meth:`~cryptography.x509.ocsp.OCSPRequestBuilder.add_certificate_by_hash`. .. _v38-0-2: diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 14f31e1b100d..56a9ac881211 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -96,6 +96,7 @@ plaintext Poly pre precompute +precomputed preprocessor preprocessors presentational diff --git a/docs/x509/ocsp.rst b/docs/x509/ocsp.rst index aee6fdd73268..603f9f6dd040 100644 --- a/docs/x509/ocsp.rst +++ b/docs/x509/ocsp.rst @@ -134,7 +134,8 @@ Creating Requests .. method:: add_certificate(cert, issuer, algorithm) Adds a request using a certificate, issuer certificate, and hash - algorithm. This can only be called once. + algorithm. You can call this method or ``add_certificate_by_hash`` + only once. :param cert: The :class:`~cryptography.x509.Certificate` whose validity is being checked. @@ -151,6 +152,35 @@ Creating Requests :class:`~cryptography.hazmat.primitives.hashes.SHA384`, and :class:`~cryptography.hazmat.primitives.hashes.SHA512` are allowed. + .. method:: add_certificate_by_hash(issuer_name_hash, issuer_key_hash, serial_number, algorithm) + + .. versionadded:: 39.0.0 + + Adds a request using the issuer's name hash, key hash, the certificate + serial number and hash algorithm. You can call this method or + ``add_certificate`` only once. + + :param issuer_name_hash: The hash of the issuer's DER encoded name using the + same hash algorithm as the one specified in the ``algorithm`` parameter. + :type issuer_name_hash: bytes + + :param issuer_key_hash: The hash of the issuer's public key bit string + DER encoding using the same hash algorithm as the one specified in + the ``algorithm`` parameter. + :type issuer_key_hash: bytes + + :param serial_number: The serial number of the certificate being checked. + :type serial_number: int + + :param algorithm: A + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` + instance. For OCSP only + :class:`~cryptography.hazmat.primitives.hashes.SHA1`, + :class:`~cryptography.hazmat.primitives.hashes.SHA224`, + :class:`~cryptography.hazmat.primitives.hashes.SHA256`, + :class:`~cryptography.hazmat.primitives.hashes.SHA384`, and + :class:`~cryptography.hazmat.primitives.hashes.SHA512` are allowed. + .. method:: add_extension(extval, critical) Adds an extension to the request. diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index c01e77a83c17..0e59fa4bc161 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -375,9 +375,13 @@ def __init__( x509.Certificate, x509.Certificate, hashes.HashAlgorithm ] ] = None, + request_hash: typing.Optional[ + typing.Tuple[bytes, bytes, int, hashes.HashAlgorithm] + ] = None, extensions: typing.List[x509.Extension[x509.ExtensionType]] = [], ) -> None: self._request = request + self._request_hash = request_hash self._extensions = extensions def add_certificate( @@ -386,7 +390,7 @@ def add_certificate( issuer: x509.Certificate, algorithm: hashes.HashAlgorithm, ) -> "OCSPRequestBuilder": - if self._request is not None: + if self._request is not None or self._request_hash is not None: raise ValueError("Only one certificate can be added to a request") _verify_algorithm(algorithm) @@ -395,7 +399,39 @@ def add_certificate( ): raise TypeError("cert and issuer must be a Certificate") - return OCSPRequestBuilder((cert, issuer, algorithm), self._extensions) + return OCSPRequestBuilder( + (cert, issuer, algorithm), self._request_hash, self._extensions + ) + + def add_certificate_by_hash( + self, + issuer_name_hash: bytes, + issuer_key_hash: bytes, + serial_number: int, + algorithm: hashes.HashAlgorithm, + ) -> "OCSPRequestBuilder": + if self._request is not None or self._request_hash is not None: + raise ValueError("Only one certificate can be added to a request") + + if not isinstance(serial_number, int): + raise TypeError("serial_number must be an integer") + + _verify_algorithm(algorithm) + utils._check_bytes("issuer_name_hash", issuer_name_hash) + utils._check_bytes("issuer_key_hash", issuer_key_hash) + if algorithm.digest_size != len( + issuer_name_hash + ) or algorithm.digest_size != len(issuer_key_hash): + raise ValueError( + "issuer_name_hash and issuer_key_hash must be the same length " + "as the digest size of the algorithm" + ) + + return OCSPRequestBuilder( + self._request, + (issuer_name_hash, issuer_key_hash, serial_number, algorithm), + self._extensions, + ) def add_extension( self, extval: x509.ExtensionType, critical: bool @@ -407,11 +443,11 @@ def add_extension( _reject_duplicate_extension(extension, self._extensions) return OCSPRequestBuilder( - self._request, self._extensions + [extension] + self._request, self._request_hash, self._extensions + [extension] ) def build(self) -> OCSPRequest: - if self._request is None: + if self._request is None and self._request_hash is None: raise ValueError("You must add a certificate before building") return ocsp.create_ocsp_request(self) diff --git a/src/rust/src/x509/ocsp.rs b/src/rust/src/x509/ocsp.rs index 67bdca0f480b..de5ace7d069e 100644 --- a/src/rust/src/x509/ocsp.rs +++ b/src/rust/src/x509/ocsp.rs @@ -70,6 +70,27 @@ impl CertID<'_> { serial_number: cert.raw.borrow_value_public().tbs_cert.serial, }) } + + pub(crate) fn new_from_hash<'p>( + py: pyo3::Python<'p>, + issuer_name_hash: &'p [u8], + issuer_key_hash: &'p [u8], + serial_number: asn1::BigInt<'p>, + hash_algorithm: &'p pyo3::PyAny, + ) -> PyAsn1Result> { + Ok(CertID { + hash_algorithm: x509::AlgorithmIdentifier { + oid: HASH_NAME_TO_OIDS[hash_algorithm + .getattr(crate::intern!(py, "name"))? + .extract::<&str>()?] + .clone(), + params: Some(*x509::sign::NULL_TLV), + }, + issuer_name_hash, + issuer_key_hash, + serial_number, + }) + } } pub(crate) fn hash_data<'p>( diff --git a/src/rust/src/x509/ocsp_req.rs b/src/rust/src/x509/ocsp_req.rs index 92fe96fa0276..0f7e8f86992e 100644 --- a/src/rust/src/x509/ocsp_req.rs +++ b/src/rust/src/x509/ocsp_req.rs @@ -2,7 +2,9 @@ // 2.0, and the BSD License. See the LICENSE file in the root of this repository // for complete details. -use crate::asn1::{big_byte_slice_to_py_int, PyAsn1Error, PyAsn1Result}; +use crate::asn1::{ + big_byte_slice_to_py_int, py_uint_to_big_endian_bytes, PyAsn1Error, PyAsn1Result, +}; use crate::x509; use crate::x509::{extensions, ocsp, oid}; use std::sync::Arc; @@ -180,11 +182,42 @@ struct Request<'a> { #[pyo3::prelude::pyfunction] fn create_ocsp_request(py: pyo3::Python<'_>, builder: &pyo3::PyAny) -> PyAsn1Result { + let builder_request = builder.getattr(crate::intern!(py, "_request"))?; + + // Declare outside the if-block so the lifetimes are right. let (py_cert, py_issuer, py_hash): ( pyo3::PyRef<'_, x509::Certificate>, pyo3::PyRef<'_, x509::Certificate>, &pyo3::PyAny, - ) = builder.getattr(crate::intern!(py, "_request"))?.extract()?; + ); + let req_cert = if !builder_request.is_none() { + let tuple = builder_request.extract::<( + pyo3::PyRef<'_, x509::Certificate>, + pyo3::PyRef<'_, x509::Certificate>, + &pyo3::PyAny, + )>()?; + py_cert = tuple.0; + py_issuer = tuple.1; + py_hash = tuple.2; + ocsp::CertID::new(py, &py_cert, &py_issuer, py_hash)? + } else { + let (issuer_name_hash, issuer_key_hash, py_serial, py_hash): ( + &[u8], + &[u8], + &pyo3::types::PyLong, + &pyo3::PyAny, + ) = builder + .getattr(crate::intern!(py, "_request_hash"))? + .extract()?; + let serial_number = asn1::BigInt::new(py_uint_to_big_endian_bytes(py, py_serial)?).unwrap(); + ocsp::CertID::new_from_hash( + py, + issuer_name_hash, + issuer_key_hash, + serial_number, + py_hash, + )? + }; let extensions = x509::common::encode_extensions( py, @@ -192,7 +225,7 @@ fn create_ocsp_request(py: pyo3::Python<'_>, builder: &pyo3::PyAny) -> PyAsn1Res extensions::encode_extension, )?; let reqs = [Request { - req_cert: ocsp::CertID::new(py, &py_cert, &py_issuer, py_hash)?, + req_cert, single_request_extensions: None, }]; let ocsp_req = RawOCSPRequest { diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 9b276783a5d2..9090e5205ab7 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -162,12 +162,55 @@ def test_invalid_serialize_encoding(self): class TestOCSPRequestBuilder: - def test_add_two_certs(self): + def test_add_cert_twice(self): cert, issuer = _cert_and_issuer() builder = ocsp.OCSPRequestBuilder() builder = builder.add_certificate(cert, issuer, hashes.SHA1()) + # Fails calling a second time with pytest.raises(ValueError): builder.add_certificate(cert, issuer, hashes.SHA1()) + # Fails calling a second time with add_certificate_by_hash + with pytest.raises(ValueError): + builder.add_certificate_by_hash( + b"0" * 20, b"0" * 20, 1, hashes.SHA1() + ) + + def test_add_cert_by_hash_twice(self): + cert, issuer = _cert_and_issuer() + builder = ocsp.OCSPRequestBuilder() + builder = builder.add_certificate_by_hash( + b"0" * 20, b"0" * 20, 1, hashes.SHA1() + ) + # Fails calling a second time + with pytest.raises(ValueError): + builder.add_certificate_by_hash( + b"0" * 20, b"0" * 20, 1, hashes.SHA1() + ) + # Fails calling a second time with add_certificate + with pytest.raises(ValueError): + builder.add_certificate(cert, issuer, hashes.SHA1()) + + def test_add_cert_by_hash_bad_hash(self): + builder = ocsp.OCSPRequestBuilder() + with pytest.raises(ValueError): + builder.add_certificate_by_hash( + b"0" * 20, b"0" * 20, 1, "notahash" # type:ignore[arg-type] + ) + with pytest.raises(ValueError): + builder.add_certificate_by_hash( + b"0" * 19, b"0" * 20, 1, hashes.SHA1() + ) + with pytest.raises(ValueError): + builder.add_certificate_by_hash( + b"0" * 20, b"0" * 21, 1, hashes.SHA1() + ) + with pytest.raises(TypeError): + builder.add_certificate_by_hash( + b"0" * 20, + b"0" * 20, + "notanint", # type:ignore[arg-type] + hashes.SHA1(), + ) def test_create_ocsp_request_no_req(self): builder = ocsp.OCSPRequestBuilder() @@ -251,6 +294,28 @@ def test_create_ocsp_request_with_extension(self, ext, critical): assert req.extensions[0].oid == ext.oid assert req.extensions[0].critical is critical + def test_add_cert_by_hash(self): + cert, issuer = _cert_and_issuer() + builder = ocsp.OCSPRequestBuilder() + h = hashes.Hash(hashes.SHA1()) + h.update(cert.issuer.public_bytes()) + issuer_name_hash = h.finalize() + # issuer_key_hash is a hash of the public key BitString DER, + # not the subjectPublicKeyInfo + issuer_key_hash = base64.b64decode(b"w5zz/NNGCDS7zkZ/oHxb8+IIy1k=") + builder = builder.add_certificate_by_hash( + issuer_name_hash, + issuer_key_hash, + cert.serial_number, + hashes.SHA1(), + ) + req = builder.build() + serialized = req.public_bytes(serialization.Encoding.DER) + assert serialized == base64.b64decode( + b"MEMwQTA/MD0wOzAJBgUrDgMCGgUABBRAC0Z68eay0wmDug1gfn5ZN0gkxAQUw5zz" + b"/NNGCDS7zkZ/oHxb8+IIy1kCAj8g" + ) + class TestOCSPResponseBuilder: def test_add_response_twice(self): From 11f20ef86fd7c497ac678cb4eba6b0e8df819ff4 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 20:28:25 -0400 Subject: [PATCH 109/298] Bump BoringSSL version to 58f728eaecf9d1152df4977e50f90375e05c486d (#7707) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0aca55ea5ac2..95dd1f82e3ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 13, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "9cd85d0b4c3ea8fc0e1a1883bab3a46ffaa18bd9"}} + # Latest commit on the master branch, as of Oct 14, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "58f728eaecf9d1152df4977e50f90375e05c486d"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 4000393947eaeb25d7e02c0e54e375b64ba1b7a6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 13 Oct 2022 20:48:30 -0400 Subject: [PATCH 110/298] revert 3.0.6 and 1.1.1r bumps since they were withdrawn (#7708) --- .github/workflows/ci.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 95dd1f82e3ef..1e968444aa97 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,16 +28,16 @@ jobs: PYTHON: - {VERSION: "3.10", TOXENV: "flake"} - {VERSION: "3.10", TOXENV: "rust"} - - {VERSION: "3.10", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.6"}} + - {VERSION: "3.10", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1r"}} - - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1r"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1r", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.6"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.6", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.6"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} + - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} + - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} From 25f7005f2698bac5c7a1374c0f54782884385a64 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 14 Oct 2022 20:33:50 -0400 Subject: [PATCH 111/298] Bump BoringSSL version to 14aa0de18f638a92be13597bc1b8a95ca8fcf8a4 (#7709) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e968444aa97..f0ee4b1377c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,8 +43,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 14, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "58f728eaecf9d1152df4977e50f90375e05c486d"}} + # Latest commit on the master branch, as of Oct 15, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "14aa0de18f638a92be13597bc1b8a95ca8fcf8a4"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From e50884d259e9612c3df8903764857de21e8308d9 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sun, 16 Oct 2022 01:16:13 +0200 Subject: [PATCH 112/298] Make sure that one of full_name, relative_name or crl_issuer is set in distribution points (#7710) --- src/cryptography/x509/extensions.py | 11 +++++------ tests/x509/test_x509_ext.py | 4 ++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index cc8f25ef4ae2..36be6f253bd9 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -589,6 +589,11 @@ def __init__( "You cannot provide both full_name and relative_name, at " "least one must be None." ) + if not full_name and not relative_name and not crl_issuer: + raise ValueError( + "Either full_name, relative_name or crl_issuer must be " + "provided." + ) if full_name is not None: full_name = list(full_name) @@ -625,12 +630,6 @@ def __init__( "DistributionPoint" ) - if reasons and not crl_issuer and not (full_name or relative_name): - raise ValueError( - "You must supply crl_issuer, full_name, or relative_name when " - "reasons is not None" - ) - self._full_name = full_name self._relative_name = relative_name self._reasons = reasons diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index fd09b091def0..7284a73beb6d 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -3968,6 +3968,10 @@ def test_distribution_point_full_and_relative_not_none(self): "data", "notname", None, None # type:ignore[arg-type] ) + def test_no_full_name_relative_name_or_crl_issuer(self): + with pytest.raises(ValueError): + x509.DistributionPoint(None, None, None, None) + def test_crl_issuer_not_general_names(self): with pytest.raises(TypeError): x509.DistributionPoint( From 825ac25221756b9082554aa404ba97a1019e4ae8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Oct 2022 00:12:06 +0000 Subject: [PATCH 113/298] Bump re-actors/alls-green from 1.2.1 to 1.2.2 (#7711) Bumps [re-actors/alls-green](https://github.com/re-actors/alls-green) from 1.2.1 to 1.2.2. - [Release notes](https://github.com/re-actors/alls-green/releases) - [Commits](https://github.com/re-actors/alls-green/compare/13b4244b312e8a314951e03958a2f91519a6a3c9...05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe) --- updated-dependencies: - dependency-name: re-actors/alls-green dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0ee4b1377c1..646c12370107 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -530,7 +530,7 @@ jobs: with: persist-credentials: false - name: Decide whether the needed jobs succeeded or failed - uses: re-actors/alls-green@13b4244b312e8a314951e03958a2f91519a6a3c9 + uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe with: jobs: ${{ toJSON(needs) }} - name: Setup python From bb9a0c94abfbc8fba6afb9afeb14754492340a84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Oct 2022 00:12:28 +0000 Subject: [PATCH 114/298] Bump cxx-build from 1.0.78 to 1.0.79 in /src/rust (#7713) Bumps [cxx-build](https://github.com/dtolnay/cxx) from 1.0.78 to 1.0.79. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.78...1.0.79) --- updated-dependencies: - dependency-name: cxx-build dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index ae443452cc8c..cd566110354d 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e580d70777c116df50c390d1211993f62d40302881e54d4b79727acb83d0199" +checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86" dependencies = [ "cc", "codespan-reporting", From 0ff49e67a439c432fd803f821daef0542a50d8ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Oct 2022 00:12:49 +0000 Subject: [PATCH 115/298] Bump cxx from 1.0.78 to 1.0.79 in /src/rust (#7712) Bumps [cxx](https://github.com/dtolnay/cxx) from 1.0.78 to 1.0.79. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.78...1.0.79) --- updated-dependencies: - dependency-name: cxx dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index cd566110354d..cb2e028d9d29 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19f39818dcfc97d45b03953c1292efc4e80954e1583c4aa770bac1383e2310a4" +checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8" dependencies = [ "cc", "cxxbridge-flags", @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56a46460b88d1cec95112c8c363f0e2c39afdb237f60583b0b36343bf627ea9c" +checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78" [[package]] name = "cxxbridge-macro" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "747b608fecf06b0d72d440f27acc99288207324b793be2c17991839f3d4995ea" +checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f" dependencies = [ "proc-macro2", "quote", From 92d512196878b5dba5d9156943142c38d44b0103 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 15 Oct 2022 20:43:55 -0400 Subject: [PATCH 116/298] Bump rust-toolchain github action (#7715) --- .github/workflows/ci.yml | 4 ++-- .github/workflows/wheel-builder.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 646c12370107..cde24df51b4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -226,7 +226,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 + - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 with: toolchain: ${{ matrix.RUST }} - uses: actions/checkout@v3.1.0 @@ -278,7 +278,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 + - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 with: toolchain: ${{ matrix.RUST }} components: llvm-tools-preview diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index d08df988bec8..accef0a0a980 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -150,7 +150,7 @@ jobs: ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-universal2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 + - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 with: toolchain: stable # Add the arm64 target in addition to the native arch (x86_64) @@ -217,7 +217,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: dtolnay/rust-toolchain@1ce4a7352a1efe5dede2e52c75512b34256e4f44 + - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 with: toolchain: stable target: ${{ matrix.WINDOWS.RUST_TRIPLE }} From dd1b6058644a87fa419e693950c559b05d3a1f63 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 16 Oct 2022 00:52:35 +0000 Subject: [PATCH 117/298] Bump proc-macro2 from 1.0.46 to 1.0.47 in /src/rust (#7714) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.46 to 1.0.47. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.46...1.0.47) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index cb2e028d9d29..8a4aa55f7550 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -396,9 +396,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94e2ef8dbfc347b10c094890f778ee2e36ca9bb4262e86dc99cd217e35f3470b" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] From 0b795fd3f0b8d2cf445cf27d22b55466d68f5cc7 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 17 Oct 2022 20:18:50 -0400 Subject: [PATCH 118/298] disable sparse registry since its not working (#7718) --- .github/workflows/ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cde24df51b4f..522a5fad050c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,9 +16,6 @@ concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} cancel-in-progress: true -env: - CARGO_UNSTABLE_SPARSE_REGISTRY: true - jobs: linux: runs-on: ubuntu-latest From a7c8e2a8ae27fe86c31c0794cb040608758ced29 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 00:40:23 +0000 Subject: [PATCH 119/298] Bump peter-evans/create-pull-request from 4.1.3 to 4.1.4 (#7716) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.1.3 to 4.1.4. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/671dc9c9e0c2d73f07fa45a3eb0220e1622f0c5f...ad43dccb4d726ca8514126628bec209b8354b6dd) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boringssl-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index f9a6fca673bf..30162b85ded0 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -37,7 +37,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha.outputs.BORING_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@671dc9c9e0c2d73f07fa45a3eb0220e1622f0c5f + uses: peter-evans/create-pull-request@ad43dccb4d726ca8514126628bec209b8354b6dd with: commit-message: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" title: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" From 5040dfa266181de5751d9f78877459ab7e05546f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 00:43:34 +0000 Subject: [PATCH 120/298] Bump iana-time-zone-haiku from 0.1.0 to 0.1.1 in /src/rust (#7717) Bumps [iana-time-zone-haiku](https://github.com/strawlab/iana-time-zone) from 0.1.0 to 0.1.1. - [Release notes](https://github.com/strawlab/iana-time-zone/releases) - [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md) - [Commits](https://github.com/strawlab/iana-time-zone/compare/0.1.0...0.1.1) --- updated-dependencies: - dependency-name: iana-time-zone-haiku dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 8a4aa55f7550..088a78872fc6 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fde6edd6cef363e9359ed3c98ba64590ba9eecba2293eb5a723ab32aee8926aa" +checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" dependencies = [ "cxx", "cxx-build", From ce681b4043a6d0412c2f9b1a63e45fae377607a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 18 Oct 2022 12:20:03 +0000 Subject: [PATCH 121/298] Bump peter-evans/create-pull-request from 4.1.4 to 4.2.0 (#7719) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.1.4 to 4.2.0. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/ad43dccb4d726ca8514126628bec209b8354b6dd...b4d51739f96fca8047ad065eccef63442d8e99f7) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boringssl-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index 30162b85ded0..693a4556e267 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -37,7 +37,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha.outputs.BORING_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@ad43dccb4d726ca8514126628bec209b8354b6dd + uses: peter-evans/create-pull-request@b4d51739f96fca8047ad065eccef63442d8e99f7 with: commit-message: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" title: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" From b70f16e9d8f15b05624fd1cfca29d44141f6aa9b Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 19 Oct 2022 00:31:41 +0000 Subject: [PATCH 122/298] Bump BoringSSL version to b819f7e9392d25db6705a6bd3c92be3bb91775e2 (#7720) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 522a5fad050c..0c110dd92be2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 15, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "14aa0de18f638a92be13597bc1b8a95ca8fcf8a4"}} + # Latest commit on the master branch, as of Oct 19, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "b819f7e9392d25db6705a6bd3c92be3bb91775e2"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 37b0e2769c4e32a97f19553c8b19f5bcb3e23601 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 21 Oct 2022 18:01:56 -0400 Subject: [PATCH 123/298] attempt to workaround downstream package testing situation (#7725) * attempt to workaround downstream package testing situation --- .github/workflows/ci.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0c110dd92be2..a8b9a96ea4ef 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -496,6 +496,23 @@ jobs: - run: pip install . env: CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} + # cryptography main has a version of "(X+1).0.0.dev1" where X is the + # most recently released major version. A package used by a downstream + # may depend on cryptography <=X. If you use entrypoints stuff, this can + # lead to runtime errors due to version incompatibilities. Rename the + # dist-info directory to pretend to be an older version to "solve" this. + - run: | + import json + import pkg_resources + import shutil + import urllib.request + + d = pkg_resources.get_distribution("cryptography") + with urllib.request.urlopen("https://pypi.org/pypi/cryptography/json") as r: + latest_version = json.load(r)["info"]["version"] + new_path = d.egg_info.replace(d.version, latest_version) + shutil.move(d.egg_info, new_path) + shell: python - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run docs-linkcheck: From 93a0a75e53c45fac3417d303a3fe01e8a3b77ec6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 21 Oct 2022 18:29:28 -0400 Subject: [PATCH 124/298] add FAQ on new wheel architectures (#7724) --- docs/faq.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index 640ec9e3aeb5..a520345696c3 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -185,6 +185,7 @@ For example, this is a PEM file for a RSA Public Key: :: What happened to the backend argument? -------------------------------------- + ``cryptography`` stopped requiring the use of ``backend`` arguments in version 3.1 and deprecated their use in version 36.0. If you are on an older version that requires these arguments please view the appropriate documentation @@ -194,6 +195,24 @@ Note that for forward compatibility ``backend`` is still silently accepted by functions that previously required it, but it is ignored and no longer documented. +Will you upload wheels for my non-x86 non-ARM64 CPU architecture? +----------------------------------------------------------------- + +Maybe! But there's some pre-requisites. For us to build wheels and upload them +to PyPI, we consider it necessary to run our tests for that architecture as a +part of our CI (i.e. for every commit). If we don't run the tests, it's hard +to have confidence that everything works -- particularly with cryptography, +which frequently employs per-architecture assembly code. + +For us to add something to CI we need a provider which offers builds on that +architecture, which integrate into our workflows, has sufficient capacity, and +performs well enough not to regress the contributor experience. We don't think +this is an insurmountable bar, but it's also not one that can be cleared +lightly. + +If you are interested in helping support a new CPU architecture, we encourage +you to reach out, discuss, and contribute that support. We will attempt to be +supportive, but we cannot commit to doing the work ourselves. .. _`NaCl`: https://nacl.cr.yp.to/ .. _`PyNaCl`: https://pynacl.readthedocs.io From 49835de59bec8d0c6f1516c77a43a04d2b9eee70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Oct 2022 22:29:49 +0000 Subject: [PATCH 125/298] Bump actions/download-artifact from 3.0.0 to 3.0.1 (#7726) Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v3.0.0...v3.0.1) --- updated-dependencies: - dependency-name: actions/download-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a8b9a96ea4ef..2095219bb6af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -556,7 +556,7 @@ jobs: if: ${{ always() }} - name: Download coverage data if: ${{ always() }} - uses: actions/download-artifact@v3.0.0 + uses: actions/download-artifact@v3.0.1 with: name: coverage-data - name: Combine coverage and fail if it's <100%. From 21c1a482db4b627ce917fd98a5be13967255c584 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Oct 2022 22:39:21 +0000 Subject: [PATCH 126/298] Bump syn from 1.0.102 to 1.0.103 in /src/rust (#7727) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.102 to 1.0.103. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.102...1.0.103) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 088a78872fc6..44e381061236 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -489,9 +489,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1" +checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" dependencies = [ "proc-macro2", "quote", From 61e08a23cf52be2960f8206ec586ca86baadf7c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 21 Oct 2022 22:45:36 +0000 Subject: [PATCH 127/298] Bump actions/upload-artifact from 3.1.0 to 3.1.1 (#7728) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3.1.0...v3.1.1) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/wheel-builder.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2095219bb6af..09e8bddface1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -598,14 +598,14 @@ jobs: run: python -m coverage html if: ${{ failure() && steps.combinecoverage.outcome == 'failure' }} - name: Upload HTML report. - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@v3.1.1 with: name: _html-report path: htmlcov if-no-files-found: ignore if: ${{ failure() && steps.combinecoverage.outcome == 'failure' }} - name: Upload rust HTML report. - uses: actions/upload-artifact@v3.1.0 + uses: actions/upload-artifact@v3.1.1 with: name: _html-rust-report path: rust-coverage diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index accef0a0a980..7b2046101f7e 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -82,7 +82,7 @@ jobs: .venv/bin/python -c "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" - run: mkdir cryptography-wheelhouse - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ - - uses: actions/upload-artifact@v3.1.0 + - uses: actions/upload-artifact@v3.1.1 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.MANYLINUX.NAME }}-${{ matrix.PYTHON.VERSION }}" path: cryptography-wheelhouse/ @@ -182,7 +182,7 @@ jobs: - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ - run: | echo "CRYPTOGRAPHY_WHEEL_NAME=$(basename $(ls cryptography-wheelhouse/cryptography*.whl))" >> $GITHUB_ENV - - uses: actions/upload-artifact@v3.1.0 + - uses: actions/upload-artifact@v3.1.1 with: name: "${{ env.CRYPTOGRAPHY_WHEEL_NAME }}" path: cryptography-wheelhouse/ @@ -245,7 +245,7 @@ jobs: - run: mkdir cryptography-wheelhouse - run: move wheelhouse\cryptography*.whl cryptography-wheelhouse\ - - uses: actions/upload-artifact@v3.1.0 + - uses: actions/upload-artifact@v3.1.1 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.VERSION }}-${{ matrix.PYTHON.ABI_VERSION}}" path: cryptography-wheelhouse\ From 9121f262dff5f15d154a0ed93780cbd07b996842 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 22 Oct 2022 17:25:13 -0400 Subject: [PATCH 128/298] Remove SHA1 signatures support from PKCS7 (#7734) --- CHANGELOG.rst | 4 ++-- src/cryptography/hazmat/primitives/serialization/pkcs7.py | 1 - tests/hazmat/primitives/test_pkcs7.py | 7 ------- tests/hazmat/primitives/utils.py | 5 ----- 4 files changed, 2 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 342c87ef66cc..bea3177011d4 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,8 +23,8 @@ Changelog :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point` should be used instead. * **BACKWARDS INCOMPATIBLE:** Support for using MD5 or SHA1 in - :class:`~cryptography.x509.CertificateBuilder` and - other X.509 builders has been removed. + :class:`~cryptography.x509.CertificateBuilder`, other X.509 builders, and + PKCS7 has been removed. * Added support for :ref:`disabling the legacy provider in OpenSSL 3.0.x`. * Added support for disabling RSA key validation checks when loading RSA diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index fb754dff3a0c..1d3c7b124c03 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -32,7 +32,6 @@ def serialize_certificates( _ALLOWED_PKCS7_HASH_TYPES = typing.Union[ - hashes.SHA1, hashes.SHA224, hashes.SHA256, hashes.SHA384, diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index d3edc4845b45..8c5c1e3cff7d 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -14,7 +14,6 @@ from cryptography.hazmat.primitives.asymmetric import ed25519, rsa from cryptography.hazmat.primitives.serialization import pkcs7 -from .utils import skip_signature_hash from ...utils import load_vectors_from_file, raises_unsupported_algorithm @@ -345,7 +344,6 @@ def test_sign_pem(self, backend): @pytest.mark.parametrize( ("hash_alg", "expected_value"), [ - (hashes.SHA1(), b"\x06\x05+\x0e\x03\x02\x1a"), (hashes.SHA256(), b"\x06\t`\x86H\x01e\x03\x04\x02\x01"), (hashes.SHA384(), b"\x06\t`\x86H\x01e\x03\x04\x02\x02"), (hashes.SHA512(), b"\x06\t`\x86H\x01e\x03\x04\x02\x03"), @@ -354,8 +352,6 @@ def test_sign_pem(self, backend): def test_sign_alternate_digests_der( self, hash_alg, expected_value, backend ): - skip_signature_hash(backend, hash_alg) - data = b"hello world" cert, key = _load_cert_key() builder = ( @@ -373,7 +369,6 @@ def test_sign_alternate_digests_der( @pytest.mark.parametrize( ("hash_alg", "expected_value"), [ - (hashes.SHA1(), b"sha1"), (hashes.SHA256(), b"sha-256"), (hashes.SHA384(), b"sha-384"), (hashes.SHA512(), b"sha-512"), @@ -382,8 +377,6 @@ def test_sign_alternate_digests_der( def test_sign_alternate_digests_detached( self, hash_alg, expected_value, backend ): - skip_signature_hash(backend, hash_alg) - data = b"hello world" cert, key = _load_cert_key() builder = ( diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 3684c38c39e1..c8021cc2faa3 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -572,8 +572,3 @@ def skip_fips_traditional_openssl(backend, fmt): pytest.skip( "Traditional OpenSSL key format is not supported in FIPS mode." ) - - -def skip_signature_hash(backend, hash_alg: hashes.HashAlgorithm): - if not backend.signature_hash_supported(hash_alg): - pytest.skip(f"{hash_alg} is not a supported signature hash algorithm.") From 2cb595f1a56686ef54356069a38da43ecfa86120 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 22 Oct 2022 17:25:28 -0400 Subject: [PATCH 129/298] expose two x509 submodules (#7732) refs #7729 --- src/rust/src/x509/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/src/x509/mod.rs b/src/rust/src/x509/mod.rs index ee6c8d74c712..8c7b39f4b369 100644 --- a/src/rust/src/x509/mod.rs +++ b/src/rust/src/x509/mod.rs @@ -7,10 +7,10 @@ pub(crate) mod common; pub(crate) mod crl; pub(crate) mod csr; pub(crate) mod extensions; -mod ocsp; +pub(crate) mod ocsp; pub(crate) mod ocsp_req; pub(crate) mod ocsp_resp; -mod oid; +pub(crate) mod oid; pub(crate) mod sct; pub(crate) mod sign; From a680959a8d0a338ffe3b052a9ff55a65ad7f4642 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 22 Oct 2022 17:25:56 -0400 Subject: [PATCH 130/298] expose time_from_chrono refs (#7731) refs #7729 --- src/rust/src/x509/certificate.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs index a70a9c78039a..e2879b9475ce 100644 --- a/src/rust/src/x509/certificate.rs +++ b/src/rust/src/x509/certificate.rs @@ -936,6 +936,10 @@ pub fn parse_cert_ext<'p>( pub(crate) fn time_from_py(py: pyo3::Python<'_>, val: &pyo3::PyAny) -> PyAsn1Result { let dt = x509::py_to_chrono(py, val)?; + time_from_chrono(dt) +} + +pub(crate) fn time_from_chrono(dt: chrono::DateTime) -> PyAsn1Result { if dt.year() >= 2050 { Ok(x509::Time::GeneralizedTime(asn1::GeneralizedTime::new(dt)?)) } else { From 7321dd92873e49bbd9297f20f834c106add15bbe Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 22 Oct 2022 17:26:23 -0400 Subject: [PATCH 131/298] Expose some CSR attributes details for other modules (#7730) refs #7729 --- src/rust/src/x509/csr.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs index 280176b95d61..7bc3dc98a222 100644 --- a/src/rust/src/x509/csr.rs +++ b/src/rust/src/x509/csr.rs @@ -22,17 +22,19 @@ struct CertificationRequestInfo<'a> { subject: x509::Name<'a>, spki: certificate::SubjectPublicKeyInfo<'a>, #[implicit(0, required)] - attributes: x509::Asn1ReadableOrWritable< - 'a, - asn1::SetOf<'a, Attribute<'a>>, - asn1::SetOfWriter<'a, Attribute<'a>, Vec>>, - >, + attributes: Attributes<'a>, } +pub(crate) type Attributes<'a> = x509::Asn1ReadableOrWritable< + 'a, + asn1::SetOf<'a, Attribute<'a>>, + asn1::SetOfWriter<'a, Attribute<'a>, Vec>>, +>; + #[derive(asn1::Asn1Read, asn1::Asn1Write)] -struct Attribute<'a> { - type_id: asn1::ObjectIdentifier, - values: x509::Asn1ReadableOrWritable< +pub(crate) struct Attribute<'a> { + pub(crate) type_id: asn1::ObjectIdentifier, + pub(crate) values: x509::Asn1ReadableOrWritable< 'a, asn1::SetOf<'a, asn1::Tlv<'a>>, asn1::SetOfWriter<'a, x509::common::RawTlv<'a>, [x509::common::RawTlv<'a>; 1]>, From 22fa3b5f9bbeeda4fa2a2fb2a0b52df6904fd782 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Oct 2022 23:39:34 +0000 Subject: [PATCH 132/298] Bump cxx-build from 1.0.79 to 1.0.80 in /src/rust (#7735) Bumps [cxx-build](https://github.com/dtolnay/cxx) from 1.0.79 to 1.0.80. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.79...1.0.80) --- updated-dependencies: - dependency-name: cxx-build dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 44e381061236..57f355e4195a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07d050484b55975889284352b0ffc2ecbda25c0c55978017c132b29ba0818a86" +checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" dependencies = [ "cc", "codespan-reporting", From a68dc7c6441ab8f770b942bde41af42bbc8173bf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 22 Oct 2022 23:44:25 +0000 Subject: [PATCH 133/298] Bump base64 from 0.13.0 to 0.13.1 in /src/rust (#7736) Bumps [base64](https://github.com/marshallpierce/rust-base64) from 0.13.0 to 0.13.1. - [Release notes](https://github.com/marshallpierce/rust-base64/releases) - [Changelog](https://github.com/marshallpierce/rust-base64/blob/master/RELEASE-NOTES.md) - [Commits](https://github.com/marshallpierce/rust-base64/compare/v0.13.0...v0.13.1) --- updated-dependencies: - dependency-name: base64 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 57f355e4195a..a5ca1a2cc086 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -52,9 +52,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "bitflags" From f57a2a3fa00b1f7a0c2d1b66cee9ac861ba08f34 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 23 Oct 2022 00:08:28 +0000 Subject: [PATCH 134/298] Bump cxx from 1.0.79 to 1.0.80 in /src/rust (#7737) Bumps [cxx](https://github.com/dtolnay/cxx) from 1.0.79 to 1.0.80. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.79...1.0.80) --- updated-dependencies: - dependency-name: cxx dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a5ca1a2cc086..de3297b14860 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f83d0ebf42c6eafb8d7c52f7e5f2d3003b89c7aa4fd2b79229209459a849af8" +checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" dependencies = [ "cc", "cxxbridge-flags", @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d2199b00553eda8012dfec8d3b1c75fce747cf27c169a270b3b99e3448ab78" +checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" [[package]] name = "cxxbridge-macro" -version = "1.0.79" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb67a6de1f602736dd7eaead0080cf3435df806c61b24b13328db128c58868f" +checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" dependencies = [ "proc-macro2", "quote", From ac64bfa2eabe704adf0ec500c842b4ed9d863fa6 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sun, 23 Oct 2022 00:34:40 +0000 Subject: [PATCH 135/298] Bump BoringSSL version to 671ccb1a98fae26bf9c115068b2993418cecc800 (#7738) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 09e8bddface1..f0d2373684a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 19, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "b819f7e9392d25db6705a6bd3c92be3bb91775e2"}} + # Latest commit on the master branch, as of Oct 23, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "671ccb1a98fae26bf9c115068b2993418cecc800"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From b1aba941583f8bf45c9f659d354e223081afbbb1 Mon Sep 17 00:00:00 2001 From: Peter Williams Date: Sun, 23 Oct 2022 21:24:05 +0000 Subject: [PATCH 136/298] In memleak test, track reallocs of startup pointers (#7379) (#7739) The conda-forge build of this package was encountering test failures because their Windows build configuration involves a situation where some of the tests cause a realloc of memory in the memleak test's `start_heap`. Here we allow such reallocs and do not count them as leaks if they do not add too much memory usage, where "too much" is currently defined as 1024 bytes. refs #7379 --- tests/hazmat/backends/test_openssl_memleak.py | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index 2605566bd555..b1df39e27938 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -27,6 +27,8 @@ def main(argv): from cryptography.hazmat.bindings._openssl import ffi, lib heap = {} + start_heap = {} + start_heap_realloc_delta = [0] # 1-item list so callbacks can mutate it BACKTRACE_ENABLED = False if BACKTRACE_ENABLED: @@ -70,6 +72,20 @@ def realloc(ptr, size, path, line): del heap[ptr] new_ptr = lib.Cryptography_realloc_wrapper(ptr, size, path, line) heap[new_ptr] = (size, path, line, backtrace()) + + # It is possible that something during the test will cause a + # realloc of memory allocated during the startup phase. (This + # was observed in conda-forge Windows builds of this package with + # provider operation_bits pointers in crypto/provider_core.c.) If + # we don't pay attention to that, the realloc'ed pointer will show + # up as a leak; but we also don't want to allow this kind of realloc + # to consume large amounts of additional memory. So we track the + # realloc and the change in memory consumption. + startup_info = start_heap.pop(ptr, None) + if startup_info is not None: + start_heap[new_ptr] = heap[new_ptr] + start_heap_realloc_delta[0] += size - startup_info[0] + return new_ptr @ffi.callback("void(void *, const char *, int)") @@ -87,7 +103,7 @@ def free(ptr, path, line): hashlib.sha256() - start_heap = set(heap) + start_heap.update(heap) try: func(*argv[1:]) @@ -113,10 +129,12 @@ def free(ptr, path, line): ) assert result == 1 - remaining = set(heap) - start_heap + remaining = set(heap) - set(start_heap) - if remaining: - sys.stdout.write(json.dumps(dict( + # The constant here is the number of additional bytes of memory + # consumption that are allowed in reallocs of start_heap memory. + if remaining or start_heap_realloc_delta[0] > 1024: + info = dict( (int(ffi.cast("size_t", ptr)), { "size": heap[ptr][0], "path": ffi.string(heap[ptr][1]).decode(), @@ -124,7 +142,9 @@ def free(ptr, path, line): "backtrace": symbolize_backtrace(heap[ptr][3]), }) for ptr in remaining - ))) + ) + info["start_heap_realloc_delta"] = start_heap_realloc_delta[0] + sys.stdout.write(json.dumps(info)) sys.stdout.flush() sys.exit(255) From 255a451c3f61d396e5ae53f1de88737cd1ad3e1e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 23 Oct 2022 17:41:33 -0400 Subject: [PATCH 137/298] remove memleak tests that no longer exercise openssl code (#7740) tests that _create_ x509 structures are left, since they at least exercise signing code --- tests/hazmat/backends/test_openssl_memleak.py | 46 ------------------- 1 file changed, 46 deletions(-) diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index b1df39e27938..6d27012f6362 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -269,52 +269,6 @@ def func(): @pytest.mark.skip_fips(reason="FIPS self-test sets allow_customize = 0") @skip_if_memtesting_not_supported() class TestOpenSSLMemoryLeaks: - @pytest.mark.parametrize( - "path", ["x509/PKITS_data/certs/ValidcRLIssuerTest28EE.crt"] - ) - def test_der_x509_certificate_extensions(self, path): - assert_no_memory_leaks( - textwrap.dedent( - """ - def func(path): - from cryptography import x509 - from cryptography.hazmat.backends.openssl import backend - - import cryptography_vectors - - with cryptography_vectors.open_vector_file(path, "rb") as f: - cert = x509.load_der_x509_certificate( - f.read(), backend - ) - - cert.extensions - """ - ), - [path], - ) - - @pytest.mark.parametrize("path", ["x509/cryptography.io.pem"]) - def test_pem_x509_certificate_extensions(self, path): - assert_no_memory_leaks( - textwrap.dedent( - """ - def func(path): - from cryptography import x509 - from cryptography.hazmat.backends.openssl import backend - - import cryptography_vectors - - with cryptography_vectors.open_vector_file(path, "rb") as f: - cert = x509.load_pem_x509_certificate( - f.read(), backend - ) - - cert.extensions - """ - ), - [path], - ) - def test_x509_csr_extensions(self): assert_no_memory_leaks( textwrap.dedent( From a8051e1639f283aa1865a37497185b1d61d959c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 24 Oct 2022 12:19:15 +0000 Subject: [PATCH 138/298] Bump libc from 0.2.135 to 0.2.136 in /src/rust (#7741) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.135 to 0.2.136. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.135...0.2.136) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index de3297b14860..4aeef93b1293 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.135" +version = "0.2.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c" +checksum = "55edcf6c0bb319052dea84732cf99db461780fd5e8d3eb46ab6ff312ab31f197" [[package]] name = "link-cplusplus" From 9cdca018c5aaf419edea1d2d22eed989bf1b75d5 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 26 Oct 2022 00:24:22 +0000 Subject: [PATCH 139/298] Bump BoringSSL version to 1ec335da79eaa8341308acd9dc804078b8593c84 (#7744) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f0d2373684a0..f07b8320daf9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11-dev", TOXENV: "py311"} - {VERSION: "3.10", TOXENV: "py310-randomorder"} - # Latest commit on the master branch, as of Oct 23, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "671ccb1a98fae26bf9c115068b2993418cecc800"}} + # Latest commit on the master branch, as of Oct 26, 2022. + - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "1ec335da79eaa8341308acd9dc804078b8593c84"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From da971616fcae7d5962d3fac236a5e7a7675db57b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 26 Oct 2022 01:42:24 -0400 Subject: [PATCH 140/298] Silence a new clippy warning that requires a high MSRV (#7742) * Silence a new clippy warning that requires a high MSRV * Update lib.rs * Update twisted.sh * Update twisted.sh --- src/rust/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs index df4cf92e058f..614680268816 100644 --- a/src/rust/src/lib.rs +++ b/src/rust/src/lib.rs @@ -5,8 +5,11 @@ #![deny(rust_2018_idioms)] // Temporarily allow `clippy::borrow_deref_ref` until we can upgrade to the // latest pyo3: https://github.com/PyO3/pyo3/pull/2503 +// +// `clippy::uninlined_format_args` is required until our MSRV is >=1.58.0 +// // `unknown_lints` is required until GHA upgrades their rustc. -#![allow(unknown_lints, clippy::borrow_deref_ref)] +#![allow(unknown_lints, clippy::borrow_deref_ref, clippy::uninlined_format_args)] mod asn1; mod intern; From 50fb4471737522f54f92fe53d23db25972d6ac29 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 26 Oct 2022 01:44:03 -0400 Subject: [PATCH 141/298] Update CI for py3.11 release (#7743) * Update CI for py3.11 release * Don't use a name that's an existing enum method --- .github/workflows/benchmark.yml | 2 +- .github/workflows/ci.yml | 37 ++++++++++++++++---------------- setup.cfg | 1 + tests/test_cryptography_utils.py | 8 +++---- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 9ea619b667aa..d2f48250525c 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -30,7 +30,7 @@ jobs: id: setup-python uses: actions/setup-python@v4.3.0 with: - python-version: "3.10" + python-version: "3.11" - name: Create virtualenv (main) run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f07b8320daf9..1da02c9435b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,25 +23,24 @@ jobs: fail-fast: false matrix: PYTHON: - - {VERSION: "3.10", TOXENV: "flake"} - - {VERSION: "3.10", TOXENV: "rust"} - - {VERSION: "3.10", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} + - {VERSION: "3.11", TOXENV: "flake"} + - {VERSION: "3.11", TOXENV: "rust"} + - {VERSION: "3.11", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - - {VERSION: "3.10", TOXENV: "py310-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - - {VERSION: "3.10", TOXENV: "py310", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - - {VERSION: "3.11-dev", TOXENV: "py311"} - - {VERSION: "3.10", TOXENV: "py310-randomorder"} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} + - {VERSION: "3.11", TOXENV: "py311-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} + - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} + - {VERSION: "3.11", TOXENV: "py311-randomorder"} # Latest commit on the master branch, as of Oct 26, 2022. - - {VERSION: "3.10", TOXENV: "py310", OPENSSL: {TYPE: "boringssl", VERSION: "1ec335da79eaa8341308acd9dc804078b8593c84"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "1ec335da79eaa8341308acd9dc804078b8593c84"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: @@ -188,7 +187,7 @@ jobs: fail-fast: false matrix: PYTHON: - - {VERSION: "3.9", TOXENV: "py39"} + - {VERSION: "3.11", TOXENV: "py311"} RUST: # Cover MSRV (and likely next MSRV). In-dev versions are below in # the linux-rust-coverage section. Once our MSRV is 1.60 we can @@ -246,7 +245,7 @@ jobs: strategy: matrix: PYTHON: - - {VERSION: "3.10", TOXENV: "py310"} + - {VERSION: "3.11", TOXENV: "py311"} RUST: - beta - nightly @@ -398,7 +397,7 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - {VERSION: "3.6", TOXENV: "py36-nocoverage", CL_FLAGS: ""} - - {VERSION: "3.10", TOXENV: "py310", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} + - {VERSION: "3.11", TOXENV: "py311", CL_FLAGS: "/D USE_OSRANDOM_RNG_FOR_TESTING"} JOB_NUMBER: [0, 1, 2] name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 15 @@ -527,7 +526,7 @@ jobs: - name: Setup python uses: actions/setup-python@v4.3.0 with: - python-version: 3.9 + python-version: 3.11 - run: python -m pip install -U tox - run: tox -r -- --color=yes env: diff --git a/setup.cfg b/setup.cfg index 724b86e657eb..d42e78930c19 100644 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ classifiers = Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.10 + Programming Language :: Python :: 3.11 Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: Implementation :: PyPy Topic :: Security :: Cryptography diff --git a/tests/test_cryptography_utils.py b/tests/test_cryptography_utils.py index 065da7b2d173..98fd6165afc1 100644 --- a/tests/test_cryptography_utils.py +++ b/tests/test_cryptography_utils.py @@ -56,9 +56,9 @@ def t(self): def test_enum(): class TestEnum(utils.Enum): - value = "something" + something = "something" assert issubclass(TestEnum, enum.Enum) - assert isinstance(TestEnum.value, enum.Enum) - assert repr(TestEnum.value) == "" - assert str(TestEnum.value) == "TestEnum.value" + assert isinstance(TestEnum.something, enum.Enum) + assert repr(TestEnum.something) == "" + assert str(TestEnum.something) == "TestEnum.something" From c02a8f05b1a97a750f2d1a4e49711ad55ed8493b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Oct 2022 12:32:29 +0000 Subject: [PATCH 142/298] Bump libc from 0.2.136 to 0.2.137 in /src/rust (#7746) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.136 to 0.2.137. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.136...0.2.137) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 4aeef93b1293..e180a6e5cf0a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.136" +version = "0.2.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55edcf6c0bb319052dea84732cf99db461780fd5e8d3eb46ab6ff312ab31f197" +checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" [[package]] name = "link-cplusplus" From 6bf69f488c723747f8c86d518b3435a7fa68910a Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 27 Oct 2022 00:25:59 +0000 Subject: [PATCH 143/298] Bump BoringSSL version to 1e0f0423dd5f1a279bd09bac62e989dd438edd7b (#7748) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1da02c9435b1..214b39a50b28 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,8 +39,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the master branch, as of Oct 26, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "1ec335da79eaa8341308acd9dc804078b8593c84"}} + # Latest commit on the master branch, as of Oct 27, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "1e0f0423dd5f1a279bd09bac62e989dd438edd7b"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 507a50ad99765ff26747c67a14dcad44f71b6890 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 28 Oct 2022 00:29:32 +0000 Subject: [PATCH 144/298] Bump BoringSSL version to 054a5d36bb4df09f4ecf62f6ddeb2439aa76d4ba (#7750) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 214b39a50b28..102382b2d2d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,8 +39,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the master branch, as of Oct 27, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "1e0f0423dd5f1a279bd09bac62e989dd438edd7b"}} + # Latest commit on the master branch, as of Oct 28, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "054a5d36bb4df09f4ecf62f6ddeb2439aa76d4ba"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1ce3e627d2338c57671ea2d44f87e681ca07b781 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 28 Oct 2022 02:16:23 -0400 Subject: [PATCH 145/298] Try raising OPENSSL_API_COMPAT to 1.1.0 (#6948) --- src/_cffi_src/build_openssl.py | 1 - src/_cffi_src/openssl/asn1.py | 1 - src/_cffi_src/openssl/conf.py | 18 ------------------ src/_cffi_src/openssl/cryptography.py | 7 +++---- src/_cffi_src/openssl/evp.py | 1 - src/_cffi_src/openssl/ssl.py | 26 -------------------------- 6 files changed, 3 insertions(+), 51 deletions(-) delete mode 100644 src/_cffi_src/openssl/conf.py diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 3ead86a89697..0b5115fd96e5 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -81,7 +81,6 @@ def _extra_compile_args(platform): "bignum", "bio", "cmac", - "conf", "crypto", "dh", "dsa", diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 0e392349ef57..98a933c195e8 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -42,7 +42,6 @@ void ASN1_OBJECT_free(ASN1_OBJECT *); /* ASN1 STRING */ -unsigned char *ASN1_STRING_data(ASN1_STRING *); const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *); int ASN1_STRING_set(ASN1_STRING *, const void *, int); diff --git a/src/_cffi_src/openssl/conf.py b/src/_cffi_src/openssl/conf.py deleted file mode 100644 index dd1e80a708ab..000000000000 --- a/src/_cffi_src/openssl/conf.py +++ /dev/null @@ -1,18 +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. - - -INCLUDES = """ -#include -""" - -TYPES = """ -""" - -FUNCTIONS = """ -void OPENSSL_config(const char *); -""" - -CUSTOMIZATIONS = """ -""" diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index c559401ddd05..6223ed5fbd79 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -4,10 +4,9 @@ INCLUDES = """ -/* define our OpenSSL API compatibility level to 1.0.1. Any symbols older than - that will raise an error during compilation. We can raise this number again - after we drop 1.0.2 support in the distant future. */ -#define OPENSSL_API_COMPAT 0x10001000L +/* define our OpenSSL API compatibility level to 1.1.0. Any symbols older than + that will raise an error during compilation. */ +#define OPENSSL_API_COMPAT 0x10100000L #if defined(_WIN32) #define WIN32_LEAN_AND_MEAN diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index fabc455c3ba8..ca25c35c862c 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -138,7 +138,6 @@ int EVP_PKEY_bits(const EVP_PKEY *); -void OpenSSL_add_all_algorithms(void); int EVP_PKEY_assign_RSA(EVP_PKEY *, RSA *); EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *); diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index ac396302d5ee..5a386773e7a1 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -324,8 +324,6 @@ const char *SSL_get_servername(const SSL *, const int); const char *SSL_CIPHER_get_version(const SSL_CIPHER *); -int SSL_library_init(void); -void SSL_load_error_strings(void); SSL_SESSION *SSL_get_session(const SSL *); const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *, unsigned int *); @@ -371,30 +369,6 @@ unsigned long SSL_CTX_set_tmp_ecdh(SSL_CTX *, EC_KEY *); unsigned long SSL_CTX_add_extra_chain_cert(SSL_CTX *, X509 *); -/*- These aren't macros these functions are all const X on openssl > 1.0.x -*/ - -/* methods */ - -const SSL_METHOD *TLSv1_1_method(void); -const SSL_METHOD *TLSv1_1_server_method(void); -const SSL_METHOD *TLSv1_1_client_method(void); - -const SSL_METHOD *TLSv1_2_method(void); -const SSL_METHOD *TLSv1_2_server_method(void); -const SSL_METHOD *TLSv1_2_client_method(void); - -const SSL_METHOD *SSLv3_method(void); -const SSL_METHOD *SSLv3_server_method(void); -const SSL_METHOD *SSLv3_client_method(void); - -const SSL_METHOD *TLSv1_method(void); -const SSL_METHOD *TLSv1_server_method(void); -const SSL_METHOD *TLSv1_client_method(void); - -const SSL_METHOD *DTLSv1_method(void); -const SSL_METHOD *DTLSv1_server_method(void); -const SSL_METHOD *DTLSv1_client_method(void); - const SSL_METHOD *DTLS_method(void); const SSL_METHOD *DTLS_server_method(void); const SSL_METHOD *DTLS_client_method(void); From 91ef23081994ff5430d6f96427040609216f268b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 28 Oct 2022 20:20:48 +0000 Subject: [PATCH 146/298] Bump iana-time-zone from 0.1.51 to 0.1.53 in /src/rust (#7753) Bumps [iana-time-zone](https://github.com/strawlab/iana-time-zone) from 0.1.51 to 0.1.53. - [Release notes](https://github.com/strawlab/iana-time-zone/releases) - [Changelog](https://github.com/strawlab/iana-time-zone/blob/main/CHANGELOG.md) - [Commits](https://github.com/strawlab/iana-time-zone/compare/v0.1.51...v0.1.53) --- updated-dependencies: - dependency-name: iana-time-zone dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index e180a6e5cf0a..fddabcea5702 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.51" +version = "0.1.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5a6ef98976b22b3b7f2f3a806f858cb862044cfa66805aa3ad84cb3d3b785ed" +checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" dependencies = [ "android_system_properties", "core-foundation-sys", From f6220bbb4f62ead22946cd321fe1fc39c3f80c06 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 29 Oct 2022 22:33:44 +0000 Subject: [PATCH 147/298] Bump cc from 1.0.73 to 1.0.74 in /src/rust (#7755) Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.73 to 1.0.74. - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.73...1.0.74) --- updated-dependencies: - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index fddabcea5702..f4c958e02318 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -70,9 +70,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574" [[package]] name = "cfg-if" From e10f991c849f57733074224b79d603ba98840c76 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 1 Nov 2022 15:39:42 -0400 Subject: [PATCH 148/298] libressl 3.6.1 (#7760) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 102382b2d2d4..5cb2157824d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -37,7 +37,7 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.0"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} # Latest commit on the master branch, as of Oct 28, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "054a5d36bb4df09f4ecf62f6ddeb2439aa76d4ba"}} From 382e759bcded5773330eeed748c86b213ec618c5 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 1 Nov 2022 15:40:25 -0400 Subject: [PATCH 149/298] bumps for new openssl release (#7759) --- .github/workflows/ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cb2157824d5..6538e5fea543 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,12 +29,12 @@ jobs: - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - - {VERSION: "3.11", TOXENV: "py311-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q"}} - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1q", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.5"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1s"}} + - {VERSION: "3.11", TOXENV: "py311-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1s"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1s", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct no-psk"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} + - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.7"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} From cf2ada625d1188d6cd46396f301b98095da577f7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 2 Nov 2022 05:19:52 +0800 Subject: [PATCH 150/298] forward port 38.0.3 changelog (#7762) --- CHANGELOG.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bea3177011d4..2b5e42bb1a8c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -41,6 +41,14 @@ Changelog * Added support for creating OCSP requests with precomputed hashes using :meth:`~cryptography.x509.ocsp.OCSPRequestBuilder.add_certificate_by_hash`. +.. _v38-0-3: + +38.0.3 - 2022-11-01 +~~~~~~~~~~~~~~~~~~~ + +* Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.0.7, + which resolves *CVE-2022-3602* and *CVE-2022-3786*. + .. _v38-0-2: 38.0.2 - 2022-10-11 (YANKED) From 4bb3263a96c3f703ad01f1856c26073f4363c720 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 2 Nov 2022 15:41:59 -0400 Subject: [PATCH 151/298] Revert workaround for yanked OpenSSL (#7765) Partial revert of 6578d86ec557e0b4af2ba9d0c0a821fe939044ee --- src/cryptography/hazmat/backends/openssl/backend.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 64be465d4c73..460ad00e48f4 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2204,11 +2204,8 @@ def load_pkcs12( res = self._lib.PKCS12_parse( p12, password_buf, evp_pkey_ptr, x509_ptr, sk_x509_ptr ) - # OpenSSL 3.0.6 leaves errors on the stack even in success, so - # we consume all errors unconditionally. - # https://github.com/openssl/openssl/issues/19389 - self._consume_errors() if res == 0: + self._consume_errors() raise ValueError("Invalid password or PKCS12 data") cert = None From d04cfe1df8654a2ac8668e8cddce2cecec92233e Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 3 Nov 2022 00:25:45 +0000 Subject: [PATCH 152/298] Bump BoringSSL version to 10458977f6a803859808365fad071731369f655a (#7768) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6538e5fea543..51d280134bb1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,8 +39,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the master branch, as of Oct 28, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "054a5d36bb4df09f4ecf62f6ddeb2439aa76d4ba"}} + # Latest commit on the master branch, as of Nov 03, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "10458977f6a803859808365fad071731369f655a"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 2a4cf7dc9bcf6924aa2a8ea8e7bc1e108d64872e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 3 Nov 2022 07:41:03 -0400 Subject: [PATCH 153/298] Build vectors and sdist artifacts in CI as well. (#7766) This is in preperation for ultimately uploading them from GHA once PyPI has OIDC integration. --- .github/workflows/wheel-builder.yml | 55 +++++++++++++++++++++++------ release.py | 21 +++-------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 7b2046101f7e..09b61221a8da 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -20,7 +20,34 @@ on: jobs: + sdist: + runs-on: ubuntu-latest + name: sdists + steps: + - uses: actions/checkout@v3.1.0 + with: + # The tag to build or the tag received by the tag event + ref: ${{ github.event.inputs.version || github.ref }} + persist-credentials: false + + - run: python -m venv .venv + - name: Install Python dependencies + run: .venv/bin/pip install -U pip wheel cffi setuptools-rust + - name: Make sdist (cryptography) + run: .venv/bin/python setup.py sdist + - name: Make sdist and wheel (vectors) + run: cd vectors/ && ../.venv/bin/python setup.py sdist bdist_wheel + - uses: actions/upload-artifact@v3.1.1 + with: + name: "cryptography-sdist" + path: dist/cryptography* + - uses: actions/upload-artifact@v3.1.1 + with: + name: "vectors-sdist-wheel" + path: vectors/dist/cryptography* + manylinux: + needs: [sdist] runs-on: ubuntu-latest container: ghcr.io/pyca/${{ matrix.MANYLINUX.CONTAINER }} strategy: @@ -46,16 +73,14 @@ jobs: MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/download-artifact@v3.0.1 with: - # The tag to build or the tag received by the tag event - ref: ${{ github.event.inputs.version || github.ref }} + name: cryptography-sdist + - run: /opt/python/${{ matrix.PYTHON.VERSION }}/bin/python -m venv .venv - name: Install Python dependencies run: .venv/bin/pip install -U pip wheel cffi setuptools-rust - - name: Make sdist - run: .venv/bin/python setup.py sdist - - run: tar zxvf dist/cryptography*.tar.gz && mkdir tmpwheelhouse + - run: tar zxvf cryptography*.tar.gz && rm cryptography*.tar.gz && mkdir tmpwheelhouse - name: Build the wheel run: | if [ -n "${{ matrix.PYTHON.ABI_VERSION }}" ]; then @@ -88,6 +113,7 @@ jobs: path: cryptography-wheelhouse/ macos: + needs: [sdist] runs-on: macos-12 strategy: fail-fast: false @@ -127,11 +153,16 @@ jobs: ARCHFLAGS: '-arch x86_64' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS ${{ matrix.PYTHON.ARCHFLAGS }}" steps: + # Needed for download_openssl.py - uses: actions/checkout@v3.1.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} persist-credentials: false + - uses: actions/download-artifact@v3.0.1 + with: + name: cryptography-sdist + - name: Setup python run: | curl "$PYTHON_DOWNLOAD_URL" -o python.pkg @@ -158,8 +189,7 @@ jobs: - run: ${{ matrix.PYTHON.BIN_PATH }} -m venv venv - run: venv/bin/pip install -U pip wheel cffi setuptools-rust - - run: venv/bin/python setup.py sdist - - run: tar zxvf dist/cryptography*.tar.gz && mkdir wheelhouse + - run: tar zxvf cryptography*.tar.gz && mkdir wheelhouse - name: Build the wheel run: | cd cryptography* @@ -188,6 +218,7 @@ jobs: path: cryptography-wheelhouse/ windows: + needs: [sdist] runs-on: windows-latest strategy: fail-fast: false @@ -207,11 +238,16 @@ jobs: PYTHON: {VERSION: "pypy-3.9"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: + # Needed for download_openssl.py - uses: actions/checkout@v3.1.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} persist-credentials: false + - uses: actions/download-artifact@v3.0.1 + with: + name: cryptography-sdist + - name: Setup python uses: actions/setup-python@v4.3.0 with: @@ -234,8 +270,7 @@ jobs: - run: python -m pip install -U pip wheel - run: python -m pip install cffi setuptools-rust - - run: python setup.py sdist - - run: tar zxvf dist/cryptography*.tar.gz && mkdir wheelhouse + - run: tar zxvf cryptography*.tar.gz && mkdir wheelhouse shell: bash - run: cd cryptography* && python setup.py bdist_wheel --py-limited-api=${{ matrix.PYTHON.ABI_VERSION }} && mv dist/cryptography*.whl ../wheelhouse - run: pip install -f wheelhouse --no-index cryptography diff --git a/release.py b/release.py index a2b196046aef..79ba0b7bc489 100644 --- a/release.py +++ b/release.py @@ -3,7 +3,6 @@ # for complete details. import getpass -import glob import io import os import subprocess @@ -64,7 +63,7 @@ def download_artifacts_github_actions(session, token, run_url): ) with zipfile.ZipFile(io.BytesIO(response.content)) as z: for name in z.namelist(): - if not name.endswith(".whl"): + if not name.endswith(".whl") and not name.endswith(".tar.gz"): continue p = z.open(name) out_path = os.path.join( @@ -78,7 +77,7 @@ def download_artifacts_github_actions(session, token, run_url): return paths -def fetch_github_actions_wheels(token, version): +def fetch_github_actions_artifacts(token, version): session = requests.Session() response = session.get( @@ -114,25 +113,13 @@ def release(version): run("git", "tag", "-s", version, "-m", "{0} release".format(version)) run("git", "push", "--tags") - # Generate and upload vector packages - run("python", "setup.py", "sdist", "bdist_wheel", cwd="vectors/") - packages = glob.glob( - "vectors/dist/cryptography_vectors-{0}*".format(version) - ) - run("twine", "upload", "-s", *packages) - - # Generate sdist for upload - run("python", "setup.py", "sdist") - sdist = glob.glob("dist/cryptography-{0}*".format(version)) - # Wait for Actions to complete and download the wheels - github_actions_wheel_paths = fetch_github_actions_wheels( + github_actions_artifact_paths = fetch_github_actions_artifacts( github_token, version ) # Upload wheels and sdist - run("twine", "upload", *github_actions_wheel_paths) - run("twine", "upload", "-s", *sdist) + run("twine", "upload", *github_actions_artifact_paths) if __name__ == "__main__": From 199100bda006ff7641bc17dce4351b1816e26929 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 3 Nov 2022 15:45:42 -0400 Subject: [PATCH 154/298] Make comment in ci.yml unambigious (#7769) In the future we may want to test against dev branches of other openssls --- .github/workflows/boringssl-version-bump.yml | 2 +- .github/workflows/ci.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml index 693a4556e267..f7c098b625cd 100644 --- a/.github/workflows/boringssl-version-bump.yml +++ b/.github/workflows/boringssl-version-bump.yml @@ -26,7 +26,7 @@ jobs: run: | set -xe CURRENT_DATE=$(date "+%b %d, %Y") - sed -E -i "s/Latest commit on the master branch.*/Latest commit on the master branch, as of ${CURRENT_DATE}./" .github/workflows/ci.yml + sed -E -i "s/Latest commit on the BoringSSL master branch.*/Latest commit on the BoringSSL master branch, as of ${CURRENT_DATE}./" .github/workflows/ci.yml sed -E -i "s/TYPE: \"boringssl\", VERSION: \"[0-9a-f]{40}\"/TYPE: \"boringssl\", VERSION: \"${{ steps.check-sha.outputs.BORING_SHA }}\"/" .github/workflows/ci.yml git status if: steps.check-sha.outputs.BORING_SHA diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 51d280134bb1..099603d069e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the master branch, as of Nov 03, 2022. + # Latest commit on the BoringSSL master branch, as of Nov 03, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "10458977f6a803859808365fad071731369f655a"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 From 89a32fc94f437f4e17ebe6ee2a5abd819ab7b10d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 3 Nov 2022 20:06:41 -0400 Subject: [PATCH 155/298] Test against OpenSSL master in CI (#7770) * Test against OpenSSL master in CI A future PR will incorporate automatic revision bumping into our CI * Sigh, increase this.... --- .github/workflows/build_openssl.sh | 12 +++++++++--- .github/workflows/ci.yml | 2 ++ tests/hazmat/backends/test_openssl_memleak.py | 2 +- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_openssl.sh b/.github/workflows/build_openssl.sh index d33d9e5e0cf6..d2358d1a7f1a 100755 --- a/.github/workflows/build_openssl.sh +++ b/.github/workflows/build_openssl.sh @@ -11,9 +11,15 @@ shlib_sed() { } if [[ "${TYPE}" == "openssl" ]]; then - curl -O "https://www.openssl.org/source/openssl-${VERSION}.tar.gz" - tar zxf "openssl-${VERSION}.tar.gz" - pushd "openssl-${VERSION}" + if [[ "${VERSION}" =~ ^[0-9a-f]{40}$ ]]; then + git clone https://github.com/openssl/openssl + pushd openssl + git checkout "${VERSION}" + else + curl -O "https://www.openssl.org/source/openssl-${VERSION}.tar.gz" + tar zxf "openssl-${VERSION}.tar.gz" + pushd "openssl-${VERSION}" + fi # CONFIG_FLAGS is a global coming from a previous step ./config ${CONFIG_FLAGS} -fPIC --prefix="${OSSL_PATH}" shlib_sed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 099603d069e2..f965937a89c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311-randomorder"} # Latest commit on the BoringSSL master branch, as of Nov 03, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "10458977f6a803859808365fad071731369f655a"}} + # Latest commit on the OpenSSL master branch, as of Nov 03, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "ce0a7cadadb973216399e70d3a69f352b0843deb"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index 6d27012f6362..e23054a6ecf4 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -133,7 +133,7 @@ def free(ptr, path, line): # The constant here is the number of additional bytes of memory # consumption that are allowed in reallocs of start_heap memory. - if remaining or start_heap_realloc_delta[0] > 1024: + if remaining or start_heap_realloc_delta[0] > 3072: info = dict( (int(ffi.cast("size_t", ptr)), { "size": heap[ptr][0], From ef39db3d77279b6bdf03b8b60989fbb0c18231fd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 4 Nov 2022 10:10:52 +0800 Subject: [PATCH 156/298] update openssl version for docs (#7773) --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f965937a89c3..c9f6d2c22239 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,7 @@ jobs: PYTHON: - {VERSION: "3.11", TOXENV: "flake"} - {VERSION: "3.11", TOXENV: "rust"} - - {VERSION: "3.11", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.5"}} + - {VERSION: "3.11", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7"}} - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} @@ -507,7 +507,7 @@ jobs: import pkg_resources import shutil import urllib.request - + d = pkg_resources.get_distribution("cryptography") with urllib.request.urlopen("https://pypi.org/pypi/cryptography/json") as r: latest_version = json.load(r)["info"]["version"] From 9925d2b57dd50c6b016db3db9c84d8c31a394327 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 6 Nov 2022 20:43:56 +0800 Subject: [PATCH 157/298] automatically bump openssl's master commit hash too (#7772) --- .../workflows/boring-open-version-bump.yml | 70 +++++++++++++++++++ .github/workflows/boringssl-version-bump.yml | 50 ------------- 2 files changed, 70 insertions(+), 50 deletions(-) create mode 100644 .github/workflows/boring-open-version-bump.yml delete mode 100644 .github/workflows/boringssl-version-bump.yml diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml new file mode 100644 index 000000000000..e4f5aa7c37a4 --- /dev/null +++ b/.github/workflows/boring-open-version-bump.yml @@ -0,0 +1,70 @@ +name: Bump BoringSSL and/or OpenSSL +permissions: + contents: read + +on: + workflow_dispatch: + schedule: + # Run daily + - cron: "0 0 * * *" + +jobs: + bump: + if: github.repository_owner == 'pyca' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.1.0 + - id: check-sha-boring + run: | + SHA=$(git ls-remote https://boringssl.googlesource.com/boringssl refs/heads/master | cut -f1) + LAST_COMMIT=$(grep boringssl .github/workflows/ci.yml | grep TYPE | grep -oE '[a-f0-9]{40}') + if ! grep -q "$SHA" .github/workflows/ci.yml; then + echo "COMMIT_SHA=${SHA}" >> $GITHUB_OUTPUT + echo "COMMIT_MSG<> $GITHUB_OUTPUT + echo -e "## BoringSSL\n[Commit: ${SHA}](https://boringssl.googlesource.com/boringssl/+/${SHA})\n\n[Diff](https://boringssl.googlesource.com/boringssl/+/${LAST_COMMIT}..${SHA}) between the last commit hash merged to this repository and the new commit." >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + fi + - id: check-sha-openssl + run: | + SHA=$(git ls-remote https://github.com/openssl/openssl refs/heads/master | cut -f1) + LAST_COMMIT=$(grep openssl .github/workflows/ci.yml | grep TYPE | grep -oE '[a-f0-9]{40}') + if ! grep -q "$SHA" .github/workflows/ci.yml; then + echo "COMMIT_SHA=${SHA}" >> $GITHUB_OUTPUT + echo "COMMIT_MSG<> $GITHUB_OUTPUT + echo -e "## OpenSSL\n[Commit: ${SHA}](https://github.com/openssl/openssl/commit/${SHA})\n\n[Diff](https://github.com/openssl/openssl/compare/${LAST_COMMIT}..${SHA}) between the last commit hash merged to this repository and the new commit." >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + fi + - name: Update boring + run: | + set -xe + CURRENT_DATE=$(date "+%b %d, %Y") + sed -E -i "s/Latest commit on the BoringSSL master branch.*/Latest commit on the BoringSSL master branch, as of ${CURRENT_DATE}./" .github/workflows/ci.yml + sed -E -i "s/TYPE: \"boringssl\", VERSION: \"[0-9a-f]{40}\"/TYPE: \"boringssl\", VERSION: \"${{ steps.check-sha-boring.outputs.COMMIT_SHA }}\"/" .github/workflows/ci.yml + git status + if: steps.check-sha-boring.outputs.COMMIT_SHA + - name: Update OpenSSL + run: | + set -xe + CURRENT_DATE=$(date "+%b %d, %Y") + sed -E -i "s/Latest commit on the OpenSSL master branch.*/Latest commit on the OpenSSL master branch, as of ${CURRENT_DATE}./" .github/workflows/ci.yml + sed -E -i "s/TYPE: \"openssl\", VERSION: \"[0-9a-f]{40}\"/TYPE: \"openssl\", VERSION: \"${{ steps.check-sha-openssl.outputs.COMMIT_SHA }}\"/" .github/workflows/ci.yml + git status + if: steps.check-sha-openssl.outputs.COMMIT_SHA + - uses: tibdex/github-app-token@f717b5ecd4534d3c4df4ce9b5c1c2214f0f7cd06 + id: generate-token + with: + app_id: ${{ secrets.BORINGBOT_APP_ID }} + private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} + if: steps.check-sha-boring.outputs.COMMIT_SHA || steps.check-sha-openssl.outputs.COMMIT_SHA + - name: Create Pull Request + uses: peter-evans/create-pull-request@b4d51739f96fca8047ad065eccef63442d8e99f7 + with: + commit-message: "Bump BoringSSL and/or OpenSSL in CI" + title: "Bump BoringSSL and/or OpenSSSL in CI" + author: "BoringSSL Bot " + body: | + ${{ steps.check-sha-boring.outputs.COMMIT_MSG }} + ${{ steps.check-sha-openssl.outputs.COMMIT_MSG }} + token: ${{ steps.generate-token.outputs.token }} + if: steps.check-sha-boring.outputs.COMMIT_SHA || steps.check-sha-openssl.outputs.COMMIT_SHA diff --git a/.github/workflows/boringssl-version-bump.yml b/.github/workflows/boringssl-version-bump.yml deleted file mode 100644 index f7c098b625cd..000000000000 --- a/.github/workflows/boringssl-version-bump.yml +++ /dev/null @@ -1,50 +0,0 @@ -name: Bump BoringSSL version -permissions: - contents: read - -on: - workflow_dispatch: - schedule: - # Run daily - - cron: "0 0 * * *" - -jobs: - bump: - if: github.repository_owner == 'pyca' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3.1.0 - - id: check-sha - run: | - SHA=$(git ls-remote https://boringssl.googlesource.com/boringssl refs/heads/master | cut -f1) - if ! grep -q "$SHA" .github/workflows/ci.yml; then - echo "BORING_SHA=${SHA}" >> $GITHUB_OUTPUT - fi - LAST_COMMIT=$(grep boringssl .github/workflows/ci.yml | grep TYPE | grep -oE '[a-z0-9]{40}') - echo "LAST_COMMIT=${LAST_COMMIT}" >> $GITHUB_OUTPUT - - name: Update boring - run: | - set -xe - CURRENT_DATE=$(date "+%b %d, %Y") - sed -E -i "s/Latest commit on the BoringSSL master branch.*/Latest commit on the BoringSSL master branch, as of ${CURRENT_DATE}./" .github/workflows/ci.yml - sed -E -i "s/TYPE: \"boringssl\", VERSION: \"[0-9a-f]{40}\"/TYPE: \"boringssl\", VERSION: \"${{ steps.check-sha.outputs.BORING_SHA }}\"/" .github/workflows/ci.yml - git status - if: steps.check-sha.outputs.BORING_SHA - - uses: tibdex/github-app-token@f717b5ecd4534d3c4df4ce9b5c1c2214f0f7cd06 - id: generate-token - with: - app_id: ${{ secrets.BORINGBOT_APP_ID }} - private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} - if: steps.check-sha.outputs.BORING_SHA - - name: Create Pull Request - uses: peter-evans/create-pull-request@b4d51739f96fca8047ad065eccef63442d8e99f7 - with: - commit-message: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" - title: "Bump BoringSSL version to ${{ steps.check-sha.outputs.BORING_SHA }}" - author: "BoringSSL Bot " - body: | - [Commit: ${{ steps.check-sha.outputs.BORING_SHA }}](https://boringssl.googlesource.com/boringssl/+/${{ steps.check-sha.outputs.BORING_SHA }}) - - [Diff](https://boringssl.googlesource.com/boringssl/+/${{ steps.check-sha.outputs.LAST_COMMIT }}..${{ steps.check-sha.outputs.BORING_SHA }}) between the last commit hash merged to this repository and the new commit. - token: ${{ steps.generate-token.outputs.token }} - if: steps.check-sha.outputs.BORING_SHA From 544ac2a69f390baf472d1d5901fbb3e4f3301f97 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sun, 6 Nov 2022 13:28:49 +0000 Subject: [PATCH 158/298] Bump BoringSSL and/or OpenSSL in CI (#7778) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c9f6d2c22239..292ae1949fe1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,10 +39,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the BoringSSL master branch, as of Nov 03, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "10458977f6a803859808365fad071731369f655a"}} - # Latest commit on the OpenSSL master branch, as of Nov 03, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "ce0a7cadadb973216399e70d3a69f352b0843deb"}} + # Latest commit on the BoringSSL master branch, as of Nov 06, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "da663b7ca86d70f7da979f9a48d2238ca5762bdd"}} + # Latest commit on the OpenSSL master branch, as of Nov 06, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f5a10d5cc19215ab22be55b4a2ee1e41bd38fb14"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From c8977080510626867edaf866d7a31f0e8ff52f71 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 6 Nov 2022 15:56:37 -0500 Subject: [PATCH 159/298] bump action version (#7779) --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index e4f5aa7c37a4..0d0fd7ca56e0 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -51,7 +51,7 @@ jobs: sed -E -i "s/TYPE: \"openssl\", VERSION: \"[0-9a-f]{40}\"/TYPE: \"openssl\", VERSION: \"${{ steps.check-sha-openssl.outputs.COMMIT_SHA }}\"/" .github/workflows/ci.yml git status if: steps.check-sha-openssl.outputs.COMMIT_SHA - - uses: tibdex/github-app-token@f717b5ecd4534d3c4df4ce9b5c1c2214f0f7cd06 + - uses: tibdex/github-app-token@021a2405c7f990db57f5eae5397423dcc554159c id: generate-token with: app_id: ${{ secrets.BORINGBOT_APP_ID }} From ae38e5f1e1d06613acc47a2f259a1419ff1b5316 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 6 Nov 2022 15:58:02 -0500 Subject: [PATCH 160/298] remove reference to raising NotImplementedError in update_into (#7781) this hasn't happened in a long time --- docs/hazmat/primitives/symmetric-encryption.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/hazmat/primitives/symmetric-encryption.rst b/docs/hazmat/primitives/symmetric-encryption.rst index 37c12f7c3546..2bf7a88cb0a4 100644 --- a/docs/hazmat/primitives/symmetric-encryption.rst +++ b/docs/hazmat/primitives/symmetric-encryption.rst @@ -620,8 +620,6 @@ Interfaces into. This buffer should be ``len(data) + n - 1`` bytes where ``n`` is the block size (in bytes) of the cipher and mode combination. :return int: Number of bytes written. - :raises NotImplementedError: This is raised if the version of ``cffi`` - used is too old (this can happen on older PyPy releases). :raises ValueError: This is raised if the supplied buffer is too small. .. doctest:: From 9a30cf5ad1acfe8e54d8efd3d0d3ea1d29ae64db Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 6 Nov 2022 15:58:59 -0500 Subject: [PATCH 161/298] Update minimum LibreSSL to 3.5 (#7780) This is the version of LibreSSL in OpenBSD 7.1, which is the oldest currently supported. --- .github/workflows/ci.yml | 1 - CHANGELOG.rst | 4 +- src/_cffi_src/openssl/cryptography.py | 5 - src/_cffi_src/openssl/dh.py | 114 +----------------- src/_cffi_src/openssl/evp.py | 11 -- src/_cffi_src/openssl/fips.py | 2 +- src/_cffi_src/openssl/ssl.py | 14 +-- .../hazmat/backends/openssl/backend.py | 6 +- .../hazmat/bindings/openssl/_conditional.py | 8 -- 9 files changed, 8 insertions(+), 157 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 292ae1949fe1..fa91fccd27a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,6 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.7"}} - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.4.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2b5e42bb1a8c..93236dbdc448 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,8 +10,8 @@ Changelog * **BACKWARDS INCOMPATIBLE:** Support for OpenSSL 1.1.0 has been removed. Users on older version of OpenSSL will need to upgrade. -* **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL < 3.4. The new - minimum LibreSSL version is 3.4.0. Going forward our policy is to support +* **BACKWARDS INCOMPATIBLE:** Dropped support for LibreSSL < 3.5. The new + minimum LibreSSL version is 3.5.0. Going forward our policy is to support versions of LibreSSL that are available in versions of OpenBSD that are still receiving security support. * **BACKWARDS INCOMPATIBLE:** Removed the ``encode_point`` and diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 6223ed5fbd79..f53ee72acb3c 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -40,13 +40,10 @@ #endif #if CRYPTOGRAPHY_IS_LIBRESSL -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 \ - (LIBRESSL_VERSION_NUMBER < 0x3050000f) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 \ (LIBRESSL_VERSION_NUMBER < 0x3060000f) #else -#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 (0) #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 (0) #endif @@ -81,8 +78,6 @@ static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111E; static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE; -static const int CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350; - static const int CRYPTOGRAPHY_IS_LIBRESSL; static const int CRYPTOGRAPHY_IS_BORINGSSL; """ diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py index cbf2e9a0a82d..44b3d817ae7e 100644 --- a/src/_cffi_src/openssl/dh.py +++ b/src/_cffi_src/openssl/dh.py @@ -26,7 +26,7 @@ void DH_get0_key(const DH *, const BIGNUM **, const BIGNUM **); int DH_set0_key(DH *, BIGNUM *, BIGNUM *); -int Cryptography_DH_check(const DH *, int *); +int DH_check(const DH *, int *); int DH_generate_parameters_ex(DH *, int, int, BN_GENCB *); DH *d2i_DHparams_bio(BIO *, DH **); int i2d_DHparams_bio(BIO *, DH *); @@ -35,118 +35,6 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 -#ifndef DH_CHECK_Q_NOT_PRIME -#define DH_CHECK_Q_NOT_PRIME 0x10 -#endif - -#ifndef DH_CHECK_INVALID_Q_VALUE -#define DH_CHECK_INVALID_Q_VALUE 0x20 -#endif - -#ifndef DH_CHECK_INVALID_J_VALUE -#define DH_CHECK_INVALID_J_VALUE 0x40 -#endif - -/* DH_check implementation taken from OpenSSL 1.1.0pre6 */ - -/*- - * Check that p is a safe prime and - * if g is 2, 3 or 5, check that it is a suitable generator - * where - * for 2, p mod 24 == 11 - * for 3, p mod 12 == 5 - * for 5, p mod 10 == 3 or 7 - * should hold. - */ - -int Cryptography_DH_check(const DH *dh, int *ret) -{ - int ok = 0, r; - BN_CTX *ctx = NULL; - BN_ULONG l; - BIGNUM *t1 = NULL, *t2 = NULL; - - *ret = 0; - ctx = BN_CTX_new(); - if (ctx == NULL) - goto err; - BN_CTX_start(ctx); - t1 = BN_CTX_get(ctx); - if (t1 == NULL) - goto err; - t2 = BN_CTX_get(ctx); - if (t2 == NULL) - goto err; - - if (dh->q) { - if (BN_cmp(dh->g, BN_value_one()) <= 0) - *ret |= DH_NOT_SUITABLE_GENERATOR; - else if (BN_cmp(dh->g, dh->p) >= 0) - *ret |= DH_NOT_SUITABLE_GENERATOR; - else { - /* Check g^q == 1 mod p */ - if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx)) - goto err; - if (!BN_is_one(t1)) - *ret |= DH_NOT_SUITABLE_GENERATOR; - } - r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL); - if (r < 0) - goto err; - if (!r) - *ret |= DH_CHECK_Q_NOT_PRIME; - /* Check p == 1 mod q i.e. q divides p - 1 */ - if (!BN_div(t1, t2, dh->p, dh->q, ctx)) - goto err; - if (!BN_is_one(t2)) - *ret |= DH_CHECK_INVALID_Q_VALUE; - if (dh->j && BN_cmp(dh->j, t1)) - *ret |= DH_CHECK_INVALID_J_VALUE; - - } else if (BN_is_word(dh->g, DH_GENERATOR_2)) { - l = BN_mod_word(dh->p, 24); - if (l == (BN_ULONG)-1) - goto err; - if (l != 11) - *ret |= DH_NOT_SUITABLE_GENERATOR; - } else if (BN_is_word(dh->g, DH_GENERATOR_5)) { - l = BN_mod_word(dh->p, 10); - if (l == (BN_ULONG)-1) - goto err; - if ((l != 3) && (l != 7)) - *ret |= DH_NOT_SUITABLE_GENERATOR; - } else - *ret |= DH_UNABLE_TO_CHECK_GENERATOR; - - r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL); - if (r < 0) - goto err; - if (!r) - *ret |= DH_CHECK_P_NOT_PRIME; - else if (!dh->q) { - if (!BN_rshift1(t1, dh->p)) - goto err; - r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL); - if (r < 0) - goto err; - if (!r) - *ret |= DH_CHECK_P_NOT_SAFE_PRIME; - } - ok = 1; - err: - if (ctx != NULL) { - BN_CTX_end(ctx); - BN_CTX_free(ctx); - } - return (ok); -} -#else -int Cryptography_DH_check(const DH *dh, int *ret) { - return DH_check(dh, ret); -} -#endif - #if !(defined(EVP_PKEY_DHX) && EVP_PKEY_DHX != -1) DH *(*d2i_DHxparams_bio)(BIO *bp, DH **x) = NULL; int (*i2d_DHxparams_bio)(BIO *bp, DH *x) = NULL; diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index ca25c35c862c..7a3ae2744f39 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -215,17 +215,6 @@ static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 1; #endif -/* These defines are needed for CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 */ -#if !defined(EVP_CTRL_AEAD_SET_IVLEN) -# define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN -#endif -#if !defined(EVP_CTRL_AEAD_GET_TAG) -# define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG -#endif -#if !defined(EVP_CTRL_AEAD_SET_TAG) -# define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG -#endif - /* This is tied to X25519 support so we reuse the Cryptography_HAS_X25519 conditional to remove it. OpenSSL 1.1.0 didn't have this define, but 1.1.1 will when it is released. We can remove this in the distant diff --git a/src/_cffi_src/openssl/fips.py b/src/_cffi_src/openssl/fips.py index dd81d06cf546..9fb1e7aed0bb 100644 --- a/src/_cffi_src/openssl/fips.py +++ b/src/_cffi_src/openssl/fips.py @@ -17,7 +17,7 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 || CRYPTOGRAPHY_OPENSSL_300_OR_GREATER +#if CRYPTOGRAPHY_OPENSSL_300_OR_GREATER static const long Cryptography_HAS_FIPS = 0; int (*FIPS_mode_set)(int) = NULL; int (*FIPS_mode)(void) = NULL; diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 5a386773e7a1..0a6a124e19fd 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -523,26 +523,14 @@ int (*SSL_CTX_set_client_cert_engine)(SSL_CTX *, ENGINE *) = NULL; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 || CRYPTOGRAPHY_IS_BORINGSSL +#if CRYPTOGRAPHY_IS_BORINGSSL static const long Cryptography_HAS_VERIFIED_CHAIN = 0; Cryptography_STACK_OF_X509 *(*SSL_get0_verified_chain)(const SSL *) = NULL; #else static const long Cryptography_HAS_VERIFIED_CHAIN = 1; #endif -#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_350 -static const long Cryptography_HAS_KEYLOG = 0; -void (*SSL_CTX_set_keylog_callback)(SSL_CTX *, - void (*) (const SSL *, const char *) - ) = NULL; -void (*(*SSL_CTX_get_keylog_callback)(SSL_CTX *))( - const SSL *, - const char * - ) = NULL; -#else static const long Cryptography_HAS_KEYLOG = 1; -#endif - static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1; #ifdef OPENSSL_NO_SSL3_METHOD diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 460ad00e48f4..793fa2f71b9f 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -221,7 +221,7 @@ def _is_fips_enabled(self) -> bool: self._ffi.NULL ) else: - mode = getattr(self._lib, "FIPS_mode", lambda: 0)() + mode = self._lib.FIPS_mode() if mode == 0: # OpenSSL without FIPS pushes an error on the error stack @@ -1793,7 +1793,7 @@ def load_dh_private_numbers( self.openssl_assert(res == 1) codes = self._ffi.new("int[]", 1) - res = self._lib.Cryptography_DH_check(dh_cdata, codes) + res = self._lib.DH_check(dh_cdata, codes) self.openssl_assert(res == 1) # DH_check will return DH_NOT_SUITABLE_GENERATOR if p % 24 does not @@ -1882,7 +1882,7 @@ def dh_parameters_supported( self.openssl_assert(res == 1) codes = self._ffi.new("int[]", 1) - res = self._lib.Cryptography_DH_check(dh_cdata, codes) + res = self._lib.DH_check(dh_cdata, codes) self.openssl_assert(res == 1) return codes[0] == 0 diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index d14e55c0d8ff..7215d39f0b59 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -164,13 +164,6 @@ def cryptography_has_tlsv13_functions() -> typing.List[str]: ] -def cryptography_has_keylog() -> typing.List[str]: - return [ - "SSL_CTX_set_keylog_callback", - "SSL_CTX_get_keylog_callback", - ] - - def cryptography_has_raw_key() -> typing.List[str]: return [ "EVP_PKEY_new_raw_private_key", @@ -330,7 +323,6 @@ def cryptography_has_get_extms_support() -> typing.List[str]: "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup, "Cryptography_HAS_TLSv1_3_FUNCTIONS": cryptography_has_tlsv13_functions, - "Cryptography_HAS_KEYLOG": cryptography_has_keylog, "Cryptography_HAS_RAW_KEY": cryptography_has_raw_key, "Cryptography_HAS_EVP_DIGESTFINAL_XOF": ( cryptography_has_evp_digestfinal_xof From 94e3c2d5bdb930bd43eab1fa9ee5adf22d11ba2f Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Mon, 7 Nov 2022 00:21:21 +0000 Subject: [PATCH 162/298] Bump BoringSSL and/or OpenSSL in CI (#7782) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa91fccd27a4..b0b61321bc62 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,8 +38,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the BoringSSL master branch, as of Nov 06, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "da663b7ca86d70f7da979f9a48d2238ca5762bdd"}} + # Latest commit on the BoringSSL master branch, as of Nov 07, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "38f621a3667afca1262ce3b9390ef5a23042ff19"}} # Latest commit on the OpenSSL master branch, as of Nov 06, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f5a10d5cc19215ab22be55b4a2ee1e41bd38fb14"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" From b6ccd534f832f7b97132df97b03ccb1430e196a9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 7 Nov 2022 19:39:09 -0500 Subject: [PATCH 163/298] update for new mypy (with more accurate typing) (#7785) --- src/cryptography/hazmat/primitives/serialization/ssh.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/cryptography/hazmat/primitives/serialization/ssh.py b/src/cryptography/hazmat/primitives/serialization/ssh.py index e06b8230d29e..7125badb403d 100644 --- a/src/cryptography/hazmat/primitives/serialization/ssh.py +++ b/src/cryptography/hazmat/primitives/serialization/ssh.py @@ -174,7 +174,9 @@ class _FragList: flist: typing.List[bytes] - def __init__(self, init: typing.List[bytes] = None) -> None: + def __init__( + self, init: typing.Optional[typing.List[bytes]] = None + ) -> None: self.flist = [] if init: self.flist.extend(init) From 65996c9cabdd73a3b3940291cd1c9bd271b41bb1 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 02:49:28 +0000 Subject: [PATCH 164/298] Bump BoringSSL and/or OpenSSL in CI (#7786) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0b61321bc62..aefddf176ddf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - # Latest commit on the BoringSSL master branch, as of Nov 07, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "38f621a3667afca1262ce3b9390ef5a23042ff19"}} - # Latest commit on the OpenSSL master branch, as of Nov 06, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f5a10d5cc19215ab22be55b4a2ee1e41bd38fb14"}} + # Latest commit on the BoringSSL master branch, as of Nov 08, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "b2536a2c6234496ef609e7c909936bbf828dac6d"}} + # Latest commit on the OpenSSL master branch, as of Nov 08, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "91b7520e2385a513ad879dfa8fe8e45466315a27"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 8db4bd8127ddf4ba66ad331ca6079ab249701668 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 12:18:33 +0000 Subject: [PATCH 165/298] Bump cxx from 1.0.80 to 1.0.81 in /src/rust (#7787) Bumps [cxx](https://github.com/dtolnay/cxx) from 1.0.80 to 1.0.81. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.80...1.0.81) --- updated-dependencies: - dependency-name: cxx dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index f4c958e02318..48553be44ce7 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b7d4e43b25d3c994662706a1d4fcfc32aaa6afd287502c111b237093bb23f3a" +checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888" dependencies = [ "cc", "cxxbridge-flags", @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e72537424b474af1460806647c41d4b6d35d09ef7fe031c5c2fa5766047cc56a" +checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f" [[package]] name = "cxxbridge-macro" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "309e4fb93eed90e1e14bea0da16b209f81813ba9fc7830c20ed151dd7bc0a4d7" +checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" dependencies = [ "proc-macro2", "quote", From 3aef9db91a5978f6af5e8be7f69a018be0367e3b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Nov 2022 12:38:06 +0000 Subject: [PATCH 166/298] Bump cxx-build from 1.0.80 to 1.0.81 in /src/rust (#7788) Bumps [cxx-build](https://github.com/dtolnay/cxx) from 1.0.80 to 1.0.81. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.80...1.0.81) --- updated-dependencies: - dependency-name: cxx-build dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 48553be44ce7..a94d983fc2f9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f8829ddc213e2c1368e51a2564c552b65a8cb6a28f31e576270ac81d5e5827" +checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3" dependencies = [ "cc", "codespan-reporting", From 03fd121defdcb22605899f9f335129ed8551e569 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 8 Nov 2022 15:31:33 -0500 Subject: [PATCH 167/298] use triple dots in github comparison (#7789) --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index 0d0fd7ca56e0..78c902fa3b9c 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -32,7 +32,7 @@ jobs: if ! grep -q "$SHA" .github/workflows/ci.yml; then echo "COMMIT_SHA=${SHA}" >> $GITHUB_OUTPUT echo "COMMIT_MSG<> $GITHUB_OUTPUT - echo -e "## OpenSSL\n[Commit: ${SHA}](https://github.com/openssl/openssl/commit/${SHA})\n\n[Diff](https://github.com/openssl/openssl/compare/${LAST_COMMIT}..${SHA}) between the last commit hash merged to this repository and the new commit." >> $GITHUB_OUTPUT + echo -e "## OpenSSL\n[Commit: ${SHA}](https://github.com/openssl/openssl/commit/${SHA})\n\n[Diff](https://github.com/openssl/openssl/compare/${LAST_COMMIT}...${SHA}) between the last commit hash merged to this repository and the new commit." >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT fi - name: Update boring From 57577b50c2888c4e879f36ed3d61ce95b53a845d Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 00:23:17 +0000 Subject: [PATCH 168/298] Bump BoringSSL and/or OpenSSL in CI (#7790) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aefddf176ddf..f8eea062e8bd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311-randomorder"} # Latest commit on the BoringSSL master branch, as of Nov 08, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "b2536a2c6234496ef609e7c909936bbf828dac6d"}} - # Latest commit on the OpenSSL master branch, as of Nov 08, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "91b7520e2385a513ad879dfa8fe8e45466315a27"}} + # Latest commit on the OpenSSL master branch, as of Nov 09, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "ce74e3fb50e1756b14e394acf9dff7362099bb66"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 923f6618a311c4f83a5a9621cd56f993de3f629e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Nov 2022 12:34:06 +0000 Subject: [PATCH 169/298] Bump cc from 1.0.74 to 1.0.76 in /src/rust (#7791) Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.74 to 1.0.76. - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.74...1.0.76) --- updated-dependencies: - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index a94d983fc2f9..ee0432cc343f 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -70,9 +70,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "cc" -version = "1.0.74" +version = "1.0.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574" +checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" [[package]] name = "cfg-if" From 8d70560ee89c7eadb0fcb2894fa4d4ab715e15fe Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Nov 2022 15:25:48 -0500 Subject: [PATCH 170/298] add python 3.12-dev to CI (#7792) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f8eea062e8bd..a61209af7568 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,6 +38,7 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} + - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 08, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "b2536a2c6234496ef609e7c909936bbf828dac6d"}} # Latest commit on the OpenSSL master branch, as of Nov 09, 2022. From 9b788ec242ba9f13ecf19896f8ee7442094ddda3 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 00:21:35 +0000 Subject: [PATCH 171/298] Bump BoringSSL and/or OpenSSL in CI (#7793) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a61209af7568..b4f3f2347459 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,8 +41,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 08, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "b2536a2c6234496ef609e7c909936bbf828dac6d"}} - # Latest commit on the OpenSSL master branch, as of Nov 09, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "ce74e3fb50e1756b14e394acf9dff7362099bb66"}} + # Latest commit on the OpenSSL master branch, as of Nov 10, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "2a5c0d93cfe65b5fbb9bd91ec62371256eb26e12"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 883a13f81fd220146ed543cd18ed753523539c33 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 9 Nov 2022 22:50:20 -0500 Subject: [PATCH 172/298] Stop testing and producing wheels for PyPy 3.7 (#7795) --- .github/workflows/ci.yml | 1 - .github/workflows/wheel-builder.yml | 3 --- 2 files changed, 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4f3f2347459..96f0e9393851 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,6 @@ jobs: - {VERSION: "3.11", TOXENV: "flake"} - {VERSION: "3.11", TOXENV: "rust"} - {VERSION: "3.11", TOXENV: "docs", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7"}} - - {VERSION: "pypy-3.7", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.8", TOXENV: "pypy3-nocoverage"} - {VERSION: "pypy-3.9", TOXENV: "pypy3-nocoverage"} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1s"}} diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 09b61221a8da..5ec2997d869b 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -55,7 +55,6 @@ jobs: matrix: PYTHON: - { VERSION: "cp36-cp36m", ABI_VERSION: 'cp36' } - - { VERSION: "pp37-pypy37_pp73" } - { VERSION: "pp38-pypy38_pp73" } - { VERSION: "pp39-pypy39_pp73" } MANYLINUX: @@ -65,8 +64,6 @@ jobs: - { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} exclude: # There are no readily available musllinux PyPy distributions - - PYTHON: { VERSION: "pp37-pypy37_pp73" } - MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64" } - PYTHON: { VERSION: "pp38-pypy38_pp73" } MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} - PYTHON: { VERSION: "pp39-pypy39_pp73" } From 039ef53141d97f65d2d43e52695c6774ac349813 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 10 Nov 2022 16:22:48 -0500 Subject: [PATCH 173/298] Add issuing a GHSA to our release process for OpenSSL releases (#7776) --- .github/ISSUE_TEMPLATE/openssl-release.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/openssl-release.md b/.github/ISSUE_TEMPLATE/openssl-release.md index 482f6945f6a8..110d06d09c52 100644 --- a/.github/ISSUE_TEMPLATE/openssl-release.md +++ b/.github/ISSUE_TEMPLATE/openssl-release.md @@ -4,5 +4,6 @@ - [ ] Wait for the Github Actions job to complete - [ ] Changelog entry - [ ] Release +- [ ] File Github Security Advisory indicating which releases are impacted (if OpenSSL release is fixing a vulnerability) - [ ] Send announcement to mailing lists - [ ] Forward port changelog entry (if releasing from release branch) From 15ec31738198719bb2cb0c75743d094545973056 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 11 Nov 2022 00:20:59 +0000 Subject: [PATCH 174/298] Bump BoringSSL and/or OpenSSL in CI (#7796) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 96f0e9393851..7029535fa115 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 08, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "b2536a2c6234496ef609e7c909936bbf828dac6d"}} - # Latest commit on the OpenSSL master branch, as of Nov 10, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "2a5c0d93cfe65b5fbb9bd91ec62371256eb26e12"}} + # Latest commit on the OpenSSL master branch, as of Nov 11, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "8aa82b337081b7a22c35dddad8d62fb1ca9ea884"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 8f231a84dc9729a4e73a181bd4e695449fda0e90 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 12 Nov 2022 00:23:09 +0000 Subject: [PATCH 175/298] Bump BoringSSL and/or OpenSSL in CI (#7798) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7029535fa115..835259701b5e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 08, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "b2536a2c6234496ef609e7c909936bbf828dac6d"}} - # Latest commit on the OpenSSL master branch, as of Nov 11, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "8aa82b337081b7a22c35dddad8d62fb1ca9ea884"}} + # Latest commit on the BoringSSL master branch, as of Nov 12, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "0faffc7a30eeb195248ea43056f4848e2a9b1c6d"}} + # Latest commit on the OpenSSL master branch, as of Nov 12, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "a0783b83a3bd05a07ea64567995c7642621b4aa6"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 2c3bcf1de8a82dbdb6c47c46af7bcb9aea236ccb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Nov 2022 00:50:01 +0000 Subject: [PATCH 176/298] Bump asn1_derive from 0.12.2 to 0.12.3 in /src/rust (#7800) Bumps [asn1_derive](https://github.com/alex/rust-asn1) from 0.12.2 to 0.12.3. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.12.2...0.12.3) --- updated-dependencies: - dependency-name: asn1_derive dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index ee0432cc343f..1ff927a98854 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d48d1854a01241e8d22f8f5ae4e2dc332f66c5946e1772f5576886d83e18e1b7" +checksum = "d9a08da126b90ce7a577f8e6986513dea0243c114d7d5d88abece6168b0823db" dependencies = [ "proc-macro2", "quote", From 2afee12e3064de82e0c450661f466db72a2eaeec Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Nov 2022 00:54:37 +0000 Subject: [PATCH 177/298] Bump dtolnay/rust-toolchain (#7799) Bumps [dtolnay/rust-toolchain](https://github.com/dtolnay/rust-toolchain) from ba37adf8f94a7d9affce79bd3baff1b9e3189c33 to 55c7845fad90d0ae8b2e83715cb900e5e861e8cb. - [Release notes](https://github.com/dtolnay/rust-toolchain/releases) - [Commits](https://github.com/dtolnay/rust-toolchain/compare/ba37adf8f94a7d9affce79bd3baff1b9e3189c33...55c7845fad90d0ae8b2e83715cb900e5e861e8cb) --- updated-dependencies: - dependency-name: dtolnay/rust-toolchain dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/wheel-builder.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 835259701b5e..e9cfedb22256 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -223,7 +223,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 + - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb with: toolchain: ${{ matrix.RUST }} - uses: actions/checkout@v3.1.0 @@ -275,7 +275,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 + - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb with: toolchain: ${{ matrix.RUST }} components: llvm-tools-preview diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 5ec2997d869b..e3373b2bcd76 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -178,7 +178,7 @@ jobs: ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-universal2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 + - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb with: toolchain: stable # Add the arm64 target in addition to the native arch (x86_64) @@ -250,7 +250,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: dtolnay/rust-toolchain@ba37adf8f94a7d9affce79bd3baff1b9e3189c33 + - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb with: toolchain: stable target: ${{ matrix.WINDOWS.RUST_TRIPLE }} From 6b9f2d5b49ea692e2e54b98bbf2c8a47904d9bdb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Nov 2022 01:16:47 +0000 Subject: [PATCH 178/298] Bump asn1 from 0.12.2 to 0.12.3 in /src/rust (#7801) Bumps [asn1](https://github.com/alex/rust-asn1) from 0.12.2 to 0.12.3. - [Release notes](https://github.com/alex/rust-asn1/releases) - [Commits](https://github.com/alex/rust-asn1/compare/0.12.2...0.12.3) --- updated-dependencies: - dependency-name: asn1 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- src/rust/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 1ff927a98854..eebaf3b6bb9e 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "asn1" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22c27c85cd71c1bf4373c7c1aa752b73d2df799277c0930af16fffbf3444f210" +checksum = "a53789014a5231ee21e6af6d89d42680d73db33ad2ec83ee6fad801249432bad" dependencies = [ "asn1_derive", "chrono", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 49e70a30f7ee..82573dd9f142 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] once_cell = "1" pyo3 = { version = "0.15.2" } -asn1 = { version = "0.12.2", default-features = false, features = ["derive"] } +asn1 = { version = "0.12.3", default-features = false, features = ["derive"] } pem = "1.1" chrono = { version = "0.4.22", default-features = false, features = ["alloc", "clock"] } ouroboros = "0.15" From 06db9e3913a393a9fe7289d087d7ef14f5b3f5f1 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 11 Nov 2022 20:36:26 -0500 Subject: [PATCH 179/298] Use OctetStringEncoded in OCSP Response implementation (#7802) --- src/rust/src/x509/ocsp_resp.rs | 415 ++++++++++++++++----------------- 1 file changed, 207 insertions(+), 208 deletions(-) diff --git a/src/rust/src/x509/ocsp_resp.rs b/src/rust/src/x509/ocsp_resp.rs index 22d2940650f1..ae2488ae7af2 100644 --- a/src/rust/src/x509/ocsp_resp.rs +++ b/src/rust/src/x509/ocsp_resp.rs @@ -12,35 +12,35 @@ const BASIC_RESPONSE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 3, 6, 1, 5, 5, #[pyo3::prelude::pyfunction] fn load_der_ocsp_response(_py: pyo3::Python<'_>, data: &[u8]) -> Result { - let raw = OwnedRawOCSPResponse::try_new( - Arc::from(data), - |data| Ok(asn1::parse_single(data)?), - |_data, response| match response.response_status.value() { - SUCCESSFUL_RESPONSE => match response.response_bytes { - Some(ref bytes) => { - if bytes.response_type == BASIC_RESPONSE_OID { - Ok(asn1::parse_single(bytes.response)?) - } else { - Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( - "Successful OCSP response does not contain a BasicResponse", - ))) - } + let raw = OwnedRawOCSPResponse::try_new(Arc::from(data), |data| asn1::parse_single(data))?; + + let response = raw.borrow_value(); + match response.response_status.value() { + SUCCESSFUL_RESPONSE => match response.response_bytes { + Some(ref bytes) => { + if bytes.response_type != BASIC_RESPONSE_OID { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "Successful OCSP response does not contain a BasicResponse", + ))); } - None => Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + } + None => { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( "Successful OCSP response does not contain a BasicResponse", - ))), - }, - MALFORMED_REQUEST_RESPOSNE - | INTERNAL_ERROR_RESPONSE - | TRY_LATER_RESPONSE - | SIG_REQUIRED_RESPONSE - | UNAUTHORIZED_RESPONSE => Ok(None), - _ => Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( - "OCSP response has an unknown status code", - ))), + ))) + } }, - )?; - + MALFORMED_REQUEST_RESPOSNE + | INTERNAL_ERROR_RESPONSE + | TRY_LATER_RESPONSE + | SIG_REQUIRED_RESPONSE + | UNAUTHORIZED_RESPONSE => {} + _ => { + return Err(PyAsn1Error::from(pyo3::exceptions::PyValueError::new_err( + "OCSP response has an unknown status code", + ))) + } + }; Ok(OCSPResponse { raw: Arc::new(raw), cached_extensions: None, @@ -54,10 +54,6 @@ struct OwnedRawOCSPResponse { #[borrows(data)] #[covariant] value: RawOCSPResponse<'this>, - - #[borrows(data, value)] - #[covariant] - basic_response: Option>, } #[pyo3::prelude::pyclass] @@ -70,8 +66,8 @@ struct OCSPResponse { impl OCSPResponse { fn requires_successful_response(&self) -> pyo3::PyResult<&BasicOCSPResponse<'_>> { - match self.raw.borrow_basic_response() { - Some(b) => Ok(b), + match self.raw.borrow_value().response_bytes.as_ref() { + Some(b) => Ok(b.response.get()), None => Err(pyo3::exceptions::PyValueError::new_err( "OCSP response status is not successful so the property has no value", )), @@ -95,9 +91,12 @@ impl OCSPResponse { Ok(OCSPResponseIterator { contents: OwnedOCSPResponseIteratorData::try_new(Arc::clone(&self.raw), |v| { Ok::<_, ()>( - v.borrow_basic_response() + v.borrow_value() + .response_bytes .as_ref() .unwrap() + .response + .get() .tbs_response_data .responses .unwrap_read() @@ -210,10 +209,12 @@ impl OCSPResponse { }; for i in 0..certs.len() { // TODO: O(n^2), don't have too many certificates! - let raw_cert = map_arc_data_ocsp_response(&self.raw, |_data, _resp, basic_response| { - basic_response + let raw_cert = map_arc_data_ocsp_response(&self.raw, |_data, resp| { + resp.response_bytes .as_ref() .unwrap() + .response + .get() .certs .as_ref() .unwrap() @@ -304,9 +305,12 @@ impl OCSPResponse { &mut self.cached_extensions, &self .raw - .borrow_basic_response() + .borrow_value() + .response_bytes .as_ref() .unwrap() + .response + .get() .tbs_response_data .response_extensions, |oid, ext_data| { @@ -332,9 +336,12 @@ impl OCSPResponse { self.requires_successful_response()?; let single_resp = self .raw - .borrow_basic_response() + .borrow_value() + .response_bytes .as_ref() .unwrap() + .response + .get() .single_response()?; let x509_module = py.import("cryptography.x509")?; x509::parse_and_cache_extensions( @@ -383,17 +390,10 @@ fn map_arc_data_ocsp_response( f: impl for<'this> FnOnce( &'this [u8], &RawOCSPResponse<'this>, - &Option>, ) -> certificate::RawCertificate<'this>, ) -> certificate::OwnedRawCertificate { certificate::OwnedRawCertificate::new_public(Arc::clone(it.borrow_data()), |inner_it| { - it.with(|value| { - f( - inner_it, - unsafe { std::mem::transmute(value.value) }, - unsafe { std::mem::transmute(value.basic_response) }, - ) - }) + it.with(|value| f(inner_it, unsafe { std::mem::transmute(value.value) })) }) } fn try_map_arc_data_mut_ocsp_response_iterator( @@ -418,7 +418,7 @@ struct RawOCSPResponse<'a> { #[derive(asn1::Asn1Read, asn1::Asn1Write)] struct ResponseBytes<'a> { response_type: asn1::ObjectIdentifier, - response: &'a [u8], + response: asn1::OctetStringEncoded>, } type OCSPCerts<'a> = Option< @@ -577,166 +577,9 @@ struct RevokedInfo { revocation_reason: Option, } -fn create_ocsp_basic_response<'p>( - py: pyo3::Python<'p>, - builder: &'p pyo3::PyAny, - private_key: &'p pyo3::PyAny, - hash_algorithm: &'p pyo3::PyAny, -) -> PyAsn1Result> { - let ocsp_mod = py.import("cryptography.x509.ocsp")?; - - let py_single_resp = builder.getattr(crate::intern!(py, "_response"))?; - let py_cert: pyo3::PyRef<'_, x509::Certificate> = py_single_resp - .getattr(crate::intern!(py, "_cert"))? - .extract()?; - let py_issuer: pyo3::PyRef<'_, x509::Certificate> = py_single_resp - .getattr(crate::intern!(py, "_issuer"))? - .extract()?; - let py_cert_hash_algorithm = py_single_resp.getattr(crate::intern!(py, "_algorithm"))?; - let (responder_cert, responder_encoding): (&pyo3::PyCell, &pyo3::PyAny) = - builder - .getattr(crate::intern!(py, "_responder_id"))? - .extract()?; - - let py_cert_status = py_single_resp.getattr(crate::intern!(py, "_cert_status"))?; - let cert_status = if py_cert_status - == ocsp_mod - .getattr(crate::intern!(py, "OCSPCertStatus"))? - .getattr(crate::intern!(py, "GOOD"))? - { - CertStatus::Good(()) - } else if py_cert_status - == ocsp_mod - .getattr(crate::intern!(py, "OCSPCertStatus"))? - .getattr(crate::intern!(py, "UNKNOWN"))? - { - CertStatus::Unknown(()) - } else { - let revocation_reason = if !py_single_resp - .getattr(crate::intern!(py, "_revocation_reason"))? - .is_none() - { - let value = py - .import("cryptography.hazmat.backends.openssl.decode_asn1")? - .getattr(crate::intern!(py, "_CRL_ENTRY_REASON_ENUM_TO_CODE"))? - .get_item(py_single_resp.getattr(crate::intern!(py, "_revocation_reason"))?)? - .extract::()?; - Some(asn1::Enumerated::new(value)) - } else { - None - }; - // REVOKED - let py_revocation_time = py_single_resp.getattr(crate::intern!(py, "_revocation_time"))?; - let revocation_time = asn1::GeneralizedTime::new(py_to_chrono(py, py_revocation_time)?)?; - CertStatus::Revoked(RevokedInfo { - revocation_time, - revocation_reason, - }) - }; - let next_update = if !py_single_resp - .getattr(crate::intern!(py, "_next_update"))? - .is_none() - { - let py_next_update = py_single_resp.getattr(crate::intern!(py, "_next_update"))?; - Some(asn1::GeneralizedTime::new(py_to_chrono( - py, - py_next_update, - )?)?) - } else { - None - }; - let py_this_update = py_single_resp.getattr(crate::intern!(py, "_this_update"))?; - let this_update = asn1::GeneralizedTime::new(py_to_chrono(py, py_this_update)?)?; - - let responses = vec![SingleResponse { - cert_id: ocsp::CertID::new(py, &py_cert, &py_issuer, py_cert_hash_algorithm)?, - cert_status, - next_update, - this_update, - single_extensions: None, - }]; - - let borrowed_cert = responder_cert.borrow(); - let responder_id = if responder_encoding - == ocsp_mod - .getattr(crate::intern!(py, "OCSPResponderEncoding"))? - .getattr(crate::intern!(py, "HASH"))? - { - let sha1 = py - .import("cryptography.hazmat.primitives.hashes")? - .getattr(crate::intern!(py, "SHA1"))? - .call0()?; - ResponderId::ByKey(ocsp::hash_data( - py, - sha1, - borrowed_cert - .raw - .borrow_value_public() - .tbs_cert - .spki - .subject_public_key - .as_bytes(), - )?) - } else { - ResponderId::ByName( - borrowed_cert - .raw - .borrow_value_public() - .tbs_cert - .subject - .clone(), - ) - }; - - let tbs_response_data = ResponseData { - version: 0, - produced_at: asn1::GeneralizedTime::new(chrono::Utc::now().with_nanosecond(0).unwrap())?, - responder_id, - responses: x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new(responses)), - response_extensions: x509::common::encode_extensions( - py, - builder.getattr(crate::intern!(py, "_extensions"))?, - extensions::encode_extension, - )?, - }; - - let sigalg = x509::sign::compute_signature_algorithm(py, private_key, hash_algorithm)?; - let tbs_bytes = asn1::write_single(&tbs_response_data)?; - let signature = x509::sign::sign_data(py, private_key, hash_algorithm, &tbs_bytes)?; - - py.import("cryptography.hazmat.backends.openssl.backend")? - .getattr(crate::intern!(py, "backend"))? - .call_method1( - "_check_keys_correspond", - ( - responder_cert.call_method0("public_key")?, - private_key.call_method0("public_key")?, - ), - )?; - - let py_certs: Option>> = - builder.getattr(crate::intern!(py, "_certs"))?.extract()?; - let certs = py_certs.as_ref().map(|py_certs| { - x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new( - py_certs - .iter() - .map(|c| c.raw.borrow_value_public().clone()) - .collect(), - )) - }); - - let basic_resp = BasicOCSPResponse { - tbs_response_data, - signature: asn1::BitString::new(signature, 0).unwrap(), - signature_algorithm: sigalg, - certs, - }; - Ok(asn1::write_single(&basic_resp)?) -} - #[pyo3::prelude::pyfunction] -fn create_ocsp_response( - py: pyo3::Python<'_>, +fn create_ocsp_response<'p>( + py: pyo3::Python<'p>, status: &pyo3::PyAny, builder: &pyo3::PyAny, private_key: &pyo3::PyAny, @@ -745,12 +588,168 @@ fn create_ocsp_response( let response_status = status .getattr(crate::intern!(py, "value"))? .extract::()?; - let basic_resp_bytes; + + let py_cert: pyo3::PyRef<'_, x509::Certificate>; + let py_issuer: pyo3::PyRef<'_, x509::Certificate>; + let borrowed_cert; + let py_certs: Option>>; let response_bytes = if response_status == SUCCESSFUL_RESPONSE { - basic_resp_bytes = create_ocsp_basic_response(py, builder, private_key, hash_algorithm)?; + let ocsp_mod = py.import("cryptography.x509.ocsp")?; + + let py_single_resp = builder.getattr(crate::intern!(py, "_response"))?; + py_cert = py_single_resp + .getattr(crate::intern!(py, "_cert"))? + .extract()?; + py_issuer = py_single_resp + .getattr(crate::intern!(py, "_issuer"))? + .extract()?; + let py_cert_hash_algorithm = py_single_resp.getattr(crate::intern!(py, "_algorithm"))?; + let (responder_cert, responder_encoding): (&pyo3::PyCell, &pyo3::PyAny) = + builder + .getattr(crate::intern!(py, "_responder_id"))? + .extract()?; + + let py_cert_status = py_single_resp.getattr(crate::intern!(py, "_cert_status"))?; + let cert_status = if py_cert_status + == ocsp_mod + .getattr(crate::intern!(py, "OCSPCertStatus"))? + .getattr(crate::intern!(py, "GOOD"))? + { + CertStatus::Good(()) + } else if py_cert_status + == ocsp_mod + .getattr(crate::intern!(py, "OCSPCertStatus"))? + .getattr(crate::intern!(py, "UNKNOWN"))? + { + CertStatus::Unknown(()) + } else { + let revocation_reason = if !py_single_resp + .getattr(crate::intern!(py, "_revocation_reason"))? + .is_none() + { + let value = py + .import("cryptography.hazmat.backends.openssl.decode_asn1")? + .getattr(crate::intern!(py, "_CRL_ENTRY_REASON_ENUM_TO_CODE"))? + .get_item(py_single_resp.getattr(crate::intern!(py, "_revocation_reason"))?)? + .extract::()?; + Some(asn1::Enumerated::new(value)) + } else { + None + }; + // REVOKED + let py_revocation_time = + py_single_resp.getattr(crate::intern!(py, "_revocation_time"))?; + let revocation_time = + asn1::GeneralizedTime::new(py_to_chrono(py, py_revocation_time)?)?; + CertStatus::Revoked(RevokedInfo { + revocation_time, + revocation_reason, + }) + }; + let next_update = if !py_single_resp + .getattr(crate::intern!(py, "_next_update"))? + .is_none() + { + let py_next_update = py_single_resp.getattr(crate::intern!(py, "_next_update"))?; + Some(asn1::GeneralizedTime::new(py_to_chrono( + py, + py_next_update, + )?)?) + } else { + None + }; + let py_this_update = py_single_resp.getattr(crate::intern!(py, "_this_update"))?; + let this_update = asn1::GeneralizedTime::new(py_to_chrono(py, py_this_update)?)?; + + let responses = vec![SingleResponse { + cert_id: ocsp::CertID::new(py, &py_cert, &py_issuer, py_cert_hash_algorithm)?, + cert_status, + next_update, + this_update, + single_extensions: None, + }]; + + borrowed_cert = responder_cert.borrow(); + let responder_id = if responder_encoding + == ocsp_mod + .getattr(crate::intern!(py, "OCSPResponderEncoding"))? + .getattr(crate::intern!(py, "HASH"))? + { + let sha1 = py + .import("cryptography.hazmat.primitives.hashes")? + .getattr(crate::intern!(py, "SHA1"))? + .call0()?; + ResponderId::ByKey(ocsp::hash_data( + py, + sha1, + borrowed_cert + .raw + .borrow_value_public() + .tbs_cert + .spki + .subject_public_key + .as_bytes(), + )?) + } else { + ResponderId::ByName( + borrowed_cert + .raw + .borrow_value_public() + .tbs_cert + .subject + .clone(), + ) + }; + + let tbs_response_data = ResponseData { + version: 0, + produced_at: asn1::GeneralizedTime::new( + chrono::Utc::now().with_nanosecond(0).unwrap(), + )?, + responder_id, + responses: x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new( + responses, + )), + response_extensions: x509::common::encode_extensions( + py, + builder.getattr(crate::intern!(py, "_extensions"))?, + extensions::encode_extension, + )?, + }; + + let sigalg = x509::sign::compute_signature_algorithm(py, private_key, hash_algorithm)?; + let tbs_bytes = asn1::write_single(&tbs_response_data)?; + let signature = x509::sign::sign_data(py, private_key, hash_algorithm, &tbs_bytes)?; + + py.import("cryptography.hazmat.backends.openssl.backend")? + .getattr(crate::intern!(py, "backend"))? + .call_method1( + "_check_keys_correspond", + ( + responder_cert.call_method0("public_key")?, + private_key.call_method0("public_key")?, + ), + )?; + + py_certs = builder.getattr(crate::intern!(py, "_certs"))?.extract()?; + let certs = py_certs.as_ref().map(|py_certs| { + x509::Asn1ReadableOrWritable::new_write(asn1::SequenceOfWriter::new( + py_certs + .iter() + .map(|c| c.raw.borrow_value_public().clone()) + .collect(), + )) + }); + + let basic_resp = BasicOCSPResponse { + tbs_response_data, + signature: asn1::BitString::new(signature, 0).unwrap(), + signature_algorithm: sigalg, + certs, + }; Some(ResponseBytes { response_type: (BASIC_RESPONSE_OID).clone(), - response: &basic_resp_bytes, + response: asn1::OctetStringEncoded::new(basic_resp), }) } else { None From 3489d7a9fe0dc7563bf4b04f03fe8aede9af4a5d Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sun, 13 Nov 2022 00:23:19 +0000 Subject: [PATCH 180/298] Bump BoringSSL and/or OpenSSL in CI (#7804) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9cfedb22256..155ce8f05b82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 12, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "0faffc7a30eeb195248ea43056f4848e2a9b1c6d"}} - # Latest commit on the OpenSSL master branch, as of Nov 12, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "a0783b83a3bd05a07ea64567995c7642621b4aa6"}} + # Latest commit on the OpenSSL master branch, as of Nov 13, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "43086b1bd48958ce95fadba8459ad88675da4fdf"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From f3086129b51c9be65390ce0afe016416313db179 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 13 Nov 2022 15:55:25 -0500 Subject: [PATCH 181/298] Update chrono and resolve deprecations (#7805) --- src/rust/Cargo.lock | 4 ++-- src/rust/src/x509/common.rs | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index eebaf3b6bb9e..6d5802b424ae 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -82,9 +82,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.22" +version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" +checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" dependencies = [ "iana-time-zone", "num-integer", diff --git a/src/rust/src/x509/common.rs b/src/rust/src/x509/common.rs index 5cc833830b23..fb61b7ae8aa5 100644 --- a/src/rust/src/x509/common.rs +++ b/src/rust/src/x509/common.rs @@ -683,16 +683,15 @@ pub(crate) fn py_to_chrono( val: &pyo3::PyAny, ) -> pyo3::PyResult> { Ok(chrono::Utc - .ymd( + .with_ymd_and_hms( val.getattr(crate::intern!(py, "year"))?.extract()?, val.getattr(crate::intern!(py, "month"))?.extract()?, val.getattr(crate::intern!(py, "day"))?.extract()?, - ) - .and_hms( val.getattr(crate::intern!(py, "hour"))?.extract()?, val.getattr(crate::intern!(py, "minute"))?.extract()?, val.getattr(crate::intern!(py, "second"))?.extract()?, - )) + ) + .unwrap()) } #[derive(Hash, PartialEq, Clone)] From 8632fe86d1a2ada46402150e9560fcf0013a2c6e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 14 Nov 2022 20:59:17 -0500 Subject: [PATCH 182/298] attempt to un-curse our CI (#7810) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 155ce8f05b82..66b2e99e7e98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: linux: - runs-on: ubuntu-latest + runs-on: ubuntu-20.04 strategy: fail-fast: false matrix: From cbc06f3e406ab8d8590f73da54da63f1147d09cf Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 14 Nov 2022 22:23:02 -0500 Subject: [PATCH 183/298] Don't use double space after a period (#7808) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 9b260f5e47ce..19f1678b710f 100644 --- a/README.rst +++ b/README.rst @@ -14,7 +14,7 @@ pyca/cryptography ``cryptography`` is a package which provides cryptographic recipes and -primitives to Python developers. Our goal is for it to be your "cryptographic +primitives to Python developers. Our goal is for it to be your "cryptographic standard library". It supports Python 3.6+ and PyPy3 7.2+. ``cryptography`` includes both high level recipes and low level interfaces to From 5c7defcde6e1031b97477db906731e94568df6fc Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 15 Nov 2022 03:29:36 +0000 Subject: [PATCH 184/298] Bump BoringSSL and/or OpenSSL in CI (#7809) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66b2e99e7e98..e7bc96daaf6d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 12, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "0faffc7a30eeb195248ea43056f4848e2a9b1c6d"}} - # Latest commit on the OpenSSL master branch, as of Nov 13, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "43086b1bd48958ce95fadba8459ad88675da4fdf"}} + # Latest commit on the BoringSSL master branch, as of Nov 15, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "a1dffbfed9b78d77ab17c15fe2d189ca44704fd8"}} + # Latest commit on the OpenSSL master branch, as of Nov 15, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "c9a542e41837ea65671dcd75c448d7113d34a4fd"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From b907413311c3a197f5b66d321e7297c1d9af5b2e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 14 Nov 2022 22:44:09 -0500 Subject: [PATCH 185/298] Increased minimum macOS version to 10.12 (#7806) --- .github/workflows/ci.yml | 2 +- .github/workflows/wheel-builder.yml | 8 ++++---- CHANGELOG.rst | 2 ++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7bc96daaf6d..d1fdb50f2821 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -379,7 +379,7 @@ jobs: run: | CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \ LDFLAGS="${HOME}/openssl-macos-universal2/lib/libcrypto.a ${HOME}/openssl-macos-universal2/lib/libssl.a" \ - CFLAGS="-I${HOME}/openssl-macos-universal2/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -mmacosx-version-min=10.10 -march=core2 $EXTRA_CFLAGS" \ + CFLAGS="-I${HOME}/openssl-macos-universal2/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -mmacosx-version-min=10.12 -march=core2 $EXTRA_CFLAGS" \ tox -vvv -r -- --color=yes --wycheproof-root=wycheproof env: TOXENV: ${{ matrix.PYTHON.TOXENV }} diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index e3373b2bcd76..e25c1f749552 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -121,7 +121,7 @@ jobs: # Despite the name, this is built for the macOS 11 SDK on arm64 and 10.9+ on intel DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.10.0/python-3.10.0post2-macos11.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3' - DEPLOYMENT_TARGET: '10.10' + DEPLOYMENT_TARGET: '10.12' # This archflags is default, but let's be explicit ARCHFLAGS: '-arch x86_64 -arch arm64' # See https://github.com/pypa/cibuildwheel/blob/c8876b5c54a6c6b08de5d4b1586906b56203bd9e/cibuildwheel/macos.py#L257-L269 @@ -132,7 +132,7 @@ jobs: ABI_VERSION: 'cp36' DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.10.0/python-3.10.0post2-macos11.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3' - DEPLOYMENT_TARGET: '10.10' + DEPLOYMENT_TARGET: '10.12' # We continue to build a non-universal2 for a bit to see metrics on # download counts (this is a proxy for pip version since universal2 # requires a 21.x pip) @@ -140,12 +140,12 @@ jobs: _PYTHON_HOST_PLATFORM: 'macosx-10.9-x86_64' - VERSION: 'pypy-3.8' BIN_PATH: 'pypy3' - DEPLOYMENT_TARGET: '10.10' + DEPLOYMENT_TARGET: '10.12' _PYTHON_HOST_PLATFORM: 'macosx-10.9-x86_64' ARCHFLAGS: '-arch x86_64' - VERSION: 'pypy-3.9' BIN_PATH: 'pypy3' - DEPLOYMENT_TARGET: '10.10' + DEPLOYMENT_TARGET: '10.12' _PYTHON_HOST_PLATFORM: 'macosx-10.9-x86_64' ARCHFLAGS: '-arch x86_64' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS ${{ matrix.PYTHON.ARCHFLAGS }}" diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 93236dbdc448..1e22b2417ba8 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -25,6 +25,8 @@ Changelog * **BACKWARDS INCOMPATIBLE:** Support for using MD5 or SHA1 in :class:`~cryptography.x509.CertificateBuilder`, other X.509 builders, and PKCS7 has been removed. +* **BACKWARDS INCOMPATIBLE:** Dropped support for macOS 10.10 and 10.11, macOS + users must upgrade to 10.12 or newer. * Added support for :ref:`disabling the legacy provider in OpenSSL 3.0.x`. * Added support for disabling RSA key validation checks when loading RSA From 5625168869c9a83b7665356e661cc0c663cfa8bf Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 00:20:53 +0000 Subject: [PATCH 186/298] Bump BoringSSL and/or OpenSSL in CI (#7814) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1fdb50f2821..08746b5ddd95 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 15, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "a1dffbfed9b78d77ab17c15fe2d189ca44704fd8"}} - # Latest commit on the OpenSSL master branch, as of Nov 15, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "c9a542e41837ea65671dcd75c448d7113d34a4fd"}} + # Latest commit on the OpenSSL master branch, as of Nov 16, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "be0161ff100bf10c9549fc09ce4513681011da1c"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1730e7af071653b3e04aeac9180a727a93df2330 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 16 Nov 2022 02:40:43 -0500 Subject: [PATCH 187/298] Clear out some dead code from the OS random engine, now that macOS 10.12 is our minimum (#7813) --- src/_cffi_src/openssl/src/osrandom_engine.c | 63 +++++---------------- src/_cffi_src/openssl/src/osrandom_engine.h | 4 +- tests/hazmat/backends/test_openssl.py | 2 +- 3 files changed, 17 insertions(+), 52 deletions(-) diff --git a/src/_cffi_src/openssl/src/osrandom_engine.c b/src/_cffi_src/openssl/src/osrandom_engine.c index a84857b86df4..257fcd50968f 100644 --- a/src/_cffi_src/openssl/src/osrandom_engine.c +++ b/src/_cffi_src/openssl/src/osrandom_engine.c @@ -246,22 +246,7 @@ static void dev_urandom_close(void) { #if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY static const char *Cryptography_osrandom_engine_name = "osrandom_engine getentropy()"; -static int getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_NOT_INIT; - static int osrandom_init(ENGINE *e) { -#if !defined(__APPLE__) - getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS; -#else - if (__builtin_available(macOS 10.12, *)) { - getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS; - } else { - getentropy_works = CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK; - int fd = dev_urandom_fd(); - if (fd < 0) { - return 0; - } - } -#endif return 1; } @@ -269,34 +254,22 @@ static int osrandom_rand_bytes(unsigned char *buffer, int size) { int len; int res; - switch(getentropy_works) { -#if defined(__APPLE__) - case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK: - return dev_urandom_read(buffer, size); -#endif - case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS: - while (size > 0) { - /* OpenBSD and macOS restrict maximum buffer size to 256. */ - len = size > 256 ? 256 : size; -/* on mac, availability is already checked using `__builtin_available` above */ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunguarded-availability" - res = getentropy(buffer, (size_t)len); -#pragma clang diagnostic pop - 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; + 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; } - return 1; + buffer += len; + size -= len; } - __builtin_unreachable(); + return 1; } static int osrandom_finish(ENGINE *e) { @@ -308,13 +281,7 @@ static int osrandom_rand_status(void) { } static const char *osurandom_get_implementation(void) { - switch(getentropy_works) { - case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_FALLBACK: - return "/dev/urandom"; - case CRYPTOGRAPHY_OSRANDOM_GETENTROPY_WORKS: - return "getentropy"; - } - __builtin_unreachable(); + return "getentropy"; } #endif /* CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY */ diff --git a/src/_cffi_src/openssl/src/osrandom_engine.h b/src/_cffi_src/openssl/src/osrandom_engine.h index 93d918b88bf5..376b8ff21c21 100644 --- a/src/_cffi_src/openssl/src/osrandom_engine.h +++ b/src/_cffi_src/openssl/src/osrandom_engine.h @@ -69,9 +69,7 @@ /* Fallbacks need /dev/urandom helper functions. */ #if CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETRANDOM || \ - CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM || \ - (CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_GETENTROPY && \ - defined(__APPLE__)) + CRYPTOGRAPHY_OSRANDOM_ENGINE == CRYPTOGRAPHY_OSRANDOM_ENGINE_DEV_URANDOM #define CRYPTOGRAPHY_OSRANDOM_NEEDS_DEV_URANDOM 1 #endif diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 6f3a975bac89..a747f4d03f30 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -287,7 +287,7 @@ def test_osrandom_engine_implementation(self): if sys.platform.startswith("linux"): assert name in ["getrandom", "/dev/urandom"] if sys.platform == "darwin": - assert name in ["getentropy", "/dev/urandom"] + assert name in ["getentropy"] if sys.platform == "win32": assert name == "CryptGenRandom" From a77fc27fa10c9e9b007e64d01646a9c30366d0f6 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 16 Nov 2022 22:04:41 -0500 Subject: [PATCH 188/298] Bump BoringSSL and/or OpenSSL in CI (#7816) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 08746b5ddd95..cc6369514aa8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 15, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "a1dffbfed9b78d77ab17c15fe2d189ca44704fd8"}} - # Latest commit on the OpenSSL master branch, as of Nov 16, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "be0161ff100bf10c9549fc09ce4513681011da1c"}} + # Latest commit on the OpenSSL master branch, as of Nov 17, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "7489ada9f3fd902c5bc3c58cc03a90de2800d0ab"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From d9f6ef6a00a75c5577d81dccd82990e969899510 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 16 Nov 2022 22:59:49 -0500 Subject: [PATCH 189/298] update for new fedora (#7817) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc6369514aa8..77e1c8021c70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -136,7 +136,7 @@ jobs: - {IMAGE: "ubuntu-focal", TOXENV: "py38"} - {IMAGE: "ubuntu-jammy", TOXENV: "py310"} - {IMAGE: "ubuntu-rolling", TOXENV: "py310"} - - {IMAGE: "fedora", TOXENV: "py310"} + - {IMAGE: "fedora", TOXENV: "py311"} - {IMAGE: "alpine", TOXENV: "py310"} - {IMAGE: "centos-stream9", TOXENV: "py39"} name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" From 7e01d58438165a8158da0a5258f8c2bad9770b44 Mon Sep 17 00:00:00 2001 From: jeanluc <2163936+lkubb@users.noreply.github.com> Date: Thu, 17 Nov 2022 23:12:51 +0000 Subject: [PATCH 190/298] Add *_SHA3 signature algorithms to OID <-> hash map (#7819) * Add test for issue 7818 * Add *_SHA3 signature algorithms to OID <-> hash map * Use type instead of __class__ --- src/cryptography/hazmat/_oid.py | 8 ++++++++ tests/x509/test_x509.py | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/cryptography/hazmat/_oid.py b/src/cryptography/hazmat/_oid.py index 604cf07b381f..927ffc4c5412 100644 --- a/src/cryptography/hazmat/_oid.py +++ b/src/cryptography/hazmat/_oid.py @@ -128,11 +128,19 @@ class SignatureAlgorithmOID: SignatureAlgorithmOID.RSA_WITH_SHA256: hashes.SHA256(), SignatureAlgorithmOID.RSA_WITH_SHA384: hashes.SHA384(), SignatureAlgorithmOID.RSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.RSA_WITH_SHA3_224: hashes.SHA3_224(), + SignatureAlgorithmOID.RSA_WITH_SHA3_256: hashes.SHA3_256(), + SignatureAlgorithmOID.RSA_WITH_SHA3_384: hashes.SHA3_384(), + SignatureAlgorithmOID.RSA_WITH_SHA3_512: hashes.SHA3_512(), SignatureAlgorithmOID.ECDSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID.ECDSA_WITH_SHA224: hashes.SHA224(), SignatureAlgorithmOID.ECDSA_WITH_SHA256: hashes.SHA256(), SignatureAlgorithmOID.ECDSA_WITH_SHA384: hashes.SHA384(), SignatureAlgorithmOID.ECDSA_WITH_SHA512: hashes.SHA512(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_224: hashes.SHA3_224(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_256: hashes.SHA3_256(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_384: hashes.SHA3_384(), + SignatureAlgorithmOID.ECDSA_WITH_SHA3_512: hashes.SHA3_512(), SignatureAlgorithmOID.DSA_WITH_SHA1: hashes.SHA1(), SignatureAlgorithmOID.DSA_WITH_SHA224: hashes.SHA224(), SignatureAlgorithmOID.DSA_WITH_SHA256: hashes.SHA256(), diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 19047c87cb75..196eab7d0302 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1934,6 +1934,7 @@ def test_build_cert(self, hashalg, hashalg_oid, backend): assert cert.version is x509.Version.v3 assert cert.signature_algorithm_oid == hashalg_oid + assert type(cert.signature_hash_algorithm) is hashalg assert cert.not_valid_before == not_valid_before assert cert.not_valid_after == not_valid_after basic_constraints = cert.extensions.get_extension_for_oid( @@ -2824,6 +2825,7 @@ def test_build_cert_with_ec_private_key( assert cert.version is x509.Version.v3 assert cert.signature_algorithm_oid == hashalg_oid + assert type(cert.signature_hash_algorithm) is hashalg assert cert.not_valid_before == not_valid_before assert cert.not_valid_after == not_valid_after basic_constraints = cert.extensions.get_extension_for_oid( From 95edbd105e76bb864510a7790322781a9aeba523 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 18 Nov 2022 00:23:10 +0000 Subject: [PATCH 191/298] Bump BoringSSL and/or OpenSSL in CI (#7820) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77e1c8021c70..21035e84de8f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 15, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "a1dffbfed9b78d77ab17c15fe2d189ca44704fd8"}} - # Latest commit on the OpenSSL master branch, as of Nov 17, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "7489ada9f3fd902c5bc3c58cc03a90de2800d0ab"}} + # Latest commit on the BoringSSL master branch, as of Nov 18, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "f0518d45119dd4dd322a884669daf8247bc3c992"}} + # Latest commit on the OpenSSL master branch, as of Nov 18, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "cab5b3a344199d54dd4432dbc6d4b361e10e11d1"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From e78159cbfa70f6fd7172d15487289a1c19106791 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Nov 2022 07:17:27 -0500 Subject: [PATCH 192/298] Bump cxx from 1.0.81 to 1.0.82 in /src/rust (#7821) Bumps [cxx](https://github.com/dtolnay/cxx) from 1.0.81 to 1.0.82. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.81...1.0.82) --- updated-dependencies: - dependency-name: cxx dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6d5802b424ae..ade74d130347 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97abf9f0eca9e52b7f81b945524e76710e6cb2366aead23b7d4fbf72e281f888" +checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" dependencies = [ "cc", "cxxbridge-flags", @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca220e4794c934dc6b1207c3b42856ad4c302f2df1712e9f8d2eec5afaacf1f" +checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" [[package]] name = "cxxbridge-macro" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b846f081361125bfc8dc9d3940c84e1fd83ba54bbca7b17cd29483c828be0704" +checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" dependencies = [ "proc-macro2", "quote", From 9adc2e2a2cdda279fa2b925622a1b6b4325bd46b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Nov 2022 12:54:54 +0000 Subject: [PATCH 193/298] Bump cxx-build from 1.0.81 to 1.0.82 in /src/rust (#7822) Bumps [cxx-build](https://github.com/dtolnay/cxx) from 1.0.81 to 1.0.82. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.81...1.0.82) --- updated-dependencies: - dependency-name: cxx-build dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index ade74d130347..3afe2ab2eff8 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc32cc5fea1d894b77d269ddb9f192110069a8a9c1f1d441195fba90553dea3" +checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" dependencies = [ "cc", "codespan-reporting", From ebd452fe7ab4523bd3a3d1ba77283b62686bc3a5 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 19 Nov 2022 00:54:40 +0000 Subject: [PATCH 194/298] Bump BoringSSL and/or OpenSSL in CI (#7823) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 21035e84de8f..65c6c9b9ab10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 18, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "f0518d45119dd4dd322a884669daf8247bc3c992"}} - # Latest commit on the OpenSSL master branch, as of Nov 18, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "cab5b3a344199d54dd4432dbc6d4b361e10e11d1"}} + # Latest commit on the OpenSSL master branch, as of Nov 19, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "81929ac49aa583b2347348953d8399ad775c6fd1"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 41f6ff11f676d6a5ca0f89f36c630f1360ecfb7b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 20 Nov 2022 15:57:22 -0500 Subject: [PATCH 195/298] Remove bindings related to SSLeay (#7826) --- src/_cffi_src/openssl/crypto.py | 33 --------------------------------- 1 file changed, 33 deletions(-) diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index cbef3880496a..63843e02ee26 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -11,11 +11,6 @@ static const long Cryptography_HAS_MEM_FUNCTIONS; static const long Cryptography_HAS_OPENSSL_CLEANUP; -static const int SSLEAY_VERSION; -static const int SSLEAY_CFLAGS; -static const int SSLEAY_PLATFORM; -static const int SSLEAY_DIR; -static const int SSLEAY_BUILT_ON; static const int OPENSSL_VERSION; static const int OPENSSL_CFLAGS; static const int OPENSSL_BUILT_ON; @@ -26,10 +21,6 @@ FUNCTIONS = """ void OPENSSL_cleanup(void); -/* SSLeay was removed in 1.1.0 */ -unsigned long SSLeay(void); -const char *SSLeay_version(int); -/* these functions were added to replace the SSLeay functions in 1.1.0 */ unsigned long OpenSSL_version_num(void); const char *OpenSSL_version(int); @@ -50,30 +41,6 @@ """ CUSTOMIZATIONS = """ -/* In 1.1.0 SSLeay has finally been retired. We bidirectionally define the - values so you can use either one. This is so we can use the new function - names no matter what OpenSSL we're running on, but users on older pyOpenSSL - releases won't see issues if they're running OpenSSL 1.1.0 */ -#if !defined(SSLEAY_VERSION) -# define SSLeay OpenSSL_version_num -# define SSLeay_version OpenSSL_version -# define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER -# define SSLEAY_VERSION OPENSSL_VERSION -# define SSLEAY_CFLAGS OPENSSL_CFLAGS -# define SSLEAY_BUILT_ON OPENSSL_BUILT_ON -# define SSLEAY_PLATFORM OPENSSL_PLATFORM -# define SSLEAY_DIR OPENSSL_DIR -#endif -#if !defined(OPENSSL_VERSION) -# define OpenSSL_version_num SSLeay -# define OpenSSL_version SSLeay_version -# define OPENSSL_VERSION SSLEAY_VERSION -# define OPENSSL_CFLAGS SSLEAY_CFLAGS -# define OPENSSL_BUILT_ON SSLEAY_BUILT_ON -# define OPENSSL_PLATFORM SSLEAY_PLATFORM -# define OPENSSL_DIR SSLEAY_DIR -#endif - #if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 static const long Cryptography_HAS_OPENSSL_CLEANUP = 0; void (*OPENSSL_cleanup)(void) = NULL; From 8c9b41295011f9924944ec5f9a71fec847165c7d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 20 Nov 2022 16:04:25 -0500 Subject: [PATCH 196/298] Remove some unused bindings (#7825) --- src/_cffi_src/openssl/asn1.py | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 98a933c195e8..9cb0ea8ae107 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -39,19 +39,8 @@ """ FUNCTIONS = """ -void ASN1_OBJECT_free(ASN1_OBJECT *); - /* ASN1 STRING */ const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *); -int ASN1_STRING_set(ASN1_STRING *, const void *, int); - -/* ASN1 OCTET STRING */ -ASN1_OCTET_STRING *ASN1_OCTET_STRING_new(void); -void ASN1_OCTET_STRING_free(ASN1_OCTET_STRING *); -int ASN1_OCTET_STRING_set(ASN1_OCTET_STRING *, const unsigned char *, int); - -/* ASN1 IA5STRING */ -ASN1_IA5STRING *ASN1_IA5STRING_new(void); /* ASN1 INTEGER */ void ASN1_INTEGER_free(ASN1_INTEGER *); @@ -59,7 +48,6 @@ /* ASN1 TIME */ ASN1_TIME *ASN1_TIME_new(void); -void ASN1_TIME_free(ASN1_TIME *); int ASN1_TIME_set_string(ASN1_TIME *, const char *); /* ASN1 GENERALIZEDTIME */ @@ -78,7 +66,6 @@ ASN1_GENERALIZEDTIME **); int ASN1_STRING_length(ASN1_STRING *); -int ASN1_STRING_set_default_mask_asc(char *); BIGNUM *ASN1_INTEGER_to_BN(ASN1_INTEGER *, BIGNUM *); ASN1_INTEGER *BN_to_ASN1_INTEGER(BIGNUM *, ASN1_INTEGER *); From dcf5ec789436f3032ec2ae1297d0411ddf186b75 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 00:25:13 +0000 Subject: [PATCH 197/298] Bump BoringSSL and/or OpenSSL in CI (#7830) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65c6c9b9ab10..4c51f6c7831f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 18, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "f0518d45119dd4dd322a884669daf8247bc3c992"}} - # Latest commit on the OpenSSL master branch, as of Nov 19, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "81929ac49aa583b2347348953d8399ad775c6fd1"}} + # Latest commit on the BoringSSL master branch, as of Nov 22, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "5511fa833c96c8caa9b51c13367f057c74d850eb"}} + # Latest commit on the OpenSSL master branch, as of Nov 22, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "26cfa4cd85f6b26dd7a48c2ff06bfa4a2cea4764"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From fe25c35d1f14d870a2bc489a49b2c0ece1c30c83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 12:15:49 +0000 Subject: [PATCH 198/298] Bump peter-evans/create-pull-request from 4.2.0 to 4.2.1 (#7831) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.0 to 4.2.1. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/b4d51739f96fca8047ad065eccef63442d8e99f7...d7db273d6c7206ba99224e659c982ae34a1025e3) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index 78c902fa3b9c..aa142c480456 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -58,7 +58,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha-boring.outputs.COMMIT_SHA || steps.check-sha-openssl.outputs.COMMIT_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@b4d51739f96fca8047ad065eccef63442d8e99f7 + uses: peter-evans/create-pull-request@d7db273d6c7206ba99224e659c982ae34a1025e3 with: commit-message: "Bump BoringSSL and/or OpenSSL in CI" title: "Bump BoringSSL and/or OpenSSSL in CI" From e06ab09f683698620cfb464c3152392e92c4fa1d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 12:43:09 +0000 Subject: [PATCH 199/298] Bump cc from 1.0.76 to 1.0.77 in /src/rust (#7832) Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.76 to 1.0.77. - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.76...1.0.77) --- updated-dependencies: - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 3afe2ab2eff8..77140edec8be 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -70,9 +70,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "cc" -version = "1.0.76" +version = "1.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a284da2e6fe2092f2353e51713435363112dfd60030e22add80be333fb928f" +checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" [[package]] name = "cfg-if" From 95a2b50841648c06bacca7b3d37a3b99d4f71d1e Mon Sep 17 00:00:00 2001 From: Theo Buehler Date: Tue, 22 Nov 2022 16:33:32 +0100 Subject: [PATCH 200/298] LibreSSL 3.7 adds support for Ed25519 (#7803) * LibreSSL 3.7 adds support for Ed25519 This brings support for the raw public key API. * Use feature variable to enable Ed25519 Ed25519 support is available since OpenSSL 1.1.1b and LibreSSL 3.7.0. --- src/_cffi_src/openssl/cryptography.py | 8 ++++++++ src/_cffi_src/openssl/evp.py | 6 +++++- src/cryptography/hazmat/backends/openssl/backend.py | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index f53ee72acb3c..e12e36549528 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -42,9 +42,12 @@ #if CRYPTOGRAPHY_IS_LIBRESSL #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 \ (LIBRESSL_VERSION_NUMBER < 0x3060000f) +#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370 \ + (LIBRESSL_VERSION_NUMBER < 0x3070000f) #else #define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_360 (0) +#define CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370 (0) #endif #if OPENSSL_VERSION_NUMBER < 0x10101000 @@ -68,6 +71,10 @@ #else #define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 0 #endif +/* Ed25519 support is available from OpenSSL 1.1.1b and LibreSSL 3.7.0. */ +#define CRYPTOGRAPHY_HAS_WORKING_ED25519 \ + (!CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B || \ + (CRYPTOGRAPHY_IS_LIBRESSL && !CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370)) """ TYPES = """ @@ -77,6 +84,7 @@ 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_IS_LIBRESSL; static const int CRYPTOGRAPHY_IS_BORINGSSL; diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 7a3ae2744f39..75d2522016cb 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -199,9 +199,10 @@ #endif #if CRYPTOGRAPHY_IS_LIBRESSL -static const long Cryptography_HAS_RAW_KEY = 0; static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 0; int (*EVP_DigestFinalXOF)(EVP_MD_CTX *, unsigned char *, size_t) = NULL; +#if CRYPTOGRAPHY_LIBRESSL_LESS_THAN_370 +static const long Cryptography_HAS_RAW_KEY = 0; EVP_PKEY *(*EVP_PKEY_new_raw_private_key)(int, ENGINE *, const unsigned char *, size_t) = NULL; EVP_PKEY *(*EVP_PKEY_new_raw_public_key)(int, ENGINE *, const unsigned char *, @@ -212,6 +213,9 @@ size_t *) = NULL; #else static const long Cryptography_HAS_RAW_KEY = 1; +#endif +#else +static const long Cryptography_HAS_RAW_KEY = 1; static const long Cryptography_HAS_EVP_DIGESTFINAL_XOF = 1; #endif diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 793fa2f71b9f..a29937516958 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -2001,7 +2001,7 @@ def x448_supported(self) -> bool: def ed25519_supported(self) -> bool: if self._fips_enabled: return False - return not self._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B + return self._lib.CRYPTOGRAPHY_HAS_WORKING_ED25519 def ed25519_load_public_bytes( self, data: bytes From 2ab64b5cfe8711e3e66297b406f00915666d4271 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 22 Nov 2022 20:13:39 -0500 Subject: [PATCH 201/298] Bump BoringSSL and/or OpenSSL in CI (#7835) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4c51f6c7831f..a63148078aa4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 22, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "5511fa833c96c8caa9b51c13367f057c74d850eb"}} - # Latest commit on the OpenSSL master branch, as of Nov 22, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "26cfa4cd85f6b26dd7a48c2ff06bfa4a2cea4764"}} + # Latest commit on the BoringSSL master branch, as of Nov 23, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "e0bb21bc8f8aafe67056242bc7f5ab2e22b14b8e"}} + # Latest commit on the OpenSSL master branch, as of Nov 23, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "e0fbaf2a4add8dd012b92923b0f23e87b1d28482"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 169a803e0c4feece7b81eecefcd54a49d7ba4d31 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 23 Nov 2022 19:32:37 -0500 Subject: [PATCH 202/298] don't use flake8 6.0 (#7838) it's not compatible with the latest flake8-import-order: https://github.com/PyCQA/flake8-import-order/issues/189 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index d42e78930c19..9c73cbc3becf 100644 --- a/setup.cfg +++ b/setup.cfg @@ -76,7 +76,7 @@ sdist = setuptools_rust >= 0.11.4 pep8test = black - flake8 + flake8 != 6.0.0 flake8-import-order pep8-naming # This extra is for OpenSSH private keys that use bcrypt KDF From 4138532a40123a5d833295e9386aeb57bfa5abfd Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 24 Nov 2022 00:49:59 +0000 Subject: [PATCH 203/298] Bump BoringSSL and/or OpenSSL in CI (#7837) Co-authored-by: BoringSSL Bot --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a63148078aa4..f12ce3573109 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 23, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "e0bb21bc8f8aafe67056242bc7f5ab2e22b14b8e"}} - # Latest commit on the OpenSSL master branch, as of Nov 23, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "e0fbaf2a4add8dd012b92923b0f23e87b1d28482"}} + # Latest commit on the BoringSSL master branch, as of Nov 24, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "2fd8de65347cebe9870b872e528658b922f61fe3"}} + # Latest commit on the OpenSSL master branch, as of Nov 24, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f2a6f83862be3e20260b708288a8f7d0928e9018"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 230ef9c80386661c73ca2c4c2ad3539f86ecaea3 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 24 Nov 2022 03:55:57 +0100 Subject: [PATCH 204/298] Fix the boringbot committer/author information (#7839) This patch makes the commit author field use the correct "user noreply" email. It helps GitHub to correctly assign the commit authorship in the UI. Refs: * https://github.com/sanitizers/patchback-github-app/commit/cee09976 * https://api.github.com/users/pyca-boringbot[bot] --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index aa142c480456..e71941a0ca79 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -62,7 +62,7 @@ jobs: with: commit-message: "Bump BoringSSL and/or OpenSSL in CI" title: "Bump BoringSSL and/or OpenSSSL in CI" - author: "BoringSSL Bot " + author: "pyca-boringbot[bot] " body: | ${{ steps.check-sha-boring.outputs.COMMIT_MSG }} ${{ steps.check-sha-openssl.outputs.COMMIT_MSG }} From b522c422a9b03b973798bd8411aedbeb631298a3 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Thu, 24 Nov 2022 04:57:29 +0100 Subject: [PATCH 205/298] Correct the tripple-S typo in "OpenSSL" in bot PRs (#7840) --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index e71941a0ca79..fb694916ccc7 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -61,7 +61,7 @@ jobs: uses: peter-evans/create-pull-request@d7db273d6c7206ba99224e659c982ae34a1025e3 with: commit-message: "Bump BoringSSL and/or OpenSSL in CI" - title: "Bump BoringSSL and/or OpenSSSL in CI" + title: "Bump BoringSSL and/or OpenSSL in CI" author: "pyca-boringbot[bot] " body: | ${{ steps.check-sha-boring.outputs.COMMIT_MSG }} From 459afc5193b565fe380b431434bad7b4bb27de87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 24 Nov 2022 13:49:46 +0000 Subject: [PATCH 206/298] Bump peter-evans/create-pull-request from 4.2.1 to 4.2.2 (#7841) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.1 to 4.2.2. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/d7db273d6c7206ba99224e659c982ae34a1025e3...331d02c7e2104af23ad5974d4d5cbc58a3e6dc77) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index fb694916ccc7..a218c4578cbf 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -58,7 +58,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha-boring.outputs.COMMIT_SHA || steps.check-sha-openssl.outputs.COMMIT_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@d7db273d6c7206ba99224e659c982ae34a1025e3 + uses: peter-evans/create-pull-request@331d02c7e2104af23ad5974d4d5cbc58a3e6dc77 with: commit-message: "Bump BoringSSL and/or OpenSSL in CI" title: "Bump BoringSSL and/or OpenSSL in CI" From fce124ac95281abe349741d3b9f7919448efda66 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 00:21:41 +0000 Subject: [PATCH 207/298] Bump BoringSSL and/or OpenSSL in CI (#7842) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f12ce3573109..b330aa5d3511 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Nov 24, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "2fd8de65347cebe9870b872e528658b922f61fe3"}} - # Latest commit on the OpenSSL master branch, as of Nov 24, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f2a6f83862be3e20260b708288a8f7d0928e9018"}} + # Latest commit on the OpenSSL master branch, as of Nov 25, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3f32d29ad464591ed968a1e430111e1525280f4c"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From df542e97563660e4009c941dfbd385258551b273 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 25 Nov 2022 15:53:16 -0500 Subject: [PATCH 208/298] Rewrite PKCS7 signature generation in Rust (#7729) * Rewrite PKCS7 signature generation in Rust * Update src/rust/src/pkcs7.rs --- .../hazmat/backends/openssl/backend.py | 100 +----- .../hazmat/bindings/_rust/pkcs7.pyi | 6 + .../hazmat/primitives/serialization/pkcs7.py | 54 +++- src/rust/src/pkcs7.rs | 301 +++++++++++++++++- 4 files changed, 353 insertions(+), 108 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index a29937516958..caa5458249fe 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -114,7 +114,7 @@ XTS, ) from cryptography.hazmat.primitives.kdf import scrypt -from cryptography.hazmat.primitives.serialization import pkcs7, ssh +from cryptography.hazmat.primitives.serialization import ssh from cryptography.hazmat.primitives.serialization.pkcs12 import ( PBES, PKCS12Certificate, @@ -2483,104 +2483,6 @@ def _load_pkcs7_certificates(self, p7): return certs - def pkcs7_sign( - self, - builder: pkcs7.PKCS7SignatureBuilder, - encoding: serialization.Encoding, - options: typing.List[pkcs7.PKCS7Options], - ) -> bytes: - assert builder._data is not None - bio = self._bytes_to_bio(builder._data) - init_flags = self._lib.PKCS7_PARTIAL - final_flags = 0 - - if len(builder._additional_certs) == 0: - certs = self._ffi.NULL - else: - certs = self._lib.sk_X509_new_null() - certs = self._ffi.gc(certs, self._lib.sk_X509_free) - # This list is to keep the x509 values alive until end of function - ossl_certs = [] - for cert in builder._additional_certs: - ossl_cert = self._cert2ossl(cert) - ossl_certs.append(ossl_cert) - res = self._lib.sk_X509_push(certs, ossl_cert) - self.openssl_assert(res >= 1) - - if pkcs7.PKCS7Options.DetachedSignature in options: - # Don't embed the data in the PKCS7 structure - init_flags |= self._lib.PKCS7_DETACHED - final_flags |= self._lib.PKCS7_DETACHED - - # This just inits a structure for us. However, there - # are flags we need to set, joy. - p7 = self._lib.PKCS7_sign( - self._ffi.NULL, - self._ffi.NULL, - certs, - self._ffi.NULL, - init_flags, - ) - self.openssl_assert(p7 != self._ffi.NULL) - p7 = self._ffi.gc(p7, self._lib.PKCS7_free) - signer_flags = 0 - # These flags are configurable on a per-signature basis - # but we've deliberately chosen to make the API only allow - # setting it across all signatures for now. - if pkcs7.PKCS7Options.NoCapabilities in options: - signer_flags |= self._lib.PKCS7_NOSMIMECAP - elif pkcs7.PKCS7Options.NoAttributes in options: - signer_flags |= self._lib.PKCS7_NOATTR - - if pkcs7.PKCS7Options.NoCerts in options: - signer_flags |= self._lib.PKCS7_NOCERTS - - for certificate, private_key, hash_algorithm in builder._signers: - ossl_cert = self._cert2ossl(certificate) - md = self._evp_md_non_null_from_algorithm(hash_algorithm) - p7signerinfo = self._lib.PKCS7_sign_add_signer( - p7, - ossl_cert, - private_key._evp_pkey, # type: ignore[union-attr] - md, - signer_flags, - ) - self.openssl_assert(p7signerinfo != self._ffi.NULL) - - for option in options: - # DetachedSignature, NoCapabilities, and NoAttributes are already - # handled so we just need to check these last two options. - if option is pkcs7.PKCS7Options.Text: - final_flags |= self._lib.PKCS7_TEXT - elif option is pkcs7.PKCS7Options.Binary: - final_flags |= self._lib.PKCS7_BINARY - - bio_out = self._create_mem_bio_gc() - if encoding is serialization.Encoding.SMIME: - # This finalizes the structure - res = self._lib.SMIME_write_PKCS7( - bio_out, p7, bio.bio, final_flags - ) - elif encoding is serialization.Encoding.PEM: - res = self._lib.PKCS7_final(p7, bio.bio, final_flags) - self.openssl_assert(res == 1) - res = self._lib.PEM_write_bio_PKCS7_stream( - bio_out, p7, bio.bio, final_flags - ) - else: - assert encoding is serialization.Encoding.DER - # We need to call finalize here becauase i2d_PKCS7_bio does not - # finalize. - res = self._lib.PKCS7_final(p7, bio.bio, final_flags) - self.openssl_assert(res == 1) - # OpenSSL 3.0 leaves a random bio error on the stack: - # https://github.com/openssl/openssl/issues/16681 - if self._lib.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER: - self._consume_errors() - res = self._lib.i2d_PKCS7_bio(bio_out, p7) - self.openssl_assert(res == 1) - return self._read_mem_bio(bio_out) - class GetCipherByName: def __init__(self, fmt: str): diff --git a/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi b/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi index 1a0b5cad5db0..6cbc0bcf742c 100644 --- a/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi +++ b/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi @@ -1,9 +1,15 @@ import typing from cryptography.hazmat.primitives import serialization +from cryptography.hazmat.primitives.serialization import pkcs7 from cryptography import x509 def serialize_certificates( certs: typing.List[x509.Certificate], encoding: serialization.Encoding, ) -> bytes: ... +def sign_and_serialize( + builder: pkcs7.PKCS7SignatureBuilder, + encoding: serialization.Encoding, + options: typing.Iterable[pkcs7.PKCS7Options], +) -> bytes: ... diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index 1d3c7b124c03..a7a9e932b202 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -2,6 +2,10 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import email.base64mime +import email.generator +import email.message +import io import typing from cryptography import utils @@ -74,7 +78,7 @@ def set_data(self, data: bytes) -> "PKCS7SignatureBuilder": if self._data is not None: raise ValueError("data may only be set once") - return PKCS7SignatureBuilder(data, self._signers) + return PKCS7SignatureBuilder(bytes(data), self._signers) def add_signer( self, @@ -171,8 +175,46 @@ def sign( "both values." ) - from cryptography.hazmat.backends.openssl.backend import ( - backend as ossl, - ) - - return ossl.pkcs7_sign(self, encoding, options) + return rust_pkcs7.sign_and_serialize(self, encoding, options) + + +def _smime_encode(data, signature, micalg): + # This function works pretty hard to replicate what OpenSSL does + # precisely. For good and for ill. + + m = email.message.Message() + m.add_header("MIME-Version", "1.0") + m.add_header( + "Content-Type", + "multipart/signed", + protocol="application/x-pkcs7-signature", + micalg=micalg, + ) + + m.preamble = "This is an S/MIME signed message\n" + + msg_part = email.message.MIMEPart() + msg_part.set_payload(data) + msg_part.add_header("Content-Type", "text/plain") + m.attach(msg_part) + + sig_part = email.message.MIMEPart() + sig_part.add_header( + "Content-Type", "application/x-pkcs7-signature", name="smime.p7s" + ) + sig_part.add_header("Content-Transfer-Encoding", "base64") + sig_part.add_header( + "Content-Disposition", "attachment", filename="smime.p7s" + ) + sig_part.set_payload( + email.base64mime.body_encode(signature, maxlinelen=65) + ) + del sig_part["MIME-Version"] + m.attach(sig_part) + + fp = io.BytesIO() + g = email.generator.BytesGenerator( + fp, maxheaderlen=0, mangle_from_=False, policy=m.policy + ) + g.flatten(m) + return fp.getvalue() diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs index 079419c8f2e4..db5db88ec658 100644 --- a/src/rust/src/pkcs7.rs +++ b/src/rust/src/pkcs7.rs @@ -5,18 +5,41 @@ use crate::asn1::{encode_der_data, PyAsn1Result}; use crate::x509; +use chrono::Timelike; use once_cell::sync::Lazy; +use std::borrow::Cow; +use std::collections::HashMap; +use std::ops::Deref; const PKCS7_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 7, 1); const PKCS7_SIGNED_DATA_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 7, 2); +const PKCS7_CONTENT_TYPE_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 9, 3); +const PKCS7_MESSAGE_DIGEST_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 9, 4); +const PKCS7_SIGNING_TIME_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 9, 5); +const PKCS7_SMIME_CAP_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 9, 15); + +const AES_256_CBC_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 1, 42); +const AES_192_CBC_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 1, 22); +const AES_128_CBC_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 1, 2); + static EMPTY_STRING_DER: Lazy> = Lazy::new(|| { // TODO: kind of verbose way to say "\x04\x00". asn1::write_single(&(&[] as &[u8])).unwrap() }); -pub(crate) static EMPTY_STRING_TLV: Lazy> = +static EMPTY_STRING_TLV: Lazy> = Lazy::new(|| asn1::parse_single(&EMPTY_STRING_DER).unwrap()); +static OIDS_TO_MIC_NAME: Lazy> = Lazy::new(|| { + let mut h = HashMap::new(); + h.insert(&x509::oid::SHA1_OID, "sha1"); + h.insert(&x509::oid::SHA224_OID, "sha-224"); + h.insert(&x509::oid::SHA256_OID, "sha-256"); + h.insert(&x509::oid::SHA384_OID, "sha-384"); + h.insert(&x509::oid::SHA512_OID, "sha-512"); + h +}); + #[derive(asn1::Asn1Write)] struct ContentInfo<'a> { content_type: asn1::ObjectIdentifier, @@ -36,8 +59,28 @@ struct SignedData<'a> { #[implicit(1)] crls: Option>>, - // We don't ever supply any of these, so for now, don't fill out the fields. - signer_infos: asn1::SetOfWriter<'a, asn1::Sequence<'a>>, + signer_infos: asn1::SetOfWriter<'a, SignerInfo<'a>>, +} + +#[derive(asn1::Asn1Write)] +struct SignerInfo<'a> { + version: u8, + issuer_and_serial_number: IssuerAndSerialNumber<'a>, + digest_algorithm: x509::AlgorithmIdentifier<'a>, + #[implicit(0)] + authenticated_attributes: Option>, + + digest_encryption_algorithm: x509::AlgorithmIdentifier<'a>, + encrypted_digest: &'a [u8], + + #[implicit(1)] + unauthenticated_attributes: Option>, +} + +#[derive(asn1::Asn1Write)] +struct IssuerAndSerialNumber<'a> { + issuer: x509::Name<'a>, + serial_number: asn1::BigInt<'a>, } #[pyo3::prelude::pyfunction] @@ -81,10 +124,262 @@ fn serialize_certificates<'p>( encode_der_data(py, "PKCS7".to_string(), content_info_bytes, encoding) } +#[pyo3::prelude::pyfunction] +fn sign_and_serialize<'p>( + py: pyo3::Python<'p>, + builder: &'p pyo3::PyAny, + encoding: &'p pyo3::PyAny, + options: &'p pyo3::types::PyList, +) -> PyAsn1Result<&'p pyo3::types::PyBytes> { + let pkcs7_options = py + .import("cryptography.hazmat.primitives.serialization.pkcs7")? + .getattr(crate::intern!(py, "PKCS7Options"))?; + + let raw_data = builder.getattr(crate::intern!(py, "_data"))?.extract()?; + let data = if options.contains(pkcs7_options.getattr(crate::intern!(py, "Binary"))?)? { + Cow::Borrowed(raw_data) + } else { + smime_canonicalize( + raw_data, + options.contains(pkcs7_options.getattr(crate::intern!(py, "Text"))?)?, + ) + }; + + let content_type_bytes = asn1::write_single(&PKCS7_DATA_OID)?; + let signing_time_bytes = asn1::write_single(&x509::certificate::time_from_chrono( + chrono::Utc::now().with_nanosecond(0).unwrap(), + )?)?; + let smime_cap_bytes = asn1::write_single(&asn1::SequenceOfWriter::new([ + // Subset of values OpenSSL provides: + // https://github.com/openssl/openssl/blob/667a8501f0b6e5705fd611d5bb3ca24848b07154/crypto/pkcs7/pk7_smime.c#L150 + // removing all the ones that are bad cryptography + AES_256_CBC_OID, + AES_192_CBC_OID, + AES_128_CBC_OID, + ]))?; + + let py_signers: Vec<( + pyo3::PyRef<'p, x509::Certificate>, + &pyo3::PyAny, + &pyo3::PyAny, + )> = builder.getattr(crate::intern!(py, "_signers"))?.extract()?; + + let py_certs: Vec> = builder + .getattr(crate::intern!(py, "_additional_certs"))? + .extract()?; + + let mut signer_infos = vec![]; + let mut digest_algs = vec![]; + let mut certs = py_certs + .iter() + .map(|p| p.raw.borrow_value_public()) + .collect::>(); + for (cert, py_private_key, py_hash_alg) in &py_signers { + let (authenticated_attrs, signature) = if options + .contains(pkcs7_options.getattr(crate::intern!(py, "NoAttributes"))?)? + { + ( + None, + x509::sign::sign_data(py, py_private_key, py_hash_alg, &data)?, + ) + } else { + let mut authenticated_attrs = vec![]; + + authenticated_attrs.push(x509::csr::Attribute { + type_id: PKCS7_CONTENT_TYPE_OID, + values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([ + asn1::parse_single(&content_type_bytes).unwrap(), + ])), + }); + authenticated_attrs.push(x509::csr::Attribute { + type_id: PKCS7_SIGNING_TIME_OID, + values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([ + asn1::parse_single(&signing_time_bytes).unwrap(), + ])), + }); + + let digest = asn1::write_single(&x509::ocsp::hash_data(py, py_hash_alg, &data)?)?; + // Gross hack: copy to PyBytes to extend the lifetime to 'p + let digest_bytes = pyo3::types::PyBytes::new(py, &digest); + authenticated_attrs.push(x509::csr::Attribute { + type_id: PKCS7_MESSAGE_DIGEST_OID, + values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([ + asn1::parse_single(digest_bytes.as_bytes()).unwrap(), + ])), + }); + + if !options.contains(pkcs7_options.getattr(crate::intern!(py, "NoCapabilities"))?)? { + authenticated_attrs.push(x509::csr::Attribute { + type_id: PKCS7_SMIME_CAP_OID, + values: x509::Asn1ReadableOrWritable::new_write(asn1::SetOfWriter::new([ + asn1::parse_single(&smime_cap_bytes).unwrap(), + ])), + }); + } + + let signed_data = + asn1::write_single(&asn1::SetOfWriter::new(authenticated_attrs.as_slice()))?; + + ( + Some(x509::Asn1ReadableOrWritable::new_write( + asn1::SetOfWriter::new(authenticated_attrs), + )), + x509::sign::sign_data(py, py_private_key, py_hash_alg, &signed_data)?, + ) + }; + + let digest_alg = x509::AlgorithmIdentifier { + oid: x509::ocsp::HASH_NAME_TO_OIDS[py_hash_alg + .getattr(crate::intern!(py, "name"))? + .extract::<&str>()?] + .clone(), + params: Some(*x509::sign::NULL_TLV), + }; + // Technically O(n^2), but no one will have that many signers. + if !digest_algs.contains(&digest_alg) { + digest_algs.push(digest_alg.clone()); + } + certs.push(cert.raw.borrow_value_public()); + + signer_infos.push(SignerInfo { + version: 1, + issuer_and_serial_number: IssuerAndSerialNumber { + issuer: cert.raw.borrow_value_public().tbs_cert.issuer.clone(), + serial_number: cert.raw.borrow_value_public().tbs_cert.serial, + }, + digest_algorithm: digest_alg, + authenticated_attributes: authenticated_attrs, + digest_encryption_algorithm: x509::sign::compute_signature_algorithm( + py, + py_private_key, + py_hash_alg, + )?, + encrypted_digest: signature, + unauthenticated_attributes: None, + }); + } + + let data_tlv_bytes; + let content = + if options.contains(pkcs7_options.getattr(crate::intern!(py, "DetachedSignature"))?)? { + None + } else { + data_tlv_bytes = asn1::write_single(&data.deref())?; + Some(asn1::parse_single(&data_tlv_bytes).unwrap()) + }; + + let signed_data = SignedData { + version: 1, + digest_algorithms: asn1::SetOfWriter::new(&digest_algs), + content_info: ContentInfo { + content_type: PKCS7_DATA_OID, + content, + }, + certificates: if options.contains(pkcs7_options.getattr(crate::intern!(py, "NoCerts"))?)? { + None + } else { + Some(asn1::SetOfWriter::new(&certs)) + }, + crls: None, + signer_infos: asn1::SetOfWriter::new(&signer_infos), + }; + + let signed_data_bytes = asn1::write_single(&signed_data)?; + + let content_info = ContentInfo { + content_type: PKCS7_SIGNED_DATA_OID, + content: Some(asn1::parse_single(&signed_data_bytes).unwrap()), + }; + let content_info_bytes = asn1::write_single(&content_info)?; + + let encoding_class = py + .import("cryptography.hazmat.primitives.serialization")? + .getattr(crate::intern!(py, "Encoding"))?; + + if encoding == encoding_class.getattr(crate::intern!(py, "SMIME"))? { + let mic_algs = digest_algs + .iter() + .map(|d| OIDS_TO_MIC_NAME[&d.oid]) + .collect::>() + .join(","); + Ok(py + .import("cryptography.hazmat.primitives.serialization.pkcs7")? + .getattr(crate::intern!(py, "_smime_encode"))? + .call1(( + pyo3::types::PyBytes::new(py, &data), + pyo3::types::PyBytes::new(py, &content_info_bytes), + mic_algs, + ))? + .extract()?) + } else { + // Handles the DER, PEM, and error cases + encode_der_data(py, "PKCS7".to_string(), content_info_bytes, encoding) + } +} + +fn smime_canonicalize(data: &[u8], text_mode: bool) -> Cow<'_, [u8]> { + let mut new_data = vec![]; + if text_mode { + new_data.extend_from_slice(b"Content-Type: text/plain\r\n\r\n"); + } + + let mut last_idx = 0; + for (i, c) in data.iter().copied().enumerate() { + if c == b'\n' && (i == 0 || data[i - 1] != b'\r') { + new_data.extend_from_slice(&data[last_idx..i]); + new_data.push(b'\r'); + new_data.push(b'\n'); + last_idx = i + 1; + } + } + // If there's stuff in new_data, that means we need to copy the rest of + // data over. + if !new_data.is_empty() { + new_data.extend_from_slice(&data[last_idx..]); + Cow::Owned(new_data) + } else { + Cow::Borrowed(data) + } +} + pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::prelude::PyModule> { let submod = pyo3::prelude::PyModule::new(py, "pkcs7")?; submod.add_wrapped(pyo3::wrap_pyfunction!(serialize_certificates))?; + submod.add_wrapped(pyo3::wrap_pyfunction!(sign_and_serialize))?; Ok(submod) } + +#[cfg(test)] +mod tests { + use super::smime_canonicalize; + use std::borrow::Cow; + use std::ops::Deref; + + #[test] + fn test_smime_canonicalize() { + for (input, text_mode, expected, expected_is_borrowed) in [ + // Values with text_mode=false + (b"" as &[u8], false, b"" as &[u8], true), + (b"\n", false, b"\r\n", false), + (b"abc", false, b"abc", true), + (b"abc\r\ndef\n", false, b"abc\r\ndef\r\n", false), + (b"abc\r\n", false, b"abc\r\n", true), + (b"abc\ndef\n", false, b"abc\r\ndef\r\n", false), + // Values with text_mode=true + (b"", true, b"Content-Type: text/plain\r\n\r\n", false), + (b"abc", true, b"Content-Type: text/plain\r\n\r\nabc", false), + ( + b"abc\n", + true, + b"Content-Type: text/plain\r\n\r\nabc\r\n", + false, + ), + ] { + let result = smime_canonicalize(input, text_mode); + assert_eq!(result.deref(), expected); + assert_eq!(matches!(result, Cow::Borrowed(_)), expected_is_borrowed); + } + } +} From bf4a4914d41378e36206d97c20489c5a9c7aa81b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 25 Nov 2022 18:25:54 -0500 Subject: [PATCH 209/298] Refs #7843 -- update py36 deprecation message (#7844) --- src/cryptography/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index 599bf5169e5e..6c0fd2a62540 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -22,8 +22,9 @@ if sys.version_info[:2] == (3, 6): warnings.warn( "Python 3.6 is no longer supported by the Python core team. " - "Therefore, support for it is deprecated in cryptography and will be" - " removed in a future release.", + "Therefore, support for it is deprecated in cryptography. The next " + "release of cryptography (40.0) will be the last to support Python " + "3.6.", CryptographyDeprecationWarning, stacklevel=2, ) From 2c41ac461624662da1ad5249a045a7bf9803192b Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 25 Nov 2022 18:13:07 -0700 Subject: [PATCH 210/298] Bump BoringSSL and/or OpenSSL in CI (#7845) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b330aa5d3511..bf06e6fe72a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 24, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "2fd8de65347cebe9870b872e528658b922f61fe3"}} - # Latest commit on the OpenSSL master branch, as of Nov 25, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3f32d29ad464591ed968a1e430111e1525280f4c"}} + # Latest commit on the BoringSSL master branch, as of Nov 26, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "a880d2ac8261adca474f8682c5fe4420717e8d08"}} + # Latest commit on the OpenSSL master branch, as of Nov 26, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "667a8501f0b6e5705fd611d5bb3ca24848b07154"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 064d49dd08aa9f1269749839f9b39831f89bb8b6 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 26 Nov 2022 13:10:05 -0700 Subject: [PATCH 211/298] add job to automatically mark issues/PRs stale and close them (#7850) --- .github/workflows/auto-close-stale.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/auto-close-stale.yml diff --git a/.github/workflows/auto-close-stale.yml b/.github/workflows/auto-close-stale.yml new file mode 100644 index 000000000000..8684c30a776f --- /dev/null +++ b/.github/workflows/auto-close-stale.yml @@ -0,0 +1,23 @@ +name: Auto-close stale issues +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * *' + +permissions: + issues: "write" + pull-requests: "write" + +jobs: + auto-close: + if: github.repository_owner == 'pyca' + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v6.0.1 + with: + only-labels: waiting-on-reporter + days-before-stale: 5 + days-before-close: 7 + stale-issue-message: "This issue has been waiting for a reporter response for 5 days. It will be auto-closed if no activity occurs in the next week." + close-issue-message: "This issue has not received a reporter response and has been auto-closed. If the issue is still relevant please leave a comment and we can reopen it." + close-reason: completed From 0e21f57f4f18f2dbc6c018c8f5bc86144f36b3f8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Nov 2022 15:27:47 -0500 Subject: [PATCH 212/298] Revert "don't use flake8 6.0 (#7838)" (#7851) This reverts commit 169a803e0c4feece7b81eecefcd54a49d7ba4d31. --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 9c73cbc3becf..d42e78930c19 100644 --- a/setup.cfg +++ b/setup.cfg @@ -76,7 +76,7 @@ sdist = setuptools_rust >= 0.11.4 pep8test = black - flake8 != 6.0.0 + flake8 flake8-import-order pep8-naming # This extra is for OpenSSH private keys that use bcrypt KDF From fe5442c4a7c5bb03fe2204c246ea103e8e9004d9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 26 Nov 2022 18:00:44 -0500 Subject: [PATCH 213/298] update installation.rst for new CI OS (#7852) --- docs/installation.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/installation.rst b/docs/installation.rst index 145376f1bee7..9b46a7345c5c 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -17,6 +17,7 @@ Currently we test ``cryptography`` on Python 3.6+ and PyPy3 on these operating systems. * x86-64 RHEL 8.x +* x86-64 CentOS 9 Stream * x86-64 Fedora (latest) * x86-64 macOS 12 Monterey * ARM64 macOS 12 Monterey From 884c2cbe0a0c3af3c00aa91b8eea505ccf7de019 Mon Sep 17 00:00:00 2001 From: Nicola Tuveri Date: Sun, 27 Nov 2022 16:10:48 +0200 Subject: [PATCH 214/298] Update invalid EC key test for compatibility with upcoming OpenSSL changes (#7833) One of the tests checking behavior with invalid EC keys hardcoded the error reason. This commit replaces the string matching with a regex to match both the current string and a new reason, introduced by upcoming OpenSSL changes [0], which would otherwise trigger a false positive failure. [0]: https://github.com/openssl/openssl/pull/19681 --- tests/hazmat/primitives/test_ec.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 6022b95022f7..3d488be1720c 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -411,7 +411,9 @@ def test_load_invalid_ec_key_from_pem(self, backend): # BoringSSL rejects infinity points before it ever gets to us, so it # uses a more generic error message. match = ( - "infinity" if not backend._lib.CRYPTOGRAPHY_IS_BORINGSSL else None + r"infinity|invalid form" + if not backend._lib.CRYPTOGRAPHY_IS_BORINGSSL + else None ) with pytest.raises(ValueError, match=match): serialization.load_pem_public_key( From b1d881c17e1654af0272894025922bbba7c0fb58 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 27 Nov 2022 12:18:48 -0700 Subject: [PATCH 215/298] port 38.0.4 changelog to main (#7855) --- CHANGELOG.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1e22b2417ba8..c2a29955b77c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -43,6 +43,15 @@ Changelog * Added support for creating OCSP requests with precomputed hashes using :meth:`~cryptography.x509.ocsp.OCSPRequestBuilder.add_certificate_by_hash`. +.. _v38-0-4: + +38.0.4 - 2022-11-27 +~~~~~~~~~~~~~~~~~~~ + +* Fixed compilation when using LibreSSL 3.6.0. +* Fixed error when using ``py2app`` to build an application with a + ``cryptography`` dependency. + .. _v38-0-3: 38.0.3 - 2022-11-01 From 49530e1036198a1401ec4b1af950f02cb31733b2 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 27 Nov 2022 15:39:19 -0500 Subject: [PATCH 216/298] Bump rust-asn1 to 0.13 (#7856) --- src/rust/Cargo.lock | 8 ++++---- src/rust/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 77140edec8be..08861fb8d371 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -25,9 +25,9 @@ dependencies = [ [[package]] name = "asn1" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a53789014a5231ee21e6af6d89d42680d73db33ad2ec83ee6fad801249432bad" +checksum = "2affba5e62ee09eeba078f01a00c4aed45ac4287e091298eccbb0d4802efbdc5" dependencies = [ "asn1_derive", "chrono", @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "asn1_derive" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a08da126b90ce7a577f8e6986513dea0243c114d7d5d88abece6168b0823db" +checksum = "bfab79c195875e5aef2bd20b4c8ed8d43ef9610bcffefbbcf66f88f555cc78af" dependencies = [ "proc-macro2", "quote", diff --git a/src/rust/Cargo.toml b/src/rust/Cargo.toml index 82573dd9f142..d557fc049375 100644 --- a/src/rust/Cargo.toml +++ b/src/rust/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] once_cell = "1" pyo3 = { version = "0.15.2" } -asn1 = { version = "0.12.3", default-features = false, features = ["derive"] } +asn1 = { version = "0.13.0", default-features = false } pem = "1.1" chrono = { version = "0.4.22", default-features = false, features = ["alloc", "clock"] } ouroboros = "0.15" From a125b129b40e0883ea9a57813c010ed0bec0173a Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 00:19:13 +0000 Subject: [PATCH 217/298] Bump BoringSSL and/or OpenSSL in CI (#7857) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bf06e6fe72a8..113d6b7e9d53 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,8 +38,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 26, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "a880d2ac8261adca474f8682c5fe4420717e8d08"}} + # Latest commit on the BoringSSL master branch, as of Nov 28, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "7ab49bf0af78e4b068822f8cd8b4f0fa6bbb4bc0"}} # Latest commit on the OpenSSL master branch, as of Nov 26, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "667a8501f0b6e5705fd611d5bb3ca24848b07154"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" From 769a2cd302e26d353812cd9f15f4a952e8a7d017 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 12:16:03 +0000 Subject: [PATCH 218/298] Bump dtolnay/rust-toolchain (#7858) Bumps [dtolnay/rust-toolchain](https://github.com/dtolnay/rust-toolchain) from 55c7845fad90d0ae8b2e83715cb900e5e861e8cb to e645b0cf01249a964ec099494d38d2da0f0b349f. - [Release notes](https://github.com/dtolnay/rust-toolchain/releases) - [Commits](https://github.com/dtolnay/rust-toolchain/compare/55c7845fad90d0ae8b2e83715cb900e5e861e8cb...e645b0cf01249a964ec099494d38d2da0f0b349f) --- updated-dependencies: - dependency-name: dtolnay/rust-toolchain dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 4 ++-- .github/workflows/wheel-builder.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 113d6b7e9d53..cae349b80f98 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -223,7 +223,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb + - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f with: toolchain: ${{ matrix.RUST }} - uses: actions/checkout@v3.1.0 @@ -275,7 +275,7 @@ jobs: uses: actions/setup-python@v4.3.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb + - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f with: toolchain: ${{ matrix.RUST }} components: llvm-tools-preview diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index e25c1f749552..2aa077a85e2f 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -178,7 +178,7 @@ jobs: ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-universal2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb + - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f with: toolchain: stable # Add the arm64 target in addition to the native arch (x86_64) @@ -250,7 +250,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: dtolnay/rust-toolchain@55c7845fad90d0ae8b2e83715cb900e5e861e8cb + - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f with: toolchain: stable target: ${{ matrix.WINDOWS.RUST_TRIPLE }} From 39b96a1430429ee3b06b611e1f55d3bca82ae7b3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 12:16:25 +0000 Subject: [PATCH 219/298] Bump peter-evans/create-pull-request from 4.2.2 to 4.2.3 (#7859) Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 4.2.2 to 4.2.3. - [Release notes](https://github.com/peter-evans/create-pull-request/releases) - [Commits](https://github.com/peter-evans/create-pull-request/compare/331d02c7e2104af23ad5974d4d5cbc58a3e6dc77...2b011faafdcbc9ceb11414d64d0573f37c774b04) --- updated-dependencies: - dependency-name: peter-evans/create-pull-request dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/boring-open-version-bump.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index a218c4578cbf..251226e7c61b 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -58,7 +58,7 @@ jobs: private_key: ${{ secrets.BORINGBOT_PRIVATE_KEY }} if: steps.check-sha-boring.outputs.COMMIT_SHA || steps.check-sha-openssl.outputs.COMMIT_SHA - name: Create Pull Request - uses: peter-evans/create-pull-request@331d02c7e2104af23ad5974d4d5cbc58a3e6dc77 + uses: peter-evans/create-pull-request@2b011faafdcbc9ceb11414d64d0573f37c774b04 with: commit-message: "Bump BoringSSL and/or OpenSSL in CI" title: "Bump BoringSSL and/or OpenSSL in CI" From 0bd7ca9a46e25895b1bcafa8093733c580d19859 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Nov 2022 12:28:32 +0000 Subject: [PATCH 220/298] Bump syn from 1.0.103 to 1.0.104 in /src/rust (#7860) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.103 to 1.0.104. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.103...1.0.104) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 08861fb8d371..db68fbb05800 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -489,9 +489,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" dependencies = [ "proc-macro2", "quote", From 5a00c3389f670b74c5ff9c9fe3e2d03dd4352b53 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 28 Nov 2022 08:31:10 -0500 Subject: [PATCH 221/298] use the correct param name in stale action (#7861) --- .github/workflows/auto-close-stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-close-stale.yml b/.github/workflows/auto-close-stale.yml index 8684c30a776f..48ebd8e571f7 100644 --- a/.github/workflows/auto-close-stale.yml +++ b/.github/workflows/auto-close-stale.yml @@ -20,4 +20,4 @@ jobs: days-before-close: 7 stale-issue-message: "This issue has been waiting for a reporter response for 5 days. It will be auto-closed if no activity occurs in the next week." close-issue-message: "This issue has not received a reporter response and has been auto-closed. If the issue is still relevant please leave a comment and we can reopen it." - close-reason: completed + close-issue-reason: completed From 21225b4cbbf842d68e7086660e5caa45a8ecf31d Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 29 Nov 2022 00:23:02 +0000 Subject: [PATCH 222/298] Bump BoringSSL and/or OpenSSL in CI (#7862) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cae349b80f98..eed63c107dc9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 28, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "7ab49bf0af78e4b068822f8cd8b4f0fa6bbb4bc0"}} - # Latest commit on the OpenSSL master branch, as of Nov 26, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "667a8501f0b6e5705fd611d5bb3ca24848b07154"}} + # Latest commit on the BoringSSL master branch, as of Nov 29, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "de434576d7412b95a8eb90d613fc9f01e2d7166b"}} + # Latest commit on the OpenSSL master branch, as of Nov 29, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "055d029610712a281aed0c23ddd3c8f4dbf40f80"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 622c98349e2e21c209385624ce95d60e5bf46929 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 30 Nov 2022 00:25:05 +0000 Subject: [PATCH 223/298] Bump BoringSSL and/or OpenSSL in CI (#7864) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index eed63c107dc9..7dde02f1c1c6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 29, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "de434576d7412b95a8eb90d613fc9f01e2d7166b"}} - # Latest commit on the OpenSSL master branch, as of Nov 29, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "055d029610712a281aed0c23ddd3c8f4dbf40f80"}} + # Latest commit on the BoringSSL master branch, as of Nov 30, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "e40d0f8ee1361fbff2927a6806c755acea79a521"}} + # Latest commit on the OpenSSL master branch, as of Nov 30, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "4a7231df5ca9f3d8759dc8c22cb8e9f27b312024"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 6909cda39cf94346f405a277df62317da05a3c08 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 30 Nov 2022 20:28:16 -0500 Subject: [PATCH 224/298] Bump BoringSSL and/or OpenSSL in CI (#7866) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7dde02f1c1c6..a61fe7c25ecc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Nov 30, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "e40d0f8ee1361fbff2927a6806c755acea79a521"}} - # Latest commit on the OpenSSL master branch, as of Nov 30, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "4a7231df5ca9f3d8759dc8c22cb8e9f27b312024"}} + # Latest commit on the BoringSSL master branch, as of Dec 01, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "afbd7cf2ae197bfe83163ba47d1be7960a6cb4ba"}} + # Latest commit on the OpenSSL master branch, as of Dec 01, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "6ea44d07a7d0acb4af9eab15d9b4a76227f55f4e"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From ab2aff3b43a7ee7b49acad7aa7ab71b2ac3e6a75 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 30 Nov 2022 20:40:48 -0500 Subject: [PATCH 225/298] be careful to only publish wheels from the right CI run (#7865) --- release.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release.py b/release.py index 79ba0b7bc489..e7445d951d8f 100644 --- a/release.py +++ b/release.py @@ -82,8 +82,8 @@ def fetch_github_actions_artifacts(token, version): response = session.get( ( - "https://api.github.com/repos/pyca/cryptography/actions/workflows/" - "wheel-builder.yml/runs?event=push" + f"https://api.github.com/repos/pyca/cryptography/actions" + f"/workflows/wheel-builder.yml/runs?event=push&branch={version}" ), headers={ "Content-Type": "application/json", From 420075c4feb66919a6c8a42af00a8055d536705b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 1 Dec 2022 12:35:04 +0000 Subject: [PATCH 226/298] Bump syn from 1.0.104 to 1.0.105 in /src/rust (#7867) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.104 to 1.0.105. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.104...1.0.105) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index db68fbb05800..211108ec0519 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -489,9 +489,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae548ec36cf198c0ef7710d3c230987c2d6d7bd98ad6edc0274462724c585ce" +checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", From 2066c7ffff6d2c5969a61c3894c2599f99ff61a9 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 2 Dec 2022 00:19:29 +0000 Subject: [PATCH 227/298] Bump BoringSSL and/or OpenSSL in CI (#7869) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a61fe7c25ecc..4b30c500c391 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 01, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "afbd7cf2ae197bfe83163ba47d1be7960a6cb4ba"}} - # Latest commit on the OpenSSL master branch, as of Dec 01, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "6ea44d07a7d0acb4af9eab15d9b4a76227f55f4e"}} + # Latest commit on the BoringSSL master branch, as of Dec 02, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "7ad733c81abbf1d6bb7df67b886b7e4a49e08a6d"}} + # Latest commit on the OpenSSL master branch, as of Dec 02, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "14c593e0034ddb9ca68f4a8e06b251afa127c6d0"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 3133cd7571907ca8d5d4ca197acf5633b862cc37 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 3 Dec 2022 00:18:21 +0000 Subject: [PATCH 228/298] Bump BoringSSL and/or OpenSSL in CI (#7871) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4b30c500c391..5be6e3dcfc84 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 02, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "7ad733c81abbf1d6bb7df67b886b7e4a49e08a6d"}} - # Latest commit on the OpenSSL master branch, as of Dec 02, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "14c593e0034ddb9ca68f4a8e06b251afa127c6d0"}} + # Latest commit on the BoringSSL master branch, as of Dec 03, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "9211b80f1e4d66982b17134b61f11db1b8a8a192"}} + # Latest commit on the OpenSSL master branch, as of Dec 03, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "328dc33365f8bd9c097bc95c3632467f690502a4"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 0170ca91c2b70408e07317a7b9dffbe81c5d0b9d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Dec 2022 05:01:52 +0000 Subject: [PATCH 229/298] Bump cxx from 1.0.82 to 1.0.83 in /src/rust (#7872) Bumps [cxx](https://github.com/dtolnay/cxx) from 1.0.82 to 1.0.83. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.82...1.0.83) --- updated-dependencies: - dependency-name: cxx dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 211108ec0519..68b022de2b25 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a41a86530d0fe7f5d9ea779916b7cadd2d4f9add748b99c2c029cbbdfaf453" +checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" dependencies = [ "cc", "cxxbridge-flags", @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "820a9a2af1669deeef27cb271f476ffd196a2c4b6731336011e0ba63e2c7cf71" +checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" [[package]] name = "cxxbridge-macro" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08a6e2fcc370a089ad3b4aaf54db3b1b4cee38ddabce5896b33eb693275f470" +checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" dependencies = [ "proc-macro2", "quote", From 8fcc2526d3a0b9b479e28a530f539c2a92a3dad7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Dec 2022 05:09:04 +0000 Subject: [PATCH 230/298] Bump cxx-build from 1.0.82 to 1.0.83 in /src/rust (#7873) Bumps [cxx-build](https://github.com/dtolnay/cxx) from 1.0.82 to 1.0.83. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.82...1.0.83) --- updated-dependencies: - dependency-name: cxx-build dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 68b022de2b25..1eee33fd3d97 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06416d667ff3e3ad2df1cd8cd8afae5da26cf9cec4d0825040f88b5ca659a2f0" +checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" dependencies = [ "cc", "codespan-reporting", From 28d7fe3bd049b17ea4f81a89a1f5a1974c01aa87 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 3 Dec 2022 05:16:20 +0000 Subject: [PATCH 231/298] Bump libc from 0.2.137 to 0.2.138 in /src/rust (#7874) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.137 to 0.2.138. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.137...0.2.138) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 1eee33fd3d97..87a866078f9b 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "link-cplusplus" From 5302b2ad5829d17f4a194faafeb289eaa38b266c Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sun, 4 Dec 2022 00:22:48 +0000 Subject: [PATCH 232/298] Bump BoringSSL and/or OpenSSL in CI (#7875) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5be6e3dcfc84..d98773e4920e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 03, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "9211b80f1e4d66982b17134b61f11db1b8a8a192"}} - # Latest commit on the OpenSSL master branch, as of Dec 03, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "328dc33365f8bd9c097bc95c3632467f690502a4"}} + # Latest commit on the BoringSSL master branch, as of Dec 04, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "02f7705dff4c75439fe75e7e34086ebb3a82c2db"}} + # Latest commit on the OpenSSL master branch, as of Dec 04, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "269ad8d571e68513175fdc66227943786353cfa8"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1e9513ec7cbae7b9f89f66394b1397c9c07a427e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 4 Dec 2022 17:40:34 -0500 Subject: [PATCH 233/298] Annotate a few more functions (#7876) --- src/cryptography/fernet.py | 2 +- src/cryptography/hazmat/bindings/_rust/__init__.pyi | 8 +++++++- src/cryptography/hazmat/primitives/ciphers/aead.py | 2 +- src/cryptography/hazmat/primitives/ciphers/base.py | 2 +- src/cryptography/hazmat/primitives/cmac.py | 2 +- src/cryptography/hazmat/primitives/hashes.py | 2 +- src/cryptography/hazmat/primitives/serialization/pkcs7.py | 2 +- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/cryptography/fernet.py b/src/cryptography/fernet.py index c18c3bcd0b67..a2601f80f680 100644 --- a/src/cryptography/fernet.py +++ b/src/cryptography/fernet.py @@ -28,7 +28,7 @@ def __init__( self, key: typing.Union[bytes, str], backend: typing.Any = None, - ): + ) -> None: try: key = base64.urlsafe_b64decode(key) except binascii.Error as exc: diff --git a/src/cryptography/hazmat/bindings/_rust/__init__.pyi b/src/cryptography/hazmat/bindings/_rust/__init__.pyi index c33769054b40..94a37a20aa96 100644 --- a/src/cryptography/hazmat/bindings/_rust/__init__.pyi +++ b/src/cryptography/hazmat/bindings/_rust/__init__.pyi @@ -2,6 +2,7 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. +import types import typing def check_pkcs7_padding(data: bytes) -> bool: ... @@ -25,4 +26,9 @@ class FixedPool(typing.Generic[T]): class PoolAcquisition(typing.Generic[T]): def __enter__(self) -> T: ... - def __exit__(self, exc_type, exc_value, exc_tb) -> None: ... + def __exit__( + self, + exc_type: typing.Optional[typing.Type[BaseException]], + exc_value: typing.Optional[BaseException], + exc_tb: typing.Optional[types.TracebackType], + ) -> None: ... diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index 16c97a644440..567301acc705 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -363,7 +363,7 @@ def decrypt( def _check_params( self, data: bytes, - associated_data: typing.List, + associated_data: typing.List[bytes], ) -> None: utils._check_bytes("data", data) if len(data) == 0: diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 2ea7fc63c54d..7af305249fbe 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -80,7 +80,7 @@ def __init__( algorithm: CipherAlgorithm, mode: Mode, backend: typing.Any = None, - ): + ) -> None: if not isinstance(algorithm, CipherAlgorithm): raise TypeError("Expected interface of CipherAlgorithm.") diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py index e08d65e121fb..1ec756a8ef54 100644 --- a/src/cryptography/hazmat/primitives/cmac.py +++ b/src/cryptography/hazmat/primitives/cmac.py @@ -24,7 +24,7 @@ def __init__( algorithm: ciphers.BlockCipherAlgorithm, backend: typing.Any = None, ctx: typing.Optional["_CMACContext"] = None, - ): + ) -> None: if not isinstance(algorithm, ciphers.BlockCipherAlgorithm): raise TypeError("Expected instance of BlockCipherAlgorithm.") self._algorithm = algorithm diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index cc0771d47e3e..ba22a6646c01 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -72,7 +72,7 @@ def __init__( algorithm: HashAlgorithm, backend: typing.Any = None, ctx: typing.Optional["HashContext"] = None, - ): + ) -> None: if not isinstance(algorithm, HashAlgorithm): raise TypeError("Expected instance of hashes.HashAlgorithm.") self._algorithm = algorithm diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index a7a9e932b202..5eaeab388309 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -178,7 +178,7 @@ def sign( return rust_pkcs7.sign_and_serialize(self, encoding, options) -def _smime_encode(data, signature, micalg): +def _smime_encode(data: bytes, signature: bytes, micalg: str) -> bytes: # This function works pretty hard to replicate what OpenSSL does # precisely. For good and for ill. From 15e6acf4e383e23ec4906f64280b42ec05e0c4bd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 4 Dec 2022 15:38:51 -0800 Subject: [PATCH 234/298] a few more mypy flags and fixes (#7877) --- pyproject.toml | 2 ++ src/cryptography/hazmat/backends/openssl/ed25519.py | 2 +- src/cryptography/hazmat/backends/openssl/ed448.py | 2 +- src/cryptography/hazmat/backends/openssl/x25519.py | 2 +- src/cryptography/hazmat/backends/openssl/x448.py | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 01b8ace8c8fa..0fa34fb55a4d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,6 +27,8 @@ check_untyped_defs = true no_implicit_reexport = true warn_redundant_casts = true warn_unused_ignores = true +warn_unused_configs = true +strict_equality = true [[tool.mypy.overrides]] module = [ diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py index 5cfdffb7b14d..0ed69245ab48 100644 --- a/src/cryptography/hazmat/backends/openssl/ed25519.py +++ b/src/cryptography/hazmat/backends/openssl/ed25519.py @@ -124,7 +124,7 @@ def private_bytes( ) -> bytes: if ( encoding is serialization.Encoding.Raw - or format is serialization.PublicFormat.Raw + or format is serialization.PrivateFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw diff --git a/src/cryptography/hazmat/backends/openssl/ed448.py b/src/cryptography/hazmat/backends/openssl/ed448.py index dad93c6c5d72..0d27ea638ad6 100644 --- a/src/cryptography/hazmat/backends/openssl/ed448.py +++ b/src/cryptography/hazmat/backends/openssl/ed448.py @@ -125,7 +125,7 @@ def private_bytes( ) -> bytes: if ( encoding is serialization.Encoding.Raw - or format is serialization.PublicFormat.Raw + or format is serialization.PrivateFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw diff --git a/src/cryptography/hazmat/backends/openssl/x25519.py b/src/cryptography/hazmat/backends/openssl/x25519.py index c09a50ac59ba..e3b41eced1a5 100644 --- a/src/cryptography/hazmat/backends/openssl/x25519.py +++ b/src/cryptography/hazmat/backends/openssl/x25519.py @@ -91,7 +91,7 @@ def private_bytes( ) -> bytes: if ( encoding is serialization.Encoding.Raw - or format is serialization.PublicFormat.Raw + or format is serialization.PrivateFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw diff --git a/src/cryptography/hazmat/backends/openssl/x448.py b/src/cryptography/hazmat/backends/openssl/x448.py index f45db56e93c4..d738188c71f7 100644 --- a/src/cryptography/hazmat/backends/openssl/x448.py +++ b/src/cryptography/hazmat/backends/openssl/x448.py @@ -86,7 +86,7 @@ def private_bytes( ) -> bytes: if ( encoding is serialization.Encoding.Raw - or format is serialization.PublicFormat.Raw + or format is serialization.PrivateFormat.Raw ): if ( format is not serialization.PrivateFormat.Raw From 7b79a46df1c79db35571fbb11f9764d4dd4c3cad Mon Sep 17 00:00:00 2001 From: William Woodruff Date: Sun, 4 Dec 2022 18:20:11 -0800 Subject: [PATCH 235/298] x509: add `load_pem_x509_certificates` (#7878) * x509: add `load_pem_x509_certificates` This behaves similarly to `load_pem_x509_certificate`, except that it returns a list of loaded certificates instead of just the first X.509 certificate. It raises if the input contains no PEM-encoded certificates, or if PEM or certificate parsing fail. Signed-off-by: William Woodruff * tests/x509: blacken Signed-off-by: William Woodruff * Update docs/x509/reference.rst Co-authored-by: Alex Gaynor * tests/x509: assert each item in the list is actually a certificate Signed-off-by: William Woodruff * bindings: expose `load_pem_x509_certificates` in `x509.pyi` Signed-off-by: William Woodruff * tests/x509: test the structure of each cert a bit This has the transitive effect of establishing a fixed order. Signed-off-by: William Woodruff * CHANGELOG: record changes Signed-off-by: William Woodruff * docs: add PEM to spellcheck allowlist Signed-off-by: William Woodruff * docs/x509: document expected param Signed-off-by: William Woodruff Signed-off-by: William Woodruff Co-authored-by: Alex Gaynor --- CHANGELOG.rst | 2 + docs/development/test-vectors.rst | 2 + docs/spelling_wordlist.txt | 1 + docs/x509/reference.rst | 16 +++++ .../hazmat/bindings/_rust/x509.pyi | 3 + src/cryptography/x509/__init__.py | 2 + src/cryptography/x509/base.py | 4 ++ src/rust/src/x509/certificate.rs | 16 +++++ tests/x509/test_x509.py | 25 +++++++ .../cryptography.io.chain_with_garbage.pem | 69 +++++++++++++++++++ 10 files changed, 140 insertions(+) create mode 100644 vectors/cryptography_vectors/x509/cryptography.io.chain_with_garbage.pem diff --git a/CHANGELOG.rst b/CHANGELOG.rst index c2a29955b77c..fce205de1c37 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -42,6 +42,8 @@ Changelog when repeatedly calling ``encrypt`` or ``decrypt`` with the same key. * Added support for creating OCSP requests with precomputed hashes using :meth:`~cryptography.x509.ocsp.OCSPRequestBuilder.add_certificate_by_hash`. +* Added support for loading multiple PEM-encoded X.509 certificates from + a single input via :func:`~cryptography.x509.load_pem_x509_certificates`. .. _v38-0-4: diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 121b2155d51e..256ee9d9a4c7 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -220,6 +220,8 @@ X.509 legacy PEM header format. * ``cryptography.io.chain.pem`` - The same as ``cryptography.io.pem``, but ``rapidssl_sha256_ca_g3.pem`` is concatenated to the end. +* ``cryptography.io.chain_with_garbage.pem`` - The same as + ``cryptography.io.chain.pem``, but with other sections and text around it. * ``cryptography.io.with_garbage.pem`` - The same as ``cryptography.io.pem``, but with other sections and text around it. * ``rapidssl_sha256_ca_g3.pem`` - The intermediate CA that issued the diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index 56a9ac881211..13e1fa1dd095 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -91,6 +91,7 @@ personalization RHEL parsers Parsers +PEM pickleable plaintext Poly diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 28069e89afb8..2c5ff50a9e0f 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -168,6 +168,22 @@ Loading Certificates >>> cert.serial_number 2 +.. function:: load_pem_x509_certificates(data) + + .. versionadded:: 39.0 + + Deserialize one or more certificates from PEM encoded data. + + This is like :func:`~cryptography.x509.load_pem_x509_certificate`, but + allows for loading multiple certificates (as adjacent PEMs) at once. + + :param bytes data: One or more PEM-encoded certificates. + + :returns: list of :class:`~cryptography.x509.Certificate` + + :raises ValueError: If there isn't at least one certificate, or if any + certificate is malformed. + .. function:: load_der_x509_certificate(data) .. versionadded:: 0.7 diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index 317deb6e7b96..d92ea6c6a1d7 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -10,6 +10,9 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES def load_pem_x509_certificate(data: bytes) -> x509.Certificate: ... +def load_pem_x509_certificates( + data: bytes, +) -> typing.List[x509.Certificate]: ... def load_der_x509_certificate(data: bytes) -> x509.Certificate: ... def load_pem_x509_crl(data: bytes) -> x509.CertificateRevocationList: ... def load_der_x509_crl(data: bytes) -> x509.CertificateRevocationList: ... diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index 906075d11796..b3f6e608f8e4 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -22,6 +22,7 @@ load_der_x509_crl, load_der_x509_csr, load_pem_x509_certificate, + load_pem_x509_certificates, load_pem_x509_crl, load_pem_x509_csr, random_serial_number, @@ -169,6 +170,7 @@ __all__ = [ "certificate_transparency", "load_pem_x509_certificate", + "load_pem_x509_certificates", "load_der_x509_certificate", "load_pem_x509_csr", "load_der_x509_csr", diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 9f6c41af272b..9c0aad53035b 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -521,6 +521,10 @@ def load_pem_x509_certificate( return rust_x509.load_pem_x509_certificate(data) +def load_pem_x509_certificates(data: bytes) -> typing.List[Certificate]: + return rust_x509.load_pem_x509_certificates(data) + + # Backend argument preserved for API compatibility, but ignored. def load_der_x509_certificate( data: bytes, backend: typing.Any = None diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs index e2879b9475ce..92e522f45ffe 100644 --- a/src/rust/src/x509/certificate.rs +++ b/src/rust/src/x509/certificate.rs @@ -350,6 +350,21 @@ fn load_pem_x509_certificate(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result< load_der_x509_certificate(py, &parsed.contents) } +#[pyo3::prelude::pyfunction] +fn load_pem_x509_certificates(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result> { + let certs = pem::parse_many(data)? + .iter() + .filter(|p| p.tag == "CERTIFICATE" || p.tag == "X509 CERTIFICATE") + .map(|p| load_der_x509_certificate(py, &p.contents)) + .collect::, _>>()?; + + if certs.is_empty() { + return Err(PyAsn1Error::from(pem::PemError::MalformedFraming)); + } + + Ok(certs) +} + #[pyo3::prelude::pyfunction] fn load_der_x509_certificate(py: pyo3::Python<'_>, data: &[u8]) -> PyAsn1Result { let raw = OwnedRawCertificate::try_new(Arc::from(data), |data| asn1::parse_single(data))?; @@ -1022,6 +1037,7 @@ pub(crate) fn set_bit(vals: &mut [u8], n: usize, set: bool) { pub(crate) fn add_to_module(module: &pyo3::prelude::PyModule) -> pyo3::PyResult<()> { module.add_wrapped(pyo3::wrap_pyfunction!(load_der_x509_certificate))?; module.add_wrapped(pyo3::wrap_pyfunction!(load_pem_x509_certificate))?; + module.add_wrapped(pyo3::wrap_pyfunction!(load_pem_x509_certificates))?; module.add_wrapped(pyo3::wrap_pyfunction!(create_x509_certificate))?; module.add_class::()?; diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 196eab7d0302..8a92c297c96d 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -5777,3 +5777,28 @@ def test_no_attributes(self, backend): backend, ) assert len(request.attributes) == 0 + + +def test_load_pem_x509_certificates(): + with pytest.raises(ValueError): + x509.load_pem_x509_certificates(b"") + + certs = load_vectors_from_file( + filename=os.path.join("x509", "cryptography.io.chain.pem"), + loader=lambda pemfile: x509.load_pem_x509_certificates(pemfile.read()), + mode="rb", + ) + assert len(certs) == 2 + assert certs[0].serial_number == 16160 + assert certs[1].serial_number == 146039 + + certs = load_vectors_from_file( + filename=os.path.join( + "x509", "cryptography.io.chain_with_garbage.pem" + ), + loader=lambda pemfile: x509.load_pem_x509_certificates(pemfile.read()), + mode="rb", + ) + assert len(certs) == 2 + assert certs[0].serial_number == 16160 + assert certs[1].serial_number == 146039 diff --git a/vectors/cryptography_vectors/x509/cryptography.io.chain_with_garbage.pem b/vectors/cryptography_vectors/x509/cryptography.io.chain_with_garbage.pem new file mode 100644 index 000000000000..7a06f8d2a572 --- /dev/null +++ b/vectors/cryptography_vectors/x509/cryptography.io.chain_with_garbage.pem @@ -0,0 +1,69 @@ +... some garbage here ... + +-----BEGIN CERTIFICATE----- +MIIFvTCCBKWgAwIBAgICPyAwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UEBhMCVVMx +FjAUBgNVBAoTDUdlb1RydXN0IEluYy4xIDAeBgNVBAMTF1JhcGlkU1NMIFNIQTI1 +NiBDQSAtIEczMB4XDTE0MTAxNTEyMDkzMloXDTE4MTExNjAxMTUwM1owgZcxEzAR +BgNVBAsTCkdUNDg3NDI5NjUxMTAvBgNVBAsTKFNlZSB3d3cucmFwaWRzc2wuY29t +L3Jlc291cmNlcy9jcHMgKGMpMTQxLzAtBgNVBAsTJkRvbWFpbiBDb250cm9sIFZh +bGlkYXRlZCAtIFJhcGlkU1NMKFIpMRwwGgYDVQQDExN3d3cuY3J5cHRvZ3JhcGh5 +LmlvMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAom/FebKJIot7Sp3s +itG1sicpe3thCssjI+g1JDAS7I3GLVNmbms1DOdIIqwf01gZkzzXBN2+9sOnyRaR +PPfCe1jTr3dk2y6rPE559vPa1nZQkhlzlhMhlPyjaT+S7g4Tio4qV2sCBZU01DZJ +CaksfohN+5BNVWoJzTbOcrHOEJ+M8B484KlBCiSxqf9cyNQKru4W3bHaCVNVJ8eu +6i6KyhzLa0L7yK3LXwwXVs583C0/vwFhccGWsFODqD/9xHUzsBIshE8HKjdjDi7Y +3BFQzVUQFjBB50NSZfAA/jcdt1blxJouc7z9T8Oklh+V5DDBowgAsrT4b6Z2Fq6/ +r7D1GqivLK/ypUQmxq2WXWAUBb/Q6xHgxASxI4Br+CByIUQJsm8L2jzc7k+mF4hW +ltAIUkbo8fGiVnat0505YJgxWEDKOLc4Gda6d/7GVd5AvKrz242bUqeaWo6e4MTx +diku2Ma3rhdcr044Qvfh9hGyjqNjvhWY/I+VRWgihU7JrYvgwFdJqsQ5eiKT4OHi +gsejvWwkZzDtiQ+aQTrzM1FsY2swJBJsLSX4ofohlVRlIJCn/ME+XErj553431Lu +YQ5SzMd3nXzN78Vj6qzTfMUUY72UoT1/AcFiUMobgIqrrmwuNxfrkbVE2b6Bga74 +FsJX63prvrJ41kuHK/16RQBM7fcCAwEAAaOCAWAwggFcMB8GA1UdIwQYMBaAFMOc +8/zTRgg0u85Gf6B8W/PiCMtZMFcGCCsGAQUFBwEBBEswSTAfBggrBgEFBQcwAYYT +aHR0cDovL2d2LnN5bWNkLmNvbTAmBggrBgEFBQcwAoYaaHR0cDovL2d2LnN5bWNi +LmNvbS9ndi5jcnQwDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMB +BggrBgEFBQcDAjAvBgNVHREEKDAmghN3d3cuY3J5cHRvZ3JhcGh5Lmlvgg9jcnlw +dG9ncmFwaHkuaW8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL2d2LnN5bWNiLmNv +bS9ndi5jcmwwDAYDVR0TAQH/BAIwADBFBgNVHSAEPjA8MDoGCmCGSAGG+EUBBzYw +LDAqBggrBgEFBQcCARYeaHR0cHM6Ly93d3cucmFwaWRzc2wuY29tL2xlZ2FsMA0G +CSqGSIb3DQEBCwUAA4IBAQAzIYO2jx7h17FBT74tJ2zbV9OKqGb7QF8y3wUtP4xc +dH80vprI/Cfji8s86kr77aAvAqjDjaVjHn7UzebhSUivvRPmfzRgyWBacomnXTSt +Xlt2dp2nDQuwGyK2vB7dMfKnQAkxwq1sYUXznB8i0IhhCAoXp01QGPKq51YoIlnF +7DRMk6iEaL1SJbkIrLsCQyZFDf0xtfW9DqXugMMLoxeCsBhZJQzNyS2ryirrv9LH +aK3+6IZjrcyy9bkpz/gzJucyhU+75c4My/mnRCrtItRbCQuiI5pd5poDowm+HH9i +GVI9+0lAFwxOUnOnwsoI40iOoxjLMGB+CgFLKCGUcWxP +-----END CERTIFICATE----- + +... some more garbage here ... + +-----BEGIN CERTIFICATE----- +MIIEJTCCAw2gAwIBAgIDAjp3MA0GCSqGSIb3DQEBCwUAMEIxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i +YWwgQ0EwHhcNMTQwODI5MjEzOTMyWhcNMjIwNTIwMjEzOTMyWjBHMQswCQYDVQQG +EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXUmFwaWRTU0wg +U0hBMjU2IENBIC0gRzMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCv +VJvZWF0eLFbG1eh/9H0WA//Qi1rkjqfdVC7UBMBdmJyNkA+8EGVf2prWRHzAn7Xp +SowLBkMEu/SW4ib2YQGRZjEiwzQ0Xz8/kS9EX9zHFLYDn4ZLDqP/oIACg8PTH2lS +1p1kD8mD5xvEcKyU58Okaiy9uJ5p2L4KjxZjWmhxgHsw3hUEv8zTvz5IBVV6s9cQ +DAP8m/0Ip4yM26eO8R5j3LMBL3+vV8M8SKeDaCGnL+enP/C1DPz1hNFTvA5yT2AM +QriYrRmIV9cE7Ie/fodOoyH5U/02mEiN1vi7SPIpyGTRzFRIU4uvt2UevykzKdkp +YEj4/5G8V1jlNS67abZZAgMBAAGjggEdMIIBGTAfBgNVHSMEGDAWgBTAephojYn7 +qwVkDBF9qn1luMrMTjAdBgNVHQ4EFgQUw5zz/NNGCDS7zkZ/oHxb8+IIy1kwEgYD +VR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAQYwNQYDVR0fBC4wLDAqoCig +JoYkaHR0cDovL2cuc3ltY2IuY29tL2NybHMvZ3RnbG9iYWwuY3JsMC4GCCsGAQUF +BwEBBCIwIDAeBggrBgEFBQcwAYYSaHR0cDovL2cuc3ltY2QuY29tMEwGA1UdIARF +MEMwQQYKYIZIAYb4RQEHNjAzMDEGCCsGAQUFBwIBFiVodHRwOi8vd3d3Lmdlb3Ry +dXN0LmNvbS9yZXNvdXJjZXMvY3BzMA0GCSqGSIb3DQEBCwUAA4IBAQCjWB7GQzKs +rC+TeLfqrlRARy1+eI1Q9vhmrNZPc9ZE768LzFvB9E+aj0l+YK/CJ8cW8fuTgZCp +fO9vfm5FlBaEvexJ8cQO9K8EWYOHDyw7l8NaEpt7BDV7o5UzCHuTcSJCs6nZb0+B +kvwHtnm8hEqddwnxxYny8LScVKoSew26T++TGezvfU5ho452nFnPjJSxhJf3GrkH +uLLGTxN5279PURt/aQ1RKsHWFf83UTRlUfQevjhq7A6rvz17OQV79PP7GqHQyH5O +ZI3NjGFVkP46yl0lD/gdo0p0Vk8aVUBwdSWmMy66S6VdU5oNMOGNX2Esr8zvsJmh +gP8L8mJMcCaY +-----END CERTIFICATE----- + +... and more garbage here... + +-----BEGIN PRIVATE KEY----- +aHR0cHM6Ly9iaXQubHkvM3VKOXpZZw== +-----END PRIVATE KEY----- From cb45eba45a86a3f83acf602dccc8b94ea91082b4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 07:50:46 -0800 Subject: [PATCH 236/298] Bump dessant/lock-threads from 3.0.0 to 4.0.0 (#7879) Bumps [dessant/lock-threads](https://github.com/dessant/lock-threads) from 3.0.0 to 4.0.0. - [Release notes](https://github.com/dessant/lock-threads/releases) - [Changelog](https://github.com/dessant/lock-threads/blob/master/CHANGELOG.md) - [Commits](https://github.com/dessant/lock-threads/compare/e460dfeb36e731f3aeb214be6b0c9a9d9a67eda6...c1b35aecc5cdb1a34539d14196df55838bb2f836) --- updated-dependencies: - dependency-name: dessant/lock-threads dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lock.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lock.yml b/.github/workflows/lock.yml index 972d0c75fb05..951b70546066 100644 --- a/.github/workflows/lock.yml +++ b/.github/workflows/lock.yml @@ -12,7 +12,7 @@ jobs: if: github.repository_owner == 'pyca' runs-on: ubuntu-latest steps: - - uses: dessant/lock-threads@e460dfeb36e731f3aeb214be6b0c9a9d9a67eda6 + - uses: dessant/lock-threads@c1b35aecc5cdb1a34539d14196df55838bb2f836 with: github-token: ${{ secrets.GITHUB_TOKEN }} issue-inactive-days: 90 From f6f504e111f956767a7410a810f7206b46ee64b0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 5 Dec 2022 19:17:33 -0500 Subject: [PATCH 237/298] remove unnecessary lifetime (#7880) clippy on nightly complains about it --- src/rust/src/x509/ocsp_resp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/src/x509/ocsp_resp.rs b/src/rust/src/x509/ocsp_resp.rs index ae2488ae7af2..90ced614cf9b 100644 --- a/src/rust/src/x509/ocsp_resp.rs +++ b/src/rust/src/x509/ocsp_resp.rs @@ -578,8 +578,8 @@ struct RevokedInfo { } #[pyo3::prelude::pyfunction] -fn create_ocsp_response<'p>( - py: pyo3::Python<'p>, +fn create_ocsp_response( + py: pyo3::Python<'_>, status: &pyo3::PyAny, builder: &pyo3::PyAny, private_key: &pyo3::PyAny, From c15e99ca947e523633879b673b15ba86c2281781 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Tue, 6 Dec 2022 00:23:36 +0000 Subject: [PATCH 238/298] Bump BoringSSL and/or OpenSSL in CI (#7881) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d98773e4920e..fbb5a9496912 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 04, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "02f7705dff4c75439fe75e7e34086ebb3a82c2db"}} - # Latest commit on the OpenSSL master branch, as of Dec 04, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "269ad8d571e68513175fdc66227943786353cfa8"}} + # Latest commit on the BoringSSL master branch, as of Dec 06, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "99eac424d84d34395c7eea7a90d419e23c00dfc2"}} + # Latest commit on the OpenSSL master branch, as of Dec 06, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "25d02f333b9a5531fa88db294f69a8347f275858"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 56ca71863d44f1e22ca112f697e095ecabaffd7a Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 7 Dec 2022 00:21:27 +0000 Subject: [PATCH 239/298] Bump BoringSSL and/or OpenSSL in CI (#7882) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fbb5a9496912..fa31c99dce47 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 06, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "99eac424d84d34395c7eea7a90d419e23c00dfc2"}} - # Latest commit on the OpenSSL master branch, as of Dec 06, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "25d02f333b9a5531fa88db294f69a8347f275858"}} + # Latest commit on the BoringSSL master branch, as of Dec 07, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "28f96c2686459add7acedcd97cb841030bdda019"}} + # Latest commit on the OpenSSL master branch, as of Dec 07, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "a63fa5f711f1f97e623348656b42717d6904ee3e"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 8fc5cfa6bbd5a1dc8e8d9d9d7fffccb91e8eaf6f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 8 Dec 2022 19:34:25 -0800 Subject: [PATCH 240/298] fixes for tox4 (#7887) * possibly fix tox4 * add a missing env we need to allow * lol how did this stuff ever work --- tox.ini | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 34ec06889ce7..546c6cdd6cb3 100644 --- a/tox.ini +++ b/tox.ini @@ -10,7 +10,22 @@ deps = -e ./vectors pytest-shard>=0.1.2 randomorder: pytest-randomly -passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH RUSTFLAGS CARGO_TARGET_DIR LLVM_PROFILE_FILE OPENSSL_FORCE_FIPS_MODE RUSTUP_TOOLCHAIN CRYPTOGRAPHY_OPENSSL_NO_LEGACY OPENSSL_ENABLE_SHA1_SIGNATURES +passenv = + ARCHFLAGS + LDFLAGS + CFLAGS + CL + INCLUDE + LIB + LD_LIBRARY_PATH + RUSTFLAGS + CARGO_TARGET_DIR + LLVM_PROFILE_FILE + OPENSSL_FORCE_FIPS_MODE + RUSTUP_TOOLCHAIN + CRYPTOGRAPHY_OPENSSL_NO_LEGACY + OPENSSL_ENABLE_SHA1_SIGNATURES + CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS commands = pip list !nocoverage: pytest -n auto --cov=cryptography --cov=tests --durations=10 {posargs} tests/ From 13988f580f661925148852ec5f4bb7ae477896d1 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 04:07:57 +0000 Subject: [PATCH 241/298] Bump BoringSSL and/or OpenSSL in CI (#7884) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa31c99dce47..a551ca9f9a9e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 07, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "28f96c2686459add7acedcd97cb841030bdda019"}} - # Latest commit on the OpenSSL master branch, as of Dec 07, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "a63fa5f711f1f97e623348656b42717d6904ee3e"}} + # Latest commit on the BoringSSL master branch, as of Dec 09, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "6ce77afa91bc0db1897cba8ce08188c804f908b1"}} + # Latest commit on the OpenSSL master branch, as of Dec 09, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "d5696547e46e9ea85fcb7581b9d49c58b7c24eeb"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From b1213f7a3d186b7b141b6d57585dca41fb196b7d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 9 Dec 2022 07:18:59 -0500 Subject: [PATCH 242/298] Bump actions/setup-python from 4.3.0 to 4.3.1 (#7888) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.3.0 to 4.3.1. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.3.0...v4.3.1) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/wheel-builder.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index d2f48250525c..964e8f5399e7 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -28,7 +28,7 @@ jobs: - name: Setup python id: setup-python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: "3.11" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a551ca9f9a9e..dfd64d26e060 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -51,7 +51,7 @@ jobs: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: actions/cache@v3.0.11 @@ -220,7 +220,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} - name: Setup python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f @@ -272,7 +272,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-rust-${{ matrix.RUST }}-coverage - name: Setup python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f @@ -357,7 +357,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} @@ -409,7 +409,7 @@ jobs: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} @@ -489,7 +489,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON }} - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install @@ -525,7 +525,7 @@ jobs: with: persist-credentials: false - name: Setup python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: 3.11 - run: python -m pip install -U tox @@ -549,7 +549,7 @@ jobs: jobs: ${{ toJSON(needs) }} - name: Setup python if: ${{ always() }} - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: '3.10' - run: pip install coverage[toml] diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 2aa077a85e2f..de896c292b56 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -168,7 +168,7 @@ jobs: PYTHON_DOWNLOAD_URL: ${{ matrix.PYTHON.DOWNLOAD_URL }} if: contains(matrix.PYTHON.VERSION, 'pypy') == false - name: Setup pypy - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} if: contains(matrix.PYTHON.VERSION, 'pypy') @@ -246,7 +246,7 @@ jobs: name: cryptography-sdist - name: Setup python - uses: actions/setup-python@v4.3.0 + uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} From 05baf6d17bc7f1e089d6d35787144f0ca7b5b2fc Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 10 Dec 2022 00:18:56 +0000 Subject: [PATCH 243/298] Bump BoringSSL and/or OpenSSL in CI (#7889) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfd64d26e060..23666634552e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,8 +38,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 09, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "6ce77afa91bc0db1897cba8ce08188c804f908b1"}} + # Latest commit on the BoringSSL master branch, as of Dec 10, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "d77fdbff010ee70776036c41155d1b3711ede548"}} # Latest commit on the OpenSSL master branch, as of Dec 09, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "d5696547e46e9ea85fcb7581b9d49c58b7c24eeb"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" From ded83199c0ac44b723a687f9efd0b726399e3e76 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sun, 11 Dec 2022 22:23:49 -0500 Subject: [PATCH 244/298] Bump BoringSSL and/or OpenSSL in CI (#7890) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23666634552e..958595a9fafe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Dec 10, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "d77fdbff010ee70776036c41155d1b3711ede548"}} - # Latest commit on the OpenSSL master branch, as of Dec 09, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "d5696547e46e9ea85fcb7581b9d49c58b7c24eeb"}} + # Latest commit on the OpenSSL master branch, as of Dec 12, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "efec0f4611ee854f2b0b3da0c135e839bf8e7d04"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From a4c750addab2903e07ce969d37a60ddc6448aecd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 12 Dec 2022 17:40:25 -0500 Subject: [PATCH 245/298] ignore speakerdeck on linkcheck (#7893) --- docs/conf.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/conf.py b/docs/conf.py index 8dc36102bd9d..dda20ca93c00 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -203,6 +203,8 @@ r"https://e-trust.gosuslugi.ru", # Incomplete cert chain r"https://www.oscca.gov.cn", + # Cloudflare returns 403s for all non-browser requests + r"https://speakerdeck.com", ] autosectionlabel_prefix_document = True From 254e80d65ab7cff1a52c9312415385c4ab0e4b83 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:14:58 +0000 Subject: [PATCH 246/298] Bump actions/checkout from 3.1.0 to 3.2.0 (#7896) Bumps [actions/checkout](https://github.com/actions/checkout) from 3.1.0 to 3.2.0. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3.1.0...v3.2.0) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark.yml | 4 +-- .../workflows/boring-open-version-bump.yml | 2 +- .github/workflows/ci.yml | 30 +++++++++---------- .github/workflows/macarm64.yml | 4 +-- .github/workflows/wheel-builder.yml | 6 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 964e8f5399e7..2cce7d6d3b06 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -14,12 +14,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false path: "cryptography-pr" - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "pyca/cryptography" diff --git a/.github/workflows/boring-open-version-bump.yml b/.github/workflows/boring-open-version-bump.yml index 251226e7c61b..4f84e07cbec3 100644 --- a/.github/workflows/boring-open-version-bump.yml +++ b/.github/workflows/boring-open-version-bump.yml @@ -13,7 +13,7 @@ jobs: if: github.repository_owner == 'pyca' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 - id: check-sha-boring run: | SHA=$(git ls-remote https://boringssl.googlesource.com/boringssl refs/heads/master | cut -f1) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 958595a9fafe..754c3dabf60f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -45,7 +45,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -67,7 +67,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-${{ steps.setup-python.outputs.python-version }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -142,7 +142,7 @@ jobs: name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -159,7 +159,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -202,7 +202,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -226,7 +226,7 @@ jobs: - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f with: toolchain: ${{ matrix.RUST }} - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -253,7 +253,7 @@ jobs: name: "Rust Coverage" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -282,7 +282,7 @@ jobs: - run: cargo install cargo-binutils if: steps.cargo-cache.outputs.cache-hit != 'true' - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -339,7 +339,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on macOS" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -363,7 +363,7 @@ jobs: - run: python -m pip install tox requests coverage[toml] - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -403,7 +403,7 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -436,7 +436,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -471,7 +471,7 @@ jobs: name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false @@ -521,7 +521,7 @@ jobs: name: "linkcheck" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 with: persist-credentials: false - name: Setup python @@ -539,7 +539,7 @@ jobs: needs: [linux, linux-distros, linux-rust, linux-rust-coverage, macos, windows, linux-downstream] if: ${{ always() }} steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 timeout-minutes: 3 with: persist-credentials: false diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index 6457d4b5fa56..e178fcb22d6a 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -29,7 +29,7 @@ jobs: steps: - name: "Delete workspace" # self-hosted runners need this, sigh run: gfind ! -name '.' ! -name '..' -delete - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 with: persist-credentials: false - uses: actions/cache@v3.0.11 @@ -38,7 +38,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.PYTHON.TOXENV }}-cargo-macarm64-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 with: repository: "google/wycheproof" path: "wycheproof" diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index de896c292b56..f093f93e3867 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest name: sdists steps: - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} @@ -151,7 +151,7 @@ jobs: name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS ${{ matrix.PYTHON.ARCHFLAGS }}" steps: # Needed for download_openssl.py - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} @@ -236,7 +236,7 @@ jobs: name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: # Needed for download_openssl.py - - uses: actions/checkout@v3.1.0 + - uses: actions/checkout@v3.2.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} From 00e93c8631f69cc66da0fce49b32599c805fe679 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 13 Dec 2022 12:39:57 +0000 Subject: [PATCH 247/298] Bump parking_lot_core from 0.8.5 to 0.8.6 in /src/rust (#7897) Bumps [parking_lot_core](https://github.com/Amanieu/parking_lot) from 0.8.5 to 0.8.6. - [Release notes](https://github.com/Amanieu/parking_lot/releases) - [Changelog](https://github.com/Amanieu/parking_lot/blob/master/CHANGELOG.md) - [Commits](https://github.com/Amanieu/parking_lot/compare/core-0.8.5...core-0.8.6) --- updated-dependencies: - dependency-name: parking_lot_core dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 87a866078f9b..2f201db3f4f2 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -324,9 +324,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" dependencies = [ "cfg-if", "instant", From 7e33b0e7739d633c77b8c478620167f693ed13f4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 14 Dec 2022 01:50:06 -0500 Subject: [PATCH 248/298] Bump OpenSSL/BoringSSL and adapt for OpenSSL RSA bleichenbacher mitigation (#7895) * Bump BoringSSL and/or OpenSSL in CI * Attempt to work-around wycheproof tests Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- src/_cffi_src/openssl/rsa.py | 8 ++++++++ tests/hazmat/primitives/test_rsa.py | 5 +++-- tests/wycheproof/test_rsa.py | 20 +++++++++++++++----- 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 754c3dabf60f..77e0dbe8de82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 10, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "d77fdbff010ee70776036c41155d1b3711ede548"}} - # Latest commit on the OpenSSL master branch, as of Dec 12, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "efec0f4611ee854f2b0b3da0c135e839bf8e7d04"}} + # Latest commit on the BoringSSL master branch, as of Dec 13, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "1740ff90a7da10408e6175b516946b392ec8f11f"}} + # Latest commit on the OpenSSL master branch, as of Dec 13, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "97b8db1af2f71059ecea986e4d12fc6a23699a74"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py index b1f6e4a4d645..3492d4588e11 100644 --- a/src/_cffi_src/openssl/rsa.py +++ b/src/_cffi_src/openssl/rsa.py @@ -16,6 +16,8 @@ static const int RSA_PKCS1_PSS_PADDING; static const int RSA_F4; static const int RSA_PSS_SALTLEN_AUTO; + +static const int Cryptography_HAS_IMPLICIT_RSA_REJECTION; """ FUNCTIONS = """ @@ -49,4 +51,10 @@ #if !defined(RSA_PSS_SALTLEN_AUTO) #define RSA_PSS_SALTLEN_AUTO -2 #endif + +#if defined(EVP_PKEY_CTRL_RSA_IMPLICIT_REJECTION) +static const int Cryptography_HAS_IMPLICIT_RSA_REJECTION = 1; +#else +static const int Cryptography_HAS_IMPLICIT_RSA_REJECTION = 0; +#endif """ diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 5a9fa19f37b4..7a4b2f1e3234 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -1713,8 +1713,9 @@ def test_unsupported_padding(self, backend): private_key.decrypt(b"0" * 256, DummyAsymmetricPadding()) @pytest.mark.supported( - only_if=lambda backend: backend.rsa_padding_supported( - padding.PKCS1v15() + only_if=lambda backend: ( + backend.rsa_padding_supported(padding.PKCS1v15()) + and not backend._lib.Cryptography_HAS_IMPLICIT_RSA_REJECTION ), skip_message="Does not support PKCS1v1.5.", ) diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 0670e1c47c00..e2b8426fd0f6 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -240,8 +240,18 @@ def test_rsa_pkcs1_encryption(backend, wycheproof): ) assert pt == binascii.unhexlify(wycheproof.testcase["msg"]) else: - with pytest.raises(ValueError): - key.decrypt( - binascii.unhexlify(wycheproof.testcase["ct"]), - padding.PKCS1v15(), - ) + if backend._lib.Cryptography_HAS_IMPLICIT_RSA_REJECTION: + try: + assert key.decrypt( + binascii.unhexlify(wycheproof.testcase["ct"]), + padding.PKCS1v15(), + ) != binascii.unhexlify(wycheproof.testcase["ct"]) + except ValueError: + # Some raise ValueError due to length mismatch. + pass + else: + with pytest.raises(ValueError): + key.decrypt( + binascii.unhexlify(wycheproof.testcase["ct"]), + padding.PKCS1v15(), + ) From 42f7f5f8dd5b0ce68eb7f2039f7a93f3a7596d14 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 15 Dec 2022 00:19:52 +0000 Subject: [PATCH 249/298] Bump BoringSSL and/or OpenSSL in CI (#7898) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77e0dbe8de82..618c2ad9e2ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 13, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "1740ff90a7da10408e6175b516946b392ec8f11f"}} - # Latest commit on the OpenSSL master branch, as of Dec 13, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "97b8db1af2f71059ecea986e4d12fc6a23699a74"}} + # Latest commit on the BoringSSL master branch, as of Dec 15, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "030693dc23c91894432aa1ae28b43d2c00d4f421"}} + # Latest commit on the OpenSSL master branch, as of Dec 15, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1cf2557063b142db3684b780c301f8ed609f1e84"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From d2fead7042105afc2c16312b80e2f533e0df6c51 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 15 Dec 2022 08:03:58 -0500 Subject: [PATCH 250/298] Bump cc from 1.0.77 to 1.0.78 in /src/rust (#7899) Bumps [cc](https://github.com/rust-lang/cc-rs) from 1.0.77 to 1.0.78. - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Commits](https://github.com/rust-lang/cc-rs/compare/1.0.77...1.0.78) --- updated-dependencies: - dependency-name: cc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2f201db3f4f2..aa1651da38ba 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -70,9 +70,9 @@ checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "cc" -version = "1.0.77" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" [[package]] name = "cfg-if" From a49f36812e3202064bcf23d09b16106814f29f04 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 16 Dec 2022 00:25:03 +0000 Subject: [PATCH 251/298] Bump BoringSSL and/or OpenSSL in CI (#7900) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 618c2ad9e2ba..0430a0deaec4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,10 +38,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 15, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "030693dc23c91894432aa1ae28b43d2c00d4f421"}} - # Latest commit on the OpenSSL master branch, as of Dec 15, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "1cf2557063b142db3684b780c301f8ed609f1e84"}} + # Latest commit on the BoringSSL master branch, as of Dec 16, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "97dd962a20b1d19c9e569cf8756fbcfc48ff7c73"}} + # Latest commit on the OpenSSL master branch, as of Dec 16, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "adf289b5b67ecb414ab709a2c25b0c6f0d463d31"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 2228806c9e19508a2f361fcadc2954d0ac5d31ba Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 16 Dec 2022 19:48:19 -0500 Subject: [PATCH 252/298] put binding back that pyOpenSSL just started using (#7903) --- src/_cffi_src/openssl/asn1.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/_cffi_src/openssl/asn1.py b/src/_cffi_src/openssl/asn1.py index 9cb0ea8ae107..4927432898eb 100644 --- a/src/_cffi_src/openssl/asn1.py +++ b/src/_cffi_src/openssl/asn1.py @@ -48,6 +48,7 @@ /* ASN1 TIME */ ASN1_TIME *ASN1_TIME_new(void); +void ASN1_TIME_free(ASN1_TIME *); int ASN1_TIME_set_string(ASN1_TIME *, const char *); /* ASN1 GENERALIZEDTIME */ From 306b418d0e255ed02ed4b4486866d275ff66fd67 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Sat, 17 Dec 2022 01:07:24 +0000 Subject: [PATCH 253/298] Bump BoringSSL and/or OpenSSL in CI (#7902) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0430a0deaec4..8f7add0afe96 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,8 +40,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Dec 16, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "97dd962a20b1d19c9e569cf8756fbcfc48ff7c73"}} - # Latest commit on the OpenSSL master branch, as of Dec 16, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "adf289b5b67ecb414ab709a2c25b0c6f0d463d31"}} + # Latest commit on the OpenSSL master branch, as of Dec 17, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f5b06306b7727f830407c639f8a7bf1698f8aaa5"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 11c83b0dd9e3682070e43850b719e48834d33343 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Sat, 17 Dec 2022 17:02:51 +0100 Subject: [PATCH 254/298] document POLICY_MAPPING and SUBJECT_DIRECTORY_ATTRIBUTES (#7904) --- docs/x509/reference.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 2c5ff50a9e0f..91560280f3f1 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -3403,6 +3403,14 @@ instances. The following common OIDs are available as constants. Corresponds to the dotted string ``"2.5.29.28"``. + .. attribute:: POLICY_MAPPINGS + + Corresponds to the dotted string ``"2.5.29.33"``. + + .. attribute:: SUBJECT_DIRECTORY_ATTRIBUTES + + Corresponds to the dotted string ``"2.5.29.9"``. + .. class:: CRLEntryExtensionOID From b30b4a28b35ad2f3ef7c47ff10ea69f703ba2e6e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 12:43:10 +0000 Subject: [PATCH 255/298] Bump unindent from 0.1.10 to 0.1.11 in /src/rust (#7907) Bumps [unindent](https://github.com/dtolnay/indoc) from 0.1.10 to 0.1.11. - [Release notes](https://github.com/dtolnay/indoc/releases) - [Commits](https://github.com/dtolnay/indoc/compare/0.1.10...0.1.11) --- updated-dependencies: - dependency-name: unindent dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index aa1651da38ba..6266d8684806 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -521,9 +521,9 @@ checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unindent" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ee9362deb4a96cef4d437d1ad49cffc9b9e92d202b6995674e928ce684f112" +checksum = "e1766d682d402817b5ac4490b3c3002d91dfa0d22812f341609f97b08757359c" [[package]] name = "version_check" From fce43ecb754549a46c91ce64d7ef054f10b5fe32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 12:43:14 +0000 Subject: [PATCH 256/298] Bump quote from 1.0.21 to 1.0.23 in /src/rust (#7908) Bumps [quote](https://github.com/dtolnay/quote) from 1.0.21 to 1.0.23. - [Release notes](https://github.com/dtolnay/quote/releases) - [Commits](https://github.com/dtolnay/quote/compare/1.0.21...1.0.23) --- updated-dependencies: - dependency-name: quote dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 6266d8684806..5109dd0c2d99 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -453,9 +453,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] From 9fa9f27a81b219f49f54eb91c774b953864e8250 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 07:43:52 -0500 Subject: [PATCH 257/298] Bump scratch from 1.0.2 to 1.0.3 in /src/rust (#7909) Bumps [scratch](https://github.com/dtolnay/scratch) from 1.0.2 to 1.0.3. - [Release notes](https://github.com/dtolnay/scratch/releases) - [Commits](https://github.com/dtolnay/scratch/compare/1.0.2...1.0.3) --- updated-dependencies: - dependency-name: scratch dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 5109dd0c2d99..de93edc2b1d4 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -477,9 +477,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "scratch" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8132065adcfd6e02db789d9285a0deb2f3fcb04002865ab67d5fb103533898" +checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" [[package]] name = "smallvec" From b0e2066dcdf5e3bcccf5351323dc4d790fa5befb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 13:05:35 +0000 Subject: [PATCH 258/298] Bump unicode-ident from 1.0.5 to 1.0.6 in /src/rust (#7910) Bumps [unicode-ident](https://github.com/dtolnay/unicode-ident) from 1.0.5 to 1.0.6. - [Release notes](https://github.com/dtolnay/unicode-ident/releases) - [Commits](https://github.com/dtolnay/unicode-ident/compare/1.0.5...1.0.6) --- updated-dependencies: - dependency-name: unicode-ident dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index de93edc2b1d4..cea17ea053e9 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -509,9 +509,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-width" From b34129c9ec9d399eab4f8e75854ab58eb19ddf70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 19 Dec 2022 13:05:45 +0000 Subject: [PATCH 259/298] Bump cxx from 1.0.83 to 1.0.85 in /src/rust (#7906) Bumps [cxx](https://github.com/dtolnay/cxx) from 1.0.83 to 1.0.85. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.83...1.0.85) --- updated-dependencies: - dependency-name: cxx dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index cea17ea053e9..c9f1e4ca6942 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -122,9 +122,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdf07d07d6531bfcdbe9b8b739b104610c6508dcc4d63b410585faf338241daf" +checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" dependencies = [ "cc", "cxxbridge-flags", @@ -149,15 +149,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac040a39517fd1674e0f32177648334b0f4074625b5588a64519804ba0553b12" +checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" [[package]] name = "cxxbridge-macro" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1362b0ddcfc4eb0a1f57b68bd77dd99f0e826958a96abd0ae9bd092e114ffed6" +checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" dependencies = [ "proc-macro2", "quote", From 6c0009aa268dcecddc2dc678dd37e020455e6267 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 19 Dec 2022 19:55:37 -0500 Subject: [PATCH 260/298] new libressl release (#7911) --- .github/workflows/ci.yml | 1 + tests/hazmat/primitives/test_pkcs7.py | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f7add0afe96..23fc5ad6f2da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,6 +36,7 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.7"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.7.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Dec 16, 2022. diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py index 8c5c1e3cff7d..ebb8dc0a9baa 100644 --- a/tests/hazmat/primitives/test_pkcs7.py +++ b/tests/hazmat/primitives/test_pkcs7.py @@ -132,8 +132,11 @@ def _pkcs7_verify(encoding, sig, msg, certs, options, backend): ) else: msg_bio = backend._bytes_to_bio(msg) + # libressl 3.7.0 has a bug when NULL is passed as an `out_bio`. Work + # around it for now. + out_bio = backend._create_mem_bio_gc() res = backend._lib.PKCS7_verify( - p7, backend._ffi.NULL, store, msg_bio.bio, backend._ffi.NULL, flags + p7, backend._ffi.NULL, store, msg_bio.bio, out_bio, flags ) backend.openssl_assert(res == 1) # OpenSSL 3.0 leaves a random bio error on the stack: From 2e81f899aa52802b1bd131f773c1a95b9815159a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:28:06 +0000 Subject: [PATCH 261/298] Bump cxx-build from 1.0.83 to 1.0.85 in /src/rust (#7914) Bumps [cxx-build](https://github.com/dtolnay/cxx) from 1.0.83 to 1.0.85. - [Release notes](https://github.com/dtolnay/cxx/releases) - [Commits](https://github.com/dtolnay/cxx/compare/1.0.83...1.0.85) --- updated-dependencies: - dependency-name: cxx-build dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index c9f1e4ca6942..2a618284b584 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -134,9 +134,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2eb5b96ecdc99f72657332953d4d9c50135af1bac34277801cc3937906ebd39" +checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" dependencies = [ "cc", "codespan-reporting", From eaf6c3c69ce063c52273d596ac609c48a259457a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:28:07 +0000 Subject: [PATCH 262/298] Bump link-cplusplus from 1.0.7 to 1.0.8 in /src/rust (#7913) Bumps [link-cplusplus](https://github.com/dtolnay/link-cplusplus) from 1.0.7 to 1.0.8. - [Release notes](https://github.com/dtolnay/link-cplusplus/releases) - [Commits](https://github.com/dtolnay/link-cplusplus/compare/1.0.7...1.0.8) --- updated-dependencies: - dependency-name: link-cplusplus dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2a618284b584..abbc4498a88a 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -237,9 +237,9 @@ checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "link-cplusplus" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9272ab7b96c9046fbc5bc56c06c117cb639fe2d509df0c421cad82d2915cf369" +checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" dependencies = [ "cc", ] From cc26759833a54b3a0619ffdb926c4811a5d303a3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:39:31 +0000 Subject: [PATCH 263/298] Bump proc-macro2 from 1.0.47 to 1.0.49 in /src/rust (#7916) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.47 to 1.0.49. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.47...1.0.49) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index abbc4498a88a..3fea3418e97e 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -396,9 +396,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] From 6b6c73cde208031b37569c48584e296aa0625f40 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:39:42 +0000 Subject: [PATCH 264/298] Bump proc-macro-hack from 0.5.19 to 0.5.20+deprecated in /src/rust (#7917) Bumps [proc-macro-hack](https://github.com/dtolnay/proc-macro-hack) from 0.5.19 to 0.5.20+deprecated. - [Release notes](https://github.com/dtolnay/proc-macro-hack/releases) - [Commits](https://github.com/dtolnay/proc-macro-hack/compare/0.5.19...0.5.20) --- updated-dependencies: - dependency-name: proc-macro-hack dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 3fea3418e97e..56ece303cfbc 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -390,9 +390,9 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" From 1579bfb869d5de13600403607751670ef34e2978 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Dec 2022 12:39:44 +0000 Subject: [PATCH 265/298] Bump syn from 1.0.105 to 1.0.107 in /src/rust (#7915) Bumps [syn](https://github.com/dtolnay/syn) from 1.0.105 to 1.0.107. - [Release notes](https://github.com/dtolnay/syn/releases) - [Commits](https://github.com/dtolnay/syn/compare/1.0.105...1.0.107) --- updated-dependencies: - dependency-name: syn dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 56ece303cfbc..2fe046e370e6 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -489,9 +489,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "syn" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", From 73896bef1f777048a40d232fe3c1c565d0e6578d Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Tue, 20 Dec 2022 18:18:51 -0500 Subject: [PATCH 266/298] Remove binding for X509_STORE_get_get_issuer (#7918) This was added alongside X509_STORE_set_get_issuer in 21ef4080ec7666299f1268f3bbfb136582744359. It makes sense to want to override issuer lookup, but I've never seen a valid use case for querying the callbacks. If you're trying to get at the function that was already configured, you presumably already know it. (And if you don't, it's not safe to call because an arbitrary callback may have been written to only be usable in particular contexts.) --- src/_cffi_src/openssl/x509_vfy.py | 2 -- src/cryptography/hazmat/bindings/openssl/_conditional.py | 1 - 2 files changed, 3 deletions(-) diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index b311988639ba..daed17eeac99 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -211,7 +211,6 @@ X509 *X509_OBJECT_get0_X509(X509_OBJECT *); X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *); -X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *); void X509_STORE_set_get_issuer(X509_STORE *, X509_STORE_CTX_get_issuer_fn); """ @@ -219,7 +218,6 @@ #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_X509_STORE_CTX_GET_ISSUER = 0; typedef void *X509_STORE_CTX_get_issuer_fn; -X509_STORE_CTX_get_issuer_fn (*X509_STORE_get_get_issuer)(X509_STORE *) = NULL; void (*X509_STORE_set_get_issuer)(X509_STORE *, X509_STORE_CTX_get_issuer_fn) = NULL; #else diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 7215d39f0b59..e8ce4738fb81 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -64,7 +64,6 @@ def cryptography_has_mem_functions() -> typing.List[str]: def cryptography_has_x509_store_ctx_get_issuer() -> typing.List[str]: return [ - "X509_STORE_get_get_issuer", "X509_STORE_set_get_issuer", ] From 4868142f4193c441b4995f54c70caad7b06dc093 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 00:22:05 +0000 Subject: [PATCH 267/298] Bump BoringSSL and/or OpenSSL in CI (#7919) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23fc5ad6f2da..830efe9a8497 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,8 +39,8 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.7.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 16, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "97dd962a20b1d19c9e569cf8756fbcfc48ff7c73"}} + # Latest commit on the BoringSSL master branch, as of Dec 21, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "d1b20a9580aebb6fbb0b1b2408cf1221d83afb71"}} # Latest commit on the OpenSSL master branch, as of Dec 17, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f5b06306b7727f830407c639f8a7bf1698f8aaa5"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" From 7ff729ecf2ffeffc8442811a7ad5c8a9ab24351c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 20 Dec 2022 21:44:47 -0500 Subject: [PATCH 268/298] Switch from flake8 to ruff (#7920) It's more than 60x faster. --- .github/workflows/download_openssl.py | 1 - docs/_ext/cryptography-docs.py | 1 - .../custom-vectors/arc4/generate_arc4.py | 1 - .../rsa-oaep-sha2/generate_rsa_oaep_sha2.py | 1 - .../secp256k1/generate_secp256k1.py | 1 - .../secp256k1/verify_secp256k1.py | 1 - docs/development/submitting-patches.rst | 2 +- pyproject.toml | 15 +++++++++ release.py | 1 - setup.cfg | 10 +----- src/_cffi_src/utils.py | 1 - src/cryptography/__init__.py | 7 +---- .../hazmat/backends/openssl/__init__.py | 1 - .../hazmat/backends/openssl/aead.py | 1 - .../hazmat/backends/openssl/backend.py | 17 +++++----- .../hazmat/backends/openssl/ciphers.py | 1 - .../hazmat/backends/openssl/cmac.py | 2 +- .../hazmat/backends/openssl/dh.py | 1 - .../hazmat/backends/openssl/dsa.py | 7 ++--- .../hazmat/backends/openssl/ed25519.py | 4 +-- .../hazmat/backends/openssl/hashes.py | 1 - .../hazmat/backends/openssl/hmac.py | 1 - .../hazmat/backends/openssl/poly1305.py | 1 - .../hazmat/backends/openssl/rsa.py | 9 ++---- .../hazmat/bindings/_rust/__init__.pyi | 2 +- .../hazmat/bindings/_rust/ocsp.pyi | 5 ++- .../hazmat/bindings/_rust/pkcs7.pyi | 2 +- .../hazmat/bindings/_rust/x509.pyi | 1 - .../hazmat/primitives/_asymmetric.py | 1 - .../hazmat/primitives/_cipheralgorithm.py | 1 - .../hazmat/primitives/asymmetric/dh.py | 1 - .../hazmat/primitives/asymmetric/dsa.py | 4 +-- .../hazmat/primitives/asymmetric/ec.py | 4 +-- .../hazmat/primitives/asymmetric/ed25519.py | 1 - .../hazmat/primitives/asymmetric/rsa.py | 4 +-- .../hazmat/primitives/asymmetric/types.py | 1 - .../hazmat/primitives/asymmetric/utils.py | 1 - .../hazmat/primitives/ciphers/__init__.py | 1 - .../hazmat/primitives/ciphers/base.py | 1 - src/cryptography/hazmat/primitives/cmac.py | 4 +-- src/cryptography/hazmat/primitives/hashes.py | 4 +-- src/cryptography/hazmat/primitives/hmac.py | 4 +-- .../hazmat/primitives/kdf/concatkdf.py | 5 +-- .../hazmat/primitives/kdf/hkdf.py | 5 +-- .../hazmat/primitives/kdf/scrypt.py | 1 - .../hazmat/primitives/kdf/x963kdf.py | 5 +-- .../primitives/serialization/__init__.py | 1 - .../hazmat/primitives/serialization/pkcs12.py | 4 +-- .../hazmat/primitives/serialization/pkcs7.py | 3 +- .../hazmat/primitives/twofactor/hotp.py | 1 - .../hazmat/primitives/twofactor/totp.py | 2 +- src/cryptography/x509/__init__.py | 15 +++++---- src/cryptography/x509/base.py | 3 +- src/cryptography/x509/extensions.py | 8 ++--- src/cryptography/x509/general_name.py | 1 - src/cryptography/x509/name.py | 4 +-- src/cryptography/x509/ocsp.py | 3 +- src/cryptography/x509/oid.py | 5 ++- tests/hazmat/backends/test_openssl.py | 2 +- tests/hazmat/backends/test_openssl_memleak.py | 1 - tests/hazmat/primitives/fixtures_dsa.py | 1 - tests/hazmat/primitives/fixtures_ec.py | 1 - tests/hazmat/primitives/fixtures_rsa.py | 1 - tests/hazmat/primitives/test_3des.py | 2 +- tests/hazmat/primitives/test_aead.py | 2 +- tests/hazmat/primitives/test_aes.py | 2 +- tests/hazmat/primitives/test_aes_gcm.py | 2 +- tests/hazmat/primitives/test_arc4.py | 2 +- tests/hazmat/primitives/test_block.py | 4 +-- tests/hazmat/primitives/test_blowfish.py | 2 +- tests/hazmat/primitives/test_camellia.py | 2 +- tests/hazmat/primitives/test_cast5.py | 2 +- tests/hazmat/primitives/test_chacha20.py | 2 +- tests/hazmat/primitives/test_cmac.py | 11 ++----- tests/hazmat/primitives/test_concatkdf.py | 6 ++-- tests/hazmat/primitives/test_dh.py | 2 +- tests/hazmat/primitives/test_dsa.py | 4 +-- tests/hazmat/primitives/test_ec.py | 4 +-- tests/hazmat/primitives/test_hash_vectors.py | 2 +- tests/hazmat/primitives/test_hashes.py | 2 +- tests/hazmat/primitives/test_hkdf.py | 5 +-- tests/hazmat/primitives/test_hkdf_vectors.py | 2 +- tests/hazmat/primitives/test_hmac.py | 2 +- tests/hazmat/primitives/test_hmac_vectors.py | 2 +- tests/hazmat/primitives/test_idea.py | 2 +- tests/hazmat/primitives/test_kbkdf.py | 2 +- tests/hazmat/primitives/test_kbkdf_vectors.py | 2 +- tests/hazmat/primitives/test_keywrap.py | 2 +- .../primitives/test_pbkdf2hmac_vectors.py | 2 +- tests/hazmat/primitives/test_rsa.py | 31 +++++++++---------- tests/hazmat/primitives/test_scrypt.py | 8 ++--- tests/hazmat/primitives/test_seed.py | 2 +- tests/hazmat/primitives/test_serialization.py | 10 ++---- tests/hazmat/primitives/test_sm4.py | 2 +- .../hazmat/primitives/twofactor/test_hotp.py | 5 +-- .../hazmat/primitives/twofactor/test_totp.py | 5 +-- tests/hazmat/primitives/utils.py | 2 +- tests/test_fernet.py | 5 +-- tests/test_utils.py | 4 +-- tests/utils.py | 4 +-- tests/wycheproof/test_aes.py | 2 +- tests/wycheproof/test_chacha20poly1305.py | 2 +- tests/wycheproof/test_dsa.py | 1 - tests/wycheproof/test_ecdh.py | 3 +- tests/wycheproof/test_ecdsa.py | 1 - tests/wycheproof/test_hkdf.py | 1 - tests/wycheproof/test_hmac.py | 1 - tests/wycheproof/test_rsa.py | 1 - tests/x509/test_ocsp.py | 2 +- tests/x509/test_x509.py | 1 - tests/x509/test_x509_crlbuilder.py | 3 +- tests/x509/test_x509_ext.py | 3 +- tests/x509/test_x509_revokedcertbuilder.py | 1 - tox.ini | 2 +- vectors/cryptography_vectors/__init__.py | 1 - vectors/setup.py | 1 - 116 files changed, 133 insertions(+), 247 deletions(-) diff --git a/.github/workflows/download_openssl.py b/.github/workflows/download_openssl.py index 0e6f66286199..3be39084b0d4 100644 --- a/.github/workflows/download_openssl.py +++ b/.github/workflows/download_openssl.py @@ -9,7 +9,6 @@ import zipfile import requests - from urllib3.util.retry import Retry diff --git a/docs/_ext/cryptography-docs.py b/docs/_ext/cryptography-docs.py index 1131f6a0e279..43a9c6cb8ea1 100644 --- a/docs/_ext/cryptography-docs.py +++ b/docs/_ext/cryptography-docs.py @@ -5,7 +5,6 @@ from docutils import nodes from docutils.parsers.rst import Directive - DANGER_MESSAGE = """ This is a "Hazardous Materials" module. You should **ONLY** use it if you're 100% absolutely sure that you know what you're doing because this module is diff --git a/docs/development/custom-vectors/arc4/generate_arc4.py b/docs/development/custom-vectors/arc4/generate_arc4.py index 14a99d050610..504d19643425 100644 --- a/docs/development/custom-vectors/arc4/generate_arc4.py +++ b/docs/development/custom-vectors/arc4/generate_arc4.py @@ -7,7 +7,6 @@ from cryptography.hazmat.primitives import ciphers from cryptography.hazmat.primitives.ciphers import algorithms - _RFC6229_KEY_MATERIALS = [ ( True, diff --git a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py index 009ba7fc72c0..6940f0400d47 100644 --- a/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py +++ b/docs/development/custom-vectors/rsa-oaep-sha2/generate_rsa_oaep_sha2.py @@ -8,7 +8,6 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import padding, rsa - from tests.utils import load_pkcs1_vectors, load_vectors_from_file diff --git a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py index 2f1f69e949a2..ab616de7f963 100644 --- a/docs/development/custom-vectors/secp256k1/generate_secp256k1.py +++ b/docs/development/custom-vectors/secp256k1/generate_secp256k1.py @@ -7,7 +7,6 @@ from ecdsa.util import sigdecode_der, sigencode_der from cryptography_vectors import open_vector_file - from tests.utils import load_fips_ecdsa_signing_vectors, load_vectors_from_file HASHLIB_HASH_TYPES = { diff --git a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py index 3ba21c8d6584..7949a74ee9c7 100644 --- a/docs/development/custom-vectors/secp256k1/verify_secp256k1.py +++ b/docs/development/custom-vectors/secp256k1/verify_secp256k1.py @@ -5,7 +5,6 @@ from cryptography.hazmat.primitives.asymmetric.utils import ( encode_dss_signature, ) - from tests.utils import load_fips_ecdsa_signing_vectors, load_vectors_from_file CRYPTOGRAPHY_HASH_TYPES = { diff --git a/docs/development/submitting-patches.rst b/docs/development/submitting-patches.rst index 80a8bb496921..4deaafe09e0f 100644 --- a/docs/development/submitting-patches.rst +++ b/docs/development/submitting-patches.rst @@ -20,7 +20,7 @@ Code When in doubt, refer to :pep:`8` for Python code. You can check if your code meets our automated requirements by formatting it with ``black`` and running -``flake8`` against it. If you've installed the development requirements this +``ruff`` against it. If you've installed the development requirements this will automatically use our configuration. You can also run the ``tox`` job with ``tox -e flake``. diff --git a/pyproject.toml b/pyproject.toml index 0fa34fb55a4d..e099c29573be 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -63,3 +63,18 @@ exclude_lines = [ "@typing.overload", "if typing.TYPE_CHECKING", ] + +[tool.ruff] +exclude = [ + '.tox', + '*.egg', + '.git', + '_build', + '.hypothesis', +] +ignore = ['N818'] +select = ['E', 'F', 'I', 'N', 'W'] +line-length = 79 + +[tool.ruff.isort] +known-first-party = ["cryptography", "cryptography_vectors", "tests"] diff --git a/release.py b/release.py index e7445d951d8f..5046daff1e6c 100644 --- a/release.py +++ b/release.py @@ -10,7 +10,6 @@ import zipfile import click - import requests diff --git a/setup.cfg b/setup.cfg index d42e78930c19..07cce535b656 100644 --- a/setup.cfg +++ b/setup.cfg @@ -76,16 +76,8 @@ sdist = setuptools_rust >= 0.11.4 pep8test = black - flake8 - flake8-import-order - pep8-naming + ruff # This extra is for OpenSSH private keys that use bcrypt KDF # Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3 ssh = bcrypt >= 3.1.5 - -[flake8] -ignore = E203,E211,W503,W504,N818 -exclude = .tox,*.egg,.git,_build,.hypothesis -select = E,W,F,N,I -application-import-names = cryptography,cryptography_vectors,tests diff --git a/src/_cffi_src/utils.py b/src/_cffi_src/utils.py index 5afc084a3834..47d31b611c78 100644 --- a/src/_cffi_src/utils.py +++ b/src/_cffi_src/utils.py @@ -10,7 +10,6 @@ from cffi import FFI - # Load the cryptography __about__ to get the current package version base_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) about = {} diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index 6c0fd2a62540..07c894ea33f8 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -5,14 +5,9 @@ import sys import warnings -from cryptography.__about__ import ( - __author__, - __copyright__, - __version__, -) +from cryptography.__about__ import __author__, __copyright__, __version__ from cryptography.utils import CryptographyDeprecationWarning - __all__ = [ "__version__", "__author__", diff --git a/src/cryptography/hazmat/backends/openssl/__init__.py b/src/cryptography/hazmat/backends/openssl/__init__.py index 31fd17c3b7fe..42c4539df3ed 100644 --- a/src/cryptography/hazmat/backends/openssl/__init__.py +++ b/src/cryptography/hazmat/backends/openssl/__init__.py @@ -5,5 +5,4 @@ from cryptography.hazmat.backends.openssl.backend import backend - __all__ = ["backend"] diff --git a/src/cryptography/hazmat/backends/openssl/aead.py b/src/cryptography/hazmat/backends/openssl/aead.py index aa106fc3a3df..5b0fd2217d18 100644 --- a/src/cryptography/hazmat/backends/openssl/aead.py +++ b/src/cryptography/hazmat/backends/openssl/aead.py @@ -6,7 +6,6 @@ from cryptography.exceptions import InvalidTag - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend from cryptography.hazmat.primitives.ciphers.aead import ( diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index caa5458249fe..5294e5d1405f 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -16,10 +16,10 @@ from cryptography.hazmat.backends.openssl.ciphers import _CipherContext from cryptography.hazmat.backends.openssl.cmac import _CMACContext from cryptography.hazmat.backends.openssl.dh import ( + _dh_params_dup, _DHParameters, _DHPrivateKey, _DHPublicKey, - _dh_params_dup, ) from cryptography.hazmat.backends.openssl.dsa import ( _DSAParameters, @@ -57,9 +57,7 @@ _X448PrivateKey, _X448PublicKey, ) -from cryptography.hazmat.bindings._rust import ( - x509 as rust_x509, -) +from cryptography.hazmat.bindings._rust import x509 as rust_x509 from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding @@ -76,8 +74,8 @@ from cryptography.hazmat.primitives.asymmetric.padding import ( MGF1, OAEP, - PKCS1v15, PSS, + PKCS1v15, ) from cryptography.hazmat.primitives.asymmetric.types import ( CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES, @@ -93,9 +91,9 @@ AES128, AES256, ARC4, + SM4, Camellia, ChaCha20, - SM4, TripleDES, _BlowfishInternal, _CAST5Internal, @@ -109,21 +107,20 @@ CTR, ECB, GCM, - Mode, OFB, XTS, + Mode, ) from cryptography.hazmat.primitives.kdf import scrypt from cryptography.hazmat.primitives.serialization import ssh from cryptography.hazmat.primitives.serialization.pkcs12 import ( + _ALLOWED_PKCS12_TYPES, + _PKCS12_CAS_TYPES, PBES, PKCS12Certificate, PKCS12KeyAndCertificates, - _ALLOWED_PKCS12_TYPES, - _PKCS12_CAS_TYPES, ) - _MemoryBIO = collections.namedtuple("_MemoryBIO", ["bio", "char_ptr"]) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 1058de9f1dc9..fd2b6612f046 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -8,7 +8,6 @@ from cryptography.hazmat.primitives import ciphers from cryptography.hazmat.primitives.ciphers import algorithms, modes - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend diff --git a/src/cryptography/hazmat/backends/openssl/cmac.py b/src/cryptography/hazmat/backends/openssl/cmac.py index 35f50c5c4523..6f7363294179 100644 --- a/src/cryptography/hazmat/backends/openssl/cmac.py +++ b/src/cryptography/hazmat/backends/openssl/cmac.py @@ -13,8 +13,8 @@ from cryptography.hazmat.primitives.ciphers.modes import CBC if typing.TYPE_CHECKING: - from cryptography.hazmat.primitives import ciphers from cryptography.hazmat.backends.openssl.backend import Backend + from cryptography.hazmat.primitives import ciphers class _CMACContext: diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py index 33fed6a40394..c429c023916b 100644 --- a/src/cryptography/hazmat/backends/openssl/dh.py +++ b/src/cryptography/hazmat/backends/openssl/dh.py @@ -8,7 +8,6 @@ from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend diff --git a/src/cryptography/hazmat/backends/openssl/dsa.py b/src/cryptography/hazmat/backends/openssl/dsa.py index 8634b7256cfe..15bd84a7b5a5 100644 --- a/src/cryptography/hazmat/backends/openssl/dsa.py +++ b/src/cryptography/hazmat/backends/openssl/dsa.py @@ -10,11 +10,8 @@ _calculate_digest_and_algorithm, ) from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import ( - dsa, - utils as asym_utils, -) - +from cryptography.hazmat.primitives.asymmetric import dsa +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py index 0ed69245ab48..6f393e5b6aa9 100644 --- a/src/cryptography/hazmat/backends/openssl/ed25519.py +++ b/src/cryptography/hazmat/backends/openssl/ed25519.py @@ -7,10 +7,10 @@ from cryptography import exceptions from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.ed25519 import ( - Ed25519PrivateKey, - Ed25519PublicKey, _ED25519_KEY_SIZE, _ED25519_SIG_SIZE, + Ed25519PrivateKey, + Ed25519PublicKey, ) if typing.TYPE_CHECKING: diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py index 278b3815d062..52d4646a7ab0 100644 --- a/src/cryptography/hazmat/backends/openssl/hashes.py +++ b/src/cryptography/hazmat/backends/openssl/hashes.py @@ -7,7 +7,6 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import hashes - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py index 5fd54074772f..ba3dfb53f8b3 100644 --- a/src/cryptography/hazmat/backends/openssl/hmac.py +++ b/src/cryptography/hazmat/backends/openssl/hmac.py @@ -11,7 +11,6 @@ ) from cryptography.hazmat.primitives import constant_time, hashes - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend diff --git a/src/cryptography/hazmat/backends/openssl/poly1305.py b/src/cryptography/hazmat/backends/openssl/poly1305.py index dd6d376f037a..d0d44f6fd96e 100644 --- a/src/cryptography/hazmat/backends/openssl/poly1305.py +++ b/src/cryptography/hazmat/backends/openssl/poly1305.py @@ -7,7 +7,6 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.primitives import constant_time - _POLY1305_TAG_SIZE = 16 _POLY1305_KEY_SIZE = 32 diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 694829d2c5f1..e18bab3ff88e 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -14,15 +14,13 @@ _calculate_digest_and_algorithm, ) from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import ( - utils as asym_utils, -) +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils from cryptography.hazmat.primitives.asymmetric.padding import ( - AsymmetricPadding, MGF1, OAEP, - PKCS1v15, PSS, + AsymmetricPadding, + PKCS1v15, _Auto, _DigestLength, _MaxLength, @@ -35,7 +33,6 @@ RSAPublicNumbers, ) - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.backend import Backend diff --git a/src/cryptography/hazmat/bindings/_rust/__init__.pyi b/src/cryptography/hazmat/bindings/_rust/__init__.pyi index 94a37a20aa96..d7642fcc4fe0 100644 --- a/src/cryptography/hazmat/bindings/_rust/__init__.pyi +++ b/src/cryptography/hazmat/bindings/_rust/__init__.pyi @@ -22,7 +22,7 @@ class FixedPool(typing.Generic[T]): self, create: typing.Callable[[], T], ) -> None: ... - def acquire(self) -> PoolAcquisition[T]: ... + def acquire(self) -> "PoolAcquisition[T]": ... class PoolAcquisition(typing.Generic[T]): def __enter__(self) -> T: ... diff --git a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi index acdea3dd2309..47a037adeeff 100644 --- a/src/cryptography/hazmat/bindings/_rust/ocsp.pyi +++ b/src/cryptography/hazmat/bindings/_rust/ocsp.pyi @@ -4,15 +4,14 @@ import typing -from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES from cryptography.hazmat.primitives import hashes -from cryptography.x509 import Extension +from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES from cryptography.x509.ocsp import ( OCSPRequest, OCSPRequestBuilder, OCSPResponse, - OCSPResponseStatus, OCSPResponseBuilder, + OCSPResponseStatus, ) def load_der_ocsp_request(data: bytes) -> OCSPRequest: ... diff --git a/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi b/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi index 6cbc0bcf742c..66bd850981a6 100644 --- a/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi +++ b/src/cryptography/hazmat/bindings/_rust/pkcs7.pyi @@ -1,8 +1,8 @@ import typing +from cryptography import x509 from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.serialization import pkcs7 -from cryptography import x509 def serialize_certificates( certs: typing.List[x509.Certificate], diff --git a/src/cryptography/hazmat/bindings/_rust/x509.pyi b/src/cryptography/hazmat/bindings/_rust/x509.pyi index d92ea6c6a1d7..1bbde80056ba 100644 --- a/src/cryptography/hazmat/bindings/_rust/x509.pyi +++ b/src/cryptography/hazmat/bindings/_rust/x509.pyi @@ -2,7 +2,6 @@ # 2.0, and the BSD License. See the LICENSE file in the root of this repository # for complete details. -import datetime import typing from cryptography import x509 diff --git a/src/cryptography/hazmat/primitives/_asymmetric.py b/src/cryptography/hazmat/primitives/_asymmetric.py index cdadbdeff799..c6862d9317f5 100644 --- a/src/cryptography/hazmat/primitives/_asymmetric.py +++ b/src/cryptography/hazmat/primitives/_asymmetric.py @@ -4,7 +4,6 @@ import abc - # This exists to break an import cycle. It is normally accessible from the # asymmetric padding module. diff --git a/src/cryptography/hazmat/primitives/_cipheralgorithm.py b/src/cryptography/hazmat/primitives/_cipheralgorithm.py index 7f322048d551..6e6a79c11a6a 100644 --- a/src/cryptography/hazmat/primitives/_cipheralgorithm.py +++ b/src/cryptography/hazmat/primitives/_cipheralgorithm.py @@ -5,7 +5,6 @@ import abc import typing - # This exists to break an import cycle. It is normally accessible from the # ciphers module. diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index 2093ad4a6680..bbdd485cd30f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -8,7 +8,6 @@ from cryptography.hazmat.primitives import _serialization - _MIN_MODULUS_SIZE = 512 diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index 5e587097cfcc..e013d6204da3 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -7,9 +7,7 @@ import typing from cryptography.hazmat.primitives import _serialization, hashes -from cryptography.hazmat.primitives.asymmetric import ( - utils as asym_utils, -) +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils class DSAParameters(metaclass=abc.ABCMeta): diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 4d949da5ee16..062b33c34d1f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -9,9 +9,7 @@ from cryptography import utils from cryptography.hazmat._oid import ObjectIdentifier from cryptography.hazmat.primitives import _serialization, hashes -from cryptography.hazmat.primitives.asymmetric import ( - utils as asym_utils, -) +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils class EllipticCurveOID: diff --git a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py index 43277028338a..220bf592c0bb 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ed25519.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ed25519.py @@ -8,7 +8,6 @@ from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from cryptography.hazmat.primitives import _serialization - _ED25519_KEY_SIZE = 32 _ED25519_SIG_SIZE = 64 diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 36d360f223df..433f925dea9f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -9,9 +9,7 @@ from cryptography.hazmat.primitives import _serialization, hashes from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding -from cryptography.hazmat.primitives.asymmetric import ( - utils as asym_utils, -) +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils class RSAPrivateKey(metaclass=abc.ABCMeta): diff --git a/src/cryptography/hazmat/primitives/asymmetric/types.py b/src/cryptography/hazmat/primitives/asymmetric/types.py index d49781524328..369fbf8f2f3c 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/types.py +++ b/src/cryptography/hazmat/primitives/asymmetric/types.py @@ -15,7 +15,6 @@ x448, ) - # Every asymmetric key type PUBLIC_KEY_TYPES = typing.Union[ dh.DHPublicKey, diff --git a/src/cryptography/hazmat/primitives/asymmetric/utils.py b/src/cryptography/hazmat/primitives/asymmetric/utils.py index 638ecb351e5c..140ca1960d9f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/utils.py +++ b/src/cryptography/hazmat/primitives/asymmetric/utils.py @@ -6,7 +6,6 @@ from cryptography.hazmat.bindings._rust import asn1 from cryptography.hazmat.primitives import hashes - decode_dss_signature = asn1.decode_dss_signature encode_dss_signature = asn1.encode_dss_signature diff --git a/src/cryptography/hazmat/primitives/ciphers/__init__.py b/src/cryptography/hazmat/primitives/ciphers/__init__.py index 874dbd456e8f..95f02842ad1a 100644 --- a/src/cryptography/hazmat/primitives/ciphers/__init__.py +++ b/src/cryptography/hazmat/primitives/ciphers/__init__.py @@ -15,7 +15,6 @@ CipherContext, ) - __all__ = [ "Cipher", "CipherAlgorithm", diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 7af305249fbe..886afa1739b7 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -14,7 +14,6 @@ from cryptography.hazmat.primitives._cipheralgorithm import CipherAlgorithm from cryptography.hazmat.primitives.ciphers import modes - if typing.TYPE_CHECKING: from cryptography.hazmat.backends.openssl.ciphers import ( _CipherContext as _BackendCipherContext, diff --git a/src/cryptography/hazmat/primitives/cmac.py b/src/cryptography/hazmat/primitives/cmac.py index 1ec756a8ef54..00c4bd11d877 100644 --- a/src/cryptography/hazmat/primitives/cmac.py +++ b/src/cryptography/hazmat/primitives/cmac.py @@ -6,9 +6,7 @@ import typing from cryptography import utils -from cryptography.exceptions import ( - AlreadyFinalized, -) +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.primitives import ciphers if typing.TYPE_CHECKING: diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index ba22a6646c01..440b1a3e9460 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -6,9 +6,7 @@ import typing from cryptography import utils -from cryptography.exceptions import ( - AlreadyFinalized, -) +from cryptography.exceptions import AlreadyFinalized class HashAlgorithm(metaclass=abc.ABCMeta): diff --git a/src/cryptography/hazmat/primitives/hmac.py b/src/cryptography/hazmat/primitives/hmac.py index 1577326c9355..8f1c0eae6e1f 100644 --- a/src/cryptography/hazmat/primitives/hmac.py +++ b/src/cryptography/hazmat/primitives/hmac.py @@ -6,9 +6,7 @@ import typing from cryptography import utils -from cryptography.exceptions import ( - AlreadyFinalized, -) +from cryptography.exceptions import AlreadyFinalized from cryptography.hazmat.backends.openssl.hmac import _HMACContext from cryptography.hazmat.primitives import hashes diff --git a/src/cryptography/hazmat/primitives/kdf/concatkdf.py b/src/cryptography/hazmat/primitives/kdf/concatkdf.py index 0b0262ebb3ab..94312fec303e 100644 --- a/src/cryptography/hazmat/primitives/kdf/concatkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/concatkdf.py @@ -6,10 +6,7 @@ import typing from cryptography import utils -from cryptography.exceptions import ( - AlreadyFinalized, - InvalidKey, -) +from cryptography.exceptions import AlreadyFinalized, InvalidKey from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction diff --git a/src/cryptography/hazmat/primitives/kdf/hkdf.py b/src/cryptography/hazmat/primitives/kdf/hkdf.py index 44889b67b74a..2152ae2203ce 100644 --- a/src/cryptography/hazmat/primitives/kdf/hkdf.py +++ b/src/cryptography/hazmat/primitives/kdf/hkdf.py @@ -6,10 +6,7 @@ import typing from cryptography import utils -from cryptography.exceptions import ( - AlreadyFinalized, - InvalidKey, -) +from cryptography.exceptions import AlreadyFinalized, InvalidKey from cryptography.hazmat.primitives import constant_time, hashes, hmac from cryptography.hazmat.primitives.kdf import KeyDerivationFunction diff --git a/src/cryptography/hazmat/primitives/kdf/scrypt.py b/src/cryptography/hazmat/primitives/kdf/scrypt.py index ff81bbb1fb25..286f4388cb2a 100644 --- a/src/cryptography/hazmat/primitives/kdf/scrypt.py +++ b/src/cryptography/hazmat/primitives/kdf/scrypt.py @@ -15,7 +15,6 @@ from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.kdf import KeyDerivationFunction - # This is used by the scrypt tests to skip tests that require more memory # than the MEM_LIMIT _MEM_LIMIT = sys.maxsize // 2 diff --git a/src/cryptography/hazmat/primitives/kdf/x963kdf.py b/src/cryptography/hazmat/primitives/kdf/x963kdf.py index aa6bcc1d189f..651e691aa5c4 100644 --- a/src/cryptography/hazmat/primitives/kdf/x963kdf.py +++ b/src/cryptography/hazmat/primitives/kdf/x963kdf.py @@ -6,10 +6,7 @@ import typing from cryptography import utils -from cryptography.exceptions import ( - AlreadyFinalized, - InvalidKey, -) +from cryptography.exceptions import AlreadyFinalized, InvalidKey from cryptography.hazmat.primitives import constant_time, hashes from cryptography.hazmat.primitives.kdf import KeyDerivationFunction diff --git a/src/cryptography/hazmat/primitives/serialization/__init__.py b/src/cryptography/hazmat/primitives/serialization/__init__.py index 60241500c3ed..af4112f3968f 100644 --- a/src/cryptography/hazmat/primitives/serialization/__init__.py +++ b/src/cryptography/hazmat/primitives/serialization/__init__.py @@ -26,7 +26,6 @@ load_ssh_public_key, ) - __all__ = [ "load_der_parameters", "load_der_private_key", diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index 662ea75af748..b4d9a34362e0 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -14,9 +14,7 @@ ed448, rsa, ) -from cryptography.hazmat.primitives.asymmetric.types import ( - PRIVATE_KEY_TYPES, -) +from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES __all__ = [ "PBES", diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs7.py b/src/cryptography/hazmat/primitives/serialization/pkcs7.py index 5eaeab388309..7e593e719377 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs7.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs7.py @@ -8,8 +8,7 @@ import io import typing -from cryptography import utils -from cryptography import x509 +from cryptography import utils, x509 from cryptography.hazmat.bindings._rust import pkcs7 as rust_pkcs7 from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec, rsa diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index 9730af2b7d08..04c45bb8c6df 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -11,7 +11,6 @@ from cryptography.hazmat.primitives.hashes import SHA1, SHA256, SHA512 from cryptography.hazmat.primitives.twofactor import InvalidToken - _ALLOWED_HASH_TYPES = typing.Union[SHA1, SHA256, SHA512] diff --git a/src/cryptography/hazmat/primitives/twofactor/totp.py b/src/cryptography/hazmat/primitives/twofactor/totp.py index 317baba35564..314dbef718af 100644 --- a/src/cryptography/hazmat/primitives/twofactor/totp.py +++ b/src/cryptography/hazmat/primitives/twofactor/totp.py @@ -7,8 +7,8 @@ from cryptography.hazmat.primitives import constant_time from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.hotp import ( - HOTP, _ALLOWED_HASH_TYPES, + HOTP, _generate_uri, ) diff --git a/src/cryptography/x509/__init__.py b/src/cryptography/x509/__init__.py index b3f6e608f8e4..ad924ad42dff 100644 --- a/src/cryptography/x509/__init__.py +++ b/src/cryptography/x509/__init__.py @@ -32,19 +32,19 @@ AuthorityInformationAccess, AuthorityKeyIdentifier, BasicConstraints, + CertificateIssuer, + CertificatePolicies, CRLDistributionPoints, CRLNumber, CRLReason, - CertificateIssuer, - CertificatePolicies, DeltaCRLIndicator, DistributionPoint, DuplicateExtension, ExtendedKeyUsage, Extension, ExtensionNotFound, - ExtensionType, Extensions, + ExtensionType, FreshestCRL, GeneralNames, InhibitAnyPolicy, @@ -58,8 +58,8 @@ OCSPNonce, PolicyConstraints, PolicyInformation, - PrecertPoison, PrecertificateSignedCertificateTimestamps, + PrecertPoison, ReasonFlags, SignedCertificateTimestamps, SubjectAlternativeName, @@ -71,13 +71,13 @@ UserNotice, ) from cryptography.x509.general_name import ( - DNSName, DirectoryName, + DNSName, GeneralName, IPAddress, OtherName, - RFC822Name, RegisteredID, + RFC822Name, UniformResourceIdentifier, UnsupportedGeneralNameType, ) @@ -88,8 +88,8 @@ ) from cryptography.x509.oid import ( AuthorityInformationAccessOID, - CRLEntryExtensionOID, CertificatePoliciesOID, + CRLEntryExtensionOID, ExtendedKeyUsageOID, ExtensionOID, NameOID, @@ -97,7 +97,6 @@ SignatureAlgorithmOID, ) - OID_AUTHORITY_INFORMATION_ACCESS = ExtensionOID.AUTHORITY_INFORMATION_ACCESS OID_AUTHORITY_KEY_IDENTIFIER = ExtensionOID.AUTHORITY_KEY_IDENTIFIER OID_BASIC_CONSTRAINTS = ExtensionOID.BASIC_CONSTRAINTS diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 9c0aad53035b..49713f4c921a 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -27,14 +27,13 @@ ) from cryptography.x509.extensions import ( Extension, - ExtensionType, Extensions, + ExtensionType, _make_sequence_methods, ) from cryptography.x509.name import Name, _ASN1Type from cryptography.x509.oid import ObjectIdentifier - _EARLIEST_UTC_TIME = datetime.datetime(1950, 1, 1) diff --git a/src/cryptography/x509/extensions.py b/src/cryptography/x509/extensions.py index 36be6f253bd9..2012515f2bd3 100644 --- a/src/cryptography/x509/extensions.py +++ b/src/cryptography/x509/extensions.py @@ -23,22 +23,22 @@ SignedCertificateTimestamp, ) from cryptography.x509.general_name import ( - DNSName, + _IPADDRESS_TYPES, DirectoryName, + DNSName, GeneralName, IPAddress, OtherName, - RFC822Name, RegisteredID, + RFC822Name, UniformResourceIdentifier, - _IPADDRESS_TYPES, ) from cryptography.x509.name import Name, RelativeDistinguishedName from cryptography.x509.oid import ( CRLEntryExtensionOID, ExtensionOID, - OCSPExtensionOID, ObjectIdentifier, + OCSPExtensionOID, ) ExtensionTypeVar = typing.TypeVar( diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index 9939233fe95b..a2f12b34b693 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -11,7 +11,6 @@ from cryptography.x509.name import Name from cryptography.x509.oid import ObjectIdentifier - _IPADDRESS_TYPES = typing.Union[ ipaddress.IPv4Address, ipaddress.IPv6Address, diff --git a/src/cryptography/x509/name.py b/src/cryptography/x509/name.py index 702fb4b2140d..acd7c0f1e478 100644 --- a/src/cryptography/x509/name.py +++ b/src/cryptography/x509/name.py @@ -9,9 +9,7 @@ import warnings from cryptography import utils -from cryptography.hazmat.bindings._rust import ( - x509 as rust_x509, -) +from cryptography.hazmat.bindings._rust import x509 as rust_x509 from cryptography.x509.oid import NameOID, ObjectIdentifier diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 0e59fa4bc161..4a08525a7642 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -7,8 +7,7 @@ import datetime import typing -from cryptography import utils -from cryptography import x509 +from cryptography import utils, x509 from cryptography.hazmat.bindings._rust import ocsp from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric.types import ( diff --git a/src/cryptography/x509/oid.py b/src/cryptography/x509/oid.py index 9bfac75a4803..0d91a5469503 100644 --- a/src/cryptography/x509/oid.py +++ b/src/cryptography/x509/oid.py @@ -5,18 +5,17 @@ from cryptography.hazmat._oid import ( AttributeOID, AuthorityInformationAccessOID, - CRLEntryExtensionOID, CertificatePoliciesOID, + CRLEntryExtensionOID, ExtendedKeyUsageOID, ExtensionOID, NameOID, - OCSPExtensionOID, ObjectIdentifier, + OCSPExtensionOID, SignatureAlgorithmOID, SubjectInformationAccessOID, ) - __all__ = [ "AttributeOID", "AuthorityInformationAccessOID", diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index a747f4d03f30..9879ca984b54 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -21,7 +21,6 @@ from cryptography.hazmat.primitives.ciphers.algorithms import AES from cryptography.hazmat.primitives.ciphers.modes import CBC -from ..primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512 from ...doubles import ( DummyAsymmetricPadding, DummyBlockCipherAlgorithm, @@ -34,6 +33,7 @@ load_vectors_from_file, raises_unsupported_algorithm, ) +from ..primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512 def skip_if_libre_ssl(openssl_version): diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py index e23054a6ecf4..ad5c4eb70a0e 100644 --- a/tests/hazmat/backends/test_openssl_memleak.py +++ b/tests/hazmat/backends/test_openssl_memleak.py @@ -13,7 +13,6 @@ from cryptography.hazmat.bindings.openssl.binding import Binding - MEMORY_LEAK_SCRIPT = """ import sys diff --git a/tests/hazmat/primitives/fixtures_dsa.py b/tests/hazmat/primitives/fixtures_dsa.py index eca0ec43168b..6675a2c102fc 100644 --- a/tests/hazmat/primitives/fixtures_dsa.py +++ b/tests/hazmat/primitives/fixtures_dsa.py @@ -9,7 +9,6 @@ DSAPublicNumbers, ) - DSA_KEY_1024 = DSAPrivateNumbers( public_numbers=DSAPublicNumbers( parameter_numbers=DSAParameterNumbers( diff --git a/tests/hazmat/primitives/fixtures_ec.py b/tests/hazmat/primitives/fixtures_ec.py index 317c2ab243ef..fa671ac558c1 100644 --- a/tests/hazmat/primitives/fixtures_ec.py +++ b/tests/hazmat/primitives/fixtures_ec.py @@ -5,7 +5,6 @@ from cryptography.hazmat.primitives.asymmetric import ec - EC_KEY_SECT571R1 = ec.EllipticCurvePrivateNumbers( private_value=int( "213997069697108634621868251335076179190383272087548888968788698953" diff --git a/tests/hazmat/primitives/fixtures_rsa.py b/tests/hazmat/primitives/fixtures_rsa.py index f6b5c3b9fa78..09b32ab00b50 100644 --- a/tests/hazmat/primitives/fixtures_rsa.py +++ b/tests/hazmat/primitives/fixtures_rsa.py @@ -8,7 +8,6 @@ RSAPublicNumbers, ) - RSA_KEY_512 = RSAPrivateNumbers( p=int( "d57846898d5c0de249c08467586cb458fa9bc417cdf297f73cfc52281b787cd9", 16 diff --git a/tests/hazmat/primitives/test_3des.py b/tests/hazmat/primitives/test_3des.py index ea39a2102175..007ecfe21271 100644 --- a/tests/hazmat/primitives/test_3des.py +++ b/tests/hazmat/primitives/test_3des.py @@ -14,8 +14,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index b7a4aedf3ad6..98ebae866f03 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -17,13 +17,13 @@ ChaCha20Poly1305, ) -from .utils import _load_all_params from ...utils import ( load_nist_ccm_vectors, load_nist_vectors, load_vectors_from_file, raises_unsupported_algorithm, ) +from .utils import _load_all_params class FakeData(bytes): diff --git a/tests/hazmat/primitives/test_aes.py b/tests/hazmat/primitives/test_aes.py index 9d68ef2020e5..5798aefc6f56 100644 --- a/tests/hazmat/primitives/test_aes.py +++ b/tests/hazmat/primitives/test_aes.py @@ -10,9 +10,9 @@ from cryptography.hazmat.primitives.ciphers import algorithms, base, modes -from .utils import _load_all_params, generate_encrypt_test from ...doubles import DummyMode from ...utils import load_nist_vectors +from .utils import _load_all_params, generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py index 9220e9e09a8d..c1154a96292b 100644 --- a/tests/hazmat/primitives/test_aes_gcm.py +++ b/tests/hazmat/primitives/test_aes_gcm.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, base, modes -from .utils import generate_aead_test from ...utils import load_nist_vectors +from .utils import generate_aead_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_arc4.py b/tests/hazmat/primitives/test_arc4.py index 5bc23f92ef1f..b589518adfec 100644 --- a/tests/hazmat/primitives/test_arc4.py +++ b/tests/hazmat/primitives/test_arc4.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms -from .utils import generate_stream_encryption_test from ...utils import load_nist_vectors +from .utils import generate_stream_encryption_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_block.py b/tests/hazmat/primitives/test_block.py index fa2c4f52a665..b831de176a0a 100644 --- a/tests/hazmat/primitives/test_block.py +++ b/tests/hazmat/primitives/test_block.py @@ -15,12 +15,12 @@ modes, ) +from ...doubles import DummyCipherAlgorithm, DummyMode +from ...utils import raises_unsupported_algorithm from .utils import ( generate_aead_exception_test, generate_aead_tag_exception_test, ) -from ...doubles import DummyCipherAlgorithm, DummyMode -from ...utils import raises_unsupported_algorithm class TestCipher: diff --git a/tests/hazmat/primitives/test_blowfish.py b/tests/hazmat/primitives/test_blowfish.py index 4ff8c1f2cb9d..b8f34dfcef58 100644 --- a/tests/hazmat/primitives/test_blowfish.py +++ b/tests/hazmat/primitives/test_blowfish.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_camellia.py b/tests/hazmat/primitives/test_camellia.py index 8ec75510bbba..d6f1fca86e13 100644 --- a/tests/hazmat/primitives/test_camellia.py +++ b/tests/hazmat/primitives/test_camellia.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_cryptrec_vectors, load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_cast5.py b/tests/hazmat/primitives/test_cast5.py index 6c6f0c884d2f..a6f186a3c216 100644 --- a/tests/hazmat/primitives/test_cast5.py +++ b/tests/hazmat/primitives/test_cast5.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_chacha20.py b/tests/hazmat/primitives/test_chacha20.py index 4dd1b08cd85d..5337465b99c1 100644 --- a/tests/hazmat/primitives/test_chacha20.py +++ b/tests/hazmat/primitives/test_chacha20.py @@ -11,8 +11,8 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms -from .utils import _load_all_params from ...utils import load_nist_vectors +from .utils import _load_all_params @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_cmac.py b/tests/hazmat/primitives/test_cmac.py index 9596705b19c2..c9e7fdd88fa1 100644 --- a/tests/hazmat/primitives/test_cmac.py +++ b/tests/hazmat/primitives/test_cmac.py @@ -7,10 +7,7 @@ import pytest -from cryptography.exceptions import ( - AlreadyFinalized, - InvalidSignature, -) +from cryptography.exceptions import AlreadyFinalized, InvalidSignature from cryptography.hazmat.primitives.ciphers.algorithms import ( AES, ARC4, @@ -18,11 +15,7 @@ ) from cryptography.hazmat.primitives.cmac import CMAC -from ...utils import ( - load_nist_vectors, - load_vectors_from_file, -) - +from ...utils import load_nist_vectors, load_vectors_from_file vectors_aes128 = load_vectors_from_file( "CMAC/nist-800-38b-aes128.txt", load_nist_vectors diff --git a/tests/hazmat/primitives/test_concatkdf.py b/tests/hazmat/primitives/test_concatkdf.py index bd0117ce11fb..f0dd18828125 100644 --- a/tests/hazmat/primitives/test_concatkdf.py +++ b/tests/hazmat/primitives/test_concatkdf.py @@ -9,8 +9,10 @@ from cryptography.exceptions import AlreadyFinalized, InvalidKey from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHMAC -from cryptography.hazmat.primitives.kdf.concatkdf import ConcatKDFHash +from cryptography.hazmat.primitives.kdf.concatkdf import ( + ConcatKDFHash, + ConcatKDFHMAC, +) class TestConcatKDFHash: diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 6e708676bd19..9a28d6114dc2 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -13,9 +13,9 @@ from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import dh -from .fixtures_dh import FFDH3072_P from ...doubles import DummyKeySerializationEncryption from ...utils import load_nist_vectors, load_vectors_from_file +from .fixtures_dh import FFDH3072_P # RFC 3526 P_1536 = int( diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 424ffcee5f39..4ad4e9317482 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -17,14 +17,14 @@ encode_dss_signature, ) -from .fixtures_dsa import DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072 -from .utils import skip_fips_traditional_openssl from ...doubles import DummyHashAlgorithm, DummyKeySerializationEncryption from ...utils import ( load_fips_dsa_key_pair_vectors, load_fips_dsa_sig_vectors, load_vectors_from_file, ) +from .fixtures_dsa import DSA_KEY_1024, DSA_KEY_2048, DSA_KEY_3072 +from .utils import skip_fips_traditional_openssl _ALGORITHMS_DICT: typing.Dict[str, hashes.HashAlgorithm] = { "SHA1": hashes.SHA1(), diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 3d488be1720c..142024459cf2 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -20,8 +20,6 @@ encode_dss_signature, ) -from .fixtures_ec import EC_KEY_SECP384R1 -from .utils import skip_fips_traditional_openssl from ...doubles import DummyKeySerializationEncryption from ...utils import ( load_fips_ecdsa_key_pair_vectors, @@ -31,6 +29,8 @@ load_vectors_from_file, raises_unsupported_algorithm, ) +from .fixtures_ec import EC_KEY_SECP384R1 +from .utils import skip_fips_traditional_openssl _HASH_TYPES: typing.Dict[str, typing.Type[hashes.HashAlgorithm]] = { "SHA-1": hashes.SHA1, diff --git a/tests/hazmat/primitives/test_hash_vectors.py b/tests/hazmat/primitives/test_hash_vectors.py index d5916f061e14..bde811186268 100644 --- a/tests/hazmat/primitives/test_hash_vectors.py +++ b/tests/hazmat/primitives/test_hash_vectors.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives import hashes -from .utils import _load_all_params, generate_hash_test from ...utils import load_hash_vectors, load_nist_vectors +from .utils import _load_all_params, generate_hash_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_hashes.py b/tests/hazmat/primitives/test_hashes.py index 37744e7457b5..1d096772aed0 100644 --- a/tests/hazmat/primitives/test_hashes.py +++ b/tests/hazmat/primitives/test_hashes.py @@ -10,9 +10,9 @@ from cryptography.exceptions import AlreadyFinalized, _Reasons from cryptography.hazmat.primitives import hashes -from .utils import generate_base_hash_test from ...doubles import DummyHashAlgorithm from ...utils import raises_unsupported_algorithm +from .utils import generate_base_hash_test class TestHashContext: diff --git a/tests/hazmat/primitives/test_hkdf.py b/tests/hazmat/primitives/test_hkdf.py index cc001baf5c38..0bd5c97c48d0 100644 --- a/tests/hazmat/primitives/test_hkdf.py +++ b/tests/hazmat/primitives/test_hkdf.py @@ -12,10 +12,7 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand -from ...utils import ( - load_nist_vectors, - load_vectors_from_file, -) +from ...utils import load_nist_vectors, load_vectors_from_file class TestHKDF: diff --git a/tests/hazmat/primitives/test_hkdf_vectors.py b/tests/hazmat/primitives/test_hkdf_vectors.py index 711d1b5ec34a..080aa1b5b557 100644 --- a/tests/hazmat/primitives/test_hkdf_vectors.py +++ b/tests/hazmat/primitives/test_hkdf_vectors.py @@ -9,8 +9,8 @@ from cryptography.hazmat.primitives import hashes -from .utils import generate_hkdf_test from ...utils import load_nist_vectors +from .utils import generate_hkdf_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_hmac.py b/tests/hazmat/primitives/test_hmac.py index 414385c5dd23..818ff2a7d829 100644 --- a/tests/hazmat/primitives/test_hmac.py +++ b/tests/hazmat/primitives/test_hmac.py @@ -14,9 +14,9 @@ ) from cryptography.hazmat.primitives import hashes, hmac -from .utils import generate_base_hmac_test from ...doubles import DummyHashAlgorithm from ...utils import raises_unsupported_algorithm +from .utils import generate_base_hmac_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_hmac_vectors.py b/tests/hazmat/primitives/test_hmac_vectors.py index 703065a55f40..790993a34ae4 100644 --- a/tests/hazmat/primitives/test_hmac_vectors.py +++ b/tests/hazmat/primitives/test_hmac_vectors.py @@ -9,8 +9,8 @@ from cryptography.hazmat.primitives import hashes, hmac -from .utils import generate_hmac_test from ...utils import load_hash_vectors +from .utils import generate_hmac_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_idea.py b/tests/hazmat/primitives/test_idea.py index d591fe4e7289..9817d5444f9c 100644 --- a/tests/hazmat/primitives/test_idea.py +++ b/tests/hazmat/primitives/test_idea.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_kbkdf.py b/tests/hazmat/primitives/test_kbkdf.py index bb8ebea0df8e..4329e3df60cd 100644 --- a/tests/hazmat/primitives/test_kbkdf.py +++ b/tests/hazmat/primitives/test_kbkdf.py @@ -11,9 +11,9 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.ciphers import algorithms from cryptography.hazmat.primitives.kdf.kbkdf import ( - CounterLocation, KBKDFCMAC, KBKDFHMAC, + CounterLocation, Mode, ) diff --git a/tests/hazmat/primitives/test_kbkdf_vectors.py b/tests/hazmat/primitives/test_kbkdf_vectors.py index fef75fe213ee..cab817bf4e98 100644 --- a/tests/hazmat/primitives/test_kbkdf_vectors.py +++ b/tests/hazmat/primitives/test_kbkdf_vectors.py @@ -5,8 +5,8 @@ import os -from .utils import generate_kbkdf_counter_mode_test from ...utils import load_nist_kbkdf_vectors +from .utils import generate_kbkdf_counter_mode_test class TestCounterKDFCounterMode: diff --git a/tests/hazmat/primitives/test_keywrap.py b/tests/hazmat/primitives/test_keywrap.py index b2fa05d74191..7dfb80901871 100644 --- a/tests/hazmat/primitives/test_keywrap.py +++ b/tests/hazmat/primitives/test_keywrap.py @@ -11,8 +11,8 @@ from cryptography.hazmat.primitives import keywrap from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import _load_all_params from ...utils import load_nist_vectors +from .utils import _load_all_params class TestAESKeyWrap: diff --git a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py index f092894f564e..60d2f864da84 100644 --- a/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py +++ b/tests/hazmat/primitives/test_pbkdf2hmac_vectors.py @@ -7,8 +7,8 @@ from cryptography.hazmat.primitives import hashes -from .utils import generate_pbkdf2_test from ...utils import load_nist_vectors +from .utils import generate_pbkdf2_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 7a4b2f1e3234..919331caf293 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -15,16 +15,25 @@ _Reasons, ) from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import ( - padding, - rsa, - utils as asym_utils, -) +from cryptography.hazmat.primitives.asymmetric import padding, rsa +from cryptography.hazmat.primitives.asymmetric import utils as asym_utils from cryptography.hazmat.primitives.asymmetric.rsa import ( RSAPrivateNumbers, RSAPublicNumbers, ) +from ...doubles import ( + DummyAsymmetricPadding, + DummyHashAlgorithm, + DummyKeySerializationEncryption, +) +from ...utils import ( + load_nist_vectors, + load_pkcs1_vectors, + load_rsa_nist_vectors, + load_vectors_from_file, + raises_unsupported_algorithm, +) from .fixtures_rsa import ( RSA_KEY_1024, RSA_KEY_1025, @@ -48,18 +57,6 @@ generate_rsa_verification_test, skip_fips_traditional_openssl, ) -from ...doubles import ( - DummyAsymmetricPadding, - DummyHashAlgorithm, - DummyKeySerializationEncryption, -) -from ...utils import ( - load_nist_vectors, - load_pkcs1_vectors, - load_rsa_nist_vectors, - load_vectors_from_file, - raises_unsupported_algorithm, -) class DummyMGF(padding.MGF): diff --git a/tests/hazmat/primitives/test_scrypt.py b/tests/hazmat/primitives/test_scrypt.py index 6e95a1f26d31..4b4641854755 100644 --- a/tests/hazmat/primitives/test_scrypt.py +++ b/tests/hazmat/primitives/test_scrypt.py @@ -8,12 +8,8 @@ import pytest -from cryptography.exceptions import ( - AlreadyFinalized, - InvalidKey, -) -from cryptography.hazmat.primitives.kdf.scrypt import Scrypt, _MEM_LIMIT - +from cryptography.exceptions import AlreadyFinalized, InvalidKey +from cryptography.hazmat.primitives.kdf.scrypt import _MEM_LIMIT, Scrypt from tests.utils import ( load_nist_vectors, load_vectors_from_file, diff --git a/tests/hazmat/primitives/test_seed.py b/tests/hazmat/primitives/test_seed.py index eb0b88c2aaf4..9f68bc3fb10d 100644 --- a/tests/hazmat/primitives/test_seed.py +++ b/tests/hazmat/primitives/test_seed.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 3a08d55709b7..3f1a55c23d6d 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -39,15 +39,11 @@ ) from cryptography.hazmat.primitives.serialization.pkcs12 import PBES - -from .fixtures_rsa import RSA_KEY_2048 -from .test_ec import _skip_curve_unsupported -from .utils import ( - _check_dsa_private_numbers, - _check_rsa_private_numbers, -) from ...doubles import DummyKeySerializationEncryption from ...utils import load_vectors_from_file, raises_unsupported_algorithm +from .fixtures_rsa import RSA_KEY_2048 +from .test_ec import _skip_curve_unsupported +from .utils import _check_dsa_private_numbers, _check_rsa_private_numbers def _skip_fips_format(key_path, password, backend): diff --git a/tests/hazmat/primitives/test_sm4.py b/tests/hazmat/primitives/test_sm4.py index 07b0cc7f733c..13d9b5051c42 100644 --- a/tests/hazmat/primitives/test_sm4.py +++ b/tests/hazmat/primitives/test_sm4.py @@ -9,8 +9,8 @@ from cryptography.hazmat.primitives.ciphers import algorithms, modes -from .utils import generate_encrypt_test from ...utils import load_nist_vectors +from .utils import generate_encrypt_test @pytest.mark.supported( diff --git a/tests/hazmat/primitives/twofactor/test_hotp.py b/tests/hazmat/primitives/twofactor/test_hotp.py index d1c6cb530940..31e01a495256 100644 --- a/tests/hazmat/primitives/twofactor/test_hotp.py +++ b/tests/hazmat/primitives/twofactor/test_hotp.py @@ -12,10 +12,7 @@ from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.hotp import HOTP -from ....utils import ( - load_nist_vectors, - load_vectors_from_file, -) +from ....utils import load_nist_vectors, load_vectors_from_file vectors = load_vectors_from_file("twofactor/rfc-4226.txt", load_nist_vectors) diff --git a/tests/hazmat/primitives/twofactor/test_totp.py b/tests/hazmat/primitives/twofactor/test_totp.py index 3c8d6b372af6..f68a8339c443 100644 --- a/tests/hazmat/primitives/twofactor/test_totp.py +++ b/tests/hazmat/primitives/twofactor/test_totp.py @@ -9,10 +9,7 @@ from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.twofactor.totp import TOTP -from ....utils import ( - load_nist_vectors, - load_vectors_from_file, -) +from ....utils import load_nist_vectors, load_vectors_from_file vectors = load_vectors_from_file("twofactor/rfc-6238.txt", load_nist_vectors) diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index c8021cc2faa3..aac7296e641d 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -26,9 +26,9 @@ from cryptography.hazmat.primitives.ciphers.modes import GCM from cryptography.hazmat.primitives.kdf.hkdf import HKDF, HKDFExpand from cryptography.hazmat.primitives.kdf.kbkdf import ( - CounterLocation, KBKDFCMAC, KBKDFHMAC, + CounterLocation, Mode, ) from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC diff --git a/tests/test_fernet.py b/tests/test_fernet.py index 58dd7729631c..d4b1561a0af6 100644 --- a/tests/test_fernet.py +++ b/tests/test_fernet.py @@ -10,16 +10,13 @@ import time import iso8601 - import pretend - import pytest +import cryptography_vectors from cryptography.fernet import Fernet, InvalidToken, MultiFernet from cryptography.hazmat.primitives.ciphers import algorithms, modes -import cryptography_vectors - def json_parametrize(keys, filename): vector_file = cryptography_vectors.open_vector_file( diff --git a/tests/test_utils.py b/tests/test_utils.py index 8b07c91b05f5..9f6e271500cc 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -9,14 +9,12 @@ import textwrap import pretend - import pytest import cryptography import cryptography.utils -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons - import cryptography_vectors +from cryptography.exceptions import UnsupportedAlgorithm, _Reasons from . import deprecated_module from .utils import ( diff --git a/tests/utils.py b/tests/utils.py index 6119d3f4d572..405cfbc783d1 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -13,10 +13,8 @@ import pytest -from cryptography.exceptions import UnsupportedAlgorithm - import cryptography_vectors - +from cryptography.exceptions import UnsupportedAlgorithm HashVector = collections.namedtuple("HashVector", ["message", "digest"]) KeyedHashVector = collections.namedtuple( diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py index 891d8df4301b..ce83fe3c0fa2 100644 --- a/tests/wycheproof/test_aes.py +++ b/tests/wycheproof/test_aes.py @@ -12,8 +12,8 @@ from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.ciphers.aead import AESCCM, AESGCM -from .utils import wycheproof_tests from ..hazmat.primitives.test_aead import _aead_supported +from .utils import wycheproof_tests @wycheproof_tests("aes_cbc_pkcs5_test.json") diff --git a/tests/wycheproof/test_chacha20poly1305.py b/tests/wycheproof/test_chacha20poly1305.py index 7cb8ff50f930..06d6fc76a092 100644 --- a/tests/wycheproof/test_chacha20poly1305.py +++ b/tests/wycheproof/test_chacha20poly1305.py @@ -10,8 +10,8 @@ from cryptography.exceptions import InvalidTag from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305 -from .utils import wycheproof_tests from ..hazmat.primitives.test_aead import _aead_supported +from .utils import wycheproof_tests @pytest.mark.skipif( diff --git a/tests/wycheproof/test_dsa.py b/tests/wycheproof/test_dsa.py index 3d31ee170dd5..b7da82dc3c09 100644 --- a/tests/wycheproof/test_dsa.py +++ b/tests/wycheproof/test_dsa.py @@ -13,7 +13,6 @@ from .utils import wycheproof_tests - _DIGESTS = { "SHA-1": hashes.SHA1(), "SHA-224": hashes.SHA224(), diff --git a/tests/wycheproof/test_ecdh.py b/tests/wycheproof/test_ecdh.py index 672863fe7610..1de26cb263bd 100644 --- a/tests/wycheproof/test_ecdh.py +++ b/tests/wycheproof/test_ecdh.py @@ -11,9 +11,8 @@ from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric import ec -from .utils import wycheproof_tests from ..hazmat.primitives.test_ec import _skip_exchange_algorithm_unsupported - +from .utils import wycheproof_tests _CURVES = { "secp224r1": ec.SECP224R1(), diff --git a/tests/wycheproof/test_ecdsa.py b/tests/wycheproof/test_ecdsa.py index b2ec9dfec151..ffdfcc461342 100644 --- a/tests/wycheproof/test_ecdsa.py +++ b/tests/wycheproof/test_ecdsa.py @@ -13,7 +13,6 @@ from .utils import wycheproof_tests - _DIGESTS = { "SHA-1": hashes.SHA1(), "SHA-224": hashes.SHA224(), diff --git a/tests/wycheproof/test_hkdf.py b/tests/wycheproof/test_hkdf.py index 4886be0fe8cc..3d54e44ffc6e 100644 --- a/tests/wycheproof/test_hkdf.py +++ b/tests/wycheproof/test_hkdf.py @@ -12,7 +12,6 @@ from .utils import wycheproof_tests - _HASH_ALGORITHMS = { "HKDF-SHA-1": hashes.SHA1(), "HKDF-SHA-256": hashes.SHA256(), diff --git a/tests/wycheproof/test_hmac.py b/tests/wycheproof/test_hmac.py index 84b0c19a0539..49fe772cb67a 100644 --- a/tests/wycheproof/test_hmac.py +++ b/tests/wycheproof/test_hmac.py @@ -12,7 +12,6 @@ from .utils import wycheproof_tests - _HMAC_ALGORITHMS = { "HMACSHA1": hashes.SHA1(), "HMACSHA224": hashes.SHA224(), diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index e2b8426fd0f6..56ec21bc073b 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -13,7 +13,6 @@ from .utils import wycheproof_tests - _DIGESTS = { "SHA-1": hashes.SHA1(), "SHA-224": hashes.SHA224(), diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index 9090e5205ab7..ade9161953dd 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -15,9 +15,9 @@ from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 from cryptography.x509 import ocsp -from .test_x509 import DummyExtension, _load_cert from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1 from ..utils import load_vectors_from_file, raises_unsupported_algorithm +from .test_x509 import DummyExtension, _load_cert def _load_data(filename, loader): diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 8a92c297c96d..1de0f6c4591a 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -12,7 +12,6 @@ import typing import pytest - import pytz from cryptography import utils, x509 diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index e3e34285d7b2..5960cdd3b7bf 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -6,7 +6,6 @@ import datetime import pytest - import pytz from cryptography import x509 @@ -18,11 +17,11 @@ SignatureAlgorithmOID, ) -from .test_x509 import DummyExtension from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048 from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1 from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512 from ..hazmat.primitives.test_ec import _skip_curve_unsupported +from .test_x509 import DummyExtension class TestCertificateRevocationListBuilder: diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 7284a73beb6d..d3276b7cd370 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -10,7 +10,6 @@ import typing import pretend - import pytest from cryptography import x509 @@ -37,10 +36,10 @@ SubjectInformationAccessOID, ) -from .test_x509 import _load_cert from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048 from ..hazmat.primitives.test_ec import _skip_curve_unsupported from ..utils import load_vectors_from_file +from .test_x509 import _load_cert def _make_certbuilder(private_key): diff --git a/tests/x509/test_x509_revokedcertbuilder.py b/tests/x509/test_x509_revokedcertbuilder.py index b2facfa51e0e..83a71ff9b6ed 100644 --- a/tests/x509/test_x509_revokedcertbuilder.py +++ b/tests/x509/test_x509_revokedcertbuilder.py @@ -6,7 +6,6 @@ import datetime import pytest - import pytz from cryptography import x509 diff --git a/tox.ini b/tox.ini index 546c6cdd6cb3..5159c5a1a120 100644 --- a/tox.ini +++ b/tox.ini @@ -64,7 +64,7 @@ deps = types-pytz check-manifest commands = - flake8 . + ruff . black --check . check-manifest mypy src/cryptography/ vectors/cryptography_vectors/ tests/ diff --git a/vectors/cryptography_vectors/__init__.py b/vectors/cryptography_vectors/__init__.py index 1fe176754275..443357b28d56 100644 --- a/vectors/cryptography_vectors/__init__.py +++ b/vectors/cryptography_vectors/__init__.py @@ -7,7 +7,6 @@ from cryptography_vectors.__about__ import __version__ - __all__ = [ "__version__", ] diff --git a/vectors/setup.py b/vectors/setup.py index 68ff1cd8a507..88d88a75d8b0 100644 --- a/vectors/setup.py +++ b/vectors/setup.py @@ -6,5 +6,4 @@ from setuptools import setup - setup() From 9de11c1548fe5abf1961fe3e715fe8c696f31c6b Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 21 Dec 2022 18:54:32 +0700 Subject: [PATCH 269/298] Add openssl 3.1.0b1 to test matrix (#7921) --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 830efe9a8497..b63ae3e8d82a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,7 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.0.7", CONFIG_FLAGS: "no-legacy", NO_LEGACY: "1"}} - {VERSION: "3.11", TOXENV: "py311", TOXARGS: "--enable-fips=1", OPENSSL: {TYPE: "openssl", CONFIG_FLAGS: "enable-fips", VERSION: "3.0.7"}} + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "3.1.0-beta1"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.5.3"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.6.1"}} - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.7.0"}} From df3c32080d0fa7d4b7b466c1b9128163b284ac76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 12:15:40 +0000 Subject: [PATCH 270/298] Bump actions/stale from 6.0.1 to 7.0.0 (#7922) Bumps [actions/stale](https://github.com/actions/stale) from 6.0.1 to 7.0.0. - [Release notes](https://github.com/actions/stale/releases) - [Changelog](https://github.com/actions/stale/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/stale/compare/v6.0.1...v7.0.0) --- updated-dependencies: - dependency-name: actions/stale dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/auto-close-stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/auto-close-stale.yml b/.github/workflows/auto-close-stale.yml index 48ebd8e571f7..a08b2d9cae9f 100644 --- a/.github/workflows/auto-close-stale.yml +++ b/.github/workflows/auto-close-stale.yml @@ -13,7 +13,7 @@ jobs: if: github.repository_owner == 'pyca' runs-on: ubuntu-latest steps: - - uses: actions/stale@v6.0.1 + - uses: actions/stale@v7.0.0 with: only-labels: waiting-on-reporter days-before-stale: 5 From 95f951c1bf93621aa5a7fade4e848c801fb062f6 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Wed, 21 Dec 2022 19:47:34 -0500 Subject: [PATCH 271/298] Bump BoringSSL and/or OpenSSL in CI (#7923) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b63ae3e8d82a..192338aa9110 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,10 +40,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.7.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 21, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "d1b20a9580aebb6fbb0b1b2408cf1221d83afb71"}} - # Latest commit on the OpenSSL master branch, as of Dec 17, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "f5b06306b7727f830407c639f8a7bf1698f8aaa5"}} + # Latest commit on the BoringSSL master branch, as of Dec 22, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "90e3b6e68c0a9ff79de8cfb92fa81e6cd2a9d57d"}} + # Latest commit on the OpenSSL master branch, as of Dec 22, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "42061268ee8f9ae0555d522870740fc91b744f4f"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 1868450ee8dacf63e052d951828c0fe19f7c061c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 12:14:47 +0000 Subject: [PATCH 272/298] Bump actions/cache from 3.0.11 to 3.2.0 (#7924) Bumps [actions/cache](https://github.com/actions/cache) from 3.0.11 to 3.2.0. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.0.11...v3.2.0) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/macarm64.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 192338aa9110..1de4ea0a2a5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 timeout-minutes: 5 with: path: | @@ -89,7 +89,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.0.11 + uses: actions/cache@v3.2.0 id: ossl-cache timeout-minutes: 5 with: @@ -148,7 +148,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 timeout-minutes: 5 with: path: | @@ -208,7 +208,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 timeout-minutes: 5 with: path: | @@ -259,7 +259,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 id: cargo-cache timeout-minutes: 5 with: @@ -345,7 +345,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 timeout-minutes: 5 with: path: | @@ -415,7 +415,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 timeout-minutes: 5 with: path: | @@ -477,7 +477,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 timeout-minutes: 5 with: path: | diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index e178fcb22d6a..1d4453d167ff 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3.2.0 with: persist-credentials: false - - uses: actions/cache@v3.0.11 + - uses: actions/cache@v3.2.0 with: path: | src/rust/target/ From 0ee233c0ef2501d8f608727f2ae3337412328259 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 22 Dec 2022 12:20:29 +0000 Subject: [PATCH 273/298] Bump libc from 0.2.138 to 0.2.139 in /src/rust (#7925) Bumps [libc](https://github.com/rust-lang/libc) from 0.2.138 to 0.2.139. - [Release notes](https://github.com/rust-lang/libc/releases) - [Commits](https://github.com/rust-lang/libc/compare/0.2.138...0.2.139) --- updated-dependencies: - dependency-name: libc dependency-type: indirect update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- src/rust/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rust/Cargo.lock b/src/rust/Cargo.lock index 2fe046e370e6..02b8e8c73488 100644 --- a/src/rust/Cargo.lock +++ b/src/rust/Cargo.lock @@ -231,9 +231,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "link-cplusplus" From 011209feb8604967daef718aac0c53433306967c Mon Sep 17 00:00:00 2001 From: Nuno Veloso Date: Thu, 22 Dec 2022 23:48:39 +0000 Subject: [PATCH 274/298] Add SSL_CTX_set_msg_callback functions (#7926) * Add SSL_CTX_set_msg_callback functions to openssl/ssl.py function definitions * Fix E501 Line too long Co-authored-by: Nuno Veloso --- src/_cffi_src/openssl/ssl.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 0a6a124e19fd..a9be153416d2 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -296,6 +296,18 @@ void SSL_CTX_set_info_callback(SSL_CTX *, void (*)(const SSL *, int, int)); void (*SSL_CTX_get_info_callback(SSL_CTX *))(const SSL *, int, int); +void SSL_CTX_set_msg_callback(SSL_CTX *, + void (*)( + int, + int, + int, + const void *, + size_t, + SSL *, + void * + )); +void SSL_CTX_set_msg_callback_arg(SSL_CTX *, void *); + void SSL_CTX_set_keylog_callback(SSL_CTX *, void (*)(const SSL *, const char *)); void (*SSL_CTX_get_keylog_callback(SSL_CTX *))(const SSL *, const char *); From 831a02c8e9b1dfc353ebc99a7714b1e03567061e Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Fri, 23 Dec 2022 00:22:01 +0000 Subject: [PATCH 275/298] Bump BoringSSL and/or OpenSSL in CI (#7927) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1de4ea0a2a5a..b13ebd89d3c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,10 +40,10 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.7.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 22, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "90e3b6e68c0a9ff79de8cfb92fa81e6cd2a9d57d"}} - # Latest commit on the OpenSSL master branch, as of Dec 22, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "42061268ee8f9ae0555d522870740fc91b744f4f"}} + # Latest commit on the BoringSSL master branch, as of Dec 23, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "31bad2514d21f6207f3925ba56754611c462a873"}} + # Latest commit on the OpenSSL master branch, as of Dec 23, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "98663afce7a909be1518921a9995540308a52462"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From f1320f46fa87a8d75976f0b959c20b7704fabf2f Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 22 Dec 2022 20:55:08 -0500 Subject: [PATCH 276/298] fixes #7912 -- correct metadata for version (#7928) --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 07cce535b656..7a78922c0e2d 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 = BSD-3-Clause OR Apache-2.0 +license = (Apache-2.0 OR BSD-3-Clause) AND PSF-2.0 url = https://github.com/pyca/cryptography author = The Python Cryptographic Authority and individual contributors author_email = cryptography-dev@python.org From b1cff62f5b59f7efe814228364b691ad8701faa8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 23 Dec 2022 00:10:37 -0500 Subject: [PATCH 277/298] Pre-annouce build process changes for #7164 (#7929) * Pre-annouce build process changes for #7164 * Update CHANGELOG.rst Co-authored-by: Paul Kehrer Co-authored-by: Paul Kehrer --- CHANGELOG.rst | 8 ++++++++ docs/faq.rst | 1 - docs/installation.rst | 6 +++--- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index fce205de1c37..18988afe39c3 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -27,6 +27,13 @@ Changelog PKCS7 has been removed. * **BACKWARDS INCOMPATIBLE:** Dropped support for macOS 10.10 and 10.11, macOS users must upgrade to 10.12 or newer. +* **ANNOUNCEMENT:** The next version of ``cryptography`` (40.0) will change + the way we link OpenSSL. This will only impact users who build + ``cryptography`` from source (i.e., not from a ``wheel``), and specify their + own version of OpenSSL. For those users, the ``CFLAGS``, ``LDFLAGS``, + ``INCLUDE``, ``LIB``, and ``CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS`` environment + variables will no longer be respected. Instead, users will need to + configure their builds `as documented here`_. * Added support for :ref:`disabling the legacy provider in OpenSSL 3.0.x`. * Added support for disabling RSA key validation checks when loading RSA @@ -2094,5 +2101,6 @@ Changelog * Initial release. +.. _`as documented here`: https://docs.rs/openssl/latest/openssl/#automatic .. _`main`: https://github.com/pyca/cryptography/ .. _`cffi`: https://cffi.readthedocs.io/ diff --git a/docs/faq.rst b/docs/faq.rst index a520345696c3..1bbf5eb4b7a9 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -216,7 +216,6 @@ supportive, but we cannot commit to doing the work ourselves. .. _`NaCl`: https://nacl.cr.yp.to/ .. _`PyNaCl`: https://pynacl.readthedocs.io -.. _`WSGIApplicationGroup`: https://modwsgi.readthedocs.io/en/develop/configuration-directives/WSGIApplicationGroup.html .. _`issue`: https://github.com/pyca/cryptography/issues .. _`memory safety`: https://alexgaynor.net/2019/aug/12/introduction-to-memory-unsafety-for-vps-of-engineering/ .. _`building .zip archives for Lambda`: https://docs.aws.amazon.com/lambda/latest/dg/python-package.html diff --git a/docs/installation.rst b/docs/installation.rst index 9b46a7345c5c..a52a9df6d49f 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -111,7 +111,7 @@ Alpine .. code-block:: console - $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev cargo + $ sudo apk add gcc musl-dev python3-dev libffi-dev openssl-dev cargo pkgconfig If you get an error with ``openssl-dev`` you may have to use ``libressl-dev``. @@ -128,7 +128,7 @@ Debian/Ubuntu .. code-block:: console $ sudo apt-get install build-essential libssl-dev libffi-dev \ - python3-dev cargo + python3-dev cargo pkg-config Fedora/RHEL/CentOS ~~~~~~~~~~~~~~~~~~ @@ -143,7 +143,7 @@ Fedora/RHEL/CentOS .. code-block:: console $ sudo dnf install redhat-rpm-config gcc libffi-devel python3-devel \ - openssl-devel cargo + openssl-devel cargo pkg-config Building From 5228aa3955071e1b24c41fc3ea510bfb5c6cc830 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Dec 2022 12:11:36 +0000 Subject: [PATCH 278/298] Bump actions/cache from 3.2.0 to 3.2.1 (#7930) Bumps [actions/cache](https://github.com/actions/cache) from 3.2.0 to 3.2.1. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.2.0...v3.2.1) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/macarm64.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b13ebd89d3c3..6b31d56ccaae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: uses: actions/setup-python@v4.3.1 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 timeout-minutes: 5 with: path: | @@ -89,7 +89,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.2.0 + uses: actions/cache@v3.2.1 id: ossl-cache timeout-minutes: 5 with: @@ -148,7 +148,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 timeout-minutes: 5 with: path: | @@ -208,7 +208,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 timeout-minutes: 5 with: path: | @@ -259,7 +259,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 id: cargo-cache timeout-minutes: 5 with: @@ -345,7 +345,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 timeout-minutes: 5 with: path: | @@ -415,7 +415,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 timeout-minutes: 5 with: path: | @@ -477,7 +477,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 timeout-minutes: 5 with: path: | diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index 1d4453d167ff..b6140bc0aa0f 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3.2.0 with: persist-credentials: false - - uses: actions/cache@v3.2.0 + - uses: actions/cache@v3.2.1 with: path: | src/rust/target/ From 9f8164e32190c4be920bfac3f4c65a68b4b6da42 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 23 Dec 2022 12:29:30 +0000 Subject: [PATCH 279/298] Bump actions/setup-python from 4.3.1 to 4.4.0 (#7931) Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4.3.1 to 4.4.0. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v4.3.1...v4.4.0) --- updated-dependencies: - dependency-name: actions/setup-python dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/benchmark.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/wheel-builder.yml | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 2cce7d6d3b06..2d14948f95b4 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -28,7 +28,7 @@ jobs: - name: Setup python id: setup-python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: "3.11" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6b31d56ccaae..2fa527d90a45 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -53,7 +53,7 @@ jobs: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: actions/cache@v3.2.1 @@ -222,7 +222,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} - name: Setup python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f @@ -274,7 +274,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-rust-${{ matrix.RUST }}-coverage - name: Setup python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f @@ -359,7 +359,7 @@ jobs: key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} @@ -411,7 +411,7 @@ jobs: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} @@ -491,7 +491,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON }} - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install @@ -527,7 +527,7 @@ jobs: with: persist-credentials: false - name: Setup python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: 3.11 - run: python -m pip install -U tox @@ -551,7 +551,7 @@ jobs: jobs: ${{ toJSON(needs) }} - name: Setup python if: ${{ always() }} - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: '3.10' - run: pip install coverage[toml] diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index f093f93e3867..35e886c84afc 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -168,7 +168,7 @@ jobs: PYTHON_DOWNLOAD_URL: ${{ matrix.PYTHON.DOWNLOAD_URL }} if: contains(matrix.PYTHON.VERSION, 'pypy') == false - name: Setup pypy - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} if: contains(matrix.PYTHON.VERSION, 'pypy') @@ -246,7 +246,7 @@ jobs: name: cryptography-sdist - name: Setup python - uses: actions/setup-python@v4.3.1 + uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} From 6f6b58d941d1ece3920342fe5c00820b020e9ebe Mon Sep 17 00:00:00 2001 From: April King Date: Fri, 23 Dec 2022 11:31:03 -0600 Subject: [PATCH 280/298] Update code to match Django recommendations (#7932) --- docs/fernet.rst | 6 +++--- docs/hazmat/primitives/key-derivation-functions.rst | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/fernet.rst b/docs/fernet.rst index 167cf51f2747..0533e10642dc 100644 --- a/docs/fernet.rst +++ b/docs/fernet.rst @@ -237,7 +237,7 @@ password through a key derivation function such as ... algorithm=hashes.SHA256(), ... length=32, ... salt=salt, - ... iterations=390000, + ... iterations=480000, ... ) >>> key = base64.urlsafe_b64encode(kdf.derive(password)) >>> f = Fernet(key) @@ -252,7 +252,7 @@ to derive the same key from the password in the future. The iteration count used should be adjusted to be as high as your server can tolerate. A good default is at least 480,000 iterations, which is what `Django -recommends as of July 2022`_. +recommends as of December 2022`_. Implementation -------------- @@ -280,5 +280,5 @@ unsuitable for very large files at this time. .. _`Fernet`: https://github.com/fernet/spec/ -.. _`Django recommends as of July 2022`: https://github.com/django/django/blob/main/django/contrib/auth/hashers.py +.. _`Django recommends as of December 2022`: https://github.com/django/django/blob/main/django/contrib/auth/hashers.py .. _`specification`: https://github.com/fernet/spec/blob/master/Spec.md diff --git a/docs/hazmat/primitives/key-derivation-functions.rst b/docs/hazmat/primitives/key-derivation-functions.rst index ddd3356166e0..6427645db78f 100644 --- a/docs/hazmat/primitives/key-derivation-functions.rst +++ b/docs/hazmat/primitives/key-derivation-functions.rst @@ -62,7 +62,7 @@ PBKDF2 ... algorithm=hashes.SHA256(), ... length=32, ... salt=salt, - ... iterations=390000, + ... iterations=480000, ... ) >>> key = kdf.derive(b"my great password") >>> # verify @@ -70,7 +70,7 @@ PBKDF2 ... algorithm=hashes.SHA256(), ... length=32, ... salt=salt, - ... iterations=390000, + ... iterations=480000, ... ) >>> kdf.verify(b"my great password", key) From 3f1b55b16544f07235e83f45baafe7ae0beb9387 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 26 Dec 2022 10:08:28 -0500 Subject: [PATCH 281/298] Update formatting for new ruff (#7937) --- .../hazmat/backends/openssl/backend.py | 20 +++++++++---------- .../hazmat/primitives/asymmetric/types.py | 4 ++-- .../hazmat/primitives/serialization/pkcs12.py | 2 +- src/cryptography/x509/base.py | 4 ++-- tests/hazmat/backends/test_openssl.py | 2 +- tests/hazmat/primitives/test_pkcs12.py | 2 +- tests/hazmat/primitives/test_rsa.py | 8 ++++---- tests/hazmat/primitives/test_serialization.py | 4 ++-- tests/wycheproof/test_eddsa.py | 2 +- tests/x509/test_ocsp.py | 2 +- tests/x509/test_x509.py | 6 +++--- tests/x509/test_x509_crlbuilder.py | 4 ++-- 12 files changed, 30 insertions(+), 30 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 5294e5d1405f..48f4265b023c 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -30,15 +30,15 @@ _EllipticCurvePrivateKey, _EllipticCurvePublicKey, ) -from cryptography.hazmat.backends.openssl.ed25519 import ( - _Ed25519PrivateKey, - _Ed25519PublicKey, -) from cryptography.hazmat.backends.openssl.ed448 import ( _ED448_KEY_SIZE, _Ed448PrivateKey, _Ed448PublicKey, ) +from cryptography.hazmat.backends.openssl.ed25519 import ( + _Ed25519PrivateKey, + _Ed25519PublicKey, +) from cryptography.hazmat.backends.openssl.hashes import _HashContext from cryptography.hazmat.backends.openssl.hmac import _HMACContext from cryptography.hazmat.backends.openssl.poly1305 import ( @@ -49,14 +49,14 @@ _RSAPrivateKey, _RSAPublicKey, ) -from cryptography.hazmat.backends.openssl.x25519 import ( - _X25519PrivateKey, - _X25519PublicKey, -) from cryptography.hazmat.backends.openssl.x448 import ( _X448PrivateKey, _X448PublicKey, ) +from cryptography.hazmat.backends.openssl.x25519 import ( + _X25519PrivateKey, + _X25519PublicKey, +) from cryptography.hazmat.bindings._rust import x509 as rust_x509 from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization @@ -65,11 +65,11 @@ dh, dsa, ec, - ed25519, ed448, + ed25519, rsa, - x25519, x448, + x25519, ) from cryptography.hazmat.primitives.asymmetric.padding import ( MGF1, diff --git a/src/cryptography/hazmat/primitives/asymmetric/types.py b/src/cryptography/hazmat/primitives/asymmetric/types.py index 369fbf8f2f3c..6b5ff08017e2 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/types.py +++ b/src/cryptography/hazmat/primitives/asymmetric/types.py @@ -8,11 +8,11 @@ dh, dsa, ec, - ed25519, ed448, + ed25519, rsa, - x25519, x448, + x25519, ) # Every asymmetric key type diff --git a/src/cryptography/hazmat/primitives/serialization/pkcs12.py b/src/cryptography/hazmat/primitives/serialization/pkcs12.py index b4d9a34362e0..05212257d72d 100644 --- a/src/cryptography/hazmat/primitives/serialization/pkcs12.py +++ b/src/cryptography/hazmat/primitives/serialization/pkcs12.py @@ -10,8 +10,8 @@ from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, - ed25519, ed448, + ed25519, rsa, ) from cryptography.hazmat.primitives.asymmetric.types import PRIVATE_KEY_TYPES diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index 49713f4c921a..d1914efe8d7e 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -14,11 +14,11 @@ from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, - ed25519, ed448, + ed25519, rsa, - x25519, x448, + x25519, ) from cryptography.hazmat.primitives.asymmetric.types import ( CERTIFICATE_ISSUER_PUBLIC_KEY_TYPES, diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 9879ca984b54..9a706a1bb11a 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -33,7 +33,7 @@ load_vectors_from_file, raises_unsupported_algorithm, ) -from ..primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512 +from ..primitives.fixtures_rsa import RSA_KEY_512, RSA_KEY_2048 def skip_if_libre_ssl(openssl_version): diff --git a/tests/hazmat/primitives/test_pkcs12.py b/tests/hazmat/primitives/test_pkcs12.py index c9ef57e66bd2..9b6e6740870b 100644 --- a/tests/hazmat/primitives/test_pkcs12.py +++ b/tests/hazmat/primitives/test_pkcs12.py @@ -15,8 +15,8 @@ from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, - ed25519, ed448, + ed25519, rsa, ) from cryptography.hazmat.primitives.serialization import ( diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 919331caf293..31ae8b047c85 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -35,6 +35,10 @@ raises_unsupported_algorithm, ) from .fixtures_rsa import ( + RSA_KEY_512, + RSA_KEY_522, + RSA_KEY_599, + RSA_KEY_745, RSA_KEY_1024, RSA_KEY_1025, RSA_KEY_1026, @@ -46,10 +50,6 @@ RSA_KEY_1536, RSA_KEY_2048, RSA_KEY_2048_ALT, - RSA_KEY_512, - RSA_KEY_522, - RSA_KEY_599, - RSA_KEY_745, RSA_KEY_CORRUPTED, ) from .utils import ( diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 3f1a55c23d6d..6b026eb8e863 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -13,11 +13,11 @@ from cryptography.hazmat.primitives.asymmetric import ( dsa, ec, - ed25519, ed448, + ed25519, rsa, - x25519, x448, + x25519, ) from cryptography.hazmat.primitives.hashes import SHA1 from cryptography.hazmat.primitives.serialization import ( diff --git a/tests/wycheproof/test_eddsa.py b/tests/wycheproof/test_eddsa.py index 2de695f57f0a..3b5dae37749f 100644 --- a/tests/wycheproof/test_eddsa.py +++ b/tests/wycheproof/test_eddsa.py @@ -8,8 +8,8 @@ import pytest from cryptography.exceptions import InvalidSignature -from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey from cryptography.hazmat.primitives.asymmetric.ed448 import Ed448PublicKey +from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey from .utils import wycheproof_tests diff --git a/tests/x509/test_ocsp.py b/tests/x509/test_ocsp.py index ade9161953dd..bd9204865867 100644 --- a/tests/x509/test_ocsp.py +++ b/tests/x509/test_ocsp.py @@ -11,7 +11,7 @@ from cryptography import x509 from cryptography.hazmat.primitives import hashes, serialization -from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448, rsa +from cryptography.hazmat.primitives.asymmetric import ec, ed448, ed25519, rsa from cryptography.hazmat.primitives.asymmetric.padding import PKCS1v15 from cryptography.x509 import ocsp diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 1de0f6c4591a..59587294e5dd 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -21,12 +21,12 @@ dh, dsa, ec, - ed25519, ed448, + ed25519, padding, rsa, - x25519, x448, + x25519, ) from cryptography.hazmat.primitives.asymmetric.utils import ( decode_dss_signature, @@ -43,7 +43,7 @@ from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048 from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1 -from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512 +from ..hazmat.primitives.fixtures_rsa import RSA_KEY_512, RSA_KEY_2048 from ..hazmat.primitives.test_ec import _skip_curve_unsupported from ..utils import ( load_nist_vectors, diff --git a/tests/x509/test_x509_crlbuilder.py b/tests/x509/test_x509_crlbuilder.py index 5960cdd3b7bf..9af98e40b262 100644 --- a/tests/x509/test_x509_crlbuilder.py +++ b/tests/x509/test_x509_crlbuilder.py @@ -10,7 +10,7 @@ from cryptography import x509 from cryptography.hazmat.primitives import hashes -from cryptography.hazmat.primitives.asymmetric import ec, ed25519, ed448 +from cryptography.hazmat.primitives.asymmetric import ec, ed448, ed25519 from cryptography.x509.oid import ( AuthorityInformationAccessOID, NameOID, @@ -19,7 +19,7 @@ from ..hazmat.primitives.fixtures_dsa import DSA_KEY_2048 from ..hazmat.primitives.fixtures_ec import EC_KEY_SECP256R1 -from ..hazmat.primitives.fixtures_rsa import RSA_KEY_2048, RSA_KEY_512 +from ..hazmat.primitives.fixtures_rsa import RSA_KEY_512, RSA_KEY_2048 from ..hazmat.primitives.test_ec import _skip_curve_unsupported from .test_x509 import DummyExtension From 75cb14730f6bb01ae10be3ea18211abded1d6607 Mon Sep 17 00:00:00 2001 From: Mathias Ertl Date: Mon, 26 Dec 2022 20:26:44 +0100 Subject: [PATCH 282/298] add canonical names to Sphinx class documentation (#7938) --- .../primitives/asymmetric/serialization.rst | 6 ++ docs/x509/reference.rst | 84 +++++++++++++++++++ 2 files changed, 90 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index b60102047f2d..0d590ad1cfe1 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -644,6 +644,7 @@ file suffix. instances. .. class:: PBES + :canonical: cryptography.hazmat.primitives._serialization.PBES .. versionadded:: 38.0.0 @@ -866,6 +867,7 @@ Serialization Formats .. currentmodule:: cryptography.hazmat.primitives.serialization .. class:: PrivateFormat + :canonical: cryptography.hazmat.primitives._serialization.PrivateFormat .. versionadded:: 0.8 @@ -1052,6 +1054,7 @@ Serialization Encodings ~~~~~~~~~~~~~~~~~~~~~~~ .. class:: Encoding + :canonical: cryptography.hazmat.primitives._serialization.Encoding An enumeration for encoding types. Used with the ``private_bytes`` method available on @@ -1112,6 +1115,7 @@ Serialization Encryption Types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: KeySerializationEncryption + :canonical: cryptography.hazmat.primitives._serialization.KeySerializationEncryption Objects with this interface are usable as encryption types with methods like ``private_bytes`` available on @@ -1125,6 +1129,7 @@ Serialization Encryption Types encryption and have this interface. .. class:: BestAvailableEncryption(password) + :canonical: cryptography.hazmat.primitives._serialization.BestAvailableEncryption Encrypt using the best available encryption for a given key. This is a curated encryption choice and the algorithm may change over @@ -1134,6 +1139,7 @@ Serialization Encryption Types :param bytes password: The password to use for encryption. .. class:: NoEncryption + :canonical: cryptography.hazmat.primitives._serialization.NoEncryption Do not encrypt. diff --git a/docs/x509/reference.rst b/docs/x509/reference.rst index 91560280f3f1..839bce21d0bf 100644 --- a/docs/x509/reference.rst +++ b/docs/x509/reference.rst @@ -150,6 +150,7 @@ Loading Certificates ~~~~~~~~~~~~~~~~~~~~ .. function:: load_pem_x509_certificate(data) + :canonical: cryptography.x509.base.load_pem_x509_certificate .. versionadded:: 0.7 @@ -169,6 +170,7 @@ Loading Certificates 2 .. function:: load_pem_x509_certificates(data) + :canonical: cryptography.x509.base.load_pem_x509_certificates .. versionadded:: 39.0 @@ -185,6 +187,7 @@ Loading Certificates certificate is malformed. .. function:: load_der_x509_certificate(data) + :canonical: cryptography.x509.base.load_der_x509_certificate .. versionadded:: 0.7 @@ -200,6 +203,7 @@ Loading Certificate Revocation Lists ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. function:: load_pem_x509_crl(data) + :canonical: cryptography.x509.base.load_pem_x509_crl .. versionadded:: 1.1 @@ -221,6 +225,7 @@ Loading Certificate Revocation Lists True .. function:: load_der_x509_crl(data) + :canonical: cryptography.x509.base.load_der_x509_crl .. versionadded:: 1.1 @@ -236,6 +241,7 @@ Loading Certificate Signing Requests ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. function:: load_pem_x509_csr(data) + :canonical: cryptography.x509.base.load_pem_x509_csr .. versionadded:: 0.9 @@ -258,6 +264,7 @@ Loading Certificate Signing Requests True .. function:: load_der_x509_csr(data) + :canonical: cryptography.x509.base.load_der_x509_csr .. versionadded:: 0.9 @@ -273,6 +280,7 @@ X.509 Certificate Object ~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: Certificate + :canonical: cryptography.x509.base.Certificate .. versionadded:: 0.7 @@ -517,6 +525,7 @@ X.509 CRL (Certificate Revocation List) Object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: CertificateRevocationList + :canonical: cryptography.x509.base.CertificateRevocationList .. versionadded:: 1.0 @@ -679,6 +688,7 @@ X.509 Certificate Builder ~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: CertificateBuilder + :canonical: cryptography.x509.base.CertificateBuilder .. versionadded:: 1.0 @@ -823,6 +833,7 @@ X.509 CSR (Certificate Signing Request) Object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: CertificateSigningRequest + :canonical: cryptography.x509.base.CertificateSigningRequest .. versionadded:: 0.9 @@ -943,6 +954,7 @@ X.509 Certificate Revocation List Builder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: CertificateRevocationListBuilder + :canonical: cryptography.x509.base.CertificateRevocationListBuilder .. versionadded:: 1.2 @@ -1051,6 +1063,7 @@ X.509 Revoked Certificate Object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: RevokedCertificate + :canonical: cryptography.x509.base.RevokedCertificate .. versionadded:: 1.0 @@ -1093,6 +1106,7 @@ X.509 Revoked Certificate Builder ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: RevokedCertificateBuilder + :canonical: cryptography.x509.base.RevokedCertificateBuilder This class is used to create :class:`~cryptography.x509.RevokedCertificate` objects that can be used with the @@ -1145,6 +1159,7 @@ X.509 CSR (Certificate Signing Request) Builder Object ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: CertificateSigningRequestBuilder + :canonical: cryptography.x509.base.CertificateSigningRequestBuilder .. versionadded:: 1.0 @@ -1228,6 +1243,7 @@ X.509 CSR (Certificate Signing Request) Builder Object .. class:: Name + :canonical: cryptography.x509.name.Name .. versionadded:: 0.8 @@ -1342,6 +1358,7 @@ X.509 CSR (Certificate Signing Request) Builder Object .. class:: Version + :canonical: cryptography.x509.base.Version .. versionadded:: 0.7 @@ -1356,6 +1373,7 @@ X.509 CSR (Certificate Signing Request) Builder Object For version 3 X.509 certificates. .. class:: NameAttribute + :canonical: cryptography.x509.name.NameAttribute .. versionadded:: 0.8 @@ -1401,6 +1419,7 @@ X.509 CSR (Certificate Signing Request) Builder Object .. class:: RelativeDistinguishedName(attributes) + :canonical: cryptography.x509.name.RelativeDistinguishedName .. versionadded:: 1.6 @@ -1433,6 +1452,7 @@ X.509 CSR (Certificate Signing Request) Builder Object .. class:: ObjectIdentifier + :canonical: ObjectIdentifier .. versionadded:: 0.8 @@ -1452,6 +1472,7 @@ General Name Classes ~~~~~~~~~~~~~~~~~~~~ .. class:: GeneralName + :canonical: cryptography.x509.general_name.GeneralName .. versionadded:: 0.9 @@ -1459,6 +1480,7 @@ General Name Classes against. .. class:: RFC822Name(value) + :canonical: cryptography.x509.general_name.RFC822Name .. versionadded:: 0.9 @@ -1480,6 +1502,7 @@ General Name Classes :type: str .. class:: DNSName(value) + :canonical: cryptography.x509.general_name.DNSName .. versionadded:: 0.9 @@ -1503,6 +1526,7 @@ General Name Classes :type: str .. class:: DirectoryName(value) + :canonical: cryptography.x509.general_name.DirectoryName .. versionadded:: 0.9 @@ -1513,6 +1537,7 @@ General Name Classes :type: :class:`Name` .. class:: UniformResourceIdentifier(value) + :canonical: cryptography.x509.general_name.UniformResourceIdentifier .. versionadded:: 0.9 @@ -1535,6 +1560,7 @@ General Name Classes :type: str .. class:: IPAddress(value) + :canonical: cryptography.x509.general_name.IPAddress .. versionadded:: 0.9 @@ -1547,6 +1573,7 @@ General Name Classes or :class:`~ipaddress.IPv6Network`. .. class:: RegisteredID(value) + :canonical: cryptography.x509.general_name.RegisteredID .. versionadded:: 0.9 @@ -1557,6 +1584,7 @@ General Name Classes :type: :class:`ObjectIdentifier` .. class:: OtherName(type_id, value) + :canonical: cryptography.x509.general_name.OtherName .. versionadded:: 1.0 @@ -1574,6 +1602,7 @@ X.509 Extensions ~~~~~~~~~~~~~~~~ .. class:: Extensions + :canonical: cryptography.x509.extensions.Extensions .. versionadded:: 0.9 @@ -1613,6 +1642,7 @@ X.509 Extensions , critical=True, value=)> .. class:: Extension + :canonical: cryptography.x509.extensions.Extension .. versionadded:: 0.9 @@ -1636,6 +1666,7 @@ X.509 Extensions Returns an instance of the extension type corresponding to the OID. .. class:: ExtensionType + :canonical: cryptography.x509.extensions.ExtensionType .. versionadded:: 1.0 @@ -1657,6 +1688,7 @@ X.509 Extensions A bytes string representing the extension's DER encoded value. .. class:: KeyUsage(digital_signature, content_commitment, key_encipherment, data_encipherment, key_agreement, key_cert_sign, crl_sign, encipher_only, decipher_only) + :canonical: cryptography.x509.extensions.KeyUsage .. versionadded:: 0.9 @@ -1756,6 +1788,7 @@ X.509 Extensions .. class:: BasicConstraints(ca, path_length) + :canonical: cryptography.x509.extensions.BasicConstraints .. versionadded:: 0.9 @@ -1791,6 +1824,7 @@ X.509 Extensions is not allowed to create subordinates with ``ca`` set to true. .. class:: ExtendedKeyUsage(usages) + :canonical: cryptography.x509.extensions.ExtendedKeyusage .. versionadded:: 0.9 @@ -1813,6 +1847,7 @@ X.509 Extensions .. class:: OCSPNoCheck() + :canonical: cryptography.x509.extensions.OCSPNoCheck .. versionadded:: 1.0 @@ -1835,6 +1870,7 @@ X.509 Extensions .. class:: TLSFeature(features) + :canonical: cryptography.x509.extensions.TLSFeature .. versionadded:: 2.1 @@ -1853,6 +1889,7 @@ X.509 Extensions Returns :attr:`~cryptography.x509.oid.ExtensionOID.TLS_FEATURE`. .. class:: TLSFeatureType + :canonical: cryptography.x509.extensions.TLSFeatureType .. versionadded:: 2.1 @@ -1873,6 +1910,7 @@ X.509 Extensions .. class:: NameConstraints(permitted_subtrees, excluded_subtrees) + :canonical: cryptography.x509.extensions.NameConstraints .. versionadded:: 1.0 @@ -1907,6 +1945,7 @@ X.509 Extensions ``excluded_subtrees`` will be non-None. .. class:: AuthorityKeyIdentifier(key_identifier, authority_cert_issuer, authority_cert_serial_number) + :canonical: cryptography.x509.extensions.AuthorityKeyIdentifier .. versionadded:: 0.9 @@ -2012,6 +2051,7 @@ X.509 Extensions .. class:: SubjectKeyIdentifier(digest) + :canonical: cryptography.x509.extensions.SubjectKeyIdentifier .. versionadded:: 0.9 @@ -2066,6 +2106,7 @@ X.509 Extensions .. class:: SubjectAlternativeName(general_names) + :canonical: cryptography.x509.extensions.SubjectAlternativeName .. versionadded:: 0.9 @@ -2106,6 +2147,7 @@ X.509 Extensions .. class:: IssuerAlternativeName(general_names) + :canonical: cryptography.x509.extensions.IssuerAlternativeName .. versionadded:: 1.0 @@ -2134,6 +2176,7 @@ X.509 Extensions .. class:: PrecertificateSignedCertificateTimestamps(scts) + :canonical: cryptography.x509.extensions.PrecertificateSignedCertificateTimestamps .. versionadded:: 2.0 @@ -2160,6 +2203,7 @@ X.509 Extensions .. class:: PrecertPoison() + :canonical: cryptography.x509.extensions.PrecertPoison .. versionadded:: 2.4 @@ -2177,6 +2221,7 @@ X.509 Extensions .. class:: SignedCertificateTimestamps(scts) + :canonical: cryptography.x509.extensions.SignedCertificateTimestamps .. versionadded:: 3.0 @@ -2204,6 +2249,7 @@ X.509 Extensions .. class:: DeltaCRLIndicator(crl_number) + :canonical: cryptography.x509.extensions.DeltaCRLIndicator .. versionadded:: 2.1 @@ -2228,6 +2274,7 @@ X.509 Extensions .. class:: AuthorityInformationAccess(descriptions) + :canonical: cryptography.x509.extensions.AuthorityInformationAccess .. versionadded:: 0.9 @@ -2251,6 +2298,7 @@ X.509 Extensions .. class:: SubjectInformationAccess(descriptions) + :canonical: cryptography.x509.extensions.SubjectInformationAccess .. versionadded:: 3.0 @@ -2274,6 +2322,7 @@ X.509 Extensions .. class:: AccessDescription(access_method, access_location) + :canonical: cryptography.x509.extensions.AccessDescription .. versionadded:: 0.9 @@ -2307,6 +2356,7 @@ X.509 Extensions Where to access the information defined by the access method. .. class:: FreshestCRL(distribution_points) + :canonical: cryptography.x509.extensions.FreshestCRL .. versionadded:: 2.1 @@ -2325,6 +2375,7 @@ X.509 Extensions :attr:`~cryptography.x509.oid.ExtensionOID.FRESHEST_CRL`. .. class:: CRLDistributionPoints(distribution_points) + :canonical: cryptography.x509.extensions.CRLDistributionPoints .. versionadded:: 0.9 @@ -2345,6 +2396,7 @@ X.509 Extensions :attr:`~cryptography.x509.oid.ExtensionOID.CRL_DISTRIBUTION_POINTS`. .. class:: DistributionPoint(full_name, relative_name, reasons, crl_issuer) + :canonical: cryptography.x509.extensions.DistributionPoint .. versionadded:: 0.9 @@ -2380,6 +2432,7 @@ X.509 Extensions revocation checks. .. class:: ReasonFlags + :canonical: cryptography.x509.extensions.ReasonFlags .. versionadded:: 0.9 @@ -2432,6 +2485,7 @@ X.509 Extensions in a :class:`DistributionPoint`. .. class:: InhibitAnyPolicy(skip_certs) + :canonical: cryptography.x509.extensions.InhibitAnyPolicy .. versionadded:: 1.0 @@ -2461,6 +2515,7 @@ X.509 Extensions :type: int .. class:: PolicyConstraints + :canonical: cryptography.x509.extensions.PolicyConstraints .. versionadded:: 1.3 @@ -2499,6 +2554,7 @@ X.509 Extensions certificate, but not in additional certificates in the chain. .. class:: CRLNumber(crl_number) + :canonical: cryptography.x509.extensions.CRLNumber .. versionadded:: 1.2 @@ -2521,6 +2577,7 @@ X.509 Extensions .. class:: IssuingDistributionPoint(full_name, relative_name,\ only_contains_user_certs, only_contains_ca_certs, only_some_reasons,\ indirect_crl, only_contains_attribute_certs) + :canonical: cryptography.x509.extensions.IssuingDistributionPoint .. versionadded:: 2.5 @@ -2590,6 +2647,7 @@ X.509 Extensions non-None. .. class:: UnrecognizedExtension + :canonical: cryptography.x509.extensions.UnrecognizedExtension .. versionadded:: 1.2 @@ -2611,6 +2669,7 @@ X.509 Extensions Returns the DER encoded bytes payload of the extension. .. class:: CertificatePolicies(policies) + :canonical: cryptography.x509.extensions.CertificatePolicies .. versionadded:: 0.9 @@ -2646,6 +2705,7 @@ Certificate Policies Classes These classes may be present within a :class:`CertificatePolicies` instance. .. class:: PolicyInformation(policy_identifier, policy_qualifiers) + :canonical: cryptography.x509.extensions.PolicyInformation .. versionadded:: 0.9 @@ -2665,6 +2725,7 @@ These classes may be present within a :class:`CertificatePolicies` instance. display to the relying party when the certificate is used. .. class:: UserNotice(notice_reference, explicit_text) + :canonical: cryptography.x509.extensions.UserNotice .. versionadded:: 0.9 @@ -2687,6 +2748,7 @@ These classes may be present within a :class:`CertificatePolicies` instance. :type: str .. class:: NoticeReference(organization, notice_numbers) + :canonical: cryptography.x509.extensions.NoticeReference Notice reference can name an organization and provide information about notices related to the certificate. For example, it might identify the @@ -2715,6 +2777,7 @@ CRL Entry Extensions These extensions are only valid within a :class:`RevokedCertificate` object. .. class:: CertificateIssuer(general_names) + :canonical: cryptography.x509.extensions.CertificateIssuer .. versionadded:: 1.2 @@ -2743,6 +2806,7 @@ These extensions are only valid within a :class:`RevokedCertificate` object. The type of the returned values depends on the :class:`GeneralName`. .. class:: CRLReason(reason) + :canonical: cryptography.x509.extensions.CRLReason .. versionadded:: 1.2 @@ -2764,6 +2828,7 @@ These extensions are only valid within a :class:`RevokedCertificate` object. :type: An element from :class:`~cryptography.x509.ReasonFlags` .. class:: InvalidityDate(invalidity_date) + :canonical: cryptography.x509.extensions.InvalidityDate .. versionadded:: 1.2 @@ -2792,6 +2857,7 @@ OCSP Extensions ~~~~~~~~~~~~~~~ .. class:: OCSPNonce(nonce) + :canonical: cryptography.x509.extensions.OCSPNonce .. versionadded:: 2.4 @@ -2817,6 +2883,7 @@ X.509 Request Attributes ~~~~~~~~~~~~~~~~~~~~~~~~ .. class:: Attributes + :canonical: cryptography.x509.base.Attributes .. versionadded:: 36.0 @@ -2837,6 +2904,7 @@ X.509 Request Attributes .. class:: Attribute + :canonical: cryptography.x509.base.Attribute .. versionadded:: 36.0 @@ -2863,6 +2931,7 @@ instances. The following common OIDs are available as constants. .. currentmodule:: cryptography.x509.oid .. class:: NameOID + :canonical: cryptography.hazmat._oid.NameOID These OIDs are typically seen in X.509 names. @@ -2990,6 +3059,7 @@ instances. The following common OIDs are available as constants. .. class:: SignatureAlgorithmOID + :canonical: cryptography.hazmat._oid.SignatureAlgorithmOID .. versionadded:: 1.0 @@ -3142,6 +3212,7 @@ instances. The following common OIDs are available as constants. .. class:: ExtendedKeyUsageOID + :canonical: cryptography.hazmat._oid.ExtendedKeyUsageOID .. versionadded:: 1.0 @@ -3226,6 +3297,7 @@ instances. The following common OIDs are available as constants. .. class:: AuthorityInformationAccessOID + :canonical: cryptography.hazmat._oid.AuthorityInformationAccessOID .. versionadded:: 1.0 @@ -3243,6 +3315,7 @@ instances. The following common OIDs are available as constants. .. class:: SubjectInformationAccessOID + :canonical: cryptography.hazmat._oid.SubjectInformationAccessOID .. versionadded:: 3.0 @@ -3254,6 +3327,7 @@ instances. The following common OIDs are available as constants. .. class:: CertificatePoliciesOID + :canonical: cryptography.hazmat._oid.CertificatePoliciesOID .. versionadded:: 1.0 @@ -3271,6 +3345,7 @@ instances. The following common OIDs are available as constants. .. class:: ExtensionOID + :canonical: cryptography.hazmat._oid.ExtensionOID .. versionadded:: 1.0 @@ -3413,6 +3488,7 @@ instances. The following common OIDs are available as constants. .. class:: CRLEntryExtensionOID + :canonical: cryptography.hazmat._oid.CRLEntryExtensionOID .. versionadded:: 1.2 @@ -3430,6 +3506,7 @@ instances. The following common OIDs are available as constants. .. class:: OCSPExtensionOID + :canonical: cryptography.hazmat._oid.OCSPExtensionOID .. versionadded:: 2.4 @@ -3439,6 +3516,7 @@ instances. The following common OIDs are available as constants. .. class:: AttributeOID + :canonical: cryptography.hazmat._oid.AttributeOID .. versionadded:: 3.0 @@ -3455,6 +3533,7 @@ Helper Functions .. currentmodule:: cryptography.x509 .. function:: random_serial_number() + :canonical: cryptography.x509.base.random_serial_number .. versionadded:: 1.6 @@ -3466,6 +3545,7 @@ Exceptions .. currentmodule:: cryptography.x509 .. class:: InvalidVersion + :canonical: cryptography.x509.base.InvalidVersion This is raised when an X.509 certificate has an invalid version number. @@ -3476,6 +3556,7 @@ Exceptions Returns the raw version that was parsed from the certificate. .. class:: DuplicateExtension + :canonical: cryptography.x509.extensions.DuplicateExtension This is raised when more than one X.509 extension of the same type is found within a certificate. @@ -3487,6 +3568,7 @@ Exceptions Returns the OID. .. class:: ExtensionNotFound + :canonical: cryptography.x509.extensions.ExtensionNotFound This is raised when calling :meth:`Extensions.get_extension_for_oid` with an extension OID that is not present in the certificate. @@ -3498,6 +3580,7 @@ Exceptions Returns the OID. .. class:: AttributeNotFound + :canonical: cryptography.x509.base.AttributeNotFound This is raised when calling :meth:`Attributes.get_attribute_for_oid` with @@ -3510,6 +3593,7 @@ Exceptions Returns the OID. .. class:: UnsupportedGeneralNameType + :canonical: cryptography.x509.general_name.UnsupportedGeneralNameType This is raised when a certificate contains an unsupported general name type in an extension. From 4fd0ff0973d5dfb3fa8e328ff199b06e10dd11f1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Dec 2022 07:23:19 -0500 Subject: [PATCH 283/298] Bump actions/cache from 3.2.1 to 3.2.2 (#7941) Bumps [actions/cache](https://github.com/actions/cache) from 3.2.1 to 3.2.2. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v3.2.1...v3.2.2) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/macarm64.yml | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fa527d90a45..e5d3a0643dd2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: uses: actions/setup-python@v4.4.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 timeout-minutes: 5 with: path: | @@ -89,7 +89,7 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.2.1 + uses: actions/cache@v3.2.2 id: ossl-cache timeout-minutes: 5 with: @@ -148,7 +148,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 timeout-minutes: 5 with: path: | @@ -208,7 +208,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 timeout-minutes: 5 with: path: | @@ -259,7 +259,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 id: cargo-cache timeout-minutes: 5 with: @@ -345,7 +345,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 timeout-minutes: 5 with: path: | @@ -415,7 +415,7 @@ jobs: with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 timeout-minutes: 5 with: path: | @@ -477,7 +477,7 @@ jobs: timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 timeout-minutes: 5 with: path: | diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml index b6140bc0aa0f..71c1419a279f 100644 --- a/.github/workflows/macarm64.yml +++ b/.github/workflows/macarm64.yml @@ -32,7 +32,7 @@ jobs: - uses: actions/checkout@v3.2.0 with: persist-credentials: false - - uses: actions/cache@v3.2.1 + - uses: actions/cache@v3.2.2 with: path: | src/rust/target/ From 7d5ec530ec6130f3f8f8ec89fab882eccf383c75 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Tue, 27 Dec 2022 22:02:39 +0100 Subject: [PATCH 284/298] Replace deprecated `abstractproperty` (#7943) Deprecated since version 3.3, see https://docs.python.org/3/library/abc.html#abc.abstractproperty --- .../hazmat/primitives/asymmetric/dsa.py | 6 +- .../hazmat/primitives/asymmetric/ec.py | 21 ++-- .../hazmat/primitives/asymmetric/rsa.py | 6 +- .../hazmat/primitives/ciphers/base.py | 3 +- .../hazmat/primitives/ciphers/modes.py | 15 ++- src/cryptography/x509/base.py | 93 ++++++++++------ .../x509/certificate_transparency.py | 24 ++-- src/cryptography/x509/general_name.py | 3 +- src/cryptography/x509/ocsp.py | 105 ++++++++++++------ 9 files changed, 184 insertions(+), 92 deletions(-) diff --git a/src/cryptography/hazmat/primitives/asymmetric/dsa.py b/src/cryptography/hazmat/primitives/asymmetric/dsa.py index e013d6204da3..6103d809355f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dsa.py @@ -28,7 +28,8 @@ def parameter_numbers(self) -> "DSAParameterNumbers": class DSAPrivateKey(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The bit length of the prime modulus. @@ -78,7 +79,8 @@ def private_bytes( class DSAPublicKey(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The bit length of the prime modulus. diff --git a/src/cryptography/hazmat/primitives/asymmetric/ec.py b/src/cryptography/hazmat/primitives/asymmetric/ec.py index 062b33c34d1f..c5df2c27a6e8 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/ec.py +++ b/src/cryptography/hazmat/primitives/asymmetric/ec.py @@ -35,13 +35,15 @@ class EllipticCurveOID: class EllipticCurve(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def name(self) -> str: """ The name of the curve. e.g. secp256r1. """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ Bit size of a secret scalar for the curve. @@ -49,7 +51,8 @@ def key_size(self) -> int: class EllipticCurveSignatureAlgorithm(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def algorithm( self, ) -> typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm]: @@ -74,13 +77,15 @@ def public_key(self) -> "EllipticCurvePublicKey": The EllipticCurvePublicKey for this private key. """ - @abc.abstractproperty + @property + @abc.abstractmethod def curve(self) -> EllipticCurve: """ The EllipticCurve that this key is on. """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ Bit size of a secret scalar for the curve. @@ -118,13 +123,15 @@ def private_bytes( class EllipticCurvePublicKey(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def curve(self) -> EllipticCurve: """ The EllipticCurve that this key is on. """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ Bit size of a secret scalar for the curve. diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index 433f925dea9f..81f5a0ec639f 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -19,7 +19,8 @@ def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: Decrypts the provided ciphertext. """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The bit length of the public modulus. @@ -70,7 +71,8 @@ def encrypt(self, plaintext: bytes, padding: AsymmetricPadding) -> bytes: Encrypts the given plaintext. """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The bit length of the public modulus. diff --git a/src/cryptography/hazmat/primitives/ciphers/base.py b/src/cryptography/hazmat/primitives/ciphers/base.py index 886afa1739b7..d7c4f096d09d 100644 --- a/src/cryptography/hazmat/primitives/ciphers/base.py +++ b/src/cryptography/hazmat/primitives/ciphers/base.py @@ -60,7 +60,8 @@ def finalize_with_tag(self, tag: bytes) -> bytes: class AEADEncryptionContext(AEADCipherContext, metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def tag(self) -> bytes: """ Returns tag bytes. This is only available after encryption is diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index d04e08ccc924..b7468b1bda75 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -16,7 +16,8 @@ class Mode(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def name(self) -> str: """ A string naming this mode (e.g. "ECB", "CBC"). @@ -31,7 +32,8 @@ def validate_for_algorithm(self, algorithm: CipherAlgorithm) -> None: class ModeWithInitializationVector(Mode, metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def initialization_vector(self) -> bytes: """ The value of the initialization vector for this mode as bytes. @@ -39,7 +41,8 @@ def initialization_vector(self) -> bytes: class ModeWithTweak(Mode, metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def tweak(self) -> bytes: """ The value of the tweak for this mode as bytes. @@ -47,7 +50,8 @@ def tweak(self) -> bytes: class ModeWithNonce(Mode, metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def nonce(self) -> bytes: """ The value of the nonce for this mode as bytes. @@ -55,7 +59,8 @@ def nonce(self) -> bytes: class ModeWithAuthenticationTag(Mode, metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def tag(self) -> typing.Optional[bytes]: """ The value of the tag supplied to the constructor of this mode. diff --git a/src/cryptography/x509/base.py b/src/cryptography/x509/base.py index d1914efe8d7e..6eae41cbe895 100644 --- a/src/cryptography/x509/base.py +++ b/src/cryptography/x509/base.py @@ -153,13 +153,15 @@ def fingerprint(self, algorithm: hashes.HashAlgorithm) -> bytes: Returns bytes using digest passed. """ - @abc.abstractproperty + @property + @abc.abstractmethod def serial_number(self) -> int: """ Returns certificate serial number """ - @abc.abstractproperty + @property + @abc.abstractmethod def version(self) -> Version: """ Returns the certificate version @@ -171,31 +173,36 @@ def public_key(self) -> CERTIFICATE_PUBLIC_KEY_TYPES: Returns the public key """ - @abc.abstractproperty + @property + @abc.abstractmethod def not_valid_before(self) -> datetime.datetime: """ Not before time (represented as UTC datetime) """ - @abc.abstractproperty + @property + @abc.abstractmethod def not_valid_after(self) -> datetime.datetime: """ Not after time (represented as UTC datetime) """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer(self) -> Name: """ Returns the issuer name object. """ - @abc.abstractproperty + @property + @abc.abstractmethod def subject(self) -> Name: """ Returns the subject name object. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_hash_algorithm( self, ) -> typing.Optional[hashes.HashAlgorithm]: @@ -204,31 +211,36 @@ def signature_hash_algorithm( in the certificate. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_algorithm_oid(self) -> ObjectIdentifier: """ Returns the ObjectIdentifier of the signature algorithm. """ - @abc.abstractproperty + @property + @abc.abstractmethod def extensions(self) -> Extensions: """ Returns an Extensions object. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature(self) -> bytes: """ Returns the signature bytes. """ - @abc.abstractproperty + @property + @abc.abstractmethod def tbs_certificate_bytes(self) -> bytes: """ Returns the tbsCertificate payload bytes as defined in RFC 5280. """ - @abc.abstractproperty + @property + @abc.abstractmethod def tbs_precertificate_bytes(self) -> bytes: """ Returns the tbsCertificate payload bytes with the SCT list extension @@ -259,19 +271,22 @@ def public_bytes(self, encoding: serialization.Encoding) -> bytes: class RevokedCertificate(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def serial_number(self) -> int: """ Returns the serial number of the revoked certificate. """ - @abc.abstractproperty + @property + @abc.abstractmethod def revocation_date(self) -> datetime.datetime: """ Returns the date of when this certificate was revoked. """ - @abc.abstractproperty + @property + @abc.abstractmethod def extensions(self) -> Extensions: """ Returns an Extensions object containing a list of Revoked extensions. @@ -328,7 +343,8 @@ def get_revoked_certificate_by_serial_number( is not in the CRL. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_hash_algorithm( self, ) -> typing.Optional[hashes.HashAlgorithm]: @@ -337,43 +353,50 @@ def signature_hash_algorithm( in the certificate. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_algorithm_oid(self) -> ObjectIdentifier: """ Returns the ObjectIdentifier of the signature algorithm. """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer(self) -> Name: """ Returns the X509Name with the issuer of this CRL. """ - @abc.abstractproperty + @property + @abc.abstractmethod def next_update(self) -> typing.Optional[datetime.datetime]: """ Returns the date of next update for this CRL. """ - @abc.abstractproperty + @property + @abc.abstractmethod def last_update(self) -> datetime.datetime: """ Returns the date of last update for this CRL. """ - @abc.abstractproperty + @property + @abc.abstractmethod def extensions(self) -> Extensions: """ Returns an Extensions object containing a list of CRL extensions. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature(self) -> bytes: """ Returns the signature bytes. """ - @abc.abstractproperty + @property + @abc.abstractmethod def tbs_certlist_bytes(self) -> bytes: """ Returns the tbsCertList payload bytes as defined in RFC 5280. @@ -444,13 +467,15 @@ def public_key(self) -> CERTIFICATE_PUBLIC_KEY_TYPES: Returns the public key """ - @abc.abstractproperty + @property + @abc.abstractmethod def subject(self) -> Name: """ Returns the subject name object. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_hash_algorithm( self, ) -> typing.Optional[hashes.HashAlgorithm]: @@ -459,19 +484,22 @@ def signature_hash_algorithm( in the certificate. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_algorithm_oid(self) -> ObjectIdentifier: """ Returns the ObjectIdentifier of the signature algorithm. """ - @abc.abstractproperty + @property + @abc.abstractmethod def extensions(self) -> Extensions: """ Returns the extensions in the signing request. """ - @abc.abstractproperty + @property + @abc.abstractmethod def attributes(self) -> Attributes: """ Returns an Attributes object. @@ -483,20 +511,23 @@ def public_bytes(self, encoding: serialization.Encoding) -> bytes: Encodes the request to PEM or DER format. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature(self) -> bytes: """ Returns the signature bytes. """ - @abc.abstractproperty + @property + @abc.abstractmethod def tbs_certrequest_bytes(self) -> bytes: """ Returns the PKCS#10 CertificationRequestInfo bytes as defined in RFC 2986. """ - @abc.abstractproperty + @property + @abc.abstractmethod def is_signature_valid(self) -> bool: """ Verifies signature of signing request. diff --git a/src/cryptography/x509/certificate_transparency.py b/src/cryptography/x509/certificate_transparency.py index 18c7cf79ce19..a67709865d44 100644 --- a/src/cryptography/x509/certificate_transparency.py +++ b/src/cryptography/x509/certificate_transparency.py @@ -36,49 +36,57 @@ class SignatureAlgorithm(utils.Enum): class SignedCertificateTimestamp(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def version(self) -> Version: """ Returns the SCT version. """ - @abc.abstractproperty + @property + @abc.abstractmethod def log_id(self) -> bytes: """ Returns an identifier indicating which log this SCT is for. """ - @abc.abstractproperty + @property + @abc.abstractmethod def timestamp(self) -> datetime.datetime: """ Returns the timestamp for this SCT. """ - @abc.abstractproperty + @property + @abc.abstractmethod def entry_type(self) -> LogEntryType: """ Returns whether this is an SCT for a certificate or pre-certificate. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_hash_algorithm(self) -> HashAlgorithm: """ Returns the hash algorithm used for the SCT's signature. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_algorithm(self) -> SignatureAlgorithm: """ Returns the signing algorithm used for the SCT's signature. """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature(self) -> bytes: """ Returns the signature for this SCT. """ - @abc.abstractproperty + @property + @abc.abstractmethod def extension_bytes(self) -> bytes: """ Returns the raw bytes of any extensions for this SCT. diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py index a2f12b34b693..b8b91ed94048 100644 --- a/src/cryptography/x509/general_name.py +++ b/src/cryptography/x509/general_name.py @@ -24,7 +24,8 @@ class UnsupportedGeneralNameType(Exception): class GeneralName(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def value(self) -> typing.Any: """ Return the value of the object diff --git a/src/cryptography/x509/ocsp.py b/src/cryptography/x509/ocsp.py index 4a08525a7642..70aa3b3619f9 100644 --- a/src/cryptography/x509/ocsp.py +++ b/src/cryptography/x509/ocsp.py @@ -127,25 +127,29 @@ def __init__( class OCSPRequest(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def issuer_key_hash(self) -> bytes: """ The hash of the issuer public key """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer_name_hash(self) -> bytes: """ The hash of the issuer name """ - @abc.abstractproperty + @property + @abc.abstractmethod def hash_algorithm(self) -> hashes.HashAlgorithm: """ The hash algorithm used in the issuer name and key hashes """ - @abc.abstractproperty + @property + @abc.abstractmethod def serial_number(self) -> int: """ The serial number of the cert whose status is being checked @@ -157,7 +161,8 @@ def public_bytes(self, encoding: serialization.Encoding) -> bytes: Serializes the request to DER """ - @abc.abstractproperty + @property + @abc.abstractmethod def extensions(self) -> x509.Extensions: """ The list of request extensions. Not single request extensions. @@ -165,58 +170,67 @@ def extensions(self) -> x509.Extensions: class OCSPSingleResponse(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def certificate_status(self) -> OCSPCertStatus: """ The status of the certificate (an element from the OCSPCertStatus enum) """ - @abc.abstractproperty + @property + @abc.abstractmethod def revocation_time(self) -> typing.Optional[datetime.datetime]: """ The date of when the certificate was revoked or None if not revoked. """ - @abc.abstractproperty + @property + @abc.abstractmethod def revocation_reason(self) -> typing.Optional[x509.ReasonFlags]: """ The reason the certificate was revoked or None if not specified or not revoked. """ - @abc.abstractproperty + @property + @abc.abstractmethod def this_update(self) -> datetime.datetime: """ The most recent time at which the status being indicated is known by the responder to have been correct """ - @abc.abstractproperty + @property + @abc.abstractmethod def next_update(self) -> typing.Optional[datetime.datetime]: """ The time when newer information will be available """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer_key_hash(self) -> bytes: """ The hash of the issuer public key """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer_name_hash(self) -> bytes: """ The hash of the issuer name """ - @abc.abstractproperty + @property + @abc.abstractmethod def hash_algorithm(self) -> hashes.HashAlgorithm: """ The hash algorithm used in the issuer name and key hashes """ - @abc.abstractproperty + @property + @abc.abstractmethod def serial_number(self) -> int: """ The serial number of the cert whose status is being checked @@ -224,27 +238,31 @@ def serial_number(self) -> int: class OCSPResponse(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def responses(self) -> typing.Iterator[OCSPSingleResponse]: """ An iterator over the individual SINGLERESP structures in the response """ - @abc.abstractproperty + @property + @abc.abstractmethod def response_status(self) -> OCSPResponseStatus: """ The status of the response. This is a value from the OCSPResponseStatus enumeration """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_algorithm_oid(self) -> x509.ObjectIdentifier: """ The ObjectIdentifier of the signature algorithm """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature_hash_algorithm( self, ) -> typing.Optional[hashes.HashAlgorithm]: @@ -252,19 +270,22 @@ def signature_hash_algorithm( Returns a HashAlgorithm corresponding to the type of the digest signed """ - @abc.abstractproperty + @property + @abc.abstractmethod def signature(self) -> bytes: """ The signature bytes """ - @abc.abstractproperty + @property + @abc.abstractmethod def tbs_response_bytes(self) -> bytes: """ The tbsResponseData bytes """ - @abc.abstractproperty + @property + @abc.abstractmethod def certificates(self) -> typing.List[x509.Certificate]: """ A list of certificates used to help build a chain to verify the OCSP @@ -272,88 +293,102 @@ def certificates(self) -> typing.List[x509.Certificate]: certificate. """ - @abc.abstractproperty + @property + @abc.abstractmethod def responder_key_hash(self) -> typing.Optional[bytes]: """ The responder's key hash or None """ - @abc.abstractproperty + @property + @abc.abstractmethod def responder_name(self) -> typing.Optional[x509.Name]: """ The responder's Name or None """ - @abc.abstractproperty + @property + @abc.abstractmethod def produced_at(self) -> datetime.datetime: """ The time the response was produced """ - @abc.abstractproperty + @property + @abc.abstractmethod def certificate_status(self) -> OCSPCertStatus: """ The status of the certificate (an element from the OCSPCertStatus enum) """ - @abc.abstractproperty + @property + @abc.abstractmethod def revocation_time(self) -> typing.Optional[datetime.datetime]: """ The date of when the certificate was revoked or None if not revoked. """ - @abc.abstractproperty + @property + @abc.abstractmethod def revocation_reason(self) -> typing.Optional[x509.ReasonFlags]: """ The reason the certificate was revoked or None if not specified or not revoked. """ - @abc.abstractproperty + @property + @abc.abstractmethod def this_update(self) -> datetime.datetime: """ The most recent time at which the status being indicated is known by the responder to have been correct """ - @abc.abstractproperty + @property + @abc.abstractmethod def next_update(self) -> typing.Optional[datetime.datetime]: """ The time when newer information will be available """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer_key_hash(self) -> bytes: """ The hash of the issuer public key """ - @abc.abstractproperty + @property + @abc.abstractmethod def issuer_name_hash(self) -> bytes: """ The hash of the issuer name """ - @abc.abstractproperty + @property + @abc.abstractmethod def hash_algorithm(self) -> hashes.HashAlgorithm: """ The hash algorithm used in the issuer name and key hashes """ - @abc.abstractproperty + @property + @abc.abstractmethod def serial_number(self) -> int: """ The serial number of the cert whose status is being checked """ - @abc.abstractproperty + @property + @abc.abstractmethod def extensions(self) -> x509.Extensions: """ The list of response extensions. Not single response extensions. """ - @abc.abstractproperty + @property + @abc.abstractmethod def single_extensions(self) -> x509.Extensions: """ The list of single response extensions. Not response extensions. From 438f78179c23f226e387c33db703f541b7cecdec Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 27 Dec 2022 18:40:50 -0500 Subject: [PATCH 285/298] Typo fixes (#7942) --- docs/hazmat/primitives/asymmetric/rsa.rst | 2 +- docs/hazmat/primitives/asymmetric/serialization.rst | 4 ++-- src/_cffi_src/build_openssl.py | 2 +- src/cryptography/hazmat/primitives/twofactor/hotp.py | 2 +- src/rust/src/x509/common.rs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index 384cab0736e7..0bf4c0291b11 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -481,7 +481,7 @@ is unavailable. A keyword-only argument that defaults to ``False``. If ``True`` RSA private keys will not be validated. This significantly speeds up - loading the keys, but is is :term:`unsafe` unless you are certain + loading the keys, but is :term:`unsafe` unless you are certain the key is valid. User supplied keys should never be loaded with this parameter set to ``True``. If you do load an invalid key this way and attempt to use it OpenSSL may hang, crash, or otherwise diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 0d590ad1cfe1..4d1af99425ba 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -149,7 +149,7 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END A keyword-only argument that defaults to ``False``. If ``True`` RSA private keys will not be validated. This significantly speeds up - loading the keys, but is is :term:`unsafe` unless you are certain the + loading the keys, but is :term:`unsafe` unless you are certain the key is valid. User supplied keys should never be loaded with this parameter set to ``True``. If you do load an invalid key this way and attempt to use it OpenSSL may hang, crash, or otherwise misbehave. @@ -267,7 +267,7 @@ the rest. A keyword-only argument that defaults to ``False``. If ``True`` RSA private keys will not be validated. This significantly speeds up - loading the keys, but is is :term:`unsafe` unless you are certain the + loading the keys, but is :term:`unsafe` unless you are certain the key is valid. User supplied keys should never be loaded with this parameter set to ``True``. If you do load an invalid key this way and attempt to use it OpenSSL may hang, crash, or otherwise misbehave. diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 0b5115fd96e5..a8e560960ebe 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -33,7 +33,7 @@ def _get_openssl_libraries(platform): # libssl must come before libcrypto # (https://marc.info/?l=openssl-users&m=135361825921871) # -lpthread required due to usage of pthread an potential - # existance of a static part containing e.g. pthread_atfork + # existence of a static part containing e.g. pthread_atfork # (https://github.com/pyca/cryptography/issues/5084) if sys.platform == "zos": return ["ssl", "crypto"] diff --git a/src/cryptography/hazmat/primitives/twofactor/hotp.py b/src/cryptography/hazmat/primitives/twofactor/hotp.py index 04c45bb8c6df..cbb22704bf72 100644 --- a/src/cryptography/hazmat/primitives/twofactor/hotp.py +++ b/src/cryptography/hazmat/primitives/twofactor/hotp.py @@ -56,7 +56,7 @@ def __init__( raise TypeError("Length parameter must be an integer type.") if length < 6 or length > 8: - raise ValueError("Length of HOTP has to be between 6 to 8.") + raise ValueError("Length of HOTP has to be between 6 and 8.") if not isinstance(algorithm, (SHA1, SHA256, SHA512)): raise TypeError("Algorithm must be SHA1, SHA256 or SHA512.") diff --git a/src/rust/src/x509/common.rs b/src/rust/src/x509/common.rs index fb61b7ae8aa5..b4ffc41b28fc 100644 --- a/src/rust/src/x509/common.rs +++ b/src/rust/src/x509/common.rs @@ -44,7 +44,7 @@ pub(crate) struct AttributeTypeValue<'a> { pub(crate) value: RawTlv<'a>, } -// Like `asn1::Tlv` but doesn't store `full_data` so it can be constucted from +// Like `asn1::Tlv` but doesn't store `full_data` so it can be constructed from // an un-encoded tag and value. #[derive(Hash, PartialEq, Eq, Clone)] pub(crate) struct RawTlv<'a> { From c28bfb352ab1f390900ef92856a9570aadd5fe2c Mon Sep 17 00:00:00 2001 From: hustliyilin <1273994937@qq.com> Date: Wed, 28 Dec 2022 01:14:56 -0600 Subject: [PATCH 286/298] src/_cffi_src/openssl/evp.py: export EVP_PKEY_set_alias_type in FUNCTIONS (#7935) In openssl 1.1.1 docs/man3/EVP_PKEY_set1_RSA.pod (https://github.com/openssl/openssl/blob/OpenSSL_1_1_1/doc/man3/EVP_PKEY_set1_RSA.pod) The EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2) API is possible to convert it to using SM2 algorithms After loading an ECC key. So the EVP_PKEY_set_alias_type API is important for people who want to use cryptography with using SM2 algorithms. Therefore, we need to export EVP_PKEY_set_alias_type in FUNCTIONS. Signed-off-by: YiLin.Li Signed-off-by: YiLin.Li --- src/_cffi_src/openssl/evp.py | 10 ++++++++++ .../hazmat/bindings/openssl/_conditional.py | 9 +++++++++ 2 files changed, 19 insertions(+) diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 75d2522016cb..44e8a6e29ddc 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -31,6 +31,7 @@ static const int EVP_CTRL_AEAD_GET_TAG; static const int EVP_CTRL_AEAD_SET_TAG; +static const int Cryptography_HAS_EVP_PKEY_set_alias_type; static const int Cryptography_HAS_SCRYPT; static const int Cryptography_HAS_EVP_PKEY_DHX; static const int Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint; @@ -121,6 +122,7 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *); int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *, EVP_PKEY *); int EVP_PKEY_derive(EVP_PKEY_CTX *, unsigned char *, size_t *); +int EVP_PKEY_set_alias_type(EVP_PKEY *, int); int EVP_PKEY_set_type(EVP_PKEY *, int); int EVP_PKEY_id(const EVP_PKEY *); @@ -180,6 +182,14 @@ EVP_MD_CTX_free(md); } +#if CRYPTOGRAPHY_IS_LIBRESSL || CRYPTOGRAPHY_OPENSSL_300_OR_GREATER || \ + CRYPTOGRAPHY_IS_BORINGSSL +static const int Cryptography_HAS_EVP_PKEY_set_alias_type = 0; +int (*EVP_PKEY_set_alias_type)(EVP_PKEY *, int) = NULL; +#else +static const int Cryptography_HAS_EVP_PKEY_set_alias_type = 1; +#endif + #if CRYPTOGRAPHY_IS_LIBRESSL || defined(OPENSSL_NO_SCRYPT) static const long Cryptography_HAS_SCRYPT = 0; int (*EVP_PBE_scrypt)(const char *, size_t, const unsigned char *, size_t, diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index e8ce4738fb81..7903a9bb4543 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -42,6 +42,12 @@ def cryptography_has_tls_st() -> typing.List[str]: ] +def cryptography_has_evp_pkey_set_alias_type() -> typing.List[str]: + return [ + "EVP_PKEY_set_alias_type", + ] + + def cryptography_has_scrypt() -> typing.List[str]: return [ "EVP_PBE_scrypt", @@ -303,6 +309,9 @@ def cryptography_has_get_extms_support() -> typing.List[str]: "Cryptography_HAS_SET_CERT_CB": cryptography_has_set_cert_cb, "Cryptography_HAS_SSL_ST": cryptography_has_ssl_st, "Cryptography_HAS_TLS_ST": cryptography_has_tls_st, + "Cryptography_HAS_EVP_PKEY_set_alias_type": ( + cryptography_has_evp_pkey_set_alias_type + ), "Cryptography_HAS_SCRYPT": cryptography_has_scrypt, "Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx, "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, From 0a02a7dacf8578ef77991663bbfbfa8770c8f952 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Wed, 28 Dec 2022 11:33:22 +0100 Subject: [PATCH 287/298] Replace more deprecated `abstractproperty` (#7944) --- pyproject.toml | 1 - src/cryptography/hazmat/primitives/_asymmetric.py | 3 ++- .../hazmat/primitives/_cipheralgorithm.py | 12 ++++++++---- src/cryptography/hazmat/primitives/asymmetric/dh.py | 6 ++++-- src/cryptography/hazmat/primitives/hashes.py | 12 ++++++++---- 5 files changed, 22 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index e099c29573be..c98a37054b1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,7 +59,6 @@ tests =[ [tool.coverage.report] exclude_lines = [ "@abc.abstractmethod", - "@abc.abstractproperty", "@typing.overload", "if typing.TYPE_CHECKING", ] diff --git a/src/cryptography/hazmat/primitives/_asymmetric.py b/src/cryptography/hazmat/primitives/_asymmetric.py index c6862d9317f5..fb815a0e9154 100644 --- a/src/cryptography/hazmat/primitives/_asymmetric.py +++ b/src/cryptography/hazmat/primitives/_asymmetric.py @@ -9,7 +9,8 @@ class AsymmetricPadding(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def name(self) -> str: """ A string naming this padding (e.g. "PSS", "PKCS1"). diff --git a/src/cryptography/hazmat/primitives/_cipheralgorithm.py b/src/cryptography/hazmat/primitives/_cipheralgorithm.py index 6e6a79c11a6a..138a104e267c 100644 --- a/src/cryptography/hazmat/primitives/_cipheralgorithm.py +++ b/src/cryptography/hazmat/primitives/_cipheralgorithm.py @@ -10,19 +10,22 @@ class CipherAlgorithm(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def name(self) -> str: """ A string naming this mode (e.g. "AES", "Camellia"). """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_sizes(self) -> typing.FrozenSet[int]: """ Valid key sizes for this algorithm in bits """ - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The size of the key being used as an integer in bits (e.g. 128, 256). @@ -32,7 +35,8 @@ def key_size(self) -> int: class BlockCipherAlgorithm(metaclass=abc.ABCMeta): key: bytes - @abc.abstractproperty + @property + @abc.abstractmethod def block_size(self) -> int: """ The size of a block as an integer in bits (e.g. 64, 128). diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index bbdd485cd30f..33de0e551165 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -170,7 +170,8 @@ def parameter_numbers(self) -> DHParameterNumbers: class DHPublicKey(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The bit length of the prime modulus. @@ -203,7 +204,8 @@ def public_bytes( class DHPrivateKey(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def key_size(self) -> int: """ The bit length of the prime modulus. diff --git a/src/cryptography/hazmat/primitives/hashes.py b/src/cryptography/hazmat/primitives/hashes.py index 440b1a3e9460..330c08dfa95f 100644 --- a/src/cryptography/hazmat/primitives/hashes.py +++ b/src/cryptography/hazmat/primitives/hashes.py @@ -10,19 +10,22 @@ class HashAlgorithm(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def name(self) -> str: """ A string naming this algorithm (e.g. "sha256", "md5"). """ - @abc.abstractproperty + @property + @abc.abstractmethod def digest_size(self) -> int: """ The size of the resulting digest in bytes. """ - @abc.abstractproperty + @property + @abc.abstractmethod def block_size(self) -> typing.Optional[int]: """ The internal block size of the hash function, or None if the hash @@ -31,7 +34,8 @@ def block_size(self) -> typing.Optional[int]: class HashContext(metaclass=abc.ABCMeta): - @abc.abstractproperty + @property + @abc.abstractmethod def algorithm(self) -> HashAlgorithm: """ A HashAlgorithm that will be used by this context. From 4de6304884a752014cb9ad0f67453a5292dfa468 Mon Sep 17 00:00:00 2001 From: "pyca-boringbot[bot]" <106132319+pyca-boringbot[bot]@users.noreply.github.com> Date: Thu, 29 Dec 2022 00:19:41 +0000 Subject: [PATCH 288/298] Bump BoringSSL and/or OpenSSL in CI (#7946) Co-authored-by: pyca-boringbot[bot] --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e5d3a0643dd2..2312fd6e6796 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,8 +42,8 @@ jobs: - {VERSION: "3.12-dev", TOXENV: "py312"} # Latest commit on the BoringSSL master branch, as of Dec 23, 2022. - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "31bad2514d21f6207f3925ba56754611c462a873"}} - # Latest commit on the OpenSSL master branch, as of Dec 23, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "98663afce7a909be1518921a9995540308a52462"}} + # Latest commit on the OpenSSL master branch, as of Dec 29, 2022. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "43a9e682d80d0abe4ffd0c76d18c43cf059a2bcc"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: From 8867724b2b6db528d2900414ef86c122a1f5602a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Dec 2022 19:02:08 -0500 Subject: [PATCH 289/298] fix README for python3 (#7947) lol --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 19f1678b710f..1c0e57cbe5e4 100644 --- a/README.rst +++ b/README.rst @@ -30,9 +30,9 @@ key derivation functions. For example, to encrypt something with >>> f = Fernet(key) >>> token = f.encrypt(b"A really secret message. Not for prying eyes.") >>> token - '...' + b'...' >>> f.decrypt(token) - 'A really secret message. Not for prying eyes.' + b'A really secret message. Not for prying eyes.' You can find more information in the `documentation`_. From f150dc15582c05b1b94cf08ed3b1fbc9c4f52267 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 31 Dec 2022 22:07:59 +0700 Subject: [PATCH 290/298] fix CI to work with ubuntu 22.04 (#7950) --- .github/workflows/build_openssl.sh | 15 ++++++++++++++- .github/workflows/ci.yml | 6 +++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build_openssl.sh b/.github/workflows/build_openssl.sh index d2358d1a7f1a..947b828222b2 100755 --- a/.github/workflows/build_openssl.sh +++ b/.github/workflows/build_openssl.sh @@ -9,6 +9,10 @@ shlib_sed() { sed -i "s/^SHLIB_MINOR=.*/SHLIB_MINOR=0.0/" Makefile sed -i "s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=100.0.0/" Makefile } +shlib_sed_3() { + # OpenSSL 3 changes how it does the shlib versioning + sed -i "s/^SHLIB_VERSION=.*/SHLIB_VERSION=100/" VERSION.dat +} if [[ "${TYPE}" == "openssl" ]]; then if [[ "${VERSION}" =~ ^[0-9a-f]{40}$ ]]; then @@ -20,9 +24,18 @@ if [[ "${TYPE}" == "openssl" ]]; then tar zxf "openssl-${VERSION}.tar.gz" pushd "openssl-${VERSION}" fi + # For OpenSSL 3 we need to call this before config + if [[ "${VERSION}" =~ ^3. ]] || [[ "${VERSION}" =~ ^[0-9a-f]{40}$ ]]; then + shlib_sed_3 + fi + # CONFIG_FLAGS is a global coming from a previous step ./config ${CONFIG_FLAGS} -fPIC --prefix="${OSSL_PATH}" - shlib_sed + + # For OpenSSL 1 we need to call this after config + if [[ "${VERSION}" =~ ^1. ]]; then + shlib_sed + fi make depend make -j"$(nproc)" # avoid installing the docs (for performance) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2312fd6e6796..0dcce6503b7f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: linux: - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest strategy: fail-fast: false matrix: @@ -67,7 +67,7 @@ jobs: ~/.cargo/registry/src/ ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-${{ steps.setup-python.outputs.python-version }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-${{ steps.setup-python.outputs.python-version }}-cargo-5-${{ hashFiles('**/Cargo.lock') }} - uses: actions/checkout@v3.2.0 timeout-minutes: 3 @@ -96,7 +96,7 @@ jobs: path: ${{ github.workspace }}/osslcache # When altering the openssl build process you may need to increment the value on the end of this cache key # so that you can prevent it from fetching the cache and skipping the build step. - key: ${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.CONFIG_HASH }}-2 + key: ${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.CONFIG_HASH }}-4 if: matrix.PYTHON.OPENSSL - name: Build custom OpenSSL/LibreSSL run: .github/workflows/build_openssl.sh From 46d2a94d1b574abf5b9e88f84fa7400a138c4edb Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 1 Jan 2023 19:36:37 -0500 Subject: [PATCH 291/298] Use the latest 3.10 release when wheel building (#7953) --- .github/workflows/wheel-builder.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 35e886c84afc..9bf72146de86 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -119,7 +119,7 @@ jobs: - VERSION: '3.10' ABI_VERSION: 'cp36' # Despite the name, this is built for the macOS 11 SDK on arm64 and 10.9+ on intel - DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.10.0/python-3.10.0post2-macos11.pkg' + DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.10.9/python-3.10.9-macos11.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3' DEPLOYMENT_TARGET: '10.12' # This archflags is default, but let's be explicit @@ -130,7 +130,7 @@ jobs: _PYTHON_HOST_PLATFORM: 'macosx-10.9-universal2' - VERSION: '3.10' ABI_VERSION: 'cp36' - DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.10.0/python-3.10.0post2-macos11.pkg' + DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.10.9/python-3.10.9-macos11.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3' DEPLOYMENT_TARGET: '10.12' # We continue to build a non-universal2 for a bit to see metrics on From 525c0b3d5d89eab7f953be5de5d2b75da1c816f8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 1 Jan 2023 19:38:57 -0500 Subject: [PATCH 292/298] Type annotate release.py (#7951) --- release.py | 21 ++++++++++++++------- tox.ini | 3 ++- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/release.py b/release.py index 5046daff1e6c..655bf839a871 100644 --- a/release.py +++ b/release.py @@ -7,18 +7,21 @@ import os import subprocess import time +import typing import zipfile import click import requests -def run(*args, **kwargs): +def run(*args: str) -> None: print("[running] {0}".format(list(args))) - subprocess.check_call(list(args), **kwargs) + subprocess.check_call(list(args)) -def wait_for_build_complete_github_actions(session, token, run_url): +def wait_for_build_complete_github_actions( + session: requests.Session, token: str, run_url: str +) -> None: while True: response = session.get( run_url, @@ -33,7 +36,9 @@ def wait_for_build_complete_github_actions(session, token, run_url): time.sleep(3) -def download_artifacts_github_actions(session, token, run_url): +def download_artifacts_github_actions( + session: requests.Session, token: str, run_url: str +) -> typing.List[str]: response = session.get( run_url, headers={ @@ -76,7 +81,9 @@ def download_artifacts_github_actions(session, token, run_url): return paths -def fetch_github_actions_artifacts(token, version): +def fetch_github_actions_artifacts( + token: str, version: str +) -> typing.List[str]: session = requests.Session() response = session.get( @@ -90,14 +97,14 @@ def fetch_github_actions_artifacts(token, version): }, ) response.raise_for_status() - run_url = response.json()["workflow_runs"][0]["url"] + run_url: str = response.json()["workflow_runs"][0]["url"] wait_for_build_complete_github_actions(session, token, run_url) return download_artifacts_github_actions(session, token, run_url) @click.command() @click.argument("version") -def release(version): +def release(version: str) -> None: """ ``version`` should be a string like '0.4' or '1.0'. """ diff --git a/tox.ini b/tox.ini index 5159c5a1a120..fc30b72f101c 100644 --- a/tox.ini +++ b/tox.ini @@ -62,12 +62,13 @@ extras = deps = mypy types-pytz + types-requests check-manifest commands = ruff . black --check . check-manifest - mypy src/cryptography/ vectors/cryptography_vectors/ tests/ + mypy src/cryptography/ vectors/cryptography_vectors/ tests/ release.py [testenv:rust] basepython = python3 From 84a3cd7abb16f594d8c315e8aedb4be02583bf6a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 2 Jan 2023 09:22:32 +0700 Subject: [PATCH 293/298] automatically download and upload circleci wheels (#7949) --- release.py | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 113 insertions(+), 1 deletion(-) diff --git a/release.py b/release.py index 655bf839a871..003605384583 100644 --- a/release.py +++ b/release.py @@ -8,6 +8,7 @@ import subprocess import time import typing +import urllib import zipfile import click @@ -102,6 +103,108 @@ def fetch_github_actions_artifacts( return download_artifacts_github_actions(session, token, run_url) +def wait_for_build_complete_circleci( + session: requests.Session, token: str, pipeline_id: str +) -> None: + while True: + response = session.get( + f"https://circleci.com/api/v2/pipeline/{pipeline_id}/workflow", + headers={ + "Circle-Token": token, + }, + ) + response.raise_for_status() + status = response.json()["items"][0]["status"] + if status == "success": + break + elif status not in ("running", "on_hold", "not_run"): + raise ValueError(f"CircleCI build failed with status {status}") + time.sleep(3) + + +def download_artifacts_circleci( + session: requests.Session, urls: typing.List[str] +) -> typing.List[str]: + paths = [] + for url in urls: + name = os.path.basename(urllib.parse.urlparse(url).path) + response = session.get(url) + out_path = os.path.join( + os.path.dirname(__file__), + "dist", + os.path.basename(name), + ) + with open(out_path, "wb") as f: + f.write(response.content) + paths.append(out_path) + return paths + + +def fetch_circleci_artifacts(token: str, version: str) -> typing.List[str]: + session = requests.Session() + + response = session.get( + "https://circleci.com/api/v2/pipeline?org-slug=gh/pyca", + headers={"Circle-Token": token}, + ) + response.raise_for_status() + pipeline_id = None + for item in response.json()["items"]: + if item["project_slug"] == "gh/pyca/cryptography": + if item["vcs"].get("tag", None) == version: + pipeline_id = item["id"] + break + + if pipeline_id is None: + raise ValueError(f"Could not find a pipeline for version {version}") + + wait_for_build_complete_circleci(session, token, pipeline_id) + urls = fetch_circleci_artifact_urls(session, token, pipeline_id) + return download_artifacts_circleci(session, urls) + + +def fetch_circleci_artifact_urls( + session: requests.Session, token: str, pipeline_id: str +) -> typing.List[str]: + response = session.get( + f"https://circleci.com/api/v2/pipeline/{pipeline_id}/workflow", + headers={"Circle-Token": token}, + ) + response.raise_for_status() + workflow_id = response.json()["items"][0]["id"] + job_response = session.get( + f"https://circleci.com/api/v2/workflow/{workflow_id}/job", + headers={"Circle-Token": token}, + ) + job_response.raise_for_status() + artifact_urls = [] + for job in job_response.json()["items"]: + urls = fetch_circleci_artifact_url_from_job( + session, token, job["job_number"] + ) + artifact_urls.extend(urls) + + return artifact_urls + + +def fetch_circleci_artifact_url_from_job( + session: requests.Session, token: str, job: str +) -> typing.List[str]: + response = session.get( + f"https://circleci.com/api/v2/project/gh/pyca/cryptography/" + f"{job}/artifacts", + headers={"Circle-Token": token}, + ) + response.raise_for_status() + urls = [] + for item in response.json()["items"]: + url = item.get("url", None) + if url is not None: + urls.append(url) + + return urls + + @click.command() @click.argument("version") def release(version: str) -> None: @@ -113,7 +216,12 @@ def release(version: str) -> None: f"https://github.com/settings/tokens/new?" f"description={version}&scopes=repo" ) + print( + "Get a CircleCI token at: " + "https://app.circleci.com/settings/user/tokens" + ) github_token = getpass.getpass("Github person access token: ") + circle_token = getpass.getpass("CircleCI token: ") # Tag and push the tag (this will trigger the wheel builder in Actions) run("git", "tag", "-s", version, "-m", "{0} release".format(version)) @@ -123,9 +231,13 @@ def release(version: str) -> None: github_actions_artifact_paths = fetch_github_actions_artifacts( github_token, version ) + # Download wheels from CircleCI + circle_artifact_paths = fetch_circleci_artifacts(circle_token, version) + + artifact_paths = github_actions_artifact_paths + circle_artifact_paths # Upload wheels and sdist - run("twine", "upload", *github_actions_artifact_paths) + run("twine", "upload", *artifact_paths) if __name__ == "__main__": From 338a65a7df74e189f6b5d1d3a6315ffa911b21c2 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 2 Jan 2023 09:57:00 +0700 Subject: [PATCH 294/298] 39.0.0 version bump (#7954) --- CHANGELOG.rst | 6 ++---- src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 18988afe39c3..bd70b9bc7b34 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,10 +3,8 @@ Changelog .. _v39-0-0: -39.0.0 - `main`_ -~~~~~~~~~~~~~~~~ - -.. note:: This version is not yet released and is under active development. +39.0.0 - 2023-01-01 +~~~~~~~~~~~~~~~~~~~ * **BACKWARDS INCOMPATIBLE:** Support for OpenSSL 1.1.0 has been removed. Users on older version of OpenSSL will need to upgrade. diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 7adbc40005ef..83439a962dd3 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -9,7 +9,7 @@ "__copyright__", ] -__version__ = "39.0.0.dev1" +__version__ = "39.0.0" __author__ = "The Python Cryptographic Authority and individual contributors" __copyright__ = "Copyright 2013-2022 {}".format(__author__) diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 95eb6b9919a8..9b607dd65f03 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -6,4 +6,4 @@ "__version__", ] -__version__ = "39.0.0.dev1" +__version__ = "39.0.0" From 111deefb659b8d73c56d3ce89458f2df973d60e4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 28 Jan 2023 22:53:47 -0600 Subject: [PATCH 295/298] backport main branch CI to 39.0.x (#8153) * backport main branch CI to 39.0.x * missed this one * fix boring binding (backport of #8091) * more ports * re-add 2_24 * aarch64 too * Update .github/workflows/wheel-builder.yml Co-authored-by: Alex Gaynor --------- Co-authored-by: Alex Gaynor --- .circleci/build-wheel.sh | 35 ----- .circleci/config.yml | 112 -------------- .github/workflows/build_openssl.sh | 13 +- .github/workflows/ci.yml | 167 +++++++++++--------- .github/workflows/macarm64.yml | 65 -------- .github/workflows/wheel-builder.yml | 76 ++++++--- MANIFEST.in | 4 +- ci-constraints-requirements.txt | 230 ++++++++++++++++++++++++++++ dev-requirements.txt | 5 - setup.cfg | 13 +- src/_cffi_src/openssl/x509v3.py | 2 +- tox.ini | 10 +- 12 files changed, 398 insertions(+), 334 deletions(-) delete mode 100755 .circleci/build-wheel.sh delete mode 100644 .circleci/config.yml delete mode 100644 .github/workflows/macarm64.yml create mode 100644 ci-constraints-requirements.txt delete mode 100644 dev-requirements.txt diff --git a/.circleci/build-wheel.sh b/.circleci/build-wheel.sh deleted file mode 100755 index d69e8c9213fe..000000000000 --- a/.circleci/build-wheel.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/bash -ex - -cd /test - -echo "Building for ${PLATFORM}" - -PYBIN="/opt/python/${PYTHON}/bin" - -mkdir -p /test/wheelhouse.final - -"${PYBIN}"/python -m venv .venv - -.venv/bin/pip install -U pip wheel cffi setuptools-rust - -.venv/bin/python setup.py sdist -cd dist -tar zxf cryptography*.tar.gz -rm -rf cryptograph*.tar.gz -cd cryptography* - -REGEX="cp3([0-9])*" -if [[ "${PYBIN}" =~ $REGEX ]]; then - PY_LIMITED_API="--py-limited-api=cp3${BASH_REMATCH[1]}" -fi - -LDFLAGS="-L/opt/pyca/cryptography/openssl/lib" \ - CFLAGS="-I/opt/pyca/cryptography/openssl/include -Wl,--exclude-libs,ALL" \ - ../../.venv/bin/python setup.py bdist_wheel "$PY_LIMITED_API" - -auditwheel repair --plat "${PLATFORM}" -w wheelhouse/ dist/cryptography*.whl - -../../.venv/bin/pip install cryptography --no-index -f wheelhouse/ -../../.venv/bin/python -c "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" - -mv wheelhouse/* /test/wheelhouse.final diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index ceb2a7ee28e5..000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,112 +0,0 @@ -version: 2.1 - -commands: - docker-pull: - parameters: - image: - type: string - steps: - - run: docker pull <> || docker pull <> - docker-run: - parameters: - image: - type: string - command: - type: string - steps: - - run: docker run -e PLATFORM -e PYTHON -v $(pwd):/test <> /bin/bash -c 'cd /test;<>' - -jobs: - linux-arm64: - machine: - image: ubuntu-2004:current - resource_class: arm.medium - parameters: - image: - type: string - toxenv: - type: string - steps: - - checkout - - docker-pull: - image: <> - - docker-run: - image: <> - command: /venv/bin/tox -e <> - linux-arm64-wheel: - machine: - image: ubuntu-2004:current - resource_class: arm.medium - parameters: - image: - type: string - platform: - type: string - python: - type: string - environment: - PLATFORM: <> - PYTHON: <> - steps: - - checkout - - docker-pull: - image: <> - - docker-run: - image: <> - command: /test/.circleci/build-wheel.sh - - store_artifacts: - path: wheelhouse.final - -workflows: - ci: - jobs: - - linux-arm64: - # Changing this name should only be done in conjunction with updating - # the required checks on GH - name: linux-arm64-ci - image: ghcr.io/pyca/cryptography-runner-ubuntu-focal:aarch64 - toxenv: py38 - # This makes sure it runs on all tags in addition to PRs/branches. - # By default CircleCI ignores tags. - filters: - tags: - only: /.*/ - - linux-arm64: - name: linux-arm64-alpine-ci - image: ghcr.io/pyca/cryptography-runner-alpine:aarch64 - toxenv: py310 - filters: - tags: - only: /.*/ - - linux-arm64-wheel: - name: manylinux2014_aarch64-wheel - image: ghcr.io/pyca/cryptography-manylinux2014_aarch64:latest - python: cp36-cp36m - platform: manylinux2014_aarch64 - filters: - tags: - only: /.*/ - - linux-arm64-wheel: - name: manylinux_2_24_aarch64-wheel - image: ghcr.io/pyca/cryptography-manylinux_2_24:aarch64 - python: cp36-cp36m - platform: manylinux_2_24_aarch64 - filters: - tags: - only: /.*/ - - linux-arm64-wheel: - name: manylinux_2_28_aarch64-wheel - image: ghcr.io/pyca/cryptography-manylinux_2_28:aarch64 - python: cp36-cp36m - platform: manylinux_2_28_aarch64 - filters: - tags: - only: /.*/ - - linux-arm64-wheel: - name: musllinux_1_1_aarch64-wheel - image: ghcr.io/pyca/cryptography-musllinux_1_1:aarch64 - python: cp36-cp36m - platform: musllinux_1_1_aarch64 - filters: - tags: - only: /.*/ diff --git a/.github/workflows/build_openssl.sh b/.github/workflows/build_openssl.sh index 947b828222b2..6dd6e04fc331 100755 --- a/.github/workflows/build_openssl.sh +++ b/.github/workflows/build_openssl.sh @@ -68,15 +68,12 @@ elif [[ "${TYPE}" == "boringssl" ]]; then git checkout "${VERSION}" mkdir build pushd build - cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON + # Find the default rust target based on what rustc is built for + cmake .. -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DRUST_BINDINGS="$(rustc -V --verbose | grep 'host: ' | sed 's/host: //')" -DCMAKE_INSTALL_PREFIX="${OSSL_PATH}" make -j"$(nproc)" - mkdir -p "${OSSL_PATH}/lib/" - mkdir -p "${OSSL_PATH}/include/" - mkdir -p "${OSSL_PATH}/bin/" - cp -r ../include/openssl "${OSSL_PATH}/include/" - cp ssl/libssl.a "${OSSL_PATH}/lib/" - cp crypto/libcrypto.a "${OSSL_PATH}/lib/" - cp tool/bssl "${OSSL_PATH}/bin/openssl" + make install + # BoringSSL doesn't have a bin/openssl and we use that to detect success + touch "${OSSL_PATH}/bin/openssl" popd popd fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0dcce6503b7f..8b55ddf0e5a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,23 +40,23 @@ jobs: - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "libressl", VERSION: "3.7.0"}} - {VERSION: "3.11", TOXENV: "py311-randomorder"} - {VERSION: "3.12-dev", TOXENV: "py312"} - # Latest commit on the BoringSSL master branch, as of Dec 23, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "31bad2514d21f6207f3925ba56754611c462a873"}} - # Latest commit on the OpenSSL master branch, as of Dec 29, 2022. - - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "43a9e682d80d0abe4ffd0c76d18c43cf059a2bcc"}} + # Latest commit on the BoringSSL master branch, as of Jan 28, 2023. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "boringssl", VERSION: "80a243e07ef77156af66efa7d22ac35aba44c1b3"}} + # Latest commit on the OpenSSL master branch, as of Jan 28, 2023. + - {VERSION: "3.11", TOXENV: "py311", OPENSSL: {TYPE: "openssl", VERSION: "6a9453572533e4a22e6f60fe8f6b7ef0823d9c1f"}} name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.TOXARGS }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 timeout-minutes: 5 with: path: | @@ -69,13 +69,13 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-${{ steps.setup-python.outputs.python-version }}-cargo-5-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: repository: "google/wycheproof" path: "wycheproof" ref: "master" - - run: python -m pip install tox requests coverage[toml] + - run: python -m pip install -c ci-constraints-requirements.txt tox requests coverage[toml] - name: Compute config hash and set config vars run: | DEFAULT_CONFIG_FLAGS="shared no-ssl2 no-ssl3" @@ -89,14 +89,14 @@ jobs: CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} if: matrix.PYTHON.OPENSSL - name: Load cache - uses: actions/cache@v3.2.2 + uses: actions/cache@v3.2.3 id: ossl-cache timeout-minutes: 5 with: path: ${{ github.workspace }}/osslcache # When altering the openssl build process you may need to increment the value on the end of this cache key # so that you can prevent it from fetching the cache and skipping the build step. - key: ${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.CONFIG_HASH }}-4 + key: ${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${{ env.CONFIG_HASH }}-6 if: matrix.PYTHON.OPENSSL - name: Build custom OpenSSL/LibreSSL run: .github/workflows/build_openssl.sh @@ -120,35 +120,46 @@ jobs: - uses: ./.github/actions/upload-coverage linux-distros: - runs-on: ubuntu-latest + runs-on: ${{ matrix.IMAGE.RUNNER }} container: ghcr.io/pyca/cryptography-runner-${{ matrix.IMAGE.IMAGE }} strategy: fail-fast: false matrix: IMAGE: - - {IMAGE: "rhel8", TOXENV: "py36"} - - {IMAGE: "rhel8-fips", TOXENV: "py36", FIPS: true} - - {IMAGE: "rhel8", TOXENV: "py38"} - - {IMAGE: "rhel8-fips", TOXENV: "py38", FIPS: true} - - {IMAGE: "buster", TOXENV: "py37"} - - {IMAGE: "bullseye", TOXENV: "py39"} - - {IMAGE: "bookworm", TOXENV: "py310"} - - {IMAGE: "sid", TOXENV: "py310"} - - {IMAGE: "ubuntu-bionic", TOXENV: "py36"} - - {IMAGE: "ubuntu-focal", TOXENV: "py38"} - - {IMAGE: "ubuntu-jammy", TOXENV: "py310"} - - {IMAGE: "ubuntu-rolling", TOXENV: "py310"} - - {IMAGE: "fedora", TOXENV: "py311"} - - {IMAGE: "alpine", TOXENV: "py310"} - - {IMAGE: "centos-stream9", TOXENV: "py39"} - name: "${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" + - {IMAGE: "rhel8", TOXENV: "py36", RUNNER: "ubuntu-latest"} + - {IMAGE: "rhel8-fips", TOXENV: "py36", RUNNER: "ubuntu-latest", FIPS: true} + - {IMAGE: "rhel8", TOXENV: "py38", RUNNER: "ubuntu-latest"} + - {IMAGE: "rhel8-fips", TOXENV: "py38", RUNNER: "ubuntu-latest", FIPS: true} + - {IMAGE: "buster", TOXENV: "py37", RUNNER: "ubuntu-latest"} + - {IMAGE: "bullseye", TOXENV: "py39", RUNNER: "ubuntu-latest"} + - {IMAGE: "bookworm", TOXENV: "py310", 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"} + - {IMAGE: "fedora", TOXENV: "py311", RUNNER: "ubuntu-latest"} + - {IMAGE: "alpine", TOXENV: "py310", RUNNER: "ubuntu-latest"} + - {IMAGE: "centos-stream9", TOXENV: "py39", RUNNER: "ubuntu-latest"} + + - {IMAGE: "ubuntu-jammy:aarch64", TOXENV: "py310", RUNNER: [self-hosted, Linux, ARM64]} + - {IMAGE: "alpine:aarch64", TOXENV: "py310", RUNNER: [self-hosted, Linux, ARM64]} timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - name: Ridiculous alpine workaround for actions support on arm64 + run: | + # This modifies /etc/os-release so the JS actions + # from GH can't detect that it's on alpine:aarch64. It will + # then use a glibc nodejs, which works fine when gcompat + # is installed in the container (which it is) + sed -i "s:ID=alpine:ID=NotpineForGHA:" /etc/os-release + if: matrix.IMAGE.IMAGE == 'alpine:aarch64' + + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 timeout-minutes: 5 with: path: | @@ -159,9 +170,9 @@ jobs: ~/.cargo/registry/src/ ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ matrix.IMAGE.IMAGE }}-${{ runner.arch }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -175,6 +186,7 @@ jobs: 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 coverage - run: '/venv/bin/tox -vvv -- --wycheproof-root="wycheproof"' env: TOXENV: ${{ matrix.IMAGE.TOXENV }} @@ -201,14 +213,15 @@ jobs: # Potential future MSRVs # 1.51 - const generics (for rust-asn1) # 1.56 - new versions of once_cell and bumpalo + # 1.60 - new version of cxx name: "${{ matrix.PYTHON.TOXENV }} with Rust ${{ matrix.RUST }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 timeout-minutes: 5 with: path: | @@ -222,19 +235,19 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-${{ matrix.RUST }} - name: Setup python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f + - uses: dtolnay/rust-toolchain@ce8f65846d7180d2ce63b1e74483d981800b9e22 with: toolchain: ${{ matrix.RUST }} - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: repository: "google/wycheproof" path: "wycheproof" ref: "master" - - run: python -m pip install tox coverage[toml] + - run: python -m pip install -c ci-constraints-requirements.txt tox coverage[toml] - name: Tests run: | tox -vvv -r -- --color=yes --wycheproof-root=wycheproof @@ -254,12 +267,14 @@ jobs: - nightly name: "Rust Coverage" timeout-minutes: 15 + env: + CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 id: cargo-cache timeout-minutes: 5 with: @@ -274,23 +289,23 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }}-rust-${{ matrix.RUST }}-coverage - name: Setup python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} - - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f + - uses: dtolnay/rust-toolchain@ce8f65846d7180d2ce63b1e74483d981800b9e22 with: toolchain: ${{ matrix.RUST }} components: llvm-tools-preview - run: cargo install cargo-binutils if: steps.cargo-cache.outputs.cache-hit != 'true' - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: repository: "google/wycheproof" path: "wycheproof" ref: "master" - - run: python -m pip install tox coverage[toml] + - run: python -m pip install -c ci-constraints-requirements.txt tox coverage[toml] - name: Tests run: | tox -vvv -r -- --color=yes --wycheproof-root=wycheproof @@ -331,21 +346,28 @@ jobs: - uses: ./.github/actions/upload-coverage macos: - runs-on: macos-12 + runs-on: ${{ matrix.RUNNER.OS }} strategy: fail-fast: false matrix: + RUNNER: + - {OS: 'macos-12', ARCH: 'x86_64'} + - {OS: [self-hosted, macos, ARM64, tart], ARCH: 'arm64'} PYTHON: - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} - - {VERSION: "3.10", TOXENV: "py310", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} - name: "${{ matrix.PYTHON.TOXENV }} on macOS" + - {VERSION: "3.11", TOXENV: "py311", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} + 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", EXTRA_CFLAGS: ""} + RUNNER: {OS: [self-hosted, macos, ARM64, tart], ARCH: 'arm64'} + name: "${{ matrix.PYTHON.TOXENV }} on macOS ${{ matrix.RUNNER.ARCH }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 timeout-minutes: 5 with: path: | @@ -356,16 +378,17 @@ jobs: ~/.cargo/registry/src/ ~/.cargo/git/db/ src/rust/target/ - key: ${{ runner.os }}-${{ matrix.PYTHON.VERSION }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} + key: ${{ runner.os }}-${{ runner.arch }}-${{ matrix.PYTHON.VERSION }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} + architecture: 'x64' # we force this right now so that it will install the universal2 on arm64 - - run: python -m pip install tox requests coverage[toml] + - run: python -m pip install -c ci-constraints-requirements.txt tox requests coverage[toml] - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -381,7 +404,7 @@ jobs: run: | CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \ LDFLAGS="${HOME}/openssl-macos-universal2/lib/libcrypto.a ${HOME}/openssl-macos-universal2/lib/libssl.a" \ - CFLAGS="-I${HOME}/openssl-macos-universal2/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -mmacosx-version-min=10.12 -march=core2 $EXTRA_CFLAGS" \ + CFLAGS="-I${HOME}/openssl-macos-universal2/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -mmacosx-version-min=10.12 $EXTRA_CFLAGS" \ tox -vvv -r -- --color=yes --wycheproof-root=wycheproof env: TOXENV: ${{ matrix.PYTHON.TOXENV }} @@ -405,17 +428,17 @@ jobs: name: "${{ matrix.PYTHON.TOXENV }} on ${{ matrix.WINDOWS.WINDOWS }} (part ${{ matrix.JOB_NUMBER }})" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - name: Setup python id: setup-python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 timeout-minutes: 5 with: path: | @@ -428,7 +451,7 @@ jobs: src/rust/target/ key: ${{ runner.os }}-${{ matrix.WINDOWS.ARCH }}-${{ steps.setup-python.outputs.python-version }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - - run: python -m pip install tox requests coverage[toml] + - run: python -m pip install -c ci-constraints-requirements.txt "tox>3" requests coverage[toml] - name: Download OpenSSL run: | python .github/workflows/download_openssl.py windows openssl-${{ matrix.WINDOWS.WINDOWS }} @@ -438,7 +461,7 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} shell: bash - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: repository: "google/wycheproof" @@ -469,15 +492,15 @@ jobs: - mitmproxy - scapy PYTHON: - - 3.9 + - '3.11' name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false - - uses: actions/cache@v3.2.2 + - uses: actions/cache@v3.2.3 timeout-minutes: 5 with: path: | @@ -491,7 +514,7 @@ jobs: key: ${{ runner.os }}-cargo-3-${{ hashFiles('**/Cargo.lock') }} - name: Setup python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON }} - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install @@ -523,14 +546,14 @@ jobs: name: "linkcheck" timeout-minutes: 15 steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 with: persist-credentials: false - name: Setup python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: 3.11 - - run: python -m pip install -U tox + - run: python -m pip install -c ci-constraints-requirements.txt tox - run: tox -r -- --color=yes env: TOXENV: docs-linkcheck @@ -541,7 +564,7 @@ jobs: needs: [linux, linux-distros, linux-rust, linux-rust-coverage, macos, windows, linux-downstream] if: ${{ always() }} steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 timeout-minutes: 3 with: persist-credentials: false @@ -551,14 +574,14 @@ jobs: jobs: ${{ toJSON(needs) }} - name: Setup python if: ${{ always() }} - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: '3.10' - - run: pip install coverage[toml] + - run: pip install -c ci-constraints-requirements.txt coverage[toml] if: ${{ always() }} - name: Download coverage data if: ${{ always() }} - uses: actions/download-artifact@v3.0.1 + uses: actions/download-artifact@v3.0.2 with: name: coverage-data - name: Combine coverage and fail if it's <100%. @@ -600,14 +623,14 @@ jobs: run: python -m coverage html if: ${{ failure() && steps.combinecoverage.outcome == 'failure' }} - name: Upload HTML report. - uses: actions/upload-artifact@v3.1.1 + uses: actions/upload-artifact@v3.1.2 with: name: _html-report path: htmlcov if-no-files-found: ignore if: ${{ failure() && steps.combinecoverage.outcome == 'failure' }} - name: Upload rust HTML report. - uses: actions/upload-artifact@v3.1.1 + uses: actions/upload-artifact@v3.1.2 with: name: _html-rust-report path: rust-coverage diff --git a/.github/workflows/macarm64.yml b/.github/workflows/macarm64.yml deleted file mode 100644 index 71c1419a279f..000000000000 --- a/.github/workflows/macarm64.yml +++ /dev/null @@ -1,65 +0,0 @@ -name: macOS arm64 CI -on: - push: - branches: - - main - - '*.*.x' - tags: - - '*.*' - - '*.*.*' - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} - cancel-in-progress: true - -jobs: - macos-arm64: - if: github.repository_owner == 'pyca' - runs-on: [self-hosted, macos, ARM64] - name: "macOS arm64" - strategy: - fail-fast: false - matrix: - PYTHON: - - {TOXENV: "py310", BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.10/bin/python3'} - timeout-minutes: 10 - steps: - - name: "Delete workspace" # self-hosted runners need this, sigh - run: gfind ! -name '.' ! -name '..' -delete - - uses: actions/checkout@v3.2.0 - with: - persist-credentials: false - - uses: actions/cache@v3.2.2 - with: - path: | - src/rust/target/ - key: ${{ runner.os }}-${{ matrix.PYTHON.TOXENV }}-cargo-macarm64-${{ hashFiles('**/Cargo.lock') }} - - - uses: actions/checkout@v3.2.0 - with: - repository: "google/wycheproof" - path: "wycheproof" - ref: "master" - - name: Setup venv and install deps - run: | - $BIN_PATH -m venv venv - venv/bin/python -m pip install tox requests - env: - BIN_PATH: ${{ matrix.PYTHON.BIN_PATH }} - - name: Download OpenSSL - run: | - venv/bin/python .github/workflows/download_openssl.py macos openssl-macos-universal2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Tests - run: | - CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \ - LDFLAGS="${HOME}/openssl-macos-universal2/lib/libcrypto.a ${HOME}/openssl-macos-universal2/lib/libssl.a" \ - CFLAGS="-I${HOME}/openssl-macos-universal2/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function $EXTRA_CFLAGS" \ - venv/bin/tox -r -- --color=yes --wycheproof-root=wycheproof - env: - TOXENV: ${{ matrix.PYTHON.TOXENV }} - CARGO_TARGET_DIR: ${{ format('{0}/src/rust/target/', github.workspace) }} diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 9bf72146de86..2c575efb7a3f 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest name: sdists steps: - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} @@ -37,18 +37,18 @@ jobs: run: .venv/bin/python setup.py sdist - name: Make sdist and wheel (vectors) run: cd vectors/ && ../.venv/bin/python setup.py sdist bdist_wheel - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@v3.1.2 with: name: "cryptography-sdist" path: dist/cryptography* - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@v3.1.2 with: name: "vectors-sdist-wheel" path: vectors/dist/cryptography* manylinux: needs: [sdist] - runs-on: ubuntu-latest + runs-on: ${{ matrix.MANYLINUX.RUNNER }} container: ghcr.io/pyca/${{ matrix.MANYLINUX.CONTAINER }} strategy: fail-fast: false @@ -58,19 +58,47 @@ jobs: - { VERSION: "pp38-pypy38_pp73" } - { VERSION: "pp39-pypy39_pp73" } MANYLINUX: - - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64" } - - { NAME: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64"} - - { NAME: "manylinux_2_28_x86_64", CONTAINER: "cryptography-manylinux_2_28:x86_64"} - - { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + - { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64", RUNNER: "ubuntu-latest" } + - { NAME: "manylinux_2_24_x86_64", CONTAINER: "cryptography-manylinux_2_24:x86_64", RUNNER: "ubuntu-latest"} + - { NAME: "manylinux_2_28_x86_64", CONTAINER: "cryptography-manylinux_2_28:x86_64", RUNNER: "ubuntu-latest"} + - { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64", RUNNER: "ubuntu-latest"} + + - { NAME: "manylinux2014_aarch64", CONTAINER: "cryptography-manylinux2014_aarch64", RUNNER: [self-hosted, Linux, ARM64] } + - { NAME: "manylinux_2_24_aarch64", CONTAINER: "cryptography-manylinux_2_24:aarch64", RUNNER: [self-hosted, Linux, ARM64]} + - { NAME: "manylinux_2_28_aarch64", CONTAINER: "cryptography-manylinux_2_28:aarch64", RUNNER: [self-hosted, Linux, ARM64]} + - { NAME: "musllinux_1_1_aarch64", CONTAINER: "cryptography-musllinux_1_1:aarch64", RUNNER: [self-hosted, Linux, ARM64]} exclude: # There are no readily available musllinux PyPy distributions - PYTHON: { VERSION: "pp38-pypy38_pp73" } - MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64", RUNNER: "ubuntu-latest"} + - PYTHON: { VERSION: "pp39-pypy39_pp73" } + MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64", RUNNER: "ubuntu-latest"} + - PYTHON: { VERSION: "pp38-pypy38_pp73" } + MANYLINUX: { NAME: "musllinux_1_1_aarch64", CONTAINER: "cryptography-musllinux_1_1:aarch64", RUNNER: [self-hosted, Linux, ARM64]} + - PYTHON: { VERSION: "pp39-pypy39_pp73" } + MANYLINUX: { NAME: "musllinux_1_1_aarch64", CONTAINER: "cryptography-musllinux_1_1:aarch64", RUNNER: [self-hosted, Linux, ARM64]} + # We also don't build pypy wheels for anything except the latest manylinux + - PYTHON: { VERSION: "pp38-pypy38_pp73" } + MANYLINUX: { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64", RUNNER: "ubuntu-latest"} - PYTHON: { VERSION: "pp39-pypy39_pp73" } - MANYLINUX: { NAME: "musllinux_1_1_x86_64", CONTAINER: "cryptography-musllinux_1_1:x86_64"} + MANYLINUX: { NAME: "manylinux2014_x86_64", CONTAINER: "cryptography-manylinux2014:x86_64", RUNNER: "ubuntu-latest"} + - PYTHON: { VERSION: "pp38-pypy38_pp73" } + MANYLINUX: { NAME: "manylinux2014_aarch64", CONTAINER: "cryptography-manylinux2014_aarch64", RUNNER: [self-hosted, Linux, ARM64]} + - PYTHON: { VERSION: "pp39-pypy39_pp73" } + MANYLINUX: { NAME: "manylinux2014_aarch64", CONTAINER: "cryptography-manylinux2014_aarch64", RUNNER: [self-hosted, Linux, ARM64]} + - PYTHON: { VERSION: "pp38-pypy38_pp73" } name: "${{ matrix.PYTHON.VERSION }} for ${{ matrix.MANYLINUX.NAME }}" steps: - - uses: actions/download-artifact@v3.0.1 + - name: Ridiculous alpine workaround for actions support on arm64 + run: | + # This modifies /etc/os-release so the JS actions + # from GH can't detect that it's on alpine:aarch64. It will + # then use a glibc nodejs, which works fine when gcompat + # is installed in the container (which it is) + sed -i "s:ID=alpine:ID=NotpineForGHA:" /etc/os-release + if: matrix.MANYLINUX.NAME == 'musllinux_1_1_aarch64' + + - uses: actions/download-artifact@v3.0.2 with: name: cryptography-sdist @@ -104,7 +132,7 @@ jobs: .venv/bin/python -c "from cryptography.hazmat.backends.openssl.backend import backend;print('Loaded: ' + backend.openssl_version_text());print('Linked Against: ' + backend._ffi.string(backend._lib.OPENSSL_VERSION_TEXT).decode('ascii'))" - run: mkdir cryptography-wheelhouse - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@v3.1.2 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.MANYLINUX.NAME }}-${{ matrix.PYTHON.VERSION }}" path: cryptography-wheelhouse/ @@ -151,12 +179,12 @@ jobs: name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS ${{ matrix.PYTHON.ARCHFLAGS }}" steps: # Needed for download_openssl.py - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} persist-credentials: false - - uses: actions/download-artifact@v3.0.1 + - uses: actions/download-artifact@v3.0.2 with: name: cryptography-sdist @@ -168,17 +196,17 @@ jobs: PYTHON_DOWNLOAD_URL: ${{ matrix.PYTHON.DOWNLOAD_URL }} if: contains(matrix.PYTHON.VERSION, 'pypy') == false - name: Setup pypy - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} if: contains(matrix.PYTHON.VERSION, 'pypy') - - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -U requests + - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -c ci-constraints-requirements.txt -U requests - name: Download OpenSSL run: | ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-universal2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f + - uses: dtolnay/rust-toolchain@ce8f65846d7180d2ce63b1e74483d981800b9e22 with: toolchain: stable # Add the arm64 target in addition to the native arch (x86_64) @@ -209,7 +237,7 @@ jobs: - run: mv wheelhouse/cryptography*.whl cryptography-wheelhouse/ - run: | echo "CRYPTOGRAPHY_WHEEL_NAME=$(basename $(ls cryptography-wheelhouse/cryptography*.whl))" >> $GITHUB_ENV - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@v3.1.2 with: name: "${{ env.CRYPTOGRAPHY_WHEEL_NAME }}" path: cryptography-wheelhouse/ @@ -236,26 +264,26 @@ jobs: name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: # Needed for download_openssl.py - - uses: actions/checkout@v3.2.0 + - uses: actions/checkout@v3.3.0 with: # The tag to build or the tag received by the tag event ref: ${{ github.event.inputs.version || github.ref }} persist-credentials: false - - uses: actions/download-artifact@v3.0.1 + - uses: actions/download-artifact@v3.0.2 with: name: cryptography-sdist - name: Setup python - uses: actions/setup-python@v4.4.0 + uses: actions/setup-python@v4.5.0 with: python-version: ${{ matrix.PYTHON.VERSION }} architecture: ${{ matrix.WINDOWS.ARCH }} - - uses: dtolnay/rust-toolchain@e645b0cf01249a964ec099494d38d2da0f0b349f + - uses: dtolnay/rust-toolchain@ce8f65846d7180d2ce63b1e74483d981800b9e22 with: toolchain: stable target: ${{ matrix.WINDOWS.RUST_TRIPLE }} - - run: pip install requests + - run: pip install -c ci-constraints-requirements.txt requests - name: Download OpenSSL run: | python .github/workflows/download_openssl.py windows openssl-${{ matrix.WINDOWS.WINDOWS }} @@ -277,7 +305,7 @@ jobs: - run: mkdir cryptography-wheelhouse - run: move wheelhouse\cryptography*.whl cryptography-wheelhouse\ - - uses: actions/upload-artifact@v3.1.1 + - uses: actions/upload-artifact@v3.1.2 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.WINDOWS.WINDOWS }}-${{ matrix.PYTHON.VERSION }}-${{ matrix.PYTHON.ABI_VERSION}}" path: cryptography-wheelhouse\ diff --git a/MANIFEST.in b/MANIFEST.in index 8471d75785ab..62699330e9b2 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -19,6 +19,4 @@ recursive-exclude vectors * recursive-exclude .github * -exclude release.py .readthedocs.yml dev-requirements.txt tox.ini mypy.ini - -recursive-exclude .circleci * +exclude release.py .readthedocs.yml ci-constraints-requirements.txt tox.ini mypy.ini diff --git a/ci-constraints-requirements.txt b/ci-constraints-requirements.txt new file mode 100644 index 000000000000..e7eb850fa86e --- /dev/null +++ b/ci-constraints-requirements.txt @@ -0,0 +1,230 @@ +# This is named ambigiously, but it's a pip constraints file, named like a +# requirements file so dependabot will update the pins. +# It was originally generated with; +# pip-compile --extra=docs --extra=docstest --extra=pep8test --extra=test --extra=test-randomorder --extra=tox --resolver=backtracking --strip-extras --unsafe-package=cffi --unsafe-package=pycparser --unsafe-package=setuptools setup.cfg +# and then manually massaged to add version specifiers to packages whose +# versions vary by Python version + +alabaster==0.7.13 + # via sphinx +attrs==22.2.0 + # via + # hypothesis + # pytest +babel==2.11.0 + # via sphinx +black==22.12.0 + # via cryptography (setup.cfg) +bleach==6.0.0 + # via readme-renderer +build==0.10.0 + # via check-manifest +cachetools==5.3.0 + # via tox +certifi==2022.12.7 + # via requests +chardet==5.1.0 + # via tox +charset-normalizer==3.0.1; python_version >= "3.7" + # via requests +check-manifest==0.49 + # via cryptography (setup.cfg) +click==8.1.3 + # via black +colorama==0.4.6; python_version >= "3.7" + # via tox +coverage==7.1.0; python_version >= "3.7" + # via pytest-cov +distlib==0.3.6 + # via virtualenv +docutils==0.17.1 + # via + # readme-renderer + # sphinx + # sphinx-rtd-theme +exceptiongroup==1.1.0 + # via + # hypothesis + # pytest +execnet==1.9.0 + # via pytest-xdist +filelock==3.9.0; python_version >= "3.7" + # via + # tox + # virtualenv +hypothesis==6.65.2; python_version >= "3.7" + # via cryptography (setup.cfg) +idna==3.4 + # via requests +imagesize==1.4.1 + # via sphinx +importlib-metadata==6.0.0; python_version >= "3.7" + # via + # keyring + # twine +iniconfig==2.0.0; python_version >= "3.7" + # via pytest +iso8601==1.1.0 + # via cryptography (setup.cfg) +jaraco-classes==3.2.3 + # via keyring +jinja2==3.1.2 + # via sphinx +keyring==23.13.1 + # via twine +markdown-it-py==2.1.0 + # via rich +markupsafe==2.1.2 + # via jinja2 +mdurl==0.1.2 + # via markdown-it-py +more-itertools==9.0.0 + # via jaraco-classes +mypy==0.991 + # via cryptography (setup.cfg) +mypy-extensions==0.4.3 + # via + # black + # mypy +packaging==23.0; python_version >= "3.7" + # via + # build + # pyproject-api + # pytest + # sphinx + # tox +pathspec==0.11.0 + # via black +pkginfo==1.9.6 + # via twine +platformdirs==2.6.2; python_version >= "3.7" + # via + # black + # tox + # virtualenv +pluggy==1.0.0; python_version >= "3.7" + # via + # pytest + # tox +pretend==1.0.9 + # via cryptography (setup.cfg) +py-cpuinfo==9.0.0 + # via pytest-benchmark +pyenchant==3.2.2 + # via + # cryptography (setup.cfg) + # sphinxcontrib-spelling +pygments==2.14.0 + # via + # readme-renderer + # rich + # sphinx +pyproject-api==1.5.0 + # via tox +pyproject-hooks==1.0.0 + # via build +pytest==7.2.1; python_version >= "3.7" + # via + # cryptography (setup.cfg) + # pytest-benchmark + # pytest-cov + # pytest-randomly + # pytest-shard + # pytest-subtests + # pytest-xdist +pytest-benchmark==4.0.0; python_version >= "3.7" + # via cryptography (setup.cfg) +pytest-cov==4.0.0 + # via cryptography (setup.cfg) +pytest-randomly==3.12.0 + # via cryptography (setup.cfg) +pytest-shard==0.1.2 + # via cryptography (setup.cfg) +pytest-subtests==0.9.0; python_version >= "3.7" + # via cryptography (setup.cfg) +pytest-xdist==3.1.0; python_version >= "3.7" + # via cryptography (setup.cfg) +pytz==2022.7.1 + # via + # babel + # cryptography (setup.cfg) +readme-renderer==37.3 + # via twine +requests==2.28.2; python_version >= "3.7" + # via + # requests-toolbelt + # sphinx + # twine +requests-toolbelt==0.10.1 + # via twine +rfc3986==2.0.0 + # via twine +rich==13.3.0 + # via twine +ruff==0.0.236 + # via cryptography (setup.cfg) +six==1.16.0 + # via bleach +snowballstemmer==2.2.0 + # via sphinx +sortedcontainers==2.4.0 + # via hypothesis +sphinx==5.3.0 + # via + # cryptography (setup.cfg) + # sphinx-rtd-theme + # sphinxcontrib-spelling +sphinx-rtd-theme==1.1.1 + # via cryptography (setup.cfg) +sphinxcontrib-applehelp==1.0.4 + # via sphinx +sphinxcontrib-devhelp==1.0.2 + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-qthelp==1.0.3 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 + # via sphinx +sphinxcontrib-spelling==7.7.0 + # via cryptography (setup.cfg) +tomli==2.0.1; python_version >= "3.7" + # via + # black + # build + # check-manifest + # coverage + # mypy + # pyproject-api + # pyproject-hooks + # pytest + # tox +tox==4.4.2; python_version >= "3.7" + # via cryptography (setup.cfg) +twine==4.0.2 + # via cryptography (setup.cfg) +types-pytz==2022.7.1.0 + # via cryptography (setup.cfg) +types-requests==2.28.11.8 + # via cryptography (setup.cfg) +types-urllib3==1.26.25.4 + # via types-requests +typing-extensions==4.4.0; python_version >= "3.7" + # via mypy +urllib3==1.26.14 + # via + # requests + # twine +virtualenv==20.17.1 + # via tox +webencodings==0.5.1 + # via bleach +zipp==3.12.0; python_version >= "3.7" + # via importlib-metadata + +# The following packages are considered to be unsafe in a requirements file: +# cffi +# pycparser +# setuptools diff --git a/dev-requirements.txt b/dev-requirements.txt deleted file mode 100644 index 41d533168eda..000000000000 --- a/dev-requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -click -tox >= 2.4.1 -twine >= 1.8.0 --e .[test,docs,docstest,pep8test] --e vectors diff --git a/setup.cfg b/setup.cfg index 7a78922c0e2d..8a22fec8b068 100644 --- a/setup.cfg +++ b/setup.cfg @@ -55,8 +55,11 @@ exclude = _cffi_src.* [options.extras_require] +tox = + tox test = pytest>=6.2.0 + pytest-shard>=0.1.2 pytest-benchmark pytest-cov pytest-subtests @@ -65,9 +68,11 @@ test = iso8601 pytz hypothesis>=1.11.4,!=3.79.2 +test-randomorder: + pytest-randomly docs = - sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1,!=5.2.0,!=5.2.0.post0 - sphinx_rtd_theme + sphinx >= 5.3.0 + sphinx-rtd-theme>=1.1.1 docstest = pyenchant >= 1.6.11 twine >= 1.12.0 @@ -77,6 +82,10 @@ sdist = pep8test = black ruff + mypy + types-pytz + types-requests + check-manifest # This extra is for OpenSSH private keys that use bcrypt KDF # Versions: v3.1.3 - ignore_few_rounds, v3.1.5 - abi3 ssh = diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py index 863973fc0d08..838bda2903ec 100644 --- a/src/_cffi_src/openssl/x509v3.py +++ b/src/_cffi_src/openssl/x509v3.py @@ -51,7 +51,7 @@ X509_EXTENSION *X509V3_EXT_nconf(CONF *, X509V3_CTX *, const char *, const char *); -void *X509V3_set_ctx_nodb(X509V3_CTX *); +void X509V3_set_ctx_nodb(X509V3_CTX *); int sk_GENERAL_NAME_num(struct stack_st_GENERAL_NAME *); GENERAL_NAME *sk_GENERAL_NAME_value(struct stack_st_GENERAL_NAME *, int); diff --git a/tox.ini b/tox.ini index fc30b72f101c..b369da8e9f79 100644 --- a/tox.ini +++ b/tox.ini @@ -6,10 +6,9 @@ isolated_build = True extras = test ssh: ssh + randomorder: test-randomorder deps = -e ./vectors - pytest-shard>=0.1.2 - randomorder: pytest-randomly passenv = ARCHFLAGS LDFLAGS @@ -26,6 +25,8 @@ passenv = CRYPTOGRAPHY_OPENSSL_NO_LEGACY OPENSSL_ENABLE_SHA1_SIGNATURES CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS +setenv = + PIP_CONSTRAINT=ci-constraints-requirements.txt commands = pip list !nocoverage: pytest -n auto --cov=cryptography --cov=tests --durations=10 {posargs} tests/ @@ -59,11 +60,6 @@ extras = pep8test test ssh -deps = - mypy - types-pytz - types-requests - check-manifest commands = ruff . black --check . From 69527bc79095c9646d7e839121f0783477892ecc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 2 Feb 2023 18:44:52 -0800 Subject: [PATCH 296/298] bookworm is py311 now (#8200) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8b55ddf0e5a7..8d50fcc955f6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,7 +132,7 @@ jobs: - {IMAGE: "rhel8-fips", TOXENV: "py38", RUNNER: "ubuntu-latest", FIPS: true} - {IMAGE: "buster", TOXENV: "py37", RUNNER: "ubuntu-latest"} - {IMAGE: "bullseye", TOXENV: "py39", RUNNER: "ubuntu-latest"} - - {IMAGE: "bookworm", TOXENV: "py310", 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"} From 138da90c8450446b19619e3faa77b9da54c34be3 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 7 Feb 2023 09:16:59 -0500 Subject: [PATCH 297/298] workaround scapy bug in downstream tests (#8218) (#8228) --- .github/downstream.d/scapy.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/downstream.d/scapy.sh b/.github/downstream.d/scapy.sh index ac1b8f820016..5ef3648ae2df 100755 --- a/.github/downstream.d/scapy.sh +++ b/.github/downstream.d/scapy.sh @@ -5,7 +5,8 @@ case "${1}" in git clone --depth=1 https://github.com/secdev/scapy cd scapy git rev-parse HEAD - pip install tox + # Pin virtualenv until https://github.com/secdev/scapy/pull/3862 is merged + pip install tox 'virtualenv<20.18' ;; run) cd scapy From d6951dca25de45abd52da51b608055371fbcde4e Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 7 Feb 2023 12:24:19 -0600 Subject: [PATCH 298/298] changelog + security fix backport (#8231) * Don't allow update_into to mutate immutable objects (#8230) * add changelog for 39.0.1 * oops * bump versions * remove circle --------- Co-authored-by: Alex Gaynor --- CHANGELOG.rst | 9 +++++++++ src/cryptography/__about__.py | 2 +- src/cryptography/hazmat/backends/openssl/ciphers.py | 2 +- tests/hazmat/primitives/test_ciphers.py | 8 ++++++++ vectors/cryptography_vectors/__about__.py | 2 +- 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bd70b9bc7b34..3742c6ac945c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Changelog ========= +.. _v39-0-1: + +39.0.1 - 2023-02-07 +~~~~~~~~~~~~~~~~~~~ + +* **SECURITY ISSUE** - Fixed a bug where ``Cipher.update_into`` accepted Python + buffer protocol objects, but allowed immutable buffers. **CVE-2023-23931** +* Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL 3.0.8. + .. _v39-0-0: 39.0.0 - 2023-01-01 diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 83439a962dd3..bd0b15c14657 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -9,7 +9,7 @@ "__copyright__", ] -__version__ = "39.0.0" +__version__ = "39.0.1" __author__ = "The Python Cryptographic Authority and individual contributors" __copyright__ = "Copyright 2013-2022 {}".format(__author__) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index fd2b6612f046..e5c2b6fd8453 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -156,7 +156,7 @@ def update_into(self, data: bytes, buf: bytes) -> int: data_processed = 0 total_out = 0 outlen = self._backend._ffi.new("int *") - baseoutbuf = self._backend._ffi.from_buffer(buf) + baseoutbuf = self._backend._ffi.from_buffer(buf, require_writable=True) baseinbuf = self._backend._ffi.from_buffer(data) while data_processed != total_data_len: diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index 02127dd9cab5..bf3b047dec25 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -318,6 +318,14 @@ def test_update_into_buffer_too_small(self, backend): with pytest.raises(ValueError): encryptor.update_into(b"testing", buf) + def test_update_into_immutable(self, backend): + key = b"\x00" * 16 + c = ciphers.Cipher(AES(key), modes.ECB(), backend) + encryptor = c.encryptor() + buf = b"\x00" * 32 + with pytest.raises((TypeError, BufferError)): + encryptor.update_into(b"testing", buf) + @pytest.mark.supported( only_if=lambda backend: backend.cipher_supported( AES(b"\x00" * 16), modes.GCM(b"\x00" * 12) diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 9b607dd65f03..9452a5c1e801 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -6,4 +6,4 @@ "__version__", ] -__version__ = "39.0.0" +__version__ = "39.0.1"