]> www.wagner.pp.ru Git - oss/ctypescrypto.git/blobdiff - ctypescrypto/x509.py
Python 3 support for modules pbkdf2 pkey ec x509
[oss/ctypescrypto.git] / ctypescrypto / x509.py
index 40263cffea5d1e26528bb989231a92808bfc86a2..35ab1fee27faeb47b199e62385df1239828f02f1 100644 (file)
@@ -8,14 +8,14 @@ such as CMS, OCSP and timestamps.
 
 
 
 
 
 
-from ctypes import c_void_p, c_long, c_int, POINTER, c_char_p, Structure, cast
+from ctypes import c_void_p, c_long, c_ulong, c_int, POINTER, c_char_p, Structure, cast
 from ctypescrypto.bio import Membio
 from ctypescrypto.pkey import PKey
 from ctypescrypto.oid import Oid
 from ctypescrypto.exception import LibCryptoError
 from ctypescrypto.bio import Membio
 from ctypescrypto.pkey import PKey
 from ctypescrypto.oid import Oid
 from ctypescrypto.exception import LibCryptoError
-from ctypescrypto import libcrypto
+from ctypescrypto import libcrypto, pyver, chartype, inttype, bintype
 from datetime import datetime
 from datetime import datetime
-
+import sys
 try:
     from pytz import utc
 except ImportError:
 try:
     from pytz import utc
 except ImportError:
@@ -38,43 +38,85 @@ except ImportError:
 
 __all__ = ['X509', 'X509Error', 'X509Name', 'X509Store', 'StackOfX509']
 
 
 __all__ = ['X509', 'X509Error', 'X509Name', 'X509Store', 'StackOfX509']
 
