| | |
| | |
| | |
| |
|
| | from __future__ import annotations |
| |
|
| | import os |
| | import sys |
| | import threading |
| | import types |
| | import typing |
| | import warnings |
| | from collections.abc import Callable |
| |
|
| | import cryptography |
| | from cryptography.exceptions import InternalError |
| | from cryptography.hazmat.bindings._rust import _openssl, openssl |
| | from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES |
| | from cryptography.utils import CryptographyDeprecationWarning |
| |
|
| |
|
| | def _openssl_assert(ok: bool) -> None: |
| | if not ok: |
| | errors = openssl.capture_error_stack() |
| |
|
| | raise InternalError( |
| | "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 " |
| | f"this. ({errors!r})", |
| | errors, |
| | ) |
| |
|
| |
|
| | def build_conditional_library( |
| | lib: typing.Any, |
| | conditional_names: dict[str, Callable[[], list[str]]], |
| | ) -> typing.Any: |
| | conditional_lib = types.ModuleType("lib") |
| | conditional_lib._original_lib = lib |
| | excluded_names = set() |
| | for condition, names_cb in conditional_names.items(): |
| | if not getattr(lib, condition): |
| | excluded_names.update(names_cb()) |
| |
|
| | for attr in dir(lib): |
| | if attr not in excluded_names: |
| | setattr(conditional_lib, attr, getattr(lib, attr)) |
| |
|
| | return conditional_lib |
| |
|
| |
|
| | class Binding: |
| | """ |
| | OpenSSL API wrapper. |
| | """ |
| |
|
| | lib: typing.ClassVar[typing.Any] = None |
| | ffi = _openssl.ffi |
| | _lib_loaded = False |
| | _init_lock = threading.Lock() |
| |
|
| | def __init__(self) -> None: |
| | self._ensure_ffi_initialized() |
| |
|
| | @classmethod |
| | def _ensure_ffi_initialized(cls) -> None: |
| | with cls._init_lock: |
| | if not cls._lib_loaded: |
| | cls.lib = build_conditional_library( |
| | _openssl.lib, CONDITIONAL_NAMES |
| | ) |
| | cls._lib_loaded = True |
| |
|
| | @classmethod |
| | def init_static_locks(cls) -> None: |
| | cls._ensure_ffi_initialized() |
| |
|
| |
|
| | def _verify_package_version(version: str) -> None: |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | so_package_version = _openssl.ffi.string( |
| | _openssl.lib.CRYPTOGRAPHY_PACKAGE_VERSION |
| | ) |
| | if version.encode("ascii") != so_package_version: |
| | raise ImportError( |
| | "The version of cryptography does not match the loaded " |
| | "shared object. This can happen if you have multiple copies of " |
| | "cryptography installed in your Python path. Please try creating " |
| | "a new virtual environment to resolve this issue. " |
| | f"Loaded python version: {version}, " |
| | f"shared object version: {so_package_version}" |
| | ) |
| |
|
| | _openssl_assert( |
| | _openssl.lib.OpenSSL_version_num() == openssl.openssl_version(), |
| | ) |
| |
|
| |
|
| | _verify_package_version(cryptography.__version__) |
| |
|
| | Binding.init_static_locks() |
| |
|
| | if ( |
| | sys.platform == "win32" |
| | and os.environ.get("PROCESSOR_ARCHITEW6432") is not None |
| | ): |
| | warnings.warn( |
| | "You are using cryptography on a 32-bit Python on a 64-bit Windows " |
| | "Operating System. Cryptography will be significantly faster if you " |
| | "switch to using a 64-bit Python.", |
| | UserWarning, |
| | stacklevel=2, |
| | ) |
| |
|
| | if ( |
| | not openssl.CRYPTOGRAPHY_IS_LIBRESSL |
| | and not openssl.CRYPTOGRAPHY_IS_BORINGSSL |
| | and not openssl.CRYPTOGRAPHY_IS_AWSLC |
| | and not openssl.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER |
| | ): |
| | warnings.warn( |
| | "You are using OpenSSL < 3.0. Support for OpenSSL < 3.0 is deprecated " |
| | "and will be removed in the next release. Please upgrade to OpenSSL " |
| | "3.0 or later.", |
| | CryptographyDeprecationWarning, |
| | stacklevel=2, |
| | ) |
| |
|