-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
__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
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 """
- # 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 """
- # 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 """
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
- self.ptr = libcrypto.sk_new_null()
+ self.ptr = sk_new_null()
if certs is not None:
for crt in certs:
self.append(crt)
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
- 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:
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
- 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.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):
- 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.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_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_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.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_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_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,
- 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_get_index_by_NID.argtypes = (c_void_p, c_int, c_int)