-class _validity(Structure):
-    """ ctypes representation of X509_VAL structure
-        needed to access certificate validity period, because openssl
-        doesn't provide fuctions for it - only macros
-    """
-    _fields_ = [('notBefore', c_void_p), ('notAfter', c_void_p)]
-
-class _cinf(Structure):
-    """ ctypes representtion of X509_CINF structure
-        neede to access certificate data, which are accessable only
-        via macros
-    """
-    _fields_ = [('version', c_void_p),
-                ('serialNumber', c_void_p),
-                ('sign_alg', c_void_p),
-                ('issuer', c_void_p),
-                ('validity', POINTER(_validity)),
-                ('subject', c_void_p),
-                ('pubkey', c_void_p),
-                ('issuerUID', c_void_p),
-                ('subjectUID', c_void_p),
-                ('extensions', c_void_p),
-               ]
-
-class _x509(Structure):
-    """
-    ctypes represntation of X509 structure needed
-    to access certificate data which are accesable only via
-    macros, not functions
-    """
-    _fields_ = [('cert_info', POINTER(_cinf)),
-                ('sig_alg', c_void_p),
-                ('signature', c_void_p),
-                # There are a lot of parsed extension fields there
-               ]
-_px509 = POINTER(_x509)
-
+if hasattr(libcrypto,"X509_get_version"):
+    
+# If it is OpenSSL 1.1 or above, use accessor functions
+    _X509_get_version = libcrypto.X509_get_version
+    _X509_get_version.restype = c_long
+    _X509_get_version.argtypes = (c_void_p,)
+
+    _X509_get_notBefore=libcrypto.X509_getm_notBefore
+    _X509_get_notBefore.restype = c_void_p
+    _X509_get_notBefore.argtypes = (c_void_p,)
+
+    _X509_get_notAfter=libcrypto.X509_getm_notAfter
+    _X509_get_notAfter.restype = c_void_p
+    _X509_get_notAfter.argtypes = (c_void_p,)
+else:
+    # Otherwise declare X509 structure internals and define deep poke
+    # functions
+    class _validity(Structure):
+        """ ctypes representation of X509_VAL structure
+            needed to access certificate validity period, because openssl
+            doesn't provide fuctions for it - only macros
+        """
+        _fields_ = [('notBefore', c_void_p), ('notAfter', c_void_p)]
+
+    class _cinf(Structure):
+        """ ctypes representtion of X509_CINF structure
+            neede to access certificate data, which are accessable only
+            via macros
+        """
+        _fields_ = [('version', c_void_p),
+                    ('serialNumber', c_void_p),
+                    ('sign_alg', c_void_p),
+                    ('issuer', c_void_p),
+                    ('validity', POINTER(_validity)),
+                    ('subject', c_void_p),
+                    ('pubkey', c_void_p),
+                    ('issuerUID', c_void_p),
+                    ('subjectUID', c_void_p),
+                    ('extensions', c_void_p),
+                ]
+
+    class _x509(Structure):
+        """
+        ctypes represntation of X509 structure needed
+        to access certificate data which are accesable only via
+        macros, not functions
+        """
+        _fields_ = [('cert_info', POINTER(_cinf)),
+                    ('sig_alg', c_void_p),
+                    ('signature', c_void_p),
+                    # There are a lot of parsed extension fields there
+                ]
+    _px509 = POINTER(_x509)
+    def _X509_get_version(ptr):
+        asn1int = cast(ptr, _px509)[0].cert_info[0].version  
+        return libcrypto.ASN1_INTEGER_get(asn1int)
+
+    def _X509_get_notBefore(ptr):   
+        # (x)->cert_info->validity->notBefore
+        return cast(ptr, _px509)[0].cert_info[0].validity[0].notBefore
+    def _X509_get_notAfter(ptr):
+        return cast(ptr, _px509)[0].cert_info[0].validity[0].notAfter
+
+if hasattr(libcrypto,'sk_num'):
+    sk_num = libcrypto.sk_num
+    sk_set = libcrypto.sk_set
+    sk_value = libcrypto.sk_value
+    sk_delete = libcrypto.sk_delete
+    sk_new_null = libcrypto.sk_new_null
+    sk_pop_free = libcrypto.sk_pop_free
+    sk_push = libcrypto.sk_push
+else:
+    sk_num = libcrypto.OPENSSL_sk_num
+    sk_set = libcrypto.OPENSSL_sk_set
+    sk_value = libcrypto.OPENSSL_sk_value
+    sk_delete = libcrypto.OPENSSL_sk_delete
+    sk_new_null = libcrypto.OPENSSL_sk_new_null
+    sk_pop_free = libcrypto.OPENSSL_sk_pop_free
+    sk_push = libcrypto.OPENSSL_sk_push
 class X509Error(LibCryptoError):
     """
     Exception, generated when some openssl function fail
 class X509Error(LibCryptoError):
     """
     Exception, generated when some openssl function fail
@@ -118,7 +160,7 @@ class X509Name(object):
         """
         if self.need_free:
             libcrypto.X509_NAME_free(self.ptr)
         """
         if self.need_free:
             libcrypto.X509_NAME_free(self.ptr)
-    def __str__(self):
+    def __bytes__(self):
         """
         Produces an ascii representation of the name, escaping all
         symbols > 0x80.  Probably it is not what you want, unless
         """
         Produces an ascii representation of the name, escaping all
         symbols > 0x80.  Probably it is not what you want, unless
@@ -127,7 +169,7 @@ class X509Name(object):
         bio = Membio()
         libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0,
                                      self.PRINT_FLAG | self.ESC_MSB)
         bio = Membio()
         libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0,
                                      self.PRINT_FLAG | self.ESC_MSB)
-        return str(bio)
+        return bio.__bytes__()
 
     def __unicode__(self):
         """
 
     def __unicode__(self):
         """
@@ -135,7 +177,13 @@ class X509Name(object):
         """
         bio = Membio()
         libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0, self.PRINT_FLAG)
         """
         bio = Membio()
         libcrypto.X509_NAME_print_ex(bio.bio, self.ptr, 0, self.PRINT_FLAG)
-        return unicode(bio)
+        return bio.__unicode__()
+    if pyver == 2:
+        __str__ = __bytes__
+    else:
+        __str__ = __unicode__
+            
+
     def __len__(self):
         """
         return number of components in the name
     def __len__(self):
         """
         return number of components in the name
