summaryrefslogtreecommitdiff
path: root/src/cryptography
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2023-03-19 21:41:48 -0400
committerGitHub <noreply@github.com>2023-03-20 09:41:48 +0800
commit45a5100e4ee2c154981aa0d6fbcf8d2f751f50f8 (patch)
treeda322e32ece9ee26ec6def0badc628762533c73b /src/cryptography
parent7a5170629f0ba7ce4a8b46b005cd9a5c35e06d3f (diff)
downloadcryptography-45a5100e4ee2c154981aa0d6fbcf8d2f751f50f8.tar.gz
Simplify/unify Rust and Python OpenSSL error handling (#8552)
Diffstat (limited to 'src/cryptography')
-rw-r--r--src/cryptography/exceptions.py6
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py21
-rw-r--r--src/cryptography/hazmat/backends/openssl/dh.py4
-rw-r--r--src/cryptography/hazmat/backends/openssl/rsa.py6
-rw-r--r--src/cryptography/hazmat/backends/openssl/utils.py4
-rw-r--r--src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi10
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py82
7 files changed, 33 insertions, 100 deletions
diff --git a/src/cryptography/exceptions.py b/src/cryptography/exceptions.py
index b0e2b4dac..5e69c1192 100644
--- a/src/cryptography/exceptions.py
+++ b/src/cryptography/exceptions.py
@@ -8,9 +8,7 @@ import typing
from cryptography import utils
if typing.TYPE_CHECKING:
- from cryptography.hazmat.bindings.openssl.binding import (
- _OpenSSLErrorWithText,
- )
+ from cryptography.hazmat.bindings._rust import openssl as rust_openssl
class _Reasons(utils.Enum):
@@ -58,7 +56,7 @@ class InvalidSignature(Exception):
class InternalError(Exception):
def __init__(
- self, msg: str, err_code: typing.List["_OpenSSLErrorWithText"]
+ self, msg: str, err_code: typing.List["rust_openssl.OpenSSLError"]
) -> None:
super().__init__(msg)
self.err_code = err_code
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index 0610b254e..3415863b3 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -57,6 +57,7 @@ from cryptography.hazmat.backends.openssl.x25519 import (
_X25519PrivateKey,
_X25519PublicKey,
)
+from cryptography.hazmat.bindings._rust import openssl as rust_openssl
from cryptography.hazmat.bindings.openssl import binding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives._asymmetric import AsymmetricPadding
@@ -209,7 +210,7 @@ class Backend:
def openssl_assert(
self,
ok: bool,
- errors: typing.Optional[typing.List[binding._OpenSSLError]] = None,
+ errors: typing.Optional[typing.List[rust_openssl.OpenSSLError]] = None,
) -> None:
return binding._openssl_assert(self._lib, ok, errors=errors)
@@ -484,13 +485,8 @@ class Backend:
self.openssl_assert(res == 1)
return self._ffi.buffer(buf)[:]
- def _consume_errors(self) -> typing.List[binding._OpenSSLError]:
- return binding._consume_errors()
-
- def _consume_errors_with_text(
- self,
- ) -> typing.List[binding._OpenSSLErrorWithText]:
- return binding._consume_errors_with_text()
+ def _consume_errors(self) -> typing.List[rust_openssl.OpenSSLError]:
+ return rust_openssl.capture_error_stack()
def _bn_to_int(self, bn) -> int:
assert bn != self._ffi.NULL
@@ -760,7 +756,7 @@ class Backend:
elif key_type == self._lib.EVP_PKEY_EC:
ec_cdata = self._lib.EVP_PKEY_get1_EC_KEY(evp_pkey)
if ec_cdata == self._ffi.NULL:
- errors = self._consume_errors_with_text()
+ errors = self._consume_errors()
raise ValueError("Unable to load EC key", errors)
ec_cdata = self._ffi.gc(ec_cdata, self._lib.EC_KEY_free)
return _EllipticCurvePublicKey(self, ec_cdata, evp_pkey)
@@ -1208,13 +1204,12 @@ class Backend:
raise ValueError("Unsupported public key algorithm.")
else:
- errors_with_text = binding._errors_with_text(errors)
raise ValueError(
"Could not deserialize key data. The data may be in an "
"incorrect format, it may be encrypted with an unsupported "
"algorithm, or it may be an unsupported key type (e.g. EC "
"curves with explicit parameters).",
- errors_with_text,
+ errors,
)
def elliptic_curve_supported(self, curve: ec.EllipticCurve) -> bool:
@@ -1708,7 +1703,7 @@ class Backend:
dh_param_cdata, key_size, generator, self._ffi.NULL
)
if res != 1:
- errors = self._consume_errors_with_text()
+ errors = self._consume_errors()
raise ValueError("Unable to generate DH parameters", errors)
return _DHParameters(self, dh_param_cdata)
@@ -2051,7 +2046,7 @@ class Backend:
length,
)
if res != 1:
- errors = self._consume_errors_with_text()
+ errors = self._consume_errors()
# memory required formula explained here:
# https://blog.filippo.io/the-scrypt-parameters/
min_memory = 128 * n * r // (1024**2)
diff --git a/src/cryptography/hazmat/backends/openssl/dh.py b/src/cryptography/hazmat/backends/openssl/dh.py
index c429c0239..87d6fb8af 100644
--- a/src/cryptography/hazmat/backends/openssl/dh.py
+++ b/src/cryptography/hazmat/backends/openssl/dh.py
@@ -188,10 +188,10 @@ class _DHPrivateKey(dh.DHPrivateKey):
def _exchange_assert(self, ok: bool) -> None:
if not ok:
- errors_with_text = self._backend._consume_errors_with_text()
+ errors = self._backend._consume_errors()
raise ValueError(
"Error computing shared key.",
- errors_with_text,
+ errors,
)
def public_key(self) -> dh.DHPublicKey:
diff --git a/src/cryptography/hazmat/backends/openssl/rsa.py b/src/cryptography/hazmat/backends/openssl/rsa.py
index c04cae029..c960105e7 100644
--- a/src/cryptography/hazmat/backends/openssl/rsa.py
+++ b/src/cryptography/hazmat/backends/openssl/rsa.py
@@ -285,7 +285,7 @@ def _rsa_sig_sign(
buf = backend._ffi.new("unsigned char[]", buflen[0])
res = backend._lib.EVP_PKEY_sign(pkey_ctx, buf, buflen, data, len(data))
if res != 1:
- errors = backend._consume_errors_with_text()
+ errors = backend._consume_errors()
raise ValueError(
"Digest or salt length too long for key size. Use a larger key "
"or shorter salt length if you are specifying a PSS salt",
@@ -380,7 +380,7 @@ class _RSAPrivateKey(RSAPrivateKey):
if not unsafe_skip_rsa_key_validation:
res = backend._lib.RSA_check_key(rsa_cdata)
if res != 1:
- errors = backend._consume_errors_with_text()
+ errors = backend._consume_errors()
raise ValueError("Invalid private key", errors)
# 2 is prime and passes an RSA key check, so we also check
# if p and q are odd just to be safe.
@@ -392,7 +392,7 @@ class _RSAPrivateKey(RSAPrivateKey):
p_odd = backend._lib.BN_is_odd(p[0])
q_odd = backend._lib.BN_is_odd(q[0])
if p_odd != 1 or q_odd != 1:
- errors = backend._consume_errors_with_text()
+ errors = backend._consume_errors()
raise ValueError("Invalid private key", errors)
self._backend = backend
diff --git a/src/cryptography/hazmat/backends/openssl/utils.py b/src/cryptography/hazmat/backends/openssl/utils.py
index 019f412c7..64b4a8334 100644
--- a/src/cryptography/hazmat/backends/openssl/utils.py
+++ b/src/cryptography/hazmat/backends/openssl/utils.py
@@ -35,8 +35,8 @@ def _evp_pkey_derive(backend: "Backend", evp_pkey, peer_public_key) -> bytes:
buf = backend._ffi.new("unsigned char[]", keylen[0])
res = backend._lib.EVP_PKEY_derive(ctx, buf, keylen)
if res != 1:
- errors_with_text = backend._consume_errors_with_text()
- raise ValueError("Error computing shared key.", errors_with_text)
+ errors = backend._consume_errors()
+ raise ValueError("Error computing shared key.", errors)
return backend._ffi.buffer(buf, keylen[0])[:]
diff --git a/src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi b/src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi
index 0e292a2fe..d583500df 100644
--- a/src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi
+++ b/src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi
@@ -6,3 +6,13 @@ import typing
def openssl_version() -> int: ...
def raise_openssl_error() -> typing.NoReturn: ...
+def capture_error_stack() -> typing.List[OpenSSLError]: ...
+
+class OpenSSLError:
+ @property
+ def lib(self) -> int: ...
+ @property
+ def reason(self) -> int: ...
+ @property
+ def reason_text(self) -> bytes: ...
+ def _lib_reason_match(self, lib: int, reason: int) -> bool: ...
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index b0fc8de28..7327157fd 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -16,84 +16,14 @@ from cryptography.hazmat.bindings._rust import _openssl, openssl
from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES
-class _OpenSSLErrorWithText(typing.NamedTuple):
- code: int
- lib: int
- reason: int
- reason_text: bytes
-
- @classmethod
- def from_err(cls, err: "_OpenSSLError") -> "_OpenSSLErrorWithText":
- buf = _openssl.ffi.new("char[]", 256)
- _openssl.lib.ERR_error_string_n(err.code, buf, len(buf))
- err_text_reason: bytes = _openssl.ffi.string(buf)
-
- return _OpenSSLErrorWithText(
- err.code, err.lib, err.reason, err_text_reason
- )
-
-
-class _OpenSSLError:
- def __init__(self, code: int, lib: int, reason: int):
- self._code = code
- self._lib = lib
- self._reason = reason
-
- @classmethod
- def from_code(cls, code: int) -> "_OpenSSLError":
- err_lib: int = _openssl.lib.ERR_GET_LIB(code)
- err_reason: int = _openssl.lib.ERR_GET_REASON(code)
- return cls(code, err_lib, err_reason)
-
- def _lib_reason_match(self, lib: int, reason: int) -> bool:
- return lib == self.lib and reason == self.reason
-
- @property
- def code(self) -> int:
- return self._code
-
- @property
- def lib(self) -> int:
- return self._lib
-
- @property
- def reason(self) -> int:
- return self._reason
-
-
-def _consume_errors() -> typing.List[_OpenSSLError]:
- errors = []
- while True:
- code: int = _openssl.lib.ERR_get_error()
- if code == 0:
- break
-
- errors.append(_OpenSSLError.from_code(code))
-
- return errors
-
-
-def _errors_with_text(
- errors: typing.List[_OpenSSLError],
-) -> typing.List[_OpenSSLErrorWithText]:
- errors_with_text = []
- for err in errors:
- errors_with_text.append(_OpenSSLErrorWithText.from_err(err))
-
- return errors_with_text
-
-
-def _consume_errors_with_text():
- return _errors_with_text(_consume_errors())
-
-
def _openssl_assert(
- lib, ok: bool, errors: typing.Optional[typing.List[_OpenSSLError]] = None
+ lib,
+ ok: bool,
+ errors: typing.Optional[typing.List[openssl.OpenSSLError]] = None,
) -> None:
if not ok:
if errors is None:
- errors = _consume_errors()
- errors_with_text = _errors_with_text(errors)
+ errors = openssl.capture_error_stack()
raise InternalError(
"Unknown OpenSSL error. This error is commonly encountered when "
@@ -102,8 +32,8 @@ def _openssl_assert(
"OpenSSL try disabling it before reporting a bug. Otherwise "
"please file an issue at https://github.com/pyca/cryptography/"
"issues with information on how to reproduce "
- "this. ({!r})".format(errors_with_text),
- errors_with_text,
+ "this. ({!r})".format(errors),
+ errors,
)