Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/oscrypto/__init__.py: 43%

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

94 statements  

1# coding: utf-8 

2from __future__ import unicode_literals, division, absolute_import, print_function 

3 

4import os 

5import platform 

6import sys 

7import threading 

8 

9from ._types import str_cls, type_name 

10from .errors import LibraryNotFoundError 

11from .version import __version__, __version_info__ 

12 

13 

14__all__ = [ 

15 '__version__', 

16 '__version_info__', 

17 'backend', 

18 'ffi', 

19 'load_order', 

20 'use_ctypes', 

21 'use_openssl', 

22 'use_winlegacy', 

23] 

24 

25 

26_backend_lock = threading.Lock() 

27_module_values = { 

28 'backend': None, 

29 'backend_config': None, 

30 'ffi': None 

31} 

32 

33 

34def backend(): 

35 """ 

36 :return: 

37 A unicode string of the backend being used: "openssl", "mac", "win", 

38 "winlegacy" 

39 """ 

40 

41 if _module_values['backend'] is not None: 

42 return _module_values['backend'] 

43 

44 with _backend_lock: 

45 if _module_values['backend'] is not None: 

46 return _module_values['backend'] 

47 

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' 

58 

59 return _module_values['backend'] 

60 

61 

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 """ 

70 

71 if backend() != 'openssl': 

72 return {} 

73 

74 if _module_values['backend_config'] is not None: 

75 return _module_values['backend_config'] 

76 

77 with _backend_lock: 

78 if _module_values['backend_config'] is not None: 

79 return _module_values['backend_config'] 

80 

81 _module_values['backend_config'] = {} 

82 return _module_values['backend_config'] 

83 

84 

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). 

89 

90 This can also be used to configure oscrypto to use LibreSSL dynamic 

91 libraries. 

92 

93 This method must be called before any oscrypto submodules are imported. 

94 

95 :param libcrypto_path: 

96 A unicode string of the file path to the OpenSSL/LibreSSL libcrypto 

97 dynamic library. 

98 

99 :param libssl_path: 

100 A unicode string of the file path to the OpenSSL/LibreSSL libssl 

101 dynamic library. 

102 

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. 

108 

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 """ 

115 

116 if not isinstance(libcrypto_path, str_cls): 

117 raise ValueError('libcrypto_path must be a unicode string, not %s' % type_name(libcrypto_path)) 

118 

119 if not isinstance(libssl_path, str_cls): 

120 raise ValueError('libssl_path must be a unicode string, not %s' % type_name(libssl_path)) 

121 

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) 

126 

127 if do_path_checks: 

128 if not os.path.exists(libcrypto_path): 

129 raise LibraryNotFoundError('libcrypto does not exist at %s' % libcrypto_path) 

130 

131 if not os.path.exists(libssl_path): 

132 raise LibraryNotFoundError('libssl does not exist at %s' % libssl_path) 

133 

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) 

139 

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 } 

146 

147 if _module_values['backend'] == 'openssl' and _module_values['backend_config'] == new_config: 

148 return 

149 

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') 

152 

153 _module_values['backend'] = 'openssl' 

154 _module_values['backend_config'] = new_config 

155 

156 

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?! 

165 

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 """ 

170 

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) 

176 

177 with _backend_lock: 

178 if _module_values['backend'] == 'winlegacy': 

179 return 

180 

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 ) 

185 

186 _module_values['backend'] = 'winlegacy' 

187 

188 

189def use_ctypes(): 

190 """ 

191 Forces use of ctypes instead of cffi for the FFI layer 

192 

193 :raises: 

194 RuntimeError - when this function is called after another part of oscrypto has been imported 

195 """ 

196 

197 with _backend_lock: 

198 if _module_values['ffi'] == 'ctypes': 

199 return 

200 

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 ) 

205 

206 _module_values['ffi'] = 'ctypes' 

207 

208 

209def ffi(): 

210 """ 

211 Returns the FFI module being used 

212 

213 :return: 

214 A unicode string of "cffi" or "ctypes" 

215 """ 

216 

217 if _module_values['ffi'] is not None: 

218 return _module_values['ffi'] 

219 

220 with _backend_lock: 

221 try: 

222 import cffi # noqa: F401 

223 _module_values['ffi'] = 'cffi' 

224 except (ImportError): 

225 _module_values['ffi'] = 'ctypes' 

226 

227 return _module_values['ffi'] 

228 

229 

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 

234 

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 """ 

239 

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 ]