@@ -148,6 +196,10 @@ class X509Name(object):
         return libcrypto.X509_NAME_cmp(self.ptr, other.ptr)
     def __eq__(self, other):
         return libcrypto.X509_NAME_cmp(self.ptr, other.ptr) == 0
         return libcrypto.X509_NAME_cmp(self.ptr, other.ptr)
     def __eq__(self, other):
         return libcrypto.X509_NAME_cmp(self.ptr, other.ptr) == 0
+    def __gt__(self, other):
+        return libcrypto.X509_NAME_cmp(self.ptr, other.ptr) > 0
+    def __lt__(self, other):
+        return libcrypto.X509_NAME_cmp(self.ptr, other.ptr) < 0
 
     def __getitem__(self, key):
         if isinstance(key, Oid):
 
     def __getitem__(self, key):
         if isinstance(key, Oid):
@@ -159,8 +211,8 @@ class X509Name(object):
             value = libcrypto.X509_NAME_ENTRY_get_data(entry)
             bio = Membio()
             libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
             value = libcrypto.X509_NAME_ENTRY_get_data(entry)
             bio = Membio()
             libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
-            return unicode(bio)
-        elif isinstance(key, (int, long)):
+            return chartype(bio)
+        elif isinstance(key, inttype):
             # Return OID, string tuple
             entry = libcrypto.X509_NAME_get_entry(self.ptr, key)
             if entry is None:
             # Return OID, string tuple
             entry = libcrypto.X509_NAME_get_entry(self.ptr, key)
             if entry is None:
@@ -169,7 +221,7 @@ class X509Name(object):
             value = libcrypto.X509_NAME_ENTRY_get_data(entry)
             bio = Membio()
             libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
             value = libcrypto.X509_NAME_ENTRY_get_data(entry)
             bio = Membio()
             libcrypto.ASN1_STRING_print_ex(bio.bio, value, self.PRINT_FLAG)
-            return (oid, unicode(bio))
+            return (oid, chartype(bio))
         else:
             raise TypeError("X509 NAME can be indexed by Oids or integers only")
 
         else:
             raise TypeError("X509 NAME can be indexed by Oids or integers only")
 
@@ -206,14 +258,18 @@ class X509_EXT(object):
             self.ptr = cast(ptr, POINTER(_x509_ext))
     def __del__(self):
         libcrypto.X509_EXTENSION_free(self.ptr)
             self.ptr = cast(ptr, POINTER(_x509_ext))
     def __del__(self):
         libcrypto.X509_EXTENSION_free(self.ptr)
-    def __str__(self):
+    def __bytes__(self):
         bio = Membio()
         libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
         bio = Membio()
         libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
-        return str(bio)
+        return bintype(bio)
     def __unicode__(self):
         bio = Membio()
         libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
     def __unicode__(self):
         bio = Membio()
         libcrypto.X509V3_EXT_print(bio.bio, self.ptr, 0x20010, 0)
-        return unicode(bio)
+        return chartype(bio)
+    if pyver == 2:
+        __str__ = __bytes__
+    else:
+        __str__ = __unicode__
     @property
     def oid(self):
         "Returns OID of the extension"
     @property
     def oid(self):
         "Returns OID of the extension"
@@ -327,15 +383,17 @@ class X509(object):
         Frees certificate object
         """
         libcrypto.X509_free(self.cert)
         Frees certificate object
         """
         libcrypto.X509_free(self.cert)
-    def __str__(self):
+    def __bytes__(self):
         """ Returns der string of the certificate """
         bio = Membio()
         if libcrypto.i2d_X509_bio(bio.bio, self.cert) == 0:
             raise X509Error("error serializing certificate")
         return str(bio)
         """ Returns der string of the certificate """
         bio = Membio()
         if libcrypto.i2d_X509_bio(bio.bio, self.cert) == 0:
             raise X509Error("error serializing certificate")
         return str(bio)
