summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2023-03-16 01:05:33 -0400
committerGitHub <noreply@github.com>2023-03-16 13:05:33 +0800
commit8882c3c88d082f29b66fd2e72cb92273da96c427 (patch)
treec82d222726a8b58aa2834649e2d65a90a6d3da67
parentd6866c82b48283ee773054ba95b76b5f315ee556 (diff)
downloadcryptography-8882c3c88d082f29b66fd2e72cb92273da96c427.tar.gz
Support handling OpenSSL errors from Rust code (#8530)
-rw-r--r--src/cryptography/hazmat/backends/openssl/backend.py4
-rw-r--r--src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi (renamed from src/cryptography/hazmat/bindings/_rust/openssl.pyi)3
-rw-r--r--src/cryptography/hazmat/bindings/openssl/binding.py41
-rw-r--r--src/rust/src/asn1.rs104
-rw-r--r--src/rust/src/error.rs167
-rw-r--r--src/rust/src/lib.rs7
-rw-r--r--src/rust/src/oid.rs2
-rw-r--r--src/rust/src/pkcs7.rs3
-rw-r--r--src/rust/src/x509/certificate.rs2
-rw-r--r--src/rust/src/x509/common.rs3
-rw-r--r--src/rust/src/x509/crl.rs2
-rw-r--r--src/rust/src/x509/csr.rs5
-rw-r--r--src/rust/src/x509/extensions.rs5
-rw-r--r--src/rust/src/x509/ocsp.rs2
-rw-r--r--src/rust/src/x509/ocsp_req.rs5
-rw-r--r--src/rust/src/x509/ocsp_resp.rs3
-rw-r--r--src/rust/src/x509/sct.rs2
-rw-r--r--src/rust/src/x509/sign.rs2
-rw-r--r--tests/hazmat/bindings/test_openssl.py26
19 files changed, 246 insertions, 142 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/backend.py b/src/cryptography/hazmat/backends/openssl/backend.py
index a8964f365..0610b254e 100644
--- a/src/cryptography/hazmat/backends/openssl/backend.py
+++ b/src/cryptography/hazmat/backends/openssl/backend.py
@@ -485,12 +485,12 @@ class Backend:
return self._ffi.buffer(buf)[:]
def _consume_errors(self) -> typing.List[binding._OpenSSLError]:
- return binding._consume_errors(self._lib)
+ return binding._consume_errors()
def _consume_errors_with_text(
self,
) -> typing.List[binding._OpenSSLErrorWithText]:
- return binding._consume_errors_with_text(self._lib)
+ return binding._consume_errors_with_text()
def _bn_to_int(self, bn) -> int:
assert bn != self._ffi.NULL
diff --git a/src/cryptography/hazmat/bindings/_rust/openssl.pyi b/src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi
index 8cd7b3062..0e292a2fe 100644
--- a/src/cryptography/hazmat/bindings/_rust/openssl.pyi
+++ b/src/cryptography/hazmat/bindings/_rust/openssl/__init__.pyi
@@ -2,4 +2,7 @@
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.
+import typing
+
def openssl_version() -> int: ...
+def raise_openssl_error() -> typing.NoReturn: ...
diff --git a/src/cryptography/hazmat/bindings/openssl/binding.py b/src/cryptography/hazmat/bindings/openssl/binding.py
index 680164f41..b0fc8de28 100644
--- a/src/cryptography/hazmat/bindings/openssl/binding.py
+++ b/src/cryptography/hazmat/bindings/openssl/binding.py
@@ -22,6 +22,16 @@ class _OpenSSLErrorWithText(typing.NamedTuple):
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):
@@ -29,6 +39,12 @@ class _OpenSSLError:
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
@@ -45,17 +61,14 @@ class _OpenSSLError:
return self._reason
-def _consume_errors(lib) -> typing.List[_OpenSSLError]:
+def _consume_errors() -> typing.List[_OpenSSLError]:
errors = []
while True:
- code: int = lib.ERR_get_error()
+ code: int = _openssl.lib.ERR_get_error()
if code == 0:
break
- err_lib: int = lib.ERR_GET_LIB(code)
- err_reason: int = lib.ERR_GET_REASON(code)
-
- errors.append(_OpenSSLError(code, err_lib, err_reason))
+ errors.append(_OpenSSLError.from_code(code))
return errors
@@ -65,21 +78,13 @@ def _errors_with_text(
) -> typing.List[_OpenSSLErrorWithText]:
errors_with_text = []
for err in errors:
- 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)
-
- errors_with_text.append(
- _OpenSSLErrorWithText(
- err.code, err.lib, err.reason, err_text_reason
- )
- )
+ errors_with_text.append(_OpenSSLErrorWithText.from_err(err))
return errors_with_text
-def _consume_errors_with_text(lib):
- return _errors_with_text(_consume_errors(lib))
+def _consume_errors_with_text():
+ return _errors_with_text(_consume_errors())
def _openssl_assert(
@@ -87,7 +92,7 @@ def _openssl_assert(
) -> None:
if not ok:
if errors is None:
- errors = _consume_errors(lib)
+ errors = _consume_errors()
errors_with_text = _errors_with_text(errors)
raise InternalError(
diff --git a/src/rust/src/asn1.rs b/src/rust/src/asn1.rs
index 72dc7101d..0bc57341e 100644
--- a/src/rust/src/asn1.rs
+++ b/src/rust/src/asn1.rs
@@ -2,81 +2,12 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509::Name;
use pyo3::basic::CompareOp;
use pyo3::types::IntoPyDict;
use pyo3::ToPyObject;
-pub enum CryptographyError {
- Asn1Parse(asn1::ParseError),
- Asn1Write(asn1::WriteError),
- Py(pyo3::PyErr),
-}
-
-impl From<asn1::ParseError> for CryptographyError {
- fn from(e: asn1::ParseError) -> CryptographyError {
- CryptographyError::Asn1Parse(e)
- }
-}
-
-impl From<asn1::WriteError> for CryptographyError {
- fn from(e: asn1::WriteError) -> CryptographyError {
- CryptographyError::Asn1Write(e)
- }
-}
-
-impl From<pyo3::PyErr> for CryptographyError {
- fn from(e: pyo3::PyErr) -> CryptographyError {
- CryptographyError::Py(e)
- }
-}
-
-impl From<pyo3::PyDowncastError<'_>> for CryptographyError {
- fn from(e: pyo3::PyDowncastError<'_>) -> CryptographyError {
- CryptographyError::Py(e.into())
- }
-}
-
-impl From<pem::PemError> for CryptographyError {
- fn from(e: pem::PemError) -> CryptographyError {
- CryptographyError::Py(pyo3::exceptions::PyValueError::new_err(format!(
- "Unable to load PEM file. See https://cryptography.io/en/latest/faq/#why-can-t-i-import-my-pem-file for more details. {:?}",
- e
- )))
- }
-}
-
-impl From<CryptographyError> for pyo3::PyErr {
- fn from(e: CryptographyError) -> pyo3::PyErr {
- match e {
- CryptographyError::Asn1Parse(asn1_error) => pyo3::exceptions::PyValueError::new_err(
- format!("error parsing asn1 value: {:?}", asn1_error),
- ),
- CryptographyError::Asn1Write(asn1::WriteError::AllocationError) => {
- pyo3::exceptions::PyMemoryError::new_err(
- "failed to allocate memory while performing ASN.1 serialization",
- )
- }
- CryptographyError::Py(py_error) => py_error,
- }
- }
-}
-
-impl CryptographyError {
- pub(crate) fn add_location(self, loc: asn1::ParseLocation) -> Self {
- match self {
- CryptographyError::Py(e) => CryptographyError::Py(e),
- CryptographyError::Asn1Parse(e) => CryptographyError::Asn1Parse(e.add_location(loc)),
- CryptographyError::Asn1Write(e) => CryptographyError::Asn1Write(e),
- }
- }
-}
-
-// The primary purpose of this alias is for brevity to keep function signatures
-// to a single-line as a work around for coverage issues. See
-// https://github.com/pyca/cryptography/pull/6173
-pub(crate) type CryptographyResult<T = pyo3::PyObject> = Result<T, CryptographyError>;
-
pub(crate) fn py_oid_to_oid(py_oid: &pyo3::PyAny) -> pyo3::PyResult<asn1::ObjectIdentifier> {
Ok(py_oid
.downcast::<pyo3::PyCell<crate::oid::ObjectIdentifier>>()?
@@ -297,36 +228,3 @@ pub(crate) fn create_submodule(py: pyo3::Python<'_>) -> pyo3::PyResult<&pyo3::pr
Ok(submod)
}
-
-#[cfg(test)]
-mod tests {
- use super::CryptographyError;
-
- #[test]
- fn test_cryptographyerror_from() {
- pyo3::prepare_freethreaded_python();
- pyo3::Python::with_gil(|py| {
- let e: CryptographyError = asn1::WriteError::AllocationError.into();
- assert!(matches!(
- e,
- CryptographyError::Asn1Write(asn1::WriteError::AllocationError)
- ));
- let py_e: pyo3::PyErr = e.into();
- assert!(py_e.is_instance::<pyo3::exceptions::PyMemoryError>(py));
-
- let e: CryptographyError =
- pyo3::PyDowncastError::new(py.None().as_ref(py), "abc").into();
- assert!(matches!(e, CryptographyError::Py(_)));
- })
- }
-
- #[test]
- fn test_cryptographyerror_add_location() {
- let py_err = pyo3::PyErr::new::<pyo3::exceptions::PyValueError, _>("Error!");
- CryptographyError::Py(py_err).add_location(asn1::ParseLocation::Field("meh"));
-
- let asn1_write_err = asn1::WriteError::AllocationError;
- CryptographyError::Asn1Write(asn1_write_err)
- .add_location(asn1::ParseLocation::Field("meh"));
- }
-}
diff --git a/src/rust/src/error.rs b/src/rust/src/error.rs
new file mode 100644
index 000000000..ac3da6bd0
--- /dev/null
+++ b/src/rust/src/error.rs
@@ -0,0 +1,167 @@
+// This file is dual licensed under the terms of the Apache License, Version
+// 2.0, and the BSD License. See the LICENSE file in the root of this repository
+// for complete details.
+
+pub enum CryptographyError {
+ Asn1Parse(asn1::ParseError),
+ Asn1Write(asn1::WriteError),
+ Py(pyo3::PyErr),
+ OpenSSL(openssl::error::ErrorStack),
+}
+
+impl From<asn1::ParseError> for CryptographyError {
+ fn from(e: asn1::ParseError) -> CryptographyError {
+ CryptographyError::Asn1Parse(e)
+ }
+}
+
+impl From<asn1::WriteError> for CryptographyError {
+ fn from(e: asn1::WriteError) -> CryptographyError {
+ CryptographyError::Asn1Write(e)
+ }
+}
+
+impl From<pyo3::PyErr> for CryptographyError {
+ fn from(e: pyo3::PyErr) -> CryptographyError {
+ CryptographyError::Py(e)
+ }
+}
+
+impl From<pyo3::PyDowncastError<'_>> for CryptographyError {
+ fn from(e: pyo3::PyDowncastError<'_>) -> CryptographyError {
+ CryptographyError::Py(e.into())
+ }
+}
+
+impl From<openssl::error::ErrorStack> for CryptographyError {
+ fn from(e: openssl::error::ErrorStack) -> CryptographyError {
+ CryptographyError::OpenSSL(e)
+ }
+}
+
+impl From<pem::PemError> for CryptographyError {
+ fn from(e: pem::PemError) -> CryptographyError {
+ CryptographyError::Py(pyo3::exceptions::PyValueError::new_err(format!(
+ "Unable to load PEM file. See https://cryptography.io/en/latest/faq/#why-can-t-i-import-my-pem-file for more details. {:?}",
+ e
+ )))
+ }
+}
+
+impl From<CryptographyError> for pyo3::PyErr {
+ fn from(e: CryptographyError) -> pyo3::PyErr {
+ match e {
+ CryptographyError::Asn1Parse(asn1_error) => pyo3::exceptions::PyValueError::new_err(
+ format!("error parsing asn1 value: {:?}", asn1_error),
+ ),
+ CryptographyError::Asn1Write(asn1::WriteError::AllocationError) => {
+ pyo3::exceptions::PyMemoryError::new_err(
+ "failed to allocate memory while performing ASN.1 serialization",
+ )
+ }
+ CryptographyError::Py(py_error) => py_error,
+ CryptographyError::OpenSSL(error_stack) => {
+ let gil = pyo3::Python::acquire_gil();
+ let py = gil.python();
+
+ let internal_error = py
+ .import("cryptography.exceptions")
+ .expect("Failed to import cryptography module")
+ .getattr(crate::intern!(py, "InternalError"))
+ .expect("Failed to get InternalError attribute");
+
+ let binding_mod = py
+ .import("cryptography.hazmat.bindings.openssl.binding")
+ .expect("Failed to import cryptography module");
+
+ let openssl_error = binding_mod
+ .getattr(crate::intern!(py, "_OpenSSLError"))
+ .expect("Failed to get _OpenSSL attribute");
+ let openssl_error_with_text = binding_mod
+ .getattr(crate::intern!(py, "_OpenSSLErrorWithText"))
+ .expect("Failed to get _OpenSSLErrorWithText attribute");
+
+ let errors = pyo3::types::PyList::empty(py);
+ for e in error_stack.errors() {
+ let err = openssl_error
+ .call_method1("from_code", (e.code(),))
+ .expect("Failed to call from_code");
+
+ errors
+ .append(
+ openssl_error_with_text
+ .call_method1("from_err", (err,))
+ .expect("Failed to call from_err"),
+ )
+ .expect("List append failed");
+ }
+ pyo3::PyErr::from_instance(
+ internal_error
+ .call1((
+ "Unknown OpenSSL error. This error is commonly encountered
+ when another library is not cleaning up the OpenSSL error
+ stack. If you are using cryptography with another library
+ that uses 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.",
+ errors,
+ ))
+ .expect("Failed to create InternalError"),
+ )
+ }
+ }
+ }
+}
+
+impl CryptographyError {
+ pub(crate) fn add_location(self, loc: asn1::ParseLocation) -> Self {
+ match self {
+ CryptographyError::Py(e) => CryptographyError::Py(e),
+ CryptographyError::Asn1Parse(e) => CryptographyError::Asn1Parse(e.add_location(loc)),
+ CryptographyError::Asn1Write(e) => CryptographyError::Asn1Write(e),
+ CryptographyError::OpenSSL(e) => CryptographyError::OpenSSL(e),
+ }
+ }
+}
+
+// The primary purpose of this alias is for brevity to keep function signatures
+// to a single-line as a work around for coverage issues. See
+// https://github.com/pyca/cryptography/pull/6173
+pub(crate) type CryptographyResult<T = pyo3::PyObject> = Result<T, CryptographyError>;
+
+#[cfg(test)]
+mod tests {
+ use super::CryptographyError;
+
+ #[test]
+ fn test_cryptographyerror_from() {
+ pyo3::prepare_freethreaded_python();
+ pyo3::Python::with_gil(|py| {
+ let e: CryptographyError = asn1::WriteError::AllocationError.into();
+ assert!(matches!(
+ e,
+ CryptographyError::Asn1Write(asn1::WriteError::AllocationError)
+ ));
+ let py_e: pyo3::PyErr = e.into();
+ assert!(py_e.is_instance::<pyo3::exceptions::PyMemoryError>(py));
+
+ let e: CryptographyError =
+ pyo3::PyDowncastError::new(py.None().as_ref(py), "abc").into();
+ assert!(matches!(e, CryptographyError::Py(_)));
+ })
+ }
+
+ #[test]
+ fn test_cryptographyerror_add_location() {
+ let py_err = pyo3::PyErr::new::<pyo3::exceptions::PyValueError, _>("Error!");
+ CryptographyError::Py(py_err).add_location(asn1::ParseLocation::Field("meh"));
+
+ let asn1_write_err = asn1::WriteError::AllocationError;
+ CryptographyError::Asn1Write(asn1_write_err)
+ .add_location(asn1::ParseLocation::Field("meh"));
+
+ let openssl_error = openssl::error::ErrorStack::get();
+ CryptographyError::from(openssl_error).add_location(asn1::ParseLocation::Field("meh"));
+ }
+}
diff --git a/src/rust/src/lib.rs b/src/rust/src/lib.rs
index c3cb25154..d5de05932 100644
--- a/src/rust/src/lib.rs
+++ b/src/rust/src/lib.rs
@@ -10,6 +10,7 @@
#![allow(unknown_lints, clippy::borrow_deref_ref)]
mod asn1;
+mod error;
mod intern;
pub(crate) mod oid;
mod pkcs7;
@@ -95,6 +96,11 @@ fn openssl_version() -> i64 {
openssl::version::number()
}
+#[pyo3::prelude::pyfunction]
+fn raise_openssl_error() -> crate::error::CryptographyResult<()> {
+ Err(openssl::error::ErrorStack::get().into())
+}
+
#[pyo3::prelude::pymodule]
fn _rust(py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()> {
m.add_function(pyo3::wrap_pyfunction!(check_pkcs7_padding, m)?)?;
@@ -133,6 +139,7 @@ fn _rust(py: pyo3::Python<'_>, m: &pyo3::types::PyModule) -> pyo3::PyResult<()>
let openssl_mod = pyo3::prelude::PyModule::new(py, "openssl")?;
openssl_mod.add_function(pyo3::wrap_pyfunction!(openssl_version, m)?)?;
+ openssl_mod.add_function(pyo3::wrap_pyfunction!(raise_openssl_error, m)?)?;
m.add_submodule(openssl_mod)?;
Ok(())
diff --git a/src/rust/src/oid.rs b/src/rust/src/oid.rs
index c172310c0..a13668579 100644
--- a/src/rust/src/oid.rs
+++ b/src/rust/src/oid.rs
@@ -2,7 +2,7 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::CryptographyResult;
+use crate::error::CryptographyResult;
use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
diff --git a/src/rust/src/pkcs7.rs b/src/rust/src/pkcs7.rs
index 557c09be1..93d9a11e4 100644
--- a/src/rust/src/pkcs7.rs
+++ b/src/rust/src/pkcs7.rs
@@ -2,7 +2,8 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{encode_der_data, CryptographyResult};
+use crate::asn1::encode_der_data;
+use crate::error::CryptographyResult;
use crate::x509;
use chrono::Timelike;
diff --git a/src/rust/src/x509/certificate.rs b/src/rust/src/x509/certificate.rs
index 39d0ebfb5..1a9820e5e 100644
--- a/src/rust/src/x509/certificate.rs
+++ b/src/rust/src/x509/certificate.rs
@@ -4,8 +4,8 @@
use crate::asn1::{
big_byte_slice_to_py_int, encode_der_data, oid_to_py_oid, py_uint_to_big_endian_bytes,
- CryptographyError, CryptographyResult,
};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::{crl, extensions, oid, sct, sign, Asn1ReadableOrWritable};
use chrono::Datelike;
diff --git a/src/rust/src/x509/common.rs b/src/rust/src/x509/common.rs
index e93ec7ec0..a765d6144 100644
--- a/src/rust/src/x509/common.rs
+++ b/src/rust/src/x509/common.rs
@@ -2,7 +2,8 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{oid_to_py_oid, py_oid_to_oid, CryptographyError, CryptographyResult};
+use crate::asn1::{oid_to_py_oid, py_oid_to_oid};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use chrono::{Datelike, TimeZone, Timelike};
use pyo3::types::IntoPyDict;
diff --git a/src/rust/src/x509/crl.rs b/src/rust/src/x509/crl.rs
index 75ac22541..c1b5c8c48 100644
--- a/src/rust/src/x509/crl.rs
+++ b/src/rust/src/x509/crl.rs
@@ -4,8 +4,8 @@
use crate::asn1::{
big_byte_slice_to_py_int, encode_der_data, oid_to_py_oid, py_uint_to_big_endian_bytes,
- CryptographyError, CryptographyResult,
};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::{certificate, extensions, oid, sign};
use pyo3::ToPyObject;
diff --git a/src/rust/src/x509/csr.rs b/src/rust/src/x509/csr.rs
index 66ce3413b..e16a58164 100644
--- a/src/rust/src/x509/csr.rs
+++ b/src/rust/src/x509/csr.rs
@@ -2,9 +2,8 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{
- encode_der_data, oid_to_py_oid, py_oid_to_oid, CryptographyError, CryptographyResult,
-};
+use crate::asn1::{encode_der_data, oid_to_py_oid, py_oid_to_oid};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::{certificate, oid, sign};
use asn1::SimpleAsn1Readable;
diff --git a/src/rust/src/x509/extensions.rs b/src/rust/src/x509/extensions.rs
index f8dd28a45..d93e87c0f 100644
--- a/src/rust/src/x509/extensions.rs
+++ b/src/rust/src/x509/extensions.rs
@@ -2,9 +2,8 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{
- py_oid_to_oid, py_uint_to_big_endian_bytes, CryptographyError, CryptographyResult,
-};
+use crate::asn1::{py_oid_to_oid, py_uint_to_big_endian_bytes};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::{certificate, crl, oid, sct};
diff --git a/src/rust/src/x509/ocsp.rs b/src/rust/src/x509/ocsp.rs
index d06487021..a06e7f1cc 100644
--- a/src/rust/src/x509/ocsp.rs
+++ b/src/rust/src/x509/ocsp.rs
@@ -2,7 +2,7 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::CryptographyResult;
+use crate::error::CryptographyResult;
use crate::x509;
use crate::x509::oid;
use once_cell::sync::Lazy;
diff --git a/src/rust/src/x509/ocsp_req.rs b/src/rust/src/x509/ocsp_req.rs
index 078df6050..638caf9b2 100644
--- a/src/rust/src/x509/ocsp_req.rs
+++ b/src/rust/src/x509/ocsp_req.rs
@@ -2,9 +2,8 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{
- big_byte_slice_to_py_int, py_uint_to_big_endian_bytes, CryptographyError, CryptographyResult,
-};
+use crate::asn1::{big_byte_slice_to_py_int, py_uint_to_big_endian_bytes};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::{extensions, ocsp, oid};
use std::sync::Arc;
diff --git a/src/rust/src/x509/ocsp_resp.rs b/src/rust/src/x509/ocsp_resp.rs
index 35e1d672b..2f878b2c4 100644
--- a/src/rust/src/x509/ocsp_resp.rs
+++ b/src/rust/src/x509/ocsp_resp.rs
@@ -2,7 +2,8 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{big_byte_slice_to_py_int, oid_to_py_oid, CryptographyError, CryptographyResult};
+use crate::asn1::{big_byte_slice_to_py_int, oid_to_py_oid};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::{certificate, crl, extensions, ocsp, oid, py_to_chrono, sct};
use chrono::Timelike;
diff --git a/src/rust/src/x509/sct.rs b/src/rust/src/x509/sct.rs
index 363a8187d..e3f7be4d9 100644
--- a/src/rust/src/x509/sct.rs
+++ b/src/rust/src/x509/sct.rs
@@ -2,7 +2,7 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::CryptographyError;
+use crate::error::CryptographyError;
use pyo3::types::IntoPyDict;
use pyo3::ToPyObject;
use std::collections::hash_map::DefaultHasher;
diff --git a/src/rust/src/x509/sign.rs b/src/rust/src/x509/sign.rs
index 4c1e9664f..33d293b21 100644
--- a/src/rust/src/x509/sign.rs
+++ b/src/rust/src/x509/sign.rs
@@ -2,7 +2,7 @@
// 2.0, and the BSD License. See the LICENSE file in the root of this repository
// for complete details.
-use crate::asn1::{CryptographyError, CryptographyResult};
+use crate::error::{CryptographyError, CryptographyResult};
use crate::x509;
use crate::x509::oid;
diff --git a/tests/hazmat/bindings/test_openssl.py b/tests/hazmat/bindings/test_openssl.py
index 0721fc09a..c80753bd0 100644
--- a/tests/hazmat/bindings/test_openssl.py
+++ b/tests/hazmat/bindings/test_openssl.py
@@ -5,6 +5,7 @@
import pytest
from cryptography.exceptions import InternalError
+from cryptography.hazmat.bindings._rust import openssl as rust_openssl
from cryptography.hazmat.bindings.openssl.binding import (
Binding,
_consume_errors,
@@ -95,7 +96,7 @@ class TestOpenSSL:
-1,
)
b._register_osrandom_engine()
- assert _consume_errors(b.lib) == []
+ assert _consume_errors() == []
def test_version_mismatch(self):
with pytest.raises(ImportError):
@@ -106,3 +107,26 @@ class TestOpenSSL:
_legacy_provider_error(False)
_legacy_provider_error(True)
+
+ def test_rust_internal_error(self):
+ with pytest.raises(InternalError) as exc_info:
+ rust_openssl.raise_openssl_error()
+
+ assert len(exc_info.value.err_code) == 0
+
+ b = Binding()
+ b.lib.ERR_put_error(
+ b.lib.ERR_LIB_EVP,
+ b.lib.EVP_F_EVP_ENCRYPTFINAL_EX,
+ b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH,
+ b"",
+ -1,
+ )
+ with pytest.raises(InternalError) as exc_info:
+ rust_openssl.raise_openssl_error()
+
+ error = exc_info.value.err_code[0]
+ assert error.lib == b.lib.ERR_LIB_EVP
+ assert error.reason == b.lib.EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH
+ if not b.lib.CRYPTOGRAPHY_IS_BORINGSSL:
+ assert b"data not multiple of block length" in error.reason_text