blob: 5e2b2564fc3900ef5fa46452e969a017d24b3cdb [file] [log] [blame]
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001from six import PY3, binary_type, text_type
2
Jean-Paul Calderonee36b31a2014-01-08 16:55:06 -05003from cryptography.hazmat.bindings.openssl.binding import Binding
4binding = Binding()
5ffi = binding.ffi
6lib = binding.lib
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -05007
Stephen Holsapple0d9815f2014-08-27 19:36:53 -07008
9
10def text(charp):
Jean-Paul Calderone130cd0e2015-03-15 15:49:33 -040011 """
12 Get a native string type representing of the given CFFI ``char*`` object.
13
14 :param charp: A C-style string represented using CFFI.
15
16 :return: :class:`str`
17 """
Jean-Paul Calderone6d862182015-04-11 07:24:52 -040018 if not charp:
19 return ""
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070020 return native(ffi.string(charp))
21
22
23
24def exception_from_error_queue(exception_type):
25 """
26 Convert an OpenSSL library failure into a Python exception.
27
28 When a call to the native OpenSSL library fails, this is usually signalled
29 by the return value, and an error code is stored in an error queue
30 associated with the current thread. The err library provides functions to
31 obtain these error codes and textual error messages.
32 """
Jean-Paul Calderonede075462014-01-18 10:34:12 -050033
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050034 errors = []
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070035
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050036 while True:
37 error = lib.ERR_get_error()
38 if error == 0:
39 break
40 errors.append((
Jean-Paul Calderonede075462014-01-18 10:34:12 -050041 text(lib.ERR_lib_error_string(error)),
42 text(lib.ERR_func_error_string(error)),
43 text(lib.ERR_reason_error_string(error))))
Jean-Paul Calderonec86bb7d2013-12-29 10:25:59 -050044
Stephen Holsapple0d9815f2014-08-27 19:36:53 -070045 raise exception_type(errors)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050046
47
48
49def native(s):
50 """
51 Convert :py:class:`bytes` or :py:class:`unicode` to the native
Jean-Paul Calderoneaca50f42014-01-11 14:43:37 -050052 :py:class:`str` type, using UTF-8 encoding if conversion is necessary.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050053
54 :raise UnicodeError: The input string is not UTF-8 decodeable.
55
56 :raise TypeError: The input is neither :py:class:`bytes` nor
57 :py:class:`unicode`.
58 """
59 if not isinstance(s, (binary_type, text_type)):
60 raise TypeError("%r is neither bytes nor unicode" % s)
61 if PY3:
62 if isinstance(s, binary_type):
63 return s.decode("utf-8")
64 else:
65 if isinstance(s, text_type):
66 return s.encode("utf-8")
67 return s
68
69
70
71if PY3:
72 def byte_string(s):
73 return s.encode("charmap")
74else:
75 def byte_string(s):
76 return s