Skip to content

Commit

Permalink
Stop explicitly enabling RSA blinding
Browse files Browse the repository at this point in the history
It is on by default in OpenSSL, going back at least as far 1.1.1d, and probably much farther.
  • Loading branch information
alex committed Jun 27, 2023
1 parent 3521933 commit 7ed3040
Show file tree
Hide file tree
Showing 2 changed files with 0 additions and 64 deletions.
25 changes: 0 additions & 25 deletions src/cryptography/hazmat/backends/openssl/rsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

from __future__ import annotations

import threading
import typing

from cryptography.exceptions import (
Expand Down Expand Up @@ -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(
Expand All @@ -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.")
Expand Down Expand Up @@ -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)

Expand Down
39 changes: 0 additions & 39 deletions tests/hazmat/primitives/test_rsa.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit 7ed3040

Please sign in to comment.