+    if pyver == 2:
+        __str__ = __bytes__
     def __repr__(self):
         """ Returns valid call to the constructor """
     def __repr__(self):
         """ Returns valid call to the constructor """
-        return "X509(data=" + repr(str(self)) + ",format='DER')"
+        return "X509(data=" + repr(self.pem()) + ",format='PEM')"
     @property
     def pubkey(self):
         """EVP PKEy object of certificate public key"""
     @property
     def pubkey(self):
         """EVP PKEy object of certificate public key"""
@@ -407,21 +465,16 @@ class X509(object):
         certificate version as integer. Really certificate stores 0 for
         version 1 and 2 for version 3, but we return 1 and 3
         """
         certificate version as integer. Really certificate stores 0 for
         version 1 and 2 for version 3, but we return 1 and 3
         """
-        asn1int = cast(self.cert, _px509)[0].cert_info[0].version
-        return libcrypto.ASN1_INTEGER_get(asn1int) + 1
+        return _X509_get_version(self.cert) + 1
     @property
     def startDate(self):
         """ Certificate validity period start date """
     @property
     def startDate(self):
         """ Certificate validity period start date """
-        # Need deep poke into certificate structure
-        # (x)->cert_info->validity->notBefore
-        asn1 = cast(self.cert, _px509)[0].cert_info[0].validity[0].notBefore
+        asn1 = _X509_get_notBefore(self.cert)
         return __asn1date_to_datetime(asn1)
     @property
     def endDate(self):
         """ Certificate validity period end date """
         return __asn1date_to_datetime(asn1)
     @property
     def endDate(self):
         """ Certificate validity period end date """
-        # Need deep poke into certificate structure
-        # (x)->cert_info->validity->notAfter
-        asn1 = cast(self.cert, _px509)[0].cert_info[0].validity[0].notAfter
+        asn1 = _X509_get_notAfter(self.cert)
         return __asn1date_to_datetime(asn1)
     def check_ca(self):
         """ Returns True if certificate is CA certificate """
         return __asn1date_to_datetime(asn1)
     def check_ca(self):
         """ Returns True if certificate is CA certificate """
@@ -455,14 +508,22 @@ class X509Store(object):
         if lookup is None:
             raise X509Error("error installing file lookup method")
         if file is not None:
         if lookup is None:
             raise X509Error("error installing file lookup method")
         if file is not None:
-            if not libcrypto.X509_LOOKUP_ctrl(lookup, 1, file, 1, None) > 0:
+            if pyver == 2:
+                fn = file
+            else:
+                fn = file.encode(sys.getfilesystemencoding())
+            if not libcrypto.X509_LOOKUP_ctrl(lookup, 1, fn, 1, None) > 0:
                 raise X509Error("error loading trusted certs from file "+file)
         lookup = libcrypto.X509_STORE_add_lookup(self.store,
                                              libcrypto.X509_LOOKUP_hash_dir())
         if lookup is None:
             raise X509Error("error installing hashed lookup method")
         if dir is not None:
                 raise X509Error("error loading trusted certs from file "+file)
         lookup = libcrypto.X509_STORE_add_lookup(self.store,
                                              libcrypto.X509_LOOKUP_hash_dir())
         if lookup is None:
             raise X509Error("error installing hashed lookup method")
         if dir is not None:
-            if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, dir, 1, None) > 0:
+            if pyver == 2:
+                dr = dir
+            else:
+                dr = dir.encode(sys.getfilesystemencoding())
+            if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, dr, 1, None) > 0:
                 raise X509Error("error adding hashed  trusted certs dir "+dir)
         if default:
             if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, None, 3, None) > 0:
                 raise X509Error("error adding hashed  trusted certs dir "+dir)
         if default:
             if not libcrypto.X509_LOOKUP_ctrl(lookup, 2, None, 3, None) > 0:
@@ -541,9 +602,10 @@ class StackOfX509(object):
                 freeid. If false, it is just pointer into another
                 structure i.e. CMS_ContentInfo
         """
                 freeid. If false, it is just pointer into another
                 structure i.e. CMS_ContentInfo
         """
