]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blob - ctypescrypto/bio.py
Begin to implement python3 support. Now tests for oid, bio, cipher, digest, mac and...
[oss/ctypescrypto.git] / ctypescrypto / bio.py
1 """
2 Interface to OpenSSL BIO library
3 """
4 from ctypescrypto import libcrypto,pyver, inttype
5 from ctypes import c_char_p, c_void_p, c_int, string_at, c_long
6 from ctypes import POINTER, byref, create_string_buffer
7 class Membio(object):
8     """
9     Provides interface to OpenSSL memory bios
10     use str() or unicode() to get contents of writable bio
11     use bio member to pass to libcrypto function
12     """
13     def __init__(self, data=None):
14         """
15         If data is specified, creates read-only BIO. If data is
16         None, creates writable BIO, contents of which can be retrieved
17         by str() or unicode()
18         """
19         if data is None:
20             method = libcrypto.BIO_s_mem()
21             self.bio = libcrypto.BIO_new(method)
22         else:
23             self.bio = libcrypto.BIO_new_mem_buf(c_char_p(data), len(data))
24
25     def __del__(self):
26         """
27         Cleans up memory used by bio
28         """
29         if hasattr(self,'bio'):
30             libcrypto.BIO_free(self.bio)
31             del self.bio
32
33     def __bytes__(self):
34         """
35         Returns current contents of buffer as byte string
36         """
37         string_ptr = c_char_p(None)
38         string_len = libcrypto.BIO_ctrl(self.bio, 3, 0, byref(string_ptr))
39         return string_at(string_ptr, string_len)
40
41     def __unicode__(self):
42         """
43         Attempts to interpret current contents of buffer as UTF-8 string
44         and convert it to unicode
45         """
46         return self.__bytes__().decode("utf-8")
47     if pyver == 2:
48         __str__ = __bytes__
49     else: 
50         __str__ = __unicode__
51     def read(self, length=None):
52         """
53         Reads data from readble BIO. For test purposes.
54         @param length - if specifed, limits amount of data read.
55         If not BIO is read until end of buffer
56         """
57         if not length is None:
58             if not isinstance(length, inttype) :
59                 raise TypeError("length to read should be number")
60             buf = create_string_buffer(length)
61             readbytes = libcrypto.BIO_read(self.bio, buf, length)
62             if readbytes == -2:
63                 raise NotImplementedError("Function is not supported by" +
64                                           "this BIO")
65             if readbytes == -1:
66                 raise IOError
67             if readbytes == 0:
68                 return b""
69             return buf.raw[:readbytes]
70         else:
71             buf = create_string_buffer(1024)
72             out = b""
73             readbytes = 1
74             while readbytes > 0:
75                 readbytes = libcrypto.BIO_read(self.bio, buf, 1024)
76                 if readbytes == -2:
77                     raise NotImplementedError("Function is not supported by " +
78                                               "this BIO")
79                 if readbytes == -1:
80                     raise IOError
81                 if readbytes > 0:
82                     out += buf.raw[:readbytes]
83             return out
84
85     def write(self, data):
86         """
87         Writes data to writable bio. For test purposes
88         """
89         if pyver == 2:
90              if isinstance(data, unicode):
91                 data = data.encode("utf-8")
92              else:
93                 data = str(data)
94         else:
95              if not isinstance(data, bytes): 
96                 data=str(data).encode("utf-8")   
97
98         written = libcrypto.BIO_write(self.bio, data, len(data))
99         if written == -2:
100             raise NotImplementedError("Function not supported by this BIO")
101         if written < len(data):
102             raise IOError("Not all data were successfully written")
103
104     def reset(self):
105         """
106         Resets the read-only bio to start and discards all data from
107         writable bio
108         """
109         libcrypto.BIO_ctrl(self.bio, 1, 0, None)
110
111 __all__ = ['Membio']
112 libcrypto.BIO_s_mem.restype = c_void_p
113 libcrypto.BIO_new.restype = c_void_p
114 libcrypto.BIO_new.argtypes = (c_void_p, )
115 libcrypto.BIO_ctrl.restype = c_long
116 libcrypto.BIO_ctrl.argtypes = (c_void_p, c_int, c_long, POINTER(c_char_p))
117 libcrypto.BIO_read.argtypes = (c_void_p, c_char_p, c_int)
118 libcrypto.BIO_write.argtypes = (c_void_p, c_char_p, c_int)
119 libcrypto.BIO_free.argtypes = (c_void_p, )
120 libcrypto.BIO_new_mem_buf.restype = c_void_p
121 libcrypto.BIO_new_mem_buf.argtypes = (c_char_p, c_int)