diff --git a/backport-CVE-2020-36242-pre1.patch b/backport-CVE-2020-36242-pre1.patch new file mode 100644 index 0000000000000000000000000000000000000000..7466965a65903487bceb0204cc28280c66c3c243 --- /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 | 34 ++++++++++++------- + tests/hazmat/primitives/test_ciphers.py | 17 ++++++++++ + 2 files changed, 38 insertions(+), 13 deletions(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/ciphers.py b/src/cryptography/hazmat/backends/openssl/ciphers.py +index 6092803b7f..171605a683 100644 +--- a/src/cryptography/hazmat/backends/openssl/ciphers.py ++++ b/src/cryptography/hazmat/backends/openssl/ciphers.py +@@ -17,6 +17,7 @@ + class _CipherContext(object): + _ENCRYPT = 1 + _DECRYPT = 0 ++ _MAX_CHUNK_SIZE = 2 ** 31 + + def __init__(self, backend, cipher, mode, operation): + self._backend = backend +@@ -124,25 +125,32 @@ def update(self, data): + 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): + if ( +diff --git a/tests/hazmat/primitives/test_ciphers.py b/tests/hazmat/primitives/test_ciphers.py +index 185c213591..104e679e54 100644 +--- a/tests/hazmat/primitives/test_ciphers.py ++++ b/tests/hazmat/primitives/test_ciphers.py +@@ -316,3 +316,20 @@ def test_update_into_buffer_too_small_gcm(self, backend): + 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 diff --git a/backport-CVE-2020-36242-pre2.patch b/backport-CVE-2020-36242-pre2.patch new file mode 100644 index 0000000000000000000000000000000000000000..fe1ca1ac28e4f60266db2b88fc22549db5242f4d --- /dev/null +++ b/backport-CVE-2020-36242-pre2.patch @@ -0,0 +1,40 @@ +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 171605a683..1e805d235a 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 ++ _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 104e679e54..4d82f0c13f 100644 +--- a/tests/hazmat/primitives/test_ciphers.py ++++ b/tests/hazmat/primitives/test_ciphers.py +@@ -333,3 +333,12 @@ def test_update_into_auto_chunking(self, backend, monkeypatch): + 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) diff --git a/backport-CVE-2020-36242.patch b/backport-CVE-2020-36242.patch new file mode 100644 index 0000000000000000000000000000000000000000..e96bc560c73e249ef49b8983077261235647444d --- /dev/null +++ b/backport-CVE-2020-36242.patch @@ -0,0 +1,24 @@ +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) + +--- + CHANGELOG.rst | 9 +++++++++ + src/cryptography/hazmat/backends/openssl/ciphers.py | 2 +- + 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 2b10681b31..0f96795fdc 100644 +--- a/src/cryptography/hazmat/backends/openssl/ciphers.py ++++ b/src/cryptography/hazmat/backends/openssl/ciphers.py +@@ -16,7 +16,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/python-cryptography.spec b/python-cryptography.spec index fa158280072717821a395e59aefd15dbd2a47518..cd0e27708ee4abf5afaa585acffb044d5e4ba16a 100644 --- a/python-cryptography.spec +++ b/python-cryptography.spec @@ -1,11 +1,14 @@ Name: python-cryptography Version: 3.0 -Release: 2 +Release: 3 Summary: PyCA's cryptography library License: ASL 2.0 or BSD URL: https://cryptography.io/en/latest/ Source0: https://files.pythonhosted.org/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 @@ -69,6 +72,12 @@ PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest -k "not (test_ %doc README.rst docs %changelog +* Wed Feb 24 2021 shixuantong - 3.0-3 +- Type:CVE +- ID:CVE-2020-36242 +- SUG:NA +- DESC:fix CVE-2020-36242 + * Tue Aug 11 2020 tianwei -3.0-2 - Type:enhancement - ID:NA