diff options
author | Pavol Žáčik <[email protected]> | 2019-12-03 21:38:34 +0100 |
---|---|---|
committer | Pavol Žáčik <[email protected]> | 2019-12-03 21:38:34 +0100 |
commit | 75f73a0e74bf5c3fde87ac61b24bf0b2fde3a742 (patch) | |
tree | 350497da826898d6fd9b77ed2036338f3ff24fba | |
parent | 001b5250d61f8700438a9f609c6a3e5cb81a5de8 (diff) |
Add CRL support for Python binding
-rwxr-xr-x | src/python/botan2.py | 106 | ||||
-rw-r--r-- | src/scripts/test_python.py | 23 |
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() |