]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blob - ctypescrypto/x509.py
ed47cf5e1ba6989a2f93fc9009f22069936d920e
[oss/ctypescrypto.git] / ctypescrypto / x509.py
1 """
2 Implements interface to openssl X509 and X509Store structures,
3 I.e allows to load, analyze and verify certificates.
4
5 X509Store objects are also used to verify other signed documets,
6 such as CMS, OCSP and timestamps.
7 """
8
9
10
11 from ctypes import c_void_p, c_long, c_ulong, c_int, POINTER, c_char_p, Structure, cast
12 from ctypescrypto.bio import Membio
13 from ctypescrypto.pkey import PKey
14 from ctypescrypto.oid import Oid
15 from ctypescrypto.exception import LibCryptoError
16 from ctypescrypto import libcrypto
17 from datetime import datetime
18
19 try:
20     from pytz import utc
21 except ImportError:
22     from datetime import timedelta, tzinfo
23     ZERO = timedelta(0)
24     class UTC(tzinfo):
25         """tzinfo object for UTC.
26             If no pytz is available, we would use it.
27         """
28         def utcoffset(self, dt):
29             return ZERO
30
31         def tzname(self, dt):
32             return "UTC"
33
34         def dst(self, dt):
35             return ZERO
36
37     utc = UTC()
38
39 __all__ = ['X509', 'X509Error', 'X509Name', 'X509Store', 'StackOfX509']
40
41 if hasattr(libcrypto,"X509_get_version"):
42     
43 # If it is OpenSSL 1.1 or above, use accessor functions
44     _X509_get_version = libcrypto.X509_get_version
45     _X509_get_version.restype = c_long
46     _X509_get_version.argtypes = (c_void_p,)
47
48     _X509_get_notBefore=libcrypto.X509_get_notBefore
49     _X509_get_notBefore.restype = c_void_p
50     _X509_get_notBefore.argtypes = (c_void_p,)
51
52     _X509_get_notAfter=libcrypto.X509_get_notAfter
53     _X509_get_notAfter.restype = c_void_p
54     _X509_get_notAfter.argtypes = (c_void_p,)
55 else:
56     # Otherwise declare X509 structure internals and define deep poke
57     # functions
58     class _validity(Structure):
59         """ ctypes representation of X509_VAL structure
60             needed to access certificate validity period, because openssl
61             doesn't provide fuctions for it - only macros
62         """
63         _fields_ = [('notBefore', c_void_p), ('notAfter', c_void_p)]
64
65     class _cinf(Structure):
66         """ ctypes representtion of X509_CINF structure
67             neede to access certificate data, which are accessable only
68             via macros
69         """
70         _fields_ = [('version', c_void_p),
71                     ('serialNumber', c_void_p),
72                     ('sign_alg', c_void_p),
73                     ('issuer', c_void_p),
74                     ('validity', POINTER(_validity)),
75                     ('subject', c_void_p),
76                     ('pubkey', c_void_p),
77                     ('issuerUID', c_void_p),
78                     ('subjectUID', c_void_p),
79                     ('extensions', c_void_p),
80                 ]
81
82     class _x509(Structure):
83         """
84         ctypes represntation of X509 structure needed
85         to access certificate data which are accesable only via
86         macros, not functions
87         """
88         _fields_ = [('cert_info', POINTER(_cinf)),
89                     ('sig_alg', c_void_p),
90                     ('signature', c_void_p),
91                     # There are a lot of parsed extension fields there
92                 ]
93     _px509 = POINTER(_x509)
94     def _X509_get_version(ptr):
95         asn1int = cast(ptr, _px509)[0].cert_info[0].version  
96         return libcrypto.ASN1_INTEGER_get(asn1int)
97
98     def _X509_get_notBefore(ptr):   
99         # (x)->cert_info->validity->notBefore
100         return cast(ptr, _px509)[0].cert_info[0].validity[0].notBefore
101     def _X509_get_notAfter(ptr):
102         return cast(ptr, _px509)[0].cert_info[0].validity[0].notAfter
103
104 class X509Error(LibCryptoError):
105     """
106     Exception, generated when some openssl function fail
107     during X509 operation
108     """
109     pass
110
111
112 class X509Name(object):
113     """
114     Class which represents X.509 distinguished name - typically
115     a certificate subject name or an issuer name.
116
117     Now used only to represent information, extracted from the
118     certificate. Potentially can be also used to build DN when creating
119     certificate signing request
120     """
121     # XN_FLAG_SEP_COMMA_PLUS & ASN1_STRFLG_UTF8_CONVERT
122     PRINT_FLAG = 0x10010
123     ESC_MSB = 4
124     def __init__(self, ptr=None, copy=False):
125         """
126         Creates a X509Name object
127         @param ptr - pointer to X509_NAME C structure (as returned by some
128                      OpenSSL functions
129         @param copy - indicates that this structure have to be freed upon
130                       object destruction
131         """
132         if ptr is not None:
133             self.ptr = ptr
134             self.need_free = copy
135             self.writable = False
136         else:
137             self.ptr = libcrypto.X509_NAME_new()
138             self.need_free = True
139             self.writable = True
140
141     def __del__(self):
142         """
143         Frees if neccessary
144         """
145         if self.need_free:
146             libcrypto.X509_NAME_free(self.ptr)
147     def __str__(self):
148         """
149         Produces an ascii representation of the name, escaping all
150         symbols > 0x80.  Probably it is not what you want, unless
151         your native language is English
152         """
153         bio = Membio()
154         libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0,
155                                      self.PRINT_FLAG | self.ESC_MSB)
156         return str(bio)
157
158     def __unicode__(self):
159         """
160         Produces unicode representation of the name.
161         """
162         bio = Membio()
163         libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0, self.PRINT_FLAG)
164         return unicode(bio)
165     def __len__(self):
166         """
167         return number of components in the name
168         """
169         return libcrypto.X509_NAME_entry_count(self.ptr)
170     def __cmp__(self, other):
171         """
172         Compares X509 names
173         """
174         return libcrypto.X509_NAME_cmp(self.ptr, other.ptr)
175     def __eq__(self, other):
176         return libcrypto.X509_NAME_cmp(self.ptr, other.ptr) == 0
177
178     def __getitem__(self, key):
179         if isinstance(key, Oid):
180             # Return first matching field
181             idx = libcrypto.X509_NAME_get_index_by_NID(self.ptr, key.nid, -1)
182             if idx < 0:
183                 raise KeyError("Key not found " + str(Oid))
184             entry = libcrypto.X509_NAME_get_entry(self.ptr, idx)
185             value = libcrypto.X509_NAME_ENTRY_get_data(entry)
186             bio = Membio()
187             libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
188             return unicode(bio)
189         elif isinstance(key, (int, long)):
190             # Return OID, string tuple
191             entry = libcrypto.X509_NAME_get_entry(self.ptr, key)
192             if entry is None:
193                 raise IndexError("name entry index out of range")
194             oid = Oid.fromobj(libcrypto.X509_NAME_ENTRY_get_object(entry))
195             value = libcrypto.X509_NAME_ENTRY_get_data(entry)
196             bio = Membio()
197             libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
198             return (oid, unicode(bio))
199         else:
200             raise TypeError("X509 NAME can be indexed by Oids or integers only")
201
202     def __setitem__(self, key, val):
203         if not self.writable:
204             raise ValueError("Attempt to modify constant X509 object")
205         else:
206             raise NotImplementedError
207     def __delitem__(self, key):
208         if not self.writable:
209             raise ValueError("Attempt to modify constant X509 object")
210         else:
211             raise NotImplementedError
212     def __hash__(self):
213         return libcrypto.X509_NAME_hash(self.ptr)
214
215 class _x509_ext(Structure):
216     """ Represens C structure X509_EXTENSION """
217     _fields_ = [("object", c_void_p),
218                 ("critical", c_int),
219                 ("value", c_void_p)
220                ]
221
222 class X509_EXT(object):
223     """ Python object which represents a certificate extension """
224     def __init__(self, ptr, copy=False):
225         """ Initializes from the pointer to X509_EXTENSION.
226             If copy is True, creates a copy, otherwise just
227             stores pointer.
228         """
229         if copy:
230             self.ptr = libcrypto.X509_EXTENSION_dup(ptr)
231         else:
232             self.ptr = cast(ptr, POINTER(_x509_ext))
233     def __del__(self):
234         libcrypto.X509_EXTENSION_free(self.ptr)
235     def __str__(self):
236         bio = Membio()
237         libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
238         return str(bio)
239     def __unicode__(self):
240         bio = Membio()
241         libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
242         return unicode(bio)
243     @property
244     def oid(self):
245         "Returns OID of the extension"
246         return Oid.fromobj(self.ptr[0].object)
247     @property
248     def critical(self):
249         "Returns True if extensin have critical flag set"
250         return self.ptr[0].critical > 0
251
252 class _X509extlist(object):
253     """
254     Represents list of certificate extensions. Really it keeps
255     reference to certificate object
256     """
257     def __init__(self, cert):
258         """
259         Initialize from X509 object
260         """
261         self.cert = cert
262
263     def __len__(self):
264         """
265         Returns number of extensions
266         """
267         return libcrypto.X509_get_ext_count(self.cert.cert)
268
269     def __getitem__(self, item):
270         """
271         Returns extension by index, creating a copy
272         """
273         ext_ptr = libcrypto.X509_get_ext(self.cert.cert, item)
274         if ext_ptr is None:
275             raise IndexError
276         return X509_EXT(ext_ptr, True)
277     def find(self, oid):
278         """
279         Return list of extensions with given Oid
280         """
281         if not isinstance(oid, Oid):
282             raise TypeError("Need crytypescrypto.oid.Oid as argument")
283         found = []
284         index = -1
285         end = len(self)
286         while True:
287             index = libcrypto.X509_get_ext_by_NID(self.cert.cert, oid.nid,
288                                                   index)
289             if index >= end or index < 0:
290                 break
291             found.append(self[index])
292         return found
293
294     def find_critical(self, crit=True):
295         """
296         Return list of critical extensions (or list of non-cricital, if
297         optional second argument is False
298         """
299         if crit:
300             flag = 1
301         else:
302             flag = 0
303         found = []
304         end = len(self)
305         index = -1
306         while True:
307             index = libcrypto.X509_get_ext_by_critical(self.cert.cert, flag,
308                                                        index)
309             if index >= end or index < 0:
310                 break
311             found.append(self[index])
312         return found
313
314 def _X509__asn1date_to_datetime(asn1date):
315     """ 
316     Converts openssl ASN1_TIME object to python datetime.datetime
317     """
318     bio = Membio()
319     libcrypto.ASN1_TIME_print(bio.bio, asn1date)
320     pydate = datetime.strptime(str(bio), "%b %d %H:%M:%S %Y %Z")
321     return pydate.replace(tzinfo=utc)
322
323 class X509(object):
324     """
325     Represents X.509 certificate.
326     """
327     def __init__(self, data=None, ptr=None, format="PEM"):
328         """
329         Initializes certificate
330         @param data - serialized certificate in PEM or DER format.
331         @param ptr - pointer to X509, returned by some openssl function.
332             mutually exclusive with data
333         @param format - specifies data format. "PEM" or "DER", default PEM
334         """
335         if ptr is not None:
336             if data is not None:
337                 raise TypeError("Cannot use data and ptr simultaneously")
338             self.cert = ptr
339         elif data is None:
340             raise TypeError("data argument is required")
341         else:
342             bio = Membio(data)
343             if format == "PEM":
344                 self.cert = libcrypto.PEM_read_bio_X509(bio.bio, None, None,
345                                                         None)
346             else:
347                 self.cert = libcrypto.d2i_X509_bio(bio.bio, None)
348             if self.cert is None:
349                 raise X509Error("error reading certificate")
350         self.extensions = _X509extlist(self)
351     def __del__(self):
352         """
353         Frees certificate object
354         """
355         libcrypto.X509_free(self.cert)
356     def __str__(self):
357         """ Returns der string of the certificate """
358         bio = Membio()
359         if libcrypto.i2d_X509_bio(bio.bio, self.cert) == 0:
360             raise X509Error("error serializing certificate")
361         return str(bio)
362     def __repr__(self):
363         """ Returns valid call to the constructor """
364         return "X509(data=" + repr(str(self)) + ",format='DER')"
365     @property
366     def pubkey(self):
367         """EVP PKEy object of certificate public key"""
368         return PKey(ptr=libcrypto.X509_get_pubkey(self.cert, False))
369     def pem(self):
370         """ Returns PEM represntation of the certificate """
371         bio = Membio()
372         if libcrypto.PEM_write_bio_X509(bio.bio, self.cert) == 0:
373             raise X509Error("error serializing certificate")
374         return str(bio)
375     def verify(self, store=None, chain=None, key=None):
376         """
377         Verify self. Supports verification on both X509 store object
378         or just public issuer key
379         @param store X509Store object.
380         @param chain - list of X509 objects to add into verification
381             context.These objects are untrusted, but can be used to
382             build certificate chain up to trusted object in the store
383         @param key - PKey object with open key to validate signature
384
385         parameters store and key are mutually exclusive. If neither
386         is specified, attempts to verify self as self-signed certificate
387         """
388         if store is not None and key is not None:
389             raise X509Error("key and store cannot be specified simultaneously")
390         if store is not None:
391             ctx = libcrypto.X509_STORE_CTX_new()
392             if ctx is None:
393                 raise X509Error("Error allocating X509_STORE_CTX")
394             if chain is not None and len(chain) > 0:
395                 chain_ptr = StackOfX509(chain).ptr
396             else:
397                 chain_ptr = None
398             if libcrypto.X509_STORE_CTX_init(ctx, store.store, self.cert,
399                                              chain_ptr) < 0:
400                 raise X509Error("Error allocating X509_STORE_CTX")
401             res = libcrypto.X509_verify_cert(ctx)
402             libcrypto.X509_STORE_CTX_free(ctx)
403             return res > 0
404         else:
405             if key is None:
406                 if self.issuer != self.subject:
407                     # Not a self-signed certificate
408                     return False
409                 key = self.pubkey
410             res = libcrypto.X509_verify(self.cert, key.key)
411             if res < 0:
412                 raise X509Error("X509_verify failed")
413             return res > 0
414
415     @property
416     def subject(self):
417         """ X509Name for certificate subject name """
418         return X509Name(libcrypto.X509_get_subject_name(self.cert))
419     @property
420     def issuer(self):
421         """ X509Name for certificate issuer name """
422         return X509Name(libcrypto.X509_get_issuer_name(self.cert))
423     @property
424     def serial(self):
425         """ Serial number of certificate as integer """
426         asnint = libcrypto.X509_get_serialNumber(self.cert)
427         bio = Membio()
428         libcrypto.i2a_ASN1_INTEGER(bio.bio, asnint)
429         return int(str(bio), 16)
430     @property
431     def version(self):
432         """
433         certificate version as integer. Really certificate stores 0 for
434         version 1 and 2 for version 3, but we return 1 and 3
435         """
436         return _X509_get_version(self.cert) + 1
437     @property
438     def startDate(self):
439         """ Certificate validity period start date """
440         asn1 = _X509_get_notBefore(self.cert)
441         return __asn1date_to_datetime(asn1)
442     @property
443     def endDate(self):
444         """ Certificate validity period end date """
445         asn1 = _X509_get_notAfter(self.cert)
446         return __asn1date_to_datetime(asn1)
447     def check_ca(self):
448         """ Returns True if certificate is CA certificate """
449         return libcrypto.X509_check_ca(self.cert) > 0
450
451 class X509Store(object):
452     """
453     Represents trusted certificate store. Can be used to lookup CA
454     certificates to verify
455
456     @param file - file with several certificates and crls
457             to load into store
458     @param dir - hashed directory with certificates and crls
459     @param default - if true, default verify location (directory)
460         is installed
461
462     """
463     def __init__(self, file=None, dir=None, default=False):
464         """
465         Creates X509 store and installs lookup method. Optionally initializes
466         by certificates from given file or directory.
467         """
468         #
469         # Todo - set verification flags
470         #
471         self.store = libcrypto.X509_STORE_new()
472         if self.store is None:
473             raise X509Error("allocating store")
474         lookup = libcrypto.X509_STORE_add_lookup(self.store,
475                                                  libcrypto.X509_LOOKUP_file())
476         if lookup is None:
477             raise X509Error("error installing file lookup method")
478         if file is not None:
479             if not libcrypto.X509_LOOKUP_ctrl(lookup, 1, file, 1, None) > 0:
480                 raise X509Error("error loading trusted certs from file "+file)
481         lookup = libcrypto.X509_STORE_add_lookup(self.store,
482                                              libcrypto.X509_LOOKUP_hash_dir())
483         if lookup is None:
484             raise X509Error("error installing hashed lookup method")
485         if dir is not None:
486             if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, dir, 1, None) > 0:
487                 raise X509Error("error adding hashed  trusted certs dir "+dir)
488         if default:
489             if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, None, 3, None) > 0:
490                 raise X509Error("error adding default trusted certs dir ")
491     def add_cert(self, cert):
492         """
493         Explicitely adds certificate to set of trusted in the store
494         @param cert - X509 object to add
495         """
496         if not isinstance(cert, X509):
497             raise TypeError("cert should be X509")
498         libcrypto.X509_STORE_add_cert(self.store, cert.cert)
499     def add_callback(self, callback):
500         """
501         Installs callback function, which would receive detailed information
502         about verified ceritificates
503         """
504         raise NotImplementedError
505     def setflags(self, flags):
506         """
507         Set certificate verification flags.
508         @param flags - integer bit mask. See OpenSSL X509_V_FLAG_* constants
509         """
510         libcrypto.X509_STORE_set_flags(self.store, flags)
511     def setpurpose(self, purpose):
512         """
513         Sets certificate purpose which verified certificate should match
514         @param purpose - number from 1 to 9 or standard strind defined
515                          in Openssl
516         possible strings - sslcient,sslserver, nssslserver, smimesign,i
517                          smimeencrypt, crlsign, any, ocsphelper
518         """
519         if isinstance(purpose, str):
520             purp_no = libcrypto.X509_PURPOSE_get_by_sname(purpose)
521             if purp_no <= 0:
522                 raise X509Error("Invalid certificate purpose '%s'" % purpose)
523         elif isinstance(purpose, int):
524             purp_no = purpose
525         if libcrypto.X509_STORE_set_purpose(self.store, purp_no) <= 0:
526             raise X509Error("cannot set purpose")
527     def setdepth(self, depth):
528         """
529         Sets the verification depth i.e. max length of certificate chain
530         which is acceptable
531         """
532         libcrypto.X509_STORE_set_depth(self.store, depth)
533     def settime(self, time):
534         """
535         Set point in time used to check validity of certificates for
536         Time can be either python datetime object or number of seconds
537         sinse epoch
538         """
539         if isinstance(time, datetime) or isinstance(time,
540                                                              datetime.date):
541             seconds = int(time.strftime("%s"))
542         elif isinstance(time, int):
543             seconds = time
544         else:
545             raise TypeError("datetime.date, datetime.datetime or integer " +
546                             "is required as time argument")
547         raise NotImplementedError
548 class StackOfX509(object):
549     """
550     Implements OpenSSL STACK_OF(X509) object.
551     It looks much like python container types
552     """
553     def __init__(self, certs=None, ptr=None, disposable=True):
554         """
555         Create stack
556         @param certs - list of X509 objects. If specified, read-write
557             stack is created and populated by these certificates
558         @param ptr - pointer to OpenSSL STACK_OF(X509) as returned by
559             some functions
560         @param disposable - if True, stack created from object, returned
561                 by function is copy, and can be modified and need to be
562                 freeid. If false, it is just pointer into another
563                 structure i.e. CMS_ContentInfo
564         """
565         self.need_free = False
566         if  ptr is None:
567             self.need_free = True
568             self.ptr = libcrypto.sk_new_null()
569             if certs is not None:
570                 for crt in certs:
571                     self.append(crt)
572         elif certs is not None:
573             raise ValueError("cannot handle certs an ptr simultaneously")
574         else:
575             self.need_free = disposable
576             self.ptr = ptr
577     def __len__(self):
578         return libcrypto.sk_num(self.ptr)
579     def __getitem__(self, index):
580         if index < 0 or index >= len(self):
581             raise IndexError
582         p = libcrypto.sk_value(self.ptr, index)
583         return X509(ptr=libcrypto.X509_dup(p))
584     def __setitem__(self, index, value):
585         if not self.need_free:
586             raise ValueError("Stack is read-only")
587         if index < 0 or index >= len(self):
588             raise IndexError
589         if not isinstance(value, X509):
590             raise TypeError('StackOfX509 can contain only X509 objects')
591         p = libcrypto.sk_value(self.ptr, index)
592         libcrypto.sk_set(self.ptr, index, libcrypto.X509_dup(value.cert))
593         libcrypto.X509_free(p)
594     def __delitem__(self, index):
595         if not self.need_free:
596             raise ValueError("Stack is read-only")
597         if index < 0 or index >= len(self):
598             raise IndexError
599         p = libcrypto.sk_delete(self.ptr, index)
600         libcrypto.X509_free(p)
601     def __del__(self):
602         if self.need_free:
603             libcrypto.sk_pop_free(self.ptr, libcrypto.X509_free)
604     def append(self, value):
605         """ Adds certificate to stack """
606         if not self.need_free:
607             raise ValueError("Stack is read-only")
608         if not isinstance(value, X509):
609             raise TypeError('StackOfX509 can contain only X509 objects')
610         libcrypto.sk_push(self.ptr, libcrypto.X509_dup(value.cert))
611
612 libcrypto.d2i_X509_bio.argtypes = (c_void_p,POINTER(c_void_p))
613 libcrypto.X509_free.argtypes = (c_void_p,)
614 libcrypto.X509_dup.restype = c_void_p
615 libcrypto.X509_dup.argtypes = (c_void_p, )
616 libcrypto.i2a_ASN1_INTEGER.argtypes = (c_void_p, c_void_p)
617 libcrypto.ASN1_STRING_print_ex.argtypes = (c_void_p, c_void_p, c_long)
618 libcrypto.PEM_read_bio_X509.restype = c_void_p
619 libcrypto.PEM_read_bio_X509.argtypes = (c_void_p, POINTER(c_void_p),
620                                         c_void_p, c_void_p)
621 libcrypto.PEM_write_bio_X509.restype = c_int
622 libcrypto.PEM_write_bio_X509.argtypes = (c_void_p, c_void_p)
623 libcrypto.ASN1_TIME_print.argtypes = (c_void_p, c_void_p)
624 libcrypto.ASN1_INTEGER_get.argtypes = (c_void_p, )
625 libcrypto.ASN1_INTEGER_get.restype = c_long
626 libcrypto.X509_check_ca.argtypes = (c_void_p, )
627 libcrypto.X509_get_serialNumber.argtypes = (c_void_p, )
628 libcrypto.X509_get_serialNumber.restype = c_void_p
629 libcrypto.X509_get_subject_name.argtypes = (c_void_p, )
630 libcrypto.X509_get_subject_name.restype = c_void_p
631 libcrypto.X509_get_issuer_name.argtypes = (c_void_p, )
632 libcrypto.X509_get_issuer_name.restype = c_void_p
633 libcrypto.X509_NAME_ENTRY_get_object.restype = c_void_p
634 libcrypto.X509_NAME_ENTRY_get_object.argtypes = (c_void_p, )
635 libcrypto.X509_NAME_ENTRY_get_data.restype = c_void_p
636 libcrypto.X509_NAME_ENTRY_get_data.argtypes = (c_void_p, )
637 libcrypto.OBJ_obj2nid.argtypes = (c_void_p, )
638 libcrypto.X509_NAME_get_entry.restype = c_void_p
639 libcrypto.X509_NAME_get_entry.argtypes = (c_void_p, c_int)
640 libcrypto.X509_STORE_new.restype = c_void_p
641 libcrypto.X509_STORE_add_lookup.restype = c_void_p
642 libcrypto.X509_STORE_add_lookup.argtypes = (c_void_p, c_void_p)
643 libcrypto.X509_STORE_add_cert.argtypes = (c_void_p, c_void_p)
644 libcrypto.X509_STORE_CTX_new.restype = c_void_p
645 libcrypto.X509_STORE_CTX_free.argtypes = (c_void_p,)
646 libcrypto.X509_STORE_CTX_init.argtypes = (c_void_p, c_void_p, c_void_p,
647                                             c_void_p)
648 libcrypto.X509_STORE_set_depth.argtypes = (c_void_p, c_int)
649 libcrypto.X509_STORE_set_flags.argtypes = (c_void_p, c_ulong)
650 libcrypto.X509_STORE_set_purpose.argtypes = (c_void_p, c_int)
651 libcrypto.X509_LOOKUP_file.restype = c_void_p
652 libcrypto.X509_LOOKUP_hash_dir.restype = c_void_p
653 libcrypto.X509_LOOKUP_ctrl.restype = c_int
654 libcrypto.X509_LOOKUP_ctrl.argtypes = (c_void_p, c_int, c_char_p, c_long,
655                                        POINTER(c_char_p))
656 libcrypto.X509_EXTENSION_free.argtypes = (c_void_p, )
657 libcrypto.X509_EXTENSION_dup.argtypes = (c_void_p, )
658 libcrypto.X509_EXTENSION_dup.restype = POINTER(_x509_ext)
659 libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
660                                        c_int)
661 libcrypto.X509_get_ext.restype = c_void_p
662 libcrypto.X509_get_ext.argtypes = (c_void_p, c_int)
663 libcrypto.X509_get_ext_by_critical.argtypes = (c_void_p, c_int, c_int)
664 libcrypto.X509_get_ext_by_NID.argtypes = (c_void_p, c_int, c_int)
665 libcrypto.X509_get_ext_count.argtypes = (c_void_p, )
666 libcrypto.X509_get_pubkey.restype = c_void_p
667 libcrypto.X509_get_pubkey.argtypes = (c_void_p, )
668 libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
669       c_int)
670 libcrypto.X509_LOOKUP_file.restype = c_void_p
671 libcrypto.X509_LOOKUP_hash_dir.restype = c_void_p
672 libcrypto.X509_NAME_cmp.argtypes = (c_void_p, c_void_p)
673 libcrypto.X509_NAME_entry_count.argtypes = (c_void_p,) 
674 libcrypto.X509_NAME_free.argtypes = (c_void_p,)
675 libcrypto.X509_NAME_new.restype = c_void_p
676 libcrypto.X509_NAME_print_ex.argtypes = (c_void_p, c_void_p, c_int, c_ulong)
677 libcrypto.X509_PURPOSE_get_by_sname.argtypes=(c_char_p,)
678 libcrypto.X509_verify.argtypes = (c_void_p, c_void_p)
679 libcrypto.X509_verify_cert.argtypes = (c_void_p,)
680 libcrypto.sk_num.restype = c_int
681 libcrypto.sk_num.argtypes= (c_void_p,)
682 libcrypto.sk_set.argtypes = (c_void_p, c_int, c_void_p)
683 libcrypto.sk_set.restype = c_void_p
684 libcrypto.sk_value.argtypes = (c_void_p, c_int)
685 libcrypto.sk_value.restype = c_void_p
686 libcrypto.sk_delete.argtypes = (c_void_p, c_int)
687 libcrypto.sk_delete.restype = c_void_p
688 libcrypto.sk_new_null.restype = c_void_p
689 libcrypto.sk_pop_free.argtypes = (c_void_p, c_void_p)
690 libcrypto.sk_push.argtypes = (c_void_p, c_void_p)
691 libcrypto.X509_NAME_hash.restype = c_long
692 libcrypto.X509_NAME_hash.argtypes = (c_void_p, )
693 libcrypto.X509_NAME_get_index_by_NID.argtypes = (c_void_p, c_int, c_int)