Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/oscrypto/_openssl/_libcrypto.py: 68%

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

75 statements  

1# coding: utf-8 

2from __future__ import unicode_literals, division, absolute_import, print_function 

3 

4from .. import ffi 

5from .._ffi import buffer_from_bytes, byte_string_from_buffer, null 

6from .._types import str_cls 

7 

8if ffi() == 'cffi': 

9 from ._libcrypto_cffi import ( 

10 libcrypto, 

11 version as libcrypto_version, 

12 version_info as libcrypto_version_info 

13 ) 

14else: 

15 from ._libcrypto_ctypes import ( 

16 libcrypto, 

17 version as libcrypto_version, 

18 version_info as libcrypto_version_info 

19 ) 

20 

21 

22__all__ = [ 

23 'get_first_openssl_error', 

24 'handle_openssl_error', 

25 'libcrypto', 

26 'libcrypto_legacy_support', 

27 'libcrypto_version', 

28 'libcrypto_version_info', 

29 'LibcryptoConst', 

30 'peek_openssl_error', 

31 'raise_openssl_error', 

32] 

33 

34 

35_encoding = 'utf-8' 

36_fallback_encodings = ['utf-8', 'cp1252'] 

37 

38 

39if libcrypto_version_info < (1, 1): 

40 libcrypto.ERR_load_crypto_strings() 

41libcrypto.OPENSSL_config(null()) 

42 

43 

44# This enables legacy algorithms in OpenSSL 3.0, such as RC2, etc 

45# which are used by various tests and some old protocols and things 

46# like PKCS12 

47libcrypto_legacy_support = True 

48if libcrypto_version_info >= (3, ): 

49 

50 libcrypto.OSSL_PROVIDER_load(null(), "legacy".encode("ascii")) 

51 libcrypto.OSSL_PROVIDER_load(null(), "default".encode("ascii")) 

52 

53 if libcrypto.OSSL_PROVIDER_available(null(), "legacy".encode("ascii")) == 0: 

54 libcrypto_legacy_support = False 

55 

56 

57def _try_decode(value): 

58 

59 try: 

60 return str_cls(value, _encoding) 

61 

62 # If the "correct" encoding did not work, try some defaults, and then just 

63 # obliterate characters that we can't seen to decode properly 

64 except (UnicodeDecodeError): 

65 for encoding in _fallback_encodings: 

66 try: 

67 return str_cls(value, encoding, errors='strict') 

68 except (UnicodeDecodeError): 

69 pass 

70 

71 return str_cls(value, errors='replace') 

72 

73 

74def get_first_openssl_error(): 

75 """ 

76 Returns the first OpenSSL error code and drains the rest of the error queue. 

77 

78 :return: 

79 An integer error code 

80 """ 

81 

82 error_num = libcrypto.ERR_get_error() 

83 while libcrypto.ERR_get_error(): 

84 pass 

85 

86 return error_num 

87 

88 

89def raise_openssl_error(error_num, exception_class=None): 

90 """ 

91 Raises an exception for an OpenSSL error code. 

92 

93 :param error_num: 

94 An integer error code 

95 

96 :param exception_class: 

97 The exception class to use 

98 

99 :raises: 

100 OSError - when exception_class is not specified 

101 """ 

102 

103 if exception_class is None: 

104 exception_class = OSError 

105 

106 buffer = buffer_from_bytes(120) 

107 libcrypto.ERR_error_string(error_num, buffer) 

108 

109 # Since we are dealing with a string, it is NULL terminated 

110 error_string = byte_string_from_buffer(buffer) 

111 

112 raise exception_class(_try_decode(error_string)) 

113 

114 

115def handle_openssl_error(result, exception_class=None): 

116 """ 

117 Checks if an error occurred, and if so throws an OSError containing the 

118 last OpenSSL error message 

119 

120 :param result: 

121 An integer result code - 1 or greater indicates success 

122 

123 :param exception_class: 

124 The exception class to use for the exception if an error occurred 

125 

126 :raises: 

127 OSError - when an OpenSSL error occurs 

128 """ 

129 

130 if result > 0: 

131 return 

132 

133 error_num = get_first_openssl_error() 

134 raise_openssl_error(error_num, exception_class) 

135 

136 

137def peek_openssl_error(): 

138 """ 

139 Peeks into the error stack and pulls out the lib, func and reason 

140 

141 :return: 

142 A three-element tuple of integers (lib, func, reason) 

143 """ 

144 

145 error = libcrypto.ERR_peek_error() 

146 if libcrypto_version_info < (3, 0): 

147 lib = int((error >> 24) & 0xff) 

148 func = int((error >> 12) & 0xfff) 

149 reason = int(error & 0xfff) 

150 else: 

151 lib = int((error >> 23) & 0xff) 

152 # OpenSSL 3.0 removed ERR_GET_FUNC() 

153 func = 0 

154 reason = int(error & 0x7fffff) 

155 

156 return (lib, func, reason) 

157 

158 

159class LibcryptoConst(): 

160 EVP_CTRL_SET_RC2_KEY_BITS = 3 

161 

162 SSLEAY_VERSION = 0 

163 

164 RSA_PKCS1_PADDING = 1 

165 RSA_NO_PADDING = 3 

166 RSA_PKCS1_OAEP_PADDING = 4 

167 

168 # OpenSSL 0.9.x 

169 EVP_MD_CTX_FLAG_PSS_MDLEN = -1 

170 

171 # OpenSSL 1.x.x 

172 EVP_PKEY_CTRL_RSA_PADDING = 0x1001 

173 RSA_PKCS1_PSS_PADDING = 6 

174 EVP_PKEY_CTRL_RSA_PSS_SALTLEN = 0x1002 

175 EVP_PKEY_RSA = 6 

176 EVP_PKEY_OP_SIGN = 1 << 3 

177 EVP_PKEY_OP_VERIFY = 1 << 4 

178 

179 NID_X9_62_prime256v1 = 415 

180 NID_secp384r1 = 715 

181 NID_secp521r1 = 716 

182 

183 OPENSSL_EC_NAMED_CURVE = 1 

184 

185 DH_GENERATOR_2 = 2