From 7ed30404a5eb56e96e042d9e757ca6e742bf9c64 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 27 Jun 2023 07:39:58 -0400 Subject: [PATCH] Stop explicitly enabling RSA blinding It is on by default in OpenSSL, going back at least as far 1.1.1d, and probably much farther. --- .../hazmat/backends/openssl/rsa.py | 25 ------------ tests/hazmat/primitives/test_rsa.py | 39 ------------------- 2 files changed, 64 deletions(-) diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py index ef27d4ead570..b9c96a78faa1 100644 --- a/src/cryptography/hazmat/backends/openssl/rsa.py +++ b/src/cryptography/hazmat/backends/openssl/rsa.py @@ -4,7 +4,6 @@ from __future__ import annotations -import threading import typing from cryptography.exceptions import ( @@ -400,9 +399,6 @@ def __init__( self._backend = backend self._rsa_cdata = rsa_cdata self._evp_pkey = evp_pkey - # Used for lazy blinding - self._blinded = False - self._blinding_lock = threading.Lock() n = self._backend._ffi.new("BIGNUM **") self._backend._lib.RSA_get0_key( @@ -414,31 +410,11 @@ def __init__( self._backend.openssl_assert(n[0] != self._backend._ffi.NULL) self._key_size = self._backend._lib.BN_num_bits(n[0]) - def _enable_blinding(self) -> None: - # If you call blind on an already blinded RSA key OpenSSL will turn - # it off and back on, which is a performance hit we want to avoid. - if not self._blinded: - with self._blinding_lock: - self._non_threadsafe_enable_blinding() - - def _non_threadsafe_enable_blinding(self) -> None: - # This is only a separate function to allow for testing to cover both - # branches. It should never be invoked except through _enable_blinding. - # Check if it's not True again in case another thread raced past the - # first non-locked check. - if not self._blinded: - res = self._backend._lib.RSA_blinding_on( - self._rsa_cdata, self._backend._ffi.NULL - ) - self._backend.openssl_assert(res == 1) - self._blinded = True - @property def key_size(self) -> int: return self._key_size def decrypt(self, ciphertext: bytes, padding: AsymmetricPadding) -> bytes: - self._enable_blinding() key_size_bytes = (self.key_size + 7) // 8 if key_size_bytes != len(ciphertext): raise ValueError("Ciphertext length must be equal to key size.") @@ -508,7 +484,6 @@ def sign( padding: AsymmetricPadding, algorithm: typing.Union[asym_utils.Prehashed, hashes.HashAlgorithm], ) -> bytes: - self._enable_blinding() data, algorithm = _calculate_digest_and_algorithm(data, algorithm) return _rsa_sig_sign(self._backend, padding, algorithm, self, data) diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 85459a59461a..753feca37923 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -451,45 +451,6 @@ def test_oaep_wrong_label(self, rsa_key_2048, enclabel, declabel, backend): ), ) - @pytest.mark.supported( - only_if=lambda backend: backend.rsa_encryption_supported( - padding.PKCS1v15() - ), - skip_message="Does not support PKCS1v1.5.", - ) - def test_lazy_blinding(self, backend): - # We don't want to reuse the rsa_key_2048 fixture here because lazy - # blinding mutates the object to add the blinding factor on - # the first call to decrypt/sign. Since we reuse rsa_key_2048 in - # many tests we can't properly test blinding, which will (likely) - # already be set on the fixture. - private_key = RSA_KEY_2048.private_key( - unsafe_skip_rsa_key_validation=True - ) - public_key = private_key.public_key() - msg = b"encrypt me!" - ct = public_key.encrypt( - msg, - padding.PKCS1v15(), - ) - assert private_key._blinded is False # type: ignore[attr-defined] - pt = private_key.decrypt( - ct, - padding.PKCS1v15(), - ) - assert private_key._blinded is True # type: ignore[attr-defined] - # Call a second time to cover the branch where blinding - # has already occurred and we don't want to do it again. - pt2 = private_key.decrypt( - ct, - padding.PKCS1v15(), - ) - assert pt == pt2 - assert private_key._blinded is True - # Private method call to cover the racy branch within the lock - private_key._non_threadsafe_enable_blinding() - assert private_key._blinded is True - class TestRSASignature: @pytest.mark.supported(