+        self.need_free = False
         if  ptr is None:
             self.need_free = True
         if  ptr is None:
             self.need_free = True
-            self.ptr = libcrypto.sk_new_null()
+            self.ptr = sk_new_null()
             if certs is not None:
                 for crt in certs:
                     self.append(crt)
             if certs is not None:
                 for crt in certs:
                     self.append(crt)
@@ -553,11 +615,11 @@ class StackOfX509(object):
             self.need_free = disposable
             self.ptr = ptr
     def __len__(self):
             self.need_free = disposable
             self.ptr = ptr
     def __len__(self):
-        return libcrypto.sk_num(self.ptr)
+        return sk_num(self.ptr)
     def __getitem__(self, index):
         if index < 0 or index >= len(self):
             raise IndexError
     def __getitem__(self, index):
         if index < 0 or index >= len(self):
             raise IndexError
-        p = libcrypto.sk_value(self.ptr, index)
+        p = sk_value(self.ptr, index)
         return X509(ptr=libcrypto.X509_dup(p))
     def __setitem__(self, index, value):
         if not self.need_free:
         return X509(ptr=libcrypto.X509_dup(p))
     def __setitem__(self, index, value):
         if not self.need_free:
@@ -565,28 +627,32 @@ class StackOfX509(object):
         if index < 0 or index >= len(self):
             raise IndexError
         if not isinstance(value, X509):
         if index < 0 or index >= len(self):
             raise IndexError
         if not isinstance(value, X509):
-            raise TypeError('StackOfX508 can contain only X509 objects')
-        p = libcrypto.sk_value(self.ptr, index)
-        libcrypto.sk_set(self.ptr, index, libcrypto.X509_dup(value.cert))
+            raise TypeError('StackOfX509 can contain only X509 objects')
+        p = sk_value(self.ptr, index)
+        sk_set(self.ptr, index, libcrypto.X509_dup(value.cert))
         libcrypto.X509_free(p)
     def __delitem__(self, index):
         if not self.need_free:
             raise ValueError("Stack is read-only")
         if index < 0 or index >= len(self):
             raise IndexError
         libcrypto.X509_free(p)
     def __delitem__(self, index):
         if not self.need_free:
             raise ValueError("Stack is read-only")
         if index < 0 or index >= len(self):
             raise IndexError
-        p = libcrypto.sk_delete(self.ptr, index)
+        p = sk_delete(self.ptr, index)
         libcrypto.X509_free(p)
     def __del__(self):
         if self.need_free:
         libcrypto.X509_free(p)
     def __del__(self):
         if self.need_free:
-            libcrypto.sk_pop_free(self.ptr, libcrypto.X509_free)
+            sk_pop_free(self.ptr, libcrypto.X509_free)
     def append(self, value):
         """ Adds certificate to stack """
         if not self.need_free:
             raise ValueError("Stack is read-only")
         if not isinstance(value, X509):
     def append(self, value):
         """ Adds certificate to stack """
         if not self.need_free:
             raise ValueError("Stack is read-only")
         if not isinstance(value, X509):
-            raise TypeError('StackOfX508 can contain only X509 objects')
-        libcrypto.sk_push(self.ptr, libcrypto.X509_dup(value.cert))
+            raise TypeError('StackOfX509 can contain only X509 objects')
+        sk_push(self.ptr, libcrypto.X509_dup(value.cert))
 
 
+libcrypto.d2i_X509_bio.argtypes = (c_void_p,POINTER(c_void_p))
+libcrypto.X509_free.argtypes = (c_void_p,)
+libcrypto.X509_dup.restype = c_void_p
+libcrypto.X509_dup.argtypes = (c_void_p, )
 libcrypto.i2a_ASN1_INTEGER.argtypes = (c_void_p, c_void_p)
 libcrypto.ASN1_STRING_print_ex.argtypes = (c_void_p, c_void_p, c_long)
 libcrypto.PEM_read_bio_X509.restype = c_void_p
 libcrypto.i2a_ASN1_INTEGER.argtypes = (c_void_p, c_void_p)
 libcrypto.ASN1_STRING_print_ex.argtypes = (c_void_p, c_void_p, c_long)
 libcrypto.PEM_read_bio_X509.restype = c_void_p
