Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/cryptography/hazmat/bindings/openssl/binding.py: 91%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

56 statements  

1# This file is dual licensed under the terms of the Apache License, Version 

2# 2.0, and the BSD License. See the LICENSE file in the root of this repository 

3# for complete details. 

4 

5from __future__ import annotations 

6 

7import os 

8import sys 

9import threading 

10import types 

11import typing 

12import warnings 

13from collections.abc import Callable 

14 

15import cryptography 

16from cryptography.exceptions import InternalError 

17from cryptography.hazmat.bindings._rust import _openssl, openssl 

18from cryptography.hazmat.bindings.openssl._conditional import CONDITIONAL_NAMES 

19from cryptography.utils import CryptographyDeprecationWarning 

20 

21 

22def _openssl_assert(ok: bool) -> None: 

23 if not ok: 

24 errors = openssl.capture_error_stack() 

25 

26 raise InternalError( 

27 "Unknown OpenSSL error. This error is commonly encountered when " 

28 "another library is not cleaning up the OpenSSL error stack. If " 

29 "you are using cryptography with another library that uses " 

30 "OpenSSL try disabling it before reporting a bug. Otherwise " 

31 "please file an issue at https://github.com/pyca/cryptography/" 

32 "issues with information on how to reproduce " 

33 f"this. ({errors!r})", 

34 errors, 

35 ) 

36 

37 

38def build_conditional_library( 

39 lib: typing.Any, 

40 conditional_names: dict[str, Callable[[], list[str]]], 

41) -> typing.Any: 

42 conditional_lib = types.ModuleType("lib") 

43 conditional_lib._original_lib = lib # type: ignore[attr-defined] 

44 excluded_names = set() 

45 for condition, names_cb in conditional_names.items(): 

46 if not getattr(lib, condition): 

47 excluded_names.update(names_cb()) 

48 

49 for attr in dir(lib): 

50 if attr not in excluded_names: 

51 setattr(conditional_lib, attr, getattr(lib, attr)) 

52 

53 return conditional_lib 

54 

55 

56class Binding: 

57 """ 

58 OpenSSL API wrapper. 

59 """ 

60 

61 lib: typing.ClassVar = None 

62 ffi = _openssl.ffi 

63 _lib_loaded = False 

64 _init_lock = threading.Lock() 

65 

66 def __init__(self) -> None: 

67 self._ensure_ffi_initialized() 

68 

69 @classmethod 

70 def _ensure_ffi_initialized(cls) -> None: 

71 with cls._init_lock: 

72 if not cls._lib_loaded: 

73 cls.lib = build_conditional_library( 

74 _openssl.lib, CONDITIONAL_NAMES 

75 ) 

76 cls._lib_loaded = True 

77 

78 @classmethod 

79 def init_static_locks(cls) -> None: 

80 cls._ensure_ffi_initialized() 

81 

82 

83def _verify_package_version(version: str) -> None: 

84 # Occasionally we run into situations where the version of the Python 

85 # package does not match the version of the shared object that is loaded. 

86 # This may occur in environments where multiple versions of cryptography 

87 # are installed and available in the python path. To avoid errors cropping 

88 # up later this code checks that the currently imported package and the 

89 # shared object that were loaded have the same version and raise an 

90 # ImportError if they do not 

91 so_package_version = _openssl.ffi.string( 

92 _openssl.lib.CRYPTOGRAPHY_PACKAGE_VERSION 

93 ) 

94 if version.encode("ascii") != so_package_version: 

95 raise ImportError( 

96 "The version of cryptography does not match the loaded " 

97 "shared object. This can happen if you have multiple copies of " 

98 "cryptography installed in your Python path. Please try creating " 

99 "a new virtual environment to resolve this issue. " 

100 f"Loaded python version: {version}, " 

101 f"shared object version: {so_package_version}" 

102 ) 

103 

104 _openssl_assert( 

105 _openssl.lib.OpenSSL_version_num() == openssl.openssl_version(), 

106 ) 

107 

108 

109_verify_package_version(cryptography.__version__) 

110 

111Binding.init_static_locks() 

112 

113if ( 

114 sys.platform == "win32" 

115 and os.environ.get("PROCESSOR_ARCHITEW6432") is not None 

116): 

117 warnings.warn( 

118 "You are using cryptography on a 32-bit Python on a 64-bit Windows " 

119 "Operating System. Cryptography will be significantly faster if you " 

120 "switch to using a 64-bit Python.", 

121 UserWarning, 

122 stacklevel=2, 

123 ) 

124 

125if ( 

126 not openssl.CRYPTOGRAPHY_IS_LIBRESSL 

127 and not openssl.CRYPTOGRAPHY_IS_BORINGSSL 

128 and not openssl.CRYPTOGRAPHY_IS_AWSLC 

129 and not openssl.CRYPTOGRAPHY_OPENSSL_300_OR_GREATER 

130): 

131 warnings.warn( 

132 "You are using OpenSSL < 3.0. Support for OpenSSL < 3.0 is deprecated " 

133 "and will be removed in the next release. Please upgrade to OpenSSL " 

134 "3.0 or later.", 

135 CryptographyDeprecationWarning, 

136 stacklevel=2, 

137 )