From 558cf91f4760193e73ad6dc42b2ad6e87a06909b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 25 Oct 2020 23:50:35 -0400 Subject: [PATCH 01/61] Reopen master for 3.3 (#5509) * Reopen master for 3.3 * its how you know its authentic alex gaynor code --- CHANGELOG.rst | 7 +++++++ src/cryptography/__about__.py | 4 ++-- vectors/cryptography_vectors/__about__.py | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 007f802006d1..cf3d3779af7c 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,13 @@ Changelog ========= +.. _v3-3: + +3.3 - `master`_ +~~~~~~~~~~~~~~~ + +.. note:: This version is not yet released and is under active development. + .. _v3-2: 3.2 - 2020-10-25 diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index b960f7ed1af5..758b17899647 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -22,10 +22,10 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.2" +__version__ = "3.3.dev1" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2019 {}".format(__author__) +__copyright__ = "Copyright 2013-2020 {}".format(__author__) diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 3b41b82e0ab9..9252c0f0f0d0 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -20,10 +20,10 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.2" +__version__ = "3.3.dev1" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2019 %s" % __author__ +__copyright__ = "Copyright 2013-2020 %s" % __author__ From d3eae8d7dbcd7ca491531424a4ac8b4838acf199 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 26 Oct 2020 01:41:40 -0400 Subject: [PATCH 02/61] Delete all the 1.0.2 code (#5511) --- .readthedocs.yml | 5 + .travis.yml | 5 - MANIFEST.in | 2 +- docs/development/c-bindings.rst | 4 +- docs/faq.rst | 29 ++--- docs/hazmat/backends/openssl.rst | 2 +- docs/installation.rst | 5 - src/_cffi_src/build_openssl.py | 20 ++-- src/_cffi_src/openssl/bio.py | 6 - src/_cffi_src/openssl/callbacks.py | 2 +- src/_cffi_src/openssl/crypto.py | 4 +- src/_cffi_src/openssl/cryptography.py | 15 --- src/_cffi_src/openssl/dh.py | 74 +----------- src/_cffi_src/openssl/dsa.py | 66 ----------- src/_cffi_src/openssl/evp.py | 8 +- src/_cffi_src/openssl/hmac.py | 26 +---- src/_cffi_src/openssl/nid.py | 14 --- src/_cffi_src/openssl/ocsp.py | 8 +- src/_cffi_src/openssl/rsa.py | 107 ------------------ src/_cffi_src/openssl/ssl.py | 70 +----------- src/_cffi_src/openssl/x509.py | 44 +------ src/_cffi_src/openssl/x509_vfy.py | 26 +---- src/_cffi_src/openssl/x509name.py | 2 +- .../hazmat/backends/openssl/backend.py | 10 +- .../hazmat/backends/openssl/ec.py | 6 +- .../hazmat/backends/openssl/hmac.py | 10 +- .../hazmat/bindings/openssl/_conditional.py | 27 ----- .../hazmat/bindings/openssl/binding.py | 27 ----- tests/hazmat/backends/test_openssl.py | 2 +- tests/hazmat/bindings/test_openssl.py | 16 +-- tests/wycheproof/test_rsa.py | 17 +-- tests/x509/test_x509.py | 4 - tests/x509/test_x509_ext.py | 6 +- tox.ini | 2 - 34 files changed, 61 insertions(+), 610 deletions(-) create mode 100644 .readthedocs.yml diff --git a/.readthedocs.yml b/.readthedocs.yml new file mode 100644 index 000000000000..728bb390c30c --- /dev/null +++ b/.readthedocs.yml @@ -0,0 +1,5 @@ +version: 2 + +build: + image: "7.0" + diff --git a/.travis.yml b/.travis.yml index b0f0fe78d6e6..a13a977f16f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -31,8 +31,6 @@ matrix: env: TOXENV=pypy-nocoverage - python: pypy3.6-7.3.1 env: TOXENV=pypy3-nocoverage - - python: 3.8 - env: TOXENV=py38 OPENSSL=1.0.2u - python: 2.7 env: TOXENV=py27 OPENSSL=1.1.0l - python: 2.7 @@ -56,9 +54,6 @@ matrix: - python: 3.8 env: TOXENV=py38 LIBRESSL=3.2.2 - - python: 2.7 - services: docker - env: TOXENV=py27 DOCKER=pyca/cryptography-runner-centos7 - python: 2.7 services: docker env: TOXENV=py27 DOCKER=pyca/cryptography-runner-centos8 diff --git a/MANIFEST.in b/MANIFEST.in index 7e97167a1b63..2b90d2465543 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -20,7 +20,7 @@ exclude .travis.yml .travis recursive-exclude .travis * recursive-exclude .github * -exclude release.py .coveragerc codecov.yml dev-requirements.txt rtd-requirements.txt tox.ini +exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt rtd-requirements.txt tox.ini recursive-exclude .zuul.d * recursive-exclude .zuul.playbooks * diff --git a/docs/development/c-bindings.rst b/docs/development/c-bindings.rst index efc21ca0a8f5..e53e0bae7f65 100644 --- a/docs/development/c-bindings.rst +++ b/docs/development/c-bindings.rst @@ -189,9 +189,9 @@ Caveats Sometimes, a set of loosely related features are added in the same version, and it's impractical to create ``#ifdef`` statements for each one. In that case, it may make sense to either check for a particular -version. For example, to check for OpenSSL 1.1.0 or newer:: +version. For example, to check for OpenSSL 1.1.1 or newer:: - #if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER + #if CRYPTOGRAPHY_OPENSSL_111_OR_GREATER Sometimes, the version of a library on a particular platform will have features that you thought it wouldn't, based on its version. diff --git a/docs/faq.rst b/docs/faq.rst index 33c5417d12db..563a241e4f1b 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -109,27 +109,14 @@ Your ``pip`` and/or ``setuptools`` are outdated. Please upgrade to the latest versions with ``pip install -U pip setuptools`` (or on Windows ``python -m pip install -U pip setuptools``). -Importing cryptography causes a ``RuntimeError`` about OpenSSL 1.0.2 --------------------------------------------------------------------- - -The OpenSSL project has dropped support for the 1.0.2 release series. Since it -is no longer receiving security patches from upstream, ``cryptography`` is also -dropping support for it. 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. - -For the 3.2 release, you can set the ``CRYPTOGRAPHY_ALLOW_OPENSSL_102`` -environment variable. Please note that this is *temporary* and will be removed -in ``cryptography`` 3.3. - -Installing cryptography with OpenSSL 0.9.8, 1.0.0, 1.0.1 fails --------------------------------------------------------------- - -The OpenSSL project has dropped support for the 0.9.8, 1.0.0, and 1.0.1 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.0.2 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 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. Why are there no wheels for Python 3.6+ on Linux or macOS? ---------------------------------------------------------- diff --git a/docs/hazmat/backends/openssl.rst b/docs/hazmat/backends/openssl.rst index 0e695279dbe4..dd85d869a635 100644 --- a/docs/hazmat/backends/openssl.rst +++ b/docs/hazmat/backends/openssl.rst @@ -3,7 +3,7 @@ OpenSSL backend =============== -The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.0.2 and +The `OpenSSL`_ C library. Cryptography supports OpenSSL version 1.1.0 and greater. .. data:: cryptography.hazmat.backends.openssl.backend diff --git a/docs/installation.rst b/docs/installation.rst index c773fdce5d69..abfbb9ba58dd 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -27,14 +27,9 @@ PyPy 7.3.1, and PyPy3 7.3.1 on these operating systems. We test compiling with ``clang`` as well as ``gcc`` and use the following OpenSSL releases: -* ``OpenSSL 1.0.2-latest`` * ``OpenSSL 1.1.0-latest`` * ``OpenSSL 1.1.1-latest`` -.. warning:: - - Cryptography 3.2 has dropped support for OpenSSL 1.0.2, see the - :doc:`FAQ ` for more details Building cryptography on Windows -------------------------------- diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index 35ccd6b9be0a..f8f41847926d 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -22,17 +22,15 @@ def _get_openssl_libraries(platform): return [] # OpenSSL goes by a different library name on different operating systems. if platform == "win32" and compiler_type() == "msvc": - windows_link_legacy_openssl = os.environ.get( - "CRYPTOGRAPHY_WINDOWS_LINK_LEGACY_OPENSSL", None - ) - if windows_link_legacy_openssl is None: - # Link against the 1.1.0 names - # CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - libs = ["libssl", "libcrypto"] - else: - # Link against the 1.0.2 and lower names - libs = ["libeay32", "ssleay32"] - return libs + ["advapi32", "crypt32", "gdi32", "user32", "ws2_32"] + return [ + "libssl", + "libcrypto", + "advapi32", + "crypt32", + "gdi32", + "user32", + "ws2_32", + ] else: # darwin, linux, mingw all use this path # In some circumstances, the order in which these libs are diff --git a/src/_cffi_src/openssl/bio.py b/src/_cffi_src/openssl/bio.py index 8f5a3e6a2b6f..52d57c6228d1 100644 --- a/src/_cffi_src/openssl/bio.py +++ b/src/_cffi_src/openssl/bio.py @@ -41,10 +41,4 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -int BIO_up_ref(BIO *b) { - CRYPTO_add(&b->references, 1, CRYPTO_LOCK_BIO); - return 1; -} -#endif """ diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py index 33ebf4df400f..5d5da1b7ec48 100644 --- a/src/_cffi_src/openssl/callbacks.py +++ b/src/_cffi_src/openssl/callbacks.py @@ -51,7 +51,7 @@ using CPython APIs by Armin Rigo of the PyPy project. */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL #ifdef _WIN32 typedef CRITICAL_SECTION Cryptography_mutex; static __inline void cryptography_mutex_init(Cryptography_mutex *mutex) { diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index f3623b21f146..a5db642e89b3 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -79,13 +79,13 @@ # define OPENSSL_PLATFORM SSLEAY_PLATFORM # define OPENSSL_DIR SSLEAY_DIR #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_LOCKING_CALLBACKS = 1; #else static const long Cryptography_HAS_LOCKING_CALLBACKS = 0; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_OPENSSL_CLEANUP = 0; void (*OPENSSL_cleanup)(void) = NULL; diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index d9d4a9ea0f41..28d659b1194a 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -33,19 +33,9 @@ #include #endif -#define CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER \ - (OPENSSL_VERSION_NUMBER >= 0x100020cf && !CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_102U_OR_GREATER \ - (OPENSSL_VERSION_NUMBER >= 0x1000215fL && !CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_110_OR_GREATER \ - (OPENSSL_VERSION_NUMBER >= 0x10100000 && !CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER \ (OPENSSL_VERSION_NUMBER >= 0x1010006f && !CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I \ - (OPENSSL_VERSION_NUMBER < 0x1000209f || CRYPTOGRAPHY_IS_LIBRESSL) -#define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 \ - (OPENSSL_VERSION_NUMBER < 0x10100000 || CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \ (OPENSSL_VERSION_NUMBER < 0x101000af || CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 \ @@ -63,13 +53,8 @@ """ TYPES = """ -static const int CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER; -static const int CRYPTOGRAPHY_OPENSSL_102U_OR_GREATER; -static const int CRYPTOGRAPHY_OPENSSL_110_OR_GREATER; static const int CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER; -static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I; -static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_110; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111; static const int CRYPTOGRAPHY_OPENSSL_LESS_THAN_111B; static const int CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE; diff --git a/src/_cffi_src/openssl/dh.py b/src/_cffi_src/openssl/dh.py index 0e1df23a6ac9..947a5a8ee02e 100644 --- a/src/_cffi_src/openssl/dh.py +++ b/src/_cffi_src/openssl/dh.py @@ -38,79 +38,7 @@ """ CUSTOMIZATIONS = """ -/* These functions were added in OpenSSL 1.1.0 */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -void DH_get0_pqg(const DH *dh, - const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -{ - if (p != NULL) - *p = dh->p; - if (q != NULL) - *q = dh->q; - if (g != NULL) - *g = dh->g; -} - -int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) -{ - /* If the fields p and g in d are NULL, the corresponding input - * parameters MUST be non-NULL. q may remain NULL. - */ - if ((dh->p == NULL && p == NULL) - || (dh->g == NULL && g == NULL)) - return 0; - - if (p != NULL) { - BN_free(dh->p); - dh->p = p; - } - if (q != NULL) { - BN_free(dh->q); - dh->q = q; - } - if (g != NULL) { - BN_free(dh->g); - dh->g = g; - } - - if (q != NULL) { - dh->length = BN_num_bits(q); - } - - return 1; -} - -void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) -{ - if (pub_key != NULL) - *pub_key = dh->pub_key; - if (priv_key != NULL) - *priv_key = dh->priv_key; -} - -int DH_set0_key(DH *dh, BIGNUM *pub_key, BIGNUM *priv_key) -{ - /* If the field pub_key in dh is NULL, the corresponding input - * parameters MUST be non-NULL. The priv_key field may - * be left NULL. - */ - if (dh->pub_key == NULL && pub_key == NULL) - return 0; - - if (pub_key != NULL) { - BN_free(dh->pub_key); - dh->pub_key = pub_key; - } - if (priv_key != NULL) { - BN_free(dh->priv_key); - dh->priv_key = priv_key; - } - - return 1; -} -#endif - -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL #ifndef DH_CHECK_Q_NOT_PRIME #define DH_CHECK_Q_NOT_PRIME 0x10 #endif diff --git a/src/_cffi_src/openssl/dsa.py b/src/_cffi_src/openssl/dsa.py index 938c18fcf1b1..3a290067bc5b 100644 --- a/src/_cffi_src/openssl/dsa.py +++ b/src/_cffi_src/openssl/dsa.py @@ -34,70 +34,4 @@ """ CUSTOMIZATIONS = """ -/* These functions were added in OpenSSL 1.1.0 */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -void DSA_get0_pqg(const DSA *d, - const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -{ - if (p != NULL) - *p = d->p; - if (q != NULL) - *q = d->q; - if (g != NULL) - *g = d->g; -} -int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) -{ - /* If the fields p, q and g in d are NULL, the corresponding input - * parameters MUST be non-NULL. - */ - if ((d->p == NULL && p == NULL) - || (d->q == NULL && q == NULL) - || (d->g == NULL && g == NULL)) - return 0; - - if (p != NULL) { - BN_free(d->p); - d->p = p; - } - if (q != NULL) { - BN_free(d->q); - d->q = q; - } - if (g != NULL) { - BN_free(d->g); - d->g = g; - } - - return 1; -} -void DSA_get0_key(const DSA *d, - const BIGNUM **pub_key, const BIGNUM **priv_key) -{ - if (pub_key != NULL) - *pub_key = d->pub_key; - if (priv_key != NULL) - *priv_key = d->priv_key; -} -int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) -{ - /* If the field pub_key in d is NULL, the corresponding input - * parameters MUST be non-NULL. The priv_key field may - * be left NULL. - */ - if (d->pub_key == NULL && pub_key == NULL) - return 0; - - if (pub_key != NULL) { - BN_free(d->pub_key); - d->pub_key = pub_key; - } - if (priv_key != NULL) { - BN_free(d->priv_key); - d->priv_key = priv_key; - } - - return 1; -} -#endif """ diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index d7ac93e603fc..bc8ad80ec7ea 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -176,20 +176,20 @@ } EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void) { -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL return EVP_MD_CTX_create(); #else return EVP_MD_CTX_new(); #endif } void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *ctx) { -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL EVP_MD_CTX_destroy(ctx); #else EVP_MD_CTX_free(ctx); #endif } -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || defined(OPENSSL_NO_SCRYPT) +#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, uint64_t, uint64_t, uint64_t, uint64_t, unsigned char *, @@ -198,7 +198,7 @@ static const long Cryptography_HAS_SCRYPT = 1; #endif -#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER +#if !CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint = 1; #else static const long Cryptography_HAS_EVP_PKEY_get_set_tls_encodedpoint = 0; diff --git a/src/_cffi_src/openssl/hmac.py b/src/_cffi_src/openssl/hmac.py index 2bc70068ed6b..2e0e33ffe3b0 100644 --- a/src/_cffi_src/openssl/hmac.py +++ b/src/_cffi_src/openssl/hmac.py @@ -18,31 +18,9 @@ int HMAC_Final(HMAC_CTX *, unsigned char *, unsigned int *); int HMAC_CTX_copy(HMAC_CTX *, HMAC_CTX *); -HMAC_CTX *Cryptography_HMAC_CTX_new(void); -void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx); +HMAC_CTX *HMAC_CTX_new(void); +void HMAC_CTX_free(HMAC_CTX *ctx); """ CUSTOMIZATIONS = """ -HMAC_CTX *Cryptography_HMAC_CTX_new(void) { -#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - return HMAC_CTX_new(); -#else - /* This uses OPENSSL_zalloc in 1.1.0, which is malloc + memset */ - HMAC_CTX *ctx = (HMAC_CTX *)OPENSSL_malloc(sizeof(HMAC_CTX)); - memset(ctx, 0, sizeof(HMAC_CTX)); - return ctx; -#endif -} - - -void Cryptography_HMAC_CTX_free(HMAC_CTX *ctx) { -#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - HMAC_CTX_free(ctx); -#else - if (ctx != NULL) { - HMAC_CTX_cleanup(ctx); - OPENSSL_free(ctx); - } -#endif -} """ diff --git a/src/_cffi_src/openssl/nid.py b/src/_cffi_src/openssl/nid.py index aecdc9c0f4ed..9ef88cdbbd41 100644 --- a/src/_cffi_src/openssl/nid.py +++ b/src/_cffi_src/openssl/nid.py @@ -9,8 +9,6 @@ """ TYPES = """ -static const int Cryptography_HAS_X25519; -static const int Cryptography_HAS_X448; static const int Cryptography_HAS_ED448; static const int Cryptography_HAS_ED25519; static const int Cryptography_HAS_POLY1305; @@ -33,24 +31,12 @@ """ CUSTOMIZATIONS = """ -#ifndef NID_X25519 -static const long Cryptography_HAS_X25519 = 0; -static const int NID_X25519 = 0; -#else -static const long Cryptography_HAS_X25519 = 1; -#endif #ifndef NID_ED25519 static const long Cryptography_HAS_ED25519 = 0; static const int NID_ED25519 = 0; #else static const long Cryptography_HAS_ED25519 = 1; #endif -#ifndef NID_X448 -static const long Cryptography_HAS_X448 = 0; -static const int NID_X448 = 0; -#else -static const long Cryptography_HAS_X448 = 1; -#endif #ifndef NID_ED448 static const long Cryptography_HAS_ED448 = 0; static const int NID_ED448 = 0; diff --git a/src/_cffi_src/openssl/ocsp.py b/src/_cffi_src/openssl/ocsp.py index f1a8bf617941..c3d034c2c48d 100644 --- a/src/_cffi_src/openssl/ocsp.py +++ b/src/_cffi_src/openssl/ocsp.py @@ -78,7 +78,7 @@ CUSTOMIZATIONS = """ #if ( \ - CRYPTOGRAPHY_OPENSSL_110_OR_GREATER && \ + !CRYPTOGRAPHY_IS_LIBRESSL && \ CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J \ ) /* These structs come from ocsp_lcl.h and are needed to de-opaque the struct @@ -105,7 +105,7 @@ }; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL /* These functions are all taken from ocsp_cl.c in OpenSSL 1.1.0 */ const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *single) { @@ -147,7 +147,7 @@ #if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110J const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs) { -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL return bs->signatureAlgorithm; #else return &bs->signatureAlgorithm; @@ -156,7 +156,7 @@ const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs) { -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL return bs->tbsResponseData; #else return &bs->tbsResponseData; diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py index 765498fbc9ef..d83dda283841 100644 --- a/src/_cffi_src/openssl/rsa.py +++ b/src/_cffi_src/openssl/rsa.py @@ -65,111 +65,4 @@ int (*EVP_PKEY_CTX_set0_rsa_oaep_label)(EVP_PKEY_CTX *, unsigned char *, int) = NULL; #endif - -/* These functions were added in OpenSSL 1.1.0 */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) -{ - /* If the fields n and e in r are NULL, the corresponding input - * parameters MUST be non-NULL for n and e. d may be - * left NULL (in case only the public key is used). - */ - if ((r->n == NULL && n == NULL) - || (r->e == NULL && e == NULL)) - return 0; - - if (n != NULL) { - BN_free(r->n); - r->n = n; - } - if (e != NULL) { - BN_free(r->e); - r->e = e; - } - if (d != NULL) { - BN_free(r->d); - r->d = d; - } - - return 1; -} - -int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) -{ - /* If the fields p and q in r are NULL, the corresponding input - * parameters MUST be non-NULL. - */ - if ((r->p == NULL && p == NULL) - || (r->q == NULL && q == NULL)) - return 0; - - if (p != NULL) { - BN_free(r->p); - r->p = p; - } - if (q != NULL) { - BN_free(r->q); - r->q = q; - } - - return 1; -} - -int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) -{ - /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input - * parameters MUST be non-NULL. - */ - if ((r->dmp1 == NULL && dmp1 == NULL) - || (r->dmq1 == NULL && dmq1 == NULL) - || (r->iqmp == NULL && iqmp == NULL)) - return 0; - - if (dmp1 != NULL) { - BN_free(r->dmp1); - r->dmp1 = dmp1; - } - if (dmq1 != NULL) { - BN_free(r->dmq1); - r->dmq1 = dmq1; - } - if (iqmp != NULL) { - BN_free(r->iqmp); - r->iqmp = iqmp; - } - - return 1; -} - -void RSA_get0_key(const RSA *r, - const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) -{ - if (n != NULL) - *n = r->n; - if (e != NULL) - *e = r->e; - if (d != NULL) - *d = r->d; -} - -void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) -{ - if (p != NULL) - *p = r->p; - if (q != NULL) - *q = r->q; -} - -void RSA_get0_crt_params(const RSA *r, - const BIGNUM **dmp1, const BIGNUM **dmq1, - const BIGNUM **iqmp) -{ - if (dmp1 != NULL) - *dmp1 = r->dmp1; - if (dmq1 != NULL) - *dmq1 = r->dmq1; - if (iqmp != NULL) - *iqmp = r->iqmp; -} -#endif """ diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index c38e309a1835..93b8eac8a25b 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -26,7 +26,6 @@ static const long Cryptography_HAS_DTLS; static const long Cryptography_HAS_SIGALGS; static const long Cryptography_HAS_PSK; -static const long Cryptography_HAS_CIPHER_DETAILS; static const long Cryptography_HAS_VERIFIED_CHAIN; static const long Cryptography_HAS_KEYLOG; @@ -501,7 +500,7 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_VERIFIED_CHAIN = 0; Cryptography_STACK_OF_X509 *(*SSL_get0_verified_chain)(const SSL *) = NULL; #else @@ -521,58 +520,6 @@ static const long Cryptography_HAS_KEYLOG = 1; #endif -/* Added in 1.1.0 in the great opaquing, but we need to define it for older - OpenSSLs. Such is our burden. */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -/* from ssl/ssl_lib.c */ -size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen) -{ - if (outlen == 0) - return sizeof(ssl->s3->client_random); - if (outlen > sizeof(ssl->s3->client_random)) - outlen = sizeof(ssl->s3->client_random); - memcpy(out, ssl->s3->client_random, outlen); - return outlen; -} -/* Added in 1.1.0 as well */ -/* from ssl/ssl_lib.c */ -size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen) -{ - if (outlen == 0) - return sizeof(ssl->s3->server_random); - if (outlen > sizeof(ssl->s3->server_random)) - outlen = sizeof(ssl->s3->server_random); - memcpy(out, ssl->s3->server_random, outlen); - return outlen; -} -/* Added in 1.1.0 as well */ -/* from ssl/ssl_lib.c */ -size_t SSL_SESSION_get_master_key(const SSL_SESSION *session, - unsigned char *out, size_t outlen) -{ - if (session->master_key_length < 0) { - /* Should never happen */ - return 0; - } - if (outlen == 0) - return session->master_key_length; - if (outlen > (size_t)session->master_key_length) - outlen = session->master_key_length; - memcpy(out, session->master_key, outlen); - return outlen; -} -/* from ssl/ssl_sess.c */ -int SSL_SESSION_has_ticket(const SSL_SESSION *s) -{ - return (s->tlsext_ticklen > 0) ? 1 : 0; -} -/* from ssl/ssl_sess.c */ -unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s) -{ - return s->tlsext_tick_lifetime_hint; -} -#endif - static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1; /* Cryptography now compiles out all SSLv2 bindings. This exists to allow @@ -616,7 +563,7 @@ /* in OpenSSL 1.1.0 the SSL_ST values were renamed to TLS_ST and several were removed */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_SSL_ST = 1; #else static const long Cryptography_HAS_SSL_ST = 0; @@ -625,7 +572,7 @@ static const long SSL_ST_INIT = 0; static const long SSL_ST_RENEGOTIATE = 0; #endif -#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER +#if !CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_TLS_ST = 1; #else static const long Cryptography_HAS_TLS_ST = 0; @@ -729,17 +676,6 @@ SRTP_PROTECTION_PROFILE * (*SSL_get_selected_srtp_profile)(SSL *) = NULL; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -int (*SSL_CIPHER_is_aead)(const SSL_CIPHER *) = NULL; -int (*SSL_CIPHER_get_cipher_nid)(const SSL_CIPHER *) = NULL; -int (*SSL_CIPHER_get_digest_nid)(const SSL_CIPHER *) = NULL; -int (*SSL_CIPHER_get_kx_nid)(const SSL_CIPHER *) = NULL; -int (*SSL_CIPHER_get_auth_nid)(const SSL_CIPHER *) = NULL; -static const long Cryptography_HAS_CIPHER_DETAILS = 0; -#else -static const long Cryptography_HAS_CIPHER_DETAILS = 1; -#endif - #if CRYPTOGRAPHY_OPENSSL_LESS_THAN_111 static const long Cryptography_HAS_TLSv1_3 = 0; static const long SSL_OP_NO_TLSv1_3 = 0; diff --git a/src/_cffi_src/openssl/x509.py b/src/_cffi_src/openssl/x509.py index b88daa1f213d..24946ea48d07 100644 --- a/src/_cffi_src/openssl/x509.py +++ b/src/_cffi_src/openssl/x509.py @@ -288,7 +288,7 @@ } /* Added in 1.1.0 but we need it in all versions now due to the great opaquing. */ -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#if CRYPTOGRAPHY_IS_LIBRESSL int i2d_re_X509_REQ_tbs(X509_REQ *req, unsigned char **pp) { req->req_info->enc.modified = 1; @@ -298,47 +298,5 @@ crl->crl->enc.modified = 1; return i2d_X509_CRL_INFO(crl->crl, pp); } - -#if !CRYPTOGRAPHY_IS_LIBRESSL -int X509_up_ref(X509 *x) { - return CRYPTO_add(&x->references, 1, CRYPTO_LOCK_X509); -} - -const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x) -{ - return x->cert_info->signature; -} - -/* from x509/x509_req.c */ -void X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg) -{ - if (psig != NULL) - *psig = req->signature; - if (palg != NULL) - *palg = req->sig_alg; -} -void X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg) -{ - if (psig != NULL) - *psig = crl->signature; - if (palg != NULL) - *palg = crl->sig_alg; -} -const ASN1_TIME *X509_REVOKED_get0_revocationDate(const X509_REVOKED *x) -{ - return x->revocationDate; -} -const ASN1_INTEGER *X509_REVOKED_get0_serialNumber(const X509_REVOKED *x) -{ - return x->serialNumber; -} - -#define X509_set1_notBefore X509_set_notBefore -#define X509_set1_notAfter X509_set_notAfter -#define X509_getm_notAfter X509_get_notAfter -#define X509_getm_notBefore X509_get_notBefore -#endif #endif """ diff --git a/src/_cffi_src/openssl/x509_vfy.py b/src/_cffi_src/openssl/x509_vfy.py index d2bc5f4ec6e1..ba3d3dbb1421 100644 --- a/src/_cffi_src/openssl/x509_vfy.py +++ b/src/_cffi_src/openssl/x509_vfy.py @@ -234,7 +234,7 @@ static const long X509_V_FLAG_SUITEB_128_LOS = 0; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 || CRYPTOGRAPHY_IS_LIBRESSL +#if CRYPTOGRAPHY_IS_LIBRESSL 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; @@ -243,29 +243,7 @@ static const long Cryptography_HAS_110_VERIFICATION_PARAMS = 1; #endif -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 && !CRYPTOGRAPHY_IS_LIBRESSL -Cryptography_STACK_OF_X509_OBJECT *X509_STORE_get0_objects(X509_STORE *ctx) { - return ctx->objs; -} -X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *store) { - return store->param; -} -int X509_OBJECT_get_type(const X509_OBJECT *x) { - return x->type; -} - -/* from x509/x509_vfy.c */ -X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) -{ - return ctx->cert; -} - -X509 *X509_OBJECT_get0_X509(X509_OBJECT *x) { - return x->data.x509; -} -#endif - -#if CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 +#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; diff --git a/src/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py index f88c8b063b33..c618899953c9 100644 --- a/src/_cffi_src/openssl/x509name.py +++ b/src/_cffi_src/openssl/x509name.py @@ -75,7 +75,7 @@ """ CUSTOMIZATIONS = """ -#if CRYPTOGRAPHY_OPENSSL_110_OR_GREATER +#if !CRYPTOGRAPHY_IS_LIBRESSL int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) { return X509_NAME_ENTRY_set(ne); } diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index b7757e333d9e..5f5c5795bd33 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1660,14 +1660,6 @@ def _ec_key_new_by_curve(self, curve): def _ec_key_new_by_curve_nid(self, curve_nid): ec_cdata = self._lib.EC_KEY_new_by_curve_name(curve_nid) self.openssl_assert(ec_cdata != self._ffi.NULL) - # Setting the ASN.1 flag to OPENSSL_EC_NAMED_CURVE is - # only necessary on OpenSSL 1.0.2t/u. Once we drop support for 1.0.2 - # we can remove this as it's done automatically when getting an EC_KEY - # from new_by_curve_name - # CRYPTOGRAPHY_OPENSSL_102U_OR_GREATER - self._lib.EC_KEY_set_asn1_flag( - ec_cdata, backend._lib.OPENSSL_EC_NAMED_CURVE - ) return self._ffi.gc(ec_cdata, self._lib.EC_KEY_free) def load_der_ocsp_request(self, data): @@ -2334,7 +2326,7 @@ def x25519_generate_key(self): def x25519_supported(self): if self._fips_enabled: return False - return self._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER + return not self._lib.CRYPTOGRAPHY_IS_LIBRESSL def x448_load_public_bytes(self, data): if len(data) != 56: diff --git a/src/cryptography/hazmat/backends/openssl/ec.py b/src/cryptography/hazmat/backends/openssl/ec.py index bf61bcf16b20..05d32baba662 100644 --- a/src/cryptography/hazmat/backends/openssl/ec.py +++ b/src/cryptography/hazmat/backends/openssl/ec.py @@ -40,18 +40,18 @@ def _ec_key_curve_sn(backend, ec_key): # an error for now. if nid == backend._lib.NID_undef: raise NotImplementedError( - "ECDSA keys with unnamed curves are unsupported " "at this time" + "ECDSA keys with unnamed curves are unsupported at this time" ) # This is like the above check, but it also catches the case where you # explicitly encoded a curve with the same parameters as a named curve. # Don't do that. if ( - backend._lib.CRYPTOGRAPHY_OPENSSL_102U_OR_GREATER + not backend._lib.CRYPTOGRAPHY_IS_LIBRESSL and backend._lib.EC_GROUP_get_asn1_flag(group) == 0 ): raise NotImplementedError( - "ECDSA keys with unnamed curves are unsupported " "at this time" + "ECDSA keys with unnamed curves are unsupported at this time" ) curve_name = backend._lib.OBJ_nid2sn(nid) diff --git a/src/cryptography/hazmat/backends/openssl/hmac.py b/src/cryptography/hazmat/backends/openssl/hmac.py index 5024223b219b..1cc9d99fec7b 100644 --- a/src/cryptography/hazmat/backends/openssl/hmac.py +++ b/src/cryptography/hazmat/backends/openssl/hmac.py @@ -21,11 +21,9 @@ def __init__(self, backend, key, algorithm, ctx=None): self._backend = backend if ctx is None: - ctx = self._backend._lib.Cryptography_HMAC_CTX_new() + ctx = self._backend._lib.HMAC_CTX_new() self._backend.openssl_assert(ctx != self._backend._ffi.NULL) - ctx = self._backend._ffi.gc( - ctx, self._backend._lib.Cryptography_HMAC_CTX_free - ) + ctx = self._backend._ffi.gc(ctx, self._backend._lib.HMAC_CTX_free) evp_md = self._backend._evp_md_from_algorithm(algorithm) if evp_md == self._backend._ffi.NULL: raise UnsupportedAlgorithm( @@ -46,10 +44,10 @@ def __init__(self, backend, key, algorithm, ctx=None): algorithm = utils.read_only_property("_algorithm") def copy(self): - copied_ctx = self._backend._lib.Cryptography_HMAC_CTX_new() + copied_ctx = self._backend._lib.HMAC_CTX_new() self._backend.openssl_assert(copied_ctx != self._backend._ffi.NULL) copied_ctx = self._backend._ffi.gc( - copied_ctx, self._backend._lib.Cryptography_HMAC_CTX_free + copied_ctx, self._backend._lib.HMAC_CTX_free ) res = self._backend._lib.HMAC_CTX_copy(copied_ctx, self._ctx) self._backend.openssl_assert(res != 0) diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index cdc18eab6848..aeca166b2310 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -126,20 +126,6 @@ def cryptography_has_x509_store_ctx_get_issuer(): ] -def cryptography_has_x25519(): - return [ - "EVP_PKEY_X25519", - "NID_X25519", - ] - - -def cryptography_has_x448(): - return [ - "EVP_PKEY_X448", - "NID_X448", - ] - - def cryptography_has_ed448(): return [ "EVP_PKEY_ED448", @@ -217,16 +203,6 @@ def cryptography_has_openssl_cleanup(): ] -def cryptography_has_cipher_details(): - return [ - "SSL_CIPHER_is_aead", - "SSL_CIPHER_get_cipher_nid", - "SSL_CIPHER_get_digest_nid", - "SSL_CIPHER_get_kx_nid", - "SSL_CIPHER_get_auth_nid", - ] - - def cryptography_has_tlsv13(): return [ "SSL_OP_NO_TLSv1_3", @@ -316,8 +292,6 @@ def cryptography_has_srtp(): "Cryptography_HAS_X509_STORE_CTX_GET_ISSUER": ( cryptography_has_x509_store_ctx_get_issuer ), - "Cryptography_HAS_X25519": cryptography_has_x25519, - "Cryptography_HAS_X448": cryptography_has_x448, "Cryptography_HAS_ED448": cryptography_has_ed448, "Cryptography_HAS_ED25519": cryptography_has_ed25519, "Cryptography_HAS_POLY1305": cryptography_has_poly1305, @@ -332,7 +306,6 @@ def cryptography_has_srtp(): "Cryptography_HAS_PSK": cryptography_has_psk, "Cryptography_HAS_CUSTOM_EXT": cryptography_has_custom_ext, "Cryptography_HAS_OPENSSL_CLEANUP": cryptography_has_openssl_cleanup, - "Cryptography_HAS_CIPHER_DETAILS": cryptography_has_cipher_details, "Cryptography_HAS_TLSv1_3": cryptography_has_tlsv13, "Cryptography_HAS_KEYLOG": cryptography_has_keylog, "Cryptography_HAS_RAW_KEY": cryptography_has_raw_key, diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index f6bf93729118..5fd3b0de9656 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -5,10 +5,8 @@ from __future__ import absolute_import, division, print_function import collections -import os import threading import types -import warnings import cryptography from cryptography import utils @@ -166,29 +164,6 @@ def init_static_locks(cls): _openssl_assert(cls.lib, res == 1) -def _verify_openssl_version(lib): - if ( - lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 - and not lib.CRYPTOGRAPHY_IS_LIBRESSL - ): - if os.environ.get("CRYPTOGRAPHY_ALLOW_OPENSSL_102"): - warnings.warn( - "OpenSSL version 1.0.2 is no longer supported by the OpenSSL " - "project, please upgrade. The next version of cryptography " - "will completely remove support for it.", - utils.CryptographyDeprecationWarning, - ) - else: - raise RuntimeError( - "You are linking against OpenSSL 1.0.2, which is no longer " - "supported by the OpenSSL project. To use this version of " - "cryptography you need to upgrade to a newer version of " - "OpenSSL. For this version only you can also set the " - "environment variable CRYPTOGRAPHY_ALLOW_OPENSSL_102 to " - "allow OpenSSL 1.0.2." - ) - - 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. @@ -218,5 +193,3 @@ def _verify_package_version(version): # condition registering the OpenSSL locks. On Python 3.4+ the import lock # is per module so this approach will not work. Binding.init_static_locks() - -_verify_openssl_version(Binding.lib) diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index 2f7e7bebfd0c..e4bf7f97c6f5 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -590,7 +590,7 @@ def test_numeric_string_x509_name_entry(self): x509.load_der_x509_certificate, backend, ) - if backend._lib.CRYPTOGRAPHY_OPENSSL_LESS_THAN_102I: + if backend._lib.CRYPTOGRAPHY_IS_LIBRESSL: with pytest.raises(ValueError) as exc: cert.subject diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index ecee34091dc7..069452cbb091 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -4,8 +4,6 @@ from __future__ import absolute_import, division, print_function -import pretend - import pytest from cryptography.exceptions import InternalError @@ -13,7 +11,6 @@ Binding, _consume_errors, _openssl_assert, - _verify_openssl_version, _verify_package_version, ) @@ -30,7 +27,7 @@ def test_crypto_lock_init(self): b.init_static_locks() lock_cb = b.lib.CRYPTO_get_locking_callback() - if b.lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER: + if not b.lib.CRYPTOGRAPHY_IS_LIBRESSL: assert lock_cb == b.ffi.NULL assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 0 else: @@ -88,7 +85,7 @@ def test_ssl_mode(self): def test_conditional_removal(self): b = Binding() - if b.lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER: + if not b.lib.CRYPTOGRAPHY_IS_LIBRESSL: assert b.lib.TLS_ST_OK else: with pytest.raises(AttributeError): @@ -128,12 +125,3 @@ def test_check_startup_errors_are_allowed(self): def test_version_mismatch(self): with pytest.raises(ImportError): _verify_package_version("nottherightversion") - - def test_verify_openssl_version(self, monkeypatch): - monkeypatch.delenv("CRYPTOGRAPHY_ALLOW_OPENSSL_102", raising=False) - lib = pretend.stub( - CRYPTOGRAPHY_OPENSSL_LESS_THAN_110=True, - CRYPTOGRAPHY_IS_LIBRESSL=False, - ) - with pytest.raises(RuntimeError): - _verify_openssl_version(lib) diff --git a/tests/wycheproof/test_rsa.py b/tests/wycheproof/test_rsa.py index 1262b58853d3..926bb44e999f 100644 --- a/tests/wycheproof/test_rsa.py +++ b/tests/wycheproof/test_rsa.py @@ -35,12 +35,7 @@ def should_verify(backend, wycheproof): return True if wycheproof.acceptable: - if ( - backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - or backend._lib.CRYPTOGRAPHY_IS_LIBRESSL - ) and wycheproof.has_flag("MissingNull"): - return False - return True + return not wycheproof.has_flag("MissingNull") return False @@ -165,16 +160,6 @@ def test_rsa_pss_signature(backend, wycheproof): @pytest.mark.requires_backend_interface(interface=RSABackend) -@pytest.mark.supported( - only_if=lambda backend: ( - backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - or backend._lib.CRYPTOGRAPHY_IS_LIBRESSL - ), - skip_message=( - "A handful of these tests fail on OpenSSL 1.0.2 and since upstream " - "isn't maintaining it, they'll never be fixed." - ), -) @pytest.mark.wycheproof_tests( "rsa_oaep_2048_sha1_mgf1sha1_test.json", "rsa_oaep_2048_sha224_mgf1sha1_test.json", diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 11c80816cff7..f4d93389ac02 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1820,10 +1820,6 @@ def read_next_rdn_value_tag(reader): if ( # This only works correctly in OpenSSL 1.1.0f+ and 1.0.2l+ backend._lib.CRYPTOGRAPHY_OPENSSL_110F_OR_GREATER - or ( - backend._lib.CRYPTOGRAPHY_OPENSSL_102L_OR_GREATER - and not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - ) ): assert read_next_rdn_value_tag(subject) == PRINTABLE_STRING assert read_next_rdn_value_tag(issuer) == PRINTABLE_STRING diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 2cd216fb688a..429169a45ebc 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -5679,10 +5679,8 @@ def test_simple(self, backend): ) @pytest.mark.supported( - only_if=lambda backend: ( - not backend._lib.CRYPTOGRAPHY_OPENSSL_110_OR_GREATER - ), - skip_message="Requires OpenSSL < 1.1.0", + only_if=lambda backend: backend._lib.CRYPTOGRAPHY_IS_LIBRESSL, + skip_message="Requires LibreSSL", ) def test_skips_scts_if_unsupported(self, backend): cert = _load_cert( diff --git a/tox.ini b/tox.ini index e94d3c1e0753..bc5de1ad9953 100644 --- a/tox.ini +++ b/tox.ini @@ -13,8 +13,6 @@ deps = ./vectors randomorder: pytest-randomly passenv = ARCHFLAGS LDFLAGS CFLAGS INCLUDE LIB LD_LIBRARY_PATH USERNAME PYTHONIOENCODING OPENSSL_FORCE_FIPS_MODE -setenv = - CRYPTOGRAPHY_ALLOW_OPENSSL_102=1 commands = pip list # We use parallel mode and then combine here so that coverage.py will take From 5a7dfb705f086f373093021add6a3540196abb10 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 26 Oct 2020 06:33:58 -0700 Subject: [PATCH 03/61] Revert to upload-artifact v1 for manylinux (#5514) --- .github/workflows/wheel-builder.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 74012f09b53a..0534513ac3a8 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -47,7 +47,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@v2.2.0 + - uses: actions/upload-artifact@v1 with: name: "cryptography-${{ github.event.inputs.version }}-${{ matrix.MANYLINUX.NAME }}-${{ matrix.PYTHON }}" path: cryptography-wheelhouse/ From b187b80421d535ef53362ec9f42a2aa5422c0add Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 26 Oct 2020 10:55:31 -0400 Subject: [PATCH 04/61] Simplify a number of branches around libressl (#5515) --- src/_cffi_src/openssl/evp.py | 21 +++++++------------ src/_cffi_src/openssl/x509name.py | 11 +--------- .../hazmat/backends/openssl/decode_asn1.py | 2 +- .../hazmat/backends/openssl/ed25519.py | 8 +++---- .../hazmat/backends/openssl/ed448.py | 8 +++---- .../hazmat/backends/openssl/hashes.py | 8 +++---- .../hazmat/backends/openssl/poly1305.py | 4 ++-- 7 files changed, 23 insertions(+), 39 deletions(-) diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index bc8ad80ec7ea..5b6e35cf9dd6 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -120,11 +120,12 @@ int EVP_PKEY_id(const EVP_PKEY *); int Cryptography_EVP_PKEY_id(const EVP_PKEY *); -/* in 1.1.0 _create and _destroy were renamed to _new and _free. The following - two functions wrap both the old and new functions so we can call them - without worrying about what OpenSSL we're running against. */ +EVP_MD_CTX *EVP_MD_CTX_new(void); +void EVP_MD_CTX_free(EVP_MD_CTX *); +/* Backwards compat aliases for pyOpenSSL */ EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void); void Cryptography_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); @@ -174,21 +175,13 @@ int Cryptography_EVP_PKEY_id(const EVP_PKEY *key) { return EVP_PKEY_id(key); } - EVP_MD_CTX *Cryptography_EVP_MD_CTX_new(void) { -#if CRYPTOGRAPHY_IS_LIBRESSL - return EVP_MD_CTX_create(); -#else return EVP_MD_CTX_new(); -#endif } -void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *ctx) { -#if CRYPTOGRAPHY_IS_LIBRESSL - EVP_MD_CTX_destroy(ctx); -#else - EVP_MD_CTX_free(ctx); -#endif +void Cryptography_EVP_MD_CTX_free(EVP_MD_CTX *md) { + EVP_MD_CTX_free(md); } + #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/_cffi_src/openssl/x509name.py b/src/_cffi_src/openssl/x509name.py index c618899953c9..1fbe26aa7432 100644 --- a/src/_cffi_src/openssl/x509name.py +++ b/src/_cffi_src/openssl/x509name.py @@ -35,7 +35,7 @@ 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 *); -int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *); +int X509_NAME_ENTRY_set(X509_NAME_ENTRY *); /* 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); @@ -75,13 +75,4 @@ """ CUSTOMIZATIONS = """ -#if !CRYPTOGRAPHY_IS_LIBRESSL -int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) { - return X509_NAME_ENTRY_set(ne); -} -#else -int Cryptography_X509_NAME_ENTRY_set(X509_NAME_ENTRY *ne) { - return ne->set; -} -#endif """ diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py index 279b00ca5c10..cc9b8c0e34d9 100644 --- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py @@ -64,7 +64,7 @@ def _decode_x509_name(backend, x509_name): for x in range(count): entry = backend._lib.X509_NAME_get_entry(x509_name, x) attribute = _decode_x509_name_entry(backend, entry) - set_id = backend._lib.Cryptography_X509_NAME_ENTRY_set(entry) + set_id = backend._lib.X509_NAME_ENTRY_set(entry) if set_id != prev_set_id: attributes.append({attribute}) else: diff --git a/src/cryptography/hazmat/backends/openssl/ed25519.py b/src/cryptography/hazmat/backends/openssl/ed25519.py index 75653373b3cf..13bec3af1094 100644 --- a/src/cryptography/hazmat/backends/openssl/ed25519.py +++ b/src/cryptography/hazmat/backends/openssl/ed25519.py @@ -50,10 +50,10 @@ def _raw_public_bytes(self): return self._backend._ffi.buffer(buf, _ED25519_KEY_SIZE)[:] def verify(self, signature, data): - evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( - evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestVerifyInit( evp_md_ctx, @@ -89,10 +89,10 @@ def public_key(self): return self._backend.ed25519_load_public_bytes(public_bytes) def sign(self, data): - evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( - evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestSignInit( evp_md_ctx, diff --git a/src/cryptography/hazmat/backends/openssl/ed448.py b/src/cryptography/hazmat/backends/openssl/ed448.py index 4a8dab1a8115..6512770e5b76 100644 --- a/src/cryptography/hazmat/backends/openssl/ed448.py +++ b/src/cryptography/hazmat/backends/openssl/ed448.py @@ -51,10 +51,10 @@ def _raw_public_bytes(self): return self._backend._ffi.buffer(buf, _ED448_KEY_SIZE)[:] def verify(self, signature, data): - evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( - evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestVerifyInit( evp_md_ctx, @@ -90,10 +90,10 @@ def public_key(self): return self._backend.ed448_load_public_bytes(public_bytes) def sign(self, data): - evp_md_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + evp_md_ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(evp_md_ctx != self._backend._ffi.NULL) evp_md_ctx = self._backend._ffi.gc( - evp_md_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + evp_md_ctx, self._backend._lib.EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestSignInit( evp_md_ctx, diff --git a/src/cryptography/hazmat/backends/openssl/hashes.py b/src/cryptography/hazmat/backends/openssl/hashes.py index 44033993e166..764dce0ede60 100644 --- a/src/cryptography/hazmat/backends/openssl/hashes.py +++ b/src/cryptography/hazmat/backends/openssl/hashes.py @@ -18,9 +18,9 @@ def __init__(self, backend, algorithm, ctx=None): self._backend = backend if ctx is None: - ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + ctx = self._backend._lib.EVP_MD_CTX_new() ctx = self._backend._ffi.gc( - ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + ctx, self._backend._lib.EVP_MD_CTX_free ) evp_md = self._backend._evp_md_from_algorithm(algorithm) if evp_md == self._backend._ffi.NULL: @@ -40,9 +40,9 @@ def __init__(self, backend, algorithm, ctx=None): algorithm = utils.read_only_property("_algorithm") def copy(self): - copied_ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + copied_ctx = self._backend._lib.EVP_MD_CTX_new() copied_ctx = self._backend._ffi.gc( - copied_ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + copied_ctx, self._backend._lib.EVP_MD_CTX_free ) res = self._backend._lib.EVP_MD_CTX_copy_ex(copied_ctx, self._ctx) self._backend.openssl_assert(res != 0) diff --git a/src/cryptography/hazmat/backends/openssl/poly1305.py b/src/cryptography/hazmat/backends/openssl/poly1305.py index 17493ca60ce8..5699918b1726 100644 --- a/src/cryptography/hazmat/backends/openssl/poly1305.py +++ b/src/cryptography/hazmat/backends/openssl/poly1305.py @@ -30,10 +30,10 @@ def __init__(self, backend, key): self._evp_pkey = self._backend._ffi.gc( evp_pkey, self._backend._lib.EVP_PKEY_free ) - ctx = self._backend._lib.Cryptography_EVP_MD_CTX_new() + ctx = self._backend._lib.EVP_MD_CTX_new() self._backend.openssl_assert(ctx != self._backend._ffi.NULL) self._ctx = self._backend._ffi.gc( - ctx, self._backend._lib.Cryptography_EVP_MD_CTX_free + ctx, self._backend._lib.EVP_MD_CTX_free ) res = self._backend._lib.EVP_DigestSignInit( self._ctx, From 956e0965fdc59641227eb9a9df2763a60959a398 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 26 Oct 2020 17:58:35 -0400 Subject: [PATCH 05/61] fixes #5513 update comment on why we can't have nice things (#5517) --- src/_cffi_src/build_openssl.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/_cffi_src/build_openssl.py b/src/_cffi_src/build_openssl.py index f8f41847926d..4380c3396909 100644 --- a/src/_cffi_src/build_openssl.py +++ b/src/_cffi_src/build_openssl.py @@ -51,10 +51,9 @@ def _extra_compile_args(platform): We set -Wconversion args here so that we only do Wconversion checks on the code we're compiling and not on cffi itself (as passing -Wconversion in CFLAGS would do). We set no error on sign conversion because some - function signatures in OpenSSL have changed from long -> unsigned long - in the past. Since that isn't a precision issue we don't care. - When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 we can - revisit this. + function signatures in LibreSSL differ from OpenSSL have changed on long + vs. unsigned long in the past. Since that isn't a precision issue we don't + care. """ # make sure the compiler used supports the flags to be added is_gcc = False @@ -117,13 +116,6 @@ def _extra_compile_args(platform): "callbacks", ], libraries=_get_openssl_libraries(sys.platform), - # These args are passed here so that we only do Wconversion checks on the - # code we're compiling and not on cffi itself (as passing -Wconversion in - # CFLAGS would do). We set no error on sign convesrion because some - # function signatures in OpenSSL have changed from long -> unsigned long - # in the past. Since that isn't a precision issue we don't care. - # When we drop support for CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 we can - # revisit this. extra_compile_args=_extra_compile_args(sys.platform), extra_link_args=extra_link_args(compiler_type()), ) From b0a3d89e0f69d6e460a4ae65a57ea2c721f9370b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 26 Oct 2020 23:43:33 -0400 Subject: [PATCH 06/61] Remove some dead constants (#5518) --- src/_cffi_src/openssl/rand.py | 3 --- src/_cffi_src/openssl/rsa.py | 3 --- src/_cffi_src/openssl/ssl.py | 17 ----------------- 3 files changed, 23 deletions(-) diff --git a/src/_cffi_src/openssl/rand.py b/src/_cffi_src/openssl/rand.py index c0cd68365960..1bc2ec0bc386 100644 --- a/src/_cffi_src/openssl/rand.py +++ b/src/_cffi_src/openssl/rand.py @@ -10,8 +10,6 @@ TYPES = """ typedef ... RAND_METHOD; - -static const long Cryptography_HAS_EGD; """ FUNCTIONS = """ @@ -27,5 +25,4 @@ """ CUSTOMIZATIONS = """ -static const long Cryptography_HAS_EGD = 0; """ diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py index d83dda283841..9298226bb223 100644 --- a/src/_cffi_src/openssl/rsa.py +++ b/src/_cffi_src/openssl/rsa.py @@ -17,7 +17,6 @@ static const int RSA_PKCS1_PSS_PADDING; static const int RSA_F4; -static const int Cryptography_HAS_PSS_PADDING; static const int Cryptography_HAS_RSA_OAEP_MD; static const int Cryptography_HAS_RSA_OAEP_LABEL; """ @@ -49,8 +48,6 @@ """ CUSTOMIZATIONS = """ -static const long Cryptography_HAS_PSS_PADDING = 1; - #if defined(EVP_PKEY_CTX_set_rsa_oaep_md) static const long Cryptography_HAS_RSA_OAEP_MD = 1; #else diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index 93b8eac8a25b..ff960f5775ad 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -13,15 +13,11 @@ TYPES = """ static const long Cryptography_HAS_SSL_ST; static const long Cryptography_HAS_TLS_ST; -static const long Cryptography_HAS_SSL2; 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_SECURE_RENEGOTIATION; -static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB; -static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP; -static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE; static const long Cryptography_HAS_SSL_CTX_CLEAR_OPTIONS; static const long Cryptography_HAS_DTLS; static const long Cryptography_HAS_SIGALGS; @@ -29,9 +25,6 @@ static const long Cryptography_HAS_VERIFIED_CHAIN; static const long Cryptography_HAS_KEYLOG; -/* Internally invented symbol to tell us if SNI is supported */ -static const long Cryptography_HAS_TLSEXT_HOSTNAME; - /* Internally invented symbol to tell us if SSL_MODE_RELEASE_BUFFERS is * supported */ @@ -522,12 +515,6 @@ static const long Cryptography_HAS_SECURE_RENEGOTIATION = 1; -/* Cryptography now compiles out all SSLv2 bindings. This exists to allow - * clients that use it to check for SSLv2 support to keep functioning as - * expected. - */ -static const long Cryptography_HAS_SSL2 = 0; - #ifdef OPENSSL_NO_SSL3_METHOD static const long Cryptography_HAS_SSL3_METHOD = 0; SSL_METHOD* (*SSLv3_method)(void) = NULL; @@ -537,10 +524,6 @@ static const long Cryptography_HAS_SSL3_METHOD = 1; #endif -static const long Cryptography_HAS_TLSEXT_HOSTNAME = 1; -static const long Cryptography_HAS_TLSEXT_STATUS_REQ_CB = 1; -static const long Cryptography_HAS_STATUS_REQ_OCSP_RESP = 1; -static const long Cryptography_HAS_TLSEXT_STATUS_REQ_TYPE = 1; static const long Cryptography_HAS_RELEASE_BUFFERS = 1; static const long Cryptography_HAS_OP_NO_COMPRESSION = 1; static const long Cryptography_HAS_TLSv1_1 = 1; From 48211dd71707473c816cc043f80207cd20d2ff0f Mon Sep 17 00:00:00 2001 From: lukpueh Date: Tue, 27 Oct 2020 12:42:10 +0100 Subject: [PATCH 07/61] Fix installation docs link in README.rst (#5520) Signed-off-by: Lukas Puehringer --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index fddde9878581..0175c7f555ac 100644 --- a/README.rst +++ b/README.rst @@ -68,7 +68,7 @@ documentation. .. _`documentation`: https://cryptography.io/ -.. _`the installation documentation`: https://cryptography.io/en/latest/installation/ +.. _`the installation documentation`: https://cryptography.io/en/latest/installation.html .. _`issue tracker`: https://github.com/pyca/cryptography/issues .. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev .. _`security reporting`: https://cryptography.io/en/latest/security/ From b16561670320c65a18cce41d0db0c42ab68350a9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 27 Oct 2020 18:51:20 -0400 Subject: [PATCH 08/61] Disable blinding for RSA pub keys (#5524) --- src/cryptography/hazmat/backends/openssl/rsa.py | 5 ----- tests/hazmat/primitives/test_rsa.py | 3 +++ 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index 66b37224e443..de299779d942 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -410,11 +410,6 @@ def sign(self, data, padding, algorithm): @utils.register_interface(RSAPublicKeyWithSerialization) class _RSAPublicKey(object): def __init__(self, backend, rsa_cdata, evp_pkey): - # Blinding is on by default in many versions of OpenSSL, but let's - # just be conservative here. - res = backend._lib.RSA_blinding_on(rsa_cdata, backend._ffi.NULL) - backend.openssl_assert(res == 1) - self._backend = backend self._rsa_cdata = rsa_cdata self._evp_pkey = evp_pkey diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index d7fa7744f493..1a770d3efe50 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -1894,6 +1894,9 @@ def test_rsa_public_numbers_create_key(self, backend): public_key = RSA_KEY_1024.public_numbers.public_key(backend) assert public_key + public_key = rsa.RSAPublicNumbers(n=10, e=3).public_key(backend) + assert public_key + def test_public_numbers_invalid_types(self): with pytest.raises(TypeError): rsa.RSAPublicNumbers(e=None, n=15) From 46d35a835fe9e0c586c6b89db31280dde82280c0 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Tue, 27 Oct 2020 21:28:57 -0700 Subject: [PATCH 09/61] port 3.2.1 changelog (#5526) --- CHANGELOG.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index cf3d3779af7c..3e3a0dd6435b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,15 @@ Changelog .. note:: This version is not yet released and is under active development. +.. _v3-2-1: + +3.2.1 - 2020-10-27 +~~~~~~~~~~~~~~~~~~ + +* Disable blinding on RSA public keys to address an error with some versions + of OpenSSL. + + .. _v3-2: 3.2 - 2020-10-25 From d9e174d3e16c4dc50789f9897334bcc14d0b05d9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 28 Oct 2020 10:38:42 -0400 Subject: [PATCH 10/61] Drop python 3.5 (#5527) --- .github/workflows/ci.yml | 3 +-- .github/workflows/wheel-builder.yml | 5 ++--- .travis.yml | 3 --- .zuul.d/jobs.yaml | 6 +++--- CHANGELOG.rst | 4 +++- README.rst | 2 +- docs/installation.rst | 2 +- setup.py | 4 ++-- src/cryptography/__init__.py | 7 ------- tox.ini | 2 +- 10 files changed, 14 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b55266721e95..fc556f06189a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: matrix: PYTHON: - {VERSION: "2.7", TOXENV: "py27", EXTRA_CFLAGS: ""} - - {VERSION: "3.5", TOXENV: "py35", EXTRA_CFLAGS: ""} + - {VERSION: "3.6", TOXENV: "py36", EXTRA_CFLAGS: ""} - {VERSION: "3.9", TOXENV: "py39", EXTRA_CFLAGS: "-DUSE_OSRANDOM_RNG_FOR_TESTING"} name: "Python ${{ matrix.PYTHON.VERSION }} on macOS" steps: @@ -59,7 +59,6 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - {VERSION: "2.7", TOXENV: "py27", MSVC_VERSION: "2010", CL_FLAGS: ""} - - {VERSION: "3.5", TOXENV: "py35", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.6", TOXENV: "py36", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.7", TOXENV: "py37", MSVC_VERSION: "2019", CL_FLAGS: ""} - {VERSION: "3.8", TOXENV: "py38", MSVC_VERSION: "2019", CL_FLAGS: ""} diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index 0534513ac3a8..df8a752eaa4f 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -11,7 +11,7 @@ jobs: container: ${{ matrix.MANYLINUX.CONTAINER }} strategy: matrix: - PYTHON: ["cp27-cp27m", "cp27-cp27mu", "cp35-cp35m"] + PYTHON: ["cp27-cp27m", "cp27-cp27mu", "cp36-cp36m"] MANYLINUX: - NAME: manylinux1_x86_64 CONTAINER: "pyca/cryptography-manylinux1:x86_64" @@ -62,7 +62,7 @@ jobs: DOWNLOAD_URL: 'https://www.python.org/ftp/python/2.7.17/python-2.7.17-macosx10.9.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/2.7/bin/python' - VERSION: '3.8' - ABI_VERSION: '3.5' + ABI_VERSION: '3.6' DOWNLOAD_URL: 'https://www.python.org/ftp/python/3.8.2/python-3.8.2-macosx10.9.pkg' BIN_PATH: '/Library/Frameworks/Python.framework/Versions/3.8/bin/python3' name: "${{ matrix.PYTHON.VERSION }} ABI ${{ matrix.PYTHON.ABI_VERSION }} macOS" @@ -115,7 +115,6 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - {VERSION: "2.7", MSVC_VERSION: "2010"} - - {VERSION: "3.5", MSVC_VERSION: "2019"} - {VERSION: "3.6", MSVC_VERSION: "2019"} - {VERSION: "3.7", MSVC_VERSION: "2019"} - {VERSION: "3.8", MSVC_VERSION: "2019"} diff --git a/.travis.yml b/.travis.yml index a13a977f16f3..45b8122a2d8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -66,9 +66,6 @@ matrix: - python: 2.7 services: docker env: TOXENV=py27 DOCKER=pyca/cryptography-runner-stretch - - python: 3.5 - services: docker - env: TOXENV=py35 DOCKER=pyca/cryptography-runner-stretch - python: 3.7 services: docker env: TOXENV=py37 DOCKER=pyca/cryptography-runner-buster diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 1430b0c31510..38cab295060f 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -46,7 +46,7 @@ - platform: manylinux2014_aarch64 image: pyca/cryptography-manylinux2014_aarch64 pythons: - - cp35-cp35m + - cp36-cp36m - job: name: pyca-cryptography-build-wheel-x86_64 @@ -59,10 +59,10 @@ pythons: - cp27-cp27m - cp27-cp27mu - - cp35-cp35m + - cp36-cp36m - platform: manylinux2010_x86_64 image: pyca/cryptography-manylinux2010:x86_64 pythons: - cp27-cp27m - cp27-cp27mu - - cp35-cp35m + - cp36-cp36m diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3e3a0dd6435b..b652d2ba733e 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -8,6 +8,9 @@ Changelog .. note:: This version is not yet released and is under active development. +* **BACKWARDS INCOMPATIBLE:** Support for Python 3.5 has been removed due to + low usage and maintenance burden. + .. _v3-2-1: 3.2.1 - 2020-10-27 @@ -16,7 +19,6 @@ Changelog * Disable blinding on RSA public keys to address an error with some versions of OpenSSL. - .. _v3-2: 3.2 - 2020-10-25 diff --git a/README.rst b/README.rst index 0175c7f555ac..062e3c75431c 100644 --- a/README.rst +++ b/README.rst @@ -21,7 +21,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 -standard library". It supports Python 2.7, Python 3.5+, and PyPy 5.4+. +standard library". It supports Python 2.7, Python 3.6+, and PyPy 5.4+. ``cryptography`` includes both high level recipes and low level interfaces to common cryptographic algorithms such as symmetric ciphers, message digests, and diff --git a/docs/installation.rst b/docs/installation.rst index abfbb9ba58dd..eb270e62f371 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -10,7 +10,7 @@ You can install ``cryptography`` with ``pip``: Supported platforms ------------------- -Currently we test ``cryptography`` on Python 2.7, 3.5+, +Currently we test ``cryptography`` on Python 2.7, 3.6+, PyPy 7.3.1, and PyPy3 7.3.1 on these operating systems. * x86-64 CentOS 7.x diff --git a/setup.py b/setup.py index 82800a96e59b..23671748f025 100644 --- a/setup.py +++ b/setup.py @@ -76,10 +76,10 @@ "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Security :: Cryptography", @@ -87,7 +87,7 @@ package_dir={"": "src"}, packages=find_packages(where="src", exclude=["_cffi_src", "_cffi_src.*"]), include_package_data=True, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*", + python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*", install_requires=["six >= 1.4.1"] + setup_requirements, setup_requires=setup_requirements, extras_require={ diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index 7211614d7f4a..f128502e2fd5 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -39,10 +39,3 @@ CryptographyDeprecationWarning, stacklevel=2, ) -if sys.version_info[:2] == (3, 5): - warnings.warn( - "Python 3.5 support will be dropped in the next release of " - "cryptography. Please upgrade your Python.", - CryptographyDeprecationWarning, - stacklevel=2, - ) diff --git a/tox.ini b/tox.ini index bc5de1ad9953..2ecd30a222bb 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 2.4 -envlist = py27,pypy,py35,py36,py37,py38,docs,pep8,packaging +envlist = py27,pypy,py36,py37,py38,py39,docs,pep8,packaging isolated_build = True [testenv] From 95049c5c5f9ebaae537b8421495a9b911ded967e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 28 Oct 2020 11:41:39 -0400 Subject: [PATCH 11/61] fedora has python 3.9 now (#5528) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 45b8122a2d8e..25dccb21c9cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -90,9 +90,9 @@ matrix: - python: 3.8 services: docker env: TOXENV=py38-randomorder DOCKER=pyca/cryptography-runner-ubuntu-rolling - - python: 3.8 + - python: 3.9 services: docker - env: TOXENV=py38 DOCKER=pyca/cryptography-runner-fedora + env: TOXENV=py39 DOCKER=pyca/cryptography-runner-fedora - python: 3.8 services: docker env: TOXENV=py38 DOCKER=pyca/cryptography-runner-alpine:latest From 6c43bbce9a77d96925c9e045ab37c9de56af7acd Mon Sep 17 00:00:00 2001 From: Thomas Grainger Date: Wed, 28 Oct 2020 18:02:17 +0000 Subject: [PATCH 12/61] fix Python 2 CryptographyDeprecationWarning guide (#5529) --- docs/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.rst b/docs/faq.rst index 563a241e4f1b..842dd75bbb5d 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -16,7 +16,7 @@ If your pytest setup follows the best practices of failing on emitted warnings (``filterwarnings = error``), you may ignore it by adding the following line at the end of the list:: - ignore:Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.:UserWarning:cryptography + ignore:Python 2 is no longer supported by the Python core team. Support for it is now deprecated in cryptography, and will be removed in a future release.:UserWarning **Note:** Using ``cryptography.utils.CryptographyDeprecationWarning`` is not possible here because specifying it triggers From ec8b0b204fcb9c99239c6b5d36225b46e59eb89d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 28 Oct 2020 14:02:46 -0400 Subject: [PATCH 13/61] Update .travis.yml for 3.9 (#5482) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 25dccb21c9cd..026977ee22f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ matrix: # Setting 'python' is just to make travis's UI a bit prettier - python: 3.6 env: TOXENV=py36 - - python: 3.9-dev + - python: 3.9 env: TOXENV=py39 # Travis lists available Pythons (including PyPy) by arch and distro here: # https://docs.travis-ci.com/user/languages/python/#python-versions From 2ce289fdae9d1a422e11236875b456c224527cda Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Oct 2020 01:01:37 -0400 Subject: [PATCH 14/61] Update installation docs for 3.5 drop (#5531) --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index eb270e62f371..ea4625582a87 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -45,7 +45,7 @@ just run If you prefer to compile it yourself you'll need to have OpenSSL installed. You can compile OpenSSL yourself as well or use `a binary distribution`_. Be sure to download the proper version for your architecture and Python -(VC2010 works for Python 2.7 while VC2015 is required for 3.5 and above). +(VC2010 works for Python 2.7 while VC2015 is required for 3.6 and above). Wherever you place your copy of OpenSSL you'll need to set the ``LIB`` and ``INCLUDE`` environment variables to include the proper locations. For example: From a48bcfba2aff6f40a9f98137cf3a94b62e508e69 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 29 Oct 2020 01:01:59 -0400 Subject: [PATCH 15/61] Clean up travis scripts now that 1.0.2 is dropped (#5530) --- .travis/install.sh | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.travis/install.sh b/.travis/install.sh index 91df42285cdb..c9c90b041a3e 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -25,14 +25,9 @@ if [ -n "${OPENSSL}" ]; then shlib_sed make depend make -j"$(nproc)" - # CRYPTOGRAPHY_OPENSSL_LESS_THAN_110 - if [ "${OPENSSL}" == "1.0.2u" ]; then - make install - else - # avoid installing the docs on versions of OpenSSL that aren't ancient. - # https://github.com/openssl/openssl/issues/6685#issuecomment-403838728 - make install_sw install_ssldirs - fi + # avoid installing the docs on versions of OpenSSL that aren't ancient. + # https://github.com/openssl/openssl/issues/6685#issuecomment-403838728 + make install_sw install_ssldirs popd fi elif [ -n "${LIBRESSL}" ]; then From 851acb5ab4427fefc769b1380592c0a01da7bb06 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 30 Oct 2020 12:55:40 -0400 Subject: [PATCH 16/61] Rephrase abi3 FAQ so it stays accurate (#5534) --- docs/faq.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 842dd75bbb5d..e4c2af4f4eb6 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -122,9 +122,9 @@ Why are there no wheels for Python 3.6+ on Linux or macOS? ---------------------------------------------------------- Our Python3 wheels, for macOS and Linux, are ``abi3`` wheels. This means they -support multiple versions of Python. The Python 3.5 ``abi3`` wheel can be used -with any version of Python greater than or equal to 3.5. Recent versions of -``pip`` will automatically install ``abi3`` wheels. +support multiple versions of Python. The ``abi3`` wheel can be used with any +version of Python greater than or equal to the version it specifies. Recent +versions of ``pip`` will automatically install ``abi3`` wheels. Why can't I import my PEM file? ------------------------------- From e06e5c6767a07851e08039f1f46750f449ec0c97 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 31 Oct 2020 14:05:21 -0400 Subject: [PATCH 17/61] tense (#5538) --- docs/api-stability.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api-stability.rst b/docs/api-stability.rst index 205b18447b05..fd34ced0aba1 100644 --- a/docs/api-stability.rst +++ b/docs/api-stability.rst @@ -1,7 +1,7 @@ API stability ============= -From its first release, ``cryptography`` will have a strong API stability +From its first release, ``cryptography`` has had a strong API stability policy. What does this policy cover? From 752f966c947b8e95781a3ac6247231015d686d86 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 31 Oct 2020 14:05:45 -0400 Subject: [PATCH 18/61] we have abi3 wheels for windows now (#5536) * we have abi3 wheels for windows now * Update faq.rst --- docs/faq.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index e4c2af4f4eb6..e57d9c295ed1 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -118,13 +118,13 @@ 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. -Why are there no wheels for Python 3.6+ on Linux or macOS? ----------------------------------------------------------- +Why are there no wheels for my Python3.x version? +------------------------------------------------- -Our Python3 wheels, for macOS and Linux, are ``abi3`` wheels. This means they -support multiple versions of Python. The ``abi3`` wheel can be used with any -version of Python greater than or equal to the version it specifies. Recent -versions of ``pip`` will automatically install ``abi3`` wheels. +Our Python3 wheels are ``abi3`` wheels. This means they support multiple +versions of Python. The ``abi3`` wheel can be used with any version of Python +greater than or equal to the version it specifies. Recent versions of ``pip`` +will automatically install ``abi3`` wheels. Why can't I import my PEM file? ------------------------------- From 753965c13aeae63001ad370f1e45307b3687f665 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 31 Oct 2020 14:23:44 -0400 Subject: [PATCH 19/61] abi3 only on windows (#5537) --- .github/workflows/wheel-builder.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index df8a752eaa4f..c4bf9ab057d3 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -115,9 +115,6 @@ jobs: - {ARCH: 'x64', WINDOWS: 'win64'} PYTHON: - {VERSION: "2.7", MSVC_VERSION: "2010"} - - {VERSION: "3.6", MSVC_VERSION: "2019"} - - {VERSION: "3.7", MSVC_VERSION: "2019"} - - {VERSION: "3.8", MSVC_VERSION: "2019"} - {VERSION: "3.8", MSVC_VERSION: "2019", "USE_ABI3": "true", "ABI_VERSION": "cp36"} name: "${{ matrix.PYTHON.VERSION }} ${{ matrix.WINDOWS.WINDOWS }} ${{ matrix.PYTHON.ABI_VERSION }}" steps: From 81e5de8986abfb50a322fe1f3cccf319c77e5f6f Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 31 Oct 2020 16:09:07 -0700 Subject: [PATCH 20/61] updated faq entry (#5541) the error will be opensslv.h these days and we don't need to talk specifically about macOS --- docs/faq.rst | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index e57d9c295ed1..d6f4ad336ac7 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -70,18 +70,17 @@ legacy libraries: :class:`AES-GCM ` and :class:`~cryptography.hazmat.primitives.kdf.hkdf.HKDF`. -Compiling ``cryptography`` on macOS produces a ``fatal error: 'openssl/aes.h' file not found`` error ----------------------------------------------------------------------------------------------------- - -This happens because macOS 10.11 no longer includes a copy of OpenSSL. -``cryptography`` now provides wheels which include a statically linked copy of -OpenSSL. You're seeing this error because your copy of pip is too old to find -our wheel files. Upgrade your copy of pip with ``pip install -U pip`` and then -try install ``cryptography`` again. - -If you are using PyPy, we do not currently ship ``cryptography`` wheels for -PyPy. You will need to install your own copy of OpenSSL -- we recommend using -Homebrew. +Installing ``cryptography`` produces a ``fatal error: 'openssl/opensslv.h' file not found`` error +------------------------------------------------------------------------------------------------- + +``cryptography`` provides wheels which include a statically linked copy of +OpenSSL. If you see this error it is likely because your copy of ``pip`` is too +old to find our wheel files. Upgrade your ``pip`` with ``pip install -U pip`` +and then try to install ``cryptography`` again. + +Users on PyPy, unusual CPU architectures, or distributions of Linux using +``musl`` (like Alpine) will need to compile ``cryptography`` themselves. Please +view our :doc:`/installation` documentation. ``cryptography`` raised an ``InternalError`` and I'm not sure what to do? ------------------------------------------------------------------------- From 66654d628d1445edf42c66de402c6386b67a4292 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sat, 31 Oct 2020 16:10:10 -0700 Subject: [PATCH 21/61] print some stuff in setup.py to try to educate people (#5539) This is likely futile, but maybe it will slightly help out people who run into compilation errors and actually choose to look at the output. --- setup.py | 171 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 102 insertions(+), 69 deletions(-) diff --git a/setup.py b/setup.py index 23671748f025..c6c3e994625e 100644 --- a/setup.py +++ b/setup.py @@ -51,74 +51,107 @@ long_description = f.read() -setup( - name=about["__title__"], - version=about["__version__"], - description=about["__summary__"], - long_description=long_description, - long_description_content_type="text/x-rst", - license=about["__license__"], - url=about["__uri__"], - author=about["__author__"], - author_email=about["__email__"], - classifiers=[ - "Development Status :: 5 - Production/Stable", - "Intended Audience :: Developers", - "License :: OSI Approved :: Apache Software License", - "License :: OSI Approved :: BSD License", - "Natural Language :: English", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX", - "Operating System :: POSIX :: BSD", - "Operating System :: POSIX :: Linux", - "Operating System :: Microsoft :: Windows", - "Programming Language :: Python", - "Programming Language :: Python :: 2", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Security :: Cryptography", - ], - package_dir={"": "src"}, - packages=find_packages(where="src", exclude=["_cffi_src", "_cffi_src.*"]), - include_package_data=True, - python_requires=">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*", - install_requires=["six >= 1.4.1"] + setup_requirements, - setup_requires=setup_requirements, - extras_require={ - ":python_version < '3'": ["enum34", "ipaddress"], - "test": [ - "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2", - "pretend", - "iso8601", - "pytz", - "hypothesis>=1.11.4,!=3.79.2", +try: + setup( + name=about["__title__"], + version=about["__version__"], + description=about["__summary__"], + long_description=long_description, + long_description_content_type="text/x-rst", + license=about["__license__"], + url=about["__uri__"], + author=about["__author__"], + author_email=about["__email__"], + classifiers=[ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "License :: OSI Approved :: Apache Software License", + "License :: OSI Approved :: BSD License", + "Natural Language :: English", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX", + "Operating System :: POSIX :: BSD", + "Operating System :: POSIX :: Linux", + "Operating System :: Microsoft :: Windows", + "Programming Language :: Python", + "Programming Language :: Python :: 2", + "Programming Language :: Python :: 2.7", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: Implementation :: CPython", + "Programming Language :: Python :: Implementation :: PyPy", + "Topic :: Security :: Cryptography", ], - "docs": [ - "sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1", - "sphinx_rtd_theme", + package_dir={"": "src"}, + packages=find_packages( + where="src", exclude=["_cffi_src", "_cffi_src.*"] + ), + include_package_data=True, + python_requires=( + ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*" + ), + install_requires=["six >= 1.4.1"] + setup_requirements, + setup_requires=setup_requirements, + extras_require={ + ":python_version < '3'": ["enum34", "ipaddress"], + "test": [ + "pytest>=3.6.0,!=3.9.0,!=3.9.1,!=3.9.2", + "pretend", + "iso8601", + "pytz", + "hypothesis>=1.11.4,!=3.79.2", + ], + "docs": [ + "sphinx >= 1.6.5,!=1.8.0,!=3.1.0,!=3.1.1", + "sphinx_rtd_theme", + ], + "docstest": [ + "doc8", + "pyenchant >= 1.6.11", + "twine >= 1.12.0", + "sphinxcontrib-spelling >= 4.0.1", + ], + "pep8test": [ + "black", + "flake8", + "flake8-import-order", + "pep8-naming", + ], + # 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"], + }, + # for cffi + zip_safe=False, + ext_package="cryptography.hazmat.bindings", + cffi_modules=[ + "src/_cffi_src/build_openssl.py:ffi", + "src/_cffi_src/build_padding.py:ffi", ], - "docstest": [ - "doc8", - "pyenchant >= 1.6.11", - "twine >= 1.12.0", - "sphinxcontrib-spelling >= 4.0.1", - ], - "pep8test": ["black", "flake8", "flake8-import-order", "pep8-naming"], - # 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"], - }, - # for cffi - zip_safe=False, - ext_package="cryptography.hazmat.bindings", - cffi_modules=[ - "src/_cffi_src/build_openssl.py:ffi", - "src/_cffi_src/build_padding.py:ffi", - ], -) + ) +except: # noqa: E722 + # Note: This is a bare exception that re-raises so that we don't interfere + # with anything the installation machinery might want to do. Because we + # print this for any exception this msg can appear (e.g. in verbose logs) + # even if there's no failure. For example, SetupRequirementsError is raised + # during PEP517 building and prints this text. setuptools raises SystemExit + # when compilation fails right now, but it's possible this isn't stable + # or a public API commitment so we'll remain ultra conservative. + print( + """ + =============================DEBUG ASSISTANCE============================= + If you are seeing a compilation error please try the following steps to + successfully install cryptography: + 1) Upgrade to the latest pip and try again. This will fix errors for most + users. See: https://pip.pypa.io/en/stable/installing/#upgrading-pip + 2) Read https://cryptography.io/en/latest/installation.html for specific + instructions for your platform. + 3) Check our frequently asked questions for more information: + https://cryptography.io/en/latest/faq.html + =============================DEBUG ASSISTANCE============================= + """ + ) + raise From d59b7c235b0f0819e3f7e4f01e351d4b2f385026 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 1 Nov 2020 11:55:52 -0500 Subject: [PATCH 22/61] Don't tell people to use PGP, it's not good (#5543) --- docs/security.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/security.rst b/docs/security.rst index 8cdd2d114d9a..d11f2700012a 100644 --- a/docs/security.rst +++ b/docs/security.rst @@ -53,10 +53,9 @@ We ask that you do not report security issues to our normal GitHub issue tracker. If you believe you've identified a security issue with ``cryptography``, please -report it to ``alex.gaynor@gmail.com``. Messages may be optionally encrypted -with PGP using key fingerprint -``F7FC 698F AAE2 D2EF BECD E98E D1B3 ADC0 E023 8CA6`` (this public key is -available from most commonly-used key servers). +report it to ``alex.gaynor@gmail.com`` and/or ``paul.l.kehrer@gmail.com``. You +should verify that your MTA uses TLS to ensure the confidentiality of your +message. Once you've submitted an issue via email, you should receive an acknowledgment within 48 hours, and depending on the action to be taken, you may receive From 923de98f040dd280c7b7eae4a8e83488853fbd12 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 3 Nov 2020 10:16:06 -0500 Subject: [PATCH 23/61] Attempt to move docker builds from travis to GHA (#5545) * Attempt to move docker builds from travis to GHA * fix linkcheck --- .github/workflows/ci.yml | 36 +++++++++++++++++++++++++++++ .travis.yml | 46 +------------------------------------- .travis/install.sh | 8 ------- .travis/run.sh | 10 +-------- .travis/upload_coverage.sh | 4 ++-- 5 files changed, 40 insertions(+), 64 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc556f06189a..5580b0ec09d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,42 @@ on: - '*.*.*' jobs: + linux-distros: + runs-on: ubuntu-latest + container: ${{ matrix.IMAGE.IMAGE }} + strategy: + matrix: + IMAGE: + - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py27"} + - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py36"} + - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", ENV: "OPENSSL_FORCE_FIPS_MODE=1"} + - {IMAGE: "pyca/cryptography-runner-stretch", TOXENV: "py27"} + - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} + - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-ubuntu-bionic", TOXENV: "py36"} + - {IMAGE: "pyca/cryptography-runner-ubuntu-focal", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py27"} + - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38-randomorder"} + - {IMAGE: "pyca/cryptography-runner-fedora", TOXENV: "py39"} + - {IMAGE: "pyca/cryptography-runner-alpine", TOXENV: "py38"} + name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }} ${{ matrix.IMAGE.ENV }}" + steps: + - uses: actions/checkout@v2 + - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' + - run: 'echo "$ENV_VAR" >> $GITHUB_ENV' + if: matrix.IMAGE.ENV + env: + ENV_VAR: ${{ matrix.IMAGE.ENV }} + - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' + env: + TOXENV: ${{ matrix.IMAGE.TOXENV }} + - name: Upload coverage + run: | + curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash + bash codecov.sh -n "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }} ${{ matrix.IMAGE.ENV }}" + macos: runs-on: macos-latest strategy: diff --git a/.travis.yml b/.travis.yml index 026977ee22f0..b214aa49421e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -54,49 +54,6 @@ matrix: - python: 3.8 env: TOXENV=py38 LIBRESSL=3.2.2 - - python: 2.7 - services: docker - env: TOXENV=py27 DOCKER=pyca/cryptography-runner-centos8 - - python: 3.6 - services: docker - env: TOXENV=py36 DOCKER=pyca/cryptography-runner-centos8 - - python: 3.6 - services: docker - env: TOXENV=py36 OPENSSL_FORCE_FIPS_MODE=1 DOCKER=pyca/cryptography-runner-centos8-fips - - python: 2.7 - services: docker - env: TOXENV=py27 DOCKER=pyca/cryptography-runner-stretch - - python: 3.7 - services: docker - env: TOXENV=py37 DOCKER=pyca/cryptography-runner-buster - - python: 3.8 - services: docker - env: TOXENV=py38 DOCKER=pyca/cryptography-runner-bullseye - - python: 3.8 - services: docker - env: TOXENV=py38 DOCKER=pyca/cryptography-runner-sid - - python: 3.6 - services: docker - env: TOXENV=py36 DOCKER=pyca/cryptography-runner-ubuntu-bionic - - python: 3.8 - services: docker - env: TOXENV=py38 DOCKER=pyca/cryptography-runner-ubuntu-focal - - python: 2.7 - services: docker - env: TOXENV=py27 DOCKER=pyca/cryptography-runner-ubuntu-rolling - - python: 3.8 - services: docker - env: TOXENV=py38 DOCKER=pyca/cryptography-runner-ubuntu-rolling - - python: 3.8 - services: docker - env: TOXENV=py38-randomorder DOCKER=pyca/cryptography-runner-ubuntu-rolling - - python: 3.9 - services: docker - env: TOXENV=py39 DOCKER=pyca/cryptography-runner-fedora - - python: 3.8 - services: docker - env: TOXENV=py38 DOCKER=pyca/cryptography-runner-alpine:latest - - python: 3.8 env: TOXENV=docs OPENSSL=1.1.1h addons: @@ -104,8 +61,7 @@ matrix: packages: - libenchant-dev - python: 3.8 - services: docker - env: TOXENV=docs-linkcheck DOCKER=pyca/cryptography-runner-buster + env: TOXENV=docs-linkcheck if: (branch = master AND type != pull_request) OR commit_message =~ /linkcheck/ - python: 3.8 diff --git a/.travis/install.sh b/.travis/install.sh index c9c90b041a3e..ccc7f444dfe8 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -43,14 +43,6 @@ elif [ -n "${LIBRESSL}" ]; then fi fi -if [ -n "${DOCKER}" ]; then - if [ -n "${OPENSSL}" ] || [ -n "${LIBRESSL}" ]; then - echo "OPENSSL and LIBRESSL are not allowed when DOCKER is set." - exit 1 - fi - docker pull "$DOCKER" || docker pull "$DOCKER" || docker pull "$DOCKER" -fi - if [ -z "${DOWNSTREAM}" ]; then git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof" fi diff --git a/.travis/run.sh b/.travis/run.sh index 01605c2717d4..313fb86b6d8d 100755 --- a/.travis/run.sh +++ b/.travis/run.sh @@ -20,15 +20,7 @@ fi source ~/.venv/bin/activate -if [ -n "${DOCKER}" ]; then - docker run --rm \ - -v "${TRAVIS_BUILD_DIR}":"${TRAVIS_BUILD_DIR}" \ - -v "${HOME}/wycheproof":/wycheproof \ - -w "${TRAVIS_BUILD_DIR}" \ - -e OPENSSL_FORCE_FIPS_MODE \ - -e TOXENV "${DOCKER}" \ - /bin/sh -c "tox -- --wycheproof-root='/wycheproof'" -elif [ -n "${TOXENV}" ]; then +if [ -n "${TOXENV}" ]; then tox -- --wycheproof-root="$HOME/wycheproof" else downstream_script="${TRAVIS_BUILD_DIR}/.travis/downstream.d/${DOWNSTREAM}.sh" diff --git a/.travis/upload_coverage.sh b/.travis/upload_coverage.sh index 2999bb7e6b25..28251f8ba010 100755 --- a/.travis/upload_coverage.sh +++ b/.travis/upload_coverage.sh @@ -14,8 +14,8 @@ if [ -n "${TOXENV}" ]; then source ~/.venv/bin/activate curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash - bash codecov.sh -Z -e TRAVIS_OS_NAME,TOXENV,OPENSSL,DOCKER,OPENSSL_FORCE_FIPS_MODE || \ - bash codecov.sh -Z -e TRAVIS_OS_NAME,TOXENV,OPENSSL,DOCKER,OPENSSL_FORCE_FIPS_MODE + bash codecov.sh -Z -e TRAVIS_OS_NAME,TOXENV,OPENSSL || \ + bash codecov.sh -Z -e TRAVIS_OS_NAME,TOXENV,OPENSSL ;; esac fi From 4ba0d6ea4af2fb93826378e6f21744161dda082b Mon Sep 17 00:00:00 2001 From: Mads Jensen Date: Wed, 4 Nov 2020 15:51:17 +0100 Subject: [PATCH 24/61] Fix broken link to security documentation in README.rst (#5551) --- README.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.rst b/README.rst index 062e3c75431c..586cb1b0b3bc 100644 --- a/README.rst +++ b/README.rst @@ -71,4 +71,4 @@ documentation. .. _`the installation documentation`: https://cryptography.io/en/latest/installation.html .. _`issue tracker`: https://github.com/pyca/cryptography/issues .. _`cryptography-dev`: https://mail.python.org/mailman/listinfo/cryptography-dev -.. _`security reporting`: https://cryptography.io/en/latest/security/ +.. _`security reporting`: https://cryptography.io/en/latest/security.html From 15771e2ec2f94e2a82057d3eae38cb5580fb6727 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Wed, 4 Nov 2020 09:49:47 -0600 Subject: [PATCH 25/61] padding: Tip-toe around bytes subclasses. (#5548) This change allows future's newbytes class to be padded again. Fixes https://github.com/pyca/cryptography/issues/5547. --- src/cryptography/hazmat/primitives/padding.py | 10 ++++++-- tests/hazmat/primitives/test_padding.py | 24 +++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/cryptography/hazmat/primitives/padding.py b/src/cryptography/hazmat/primitives/padding.py index d3dc7093ae51..98abffbc08be 100644 --- a/src/cryptography/hazmat/primitives/padding.py +++ b/src/cryptography/hazmat/primitives/padding.py @@ -42,7 +42,10 @@ def _byte_padding_update(buffer_, data, block_size): utils._check_byteslike("data", data) - buffer_ += bytes(data) + # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior + # of future's newbytes type. Unconditionally call bytes() after Python 2 + # support is gone. + buffer_ += data if isinstance(data, bytes) else bytes(data) finished_blocks = len(buffer_) // (block_size // 8) @@ -66,7 +69,10 @@ def _byte_unpadding_update(buffer_, data, block_size): utils._check_byteslike("data", data) - buffer_ += bytes(data) + # six.PY2: Only coerce non-bytes objects to avoid triggering bad behavior + # of future's newbytes type. Unconditionally call bytes() after Python 2 + # support is gone. + buffer_ += data if isinstance(data, bytes) else bytes(data) finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0) diff --git a/tests/hazmat/primitives/test_padding.py b/tests/hazmat/primitives/test_padding.py index bf5379730131..b15eb37539c5 100644 --- a/tests/hazmat/primitives/test_padding.py +++ b/tests/hazmat/primitives/test_padding.py @@ -43,6 +43,18 @@ def test_non_bytes(self): with pytest.raises(TypeError): unpadder.update(u"abc") + def test_zany_py2_bytes_subclass(self): + class mybytes(bytes): # noqa: N801 + def __str__(self): + return "broken" + + str(mybytes()) + padder = padding.PKCS7(128).padder() + padder.update(mybytes(b"abc")) + unpadder = padding.PKCS7(128).unpadder() + unpadder.update(mybytes(padder.finalize())) + assert unpadder.finalize() == b"abc" + @pytest.mark.parametrize( ("size", "unpadded", "padded"), [ @@ -154,6 +166,18 @@ def test_non_bytes(self): with pytest.raises(TypeError): unpadder.update(u"abc") + def test_zany_py2_bytes_subclass(self): + class mybytes(bytes): # noqa: N801 + def __str__(self): + return "broken" + + str(mybytes()) + padder = padding.ANSIX923(128).padder() + padder.update(mybytes(b"abc")) + unpadder = padding.ANSIX923(128).unpadder() + unpadder.update(mybytes(padder.finalize())) + assert unpadder.finalize() == b"abc" + @pytest.mark.parametrize( ("size", "unpadded", "padded"), [ From b59d2de9cf0dcf5c36d37007b6e756f18e9b0160 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 9 Nov 2020 12:56:53 -0600 Subject: [PATCH 26/61] GCM IV size limits (#5553) * GCM IV size limits OpenSSL 3.0.0 is going to enforce these size limits so we might as well put them in now. * fix the tests * black * these cases can't happen if we're limiting IV size already --- CHANGELOG.rst | 6 +++++ .../hazmat/primitives/ciphers/aead.py | 4 ++-- .../hazmat/primitives/ciphers/modes.py | 12 +++++----- tests/hazmat/primitives/test_aead.py | 13 +++++++++-- tests/hazmat/primitives/test_aes_gcm.py | 22 +++++++++++++++++++ tests/hazmat/primitives/test_ciphers.py | 7 ++++++ tests/hazmat/primitives/utils.py | 4 ++++ tests/wycheproof/test_aes.py | 17 +++++++++----- 8 files changed, 70 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b652d2ba733e..b001ec266c6a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -10,6 +10,12 @@ Changelog * **BACKWARDS INCOMPATIBLE:** Support for Python 3.5 has been removed due to low usage and maintenance burden. +* **BACKWARDS INCOMPATIBLE:** The + :class:`~cryptography.hazmat.primitives.ciphers.modes.GCM` and + :class:`~cryptography.hazmat.primitives.ciphers.aead.AESGCM` now require + 64-bit to 1024-bit (8 byte to 128 byte) initialization vectors. This change + is to conform with an upcoming OpenSSL release that will no longer support + sizes outside this window. .. _v3-2-1: diff --git a/src/cryptography/hazmat/primitives/ciphers/aead.py b/src/cryptography/hazmat/primitives/ciphers/aead.py index 4eddc1ee6e37..c8c93955ce01 100644 --- a/src/cryptography/hazmat/primitives/ciphers/aead.py +++ b/src/cryptography/hazmat/primitives/ciphers/aead.py @@ -170,5 +170,5 @@ def _check_params(self, nonce, data, associated_data): utils._check_byteslike("nonce", nonce) utils._check_bytes("data", data) utils._check_bytes("associated_data", associated_data) - if len(nonce) == 0: - raise ValueError("Nonce must be at least 1 byte") + if len(nonce) < 8 or len(nonce) > 128: + raise ValueError("Nonce must be between 8 and 128 bytes") diff --git a/src/cryptography/hazmat/primitives/ciphers/modes.py b/src/cryptography/hazmat/primitives/ciphers/modes.py index dcb24444214f..0ba0f2b5a176 100644 --- a/src/cryptography/hazmat/primitives/ciphers/modes.py +++ b/src/cryptography/hazmat/primitives/ciphers/modes.py @@ -196,12 +196,14 @@ class GCM(object): _MAX_AAD_BYTES = (2 ** 64) // 8 def __init__(self, initialization_vector, tag=None, min_tag_length=16): - # len(initialization_vector) must in [1, 2 ** 64), but it's impossible - # to actually construct a bytes object that large, so we don't check - # for it + # OpenSSL 3.0.0 constrains GCM IVs to [64, 1024] bits inclusive + # This is a sane limit anyway so we'll enforce it here. utils._check_byteslike("initialization_vector", initialization_vector) - if len(initialization_vector) == 0: - raise ValueError("initialization_vector must be at least 1 byte") + if len(initialization_vector) < 8 or len(initialization_vector) > 128: + raise ValueError( + "initialization_vector must be between 8 and 128 bytes (64 " + "and 1024 bits)." + ) self._initialization_vector = initialization_vector if tag is not None: utils._check_bytes("tag", tag) diff --git a/tests/hazmat/primitives/test_aead.py b/tests/hazmat/primitives/test_aead.py index 753c7c192bc9..270693182ed2 100644 --- a/tests/hazmat/primitives/test_aead.py +++ b/tests/hazmat/primitives/test_aead.py @@ -380,6 +380,9 @@ def test_data_too_large(self): def test_vectors(self, backend, vector): nonce = binascii.unhexlify(vector["iv"]) + if len(nonce) < 8: + pytest.skip("GCM does not support less than 64-bit IVs") + if backend._fips_enabled and len(nonce) != 12: # Red Hat disables non-96-bit IV support as part of its FIPS # patches. @@ -418,11 +421,17 @@ def test_params_not_bytes(self, nonce, data, associated_data, backend): with pytest.raises(TypeError): aesgcm.decrypt(nonce, data, associated_data) - def test_invalid_nonce_length(self, backend): + @pytest.mark.parametrize("length", [7, 129]) + def test_invalid_nonce_length(self, length, backend): + if backend._fips_enabled: + # Red Hat disables non-96-bit IV support as part of its FIPS + # patches. + pytest.skip("Non-96-bit IVs unsupported in FIPS mode.") + key = AESGCM.generate_key(128) aesgcm = AESGCM(key) with pytest.raises(ValueError): - aesgcm.encrypt(b"", b"hi", None) + aesgcm.encrypt(b"\x00" * length, b"hi", None) def test_bad_key(self, backend): with pytest.raises(TypeError): diff --git a/tests/hazmat/primitives/test_aes_gcm.py b/tests/hazmat/primitives/test_aes_gcm.py index f289f18b11cc..8b71d12300c9 100644 --- a/tests/hazmat/primitives/test_aes_gcm.py +++ b/tests/hazmat/primitives/test_aes_gcm.py @@ -195,3 +195,25 @@ def test_buffer_protocol(self, backend): dec.authenticate_additional_data(bytearray(b"foo")) pt = dec.update(ct) + dec.finalize() assert pt == data + + @pytest.mark.parametrize("size", [8, 128]) + def test_gcm_min_max_iv(self, size, backend): + if backend._fips_enabled: + # Red Hat disables non-96-bit IV support as part of its FIPS + # patches. + pytest.skip("Non-96-bit IVs unsupported in FIPS mode.") + + key = os.urandom(16) + iv = b"\x00" * size + + payload = b"data" + encryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).encryptor() + ct = encryptor.update(payload) + encryptor.finalize() + tag = encryptor.tag + + decryptor = base.Cipher(algorithms.AES(key), modes.GCM(iv)).decryptor() + pt = decryptor.update(ct) + + decryptor.finalize_with_tag(tag) + assert pt == payload diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py index 4d82f0c13f42..a9219fe99c15 100644 --- a/tests/hazmat/primitives/test_ciphers.py +++ b/tests/hazmat/primitives/test_ciphers.py @@ -72,6 +72,13 @@ def test_xts_wrong_key_size(self, backend): ciphers.Cipher(AES(b"0" * 16), modes.XTS(b"0" * 16), backend) +class TestGCM(object): + @pytest.mark.parametrize("size", [7, 129]) + def test_gcm_min_max(self, size): + with pytest.raises(ValueError): + modes.GCM(b"0" * size) + + class TestCamellia(object): @pytest.mark.parametrize( ("key", "keysize"), diff --git a/tests/hazmat/primitives/utils.py b/tests/hazmat/primitives/utils.py index 741e07d5c3cc..3f1eff66e00f 100644 --- a/tests/hazmat/primitives/utils.py +++ b/tests/hazmat/primitives/utils.py @@ -86,6 +86,10 @@ def test_aead(self, backend, params): def aead_test(backend, cipher_factory, mode_factory, params): + if mode_factory is GCM and len(params["iv"]) < 16: + # 16 because this is hex encoded data + pytest.skip("Less than 64-bit IVs are no longer supported") + if ( mode_factory is GCM and backend._fips_enabled diff --git a/tests/wycheproof/test_aes.py b/tests/wycheproof/test_aes.py index e33c01e99f54..9992095ae8c3 100644 --- a/tests/wycheproof/test_aes.py +++ b/tests/wycheproof/test_aes.py @@ -54,6 +54,11 @@ def test_aes_gcm(backend, wycheproof): msg = binascii.unhexlify(wycheproof.testcase["msg"]) ct = binascii.unhexlify(wycheproof.testcase["ct"]) tag = binascii.unhexlify(wycheproof.testcase["tag"]) + if len(iv) < 8 or len(iv) > 128: + pytest.skip( + "Less than 64-bit IVs (and greater than 1024-bit) are no longer " + "supported" + ) if backend._fips_enabled and len(iv) != 12: # Red Hat disables non-96-bit IV support as part of its FIPS # patches. @@ -73,9 +78,6 @@ def test_aes_gcm(backend, wycheproof): dec.authenticate_additional_data(aad) computed_msg = dec.update(ct) + dec.finalize() assert computed_msg == msg - elif len(iv) == 0: - with pytest.raises(ValueError): - Cipher(algorithms.AES(key), modes.GCM(iv), backend) else: dec = Cipher( algorithms.AES(key), @@ -97,6 +99,12 @@ def test_aes_gcm_aead_api(backend, wycheproof): msg = binascii.unhexlify(wycheproof.testcase["msg"]) ct = binascii.unhexlify(wycheproof.testcase["ct"]) tag = binascii.unhexlify(wycheproof.testcase["tag"]) + if len(iv) < 8 or len(iv) > 128: + pytest.skip( + "Less than 64-bit IVs (and greater than 1024-bit) are no longer " + "supported" + ) + if backend._fips_enabled and len(iv) != 12: # Red Hat disables non-96-bit IV support as part of its FIPS # patches. @@ -107,9 +115,6 @@ def test_aes_gcm_aead_api(backend, wycheproof): assert computed_ct == ct + tag computed_msg = aesgcm.decrypt(iv, ct + tag, aad) assert computed_msg == msg - elif len(iv) == 0: - with pytest.raises(ValueError): - aesgcm.encrypt(iv, msg, aad) else: with pytest.raises(InvalidTag): aesgcm.decrypt(iv, ct + tag, aad) From b9b921aa898d475a080a3f7ff88419f16311a704 Mon Sep 17 00:00:00 2001 From: Felix Fontein Date: Wed, 11 Nov 2020 04:52:33 +0100 Subject: [PATCH 27/61] Fix broken links (#5552) * Fix broken links. * Shorter lines. --- src/cryptography/hazmat/backends/openssl/backend.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 5f5c5795bd33..f2b7230bbaa7 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1368,8 +1368,9 @@ def load_pem_x509_certificate(self, data): if x509 == self._ffi.NULL: self._consume_errors() raise ValueError( - "Unable to load certificate. See https://cryptography.io/en/la" - "test/faq/#why-can-t-i-import-my-pem-file for more details." + "Unable to load certificate. See https://cryptography.io/en/" + "latest/faq.html#why-can-t-i-import-my-pem-file for more" + " details." ) x509 = self._ffi.gc(x509, self._lib.X509_free) @@ -1394,7 +1395,8 @@ def load_pem_x509_crl(self, data): self._consume_errors() raise ValueError( "Unable to load CRL. See https://cryptography.io/en/la" - "test/faq/#why-can-t-i-import-my-pem-file for more details." + "test/faq.html#why-can-t-i-import-my-pem-file for more" + " details." ) x509_crl = self._ffi.gc(x509_crl, self._lib.X509_CRL_free) @@ -1418,8 +1420,9 @@ def load_pem_x509_csr(self, data): if x509_req == self._ffi.NULL: self._consume_errors() raise ValueError( - "Unable to load request. See https://cryptography.io/en/la" - "test/faq/#why-can-t-i-import-my-pem-file for more details." + "Unable to load request. See https://cryptography.io/en/" + "latest/faq.html#why-can-t-i-import-my-pem-file for more" + " details." ) x509_req = self._ffi.gc(x509_req, self._lib.X509_REQ_free) From e0b446e2e47a589de480346aaedfa0a495be5ae6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 11 Nov 2020 10:50:02 -0500 Subject: [PATCH 28/61] Migrate drownstream tests to GHA (#5554) --- .../downstream.d/aws-encryption-sdk.sh | 0 .../downstream.d/certbot-josepy.sh | 0 {.travis => .github}/downstream.d/certbot.sh | 0 .../downstream.d/dynamodb-encryption-sdk.sh | 0 .../downstream.d/pyopenssl.sh | 0 {.travis => .github}/downstream.d/twisted.sh | 0 .github/workflows/ci.yml | 23 +++++++++++++++++++ .travis.yml | 16 ++----------- .travis/downstream.d/README.rst | 13 ----------- 9 files changed, 25 insertions(+), 27 deletions(-) rename {.travis => .github}/downstream.d/aws-encryption-sdk.sh (100%) rename {.travis => .github}/downstream.d/certbot-josepy.sh (100%) rename {.travis => .github}/downstream.d/certbot.sh (100%) rename {.travis => .github}/downstream.d/dynamodb-encryption-sdk.sh (100%) rename {.travis => .github}/downstream.d/pyopenssl.sh (100%) rename {.travis => .github}/downstream.d/twisted.sh (100%) delete mode 100644 .travis/downstream.d/README.rst diff --git a/.travis/downstream.d/aws-encryption-sdk.sh b/.github/downstream.d/aws-encryption-sdk.sh similarity index 100% rename from .travis/downstream.d/aws-encryption-sdk.sh rename to .github/downstream.d/aws-encryption-sdk.sh diff --git a/.travis/downstream.d/certbot-josepy.sh b/.github/downstream.d/certbot-josepy.sh similarity index 100% rename from .travis/downstream.d/certbot-josepy.sh rename to .github/downstream.d/certbot-josepy.sh diff --git a/.travis/downstream.d/certbot.sh b/.github/downstream.d/certbot.sh similarity index 100% rename from .travis/downstream.d/certbot.sh rename to .github/downstream.d/certbot.sh diff --git a/.travis/downstream.d/dynamodb-encryption-sdk.sh b/.github/downstream.d/dynamodb-encryption-sdk.sh similarity index 100% rename from .travis/downstream.d/dynamodb-encryption-sdk.sh rename to .github/downstream.d/dynamodb-encryption-sdk.sh diff --git a/.travis/downstream.d/pyopenssl.sh b/.github/downstream.d/pyopenssl.sh similarity index 100% rename from .travis/downstream.d/pyopenssl.sh rename to .github/downstream.d/pyopenssl.sh diff --git a/.travis/downstream.d/twisted.sh b/.github/downstream.d/twisted.sh similarity index 100% rename from .travis/downstream.d/twisted.sh rename to .github/downstream.d/twisted.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5580b0ec09d7..a1879f83b490 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -135,3 +135,26 @@ jobs: run: | curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash bash codecov.sh -n "Python ${{ matrix.PYTHON.VERSION }} on ${{ matrix.WINDOWS.WINDOWS }}" + + linux-downstream: + runs-on: ubuntu-latest + strategy: + matrix: + DOWNSTREAM: + - pyopenssl + - twisted + - aws-encryption-sdk + - dynamodb-encryption-sdk + - certbot + - certbot-josepy + name: "Downstream tests for ${{ matrix.DOWNSTREAM }}" + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: 3.7 + - run: python -m pip install -U pip wheel + - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install + - run: pip install . + - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run diff --git a/.travis.yml b/.travis.yml index b214aa49421e..ff7647a7a43b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -64,22 +64,10 @@ matrix: env: TOXENV=docs-linkcheck if: (branch = master AND type != pull_request) OR commit_message =~ /linkcheck/ - - python: 3.8 - env: DOWNSTREAM=pyopenssl - - python: 3.7 - env: DOWNSTREAM=twisted OPENSSL=1.1.1h + # TODO: This needs to be moved to GHA, but it fails there. The + # confusing part is why it passes on Travis! - python: 3.7 env: DOWNSTREAM=paramiko - - python: 3.7 - env: DOWNSTREAM=aws-encryption-sdk - - python: 3.7 - # BOTO_CONFIG works around this boto issue on travis: - # https://github.com/boto/boto/issues/3717 - env: DOWNSTREAM=dynamodb-encryption-sdk BOTO_CONFIG=/dev/null - - python: 3.8 - env: DOWNSTREAM=certbot - - python: 3.8 - env: DOWNSTREAM=certbot-josepy install: - ./.travis/install.sh diff --git a/.travis/downstream.d/README.rst b/.travis/downstream.d/README.rst deleted file mode 100644 index 1553448c327f..000000000000 --- a/.travis/downstream.d/README.rst +++ /dev/null @@ -1,13 +0,0 @@ -To add downstream tests to be run in CI: - -1. Create a test handler for the downstream consumer that you want to test. - - * The test handler should be a single file in the ``.travis/downstream.d/`` directory. - * The file name should be ``{downstream name}.sh`` where ``{downstream name}`` - is the name that you wish to use to identify the consumer. - * The test handler should accept a single argument that can be either ``install`` or ``run``. - These should be used to separate installation of the downstream consumer and - any dependencies from the actual running of the tests. - -2. Add an entry to the test matrix in ``.travis.yml`` that sets the ``DOWNSTREAM`` - environment variable to the downstream name that you selected. From 94f32c14b7c0992b02943cf6fb9ebc5997d9fd7b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 11 Nov 2020 11:25:29 -0500 Subject: [PATCH 29/61] See if we can remove this now that we're on focal (#5559) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ff7647a7a43b..ef5e2d9038cb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -55,7 +55,7 @@ matrix: env: TOXENV=py38 LIBRESSL=3.2.2 - python: 3.8 - env: TOXENV=docs OPENSSL=1.1.1h + env: TOXENV=docs addons: apt: packages: From d74a477b66983bc3a169d150c3a52de83b9f85e4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 11 Nov 2020 11:57:32 -0500 Subject: [PATCH 30/61] Tighten up this warning message (#5560) --- src/cryptography/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cryptography/__init__.py b/src/cryptography/__init__.py index f128502e2fd5..465671eec826 100644 --- a/src/cryptography/__init__.py +++ b/src/cryptography/__init__.py @@ -34,8 +34,8 @@ if sys.version_info[0] == 2: warnings.warn( "Python 2 is no longer supported by the Python core team. Support for " - "it is now deprecated in cryptography, and will be removed in a " - "future release.", + "it is now deprecated in cryptography, and will be removed in the " + "next release.", CryptographyDeprecationWarning, stacklevel=2, ) From 49109ce1a6e870cb6cc87f05d9ae7c03d70a684b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 11 Nov 2020 14:35:47 -0500 Subject: [PATCH 31/61] Always rely on OpenSSL's builtin locking callbacks (#5561) --- LICENSE | 4 +- src/_cffi_src/openssl/callbacks.py | 134 +----------------- src/_cffi_src/openssl/crypto.py | 6 - .../hazmat/bindings/openssl/_conditional.py | 7 - .../hazmat/bindings/openssl/binding.py | 23 +-- tests/hazmat/bindings/test_openssl.py | 12 -- 6 files changed, 4 insertions(+), 182 deletions(-) diff --git a/LICENSE b/LICENSE index fe5af51408c1..07074259b61a 100644 --- a/LICENSE +++ b/LICENSE @@ -2,5 +2,5 @@ This software is made available under the terms of *either* of the licenses found in LICENSE.APACHE or LICENSE.BSD. Contributions to cryptography are made under the terms of *both* these licenses. -The code used in the OpenSSL locking callback and OS random engine is derived -from CPython, and is licensed under the terms of the PSF License Agreement. +The code used in the OS random engine is derived from CPython, and is licensed +under the terms of the PSF License Agreement. diff --git a/src/_cffi_src/openssl/callbacks.py b/src/_cffi_src/openssl/callbacks.py index 5d5da1b7ec48..19301b973a28 100644 --- a/src/_cffi_src/openssl/callbacks.py +++ b/src/_cffi_src/openssl/callbacks.py @@ -5,25 +5,7 @@ from __future__ import absolute_import, division, print_function INCLUDES = """ -#include -#include -#include -#include - -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#else -#include -#include -#include -#endif - -#ifdef __MVS__ -#include -#endif +#include """ TYPES = """ @@ -37,124 +19,10 @@ """ FUNCTIONS = """ -int Cryptography_setup_ssl_threads(void); int Cryptography_pem_password_cb(char *, int, int, void *); """ CUSTOMIZATIONS = """ -/* This code is derived from the locking code found in the Python _ssl module's - locking callback for OpenSSL. - - Copyright 2001-2016 Python Software Foundation; All Rights Reserved. - - It has been subsequently modified to use cross platform locking without - using CPython APIs by Armin Rigo of the PyPy project. -*/ - -#if CRYPTOGRAPHY_IS_LIBRESSL -#ifdef _WIN32 -typedef CRITICAL_SECTION Cryptography_mutex; -static __inline void cryptography_mutex_init(Cryptography_mutex *mutex) { - InitializeCriticalSection(mutex); -} -static __inline void cryptography_mutex_lock(Cryptography_mutex *mutex) { - EnterCriticalSection(mutex); -} -static __inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) { - LeaveCriticalSection(mutex); -} -#else -typedef pthread_mutex_t Cryptography_mutex; -#define ASSERT_STATUS(call) \ - if ((call) != 0) { \ - perror("Fatal error in callback initialization: " #call); \ - abort(); \ - } -#ifdef __MVS__ -/* When pthread_mutex_init is called more than once on the same mutex, - on z/OS this throws an EBUSY error. -*/ -#define ASSERT_STATUS_INIT(call) \ - if ((call) != 0 && errno != EBUSY) { \ - perror("Fatal error in callback initialization: " #call); \ - abort(); \ - } -#else -#define ASSERT_STATUS_INIT ASSERT_STATUS -#endif -static inline void cryptography_mutex_init(Cryptography_mutex *mutex) { -#if !defined(pthread_mutexattr_default) -# define pthread_mutexattr_default ((pthread_mutexattr_t *)NULL) -#endif - ASSERT_STATUS_INIT(pthread_mutex_init(mutex, pthread_mutexattr_default)); -} -static inline void cryptography_mutex_lock(Cryptography_mutex *mutex) { - ASSERT_STATUS(pthread_mutex_lock(mutex)); -} -static inline void cryptography_mutex_unlock(Cryptography_mutex *mutex) { - ASSERT_STATUS(pthread_mutex_unlock(mutex)); -} -#endif - - -static int _ssl_locks_count = 0; -static Cryptography_mutex *_ssl_locks = NULL; - -static void _ssl_thread_locking_function(int mode, int n, const char *file, - int line) { - /* this function is needed to perform locking on shared data - structures. (Note that OpenSSL uses a number of global data - structures that will be implicitly shared whenever multiple - threads use OpenSSL.) Multi-threaded applications will - crash at random if it is not set. - - locking_function() must be able to handle up to - CRYPTO_num_locks() different mutex locks. It sets the n-th - lock if mode & CRYPTO_LOCK, and releases it otherwise. - - file and line are the file number of the function setting the - lock. They can be useful for debugging. - */ - - if ((_ssl_locks == NULL) || - (n < 0) || (n >= _ssl_locks_count)) { - return; - } - - if (mode & CRYPTO_LOCK) { - cryptography_mutex_lock(_ssl_locks + n); - } else { - cryptography_mutex_unlock(_ssl_locks + n); - } -} - -static void init_mutexes(void) { - int i; - for (i = 0; i < _ssl_locks_count; i++) { - cryptography_mutex_init(_ssl_locks + i); - } -} - - -int Cryptography_setup_ssl_threads(void) { - if (_ssl_locks == NULL) { - _ssl_locks_count = CRYPTO_num_locks(); - _ssl_locks = calloc(_ssl_locks_count, sizeof(Cryptography_mutex)); - if (_ssl_locks == NULL) { - return 0; - } - init_mutexes(); - CRYPTO_set_locking_callback(_ssl_thread_locking_function); -#ifndef _WIN32 - pthread_atfork(NULL, NULL, &init_mutexes); -#endif - } - return 1; -} -#else -int (*Cryptography_setup_ssl_threads)(void) = NULL; -#endif - typedef struct { char *password; int length; diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index a5db642e89b3..6284f0579582 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -9,7 +9,6 @@ """ TYPES = """ -static const long Cryptography_HAS_LOCKING_CALLBACKS; static const long Cryptography_HAS_MEM_FUNCTIONS; static const long Cryptography_HAS_OPENSSL_CLEANUP; @@ -79,11 +78,6 @@ # define OPENSSL_PLATFORM SSLEAY_PLATFORM # define OPENSSL_DIR SSLEAY_DIR #endif -#if CRYPTOGRAPHY_IS_LIBRESSL -static const long Cryptography_HAS_LOCKING_CALLBACKS = 1; -#else -static const long Cryptography_HAS_LOCKING_CALLBACKS = 0; -#endif #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_OPENSSL_CLEANUP = 0; diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index aeca166b2310..585c7366454e 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -74,12 +74,6 @@ def cryptography_has_tls_st(): ] -def cryptography_has_locking_callbacks(): - return [ - "Cryptography_setup_ssl_threads", - ] - - def cryptography_has_scrypt(): return [ "EVP_PBE_scrypt", @@ -284,7 +278,6 @@ def cryptography_has_srtp(): "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_LOCKING_CALLBACKS": cryptography_has_locking_callbacks, "Cryptography_HAS_SCRYPT": cryptography_has_scrypt, "Cryptography_HAS_EVP_PKEY_DHX": cryptography_has_evp_pkey_dhx, "Cryptography_HAS_MEM_FUNCTIONS": cryptography_has_mem_functions, diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 5fd3b0de9656..6593bf1dc1b1 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -113,7 +113,6 @@ class Binding(object): ffi = ffi _lib_loaded = False _init_lock = threading.Lock() - _lock_init_lock = threading.Lock() def __init__(self): self._ensure_ffi_initialized() @@ -146,22 +145,7 @@ def _ensure_ffi_initialized(cls): @classmethod def init_static_locks(cls): - with cls._lock_init_lock: - cls._ensure_ffi_initialized() - # Use Python's implementation if available, importing _ssl triggers - # the setup for this. - __import__("_ssl") - - if ( - not cls.lib.Cryptography_HAS_LOCKING_CALLBACKS - or cls.lib.CRYPTO_get_locking_callback() != cls.ffi.NULL - ): - return - - # If nothing else has setup a locking callback already, we set up - # our own - res = lib.Cryptography_setup_ssl_threads() - _openssl_assert(cls.lib, res == 1) + cls._ensure_ffi_initialized() def _verify_package_version(version): @@ -187,9 +171,4 @@ def _verify_package_version(version): _verify_package_version(cryptography.__version__) -# OpenSSL is not thread safe until the locks are initialized. We call this -# method in module scope so that it executes with the import lock. On -# Pythons < 3.4 this import lock is a global lock, which can prevent a race -# condition registering the OpenSSL locks. On Python 3.4+ the import lock -# is per module so this approach will not work. Binding.init_static_locks() diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py index 069452cbb091..4bc046b80fe4 100644 --- a/tests/hazmat/bindings/test_openssl.py +++ b/tests/hazmat/bindings/test_openssl.py @@ -22,18 +22,6 @@ def test_binding_loads(self): assert binding.lib assert binding.ffi - def test_crypto_lock_init(self): - b = Binding() - - b.init_static_locks() - lock_cb = b.lib.CRYPTO_get_locking_callback() - if not b.lib.CRYPTOGRAPHY_IS_LIBRESSL: - assert lock_cb == b.ffi.NULL - assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 0 - else: - assert lock_cb != b.ffi.NULL - assert b.lib.Cryptography_HAS_LOCKING_CALLBACKS == 1 - def test_add_engine_more_than_once(self): b = Binding() b._register_osrandom_engine() From 23ce5638fdd6cd04ec982e7feec3140c474a9cef Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 11 Nov 2020 14:27:57 -0600 Subject: [PATCH 32/61] migrate more from Travis to GHA (#5555) * migrate more from Travis to GHA * actually upload coverage * use cache checks properly * also do coverage * simplify coverage check * refactor a bit * oops * remove unused things in travis * this needs to be stored to the github env... --- .github/workflows/build_openssl.sh | 36 +++++++++++++++ .github/workflows/ci.yml | 72 ++++++++++++++++++++++++++++++ .travis.yml | 50 --------------------- .travis/install.sh | 40 ----------------- .travis/openssl_config.sh | 13 ------ .travis/run.sh | 18 -------- .travis/upload_coverage.sh | 21 --------- 7 files changed, 108 insertions(+), 142 deletions(-) create mode 100755 .github/workflows/build_openssl.sh delete mode 100755 .travis/openssl_config.sh delete mode 100755 .travis/upload_coverage.sh diff --git a/.github/workflows/build_openssl.sh b/.github/workflows/build_openssl.sh new file mode 100755 index 000000000000..d5f23f61aa3a --- /dev/null +++ b/.github/workflows/build_openssl.sh @@ -0,0 +1,36 @@ +#!/bin/bash +set -e +set -x + +shlib_sed() { + # modify the shlib version to a unique one to make sure the dynamic + # linker doesn't load the system one. + sed -i "s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=100/" Makefile + sed -i "s/^SHLIB_MINOR=.*/SHLIB_MINOR=0.0/" Makefile + sed -i "s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=100.0.0/" Makefile +} + +# CONFIG_HASH is a global coming from a previous step +OPENSSL_DIR="${GITHUB_WORKSPACE}/osslcache/${TYPE}-${VERSION}-${CONFIG_HASH}" +if [[ "${TYPE}" == "openssl" ]]; then + curl -O "https://www.openssl.org/source/openssl-${VERSION}.tar.gz" + tar zxf "openssl-${VERSION}.tar.gz" + pushd "openssl-${VERSION}" + # CONFIG_FLAGS is a global coming from a previous step + ./config ${CONFIG_FLAGS} -fPIC --prefix="${OPENSSL_DIR}" + shlib_sed + make depend + make -j"$(nproc)" + # avoid installing the docs on versions of OpenSSL that aren't ancient. + # https://github.com/openssl/openssl/issues/6685#issuecomment-403838728 + make install_sw install_ssldirs + popd +elif [[ "${TYPE}" == "libressl" ]]; then + curl -O "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${VERSION}.tar.gz" + tar zxf "libressl-${VERSION}.tar.gz" + pushd "libressl-${VERSION}" + ./config -Wl -Wl,-Bsymbolic-functions -fPIC shared --prefix="${OPENSSL_DIR}" + shlib_sed + make -j"$(nproc)" install + popd +fi diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a1879f83b490..d4996232b1f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,78 @@ on: - '*.*.*' jobs: + linux: + runs-on: ubuntu-latest + strategy: + matrix: + PYTHON: + - {VERSION: "3.9", TOXENV: "pep8,packaging", COVERAGE: "false"} + - {VERSION: "pypy2", TOXENV: "pypy-nocoverage", COVERAGE: "false"} + - {VERSION: "pypy3", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} + - {VERSION: "2.7", TOXENV: "py27", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} + - {VERSION: "2.7", TOXENV: "py27-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} + - {VERSION: "2.7", TOXENV: "py27", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} + - {VERSION: "3.9", TOXENV: "py39-ssh", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "openssl", VERSION: "1.1.1h", CONFIG_FLAGS: "no-engine no-rc2 no-srtp no-ct"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "2.9.2"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.0.2"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.1.4"}} + - {VERSION: "3.9", TOXENV: "py39", OPENSSL: {TYPE: "libressl", VERSION: "3.2.2"}} + name: "${{ matrix.PYTHON.TOXENV }} ${{ matrix.PYTHON.OPENSSL.TYPE }} ${{ matrix.PYTHON.OPENSSL.VERSION }} ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }}" + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.PYTHON.VERSION }} + - run: git clone --depth=1 https://github.com/google/wycheproof + - run: python -m pip install tox requests coverage + - name: Compute config hash and set config vars + run: | + DEFAULT_CONFIG_FLAGS="shared no-ssl2 no-ssl3" + CONFIG_FLAGS="$DEFAULT_CONFIG_FLAGS $CONFIG_FLAGS" + CONFIG_HASH=$(echo "$CONFIG_FLAGS" | sha1sum | sed 's/ .*$//') + echo "CONFIG_FLAGS=${CONFIG_FLAGS}" >> $GITHUB_ENV + echo "CONFIG_HASH=${CONFIG_HASH}" >> $GITHUB_ENV + echo "OSSL_INFO=${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${CONFIG_FLAGS}" >> $GITHUB_ENV + echo "OSSL_PATH=${{ github.workspace }}/osslcache/${{ matrix.PYTHON.OPENSSL.TYPE }}-${{ matrix.PYTHON.OPENSSL.VERSION }}-${CONFIG_HASH}" >> $GITHUB_ENV + env: + CONFIG_FLAGS: ${{ matrix.PYTHON.OPENSSL.CONFIG_FLAGS }} + if: matrix.PYTHON.OPENSSL + - name: Load cache + uses: actions/cache@v2 + id: ossl-cache + 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 }}-1 + if: matrix.PYTHON.OPENSSL + - name: Build custom OpenSSL/LibreSSL + run: .github/workflows/build_openssl.sh + env: + TYPE: ${{ matrix.PYTHON.OPENSSL.TYPE }} + VERSION: ${{ matrix.PYTHON.OPENSSL.VERSION }} + GITHUB_WORKSPACE: ${{ github.workspace }} + if: matrix.PYTHON.OPENSSL && steps.ossl-cache.outputs.cache-hit != 'true' + - name: Set CFLAGS/LDFLAGS + run: | + echo "CFLAGS=${CFLAGS} -I${OSSL_PATH}/include" >> $GITHUB_ENV + echo "LDFLAGS=${LDFLAGS} -L${OSSL_PATH}/lib -Wl,-rpath=${OSSL_PATH}/lib" >> $GITHUB_ENV + if: matrix.PYTHON.OPENSSL + - name: Tests + run: | + tox -r -- --color=yes --wycheproof-root=wycheproof + env: + TOXENV: ${{ matrix.PYTHON.TOXENV }} + - name: Upload coverage + run: | + curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash + bash codecov.sh -n "tox -e ${{ matrix.PYTHON.TOXENV }} ${{ env.OSSL_INFO }}" + if: matrix.PYTHON.COVERAGE != 'false' + linux-distros: runs-on: ubuntu-latest container: ${{ matrix.IMAGE.IMAGE }} diff --git a/.travis.yml b/.travis.yml index ef5e2d9038cb..03716a386594 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,42 +18,7 @@ branches: matrix: include: - - python: 3.8 - env: TOXENV=pep8,packaging # Setting 'python' is just to make travis's UI a bit prettier - - python: 3.6 - env: TOXENV=py36 - - python: 3.9 - env: TOXENV=py39 - # Travis lists available Pythons (including PyPy) by arch and distro here: - # https://docs.travis-ci.com/user/languages/python/#python-versions - - python: pypy2.7-7.3.1 - env: TOXENV=pypy-nocoverage - - python: pypy3.6-7.3.1 - env: TOXENV=pypy3-nocoverage - - python: 2.7 - env: TOXENV=py27 OPENSSL=1.1.0l - - python: 2.7 - env: TOXENV=py27-ssh OPENSSL=1.1.0l - - python: 3.8 - env: TOXENV=py38 OPENSSL=1.1.0l - - python: 2.7 - env: TOXENV=py27 OPENSSL=1.1.1h - - python: 3.8 - env: TOXENV=py38 OPENSSL=1.1.1h - - python: 3.8 - env: TOXENV=py38 OPENSSL=1.1.1h OPENSSL_CONFIG_FLAGS="no-engine no-rc2 no-srtp no-ct" - - python: 3.8 - env: TOXENV=py38-ssh OPENSSL=1.1.1h - - python: 3.8 - env: TOXENV=py38 LIBRESSL=2.9.2 - - python: 3.8 - env: TOXENV=py38 LIBRESSL=3.0.2 - - python: 3.8 - env: TOXENV=py38 LIBRESSL=3.1.4 - - python: 3.8 - env: TOXENV=py38 LIBRESSL=3.2.2 - - python: 3.8 env: TOXENV=docs addons: @@ -74,18 +39,3 @@ install: script: - ./.travis/run.sh - -after_success: - - ./.travis/upload_coverage.sh - -notifications: - irc: - channels: - # This is set to a secure variable to prevent forks from notifying the - # IRC channel whenever they fail a build. This can be removed when travis - # implements https://github.com/travis-ci/travis-ci/issues/1094. - # The value encrypted here was created via - # travis encrypt "irc.freenode.org#cryptography-dev" - - secure: "A93qvTOlwlMK5WoEvZQ5jQ8Z4Hd0JpeO53WYt8iIJ3s/L6AubkfiN7gwhThRtPnPx7DVMenoKRMlcRg76/ICvXEViVnGgXFjsypF0CzVcIay9pPdjpZjZHP735yLfX512RtxYEdEGwi5r25Z2CEFaydhhxNwfuMxGBtLUjusix4=" - use_notice: true - skip_join: true diff --git a/.travis/install.sh b/.travis/install.sh index ccc7f444dfe8..573399c1c2ab 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -3,46 +3,6 @@ set -e set -x -SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") - -shlib_sed() { - # modify the shlib version to a unique one to make sure the dynamic - # linker doesn't load the system one. - sed -i "s/^SHLIB_MAJOR=.*/SHLIB_MAJOR=100/" Makefile - sed -i "s/^SHLIB_MINOR=.*/SHLIB_MINOR=0.0/" Makefile - sed -i "s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=100.0.0/" Makefile -} - -# download, compile, and install if it's not already present via travis -# cache -if [ -n "${OPENSSL}" ]; then - . "$SCRIPT_DIR/openssl_config.sh" - if [[ ! -f "$HOME/$OPENSSL_DIR/bin/openssl" ]]; then - curl -O "https://www.openssl.org/source/openssl-${OPENSSL}.tar.gz" - tar zxf "openssl-${OPENSSL}.tar.gz" - pushd "openssl-${OPENSSL}" - ./config $OPENSSL_CONFIG_FLAGS -fPIC --prefix="$HOME/$OPENSSL_DIR" - shlib_sed - make depend - make -j"$(nproc)" - # avoid installing the docs on versions of OpenSSL that aren't ancient. - # https://github.com/openssl/openssl/issues/6685#issuecomment-403838728 - make install_sw install_ssldirs - popd - fi -elif [ -n "${LIBRESSL}" ]; then - LIBRESSL_DIR="ossl-2/${LIBRESSL}" - if [[ ! -f "$HOME/$LIBRESSL_DIR/bin/openssl" ]]; then - curl -O "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${LIBRESSL}.tar.gz" - tar zxf "libressl-${LIBRESSL}.tar.gz" - pushd "libressl-${LIBRESSL}" - ./config -Wl -Wl,-Bsymbolic-functions -fPIC shared --prefix="$HOME/$LIBRESSL_DIR" - shlib_sed - make -j"$(nproc)" install - popd - fi -fi - if [ -z "${DOWNSTREAM}" ]; then git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof" fi diff --git a/.travis/openssl_config.sh b/.travis/openssl_config.sh deleted file mode 100755 index 83f16d2bfea8..000000000000 --- a/.travis/openssl_config.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -e -set -x - -DEFAULT_CONFIG_FLAGS="shared no-ssl2 no-ssl3" -if [ -n "${OPENSSL_CONFIG_FLAGS}" ]; then - OPENSSL_CONFIG_FLAGS="$DEFAULT_CONFIG_FLAGS $OPENSSL_CONFIG_FLAGS" -else - OPENSSL_CONFIG_FLAGS=$DEFAULT_CONFIG_FLAGS -fi -CONFIG_HASH=$(echo "$OPENSSL_CONFIG_FLAGS" | sha1sum | sed 's/ .*$//') -OPENSSL_DIR="ossl-2/${OPENSSL}${CONFIG_HASH}" diff --git a/.travis/run.sh b/.travis/run.sh index 313fb86b6d8d..41fc4a49a0d7 100755 --- a/.travis/run.sh +++ b/.travis/run.sh @@ -1,23 +1,5 @@ #!/bin/bash -ex -SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}") - -if [ -n "${LIBRESSL}" ]; then - LIBRESSL_DIR="ossl-2/${LIBRESSL}" - export CFLAGS="-Werror -Wno-error=deprecated-declarations -Wno-error=discarded-qualifiers -Wno-error=unused-function -I$HOME/$LIBRESSL_DIR/include" - export PATH="$HOME/$LIBRESSL_DIR/bin:$PATH" - export LDFLAGS="-L$HOME/$LIBRESSL_DIR/lib -Wl,-rpath=$HOME/$LIBRESSL_DIR/lib" -fi - -if [ -n "${OPENSSL}" ]; then - . "$SCRIPT_DIR/openssl_config.sh" - export PATH="$HOME/$OPENSSL_DIR/bin:$PATH" - export CFLAGS="${CFLAGS} -I$HOME/$OPENSSL_DIR/include" - # rpath on linux will cause it to use an absolute path so we don't need to - # do LD_LIBRARY_PATH - export LDFLAGS="-L$HOME/$OPENSSL_DIR/lib -Wl,-rpath=$HOME/$OPENSSL_DIR/lib" -fi - source ~/.venv/bin/activate if [ -n "${TOXENV}" ]; then diff --git a/.travis/upload_coverage.sh b/.travis/upload_coverage.sh deleted file mode 100755 index 28251f8ba010..000000000000 --- a/.travis/upload_coverage.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -set -e -set -x - -if [ -n "${TOXENV}" ]; then - case "${TOXENV}" in - pypy-nocoverage);; - pypy3-nocoverage);; - pep8);; - py3pep8);; - docs);; - *) - source ~/.venv/bin/activate - curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash - - bash codecov.sh -Z -e TRAVIS_OS_NAME,TOXENV,OPENSSL || \ - bash codecov.sh -Z -e TRAVIS_OS_NAME,TOXENV,OPENSSL - ;; - esac -fi From ce9645a9c75acb954709ce952931129c0f4fa345 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 11 Nov 2020 16:37:42 -0500 Subject: [PATCH 33/61] garbage collect dead code (#5562) --- src/_cffi_src/openssl/crypto.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/_cffi_src/openssl/crypto.py b/src/_cffi_src/openssl/crypto.py index 6284f0579582..6064a4eeea99 100644 --- a/src/_cffi_src/openssl/crypto.py +++ b/src/_cffi_src/openssl/crypto.py @@ -27,10 +27,6 @@ FUNCTIONS = """ void OPENSSL_cleanup(void); -/* as of 1.1.0 OpenSSL does its own locking *angelic chorus*. This function - is now a noop macro. We can delete this once we drop 1.0.2 support. */ -void (*CRYPTO_get_locking_callback(void))(int, int, const char *, int); - /* SSLeay was removed in 1.1.0 */ unsigned long SSLeay(void); const char *SSLeay_version(int); From a07da37f14fdd8e856bfef78bf81b46faff335c4 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 11 Nov 2020 17:56:58 -0600 Subject: [PATCH 34/61] port docs and docs-linkcheck (#5563) * port docs and docs-linkcheck * allow linkcheck if the commit msg says linkcheck combine docs job into lint jobs * can't get the commit msg at this time on a PR --- .github/workflows/ci.yml | 17 ++++++++++++++++- .travis.yml | 10 ---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d4996232b1f7..19922890677c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: PYTHON: - - {VERSION: "3.9", TOXENV: "pep8,packaging", COVERAGE: "false"} + - {VERSION: "3.9", TOXENV: "pep8,packaging,docs", COVERAGE: "false"} - {VERSION: "pypy2", TOXENV: "pypy-nocoverage", COVERAGE: "false"} - {VERSION: "pypy3", TOXENV: "pypy3-nocoverage", COVERAGE: "false"} - {VERSION: "2.7", TOXENV: "py27", OPENSSL: {TYPE: "openssl", VERSION: "1.1.0l"}} @@ -230,3 +230,18 @@ jobs: - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install - run: pip install . - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run + + docs-linkcheck: + if: github.event_name == 'push' && github.ref == 'refs/heads/master' + runs-on: ubuntu-latest + name: "linkcheck" + steps: + - uses: actions/checkout@v2 + - name: Setup python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + - run: python -m pip install -U tox + - run: tox -r -- --color=yes + env: + TOXENV: docs-linkcheck diff --git a/.travis.yml b/.travis.yml index 03716a386594..873a432cd650 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,16 +19,6 @@ branches: matrix: include: # Setting 'python' is just to make travis's UI a bit prettier - - python: 3.8 - env: TOXENV=docs - addons: - apt: - packages: - - libenchant-dev - - python: 3.8 - env: TOXENV=docs-linkcheck - if: (branch = master AND type != pull_request) OR commit_message =~ /linkcheck/ - # TODO: This needs to be moved to GHA, but it fails there. The # confusing part is why it passes on Travis! - python: 3.7 From 9e081513a09035cf2710e84bfc96b8f5a0a611d0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 11 Nov 2020 19:49:28 -0500 Subject: [PATCH 35/61] Garbage collect more CI code (#5564) --- .travis/install.sh | 4 ---- .travis/run.sh | 16 ++++++---------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/.travis/install.sh b/.travis/install.sh index 573399c1c2ab..4109cd135237 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -3,10 +3,6 @@ set -e set -x -if [ -z "${DOWNSTREAM}" ]; then - git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof" -fi - pip install -U pip pip install virtualenv diff --git a/.travis/run.sh b/.travis/run.sh index 41fc4a49a0d7..1b9200b9e4c8 100755 --- a/.travis/run.sh +++ b/.travis/run.sh @@ -2,14 +2,10 @@ source ~/.venv/bin/activate -if [ -n "${TOXENV}" ]; then - tox -- --wycheproof-root="$HOME/wycheproof" -else - downstream_script="${TRAVIS_BUILD_DIR}/.travis/downstream.d/${DOWNSTREAM}.sh" - if [ ! -x "$downstream_script" ]; then - exit 1 - fi - $downstream_script install - pip install . - $downstream_script run +downstream_script="${TRAVIS_BUILD_DIR}/.travis/downstream.d/${DOWNSTREAM}.sh" +if [ ! -x "$downstream_script" ]; then + exit 1 fi +$downstream_script install +pip install . +$downstream_script run From 548b1b2d40f6ab94072871deb90e29e05dc520c4 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 12 Nov 2020 12:31:10 -0500 Subject: [PATCH 36/61] Added python2 removal to the changelog (#5567) * Added python2 removal to the changelog * Update CHANGELOG.rst --- CHANGELOG.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b001ec266c6a..3ea22fd0aa30 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,8 @@ Changelog 64-bit to 1024-bit (8 byte to 128 byte) initialization vectors. This change is to conform with an upcoming OpenSSL release that will no longer support sizes outside this window. +* Python 2 support is deprecated in ``cryptography``. This is the last release + that will support Python 2. .. _v3-2-1: From eb02f2127f427dcb53d7ca2b0918844ecf5ca872 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 13 Nov 2020 11:13:30 -0500 Subject: [PATCH 37/61] Update artifact name for changes from pyca-infra (#5569) --- .github/workflows/ci.yml | 6 +++--- .github/workflows/download_openssl.py | 1 + .github/workflows/wheel-builder.yml | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 19922890677c..a0c1625b74fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -140,14 +140,14 @@ jobs: - name: Download OpenSSL run: | - python .github/workflows/download_openssl.py macos openssl-macos + python .github/workflows/download_openssl.py macos openssl-macos-x86-64 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Tests run: | CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS=1 \ - LDFLAGS="${HOME}/openssl-macos/lib/libcrypto.a ${HOME}/openssl-macos/lib/libssl.a" \ - CFLAGS="-I${HOME}/openssl-macos/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -Wno-error=unused-command-line-argument -mmacosx-version-min=10.10 -march=core2 $EXTRA_CFLAGS" \ + LDFLAGS="${HOME}/openssl-macos-x86-64/lib/libcrypto.a ${HOME}/openssl-macos-x86-64/lib/libssl.a" \ + CFLAGS="-I${HOME}/openssl-macos-x86-64/include -Werror -Wno-error=deprecated-declarations -Wno-error=incompatible-pointer-types-discards-qualifiers -Wno-error=unused-function -Wno-error=unused-command-line-argument -mmacosx-version-min=10.10 -march=core2 $EXTRA_CFLAGS" \ tox -r -- --color=yes --wycheproof-root=wycheproof env: TOXENV: ${{ matrix.PYTHON.TOXENV }} diff --git a/.github/workflows/download_openssl.py b/.github/workflows/download_openssl.py index 1d5e3bfb471a..46b3b7f0ee02 100644 --- a/.github/workflows/download_openssl.py +++ b/.github/workflows/download_openssl.py @@ -67,6 +67,7 @@ def main(platform, target): os.path.join(path, artifact["name"]) ) return + raise ValueError("Didn't find {} in {}".format(target, response)) if __name__ == "__main__": diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index c4bf9ab057d3..b74edc2da5a4 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -76,7 +76,7 @@ jobs: - run: ${{ matrix.PYTHON.BIN_PATH }} -m pip install -U virtualenv requests - name: Download OpenSSL run: | - ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos + ${{ matrix.PYTHON.BIN_PATH }} .github/workflows/download_openssl.py macos openssl-macos-x86-64 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -92,8 +92,8 @@ jobs: cd cryptography* CRYPTOGRAPHY_SUPPRESS_LINK_FLAGS="1" \ - LDFLAGS="${HOME}/openssl-macos/lib/libcrypto.a ${HOME}/openssl-macos/lib/libssl.a" \ - CFLAGS="-I${HOME}/openssl-macos/include -mmacosx-version-min=10.10 -march=core2" \ + LDFLAGS="${HOME}/openssl-macos-x86-64/lib/libcrypto.a ${HOME}/openssl-macos-x86-64/lib/libssl.a" \ + CFLAGS="-I${HOME}/openssl-macos-x86-64/include -mmacosx-version-min=10.10 -march=core2" \ ../venv/bin/python setup.py bdist_wheel $PY_LIMITED_API && mv dist/cryptography*.whl ../wheelhouse - run: venv/bin/pip install -f wheelhouse --no-index cryptography - run: | From 488cd740bb9502af7faad79c0575c5454045e0d0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 13 Nov 2020 12:25:43 -0500 Subject: [PATCH 38/61] Remove two linkcheck ignores (#5570) --- docs/conf.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 87e2b5869c6c..33240d8de1a3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -199,8 +199,4 @@ 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", - # 403ing from Travis - r"https://devblogs.microsoft.com/oldnewthing/\?p=4223", - # Incomplete cert chain - r"https://cveform.mitre.org/", ] From d22bdc87eede21e5ed592c1194e6a7002ef8a76a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 13 Nov 2020 19:55:05 -0500 Subject: [PATCH 39/61] Move paramiko job to github actions (#5565) --- {.travis => .github}/downstream.d/paramiko.sh | 0 .github/workflows/ci.yml | 2 ++ .travis.yml | 31 ------------------- .travis/install.sh | 12 ------- .travis/run.sh | 11 ------- MANIFEST.in | 2 -- README.rst | 3 -- tox.ini | 2 +- 8 files changed, 3 insertions(+), 60 deletions(-) rename {.travis => .github}/downstream.d/paramiko.sh (100%) delete mode 100644 .travis.yml delete mode 100755 .travis/install.sh delete mode 100755 .travis/run.sh diff --git a/.travis/downstream.d/paramiko.sh b/.github/downstream.d/paramiko.sh similarity index 100% rename from .travis/downstream.d/paramiko.sh rename to .github/downstream.d/paramiko.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0c1625b74fb..f786bd600c06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -213,6 +213,7 @@ jobs: strategy: matrix: DOWNSTREAM: + - paramiko - pyopenssl - twisted - aws-encryption-sdk @@ -228,6 +229,7 @@ jobs: python-version: 3.7 - run: python -m pip install -U pip wheel - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh install + - run: pip uninstall -y enum34 - run: pip install . - run: ./.github/downstream.d/${{ matrix.DOWNSTREAM }}.sh run diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 873a432cd650..000000000000 --- a/.travis.yml +++ /dev/null @@ -1,31 +0,0 @@ -sudo: true -dist: focal - -language: python - -cache: - directories: - - $HOME/.cache/pip - - $HOME/ossl-2/ - -# Only build master, the version branches (e.g. 1.7.x), and -# version tags (which are apparently considered branches by travis) -branches: - only: - - master - - /^\d+\.\d+\.x$/ - - /^\d+\.\d+(\.\d+)?$/ - -matrix: - include: - # Setting 'python' is just to make travis's UI a bit prettier - # TODO: This needs to be moved to GHA, but it fails there. The - # confusing part is why it passes on Travis! - - python: 3.7 - env: DOWNSTREAM=paramiko - -install: - - ./.travis/install.sh - -script: - - ./.travis/run.sh diff --git a/.travis/install.sh b/.travis/install.sh deleted file mode 100755 index 4109cd135237..000000000000 --- a/.travis/install.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e -set -x - -pip install -U pip -pip install virtualenv - -python -m virtualenv ~/.venv -source ~/.venv/bin/activate -# If we pin coverage it must be kept in sync with tox.ini and .github/workflows/ci.yml -pip install tox coverage diff --git a/.travis/run.sh b/.travis/run.sh deleted file mode 100755 index 1b9200b9e4c8..000000000000 --- a/.travis/run.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/bin/bash -ex - -source ~/.venv/bin/activate - -downstream_script="${TRAVIS_BUILD_DIR}/.travis/downstream.d/${DOWNSTREAM}.sh" -if [ ! -x "$downstream_script" ]; then - exit 1 -fi -$downstream_script install -pip install . -$downstream_script run diff --git a/MANIFEST.in b/MANIFEST.in index 2b90d2465543..5c82725a4148 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -16,8 +16,6 @@ recursive-include tests *.py exclude vectors recursive-exclude vectors * -exclude .travis.yml .travis -recursive-exclude .travis * recursive-exclude .github * exclude release.py .coveragerc codecov.yml .readthedocs.yml dev-requirements.txt rtd-requirements.txt tox.ini diff --git a/README.rst b/README.rst index 586cb1b0b3bc..10de198b8af4 100644 --- a/README.rst +++ b/README.rst @@ -9,9 +9,6 @@ pyca/cryptography :target: https://cryptography.io :alt: Latest Docs -.. image:: https://travis-ci.org/pyca/cryptography.svg?branch=master - :target: https://travis-ci.org/pyca/cryptography - .. image:: https://github.com/pyca/cryptography/workflows/CI/badge.svg?branch=master :target: https://github.com/pyca/cryptography/actions?query=workflow%3ACI+branch%3Amaster diff --git a/tox.ini b/tox.ini index 2ecd30a222bb..e6e04575bbc6 100644 --- a/tox.ini +++ b/tox.ini @@ -8,7 +8,7 @@ extras = test ssh: ssh deps = - # This must be kept in sync with .travis/install.sh and .github/workflows/ci.yml + # This must be kept in sync with .github/workflows/ci.yml coverage ./vectors randomorder: pytest-randomly From 239fddf2d97088251a5c5b1a5ee7306319776898 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 19 Nov 2020 14:07:47 -0500 Subject: [PATCH 40/61] Polish up the fernet limitations language (#5577) --- docs/fernet.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/fernet.rst b/docs/fernet.rst index 960f47137850..5e2655d3a72b 100644 --- a/docs/fernet.rst +++ b/docs/fernet.rst @@ -274,8 +274,9 @@ Limitations ----------- Fernet is ideal for encrypting data that easily fits in memory. As a design -feature it does not expose unauthenticated bytes. Unfortunately, this makes it -generally unsuitable for very large files at this time. +feature it does not expose unauthenticated bytes. This means that the complete +message contents must be available in memory, making Fernet generally +unsuitable for very large files at this time. .. _`Fernet`: https://github.com/fernet/spec/ From fd582e8913a4c061ea35025a528331f9ac851651 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 20 Nov 2020 00:48:13 -0500 Subject: [PATCH 41/61] Debian sid has python 3.9 now (#5580) --- .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 f786bd600c06..5c2ed80871e4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -94,7 +94,7 @@ jobs: - {IMAGE: "pyca/cryptography-runner-stretch", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py38"} - - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-ubuntu-bionic", TOXENV: "py36"} - {IMAGE: "pyca/cryptography-runner-ubuntu-focal", TOXENV: "py38"} - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py27"} From 2b85c4d9156ab4bd44e55b2843bd1233a7a5d9ef Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Fri, 20 Nov 2020 12:22:47 -0500 Subject: [PATCH 42/61] Simplify wycheproof pytest code (#5579) --- tests/conftest.py | 4 +--- tests/utils.py | 7 ------- tests/wycheproof/test_utils.py | 11 +---------- 3 files changed, 2 insertions(+), 20 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 4e3124fa76ea..ece7a11e716a 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -11,7 +11,6 @@ from .utils import ( check_backend_support, load_wycheproof_tests, - skip_if_wycheproof_none, ) @@ -30,8 +29,7 @@ def pytest_addoption(parser): def pytest_generate_tests(metafunc): if "wycheproof" in metafunc.fixturenames: - wycheproof = metafunc.config.getoption("--wycheproof-root") - skip_if_wycheproof_none(wycheproof) + wycheproof = metafunc.config.getoption("--wycheproof-root", skip=True) testcases = [] marker = metafunc.definition.get_closest_marker("wycheproof_tests") diff --git a/tests/utils.py b/tests/utils.py index 5d98af00e337..497fde83f0a5 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -906,13 +906,6 @@ def has_flag(self, flag): return flag in self.testcase["flags"] -def skip_if_wycheproof_none(wycheproof): - # This is factored into its own function so we can easily test both - # branches - if wycheproof is None: - pytest.skip("--wycheproof-root not provided") - - def load_wycheproof_tests(wycheproof, test_file): path = os.path.join(wycheproof, "testvectors", test_file) with open(path) as f: diff --git a/tests/wycheproof/test_utils.py b/tests/wycheproof/test_utils.py index 2cf3be08e97c..593d26bdec91 100644 --- a/tests/wycheproof/test_utils.py +++ b/tests/wycheproof/test_utils.py @@ -4,18 +4,9 @@ from __future__ import absolute_import, division, print_function -import pytest - -from ..utils import WycheproofTest, skip_if_wycheproof_none +from ..utils import WycheproofTest def test_wycheproof_test_repr(): wycheproof = WycheproofTest({}, {}, {"tcId": 3}) assert repr(wycheproof) == "" - - -def test_skip_if_wycheproof_none(): - with pytest.raises(pytest.skip.Exception): - skip_if_wycheproof_none(None) - - skip_if_wycheproof_none("abc") From 21144be3049bfe567eed0f2e59027fe5d5489ca5 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 21 Nov 2020 20:38:08 -0500 Subject: [PATCH 43/61] Simplify CI scripts (#5582) --- .github/workflows/build_openssl.sh | 8 +++----- .github/workflows/ci.yml | 1 - 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build_openssl.sh b/.github/workflows/build_openssl.sh index d5f23f61aa3a..99c3f4d33805 100755 --- a/.github/workflows/build_openssl.sh +++ b/.github/workflows/build_openssl.sh @@ -10,18 +10,16 @@ shlib_sed() { sed -i "s/^SHLIB_VERSION_NUMBER=.*/SHLIB_VERSION_NUMBER=100.0.0/" Makefile } -# CONFIG_HASH is a global coming from a previous step -OPENSSL_DIR="${GITHUB_WORKSPACE}/osslcache/${TYPE}-${VERSION}-${CONFIG_HASH}" if [[ "${TYPE}" == "openssl" ]]; then curl -O "https://www.openssl.org/source/openssl-${VERSION}.tar.gz" tar zxf "openssl-${VERSION}.tar.gz" pushd "openssl-${VERSION}" # CONFIG_FLAGS is a global coming from a previous step - ./config ${CONFIG_FLAGS} -fPIC --prefix="${OPENSSL_DIR}" + ./config ${CONFIG_FLAGS} -fPIC --prefix="${OSSL_PATH}" shlib_sed make depend make -j"$(nproc)" - # avoid installing the docs on versions of OpenSSL that aren't ancient. + # avoid installing the docs (for performance) # https://github.com/openssl/openssl/issues/6685#issuecomment-403838728 make install_sw install_ssldirs popd @@ -29,7 +27,7 @@ elif [[ "${TYPE}" == "libressl" ]]; then curl -O "https://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${VERSION}.tar.gz" tar zxf "libressl-${VERSION}.tar.gz" pushd "libressl-${VERSION}" - ./config -Wl -Wl,-Bsymbolic-functions -fPIC shared --prefix="${OPENSSL_DIR}" + ./config -Wl -Wl,-Bsymbolic-functions -fPIC shared --prefix="${OSSL_PATH}" shlib_sed make -j"$(nproc)" install popd diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5c2ed80871e4..2cd2d9c0149d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,6 @@ jobs: env: TYPE: ${{ matrix.PYTHON.OPENSSL.TYPE }} VERSION: ${{ matrix.PYTHON.OPENSSL.VERSION }} - GITHUB_WORKSPACE: ${{ github.workspace }} if: matrix.PYTHON.OPENSSL && steps.ossl-cache.outputs.cache-hit != 'true' - name: Set CFLAGS/LDFLAGS run: | From 5cd265aca0e90675ccf7e93bd900c9845fe7878b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 23 Nov 2020 19:33:44 -0500 Subject: [PATCH 44/61] Start refactoring github actions to reduce duplication (#5583) --- .github/actions/upload-coverage/action.yml | 19 +++++++++++++++ .github/workflows/ci.yml | 28 ++++++++++------------ 2 files changed, 31 insertions(+), 16 deletions(-) create mode 100644 .github/actions/upload-coverage/action.yml diff --git a/.github/actions/upload-coverage/action.yml b/.github/actions/upload-coverage/action.yml new file mode 100644 index 000000000000..11d97a7a614d --- /dev/null +++ b/.github/actions/upload-coverage/action.yml @@ -0,0 +1,19 @@ +name: Upload Coverage +description: Upload coverage to codecov + +inputs: + name: + description: "Job name" + required: true + +runs: + using: "composite" + + steps: + - run: | + curl -o codecov.sh -f https://codecov.io/bash || \ + curl -o codecov.sh -f https://codecov.io/bash || \ + curl -o codecov.sh -f https://codecov.io/bash + + bash codecov.sh -n "${{ inputs.name }}" + shell: bash diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2cd2d9c0149d..10f9eb47d326 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,10 +75,9 @@ jobs: tox -r -- --color=yes --wycheproof-root=wycheproof env: TOXENV: ${{ matrix.PYTHON.TOXENV }} - - name: Upload coverage - run: | - curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash - bash codecov.sh -n "tox -e ${{ matrix.PYTHON.TOXENV }} ${{ env.OSSL_INFO }}" + - uses: ./.github/actions/upload-coverage + with: + name: "tox -e ${{ matrix.PYTHON.TOXENV }} ${{ env.OSSL_INFO }}" if: matrix.PYTHON.COVERAGE != 'false' linux-distros: @@ -112,10 +111,9 @@ jobs: - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' env: TOXENV: ${{ matrix.IMAGE.TOXENV }} - - name: Upload coverage - run: | - curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash - bash codecov.sh -n "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }} ${{ matrix.IMAGE.ENV }}" + - uses: ./.github/actions/upload-coverage + with: + name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }} ${{ matrix.IMAGE.ENV }}" macos: runs-on: macos-latest @@ -152,10 +150,9 @@ jobs: TOXENV: ${{ matrix.PYTHON.TOXENV }} EXTRA_CFLAGS: ${{ matrix.PYTHON.EXTRA_CFLAGS }} - - name: Upload coverage - run: | - curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash - bash codecov.sh -n "Python ${{ matrix.PYTHON.VERSION }} on macOS" + - uses: ./.github/actions/upload-coverage + with: + name: "Python ${{ matrix.PYTHON.VERSION }} on macOS" windows: runs-on: windows-latest @@ -202,10 +199,9 @@ jobs: env: TOXENV: ${{ matrix.PYTHON.TOXENV }} - - name: Upload coverage - run: | - curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash || curl -o codecov.sh -f https://codecov.io/bash - bash codecov.sh -n "Python ${{ matrix.PYTHON.VERSION }} on ${{ matrix.WINDOWS.WINDOWS }}" + - uses: ./.github/actions/upload-coverage + with: + name: "Python ${{ matrix.PYTHON.VERSION }} on ${{ matrix.WINDOWS.WINDOWS }}" linux-downstream: runs-on: ubuntu-latest From 417f684f6109357a97eee013de7d10fade25bdf7 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 26 Nov 2020 11:10:44 -0600 Subject: [PATCH 45/61] in OpenSSL 1.1.0+ error strings are automatically loaded (#5587) --- src/cryptography/hazmat/bindings/openssl/binding.py | 2 -- tests/hazmat/backends/test_openssl.py | 5 ----- 2 files changed, 7 deletions(-) diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py index 6593bf1dc1b1..7a84a340e43b 100644 --- a/src/cryptography/hazmat/bindings/openssl/binding.py +++ b/src/cryptography/hazmat/bindings/openssl/binding.py @@ -139,8 +139,6 @@ def _ensure_ffi_initialized(cls): cls.lib.SSL_library_init() # adds all ciphers/digests for EVP cls.lib.OpenSSL_add_all_algorithms() - # loads error strings for libcrypto and libssl functions - cls.lib.SSL_load_error_strings() cls._register_osrandom_engine() @classmethod diff --git a/tests/hazmat/backends/test_openssl.py b/tests/hazmat/backends/test_openssl.py index e4bf7f97c6f5..eab868fad3a6 100644 --- a/tests/hazmat/backends/test_openssl.py +++ b/tests/hazmat/backends/test_openssl.py @@ -127,11 +127,6 @@ def test_evp_ciphers_registered(self): cipher = backend._lib.EVP_get_cipherbyname(b"aes-256-cbc") assert cipher != backend._ffi.NULL - def test_error_strings_loaded(self): - buf = backend._ffi.new("char[]", 256) - backend._lib.ERR_error_string_n(101183626, buf, len(buf)) - assert b"data not multiple of block length" in backend._ffi.string(buf) - def test_unknown_error_in_cipher_finalize(self): cipher = Cipher(AES(b"\0" * 16), CBC(b"\0" * 16), backend=backend) enc = cipher.encryptor() From d890e2a60616af098d6ec1d4e4a53cc82a335731 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 26 Nov 2020 11:52:47 -0600 Subject: [PATCH 46/61] define OAEP properties for all openssl versions (#5589) In 3.0 these aren't macros so we can't test this way. All our supported OpenSSLs have these bindings now and LibreSSL does not. --- src/_cffi_src/openssl/rsa.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/_cffi_src/openssl/rsa.py b/src/_cffi_src/openssl/rsa.py index 9298226bb223..92b8fa4600d8 100644 --- a/src/_cffi_src/openssl/rsa.py +++ b/src/_cffi_src/openssl/rsa.py @@ -48,17 +48,13 @@ """ CUSTOMIZATIONS = """ -#if defined(EVP_PKEY_CTX_set_rsa_oaep_md) +#if !CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_RSA_OAEP_MD = 1; -#else -static const long Cryptography_HAS_RSA_OAEP_MD = 0; -int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL; -#endif - -#if defined(EVP_PKEY_CTX_set0_rsa_oaep_label) static const long Cryptography_HAS_RSA_OAEP_LABEL = 1; #else +static const long Cryptography_HAS_RSA_OAEP_MD = 0; static const long Cryptography_HAS_RSA_OAEP_LABEL = 0; +int (*EVP_PKEY_CTX_set_rsa_oaep_md)(EVP_PKEY_CTX *, EVP_MD *) = NULL; int (*EVP_PKEY_CTX_set0_rsa_oaep_label)(EVP_PKEY_CTX *, unsigned char *, int) = NULL; #endif From ac4c22168f196921bfe00348250ff138e64bcd37 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 26 Nov 2020 13:07:25 -0600 Subject: [PATCH 47/61] Reduce granularity of error msging when deserializing keys (#5588) * Reduce granularity of error msging when deserializing keys In OpenSSL 3.0 it is no longer possible to determine whether the reason a key failed to deserialize is because of an unsupported cipher. Since we want to be more resilient to OpenSSL error code instability we'll just remove these paths. * black * changelog and update docs --- CHANGELOG.rst | 4 +++ .../primitives/asymmetric/serialization.rst | 8 +++--- .../hazmat/backends/openssl/backend.py | 26 +++++++------------ tests/hazmat/primitives/test_serialization.py | 7 +++-- 4 files changed, 19 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3ea22fd0aa30..1f1ffd99589b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -16,6 +16,10 @@ Changelog 64-bit to 1024-bit (8 byte to 128 byte) initialization vectors. This change is to conform with an upcoming OpenSSL release that will no longer support sizes outside this window. +* **BACKWARDS INCOMPATIBLE:** When deserializing asymmetric keys we now + raise ``ValueError`` rather than ``UnsupportedAlgorithm`` when an + unsupported cipher is used. This change is to conform with an upcoming + OpenSSL release that will no longer distinguish between error types. * Python 2 support is deprecated in ``cryptography``. This is the last release that will support Python 2. diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 6b2e858db9af..8811646045f6 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -158,8 +158,7 @@ all begin with ``-----BEGIN {format}-----`` and end with ``-----END password was supplied. :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key - is of a type that is not supported by the backend or if the key is - encrypted with a symmetric cipher that is not supported by the backend. + is of a type that is not supported by the backend. .. function:: load_pem_public_key(data, backend=None) @@ -267,9 +266,8 @@ the rest. not encrypted. Or if the key was encrypted but no password was supplied. - :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key is of a type that - is not supported by the backend or if the key is encrypted with a - symmetric cipher that is not supported by the backend. + :raises cryptography.exceptions.UnsupportedAlgorithm: If the serialized key + is of a type that is not supported by the backend. .. doctest:: diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index f2b7230bbaa7..e3b5718f2efb 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1491,8 +1491,11 @@ def _handle_key_loading_error(self): errors = self._consume_errors() if not errors: - raise ValueError("Could not deserialize key data.") - + raise ValueError( + "Could not deserialize key data. The data may be in an " + "incorrect format or it may be encrypted with an unsupported " + "algorithm." + ) elif errors[0]._lib_reason_match( self._lib.ERR_LIB_EVP, self._lib.EVP_R_BAD_DECRYPT ) or errors[0]._lib_reason_match( @@ -1501,16 +1504,6 @@ def _handle_key_loading_error(self): ): raise ValueError("Bad decrypt. Incorrect password?") - elif errors[0]._lib_reason_match( - self._lib.ERR_LIB_EVP, self._lib.EVP_R_UNKNOWN_PBE_ALGORITHM - ) or errors[0]._lib_reason_match( - self._lib.ERR_LIB_PEM, self._lib.PEM_R_UNSUPPORTED_ENCRYPTION - ): - raise UnsupportedAlgorithm( - "PEM data is encrypted with an unsupported cipher", - _Reasons.UNSUPPORTED_CIPHER, - ) - elif any( error._lib_reason_match( self._lib.ERR_LIB_EVP, @@ -1521,12 +1514,11 @@ def _handle_key_loading_error(self): raise ValueError("Unsupported public key algorithm.") else: - assert errors[0].lib in ( - self._lib.ERR_LIB_EVP, - self._lib.ERR_LIB_PEM, - self._lib.ERR_LIB_ASN1, + raise ValueError( + "Could not deserialize key data. The data may be in an " + "incorrect format or it may be encrypted with an unsupported " + "algorithm." ) - raise ValueError("Could not deserialize key data.") def elliptic_curve_supported(self, curve): try: diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 2f56711d5dab..c21a4fa5ee35 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -13,7 +13,7 @@ import six -from cryptography.exceptions import UnsupportedAlgorithm, _Reasons +from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.backends.interfaces import ( DERSerializationBackend, DSABackend, @@ -55,7 +55,6 @@ load_vectors_from_file, ) from ...doubles import DummyKeySerializationEncryption -from ...utils import raises_unsupported_algorithm def _skip_fips_format(key_path, password, backend): @@ -771,7 +770,7 @@ def test_unsupported_key_encryption(self, backend): password = b"password" - with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + with pytest.raises(ValueError): load_pem_private_key(key_data, password, backend) def test_corrupt_pkcs8_format(self, backend): @@ -966,7 +965,7 @@ def test_load_bad_oid_key(self, key_file, password, backend): ("key_file", "password"), [("bad-encryption-oid.pem", b"password")] ) def test_load_bad_encryption_oid_key(self, key_file, password, backend): - with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_CIPHER): + with pytest.raises(ValueError): load_vectors_from_file( os.path.join("asymmetric", "PKCS8", key_file), lambda pemfile: load_pem_private_key( From fd7ed6704087f1d71781e48e6c268341429b3abc Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Thu, 26 Nov 2020 14:13:47 -0600 Subject: [PATCH 48/61] don't require errors to be on the stack when loading a key (#5590) In OpenSSL 3.0.0 no error is added in many cases for this path and since we don't do anything with the error anyway we should just consume and move on --- src/cryptography/hazmat/backends/openssl/backend.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index e3b5718f2efb..7f4ff2a3e2e2 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -1459,8 +1459,7 @@ def _load_key(self, openssl_read_func, convert_func, data, password): if evp_pkey == self._ffi.NULL: if userdata.error != 0: - errors = self._consume_errors() - self.openssl_assert(errors) + self._consume_errors() if userdata.error == -1: raise TypeError( "Password was not given but private key is encrypted" From 4645f02c25d7d336a6d922e428c72beb55fb04cb Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 29 Nov 2020 10:01:16 -0600 Subject: [PATCH 49/61] disallow p less than 512-bit on DH (#5592) * disallow p less than 512-bit on DH OpenSSL 3.0.0 enforces this so we'll go ahead and enforce it everywhere that's practical for us. (Note that we do not enforce on deserializing PKCS1/PKCS8 keys in < 3.0.0, but this PR adds a test so that in the 3.0.0 support branch we can test an error path) * missing test * black * _MIN_MODULUS_SIZE is now a thing * skip on fips --- CHANGELOG.rst | 5 ++ docs/development/test-vectors.rst | 2 + .../hazmat/backends/openssl/backend.py | 9 +- .../hazmat/primitives/asymmetric/dh.py | 8 ++ tests/hazmat/primitives/test_dh.py | 84 +++++++++++++------ .../asymmetric/DH/dh_key_256.pem | 4 + 6 files changed, 84 insertions(+), 28 deletions(-) create mode 100644 vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 1f1ffd99589b..e9ea92a84756 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,11 @@ Changelog raise ``ValueError`` rather than ``UnsupportedAlgorithm`` when an unsupported cipher is used. This change is to conform with an upcoming OpenSSL release that will no longer distinguish between error types. +* **BACKWARDS INCOMPATIBLE:** We no longer allow loading of finite field + Diffie-Hellman parameters of less than 512 bits in length. This change is to + conform with an upcoming OpenSSL release that no longer supports smaller + sizes. These keys were already wildly insecure and should not have been used + in any application outside of testing. * Python 2 support is deprecated in ``cryptography``. This is the last release that will support Python 2. diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst index 6146c9c139b9..f952337e2347 100644 --- a/docs/development/test-vectors.rst +++ b/docs/development/test-vectors.rst @@ -184,6 +184,8 @@ Key exchange ``vectors/cryptography_vectors/asymmetric/DH/dhkey_rfc5114_2.der`` and ``vectors/cryptography_vectors/asymmetric/DH/dhpub_rfc5114_2.der`` contains are the above parameters and keys in DER format. +* ``vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem`` contains + a PEM PKCS8 encoded DH key with a 256-bit key size. * ``vectors/cryptoraphy_vectors/asymmetric/ECDH/brainpool.txt`` contains Brainpool vectors from :rfc:`7027`. diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py index 7f4ff2a3e2e2..45d4a1a1eec9 100644 --- a/src/cryptography/hazmat/backends/openssl/backend.py +++ b/src/cryptography/hazmat/backends/openssl/backend.py @@ -117,6 +117,7 @@ from cryptography.hazmat.bindings.openssl import binding from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( + dh, dsa, ec, ed25519, @@ -2086,8 +2087,12 @@ def _parameter_bytes(self, encoding, format, cdata): return self._read_mem_bio(bio) def generate_dh_parameters(self, generator, key_size): - if key_size < 512: - raise ValueError("DH key_size must be at least 512 bits") + if key_size < dh._MIN_MODULUS_SIZE: + raise ValueError( + "DH key_size must be at least {} bits".format( + dh._MIN_MODULUS_SIZE + ) + ) if generator not in (2, 5): raise ValueError("DH generator must be 2 or 5") diff --git a/src/cryptography/hazmat/primitives/asymmetric/dh.py b/src/cryptography/hazmat/primitives/asymmetric/dh.py index cd9fbfab4600..74a311d5015a 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/dh.py +++ b/src/cryptography/hazmat/primitives/asymmetric/dh.py @@ -12,6 +12,9 @@ from cryptography.hazmat.backends import _get_backend +_MIN_MODULUS_SIZE = 512 + + def generate_parameters(generator, key_size, backend=None): backend = _get_backend(backend) return backend.generate_dh_parameters(generator, key_size) @@ -95,6 +98,11 @@ def __init__(self, p, g, q=None): if g < 2: raise ValueError("DH generator must be 2 or greater") + if p.bit_length() < _MIN_MODULUS_SIZE: + raise ValueError( + "p (modulus) must be at least {}-bit".format(_MIN_MODULUS_SIZE) + ) + self._p = p self._g = g self._q = q diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 63a7c642ef7a..4c2ee1a63f86 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -23,6 +23,19 @@ from ...doubles import DummyKeySerializationEncryption from ...utils import load_nist_vectors, load_vectors_from_file +# RFC 3526 +P_1536 = int( + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" + "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" + "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" + "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB9ED529077096966D" + "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", + 16, +) + def _skip_dhx_unsupported(backend, is_dhx): if not is_dhx: @@ -32,35 +45,39 @@ def _skip_dhx_unsupported(backend, is_dhx): def test_dh_parameternumbers(): - params = dh.DHParameterNumbers(65537, 2) + params = dh.DHParameterNumbers(P_1536, 2) - assert params.p == 65537 + assert params.p == P_1536 assert params.g == 2 with pytest.raises(TypeError): dh.DHParameterNumbers(None, 2) with pytest.raises(TypeError): - dh.DHParameterNumbers(65537, None) + dh.DHParameterNumbers(P_1536, None) with pytest.raises(TypeError): dh.DHParameterNumbers(None, None) with pytest.raises(ValueError): - dh.DHParameterNumbers(65537, 1) + dh.DHParameterNumbers(P_1536, 1) - params = dh.DHParameterNumbers(65537, 7, 1245) + # p too small + with pytest.raises(ValueError): + dh.DHParameterNumbers(65537, 2) - assert params.p == 65537 + params = dh.DHParameterNumbers(P_1536, 7, 1245) + + assert params.p == P_1536 assert params.g == 7 assert params.q == 1245 with pytest.raises(TypeError): - dh.DHParameterNumbers(65537, 2, "hello") + dh.DHParameterNumbers(P_1536, 2, "hello") def test_dh_numbers(): - params = dh.DHParameterNumbers(65537, 2) + params = dh.DHParameterNumbers(P_1536, 2) public = dh.DHPublicNumbers(1, params) @@ -86,20 +103,22 @@ def test_dh_numbers(): def test_dh_parameter_numbers_equality(): - assert dh.DHParameterNumbers(65537, 2) == dh.DHParameterNumbers(65537, 2) - assert dh.DHParameterNumbers(65537, 7, 12345) == dh.DHParameterNumbers( - 65537, 7, 12345 + assert dh.DHParameterNumbers(P_1536, 2) == dh.DHParameterNumbers(P_1536, 2) + assert dh.DHParameterNumbers(P_1536, 7, 12345) == dh.DHParameterNumbers( + P_1536, 7, 12345 + ) + assert dh.DHParameterNumbers(P_1536 + 2, 2) != dh.DHParameterNumbers( + P_1536, 2 ) - assert dh.DHParameterNumbers(6, 2) != dh.DHParameterNumbers(65537, 2) - assert dh.DHParameterNumbers(65537, 2, 123) != dh.DHParameterNumbers( - 65537, 2, 456 + assert dh.DHParameterNumbers(P_1536, 2, 123) != dh.DHParameterNumbers( + P_1536, 2, 456 ) - assert dh.DHParameterNumbers(65537, 5) != dh.DHParameterNumbers(65537, 2) - assert dh.DHParameterNumbers(65537, 2) != object() + assert dh.DHParameterNumbers(P_1536, 5) != dh.DHParameterNumbers(P_1536, 2) + assert dh.DHParameterNumbers(P_1536, 2) != object() def test_dh_private_numbers_equality(): - params = dh.DHParameterNumbers(65537, 2) + params = dh.DHParameterNumbers(P_1536, 2) public = dh.DHPublicNumbers(1, params) private = dh.DHPrivateNumbers(2, public) @@ -107,18 +126,18 @@ def test_dh_private_numbers_equality(): assert private != dh.DHPrivateNumbers(0, public) assert private != dh.DHPrivateNumbers(2, dh.DHPublicNumbers(0, params)) assert private != dh.DHPrivateNumbers( - 2, dh.DHPublicNumbers(1, dh.DHParameterNumbers(65537, 5)) + 2, dh.DHPublicNumbers(1, dh.DHParameterNumbers(P_1536, 5)) ) assert private != object() def test_dh_public_numbers_equality(): - params = dh.DHParameterNumbers(65537, 2) + params = dh.DHParameterNumbers(P_1536, 2) public = dh.DHPublicNumbers(1, params) assert public == dh.DHPublicNumbers(1, params) assert public != dh.DHPublicNumbers(0, params) - assert public != dh.DHPublicNumbers(1, dh.DHParameterNumbers(65537, 5)) + assert public != dh.DHPublicNumbers(1, dh.DHParameterNumbers(P_1536, 5)) assert public != object() @@ -209,12 +228,11 @@ def test_convert_to_numbers(self, backend, with_q): ) def test_numbers_unsupported_parameters(self, backend): - # p is set to 21 because when calling private_key we want it to - # fail the DH_check call OpenSSL does. Originally this was 23, but - # we are allowing p % 24 to == 23 with this PR (see #3768 for more) - # By setting it to 21 it fails later in DH_check in a primality check - # which triggers the code path we want to test - params = dh.DHParameterNumbers(21, 2) + # p is set to P_1536 + 1 because when calling private_key we want it to + # fail the DH_check call OpenSSL does, but we specifically want it to + # fail such that we don't get a DH_NOT_SUITABLE_GENERATOR. We can cause + # this by making sure p is not prime. + params = dh.DHParameterNumbers(P_1536 + 1, 2) public = dh.DHPublicNumbers(1, params) private = dh.DHPrivateNumbers(2, public) @@ -363,6 +381,16 @@ def test_bad_exchange(self, backend, vector): assert symkey1 != symkey2 + @pytest.mark.skip_fips(reason="key_size too small for FIPS") + def test_load_256bit_key_from_pkcs8(self, backend): + data = load_vectors_from_file( + os.path.join("asymmetric", "DH", "dh_key_256.pem"), + lambda pemfile: pemfile.read(), + mode="rb", + ) + key = serialization.load_pem_private_key(data, None, backend) + assert key.key_size == 256 + @pytest.mark.parametrize( "vector", load_vectors_from_file( @@ -375,6 +403,10 @@ def test_dh_vectors(self, backend, vector): and int(vector["p"]) < backend._fips_dh_min_modulus ): pytest.skip("modulus too small for FIPS mode") + + if int(vector["p"]).bit_length() < 512: + pytest.skip("DH keys less than 512 bits are unsupported") + parameters = dh.DHParameterNumbers(int(vector["p"]), int(vector["g"])) public = dh.DHPublicNumbers(int(vector["y"]), parameters) private = dh.DHPrivateNumbers(int(vector["x"]), public) diff --git a/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem b/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem new file mode 100644 index 000000000000..1c01dd3eaf7e --- /dev/null +++ b/vectors/cryptography_vectors/asymmetric/DH/dh_key_256.pem @@ -0,0 +1,4 @@ +-----BEGIN PRIVATE KEY----- +MFwCAQAwMwYJKoZIhvcNAQMBMCYCIQCBPg6BS+5nbb09nSjtc9NnNdIf9kVyNvaN +PWFFVgwPqwIBAgQiAiBmJ3qBbu72ZnUxnCrr8ujWFU7jWTcOjhsZSqobmiD6vA== +-----END PRIVATE KEY----- From f133a3029a56d869084bc9839131bd57283027e0 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 29 Nov 2020 13:12:18 -0500 Subject: [PATCH 50/61] Don't build our custom osrandom engine on libressl (#5593) * Don't build our custom osrandom engine on libressl As far as I can tell it's never used on LibreSSL -- they're `RAND_bytes` function unconditionally calls `arc4random_buf` * Update cryptography.py --- src/_cffi_src/openssl/cryptography.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/_cffi_src/openssl/cryptography.py b/src/_cffi_src/openssl/cryptography.py index 28d659b1194a..f24bee5a4f82 100644 --- a/src/_cffi_src/openssl/cryptography.py +++ b/src/_cffi_src/openssl/cryptography.py @@ -44,8 +44,8 @@ (OPENSSL_VERSION_NUMBER < 0x10101020 || CRYPTOGRAPHY_IS_LIBRESSL) #define CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D \ (OPENSSL_VERSION_NUMBER < 0x10101040 || CRYPTOGRAPHY_IS_LIBRESSL) -#if (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D && !defined(OPENSSL_NO_ENGINE)) || \ - defined(USE_OSRANDOM_RNG_FOR_TESTING) +#if (CRYPTOGRAPHY_OPENSSL_LESS_THAN_111D && !CRYPTOGRAPHY_IS_LIBRESSL && \ + !defined(OPENSSL_NO_ENGINE)) || defined(USE_OSRANDOM_RNG_FOR_TESTING) #define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 1 #else #define CRYPTOGRAPHY_NEEDS_OSRANDOM_ENGINE 0 From 6d858c8bacc86da7dd1f9907f134767a0c8f91de Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 30 Nov 2020 22:56:52 -0500 Subject: [PATCH 51/61] fixes #4531 -- support encoding SCTs in certificates (#5594) --- src/_cffi_src/openssl/ct.py | 10 ++++--- .../hazmat/backends/openssl/encode_asn1.py | 15 ++++++++++- .../hazmat/bindings/openssl/_conditional.py | 5 ++-- tests/x509/test_x509_ext.py | 27 +++++++++++++++++++ 4 files changed, 50 insertions(+), 7 deletions(-) diff --git a/src/_cffi_src/openssl/ct.py b/src/_cffi_src/openssl/ct.py index 162004a8da73..5f0670635fa2 100644 --- a/src/_cffi_src/openssl/ct.py +++ b/src/_cffi_src/openssl/ct.py @@ -50,13 +50,14 @@ int SCT_set_source(SCT *, sct_source_t); +Cryptography_STACK_OF_SCT *sk_SCT_new_null(void); +void sk_SCT_free(Cryptography_STACK_OF_SCT *); int sk_SCT_num(const Cryptography_STACK_OF_SCT *); SCT *sk_SCT_value(const Cryptography_STACK_OF_SCT *, int); +int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *); void SCT_LIST_free(Cryptography_STACK_OF_SCT *); -int sk_SCT_push(Cryptography_STACK_OF_SCT *, SCT *); -Cryptography_STACK_OF_SCT *sk_SCT_new_null(void); SCT *SCT_new(void); int SCT_set1_log_id(SCT *, unsigned char *, size_t); void SCT_set_timestamp(SCT *, uint64_t); @@ -101,12 +102,13 @@ int (*SCT_set_source)(SCT *, sct_source_t) = NULL; +Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL; +void (*sk_SCT_free)(Cryptography_STACK_OF_SCT *) = NULL; int (*sk_SCT_num)(const Cryptography_STACK_OF_SCT *) = NULL; SCT *(*sk_SCT_value)(const Cryptography_STACK_OF_SCT *, int) = NULL; +int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL; void (*SCT_LIST_free)(Cryptography_STACK_OF_SCT *) = NULL; -int (*sk_SCT_push)(Cryptography_STACK_OF_SCT *, SCT *) = NULL; -Cryptography_STACK_OF_SCT *(*sk_SCT_new_null)(void) = NULL; SCT *(*SCT_new)(void) = NULL; int (*SCT_set1_log_id)(SCT *, unsigned char *, size_t) = NULL; void (*SCT_set_timestamp)(SCT *, uint64_t) = NULL; diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py index 88d709d21457..0a33200bbcc2 100644 --- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py +++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py @@ -604,11 +604,21 @@ def _encode_general_subtree(backend, subtrees): gs = backend._lib.GENERAL_SUBTREE_new() gs.base = _encode_general_name(backend, name) res = backend._lib.sk_GENERAL_SUBTREE_push(general_subtrees, gs) - assert res >= 1 + backend.openssl_assert(res >= 1) return general_subtrees +def _encode_precert_signed_certificate_timestamps(backend, scts): + sct_stack = backend._lib.sk_SCT_new_null() + backend.openssl_assert(sct_stack != backend._ffi.NULL) + sct_stack = backend._ffi.gc(sct_stack, backend._lib.sk_SCT_free) + for sct in scts: + res = backend._lib.sk_SCT_push(sct_stack, sct._sct) + backend.openssl_assert(res >= 1) + return sct_stack + + def _encode_nonce(backend, nonce): return _encode_asn1_str_gc(backend, nonce.nonce) @@ -630,6 +640,9 @@ def _encode_nonce(backend, nonce): ExtensionOID.OCSP_NO_CHECK: _encode_ocsp_nocheck, ExtensionOID.NAME_CONSTRAINTS: _encode_name_constraints, ExtensionOID.POLICY_CONSTRAINTS: _encode_policy_constraints, + ExtensionOID.PRECERT_SIGNED_CERTIFICATE_TIMESTAMPS: ( + _encode_precert_signed_certificate_timestamps + ), } _CRL_EXTENSION_ENCODE_HANDLERS = { diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index 585c7366454e..d990999cd1b9 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -100,11 +100,12 @@ def cryptography_has_sct(): "SCT_get0_signature", "SCT_get_timestamp", "SCT_set_source", + "sk_SCT_new_null", + "sk_SCT_free", "sk_SCT_num", "sk_SCT_value", - "SCT_LIST_free", "sk_SCT_push", - "sk_SCT_new_null", + "SCT_LIST_free", "SCT_new", "SCT_set1_log_id", "SCT_set_timestamp", diff --git a/tests/x509/test_x509_ext.py b/tests/x509/test_x509_ext.py index 429169a45ebc..8e2b402712ff 100644 --- a/tests/x509/test_x509_ext.py +++ b/tests/x509/test_x509_ext.py @@ -5678,6 +5678,33 @@ def test_simple(self, backend): == x509.certificate_transparency.LogEntryType.PRE_CERTIFICATE ) + @pytest.mark.supported( + only_if=lambda backend: (backend._lib.Cryptography_HAS_SCT), + skip_message="Requires CT support", + ) + def test_generate(self, backend): + cert = _load_cert( + os.path.join("x509", "badssl-sct.pem"), + x509.load_pem_x509_certificate, + backend, + ) + scts = cert.extensions.get_extension_for_class( + x509.PrecertificateSignedCertificateTimestamps + ).value + assert len(scts) == 1 + [sct] = scts + + private_key = RSA_KEY_2048.private_key(backend) + builder = _make_certbuilder(private_key).add_extension( + x509.PrecertificateSignedCertificateTimestamps([sct]), + critical=False, + ) + cert = builder.sign(private_key, hashes.SHA256(), backend) + ext = cert.extensions.get_extension_for_class( + x509.PrecertificateSignedCertificateTimestamps + ).value + assert list(ext) == [sct] + @pytest.mark.supported( only_if=lambda backend: backend._lib.CRYPTOGRAPHY_IS_LIBRESSL, skip_message="Requires LibreSSL", From a2096694853aed0828d0aaf38e364577a52b3780 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 1 Dec 2020 10:10:56 -0500 Subject: [PATCH 52/61] Added tls bindings for new OpenSSL APIs (#5595) fixes #5379 closes #5483 --- src/_cffi_src/openssl/ssl.py | 30 ++++++++++++++++--- .../hazmat/bindings/openssl/_conditional.py | 10 +++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index ff960f5775ad..f3511e454c98 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -24,6 +24,7 @@ static const long Cryptography_HAS_PSK; static const long Cryptography_HAS_VERIFIED_CHAIN; static const long Cryptography_HAS_KEYLOG; +static const long Cryptography_HAS_GET_PROTO_VERSION; /* Internally invented symbol to tell us if SSL_MODE_RELEASE_BUFFERS is * supported @@ -312,6 +313,16 @@ long SSL_total_renegotiations(SSL *); long SSL_get_secure_renegotiation_support(SSL *); +long SSL_CTX_set_min_proto_version(SSL_CTX *, int); +long SSL_CTX_set_max_proto_version(SSL_CTX *, int); +long SSL_set_min_proto_version(SSL *, int); +long SSL_set_max_proto_version(SSL *, int); + +long SSL_CTX_get_min_proto_version(SSL_CTX *); +long SSL_CTX_get_max_proto_version(SSL_CTX *); +long SSL_get_min_proto_version(SSL *); +long SSL_get_max_proto_version(SSL *); + /* Defined as unsigned long because SSL_OP_ALL is greater than signed 32-bit and Windows defines long as 32-bit. */ unsigned long SSL_CTX_set_options(SSL_CTX *, unsigned long); @@ -330,10 +341,6 @@ /* methods */ -/* - * TLSv1_1 and TLSv1_2 are recent additions. Only sufficiently new versions of - * OpenSSL support them. - */ const SSL_METHOD *TLSv1_1_method(void); const SSL_METHOD *TLSv1_1_server_method(void); const SSL_METHOD *TLSv1_1_client_method(void); @@ -363,6 +370,10 @@ const SSL_METHOD *SSLv23_server_method(void); const SSL_METHOD *SSLv23_client_method(void); +const SSL_METHOD *TLS_method(void); +const SSL_METHOD *TLS_server_method(void); +const SSL_METHOD *TLS_client_method(void); + /*- These aren't macros these arguments are all const X on openssl > 1.0.x -*/ SSL_CTX *SSL_CTX_new(SSL_METHOD *); long SSL_CTX_get_timeout(const SSL_CTX *); @@ -674,4 +685,15 @@ #else static const long Cryptography_HAS_TLSv1_3 = 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 """ diff --git a/src/cryptography/hazmat/bindings/openssl/_conditional.py b/src/cryptography/hazmat/bindings/openssl/_conditional.py index d990999cd1b9..ca50fed13414 100644 --- a/src/cryptography/hazmat/bindings/openssl/_conditional.py +++ b/src/cryptography/hazmat/bindings/openssl/_conditional.py @@ -262,6 +262,15 @@ def cryptography_has_srtp(): ] +def cryptography_has_get_proto_version(): + return [ + "SSL_CTX_get_min_proto_version", + "SSL_CTX_get_max_proto_version", + "SSL_get_min_proto_version", + "SSL_get_max_proto_version", + ] + + # 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 @@ -309,4 +318,5 @@ def cryptography_has_srtp(): "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, } From 2660f93eca71be5558cfcb9a120310636791e6ec Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 1 Dec 2020 11:54:29 -0500 Subject: [PATCH 53/61] Document that Firefox doesn't support unencrypted pkcs12 (#5596) --- docs/hazmat/primitives/asymmetric/serialization.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/serialization.rst b/docs/hazmat/primitives/asymmetric/serialization.rst index 8811646045f6..2324340e119c 100644 --- a/docs/hazmat/primitives/asymmetric/serialization.rst +++ b/docs/hazmat/primitives/asymmetric/serialization.rst @@ -496,6 +496,11 @@ file suffix. Serialize a PKCS12 blob. + .. note:: + + Due to `a bug in Firefox`_ it's not possible to load unencrypted PKCS12 + blobs in Firefox. + :param name: The friendly name to use for the supplied certificate and key. :type name: bytes @@ -942,6 +947,7 @@ Serialization Encryption Types Do not encrypt. +.. _`a bug in Firefox`: https://bugzilla.mozilla.org/show_bug.cgi?id=773111 .. _`PKCS3`: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf .. _`SEC 1 v2.0`: https://www.secg.org/sec1-v2.pdf .. _`PROTOCOL.key`: https://github.com/openssh/openssh-portable/blob/master/PROTOCOL.key From 96f2d96d1c4884a7d314372d4876e0d45e24e342 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 1 Dec 2020 13:23:39 -0500 Subject: [PATCH 54/61] remove legacy debugging code from setup.py (#5597) --- setup.py | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/setup.py b/setup.py index c6c3e994625e..8477c826b28f 100644 --- a/setup.py +++ b/setup.py @@ -10,20 +10,9 @@ import platform import sys -import pkg_resources - -import setuptools from setuptools import find_packages, setup -if pkg_resources.parse_version( - setuptools.__version__ -) < pkg_resources.parse_version("18.5"): - raise RuntimeError( - "cryptography requires setuptools 18.5 or newer, please upgrade to a " - "newer version of setuptools" - ) - base_dir = os.path.dirname(__file__) src_dir = os.path.join(base_dir, "src") From 1be144acc6b46ae2ece459d80a20831ac2ac1c74 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 1 Dec 2020 14:01:43 -0500 Subject: [PATCH 55/61] bump cffi minimum version to help out pyopenssl (#5598) fixes https://github.com/pyca/pyopenssl/issues/971 --- pyproject.toml | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 957b1fd04bb0..667f29e23ff2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = [ "setuptools>=40.6.0", "wheel", # Must be kept in sync with the `setup_requirements` in `setup.py` - "cffi>=1.8,!=1.11.3; platform_python_implementation != 'PyPy'", + "cffi>=1.12; platform_python_implementation != 'PyPy'", ] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 8477c826b28f..4ebbc1b50203 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ # `setup_requirements` must be kept in sync with `pyproject.toml` -setup_requirements = ["cffi>=1.8,!=1.11.3"] +setup_requirements = ["cffi>=1.12"] if platform.python_implementation() == "PyPy": if sys.pypy_version_info < (5, 4): From 8686d524b7b890bcbe6132b774bd72a3ae37cf0d Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 6 Dec 2020 23:12:44 -0500 Subject: [PATCH 56/61] Document that PKCS1v1.5 is not constant time (#5600) closes #5510 --- docs/hazmat/primitives/asymmetric/rsa.rst | 5 +++++ docs/limitations.rst | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index b8060e4740fd..fe3930fec29b 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -342,6 +342,11 @@ Padding :class:`OAEP` should be preferred for encryption and :class:`PSS` should be preferred for signatures. + .. warning:: + + Our implementation of PKCS1 v1.5 decryption is not constant time. See + :doc:`/limitations` for details. + .. function:: calculate_max_pss_salt_length(key, hash_algorithm) diff --git a/docs/limitations.rst b/docs/limitations.rst index 092d8a7cff91..5763ecd40299 100644 --- a/docs/limitations.rst +++ b/docs/limitations.rst @@ -20,5 +20,25 @@ like almost all software in Python is potentially vulnerable to this attack. The Likelihood: unlikely, Remediation Cost: expensive to repair" and we do not consider this a high risk for most users. +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. + +``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 +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 From 6693d55cbe05c98c9e1fe3a8b08639f5491a572a Mon Sep 17 00:00:00 2001 From: Zoltan Kelemen <39551158+misterzed88@users.noreply.github.com> Date: Tue, 8 Dec 2020 05:58:04 +0100 Subject: [PATCH 57/61] Add support for RSA signature recovery (#5573) * Removed unused argument. * Added support for RSA signature recovery. * Syntatic corrections for passing pep8 tests. * Corrected typo. * Added test of invalid Prehashed parameter to RSA signature recover. * Renamed recover to a more descriptive name. * Extended RSA signature recovery with option to return full data (not only the digest part). * Added missing words to pass spell check. --- CHANGELOG.rst | 5 ++ docs/hazmat/primitives/asymmetric/rsa.rst | 49 +++++++++++++ docs/spelling_wordlist.txt | 1 + src/_cffi_src/openssl/evp.py | 3 + .../hazmat/backends/openssl/rsa.py | 73 ++++++++++++++++--- .../hazmat/backends/openssl/utils.py | 3 +- .../hazmat/primitives/asymmetric/rsa.py | 6 ++ tests/hazmat/primitives/test_rsa.py | 67 ++++++++++++++++- 8 files changed, 191 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index e9ea92a84756..83d3b703504b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -27,6 +27,11 @@ Changelog in any application outside of testing. * Python 2 support is deprecated in ``cryptography``. This is the last release that will support Python 2. +* Added the + :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.recover_data_from_signature` + function to + :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey` + for recovering the signed data from an RSA signature. .. _v3-2-1: diff --git a/docs/hazmat/primitives/asymmetric/rsa.rst b/docs/hazmat/primitives/asymmetric/rsa.rst index fe3930fec29b..33f402b65a43 100644 --- a/docs/hazmat/primitives/asymmetric/rsa.rst +++ b/docs/hazmat/primitives/asymmetric/rsa.rst @@ -714,6 +714,55 @@ Key interfaces :raises cryptography.exceptions.InvalidSignature: If the signature does not validate. + .. method:: recover_data_from_signature(signature, padding, algorithm) + + .. versionadded:: 3.3 + + Recovers the signed data from the signature. The data contains the + digest of the original message string. The ``padding`` and + ``algorithm`` parameters must match the ones used when the signature + was created for the recovery to succeed. + + The ``algorithm`` parameter can also be set to ``None`` to recover all + the data present in the signature, without regard to its format or the + hash algorithm used for its creation. + + For + :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15` + padding, this returns the data after removing the padding layer. For + standard signatures the data contains the full ``DigestInfo`` structure. + For non-standard signatures, any data can be returned, including zero- + length data. + + Normally you should use the + :meth:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicKey.verify` + function to validate the signature. But for some non-standard signature + formats you may need to explicitly recover and validate the signed + data. Following are some examples: + + - Some old Thawte and Verisign timestamp certificates without ``DigestInfo``. + - Signed MD5/SHA1 hashes in TLS 1.1 or earlier (RFC 4346, section 4.7). + - IKE version 1 signatures without ``DigestInfo`` (RFC 2409, section 5.1). + + :param bytes signature: The signature. + + :param padding: An instance of + :class:`~cryptography.hazmat.primitives.asymmetric.padding.AsymmetricPadding`. + Recovery is only supported with some of the padding types. (Currently + only with + :class:`~cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15`). + + :param algorithm: An instance of + :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm`. + Can be ``None`` to return the all the data present in the signature. + + :return bytes: The signed data. + + :raises cryptography.exceptions.InvalidSignature: If the signature is + invalid. + + :raises cryptography.exceptions.UnsupportedAlgorithm: If signature + data recovery is not supported with the provided ``padding`` type. .. class:: RSAPublicKeyWithSerialization diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt index c8c275142ff7..f0486e05f704 100644 --- a/docs/spelling_wordlist.txt +++ b/docs/spelling_wordlist.txt @@ -103,6 +103,7 @@ Solaris syscall Tanja testability +Thawte timestamp timestamps tunable diff --git a/src/_cffi_src/openssl/evp.py b/src/_cffi_src/openssl/evp.py index 5b6e35cf9dd6..ab7cfeb39511 100644 --- a/src/_cffi_src/openssl/evp.py +++ b/src/_cffi_src/openssl/evp.py @@ -101,6 +101,9 @@ int EVP_PKEY_verify_init(EVP_PKEY_CTX *); int EVP_PKEY_verify(EVP_PKEY_CTX *, const unsigned char *, size_t, const unsigned char *, size_t); +int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *); +int EVP_PKEY_verify_recover(EVP_PKEY_CTX *, unsigned char *, + size_t *, const unsigned char *, size_t); int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *); int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *); diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index de299779d942..82cd49c960ab 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -142,6 +142,7 @@ def _rsa_sig_determine_padding(backend, key, padding, algorithm): backend.openssl_assert(pkey_size > 0) if isinstance(padding, PKCS1v15): + # Hash algorithm is ignored for PKCS1v15-padding, may be None. padding_enum = backend._lib.RSA_PKCS1_PADDING elif isinstance(padding, PSS): if not isinstance(padding._mgf, MGF1): @@ -150,6 +151,10 @@ def _rsa_sig_determine_padding(backend, key, padding, algorithm): _Reasons.UNSUPPORTED_MGF, ) + # PSS padding requires a hash algorithm + if not isinstance(algorithm, hashes.HashAlgorithm): + raise TypeError("Expected instance of hashes.HashAlgorithm.") + # Size of key in bytes - 2 is the maximum # PSS signature length (salt length is checked later) if pkey_size - algorithm.digest_size - 2 < 0: @@ -168,25 +173,37 @@ def _rsa_sig_determine_padding(backend, key, padding, algorithm): return padding_enum -def _rsa_sig_setup(backend, padding, algorithm, key, data, init_func): +# Hash algorithm can be absent (None) to initialize the context without setting +# any message digest algorithm. This is currently only valid for the PKCS1v15 +# padding type, where it means that the signature data is encoded/decoded +# as provided, without being wrapped in a DigestInfo structure. +def _rsa_sig_setup(backend, padding, algorithm, key, init_func): padding_enum = _rsa_sig_determine_padding(backend, key, padding, algorithm) - evp_md = backend._evp_md_non_null_from_algorithm(algorithm) pkey_ctx = backend._lib.EVP_PKEY_CTX_new(key._evp_pkey, backend._ffi.NULL) backend.openssl_assert(pkey_ctx != backend._ffi.NULL) pkey_ctx = backend._ffi.gc(pkey_ctx, backend._lib.EVP_PKEY_CTX_free) res = init_func(pkey_ctx) backend.openssl_assert(res == 1) - res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) - if res == 0: + if algorithm is not None: + evp_md = backend._evp_md_non_null_from_algorithm(algorithm) + res = backend._lib.EVP_PKEY_CTX_set_signature_md(pkey_ctx, evp_md) + if res == 0: + backend._consume_errors() + raise UnsupportedAlgorithm( + "{} is not supported by this backend for RSA signing.".format( + algorithm.name + ), + _Reasons.UNSUPPORTED_HASH, + ) + res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) + if res <= 0: backend._consume_errors() raise UnsupportedAlgorithm( - "{} is not supported by this backend for RSA signing.".format( - algorithm.name + "{} is not supported for the RSA signature operation.".format( + padding.name ), - _Reasons.UNSUPPORTED_HASH, + _Reasons.UNSUPPORTED_PADDING, ) - res = backend._lib.EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, padding_enum) - backend.openssl_assert(res > 0) if isinstance(padding, PSS): res = backend._lib.EVP_PKEY_CTX_set_rsa_pss_saltlen( pkey_ctx, _get_rsa_pss_salt_length(padding, key, algorithm) @@ -208,7 +225,6 @@ def _rsa_sig_sign(backend, padding, algorithm, private_key, data): padding, algorithm, private_key, - data, backend._lib.EVP_PKEY_sign_init, ) buflen = backend._ffi.new("size_t *") @@ -235,7 +251,6 @@ def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data): padding, algorithm, public_key, - data, backend._lib.EVP_PKEY_verify_init, ) res = backend._lib.EVP_PKEY_verify( @@ -250,6 +265,36 @@ def _rsa_sig_verify(backend, padding, algorithm, public_key, signature, data): raise InvalidSignature +def _rsa_sig_recover(backend, padding, algorithm, public_key, signature): + pkey_ctx = _rsa_sig_setup( + backend, + padding, + algorithm, + public_key, + backend._lib.EVP_PKEY_verify_recover_init, + ) + + # Attempt to keep the rest of the code in this function as constant/time + # as possible. See the comment in _enc_dec_rsa_pkey_ctx. Note that the + # outlen parameter is used even though its value may be undefined in the + # error case. Due to the tolerant nature of Python slicing this does not + # trigger any exceptions. + maxlen = backend._lib.EVP_PKEY_size(public_key._evp_pkey) + backend.openssl_assert(maxlen > 0) + buf = backend._ffi.new("unsigned char[]", maxlen) + buflen = backend._ffi.new("size_t *", maxlen) + res = backend._lib.EVP_PKEY_verify_recover( + pkey_ctx, buf, buflen, signature, len(signature) + ) + resbuf = backend._ffi.buffer(buf)[: buflen[0]] + backend._lib.ERR_clear_error() + # Assume that all parameter errors are handled during the setup phase and + # any error here is due to invalid signature. + if res != 1: + raise InvalidSignature + return resbuf + + @utils.register_interface(AsymmetricSignatureContext) class _RSASignatureContext(object): def __init__(self, backend, private_key, padding, algorithm): @@ -463,3 +508,9 @@ def verify(self, signature, data, padding, algorithm): return _rsa_sig_verify( self._backend, padding, algorithm, self, signature, data ) + + def recover_data_from_signature(self, signature, padding, algorithm): + _check_not_prehashed(algorithm) + return _rsa_sig_recover( + self._backend, padding, algorithm, self, signature + ) diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py index ec0b947a44c6..3d697d1fb56f 100644 --- a/src/cryptography/hazmat/backends/openssl/utils.py +++ b/src/cryptography/hazmat/backends/openssl/utils.py @@ -52,7 +52,8 @@ def _check_not_prehashed(signature_algorithm): if isinstance(signature_algorithm, Prehashed): raise TypeError( "Prehashed is only supported in the sign and verify methods. " - "It cannot be used with signer or verifier." + "It cannot be used with signer, verifier or " + "recover_data_from_signature." ) diff --git a/src/cryptography/hazmat/primitives/asymmetric/rsa.py b/src/cryptography/hazmat/primitives/asymmetric/rsa.py index d8b8ddd914cc..ea16bbf66e66 100644 --- a/src/cryptography/hazmat/primitives/asymmetric/rsa.py +++ b/src/cryptography/hazmat/primitives/asymmetric/rsa.py @@ -106,6 +106,12 @@ def verify(self, signature, data, padding, algorithm): Verifies the signature of the data. """ + @abc.abstractmethod + def recover_data_from_signature(self, signature, padding, algorithm): + """ + Recovers the original data from the signature. + """ + RSAPublicKeyWithSerialization = RSAPublicKey diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 1a770d3efe50..61c481504ecc 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -730,6 +730,18 @@ def test_prehashed_unsupported_in_verifier_ctx(self, backend): asym_utils.Prehashed(hashes.SHA1()), ) + def test_prehashed_unsupported_in_signature_recover(self, backend): + private_key = RSA_KEY_512.private_key(backend) + public_key = private_key.public_key() + signature = private_key.sign( + b"sign me", padding.PKCS1v15(), hashes.SHA1() + ) + prehashed_alg = asym_utils.Prehashed(hashes.SHA1()) + with pytest.raises(TypeError): + public_key.recover_data_from_signature( + signature, padding.PKCS1v15(), prehashed_alg + ) + def test_corrupted_private_key(self, backend): with pytest.raises(ValueError): serialization.load_pem_private_key( @@ -759,13 +771,28 @@ def test_pkcs1v15_verification(self, pkcs1_example, backend): public_key = rsa.RSAPublicNumbers( e=public["public_exponent"], n=public["modulus"] ).public_key(backend) + signature = binascii.unhexlify(example["signature"]) + message = binascii.unhexlify(example["message"]) public_key.verify( - binascii.unhexlify(example["signature"]), - binascii.unhexlify(example["message"]), - padding.PKCS1v15(), - hashes.SHA1(), + signature, message, padding.PKCS1v15(), hashes.SHA1() ) + # Test digest recovery by providing hash + digest = hashes.Hash(hashes.SHA1()) + digest.update(message) + msg_digest = digest.finalize() + rec_msg_digest = public_key.recover_data_from_signature( + signature, padding.PKCS1v15(), hashes.SHA1() + ) + assert msg_digest == rec_msg_digest + + # Test recovery of all data (full DigestInfo) with hash alg. as None + rec_sig_data = public_key.recover_data_from_signature( + signature, padding.PKCS1v15(), None + ) + assert len(rec_sig_data) > len(msg_digest) + assert msg_digest == rec_sig_data[-len(msg_digest) :] + @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( padding.PKCS1v15() @@ -783,6 +810,17 @@ def test_invalid_pkcs1v15_signature_wrong_data(self, backend): signature, b"incorrect data", padding.PKCS1v15(), hashes.SHA1() ) + def test_invalid_pkcs1v15_signature_recover_wrong_hash_alg(self, backend): + private_key = RSA_KEY_512.private_key(backend) + public_key = private_key.public_key() + signature = private_key.sign( + b"sign me", padding.PKCS1v15(), hashes.SHA1() + ) + with pytest.raises(InvalidSignature): + public_key.recover_data_from_signature( + signature, padding.PKCS1v15(), hashes.SHA256() + ) + def test_invalid_signature_sequence_removed(self, backend): """ This test comes from wycheproof @@ -970,6 +1008,27 @@ def test_invalid_pss_signature_data_too_large_for_modulus(self, backend): hashes.SHA1(), ) + def test_invalid_pss_signature_recover(self, backend): + private_key = RSA_KEY_1024.private_key(backend) + public_key = private_key.public_key() + pss_padding = padding.PSS( + mgf=padding.MGF1(algorithm=hashes.SHA1()), + salt_length=padding.PSS.MAX_LENGTH, + ) + signature = private_key.sign(b"sign me", pss_padding, hashes.SHA1()) + + # Hash algorithm can not be absent for PSS padding + with pytest.raises(TypeError): + public_key.recover_data_from_signature( + signature, pss_padding, None + ) + + # Signature data recovery not supported with PSS + with raises_unsupported_algorithm(_Reasons.UNSUPPORTED_PADDING): + public_key.recover_data_from_signature( + signature, pss_padding, hashes.SHA1() + ) + @pytest.mark.supported( only_if=lambda backend: backend.rsa_padding_supported( padding.PKCS1v15() From b5278c908574b2d965755d063a95812c6b520a8e Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 8 Dec 2020 16:45:30 -0500 Subject: [PATCH 58/61] Fixed DH tests for latest CentOS FIPS OpenSSL (#5604) * Fixed DH tests for latest CentOS FIPS OpenSSL (1.1.1g) --- .github/workflows/ci.yml | 14 +++++++------- tests/hazmat/primitives/test_dh.py | 12 ++++++++++++ tests/hazmat/primitives/test_serialization.py | 2 ++ tests/x509/test_x509.py | 18 +++++++++++------- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10f9eb47d326..1e03eaede894 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -88,7 +88,7 @@ jobs: IMAGE: - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-centos8", TOXENV: "py36"} - - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", ENV: "OPENSSL_FORCE_FIPS_MODE=1"} + - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", FIPS: true} - {IMAGE: "pyca/cryptography-runner-stretch", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py38"} @@ -100,20 +100,20 @@ jobs: - {IMAGE: "pyca/cryptography-runner-ubuntu-rolling", TOXENV: "py38-randomorder"} - {IMAGE: "pyca/cryptography-runner-fedora", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-alpine", TOXENV: "py38"} - name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }} ${{ matrix.IMAGE.ENV }}" + name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" steps: - uses: actions/checkout@v2 - run: 'git clone --depth=1 https://github.com/google/wycheproof "$HOME/wycheproof"' - - run: 'echo "$ENV_VAR" >> $GITHUB_ENV' - if: matrix.IMAGE.ENV - env: - ENV_VAR: ${{ matrix.IMAGE.ENV }} + - run: | + echo "OPENSSL_FORCE_FIPS_MODE=1" >> $GITHUB_ENV + echo "CFLAGS=-DUSE_OSRANDOM_RNG_FOR_TESTING" >> $GITHUB_ENV + if: matrix.IMAGE.FIPS - run: 'tox -- --wycheproof-root="$HOME/wycheproof"' env: TOXENV: ${{ matrix.IMAGE.TOXENV }} - uses: ./.github/actions/upload-coverage with: - name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }} ${{ matrix.IMAGE.ENV }}" + name: "tox -e ${{ matrix.IMAGE.TOXENV }} on ${{ matrix.IMAGE.IMAGE }}" macos: runs-on: macos-latest diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index 4c2ee1a63f86..bc5ed8fb0035 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -151,6 +151,7 @@ def test_unsupported_generator_generate_dh(self, backend): with pytest.raises(ValueError): dh.generate_parameters(7, 512, backend) + @pytest.mark.skip_fips(reason="non-FIPS parameters") def test_dh_parameters_supported(self, backend): valid_p = int( b"907c7211ae61aaaba1825ff53b6cb71ac6df9f1a424c033f4a0a41ac42fad3a9" @@ -171,6 +172,12 @@ def test_dh_parameters_supported(self, backend): ) def test_dh_parameters_allows_rfc3526_groups(self, backend, vector): p = int_from_bytes(binascii.unhexlify(vector["p"]), "big") + if ( + backend._fips_enabled + and p.bit_length() < backend._fips_dh_min_modulus + ): + pytest.skip("modulus too small for FIPS mode") + params = dh.DHParameterNumbers(p, int(vector["g"])) param = params.parameters(backend) key = param.generate_private_key() @@ -180,6 +187,7 @@ def test_dh_parameters_allows_rfc3526_groups(self, backend, vector): roundtripped_key = key.private_numbers().private_key(backend) assert key.private_numbers() == roundtripped_key.private_numbers() + @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( "vector", load_vectors_from_file( @@ -227,6 +235,7 @@ def test_convert_to_numbers(self, backend, with_q): deserialized_private, dh.DHPrivateKeyWithSerialization ) + @pytest.mark.skip_fips(reason="FIPS requires specific parameters") def test_numbers_unsupported_parameters(self, backend): # p is set to P_1536 + 1 because when calling private_key we want it to # fail the DH_check call OpenSSL does, but we specifically want it to @@ -415,6 +424,7 @@ def test_dh_vectors(self, backend, vector): assert int_from_bytes(symkey, "big") == int(vector["k"], 16) + @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( "vector", load_vectors_from_file( @@ -477,6 +487,7 @@ def test_private_bytes_rejects_invalid(self, encoding, fmt, backend): with pytest.raises(ValueError): key.private_bytes(encoding, fmt, serialization.NoEncryption()) + @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( ("key_path", "loader_func", "encoding", "is_dhx"), [ @@ -521,6 +532,7 @@ def test_private_bytes_match( ) assert serialized == key_bytes + @pytest.mark.skip_fips(reason="non-FIPS parameters") @pytest.mark.parametrize( ("key_path", "loader_func", "vec_path", "is_dhx"), [ diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index c21a4fa5ee35..32debd46c7d2 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -1757,6 +1757,7 @@ def test_openssh_serialization_unsupported(self, backend): class TestDHSerialization(object): """Test all options with least-supported key type.""" + @pytest.mark.skip_fips(reason="non-FIPS parameters") def test_dh_public_key(self, backend): data = load_vectors_from_file( os.path.join("asymmetric", "DH", "dhkey.pem"), @@ -1788,6 +1789,7 @@ def test_dh_public_key(self, backend): with pytest.raises(ValueError): public_key.public_bytes(enc, fmt) + @pytest.mark.skip_fips(reason="non-FIPS parameters") def test_dh_private_key(self, backend): data = load_vectors_from_file( os.path.join("asymmetric", "DH", "dhkey.pem"), diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index f4d93389ac02..146619b9a84b 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -41,6 +41,7 @@ ) from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ( + dh, dsa, ec, ed25519, @@ -51,6 +52,7 @@ from cryptography.hazmat.primitives.asymmetric.utils import ( decode_dss_signature, ) +from cryptography.utils import int_from_bytes from cryptography.x509.name import _ASN1Type from cryptography.x509.oid import ( AuthorityInformationAccessOID, @@ -65,7 +67,7 @@ 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 ..utils import load_vectors_from_file +from ..utils import load_nist_vectors, load_vectors_from_file @utils.register_interface(x509.ExtensionType) @@ -5237,12 +5239,14 @@ class TestSignatureRejection(object): """Test if signing rejects DH keys properly.""" def load_key(self, backend): - data = load_vectors_from_file( - os.path.join("asymmetric", "DH", "dhkey.pem"), - lambda pemfile: pemfile.read(), - mode="rb", - ) - return serialization.load_pem_private_key(data, None, backend) + vector = load_vectors_from_file( + os.path.join("asymmetric", "DH", "rfc3526.txt"), + load_nist_vectors, + )[1] + p = int_from_bytes(binascii.unhexlify(vector["p"]), "big") + params = dh.DHParameterNumbers(p, int(vector["g"])) + param = params.parameters(backend) + return param.generate_private_key() def test_crt_signing_check(self, backend): issuer_private_key = self.load_key(backend) From 7e8fff73cf0c597fe2df34daf2027506f84b9d3b Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 8 Dec 2020 17:26:19 -0500 Subject: [PATCH 59/61] Prepare for 3.3 release (#5603) --- CHANGELOG.rst | 6 ++++-- src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 83d3b703504b..caa8e20c525b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -3,8 +3,8 @@ Changelog .. _v3-3: -3.3 - `master`_ -~~~~~~~~~~~~~~~ +3.3 - 2020-12-08 +~~~~~~~~~~~~~~~~ .. note:: This version is not yet released and is under active development. @@ -25,6 +25,8 @@ Changelog conform with an upcoming OpenSSL release that no longer supports smaller sizes. These keys were already wildly insecure and should not have been used in any application outside of testing. +* Updated Windows, macOS, and ``manylinux`` wheels to be compiled with + OpenSSL 1.1.1i. * Python 2 support is deprecated in ``cryptography``. This is the last release that will support Python 2. * Added the diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 758b17899647..d7a3c1e6de87 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -22,7 +22,7 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3.dev1" +__version__ = "3.3" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 9252c0f0f0d0..5cb6768fa234 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -20,7 +20,7 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3.dev1" +__version__ = "3.3" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" From 1ff0d50948bbb6f2aa53d5648f1188a567d941cd Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Wed, 9 Dec 2020 18:27:21 -0600 Subject: [PATCH 60/61] re-add Cryptography_HAS_TLSEXT_HOSTNAME and bump for 3.3.1 (#5625) * re-add Cryptography_HAS_TLSEXT_HOSTNAME and bump for 3.3.1 * review feedback --- CHANGELOG.rst | 9 +++++++-- src/_cffi_src/openssl/ssl.py | 6 ++++++ src/cryptography/__about__.py | 2 +- vectors/cryptography_vectors/__about__.py | 2 +- 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index caa8e20c525b..3cb53d00e03d 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,13 +1,18 @@ Changelog ========= +.. _v3-3-1: + +3.3.1 - 2020-12-09 +~~~~~~~~~~~~~~~~~~ + +* Re-added a legacy symbol causing problems for older ``pyOpenSSL`` users. + .. _v3-3: 3.3 - 2020-12-08 ~~~~~~~~~~~~~~~~ -.. note:: This version is not yet released and is under active development. - * **BACKWARDS INCOMPATIBLE:** Support for Python 3.5 has been removed due to low usage and maintenance burden. * **BACKWARDS INCOMPATIBLE:** The diff --git a/src/_cffi_src/openssl/ssl.py b/src/_cffi_src/openssl/ssl.py index f3511e454c98..9400f115fb44 100644 --- a/src/_cffi_src/openssl/ssl.py +++ b/src/_cffi_src/openssl/ssl.py @@ -25,6 +25,7 @@ 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; /* Internally invented symbol to tell us if SSL_MODE_RELEASE_BUFFERS is * supported @@ -504,6 +505,11 @@ """ CUSTOMIZATIONS = """ +// This symbol is being preserved because removing it will break users with +// pyOpenSSL < 19.1 and pip < 20.x. We need to leave this in place until those +// users have upgraded. PersistentlyDeprecated2020 +static const long Cryptography_HAS_TLSEXT_HOSTNAME = 1; + #if CRYPTOGRAPHY_IS_LIBRESSL static const long Cryptography_HAS_VERIFIED_CHAIN = 0; Cryptography_STACK_OF_X509 *(*SSL_get0_verified_chain)(const SSL *) = NULL; diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index d7a3c1e6de87..0c7eaaa09603 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -22,7 +22,7 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3" +__version__ = "3.3.1" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 5cb6768fa234..44fe9e7d85e7 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -20,7 +20,7 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3" +__version__ = "3.3.1" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" From 82b6ce28389f0a317bc55ba2091a74b346db7cae Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 7 Feb 2021 11:36:56 -0500 Subject: [PATCH 61/61] correct buffer overflows cause by integer overflow in openssl (#5747) * correct buffer overflows cause by integer overflow in openssl frustratingly, there is no test for this -- that's because testing this requires allocating more memory than is available in CI. fixes #5615. * backport CI fixes * another CI backport --- .github/workflows/ci.yml | 4 ++-- .github/workflows/wheel-builder.yml | 2 +- .zuul.d/jobs.yaml | 6 +++--- CHANGELOG.rst | 9 +++++++++ docs/conf.py | 2 +- src/cryptography/__about__.py | 4 ++-- src/cryptography/hazmat/backends/openssl/ciphers.py | 2 +- vectors/cryptography_vectors/__about__.py | 4 ++-- 8 files changed, 21 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1e03eaede894..3cc8433610f9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,7 +82,7 @@ jobs: linux-distros: runs-on: ubuntu-latest - container: ${{ matrix.IMAGE.IMAGE }} + container: ghcr.io/${{ matrix.IMAGE.IMAGE }} strategy: matrix: IMAGE: @@ -91,7 +91,7 @@ jobs: - {IMAGE: "pyca/cryptography-runner-centos8-fips", TOXENV: "py36", FIPS: true} - {IMAGE: "pyca/cryptography-runner-stretch", TOXENV: "py27"} - {IMAGE: "pyca/cryptography-runner-buster", TOXENV: "py37"} - - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py38"} + - {IMAGE: "pyca/cryptography-runner-bullseye", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-sid", TOXENV: "py39"} - {IMAGE: "pyca/cryptography-runner-ubuntu-bionic", TOXENV: "py36"} - {IMAGE: "pyca/cryptography-runner-ubuntu-focal", TOXENV: "py38"} diff --git a/.github/workflows/wheel-builder.yml b/.github/workflows/wheel-builder.yml index b74edc2da5a4..94d24c5e3810 100644 --- a/.github/workflows/wheel-builder.yml +++ b/.github/workflows/wheel-builder.yml @@ -8,7 +8,7 @@ on: jobs: manylinux: runs-on: ubuntu-latest - container: ${{ matrix.MANYLINUX.CONTAINER }} + container: ghcr.io/${{ matrix.MANYLINUX.CONTAINER }} strategy: matrix: PYTHON: ["cp27-cp27m", "cp27-cp27mu", "cp36-cp36m"] diff --git a/.zuul.d/jobs.yaml b/.zuul.d/jobs.yaml index 38cab295060f..83f2c6597038 100644 --- a/.zuul.d/jobs.yaml +++ b/.zuul.d/jobs.yaml @@ -44,7 +44,7 @@ vars: wheel_builds: - platform: manylinux2014_aarch64 - image: pyca/cryptography-manylinux2014_aarch64 + image: ghcr.io/pyca/cryptography-manylinux2014_aarch64 pythons: - cp36-cp36m @@ -55,13 +55,13 @@ vars: wheel_builds: - platform: manylinux1_x86_64 - image: pyca/cryptography-manylinux1:x86_64 + image: ghcr.io/pyca/cryptography-manylinux1:x86_64 pythons: - cp27-cp27m - cp27-cp27mu - cp36-cp36m - platform: manylinux2010_x86_64 - image: pyca/cryptography-manylinux2010:x86_64 + image: ghcr.io/pyca/cryptography-manylinux2010:x86_64 pythons: - cp27-cp27m - cp27-cp27mu diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 3cb53d00e03d..4dd71460069f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Changelog ========= +.. _v3-3-2: + +3.3.2 - 2021-02-07 +~~~~~~~~~~~~~~~~~~ + +* **SECURITY ISSUE:** Fixed a bug where certain sequences of ``update()`` calls + when symmetrically encrypting very large payloads (>2GB) could result in an + integer overflow, leading to buffer overflows. *CVE-2020-36242* + .. _v3-3-1: 3.3.1 - 2020-12-09 diff --git a/docs/conf.py b/docs/conf.py index 33240d8de1a3..fb67adabc905 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -71,7 +71,7 @@ # General information about the project. project = "Cryptography" -copyright = "2013-2020, Individual Contributors" +copyright = "2013-2021, Individual Contributors" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/src/cryptography/__about__.py b/src/cryptography/__about__.py index 0c7eaaa09603..f816509257e8 100644 --- a/src/cryptography/__about__.py +++ b/src/cryptography/__about__.py @@ -22,10 +22,10 @@ ) __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3.1" +__version__ = "3.3.2" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2020 {}".format(__author__) +__copyright__ = "Copyright 2013-2021 {}".format(__author__) diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py index 1e805d235aa2..ad5dad3f7ed2 100644 --- a/src/cryptography/hazmat/backends/openssl/ciphers.py +++ b/src/cryptography/hazmat/backends/openssl/ciphers.py @@ -17,7 +17,7 @@ class _CipherContext(object): _ENCRYPT = 1 _DECRYPT = 0 - _MAX_CHUNK_SIZE = 2 ** 31 - 1 + _MAX_CHUNK_SIZE = 2 ** 30 - 1 def __init__(self, backend, cipher, mode, operation): self._backend = backend diff --git a/vectors/cryptography_vectors/__about__.py b/vectors/cryptography_vectors/__about__.py index 44fe9e7d85e7..dc069d51ba86 100644 --- a/vectors/cryptography_vectors/__about__.py +++ b/vectors/cryptography_vectors/__about__.py @@ -20,10 +20,10 @@ __uri__ = "https://github.com/pyca/cryptography" -__version__ = "3.3.1" +__version__ = "3.3.2" __author__ = "The cryptography developers" __email__ = "cryptography-dev@python.org" __license__ = "BSD or Apache License, Version 2.0" -__copyright__ = "Copyright 2013-2020 %s" % __author__ +__copyright__ = "Copyright 2013-2021 %s" % __author__