@@ -597,35 +663,71 @@ libcrypto.PEM_write_bio_X509.argtypes = (c_void_p, c_void_p)
 libcrypto.ASN1_TIME_print.argtypes = (c_void_p, c_void_p)
 libcrypto.ASN1_INTEGER_get.argtypes = (c_void_p, )
 libcrypto.ASN1_INTEGER_get.restype = c_long
 libcrypto.ASN1_TIME_print.argtypes = (c_void_p, c_void_p)
 libcrypto.ASN1_INTEGER_get.argtypes = (c_void_p, )
 libcrypto.ASN1_INTEGER_get.restype = c_long
+libcrypto.X509_check_ca.argtypes = (c_void_p, )
 libcrypto.X509_get_serialNumber.argtypes = (c_void_p, )
 libcrypto.X509_get_serialNumber.restype = c_void_p
 libcrypto.X509_get_serialNumber.argtypes = (c_void_p, )
 libcrypto.X509_get_serialNumber.restype = c_void_p
+libcrypto.X509_get_subject_name.argtypes = (c_void_p, )
+libcrypto.X509_get_subject_name.restype = c_void_p
+libcrypto.X509_get_issuer_name.argtypes = (c_void_p, )
+libcrypto.X509_get_issuer_name.restype = c_void_p
 libcrypto.X509_NAME_ENTRY_get_object.restype = c_void_p
 libcrypto.X509_NAME_ENTRY_get_object.argtypes = (c_void_p, )
 libcrypto.X509_NAME_ENTRY_get_object.restype = c_void_p
 libcrypto.X509_NAME_ENTRY_get_object.argtypes = (c_void_p, )
+libcrypto.X509_NAME_ENTRY_get_data.restype = c_void_p
+libcrypto.X509_NAME_ENTRY_get_data.argtypes = (c_void_p, )
 libcrypto.OBJ_obj2nid.argtypes = (c_void_p, )
 libcrypto.X509_NAME_get_entry.restype = c_void_p
 libcrypto.X509_NAME_get_entry.argtypes = (c_void_p, c_int)
 libcrypto.X509_STORE_new.restype = c_void_p
 libcrypto.X509_STORE_add_lookup.restype = c_void_p
 libcrypto.X509_STORE_add_lookup.argtypes = (c_void_p, c_void_p)
 libcrypto.OBJ_obj2nid.argtypes = (c_void_p, )
 libcrypto.X509_NAME_get_entry.restype = c_void_p
 libcrypto.X509_NAME_get_entry.argtypes = (c_void_p, c_int)
 libcrypto.X509_STORE_new.restype = c_void_p
 libcrypto.X509_STORE_add_lookup.restype = c_void_p
 libcrypto.X509_STORE_add_lookup.argtypes = (c_void_p, c_void_p)
+libcrypto.X509_STORE_add_cert.argtypes = (c_void_p, c_void_p)
+libcrypto.X509_STORE_CTX_new.restype = c_void_p
+libcrypto.X509_STORE_CTX_free.argtypes = (c_void_p,)
+libcrypto.X509_STORE_CTX_init.argtypes = (c_void_p, c_void_p, c_void_p,
+                                            c_void_p)
+libcrypto.X509_STORE_set_depth.argtypes = (c_void_p, c_int)
+libcrypto.X509_STORE_set_flags.argtypes = (c_void_p, c_ulong)
+libcrypto.X509_STORE_set_purpose.argtypes = (c_void_p, c_int)
 libcrypto.X509_LOOKUP_file.restype = c_void_p
 libcrypto.X509_LOOKUP_hash_dir.restype = c_void_p
 libcrypto.X509_LOOKUP_ctrl.restype = c_int
 libcrypto.X509_LOOKUP_ctrl.argtypes = (c_void_p, c_int, c_char_p, c_long,
                                        POINTER(c_char_p))
 libcrypto.X509_LOOKUP_file.restype = c_void_p
 libcrypto.X509_LOOKUP_hash_dir.restype = c_void_p
 libcrypto.X509_LOOKUP_ctrl.restype = c_int
 libcrypto.X509_LOOKUP_ctrl.argtypes = (c_void_p, c_int, c_char_p, c_long,
                                        POINTER(c_char_p))
