Skip to content

Commit

Permalink
Attempt to mitigate Bleichenbacher attacks on RSA decryption
Browse files Browse the repository at this point in the history
  • Loading branch information
alex committed Oct 26, 2020
1 parent ada53e7 commit ce1bef6
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 15 deletions.
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

0 comments on commit ce1bef6

Please sign in to comment.