Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/oscrypto/__init__.py: 43%
93 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:25 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:25 +0000
1# coding: utf-8
2from __future__ import unicode_literals, division, absolute_import, print_function
4import os
5import platform
6import sys
7import threading
9from ._types import str_cls, type_name
10from .errors import LibraryNotFoundError
11from .version import __version__, __version_info__
14__all__ = [
15 '__version__',
16 '__version_info__',
17 'backend',
18 'ffi',
19 'load_order',
20 'use_ctypes',
21 'use_openssl',
22 'use_winlegacy',
23]
26_backend_lock = threading.Lock()
27_module_values = {
28 'backend': None,
29 'backend_config': None,
30 'ffi': None
31}
34def backend():
35 """
36 :return:
37 A unicode string of the backend being used: "openssl", "mac", "win",
38 "winlegacy"
39 """
41 if _module_values['backend'] is not None:
42 return _module_values['backend']
44 with _backend_lock:
45 if _module_values['backend'] is not None:
46 return _module_values['backend']
48 if sys.platform == 'win32':
49 # Windows XP was major version 5, Vista was 6
50 if sys.getwindowsversion()[0] < 6:
51 _module_values['backend'] = 'winlegacy'
52 else:
53 _module_values['backend'] = 'win'
54 elif sys.platform == 'darwin':
55 _module_values['backend'] = 'mac'
56 else:
57 _module_values['backend'] = 'openssl'
59 return _module_values['backend']
62def _backend_config():
63 """
64 :return:
65 A dict of config info for the backend. Only currently used by "openssl",
66 it may contains zero or more of the following keys:
67 - "libcrypto_path"
68 - "libssl_path"
69 """
71 if backend() != 'openssl':
72 return {}
74 if _module_values['backend_config'] is not None:
75 return _module_values['backend_config']
77 with _backend_lock:
78 if _module_values['backend_config'] is not None:
79 return _module_values['backend_config']
81 _module_values['backend_config'] = {}
82 return _module_values['backend_config']
85def use_openssl(libcrypto_path, libssl_path, trust_list_path=None):
86 """
87 Forces using OpenSSL dynamic libraries on OS X (.dylib) or Windows (.dll),
88 or using a specific dynamic library on Linux/BSD (.so).
90 This can also be used to configure oscrypto to use LibreSSL dynamic
91 libraries.
93 This method must be called before any oscrypto submodules are imported.
95 :param libcrypto_path:
96 A unicode string of the file path to the OpenSSL/LibreSSL libcrypto
97 dynamic library.
99 :param libssl_path:
100 A unicode string of the file path to the OpenSSL/LibreSSL libssl
101 dynamic library.
103 :param trust_list_path:
104 An optional unicode string of the path to a file containing
105 OpenSSL-compatible CA certificates in PEM format. If this is not
106 provided and the platform is OS X or Windows, the system trust roots
107 will be exported from the OS and used for all TLS connections.
109 :raises:
110 ValueError - when one of the paths is not a unicode string
111 OSError - when the trust_list_path does not exist on the filesystem
112 oscrypto.errors.LibraryNotFoundError - when one of the path does not exist on the filesystem
113 RuntimeError - when this function is called after another part of oscrypto has been imported
114 """
116 if not isinstance(libcrypto_path, str_cls):
117 raise ValueError('libcrypto_path must be a unicode string, not %s' % type_name(libcrypto_path))
119 if not isinstance(libssl_path, str_cls):
120 raise ValueError('libssl_path must be a unicode string, not %s' % type_name(libssl_path))
122 do_path_checks = True
123 if sys.platform == 'darwin':
124 mac_version_info = tuple(map(int, platform.mac_ver()[0].split('.')[:2]))
125 do_path_checks = mac_version_info < (10, 16)
127 if do_path_checks:
128 if not os.path.exists(libcrypto_path):
129 raise LibraryNotFoundError('libcrypto does not exist at %s' % libcrypto_path)
131 if not os.path.exists(libssl_path):
132 raise LibraryNotFoundError('libssl does not exist at %s' % libssl_path)
134 if trust_list_path is not None:
135 if not isinstance(trust_list_path, str_cls):
136 raise ValueError('trust_list_path must be a unicode string, not %s' % type_name(trust_list_path))
137 if not os.path.exists(trust_list_path):
138 raise OSError('trust_list_path does not exist at %s' % trust_list_path)
140 with _backend_lock:
141 new_config = {
142 'libcrypto_path': libcrypto_path,
143 'libssl_path': libssl_path,
144 'trust_list_path': trust_list_path,
145 }
147 if _module_values['backend'] == 'openssl' and _module_values['backend_config'] == new_config:
148 return
150 if _module_values['backend'] is not None:
151 raise RuntimeError('Another part of oscrypto has already been imported, unable to force use of OpenSSL')
153 _module_values['backend'] = 'openssl'
154 _module_values['backend_config'] = new_config
157def use_winlegacy():
158 """
159 Forces use of the legacy Windows CryptoAPI. This should only be used on
160 Windows XP or for testing. It is less full-featured than the Cryptography
161 Next Generation (CNG) API, and as a result the elliptic curve and PSS
162 padding features are implemented in pure Python. This isn't ideal, but it
163 a shim for end-user client code. No one is going to run a server on Windows
164 XP anyway, right?!
166 :raises:
167 EnvironmentError - when this function is called on an operating system other than Windows
168 RuntimeError - when this function is called after another part of oscrypto has been imported
169 """
171 if sys.platform != 'win32':
172 plat = platform.system() or sys.platform
173 if plat == 'Darwin':
174 plat = 'OS X'
175 raise EnvironmentError('The winlegacy backend can only be used on Windows, not %s' % plat)
177 with _backend_lock:
178 if _module_values['backend'] == 'winlegacy':
179 return
181 if _module_values['backend'] is not None:
182 raise RuntimeError(
183 'Another part of oscrypto has already been imported, unable to force use of Windows legacy CryptoAPI'
184 )
186 _module_values['backend'] = 'winlegacy'
189def use_ctypes():
190 """
191 Forces use of ctypes instead of cffi for the FFI layer
193 :raises:
194 RuntimeError - when this function is called after another part of oscrypto has been imported
195 """
197 with _backend_lock:
198 if _module_values['ffi'] == 'ctypes':
199 return
201 if _module_values['backend'] is not None:
202 raise RuntimeError(
203 'Another part of oscrypto has already been imported, unable to force use of ctypes'
204 )
206 _module_values['ffi'] = 'ctypes'
209def ffi():
210 """
211 Returns the FFI module being used
213 :return:
214 A unicode string of "cffi" or "ctypes"
215 """
217 if _module_values['ffi'] is not None:
218 return _module_values['ffi']
220 with _backend_lock:
221 try:
222 import cffi # noqa: F401
223 _module_values['ffi'] = 'cffi'
224 except (ImportError):
225 _module_values['ffi'] = 'ctypes'
227 return _module_values['ffi']
230def load_order():
231 """
232 Returns a list of the module and sub-module names for oscrypto in
233 dependency load order, for the sake of live reloading code
235 :return:
236 A list of unicode strings of module names, as they would appear in
237 sys.modules, ordered by which module should be reloaded first
238 """
240 return [
241 'oscrypto._asn1',
242 'oscrypto._cipher_suites',
243 'oscrypto._errors',
244 'oscrypto._int',
245 'oscrypto._types',
246 'oscrypto.errors',
247 'oscrypto.version',
248 'oscrypto',
249 'oscrypto._ffi',
250 'oscrypto._pkcs12',
251 'oscrypto._pkcs5',
252 'oscrypto._rand',
253 'oscrypto._tls',
254 'oscrypto._linux_bsd.trust_list',
255 'oscrypto._mac._common_crypto_cffi',
256 'oscrypto._mac._common_crypto_ctypes',
257 'oscrypto._mac._common_crypto',
258 'oscrypto._mac._core_foundation_cffi',
259 'oscrypto._mac._core_foundation_ctypes',
260 'oscrypto._mac._core_foundation',
261 'oscrypto._mac._security_cffi',
262 'oscrypto._mac._security_ctypes',
263 'oscrypto._mac._security',
264 'oscrypto._mac.trust_list',
265 'oscrypto._mac.util',
266 'oscrypto._openssl._libcrypto_cffi',
267 'oscrypto._openssl._libcrypto_ctypes',
268 'oscrypto._openssl._libcrypto',
269 'oscrypto._openssl._libssl_cffi',
270 'oscrypto._openssl._libssl_ctypes',
271 'oscrypto._openssl._libssl',
272 'oscrypto._openssl.util',
273 'oscrypto._win._cng_cffi',
274 'oscrypto._win._cng_ctypes',
275 'oscrypto._win._cng',
276 'oscrypto._win._decode',
277 'oscrypto._win._advapi32_cffi',
278 'oscrypto._win._advapi32_ctypes',
279 'oscrypto._win._advapi32',
280 'oscrypto._win._kernel32_cffi',
281 'oscrypto._win._kernel32_ctypes',
282 'oscrypto._win._kernel32',
283 'oscrypto._win._secur32_cffi',
284 'oscrypto._win._secur32_ctypes',
285 'oscrypto._win._secur32',
286 'oscrypto._win._crypt32_cffi',
287 'oscrypto._win._crypt32_ctypes',
288 'oscrypto._win._crypt32',
289 'oscrypto._win.trust_list',
290 'oscrypto._win.util',
291 'oscrypto.trust_list',
292 'oscrypto.util',
293 'oscrypto.kdf',
294 'oscrypto._mac.symmetric',
295 'oscrypto._openssl.symmetric',
296 'oscrypto._win.symmetric',
297 'oscrypto.symmetric',
298 'oscrypto._asymmetric',
299 'oscrypto._ecdsa',
300 'oscrypto._pkcs1',
301 'oscrypto._mac.asymmetric',
302 'oscrypto._openssl.asymmetric',
303 'oscrypto._win.asymmetric',
304 'oscrypto.asymmetric',
305 'oscrypto.keys',
306 'oscrypto._mac.tls',
307 'oscrypto._openssl.tls',
308 'oscrypto._win.tls',
309 'oscrypto.tls',
310 ]