+libcrypto.X509_EXTENSION_free.argtypes = (c_void_p, )
 libcrypto.X509_EXTENSION_dup.argtypes = (c_void_p, )
 libcrypto.X509_EXTENSION_dup.restype = POINTER(_x509_ext)
 libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
                                        c_int)
 libcrypto.X509_get_ext.restype = c_void_p
 libcrypto.X509_get_ext.argtypes = (c_void_p, c_int)
 libcrypto.X509_EXTENSION_dup.argtypes = (c_void_p, )
 libcrypto.X509_EXTENSION_dup.restype = POINTER(_x509_ext)
 libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
                                        c_int)
 libcrypto.X509_get_ext.restype = c_void_p
 libcrypto.X509_get_ext.argtypes = (c_void_p, c_int)
+libcrypto.X509_get_ext_by_critical.argtypes = (c_void_p, c_int, c_int)
+libcrypto.X509_get_ext_by_NID.argtypes = (c_void_p, c_int, c_int)
+libcrypto.X509_get_ext_count.argtypes = (c_void_p, )
+libcrypto.X509_get_pubkey.restype = c_void_p
+libcrypto.X509_get_pubkey.argtypes = (c_void_p, )
 libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
 libcrypto.X509V3_EXT_print.argtypes = (c_void_p, POINTER(_x509_ext), c_long,
-                                       c_int)
-libcrypto.sk_set.argtypes = (c_void_p, c_int, c_void_p)
-libcrypto.sk_set.restype = c_void_p
-libcrypto.sk_value.argtypes = (c_void_p, c_int)
-libcrypto.sk_value.restype = c_void_p
-libcrypto.X509_dup.restype = c_void_p
-libcrypto.sk_new_null.restype = c_void_p
-libcrypto.X509_dup.argtypes = (c_void_p, )
+      c_int)
+libcrypto.X509_LOOKUP_file.restype = c_void_p
+libcrypto.X509_LOOKUP_hash_dir.restype = c_void_p
+libcrypto.X509_NAME_cmp.argtypes = (c_void_p, c_void_p)
+libcrypto.X509_NAME_entry_count.argtypes = (c_void_p,) 
+libcrypto.X509_NAME_free.argtypes = (c_void_p,)
+libcrypto.X509_NAME_new.restype = c_void_p
+libcrypto.X509_NAME_print_ex.argtypes = (c_void_p, c_void_p, c_int, c_ulong)
+libcrypto.X509_PURPOSE_get_by_sname.argtypes=(c_char_p,)
+libcrypto.X509_verify.argtypes = (c_void_p, c_void_p)
+libcrypto.X509_verify_cert.argtypes = (c_void_p,)
+sk_num.restype = c_int
+sk_num.argtypes= (c_void_p,)
+sk_set.argtypes = (c_void_p, c_int, c_void_p)
+sk_set.restype = c_void_p
+sk_value.argtypes = (c_void_p, c_int)
+sk_value.restype = c_void_p
+sk_delete.argtypes = (c_void_p, c_int)
+sk_delete.restype = c_void_p
+sk_new_null.restype = c_void_p
+sk_pop_free.argtypes = (c_void_p, c_void_p)
+sk_push.argtypes = (c_void_p, c_void_p)
 libcrypto.X509_NAME_hash.restype = c_long
 libcrypto.X509_NAME_hash.argtypes = (c_void_p, )
 libcrypto.X509_NAME_hash.restype = c_long
 libcrypto.X509_NAME_hash.argtypes = (c_void_p, )
+libcrypto.X509_NAME_get_index_by_NID.argtypes = (c_void_p, c_int, c_int)