78efc47b99
GitOrigin-RevId: 83cbad92d73216bb0d9187c56cce0b91f9121d5a
76 lines
3 KiB
Diff
76 lines
3 KiB
Diff
Backported of:
|
|
|
|
From 58494b41d6ecb0f56b7c5f05d5f5e3ca0320d494 Mon Sep 17 00:00:00 2001
|
|
From: Alex Gaynor <alex.gaynor@gmail.com>
|
|
Date: Sun, 25 Oct 2020 21:16:42 -0400
|
|
Subject: [PATCH] Attempt to mitigate Bleichenbacher attacks on RSA decryption
|
|
(#5507)
|
|
|
|
diff --git a/docs/spelling_wordlist.txt b/docs/spelling_wordlist.txt
|
|
index 6e4675d..ce66c28 100644
|
|
--- a/docs/spelling_wordlist.txt
|
|
+++ b/docs/spelling_wordlist.txt
|
|
@@ -6,6 +6,7 @@ backend
|
|
Backends
|
|
backends
|
|
bcrypt
|
|
+Bleichenbacher
|
|
Blowfish
|
|
boolean
|
|
Botan
|
|
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
|
|
index 3e4c2fd..6303f95 100644
|
|
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
|
|
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
|
|
@@ -117,40 +117,19 @@ def _enc_dec_rsa_pkey_ctx(backend, key, data, padding_enum, padding):
|
|
|
|
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):
|