File 5507-mitigate-Bleichenbacher-attacks.patch of Package python-cryptography.18655
From ce1bef6f1ee06ac497ca0c837fbd1c7ef6c2472b Mon Sep 17 00:00:00 2001
From: Alex Gaynor <alex.gaynor@gmail.com>
Date: Sun, 25 Oct 2020 19:01:50 -0400
Subject: [PATCH] Attempt to mitigate Bleichenbacher attacks on RSA decryption
---
CHANGELOG.rst | 6 +++++
docs/spelling_wordlist.txt | 1 +
.../hazmat/backends/openssl/rsa.py | 26 ++++++++-----------
3 files changed, 18 insertions(+), 15 deletions(-)
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,14 @@
Changelog
=========
+* **SECURITY ISSUE:** Attempted to make RSA PKCS#1v1.5 decryption
+ more constant time, to protect against Bleichenbacher
+ vulnerabilities. Due to limitations imposed by our API, we
+ cannot completely mitigate this vulnerability and a future
+ release will contain a new API which is designed to be
+ resilient to these for contexts where it is required. Credit to
+ **Hubert Kario** for reporting the issue. *CVE-2020-25659*
+
.. _v2-8:
2.8 - 2019-10-16
--- a/docs/spelling_wordlist.txt
+++ b/docs/spelling_wordlist.txt
@@ -6,6 +6,7 @@ backend
Backends
backends
bcrypt
+Bleichenbacher
Blowfish
boolean
Botan
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -117,40 +117,20 @@ def _enc_dec_rsa_pkey_ctx(backend, key,
outlen = backend._ffi.new("size_t *", buf_size)
buf = backend._ffi.new("unsigned char[]", buf_size)
+ # Everything from this line onwards is written with the goal of
+ # being as constant-time as is practical given the constraints of
+ # Python and our API. See Bleichenbacher's '98 attack on RSA, and
+ # its many many variants. As such, you should not attempt to change
+ # this (particularly to "clean it up") without understanding why it
+ # was written this way (see Chesterton's Fence), and without
+ # measuring to verify you have not introduced observable time
+ # differences.
res = crypt(pkey_ctx, buf, outlen, data, len(data))
+ resbuf = backend._ffi.buffer(buf)[: outlen[0]]
+ backend._lib.ERR_clear_error()
if res <= 0:
- _handle_rsa_enc_dec_error(backend, key)
-
- return backend._ffi.buffer(buf)[:outlen[0]]
-
-
-def _handle_rsa_enc_dec_error(backend, key):
- errors = backend._consume_errors()
- backend.openssl_assert(errors)
- backend.openssl_assert(errors[0].lib == backend._lib.ERR_LIB_RSA)
- if isinstance(key, _RSAPublicKey):
- backend.openssl_assert(
- errors[0].reason == backend._lib.RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE
- )
- raise ValueError(
- "Data too long for key size. Encrypt less data or use a "
- "larger key size."
- )
- else:
- decoding_errors = [
- backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_01,
- backend._lib.RSA_R_BLOCK_TYPE_IS_NOT_02,
- backend._lib.RSA_R_OAEP_DECODING_ERROR,
- # Though this error looks similar to the
- # RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE, this occurs on decrypts,
- # rather than on encrypts
- backend._lib.RSA_R_DATA_TOO_LARGE_FOR_MODULUS,
- ]
- if backend._lib.Cryptography_HAS_RSA_R_PKCS_DECODING_ERROR:
- decoding_errors.append(backend._lib.RSA_R_PKCS_DECODING_ERROR)
-
- backend.openssl_assert(errors[0].reason in decoding_errors)
- raise ValueError("Decryption failed.")
+ raise ValueError("Encryption/decryption failed.")
+ return resbuf
def _rsa_sig_determine_padding(backend, key, padding, algorithm):