aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPavol Žáčik <[email protected]>2019-12-03 21:38:34 +0100
committerPavol Žáčik <[email protected]>2019-12-03 21:38:34 +0100
commit75f73a0e74bf5c3fde87ac61b24bf0b2fde3a742 (patch)
tree350497da826898d6fd9b77ed2036338f3ff24fba
parent001b5250d61f8700438a9f609c6a3e5cb81a5de8 (diff)
Add CRL support for Python binding
-rwxr-xr-xsrc/python/botan2.py106
-rw-r--r--src/scripts/test_python.py23
2 files changed, 107 insertions, 22 deletions
diff --git a/src/python/botan2.py b/src/python/botan2.py
index dcff583a9..01fd4daf8 100755
--- a/src/python/botan2.py
+++ b/src/python/botan2.py
@@ -383,6 +383,14 @@ def _set_prototypes(dll):
dll.botan_x509_cert_validation_status.argtypes = [c_int]
dll.botan_x509_cert_validation_status.restype = c_char_p
+ # X509 CRL
+ ffi_api(dll.botan_x509_crl_load, [c_void_p, c_char_p, c_size_t])
+ ffi_api(dll.botan_x509_crl_load_file, [c_void_p, c_char_p])
+ ffi_api(dll.botan_x509_crl_destroy, [c_void_p])
+ ffi_api(dll.botan_x509_is_revoked, [c_void_p, c_void_p], [-1])
+ ffi_api(dll.botan_x509_cert_verify_with_crl,
+ [POINTER(c_int), c_void_p, c_void_p, c_size_t, c_void_p, c_size_t, c_void_p, c_size_t, c_char_p, c_size_t, c_char_p, c_uint64])
+
ffi_api(dll.botan_key_wrap3394,
[c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)])
ffi_api(dll.botan_key_unwrap3394,
@@ -1376,7 +1384,7 @@ class X509Cert(object): # pylint: disable=invalid-name
rc = _DLL.botan_x509_cert_allowed_usage(self.__obj, c_uint(usage))
return rc == 0
- def get_obj(self):
+ def handle_(self):
return self.__obj
def verify(self,
@@ -1385,36 +1393,90 @@ class X509Cert(object): # pylint: disable=invalid-name
trusted_path=None,
required_strength=0,
hostname=None,
- reference_time=0):
-
- c_intermediates = len(intermediates) * c_void_p
- arr_intermediates = c_intermediates()
- for i, ca in enumerate(intermediates):
- arr_intermediates[i] = ca.get_obj()
-
- c_trusted = len(trusted) * c_void_p
- arr_trusted = c_trusted()
- for i, ca in enumerate(trusted):
- arr_trusted[i] = ca.get_obj()
+ reference_time=0,
+ crls=None):
+
+ if intermediates is not None:
+ c_intermediates = len(intermediates) * c_void_p
+ arr_intermediates = c_intermediates()
+ for i, ca in enumerate(intermediates):
+ arr_intermediates[i] = ca.handle_()
+ len_intermediates = c_size_t(len(intermediates))
+ else:
+ arr_intermediates = c_void_p(0)
+ len_intermediates = c_size_t(0)
+
+ if trusted is not None:
+ c_trusted = len(trusted) * c_void_p
+ arr_trusted = c_trusted()
+ for i, ca in enumerate(trusted):
+ arr_trusted[i] = ca.handle_()
+ len_trusted = c_size_t(len(trusted))
+ else:
+ arr_trusted = c_void_p(0)
+ len_trusted = c_size_t(0)
+
+ if crls is not None:
+ c_crls = len(crls) * c_void_p
+ arr_crls = c_crls()
+ for i, crl in enumerate(crls):
+ arr_crls[i] = crl.handle_()
+ len_crls = c_size_t(len(crls))
+ else:
+ arr_crls = c_void_p(0)
+ len_crls = c_size_t(0)
error_code = c_int(0)
- _DLL.botan_x509_cert_verify(byref(error_code),
- self.__obj,
- byref(arr_intermediates),
- c_size_t(len(intermediates)),
- byref(arr_trusted),
- c_size_t(len(trusted)),
- _ctype_str(trusted_path),
- c_size_t(required_strength),
- _ctype_str(hostname),
- c_uint64(reference_time))
+ _DLL.botan_x509_cert_verify_with_crl(byref(error_code),
+ self.__obj,
+ byref(arr_intermediates),
+ len_intermediates,
+ byref(arr_trusted),
+ len_trusted,
+ byref(arr_crls),
+ len_crls,
+ _ctype_str(trusted_path),
+ c_size_t(required_strength),
+ _ctype_str(hostname),
+ c_uint64(reference_time))
+
return error_code.value
@classmethod
def validation_status(cls, error_code):
return _ctype_to_str(_DLL.botan_x509_cert_validation_status(c_int(error_code)))
+ def is_revoked(self, crl):
+ rc = _DLL.botan_x509_is_revoked(crl.handle_(), self.__obj)
+ return rc == 0
+
+
+#
+# X.509 Certificate revocation lists
+#
+class X509CRL(object):
+
+ def __init__(self, filename=None, buf=None):
+ if filename is None and buf is None:
+ raise BotanException("No filename or buf given")
+ if filename is not None and buf is not None:
+ raise BotanException("Both filename and buf given")
+
+ if filename is not None:
+ self.__obj = c_void_p(0)
+ _DLL.botan_x509_crl_load_file(byref(self.__obj), _ctype_str(filename))
+ elif buf is not None:
+ self.__obj = c_void_p(0)
+ _DLL.botan_x509_crl_load(byref(self.__obj), _ctype_bits(buf), len(buf))
+
+ def __del__(self):
+ _DLL.botan_x509_crl_destroy(self.__obj)
+
+ def handle_(self):
+ return self.__obj
+
+
class MPI(object): # pylint: disable=too-many-public-methods
def __init__(self, initial_value=None, radix=None):
diff --git a/src/scripts/test_python.py b/src/scripts/test_python.py
index ad1be89ce..40a5b6573 100644
--- a/src/scripts/test_python.py
+++ b/src/scripts/test_python.py
@@ -442,6 +442,7 @@ ofvkP1EDmpx50fHLawIDAQAB
self.assertEqual(a_pem, new_a.to_pem())
def test_certs(self):
+ # pylint: disable=too-many-statements
cert = botan2.X509Cert(filename="src/tests/data/x509/ecc/CSCA.CSCA.csca-germany.1.crt")
pubkey = cert.subject_public_key()
@@ -498,6 +499,28 @@ ofvkP1EDmpx50fHLawIDAQAB
self.assertEqual(botan2.X509Cert.validation_status(3000), 'Certificate issuer not found')
self.assertEqual(botan2.X509Cert.validation_status(4008), 'Certificate does not match provided name')
+ rootcrl = botan2.X509CRL("src/tests/data/x509/nist/root.crl")
+
+ end01 = botan2.X509Cert("src/tests/data/x509/nist/test01/end.crt")
+ self.assertEqual(end01.verify([], [root], required_strength=80, crls=[rootcrl]), 0)
+
+ int20 = botan2.X509Cert("src/tests/data/x509/nist/test20/int.crt")
+ end20 = botan2.X509Cert("src/tests/data/x509/nist/test20/end.crt")
+ int20crl = botan2.X509CRL("src/tests/data/x509/nist/test20/int.crl")
+
+ self.assertEqual(end20.verify([int20], [root], required_strength=80, crls=[int20crl, rootcrl]), 5000)
+ self.assertEqual(botan2.X509Cert.validation_status(5000), 'Certificate is revoked')
+
+ int21 = botan2.X509Cert("src/tests/data/x509/nist/test21/int.crt")
+ end21 = botan2.X509Cert("src/tests/data/x509/nist/test21/end.crt")
+ int21crl = botan2.X509CRL("src/tests/data/x509/nist/test21/int.crl")
+ self.assertEqual(end21.verify([int21], [root], required_strength=80, crls=[int21crl, rootcrl]), 5000)
+
+ self.assertTrue(int20.is_revoked(rootcrl))
+ self.assertFalse(int04_1.is_revoked(rootcrl))
+ self.assertTrue(end21.is_revoked(int21crl))
+
+
def test_mpi(self):
# pylint: disable=too-many-statements
z = botan2.MPI()