From fd5f2e0b6bc0094907444585029ce3e748d62bee Mon Sep 17 00:00:00 2001 From: sxt1001 Date: Wed, 24 Feb 2021 18:08:00 +0800 Subject: [PATCH] fix CVE-2020-36242 and skip hypothesis tests --- backport-CVE-2020-36242-pre1.patch | 98 ++++++++++++++++++++++++++++++ backport-CVE-2020-36242-pre2.patch | 43 +++++++++++++ backport-CVE-2020-36242.patch | 26 ++++++++ python-cryptography.spec | 13 +++- 4 files changed, 179 insertions(+), 1 deletion(-) create mode 100644 backport-CVE-2020-36242-pre1.patch create mode 100644 backport-CVE-2020-36242-pre2.patch create mode 100644 backport-CVE-2020-36242.patch diff --git a/backport-CVE-2020-36242-pre1.patch b/backport-CVE-2020-36242-pre1.patch new file mode 100644 index 0000000..e41ee14 --- /dev/null +++ b/backport-CVE-2020-36242-pre1.patch @@ -0,0 +1,98 @@ +From f90ba1808ee9bd9a13c5673b776484644f29d7ba Mon Sep 17 00:00:00 2001 +From: Paul Kehrer +Date: Sun, 23 Aug 2020 23:41:33 -0500 +Subject: [PATCH] chunked update_into (#5419) + +* chunked update_into + +* all pointer arithmetic all the time + +* review feedback +--- + .../hazmat/backends/openssl/ciphers.py | 30 ++++++++++++++-------- + tests/hazmat/primitives/test_ciphers.py | 17 ++++++++++++ + 2 files changed, 37 insertions(+), 10 deletions(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py +index 94b48f5..8426db9 100644 +--- a/src/cryptography/hazmat/backends/openssl/ciphers.py ++++ b/src/cryptography/hazmat/backends/openssl/ciphers.py +@@ -17,6 +17,7 @@ from cryptography.hazmat.primitives.ciphers import modes + class _CipherContext(object): + _ENCRYPT = 1 + _DECRYPT = 0 ++ _MAX_CHUNK_SIZE = 2 ** 31 + + def __init__(self, backend, cipher, mode, operation): + self._backend = backend +@@ -125,23 +126,32 @@ class _CipherContext(object): + return bytes(buf[:n]) + + def update_into(self, data, buf): +- if len(buf) < (len(data) + self._block_size_bytes - 1): ++ total_data_len = len(data) ++ if len(buf) < (total_data_len + self._block_size_bytes - 1): + raise ValueError( + "buffer must be at least {} bytes for this " + "payload".format(len(data) + self._block_size_bytes - 1) + ) + +- buf = self._backend._ffi.cast( +- "unsigned char *", self._backend._ffi.from_buffer(buf) +- ) ++ data_processed = 0 ++ total_out = 0 + outlen = self._backend._ffi.new("int *") +- res = self._backend._lib.EVP_CipherUpdate( +- self._ctx, buf, outlen, +- self._backend._ffi.from_buffer(data), len(data) +- ) +- self._backend.openssl_assert(res != 0) +- return outlen[0] ++ baseoutbuf = self._backend._ffi.from_buffer(buf) ++ baseinbuf = self._backend._ffi.from_buffer(data) ++ ++ while data_processed != total_data_len: ++ outbuf = baseoutbuf + total_out ++ inbuf = baseinbuf + data_processed ++ inlen = min(self._MAX_CHUNK_SIZE, total_data_len - data_processed) ++ ++ res = self._backend._lib.EVP_CipherUpdate( ++ self._ctx, outbuf, outlen, inbuf, inlen ++ ) ++ self._backend.openssl_assert(res != 0) ++ data_processed += inlen ++ total_out += outlen[0] + ++ return total_out + def finalize(self): + # OpenSSL 1.0.1 on Ubuntu 12.04 (and possibly other distributions) + # appears to have a bug where you must make at least one call to update +diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py +index f29ba9a..b88610e 100644 +--- a/tests/hazmat/primitives/test_ciphers.py ++++ b/tests/hazmat/primitives/test_ciphers.py +@@ -309,3 +309,20 @@ class TestCipherUpdateInto(object): + buf = bytearray(5) + with pytest.raises(ValueError): + encryptor.update_into(b"testing", buf) ++ ++ def test_update_into_auto_chunking(self, backend, monkeypatch): ++ key = b"\x00" * 16 ++ c = ciphers.Cipher(AES(key), modes.ECB(), backend) ++ encryptor = c.encryptor() ++ # Lower max chunk size so we can test chunking ++ monkeypatch.setattr(encryptor._ctx, "_MAX_CHUNK_SIZE", 40) ++ buf = bytearray(527) ++ pt = b"abcdefghijklmnopqrstuvwxyz012345" * 16 # 512 bytes ++ processed = encryptor.update_into(pt, buf) ++ assert processed == 512 ++ decryptor = c.decryptor() ++ # Change max chunk size to verify alternate boundaries don't matter ++ monkeypatch.setattr(decryptor._ctx, "_MAX_CHUNK_SIZE", 73) ++ decbuf = bytearray(527) ++ decprocessed = decryptor.update_into(buf[:processed], decbuf) ++ assert decbuf[:decprocessed] == pt +-- +1.8.3.1 + diff --git a/backport-CVE-2020-36242-pre2.patch b/backport-CVE-2020-36242-pre2.patch new file mode 100644 index 0000000..f2edf51 --- /dev/null +++ b/backport-CVE-2020-36242-pre2.patch @@ -0,0 +1,43 @@ +From 836a92a28fbe9df8c37121e340b91ed9cd519ddd Mon Sep 17 00:00:00 2001 +From: Paul Kehrer +Date: Sun, 25 Oct 2020 06:15:18 -0700 +Subject: [PATCH] chunking didn't actually work (#5499) + +--- + src/cryptography/hazmat/backends/openssl/ciphers.py | 2 +- + tests/hazmat/primitives/test_ciphers.py | 9 +++++++++ + 2 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py +index 26f2b76..cc08e30 100644 +--- a/src/cryptography/hazmat/backends/openssl/ciphers.py ++++ b/src/cryptography/hazmat/backends/openssl/ciphers.py +@@ -17,7 +17,7 @@ from cryptography.hazmat.primitives.ciphers import modes + class _CipherContext(object): + _ENCRYPT = 1 + _DECRYPT = 0 +- _MAX_CHUNK_SIZE = 2 ** 31 ++ _MAX_CHUNK_SIZE = 2 ** 31 - 1 + + def __init__(self, backend, cipher, mode, operation): + self._backend = backend +diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py +index b88610e..fd9048b 100644 +--- a/tests/hazmat/primitives/test_ciphers.py ++++ b/tests/hazmat/primitives/test_ciphers.py +@@ -326,3 +326,12 @@ class TestCipherUpdateInto(object): + decbuf = bytearray(527) + decprocessed = decryptor.update_into(buf[:processed], decbuf) + assert decbuf[:decprocessed] == pt ++ ++ def test_max_chunk_size_fits_in_int32(self, backend): ++ # max chunk must fit in signed int32 or else a call large enough to ++ # cause chunking will result in the very OverflowError we want to ++ # avoid with chunking. ++ key = b"\x00" * 16 ++ c = ciphers.Cipher(AES(key), modes.ECB(), backend) ++ encryptor = c.encryptor() ++ backend._ffi.new("int *", encryptor._ctx._MAX_CHUNK_SIZE) +-- +1.8.3.1 + diff --git a/backport-CVE-2020-36242.patch b/backport-CVE-2020-36242.patch new file mode 100644 index 0000000..8cf6190 --- /dev/null +++ b/backport-CVE-2020-36242.patch @@ -0,0 +1,26 @@ +From 06cbf77371881e80ea4b5e349136dcc53749fc0c Mon Sep 17 00:00:00 2001 +From: Paul Kehrer +Date: Sun, 7 Feb 2021 11:20:09 -0600 +Subject: [PATCH] port changelog and fix back to master for CVE-2020-36242 + (#5748) + +--- + src/cryptography/hazmat/backends/openssl/ciphers.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py +index cc08e30..47c72e9 100644 +--- a/src/cryptography/hazmat/backends/openssl/ciphers.py ++++ b/src/cryptography/hazmat/backends/openssl/ciphers.py +@@ -17,7 +17,7 @@ from cryptography.hazmat.primitives.ciphers import modes + 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 +-- +1.8.3.1 + diff --git a/python-cryptography.spec b/python-cryptography.spec index 1e2f130..d6f32c3 100644 --- a/python-cryptography.spec +++ b/python-cryptography.spec @@ -3,12 +3,16 @@ Name: python-cryptography Version: 2.9.2 -Release: 1 +Release: 2 Summary: PyCA's cryptography library License: ASL 2.0 or BSD URL: https://cryptography.io/en/latest/ Source0: https://pypi.io/packages/source/c/cryptography/cryptography-%{version}.tar.gz +Patch6000: backport-CVE-2020-36242-pre1.patch +Patch6001: backport-CVE-2020-36242-pre2.patch +Patch6002: backport-CVE-2020-36242.patch + BuildRequires: openssl-devel BuildRequires: gcc @@ -99,12 +103,16 @@ pushd %{py3dir} popd %check +# skip hypothesis tests +rm -rf tests/hypothesis # see https://github.com/pyca/cryptography/issues/4885 for the deselected test %if %{with python2} PYTHONPATH=%{buildroot}%{python2_sitearch} %{__python2} -m pytest -k "not (test_buffer_protocol_alternate_modes or test_dh_parameters_supported or test_load_ecdsa_no_named_curve)" %endif pushd %{py3dir} +# skip hypothesis tests +rm -rf tests/hypothesis PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest -k "not (test_buffer_protocol_alternate_modes or test_dh_parameters_supported or test_load_ecdsa_no_named_curve)" popd @@ -129,6 +137,9 @@ popd %doc README.rst docs %changelog +* Wed Feb 24 2021 shixuantong - 2.9.2-2 +- fix CVE-2020-36242 and skip hypothesis tests + * Wed Aug 12 2020 Leo Fang - 2.9.2-1 - Upgrade to version 2.9.2 -- Gitee