Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempt to mitigate Bleichenbacher attacks on RSA decryption #5507

Merged
merged 1 commit into from Oct 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -8,6 +8,12 @@ Changelog

.. note:: This version is not yet released and is under active development.

* **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*
* Support for OpenSSL 1.0.2 has been removed. Users on older version of OpenSSL
will need to upgrade.
* Added basic support for PKCS7 signing (including SMIME) via
Expand Down
1 change: 1 addition & 0 deletions docs/spelling_wordlist.txt
Expand Up @@ -7,6 +7,7 @@ backend
Backends
backends
bcrypt
Bleichenbacher
Blowfish
boolean
Botan
Expand Down
26 changes: 11 additions & 15 deletions src/cryptography/hazmat/backends/openssl/rsa.py
Expand Up @@ -119,23 +119,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_with_text()
if isinstance(key, _RSAPublicKey):
raise ValueError(
"Data too long for key size. Encrypt less data or use a "
"larger key size.",
errors,
)
else:
raise ValueError("Decryption failed.", errors)
raise ValueError("Encryption/decryption failed.")
return resbuf


def _rsa_sig_determine_padding(backend, key, padding, algorithm):
Expand Down