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

53 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 

19 

20 

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

22 if not ok: 

23 errors = openssl.capture_error_stack() 

24 

25 raise InternalError( 

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

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

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

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

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

31 "issues with information on how to reproduce " 

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

33 errors, 

34 ) 

35 

36 

37def build_conditional_library( 

38 lib: typing.Any, 

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

40) -> typing.Any: 

41 conditional_lib = types.ModuleType("lib") 

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

43 excluded_names = set() 

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

45 if not getattr(lib, condition): 

46 excluded_names.update(names_cb()) 

47 

48 for attr in dir(lib): 

49 if attr not in excluded_names: 

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

51 

52 return conditional_lib 

53 

54 

55class Binding: 

56 """ 

57 OpenSSL API wrapper. 

58 """ 

59 

60 lib: typing.ClassVar = None 

61 ffi = _openssl.ffi 

62 _lib_loaded = False 

63 _init_lock = threading.Lock() 

64 

65 def __init__(self) -> None: 

66 self._ensure_ffi_initialized() 

67 

68 @classmethod 

69 def _ensure_ffi_initialized(cls) -> None: 

70 with cls._init_lock: 

71 if not cls._lib_loaded: 

72 cls.lib = build_conditional_library( 

73 _openssl.lib, CONDITIONAL_NAMES 

74 ) 

75 cls._lib_loaded = True 

76 

77 @classmethod 

78 def init_static_locks(cls) -> None: 

79 cls._ensure_ffi_initialized() 

80 

81 

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

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

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

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

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

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

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

89 # ImportError if they do not 

90 so_package_version = _openssl.ffi.string( 

91 _openssl.lib.CRYPTOGRAPHY_PACKAGE_VERSION 

92 ) 

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

94 raise ImportError( 

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

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

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

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

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

100 f"shared object version: {so_package_version}" 

101 ) 

102 

103 _openssl_assert( 

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

105 ) 

106 

107 

108_verify_package_version(cryptography.__version__) 

109 

110Binding.init_static_locks() 

111 

112if ( 

113 sys.platform == "win32" 

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

115): 

116 warnings.warn( 

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

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

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

120 UserWarning, 

121 stacklevel=2, 

122 )