diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/botan/src/python | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/botan/src/python')
-rwxr-xr-x | comm/third_party/botan/src/python/botan2.py | 1787 |
1 files changed, 1787 insertions, 0 deletions
diff --git a/comm/third_party/botan/src/python/botan2.py b/comm/third_party/botan/src/python/botan2.py new file mode 100755 index 0000000000..6ae1bd6da3 --- /dev/null +++ b/comm/third_party/botan/src/python/botan2.py @@ -0,0 +1,1787 @@ +#!/usr/bin/python + +""" +Python wrapper of the botan crypto library +https://botan.randombit.net + +(C) 2015,2017,2018,2019 Jack Lloyd +(C) 2015 Uri Blumenthal (extensions and patches) + +Botan is released under the Simplified BSD License (see license.txt) + +This module uses the ctypes module and is usable by programs running +under at least CPython 2.7, CPython 3.x, and PyPy + +It uses botan's ffi module, which exposes a C API. This version of the +module requires FFI API version 20180713, which was introduced in +Botan 2.8 + +""" + +from ctypes import CDLL, POINTER, byref, create_string_buffer, \ + c_void_p, c_size_t, c_uint8, c_uint32, c_uint64, c_int, c_uint, c_char_p + +from sys import version_info, platform +from time import strptime, mktime, time as system_time +from binascii import hexlify +from datetime import datetime + +BOTAN_FFI_VERSION = 20191214 + +# +# Base exception for all exceptions raised from this module +# +class BotanException(Exception): + + def __init__(self, message, rc=0): + + self.__rc = rc + + if rc == 0: + super(BotanException, self).__init__(message) + else: + descr = _DLL.botan_error_description(rc).decode('ascii') + super(BotanException, self).__init__("%s: %d (%s)" % (message, rc, descr)) + + def error_code(self): + return self.__rc + +# +# Module initialization +# + +def _load_botan_dll(expected_version): + + possible_dll_names = [] + + if platform in ['win32', 'cygwin', 'msys']: + possible_dll_names.append('botan.dll') + elif platform in ['darwin', 'macos']: + possible_dll_names.append('libbotan-2.dylib') + else: + # assumed to be some Unix/Linux system + possible_dll_names.append('libbotan-2.so') + possible_dll_names += ['libbotan-2.so.%d' % (v) for v in reversed(range(13, 20))] + + for dll_name in possible_dll_names: + try: + dll = CDLL(dll_name) + dll.botan_ffi_supports_api.argtypes = [c_uint32] + dll.botan_ffi_supports_api.restype = c_int + if dll.botan_ffi_supports_api(expected_version) == 0: + return dll + except OSError: + pass + + raise BotanException("Could not find a usable Botan shared object library") + +def _errcheck(rc, fn, _args): + # This errcheck should only be used for int-returning functions + assert isinstance(rc, int) + + if rc >= 0 or rc in fn.allowed_errors: + return rc + raise BotanException('%s failed' % (fn.__name__), rc) + +def _set_prototypes(dll): + # pylint: disable=too-many-statements,line-too-long + def ffi_api(fn, args, allowed_errors=None): + if allowed_errors is None: + allowed_errors = [-10] + fn.argtypes = args + fn.restype = c_int + fn.errcheck = _errcheck + fn.allowed_errors = allowed_errors + + dll.botan_version_string.argtypes = [] + dll.botan_version_string.restype = c_char_p + + dll.botan_version_string.argtypes = [] + dll.botan_version_string.restype = c_char_p + + dll.botan_version_major.argtypes = [] + dll.botan_version_major.restype = c_uint32 + + dll.botan_version_minor.argtypes = [] + dll.botan_version_minor.restype = c_uint32 + + dll.botan_version_patch.argtypes = [] + dll.botan_version_patch.restype = c_uint32 + + dll.botan_ffi_api_version.argtypes = [] + dll.botan_ffi_api_version.restype = c_uint32 + + dll.botan_error_description.argtypes = [c_int] + dll.botan_error_description.restype = c_char_p + + # These are generated using src/scripts/ffi_decls.py: + ffi_api(dll.botan_constant_time_compare, [c_void_p, c_void_p, c_size_t], [-1]) + ffi_api(dll.botan_scrub_mem, [c_void_p, c_size_t]) + + ffi_api(dll.botan_hex_encode, [c_char_p, c_size_t, c_char_p, c_uint32]) + ffi_api(dll.botan_hex_decode, [c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + + ffi_api(dll.botan_base64_encode, [c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_base64_decode, [c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + + # RNG + ffi_api(dll.botan_rng_init, [c_void_p, c_char_p]) + ffi_api(dll.botan_rng_get, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_rng_reseed, [c_void_p, c_size_t]) + ffi_api(dll.botan_rng_reseed_from_rng, [c_void_p, c_void_p, c_size_t]) + ffi_api(dll.botan_rng_add_entropy, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_rng_destroy, [c_void_p]) + + # HASH + ffi_api(dll.botan_hash_init, [c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_hash_copy_state, [c_void_p, c_void_p]) + ffi_api(dll.botan_hash_output_length, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_hash_block_size, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_hash_update, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_hash_final, [c_void_p, c_char_p]) + ffi_api(dll.botan_hash_clear, [c_void_p]) + ffi_api(dll.botan_hash_destroy, [c_void_p]) + ffi_api(dll.botan_hash_name, [c_void_p, c_char_p, POINTER(c_size_t)]) + + # MAC + ffi_api(dll.botan_mac_init, [c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_mac_output_length, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_mac_set_key, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_mac_update, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_mac_final, [c_void_p, c_char_p]) + ffi_api(dll.botan_mac_clear, [c_void_p]) + ffi_api(dll.botan_mac_name, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_mac_get_keyspec, [c_void_p, POINTER(c_size_t), POINTER(c_size_t), POINTER(c_size_t)]) + ffi_api(dll.botan_mac_destroy, [c_void_p]) + + # CIPHER + ffi_api(dll.botan_cipher_init, [c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_cipher_name, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_output_length, [c_void_p, c_size_t, POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_valid_nonce_length, [c_void_p, c_size_t]) + ffi_api(dll.botan_cipher_get_tag_length, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_get_default_nonce_length, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_get_update_granularity, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_query_keylen, [c_void_p, POINTER(c_size_t), POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_get_keyspec, [c_void_p, POINTER(c_size_t), POINTER(c_size_t), POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_set_key, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_cipher_reset, [c_void_p]) + ffi_api(dll.botan_cipher_set_associated_data, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_cipher_start, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_cipher_update, + [c_void_p, c_uint32, c_char_p, c_size_t, POINTER(c_size_t), c_char_p, c_size_t, POINTER(c_size_t)]) + ffi_api(dll.botan_cipher_clear, [c_void_p]) + ffi_api(dll.botan_cipher_destroy, [c_void_p]) + + ffi_api(dll.botan_pbkdf, + [c_char_p, c_char_p, c_size_t, c_char_p, c_char_p, c_size_t, c_size_t]) + ffi_api(dll.botan_pbkdf_timed, + [c_char_p, c_char_p, c_size_t, c_char_p, c_char_p, c_size_t, c_size_t, POINTER(c_size_t)]) + + ffi_api(dll.botan_pwdhash, + [c_char_p, c_size_t, c_size_t, c_size_t, c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, c_size_t]) + ffi_api(dll.botan_pwdhash_timed, + [c_char_p, c_uint32, POINTER(c_size_t), POINTER(c_size_t), POINTER(c_size_t), c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, c_size_t]) + + ffi_api(dll.botan_scrypt, + [c_char_p, c_size_t, c_char_p, c_char_p, c_size_t, c_size_t, c_size_t, c_size_t]) + + ffi_api(dll.botan_kdf, + [c_char_p, c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, c_size_t]) + + # BLOCK + ffi_api(dll.botan_block_cipher_init, [c_void_p, c_char_p]) + ffi_api(dll.botan_block_cipher_destroy, [c_void_p]) + ffi_api(dll.botan_block_cipher_clear, [c_void_p]) + ffi_api(dll.botan_block_cipher_set_key, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_block_cipher_block_size, [c_void_p]) + ffi_api(dll.botan_block_cipher_encrypt_blocks, [c_void_p, c_char_p, c_char_p, c_size_t]) + ffi_api(dll.botan_block_cipher_decrypt_blocks, [c_void_p, c_char_p, c_char_p, c_size_t]) + ffi_api(dll.botan_block_cipher_name, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_block_cipher_get_keyspec, [c_void_p, POINTER(c_size_t), POINTER(c_size_t), POINTER(c_size_t)]) + + # MP + ffi_api(dll.botan_mp_init, [c_void_p]) + ffi_api(dll.botan_mp_destroy, [c_void_p]) + ffi_api(dll.botan_mp_to_hex, [c_void_p, c_char_p]) + ffi_api(dll.botan_mp_to_str, [c_void_p, c_uint8, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_mp_clear, [c_void_p]) + ffi_api(dll.botan_mp_set_from_int, [c_void_p, c_int]) + ffi_api(dll.botan_mp_set_from_mp, [c_void_p, c_void_p]) + ffi_api(dll.botan_mp_set_from_str, [c_void_p, c_char_p]) + ffi_api(dll.botan_mp_set_from_radix_str, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_mp_num_bits, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_mp_num_bytes, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_mp_to_bin, [c_void_p, c_char_p]) + ffi_api(dll.botan_mp_from_bin, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_mp_to_uint32, [c_void_p, POINTER(c_uint32)]) + ffi_api(dll.botan_mp_is_positive, [c_void_p]) + ffi_api(dll.botan_mp_is_negative, [c_void_p]) + ffi_api(dll.botan_mp_flip_sign, [c_void_p]) + ffi_api(dll.botan_mp_is_zero, [c_void_p]) + ffi_api(dll.botan_mp_is_odd, [c_void_p]) + ffi_api(dll.botan_mp_is_even, [c_void_p]) + ffi_api(dll.botan_mp_add_u32, [c_void_p, c_void_p, c_uint32]) + ffi_api(dll.botan_mp_sub_u32, [c_void_p, c_void_p, c_uint32]) + ffi_api(dll.botan_mp_add, [c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_sub, [c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_mul, [c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_div, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_mod_mul, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_equal, [c_void_p, c_void_p]) + ffi_api(dll.botan_mp_cmp, [POINTER(c_int), c_void_p, c_void_p]) + ffi_api(dll.botan_mp_swap, [c_void_p, c_void_p]) + ffi_api(dll.botan_mp_powmod, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_lshift, [c_void_p, c_void_p, c_size_t]) + ffi_api(dll.botan_mp_rshift, [c_void_p, c_void_p, c_size_t]) + ffi_api(dll.botan_mp_mod_inverse, [c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_rand_bits, [c_void_p, c_void_p, c_size_t]) + ffi_api(dll.botan_mp_rand_range, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_gcd, [c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_mp_is_prime, [c_void_p, c_void_p, c_size_t]) + ffi_api(dll.botan_mp_get_bit, [c_void_p, c_size_t]) + ffi_api(dll.botan_mp_set_bit, [c_void_p, c_size_t]) + ffi_api(dll.botan_mp_clear_bit, [c_void_p, c_size_t]) + + ffi_api(dll.botan_bcrypt_generate, + [c_char_p, POINTER(c_size_t), c_char_p, c_void_p, c_size_t, c_uint32]) + ffi_api(dll.botan_bcrypt_is_valid, [c_char_p, c_char_p]) + + # PUBKEY + ffi_api(dll.botan_privkey_create, [c_void_p, c_char_p, c_char_p, c_void_p]) + ffi_api(dll.botan_privkey_check_key, [c_void_p, c_void_p, c_uint32], [-1]) + ffi_api(dll.botan_privkey_create_rsa, [c_void_p, c_void_p, c_size_t]) + ffi_api(dll.botan_privkey_create_ecdsa, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_create_ecdh, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_create_mceliece, [c_void_p, c_void_p, c_size_t, c_size_t]) + ffi_api(dll.botan_privkey_create_dh, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_create_dsa, [c_void_p, c_void_p, c_size_t, c_size_t]) + ffi_api(dll.botan_privkey_create_elgamal, [c_void_p, c_void_p, c_size_t, c_size_t]) + ffi_api(dll.botan_privkey_load, + [c_void_p, c_void_p, c_char_p, c_size_t, c_char_p]) + ffi_api(dll.botan_privkey_destroy, [c_void_p]) + ffi_api(dll.botan_privkey_export, [c_void_p, c_char_p, POINTER(c_size_t), c_uint32]) + ffi_api(dll.botan_privkey_algo_name, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_privkey_export_encrypted, + [c_void_p, c_char_p, POINTER(c_size_t), c_void_p, c_char_p, c_char_p, c_uint32]) + ffi_api(dll.botan_privkey_export_encrypted_pbkdf_msec, + [c_void_p, c_char_p, POINTER(c_size_t), c_void_p, c_char_p, c_uint32, POINTER(c_size_t), c_char_p, c_char_p, c_uint32]) + ffi_api(dll.botan_privkey_export_encrypted_pbkdf_iter, + [c_void_p, c_char_p, POINTER(c_size_t), c_void_p, c_char_p, c_size_t, c_char_p, c_char_p, c_uint32]) + ffi_api(dll.botan_privkey_export_pubkey, [c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_load, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_pubkey_export, [c_void_p, c_char_p, POINTER(c_size_t), c_uint32]) + ffi_api(dll.botan_pubkey_algo_name, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pubkey_check_key, [c_void_p, c_void_p, c_uint32], [-1]) + ffi_api(dll.botan_pubkey_estimated_strength, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pubkey_fingerprint, [c_void_p, c_char_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pubkey_destroy, [c_void_p]) + ffi_api(dll.botan_pubkey_get_field, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_get_field, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_load_rsa, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_load_rsa_pkcs1, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_privkey_rsa_get_p, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_rsa_get_q, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_rsa_get_d, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_rsa_get_n, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_rsa_get_e, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_rsa_get_privkey, [c_void_p, c_char_p, POINTER(c_size_t), c_uint32]) + ffi_api(dll.botan_pubkey_load_rsa, [c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_rsa_get_e, [c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_rsa_get_n, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_load_dsa, + [c_void_p, c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_load_dsa, + [c_void_p, c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_dsa_get_x, [c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_dsa_get_p, [c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_dsa_get_q, [c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_dsa_get_g, [c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_dsa_get_y, [c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_load_dh, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_load_dh, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_pubkey_load_elgamal, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_load_elgamal, [c_void_p, c_void_p, c_void_p, c_void_p]) + ffi_api(dll.botan_privkey_load_ed25519, [c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_load_ed25519, [c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_ed25519_get_privkey, [c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_ed25519_get_pubkey, [c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_load_x25519, [c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_load_x25519, [c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_x25519_get_privkey, [c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_x25519_get_pubkey, [c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_load_ecdsa, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_load_ecdsa, [c_void_p, c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_load_ecdh, [c_void_p, c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_load_ecdh, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_load_sm2, [c_void_p, c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_load_sm2, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_load_sm2_enc, [c_void_p, c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_privkey_load_sm2_enc, [c_void_p, c_void_p, c_char_p]) + ffi_api(dll.botan_pubkey_sm2_compute_za, + [c_char_p, POINTER(c_size_t), c_char_p, c_char_p, c_void_p]) + + # PK + ffi_api(dll.botan_pk_op_encrypt_create, [c_void_p, c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_pk_op_encrypt_destroy, [c_void_p]) + ffi_api(dll.botan_pk_op_encrypt_output_length, [c_void_p, c_size_t, POINTER(c_size_t)]) + ffi_api(dll.botan_pk_op_encrypt, + [c_void_p, c_void_p, c_char_p, POINTER(c_size_t), c_char_p, c_size_t]) + ffi_api(dll.botan_pk_op_decrypt_create, [c_void_p, c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_pk_op_decrypt_destroy, [c_void_p]) + ffi_api(dll.botan_pk_op_decrypt_output_length, [c_void_p, c_size_t, POINTER(c_size_t)]) + ffi_api(dll.botan_pk_op_decrypt, + [c_void_p, c_char_p, POINTER(c_size_t), c_char_p, c_size_t]) + ffi_api(dll.botan_pk_op_sign_create, [c_void_p, c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_pk_op_sign_destroy, [c_void_p]) + ffi_api(dll.botan_pk_op_sign_output_length, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pk_op_sign_update, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_pk_op_sign_finish, [c_void_p, c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pk_op_verify_create, [c_void_p, c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_pk_op_verify_destroy, [c_void_p]) + ffi_api(dll.botan_pk_op_verify_update, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_pk_op_verify_finish, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_pk_op_key_agreement_create, [c_void_p, c_void_p, c_char_p, c_uint32]) + ffi_api(dll.botan_pk_op_key_agreement_destroy, [c_void_p]) + ffi_api(dll.botan_pk_op_key_agreement_export_public, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pk_op_key_agreement_size, [c_void_p, POINTER(c_size_t)]) + ffi_api(dll.botan_pk_op_key_agreement, + [c_void_p, c_char_p, POINTER(c_size_t), c_char_p, c_size_t, c_char_p, c_size_t]) + + ffi_api(dll.botan_pkcs_hash_id, [c_char_p, c_char_p, POINTER(c_size_t)]) + + ffi_api(dll.botan_mceies_encrypt, + [c_void_p, c_void_p, c_char_p, c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_mceies_decrypt, + [c_void_p, c_char_p, c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + + # X509 + ffi_api(dll.botan_x509_cert_load, [c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_x509_cert_load_file, [c_void_p, c_char_p]) + ffi_api(dll.botan_x509_cert_destroy, [c_void_p]) + ffi_api(dll.botan_x509_cert_dup, [c_void_p, c_void_p]) + ffi_api(dll.botan_x509_cert_get_time_starts, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_time_expires, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_not_before, [c_void_p, POINTER(c_uint64)]) + ffi_api(dll.botan_x509_cert_not_after, [c_void_p, POINTER(c_uint64)]) + ffi_api(dll.botan_x509_cert_get_fingerprint, [c_void_p, c_char_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_serial_number, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_authority_key_id, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_subject_key_id, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_public_key_bits, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_public_key, [c_void_p, c_void_p]) + ffi_api(dll.botan_x509_cert_get_issuer_dn, + [c_void_p, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_get_subject_dn, + [c_void_p, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_to_string, [c_void_p, c_char_p, POINTER(c_size_t)]) + ffi_api(dll.botan_x509_cert_allowed_usage, [c_void_p, c_uint]) + ffi_api(dll.botan_x509_cert_hostname_match, [c_void_p, c_char_p], [-1]) + ffi_api(dll.botan_x509_cert_verify, + [POINTER(c_int), c_void_p, c_void_p, c_size_t, c_void_p, c_size_t, c_char_p, c_size_t, c_char_p, c_uint64]) + + 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, + [c_char_p, c_size_t, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)]) + + # HOTP + ffi_api(dll.botan_hotp_init, + [c_void_p, c_char_p, c_size_t, c_char_p, c_size_t]) + ffi_api(dll.botan_hotp_destroy, [c_void_p]) + ffi_api(dll.botan_hotp_generate, [c_void_p, POINTER(c_uint32), c_uint64]) + ffi_api(dll.botan_hotp_check, + [c_void_p, POINTER(c_uint64), c_uint32, c_uint64, c_size_t]) + + # TOTP + ffi_api(dll.botan_totp_init, + [c_void_p, c_char_p, c_size_t, c_char_p, c_size_t, c_size_t]) + ffi_api(dll.botan_totp_destroy, [c_void_p]) + ffi_api(dll.botan_totp_generate, [c_void_p, POINTER(c_uint32), c_uint64]) + ffi_api(dll.botan_totp_check, [c_void_p, c_uint32, c_uint64, c_size_t]) + + # FPE + ffi_api(dll.botan_fpe_fe1_init, + [c_void_p, c_void_p, c_char_p, c_size_t, c_size_t, c_uint32]) + ffi_api(dll.botan_fpe_destroy, [c_void_p]) + ffi_api(dll.botan_fpe_encrypt, [c_void_p, c_void_p, c_char_p, c_size_t]) + ffi_api(dll.botan_fpe_decrypt, [c_void_p, c_void_p, c_char_p, c_size_t]) + + return dll + +# +# Load the DLL and set prototypes on it +# +_DLL = _set_prototypes(_load_botan_dll(BOTAN_FFI_VERSION)) + +# +# Internal utilities +# +def _call_fn_returning_sz(fn): + sz = c_size_t(0) + fn(byref(sz)) + return int(sz.value) + +def _call_fn_returning_vec(guess, fn): + + buf = create_string_buffer(guess) + buf_len = c_size_t(len(buf)) + + rc = fn(buf, byref(buf_len)) + if rc == -10 and buf_len.value > len(buf): + return _call_fn_returning_vec(buf_len.value, fn) + + assert buf_len.value <= len(buf) + return buf.raw[0:int(buf_len.value)] + +def _call_fn_returning_str(guess, fn): + # Assumes that anything called with this is returning plain ASCII strings + # (base64 data, algorithm names, etc) + v = _call_fn_returning_vec(guess, fn) + return v.decode('ascii')[:-1] + +def _ctype_str(s): + if s is None: + return None + assert isinstance(s, str) + if version_info[0] < 3: + return s + else: + return s.encode('utf-8') + +def _ctype_to_str(s): + if version_info[0] < 3: + return s.encode('utf-8') + else: + return s.decode('utf-8') + +def _ctype_bits(s): + if version_info[0] < 3: + if isinstance(s, str): + return s + elif isinstance(s, unicode): # pylint: disable=undefined-variable + return s.decode('utf-8') + else: + raise Exception("Internal error - unexpected type %s provided to _ctype_bits" % (type(s).__name__)) + else: + if isinstance(s, bytes): + return s + elif isinstance(s, str): + return s.encode('utf-8') + else: + raise Exception("Internal error - unexpected type %s provided to _ctype_bits" % (type(s).__name__)) + +def _ctype_bufout(buf): + if version_info[0] < 3: + return str(buf.raw) + else: + return buf.raw + +def _hex_encode(buf): + return hexlify(buf).decode('ascii') + +# +# Versioning +# +def version_major(): + return int(_DLL.botan_version_major()) + +def version_minor(): + return int(_DLL.botan_version_minor()) + +def version_patch(): + return int(_DLL.botan_version_patch()) + +def ffi_api_version(): + return int(_DLL.botan_ffi_api_version()) + +def version_string(): + return _DLL.botan_version_string().decode('ascii') + +# +# Utilities +# +def const_time_compare(x, y): + len_x = len(x) + len_y = len(y) + if len_x != len_y: + return False + rc = _DLL.botan_constant_time_compare(_ctype_bits(x), _ctype_bits(y), c_size_t(len_x)) + return rc == 0 + +# +# RNG +# +class RandomNumberGenerator(object): + # Can also use type "system" + def __init__(self, rng_type='system'): + self.__obj = c_void_p(0) + _DLL.botan_rng_init(byref(self.__obj), _ctype_str(rng_type)) + + def __del__(self): + _DLL.botan_rng_destroy(self.__obj) + + def handle_(self): + return self.__obj + + def reseed(self, bits=256): + _DLL.botan_rng_reseed(self.__obj, bits) + + def reseed_from_rng(self, source_rng, bits=256): + _DLL.botan_rng_reseed_from_rng(self.__obj, source_rng.handle_(), bits) + + def add_entropy(self, seed): + _DLL.botan_rng_add_entropy(self.__obj, _ctype_bits(seed), len(seed)) + + def get(self, length): + out = create_string_buffer(length) + l = c_size_t(length) + _DLL.botan_rng_get(self.__obj, out, l) + return _ctype_bufout(out) + +# +# Block cipher +# +class BlockCipher(object): + def __init__(self, algo): + + if isinstance(algo, c_void_p): + self.__obj = algo + else: + flags = c_uint32(0) # always zero in this API version + self.__obj = c_void_p(0) + _DLL.botan_block_cipher_init(byref(self.__obj), _ctype_str(algo), flags) + + min_keylen = c_size_t(0) + max_keylen = c_size_t(0) + mod_keylen = c_size_t(0) + _DLL.botan_block_cipher_get_keyspec(self.__obj, byref(min_keylen), byref(max_keylen), byref(mod_keylen)) + + self.__min_keylen = min_keylen.value + self.__max_keylen = max_keylen.value + self.__mod_keylen = mod_keylen.value + + self.__block_size = _DLL.botan_block_cipher_block_size(self.__obj) + + def __del__(self): + _DLL.botan_block_cipher_destroy(self.__obj) + + def set_key(self, key): + _DLL.botan_block_cipher_set_key(self.__obj, key, len(key)) + + def encrypt(self, pt): + if len(pt) % self.block_size() != 0: + raise Exception("Invalid input must be multiple of block size") + + blocks = c_size_t(len(pt) // self.block_size()) + output = create_string_buffer(len(pt)) + _DLL.botan_block_cipher_encrypt_blocks(self.__obj, pt, output, blocks) + return output + + def decrypt(self, ct): + if len(ct) % self.block_size() != 0: + raise Exception("Invalid input must be multiple of block size") + + blocks = c_size_t(len(ct) // self.block_size()) + output = create_string_buffer(len(ct)) + _DLL.botan_block_cipher_decrypt_blocks(self.__obj, ct, output, blocks) + return output + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_block_cipher_name(self.__obj, b, bl)) + + def clear(self): + _DLL.botan_block_cipher_clear(self.__obj) + + def block_size(self): + return self.__block_size + + def minimum_keylength(self): + return self.__min_keylen + + def maximum_keylength(self): + return self.__max_keylen + + +# +# Hash function +# +class HashFunction(object): + def __init__(self, algo): + + if isinstance(algo, c_void_p): + self.__obj = algo + else: + flags = c_uint32(0) # always zero in this API version + self.__obj = c_void_p(0) + _DLL.botan_hash_init(byref(self.__obj), _ctype_str(algo), flags) + + self.__output_length = _call_fn_returning_sz(lambda l: _DLL.botan_hash_output_length(self.__obj, l)) + self.__block_size = _call_fn_returning_sz(lambda l: _DLL.botan_hash_block_size(self.__obj, l)) + + def __del__(self): + _DLL.botan_hash_destroy(self.__obj) + + def copy_state(self): + copy = c_void_p(0) + _DLL.botan_hash_copy_state(byref(copy), self.__obj) + return HashFunction(copy) + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_hash_name(self.__obj, b, bl)) + + def clear(self): + _DLL.botan_hash_clear(self.__obj) + + def output_length(self): + return self.__output_length + + def block_size(self): + return self.__block_size + + def update(self, x): + _DLL.botan_hash_update(self.__obj, _ctype_bits(x), len(x)) + + def final(self): + out = create_string_buffer(self.output_length()) + _DLL.botan_hash_final(self.__obj, out) + return _ctype_bufout(out) + +# +# Message authentication codes +# +class MsgAuthCode(object): + def __init__(self, algo): + flags = c_uint32(0) # always zero in this API version + self.__obj = c_void_p(0) + _DLL.botan_mac_init(byref(self.__obj), _ctype_str(algo), flags) + + min_keylen = c_size_t(0) + max_keylen = c_size_t(0) + mod_keylen = c_size_t(0) + _DLL.botan_mac_get_keyspec(self.__obj, byref(min_keylen), byref(max_keylen), byref(mod_keylen)) + + self.__min_keylen = min_keylen.value + self.__max_keylen = max_keylen.value + self.__mod_keylen = mod_keylen.value + + output_length = c_size_t(0) + _DLL.botan_mac_output_length(self.__obj, byref(output_length)) + self.__output_length = output_length.value + + def __del__(self): + _DLL.botan_mac_destroy(self.__obj) + + def clear(self): + _DLL.botan_mac_clear(self.__obj) + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_mac_name(self.__obj, b, bl)) + + def output_length(self): + return self.__output_length + + def minimum_keylength(self): + return self.__min_keylen + + def maximum_keylength(self): + return self.__max_keylen + + def set_key(self, key): + _DLL.botan_mac_set_key(self.__obj, key, len(key)) + + def update(self, x): + _DLL.botan_mac_update(self.__obj, x, len(x)) + + def final(self): + out = create_string_buffer(self.output_length()) + _DLL.botan_mac_final(self.__obj, out) + return _ctype_bufout(out) + +class SymmetricCipher(object): + def __init__(self, algo, encrypt=True): + flags = 0 if encrypt else 1 + self.__obj = c_void_p(0) + _DLL.botan_cipher_init(byref(self.__obj), _ctype_str(algo), flags) + + def __del__(self): + _DLL.botan_cipher_destroy(self.__obj) + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_cipher_name(self.__obj, b, bl)) + + def default_nonce_length(self): + l = c_size_t(0) + _DLL.botan_cipher_get_default_nonce_length(self.__obj, byref(l)) + return l.value + + def update_granularity(self): + l = c_size_t(0) + _DLL.botan_cipher_get_update_granularity(self.__obj, byref(l)) + return l.value + + def key_length(self): + kmin = c_size_t(0) + kmax = c_size_t(0) + _DLL.botan_cipher_query_keylen(self.__obj, byref(kmin), byref(kmax)) + return kmin.value, kmax.value + + def minimum_keylength(self): + l = c_size_t(0) + _DLL.botan_cipher_get_keyspec(self.__obj, byref(l), None, None) + return l.value + + def maximum_keylength(self): + l = c_size_t(0) + _DLL.botan_cipher_get_keyspec(self.__obj, None, byref(l), None) + return l.value + + def tag_length(self): + l = c_size_t(0) + _DLL.botan_cipher_get_tag_length(self.__obj, byref(l)) + return l.value + + def is_authenticated(self): + return self.tag_length() > 0 + + def valid_nonce_length(self, nonce_len): + rc = _DLL.botan_cipher_valid_nonce_length(self.__obj, nonce_len) + return rc == 1 + + def reset(self): + _DLL.botan_cipher_reset(self.__obj) + + def clear(self): + _DLL.botan_cipher_clear(self.__obj) + + def set_key(self, key): + _DLL.botan_cipher_set_key(self.__obj, key, len(key)) + + def set_assoc_data(self, ad): + _DLL.botan_cipher_set_associated_data(self.__obj, ad, len(ad)) + + def start(self, nonce): + _DLL.botan_cipher_start(self.__obj, nonce, len(nonce)) + + def _update(self, txt, final): + + inp = txt if txt else '' + inp_sz = c_size_t(len(inp)) + inp_consumed = c_size_t(0) + out = create_string_buffer(inp_sz.value + (self.tag_length() if final else 0)) + out_sz = c_size_t(len(out)) + out_written = c_size_t(0) + flags = c_uint32(1 if final else 0) + + _DLL.botan_cipher_update(self.__obj, flags, + out, out_sz, byref(out_written), + _ctype_bits(inp), inp_sz, byref(inp_consumed)) + + # buffering not supported yet + assert inp_consumed.value == inp_sz.value + return out.raw[0:int(out_written.value)] + + def update(self, txt): + return self._update(txt, False) + + def finish(self, txt=None): + return self._update(txt, True) + +def bcrypt(passwd, rng_obj, work_factor=10): + """ + Bcrypt password hashing + """ + out_len = c_size_t(64) + out = create_string_buffer(out_len.value) + flags = c_uint32(0) + _DLL.botan_bcrypt_generate(out, byref(out_len), _ctype_str(passwd), + rng_obj.handle_(), c_size_t(work_factor), flags) + b = out.raw[0:int(out_len.value)-1] + if b[-1] == '\x00': + b = b[:-1] + return _ctype_to_str(b) + +def check_bcrypt(passwd, passwd_hash): + rc = _DLL.botan_bcrypt_is_valid(_ctype_str(passwd), _ctype_str(passwd_hash)) + return rc == 0 + +# +# PBKDF +# +def pbkdf(algo, password, out_len, iterations=10000, salt=None): + if salt is None: + salt = RandomNumberGenerator().get(12) + + out_buf = create_string_buffer(out_len) + + _DLL.botan_pwdhash(_ctype_str(algo), iterations, 0, 0, + out_buf, out_len, + _ctype_str(password), len(password), + salt, len(salt)) + return (salt, iterations, out_buf.raw) + +def pbkdf_timed(algo, password, out_len, ms_to_run=300, salt=None): + if salt is None: + salt = RandomNumberGenerator().get(12) + + out_buf = create_string_buffer(out_len) + iterations = c_size_t(0) + + _DLL.botan_pwdhash_timed(_ctype_str(algo), c_uint32(ms_to_run), + byref(iterations), None, None, + out_buf, out_len, + _ctype_str(password), len(password), + salt, len(salt)) + return (salt, iterations.value, out_buf.raw) + +# +# Scrypt +# +def scrypt(out_len, password, salt, n=1024, r=8, p=8): + out_buf = create_string_buffer(out_len) + _DLL.botan_pwdhash(_ctype_str("Scrypt"), n, r, p, + out_buf, out_len, + _ctype_str(password), len(password), + _ctype_bits(salt), len(salt)) + + return out_buf.raw + +# +# KDF +# +def kdf(algo, secret, out_len, salt, label): + out_buf = create_string_buffer(out_len) + out_sz = c_size_t(out_len) + _DLL.botan_kdf(_ctype_str(algo), out_buf, out_sz, + secret, len(secret), + salt, len(salt), + label, len(label)) + return out_buf.raw[0:int(out_sz.value)] + +# +# Public key +# +class PublicKey(object): # pylint: disable=invalid-name + + def __init__(self, obj=c_void_p(0)): + self.__obj = obj + + @classmethod + def load(cls, val): + obj = c_void_p(0) + _DLL.botan_pubkey_load(byref(obj), _ctype_bits(val), len(val)) + return PublicKey(obj) + + @classmethod + def load_rsa(cls, n, e): + obj = c_void_p(0) + n = MPI(n) + e = MPI(e) + _DLL.botan_pubkey_load_rsa(byref(obj), n.handle_(), e.handle_()) + return PublicKey(obj) + + @classmethod + def load_dsa(cls, p, q, g, y): + obj = c_void_p(0) + p = MPI(p) + q = MPI(q) + g = MPI(g) + y = MPI(y) + _DLL.botan_pubkey_load_dsa(byref(obj), p.handle_(), q.handle_(), g.handle_(), y.handle_()) + return PublicKey(obj) + + @classmethod + def load_dh(cls, p, g, y): + obj = c_void_p(0) + p = MPI(p) + g = MPI(g) + y = MPI(y) + _DLL.botan_pubkey_load_dh(byref(obj), p.handle_(), g.handle_(), y.handle_()) + return PublicKey(obj) + + @classmethod + def load_elgamal(cls, p, q, g, y): + obj = c_void_p(0) + p = MPI(p) + q = MPI(q) + g = MPI(g) + y = MPI(y) + _DLL.botan_pubkey_load_elgamal(byref(obj), p.handle_(), q.handle_(), g.handle_(), y.handle_()) + return PublicKey(obj) + + @classmethod + def load_ecdsa(cls, curve, pub_x, pub_y): + obj = c_void_p(0) + pub_x = MPI(pub_x) + pub_y = MPI(pub_y) + _DLL.botan_pubkey_load_ecdsa(byref(obj), pub_x.handle_(), pub_y.handle_(), _ctype_str(curve)) + return PublicKey(obj) + + @classmethod + def load_ecdh(cls, curve, pub_x, pub_y): + obj = c_void_p(0) + pub_x = MPI(pub_x) + pub_y = MPI(pub_y) + _DLL.botan_pubkey_load_ecdh(byref(obj), pub_x.handle_(), pub_y.handle_(), _ctype_str(curve)) + return PublicKey(obj) + + @classmethod + def load_sm2(cls, curve, pub_x, pub_y): + obj = c_void_p(0) + pub_x = MPI(pub_x) + pub_y = MPI(pub_y) + _DLL.botan_pubkey_load_sm2(byref(obj), pub_x.handle_(), pub_y.handle_(), _ctype_str(curve)) + return PublicKey(obj) + + def __del__(self): + _DLL.botan_pubkey_destroy(self.__obj) + + def handle_(self): + return self.__obj + + def check_key(self, rng_obj, strong=True): + flags = 1 if strong else 0 + rc = _DLL.botan_pubkey_check_key(self.__obj, rng_obj.handle_(), flags) + return rc == 0 + + def estimated_strength(self): + r = c_size_t(0) + _DLL.botan_pubkey_estimated_strength(self.__obj, byref(r)) + return r.value + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_pubkey_algo_name(self.__obj, b, bl)) + + def export(self, pem=False): + if pem: + return _call_fn_returning_str(4096, lambda b, bl: _DLL.botan_pubkey_export(self.__obj, b, bl, 1)) + else: + return _call_fn_returning_vec(4096, lambda b, bl: _DLL.botan_pubkey_export(self.__obj, b, bl, 0)) + + def encoding(self, pem=False): + return self.export(pem) + + def to_der(self): + return self.export(False) + + def to_pem(self): + return self.export(True) + + def fingerprint(self, hash_algorithm='SHA-256'): + n = HashFunction(hash_algorithm).output_length() + buf = create_string_buffer(n) + buf_len = c_size_t(n) + + _DLL.botan_pubkey_fingerprint(self.__obj, _ctype_str(hash_algorithm), buf, byref(buf_len)) + return _hex_encode(buf[0:int(buf_len.value)]) + + def get_field(self, field_name): + v = MPI() + _DLL.botan_pubkey_get_field(v.handle_(), self.__obj, _ctype_str(field_name)) + return int(v) + +# +# Private Key +# +class PrivateKey(object): + + def __init__(self, obj=c_void_p(0)): + self.__obj = obj + + @classmethod + def load(cls, val, passphrase=""): + obj = c_void_p(0) + rng_obj = c_void_p(0) # unused in recent versions + _DLL.botan_privkey_load(byref(obj), rng_obj, _ctype_bits(val), len(val), _ctype_str(passphrase)) + return PrivateKey(obj) + + @classmethod + def create(cls, algo, params, rng_obj): + if algo == 'rsa': + algo = 'RSA' + params = "%d" % (params) + elif algo == 'ecdsa': + algo = 'ECDSA' + elif algo in ['ecdh', 'ECDH']: + if params == 'curve25519': + algo = 'Curve25519' + params = '' + else: + algo = 'ECDH' + elif algo in ['mce', 'mceliece']: + algo = 'McEliece' + params = "%d,%d" % (params[0], params[1]) + + obj = c_void_p(0) + _DLL.botan_privkey_create(byref(obj), _ctype_str(algo), _ctype_str(params), rng_obj.handle_()) + return PrivateKey(obj) + + @classmethod + def load_rsa(cls, p, q, e): + obj = c_void_p(0) + p = MPI(p) + q = MPI(q) + e = MPI(e) + _DLL.botan_privkey_load_rsa(byref(obj), p.handle_(), q.handle_(), e.handle_()) + return PrivateKey(obj) + + @classmethod + def load_dsa(cls, p, q, g, x): + obj = c_void_p(0) + p = MPI(p) + q = MPI(q) + g = MPI(g) + x = MPI(x) + _DLL.botan_privkey_load_dsa(byref(obj), p.handle_(), q.handle_(), g.handle_(), x.handle_()) + return PrivateKey(obj) + + @classmethod + def load_dh(cls, p, g, x): + obj = c_void_p(0) + p = MPI(p) + g = MPI(g) + x = MPI(x) + _DLL.botan_privkey_load_dh(byref(obj), p.handle_(), g.handle_(), x.handle_()) + return PrivateKey(obj) + + @classmethod + def load_elgamal(cls, p, q, g, x): + obj = c_void_p(0) + p = MPI(p) + q = MPI(q) + g = MPI(g) + x = MPI(x) + _DLL.botan_privkey_load_elgamal(byref(obj), p.handle_(), q.handle_(), g.handle_(), x.handle_()) + return PrivateKey(obj) + + @classmethod + def load_ecdsa(cls, curve, x): + obj = c_void_p(0) + x = MPI(x) + _DLL.botan_privkey_load_ecdsa(byref(obj), x.handle_(), _ctype_str(curve)) + return PrivateKey(obj) + + @classmethod + def load_ecdh(cls, curve, x): + obj = c_void_p(0) + x = MPI(x) + _DLL.botan_privkey_load_ecdh(byref(obj), x.handle_(), _ctype_str(curve)) + return PrivateKey(obj) + + @classmethod + def load_sm2(cls, curve, x): + obj = c_void_p(0) + x = MPI(x) + _DLL.botan_privkey_load_sm2(byref(obj), x.handle_(), _ctype_str(curve)) + return PrivateKey(obj) + + def __del__(self): + _DLL.botan_privkey_destroy(self.__obj) + + def handle_(self): + return self.__obj + + def check_key(self, rng_obj, strong=True): + flags = 1 if strong else 0 + rc = _DLL.botan_privkey_check_key(self.__obj, rng_obj.handle_(), flags) + return rc == 0 + + def algo_name(self): + return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_privkey_algo_name(self.__obj, b, bl)) + + def get_public_key(self): + pub = c_void_p(0) + _DLL.botan_privkey_export_pubkey(byref(pub), self.__obj) + return PublicKey(pub) + + def to_der(self): + return self.export(False) + + def to_pem(self): + return self.export(True) + + def export(self, pem=False): + if pem: + return _call_fn_returning_str(4096, lambda b, bl: _DLL.botan_privkey_export(self.__obj, b, bl, 1)) + else: + return _call_fn_returning_vec(4096, lambda b, bl: _DLL.botan_privkey_export(self.__obj, b, bl, 0)) + + def export_encrypted(self, passphrase, rng_obj, pem=False, msec=300, cipher=None, pbkdf=None): # pylint: disable=redefined-outer-name + flags = 1 if pem else 0 + msec = c_uint32(msec) + _iters = c_size_t(0) + + cb = lambda b, bl: _DLL.botan_privkey_export_encrypted_pbkdf_msec( + self.__obj, b, bl, rng_obj.handle_(), _ctype_str(passphrase), + msec, byref(_iters), _ctype_str(cipher), _ctype_str(pbkdf), flags) + + if pem: + return _call_fn_returning_str(8192, cb) + else: + return _call_fn_returning_vec(4096, cb) + + def get_field(self, field_name): + v = MPI() + _DLL.botan_privkey_get_field(v.handle_(), self.__obj, _ctype_str(field_name)) + return int(v) + +class PKEncrypt(object): + def __init__(self, key, padding): + self.__obj = c_void_p(0) + flags = c_uint32(0) # always zero in this ABI + _DLL.botan_pk_op_encrypt_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags) + + def __del__(self): + _DLL.botan_pk_op_encrypt_destroy(self.__obj) + + def encrypt(self, msg, rng_obj): + outbuf_sz = c_size_t(0) + _DLL.botan_pk_op_encrypt_output_length(self.__obj, len(msg), byref(outbuf_sz)) + outbuf = create_string_buffer(outbuf_sz.value) + _DLL.botan_pk_op_encrypt(self.__obj, rng_obj.handle_(), outbuf, byref(outbuf_sz), msg, len(msg)) + return outbuf.raw[0:int(outbuf_sz.value)] + + +class PKDecrypt(object): + def __init__(self, key, padding): + self.__obj = c_void_p(0) + flags = c_uint32(0) # always zero in this ABI + _DLL.botan_pk_op_decrypt_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags) + + def __del__(self): + _DLL.botan_pk_op_decrypt_destroy(self.__obj) + + def decrypt(self, msg): + outbuf_sz = c_size_t(0) + _DLL.botan_pk_op_decrypt_output_length(self.__obj, len(msg), byref(outbuf_sz)) + outbuf = create_string_buffer(outbuf_sz.value) + _DLL.botan_pk_op_decrypt(self.__obj, outbuf, byref(outbuf_sz), _ctype_bits(msg), len(msg)) + return outbuf.raw[0:int(outbuf_sz.value)] + +class PKSign(object): # pylint: disable=invalid-name + def __init__(self, key, padding, der=False): + self.__obj = c_void_p(0) + flags = c_uint32(1) if der else c_uint32(0) + _DLL.botan_pk_op_sign_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags) + + def __del__(self): + _DLL.botan_pk_op_sign_destroy(self.__obj) + + def update(self, msg): + _DLL.botan_pk_op_sign_update(self.__obj, _ctype_str(msg), len(msg)) + + def finish(self, rng_obj): + outbuf_sz = c_size_t(0) + _DLL.botan_pk_op_sign_output_length(self.__obj, byref(outbuf_sz)) + outbuf = create_string_buffer(outbuf_sz.value) + _DLL.botan_pk_op_sign_finish(self.__obj, rng_obj.handle_(), outbuf, byref(outbuf_sz)) + return outbuf.raw[0:int(outbuf_sz.value)] + +class PKVerify(object): + def __init__(self, key, padding, der=False): + self.__obj = c_void_p(0) + flags = c_uint32(1) if der else c_uint32(0) + _DLL.botan_pk_op_verify_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags) + + def __del__(self): + _DLL.botan_pk_op_verify_destroy(self.__obj) + + def update(self, msg): + _DLL.botan_pk_op_verify_update(self.__obj, _ctype_bits(msg), len(msg)) + + def check_signature(self, signature): + rc = _DLL.botan_pk_op_verify_finish(self.__obj, _ctype_bits(signature), len(signature)) + if rc == 0: + return True + return False + +class PKKeyAgreement(object): + def __init__(self, key, kdf_name): + self.__obj = c_void_p(0) + flags = c_uint32(0) # always zero in this ABI + _DLL.botan_pk_op_key_agreement_create(byref(self.__obj), key.handle_(), _ctype_str(kdf_name), flags) + + self.m_public_value = _call_fn_returning_vec( + 0, lambda b, bl: _DLL.botan_pk_op_key_agreement_export_public(key.handle_(), b, bl)) + + def __del__(self): + _DLL.botan_pk_op_key_agreement_destroy(self.__obj) + + def public_value(self): + return self.m_public_value + + def underlying_output_length(self): + out_len = c_size_t(0) + _DLL.botan_pk_op_key_agreement_size(self.__obj, byref(out_len)) + return out_len.value + + def agree(self, other, key_len, salt): + if key_len == 0: + key_len = self.underlying_output_length() + return _call_fn_returning_vec(key_len, lambda b, bl: + _DLL.botan_pk_op_key_agreement(self.__obj, b, bl, + other, len(other), + salt, len(salt))) + +# +# MCEIES encryption +# Must be used with McEliece keys +# +def mceies_encrypt(mce, rng_obj, aead, pt, ad): + return _call_fn_returning_vec(len(pt) + 1024, lambda b, bl: + _DLL.botan_mceies_encrypt(mce.handle_(), + rng_obj.handle_(), + _ctype_str(aead), + _ctype_bits(pt), + len(pt), + _ctype_bits(ad), + len(ad), + b, bl)) + +def mceies_decrypt(mce, aead, ct, ad): + + #msg = cast(msg, c_char_p) + #ll = c_size_t(ll) + + return _call_fn_returning_vec(len(ct), lambda b, bl: + _DLL.botan_mceies_decrypt(mce.handle_(), + _ctype_str(aead), + _ctype_bits(ct), + len(ct), + _ctype_bits(ad), + len(ad), + b, bl)) + + +def _load_buf_or_file(filename, buf, file_fn, buf_fn): + 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") + + obj = c_void_p(0) + + if filename is not None: + file_fn(byref(obj), _ctype_str(filename)) + elif buf is not None: + buf_fn(byref(obj), _ctype_bits(buf), len(buf)) + + return obj + + +# +# X.509 certificates +# +class X509Cert(object): # pylint: disable=invalid-name + def __init__(self, filename=None, buf=None): + self.__obj = _load_buf_or_file(filename, buf, _DLL.botan_x509_cert_load_file, _DLL.botan_x509_cert_load) + + def __del__(self): + _DLL.botan_x509_cert_destroy(self.__obj) + + def time_starts(self): + starts = _call_fn_returning_str( + 16, lambda b, bl: _DLL.botan_x509_cert_get_time_starts(self.__obj, b, bl)) + if len(starts) == 13: + # UTC time + struct_time = strptime(starts, "%y%m%d%H%M%SZ") + elif len(starts) == 15: + # Generalized time + struct_time = strptime(starts, "%Y%m%d%H%M%SZ") + else: + raise BotanException("Unexpected date/time format for x509 start time") + + return datetime.fromtimestamp(mktime(struct_time)) + + def time_expires(self): + expires = _call_fn_returning_str( + 16, lambda b, bl: _DLL.botan_x509_cert_get_time_expires(self.__obj, b, bl)) + if len(expires) == 13: + # UTC time + struct_time = strptime(expires, "%y%m%d%H%M%SZ") + elif len(expires) == 15: + # Generalized time + struct_time = strptime(expires, "%Y%m%d%H%M%SZ") + else: + raise BotanException("Unexpected date/time format for x509 expire time") + + return datetime.fromtimestamp(mktime(struct_time)) + + def to_string(self): + return _call_fn_returning_str( + 4096, lambda b, bl: _DLL.botan_x509_cert_to_string(self.__obj, b, bl)) + + def fingerprint(self, hash_algo='SHA-256'): + n = HashFunction(hash_algo).output_length() * 3 + return _call_fn_returning_str( + n, lambda b, bl: _DLL.botan_x509_cert_get_fingerprint(self.__obj, _ctype_str(hash_algo), b, bl)) + + def serial_number(self): + return _call_fn_returning_vec( + 32, lambda b, bl: _DLL.botan_x509_cert_get_serial_number(self.__obj, b, bl)) + + def authority_key_id(self): + return _call_fn_returning_vec( + 32, lambda b, bl: _DLL.botan_x509_cert_get_authority_key_id(self.__obj, b, bl)) + + def subject_key_id(self): + return _call_fn_returning_vec( + 32, lambda b, bl: _DLL.botan_x509_cert_get_subject_key_id(self.__obj, b, bl)) + + def subject_public_key_bits(self): + return _call_fn_returning_vec( + 512, lambda b, bl: _DLL.botan_x509_cert_get_public_key_bits(self.__obj, b, bl)) + + def subject_public_key(self): + pub = c_void_p(0) + _DLL.botan_x509_cert_get_public_key(self.__obj, byref(pub)) + return PublicKey(pub) + + def subject_dn(self, key, index): + return _call_fn_returning_str( + 0, lambda b, bl: _DLL.botan_x509_cert_get_subject_dn(self.__obj, _ctype_str(key), index, b, bl)) + + def issuer_dn(self, key, index): + return _call_fn_returning_str( + 0, lambda b, bl: _DLL.botan_x509_cert_get_issuer_dn(self.__obj, _ctype_str(key), index, b, bl)) + + def hostname_match(self, hostname): + rc = _DLL.botan_x509_cert_hostname_match(self.__obj, _ctype_str(hostname)) + return rc == 0 + + def not_before(self): + time = c_uint64(0) + _DLL.botan_x509_cert_not_before(self.__obj, byref(time)) + return time.value + + def not_after(self): + time = c_uint64(0) + _DLL.botan_x509_cert_not_after(self.__obj, byref(time)) + return time.value + + def allowed_usage(self, usage_list): + usage_values = {"NO_CONSTRAINTS": 0, + "DIGITAL_SIGNATURE": 32768, + "NON_REPUDIATION": 16384, + "KEY_ENCIPHERMENT": 8192, + "DATA_ENCIPHERMENT": 4096, + "KEY_AGREEMENT": 2048, + "KEY_CERT_SIGN": 1024, + "CRL_SIGN": 512, + "ENCIPHER_ONLY": 256, + "DECIPHER_ONLY": 128} + usage = 0 + for u in usage_list: + if u not in usage_values: + return False + usage += usage_values[u] + + rc = _DLL.botan_x509_cert_allowed_usage(self.__obj, c_uint(usage)) + return rc == 0 + + def handle_(self): + return self.__obj + + def verify(self, + intermediates=None, + trusted=None, + trusted_path=None, + required_strength=0, + hostname=None, + reference_time=0, + crls=None): + #pylint: disable=too-many-locals + + 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_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): + self.__obj = _load_buf_or_file(filename, buf, _DLL.botan_x509_crl_load_file, _DLL.botan_x509_crl_load) + + 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): + + self.__obj = c_void_p(0) + _DLL.botan_mp_init(byref(self.__obj)) + + if initial_value is None: + pass # left as zero + elif isinstance(initial_value, MPI): + _DLL.botan_mp_set_from_mp(self.__obj, initial_value.handle_()) + elif radix is not None: + _DLL.botan_mp_set_from_radix_str(self.__obj, _ctype_str(initial_value), c_size_t(radix)) + elif isinstance(initial_value, str): + _DLL.botan_mp_set_from_str(self.__obj, _ctype_str(initial_value)) + else: + # For int or long (or whatever else), try converting to string: + _DLL.botan_mp_set_from_str(self.__obj, _ctype_str(str(initial_value))) + + @classmethod + def random(cls, rng_obj, bits): + bn = MPI() + _DLL.botan_mp_rand_bits(bn.handle_(), rng_obj.handle_(), c_size_t(bits)) + return bn + + @classmethod + def random_range(cls, rng_obj, lower, upper): + bn = MPI() + _DLL.botan_mp_rand_range(bn.handle_(), rng_obj.handle_(), lower.handle_(), upper.handle_()) + return bn + + def __del__(self): + _DLL.botan_mp_destroy(self.__obj) + + def handle_(self): + return self.__obj + + def __int__(self): + out = create_string_buffer(2*self.byte_count() + 1) + _DLL.botan_mp_to_hex(self.__obj, out) + val = int(out.value, 16) + if self.is_negative(): + return -val + else: + return val + + def __repr__(self): + # Should have a better size estimate than this ... + out_len = c_size_t(self.bit_count() // 2) + out = create_string_buffer(out_len.value) + + _DLL.botan_mp_to_str(self.__obj, c_uint8(10), out, byref(out_len)) + + out = out.raw[0:int(out_len.value)] + if out[-1] == '\x00': + out = out[:-1] + s = _ctype_to_str(out) + if s[0] == '0': + return s[1:] + else: + return s + + def to_bytes(self): + byte_count = self.byte_count() + out_len = c_size_t(byte_count) + out = create_string_buffer(out_len.value) + _DLL.botan_mp_to_bin(self.__obj, out, byref(out_len)) + assert out_len.value == byte_count + return out + + def is_negative(self): + rc = _DLL.botan_mp_is_negative(self.__obj) + return rc == 1 + + def is_positive(self): + rc = _DLL.botan_mp_is_positive(self.__obj) + return rc == 1 + + def is_zero(self): + rc = _DLL.botan_mp_is_zero(self.__obj) + return rc == 1 + + def is_odd(self): + return self.get_bit(0) == 1 + + def is_even(self): + return self.get_bit(0) == 0 + + def flip_sign(self): + _DLL.botan_mp_flip_sign(self.__obj) + + def cmp(self, other): + r = c_int(0) + _DLL.botan_mp_cmp(byref(r), self.__obj, other.handle_()) + return r.value + + def __hash__(self): + return hash(self.to_bytes()) + + def __eq__(self, other): + return self.cmp(other) == 0 + + def __ne__(self, other): + return self.cmp(other) != 0 + + def __lt__(self, other): + return self.cmp(other) < 0 + + def __le__(self, other): + return self.cmp(other) <= 0 + + def __gt__(self, other): + return self.cmp(other) > 0 + + def __ge__(self, other): + return self.cmp(other) >= 0 + + def __add__(self, other): + r = MPI() + _DLL.botan_mp_add(r.handle_(), self.__obj, other.handle_()) + return r + + def __iadd__(self, other): + _DLL.botan_mp_add(self.__obj, self.__obj, other.handle_()) + return self + + def __sub__(self, other): + r = MPI() + _DLL.botan_mp_sub(r.handle_(), self.__obj, other.handle_()) + return r + + def __isub__(self, other): + _DLL.botan_mp_sub(self.__obj, self.__obj, other.handle_()) + return self + + def __mul__(self, other): + r = MPI() + _DLL.botan_mp_mul(r.handle_(), self.__obj, other.handle_()) + return r + + def __imul__(self, other): + _DLL.botan_mp_mul(self.__obj, self.__obj, other.handle_()) + return self + + def __divmod__(self, other): + d = MPI() + q = MPI() + _DLL.botan_mp_div(d.handle_(), q.handle_(), self.__obj, other.handle_()) + return (d, q) + + def __mod__(self, other): + d = MPI() + q = MPI() + _DLL.botan_mp_div(d.handle_(), q.handle_(), self.__obj, other.handle_()) + return q + + def __lshift__(self, shift): + shift = c_size_t(shift) + r = MPI() + _DLL.botan_mp_lshift(r.handle_(), self.__obj, shift) + return r + + def __ilshift__(self, shift): + shift = c_size_t(shift) + _DLL.botan_mp_lshift(self.__obj, self.__obj, shift) + return self + + def __rshift__(self, shift): + shift = c_size_t(shift) + r = MPI() + _DLL.botan_mp_rshift(r.handle_(), self.__obj, shift) + return r + + def __irshift__(self, shift): + shift = c_size_t(shift) + _DLL.botan_mp_rshift(self.__obj, self.__obj, shift) + return self + + def mod_mul(self, other, modulus): + r = MPI() + _DLL.botan_mp_mod_mul(r.handle_(), self.__obj, other.handle_(), modulus.handle_()) + return r + + def gcd(self, other): + r = MPI() + _DLL.botan_mp_gcd(r.handle_(), self.__obj, other.handle_()) + return r + + def pow_mod(self, exponent, modulus): + r = MPI() + _DLL.botan_mp_powmod(r.handle_(), self.__obj, exponent.handle_(), modulus.handle_()) + return r + + def is_prime(self, rng_obj, prob=128): + return _DLL.botan_mp_is_prime(self.__obj, rng_obj.handle_(), c_size_t(prob)) == 1 + + def inverse_mod(self, modulus): + r = MPI() + _DLL.botan_mp_mod_inverse(r.handle_(), self.__obj, modulus.handle_()) + return r + + def bit_count(self): + b = c_size_t(0) + _DLL.botan_mp_num_bits(self.__obj, byref(b)) + return b.value + + def byte_count(self): + b = c_size_t(0) + _DLL.botan_mp_num_bytes(self.__obj, byref(b)) + return b.value + + def get_bit(self, bit): + return _DLL.botan_mp_get_bit(self.__obj, c_size_t(bit)) == 1 + + def clear_bit(self, bit): + _DLL.botan_mp_clear_bit(self.__obj, c_size_t(bit)) + + def set_bit(self, bit): + _DLL.botan_mp_set_bit(self.__obj, c_size_t(bit)) + +class FormatPreservingEncryptionFE1(object): + + def __init__(self, modulus, key, rounds=5, compat_mode=False): + flags = c_uint32(1 if compat_mode else 0) + self.__obj = c_void_p(0) + _DLL.botan_fpe_fe1_init(byref(self.__obj), modulus.handle_(), key, len(key), c_size_t(rounds), flags) + + def __del__(self): + _DLL.botan_fpe_destroy(self.__obj) + + def encrypt(self, msg, tweak): + r = MPI(msg) + _DLL.botan_fpe_encrypt(self.__obj, r.handle_(), _ctype_bits(tweak), len(tweak)) + return r + + def decrypt(self, msg, tweak): + r = MPI(msg) + _DLL.botan_fpe_decrypt(self.__obj, r.handle_(), _ctype_bits(tweak), len(tweak)) + return r + +class HOTP(object): + def __init__(self, key, digest="SHA-1", digits=6): + self.__obj = c_void_p(0) + _DLL.botan_hotp_init(byref(self.__obj), key, len(key), _ctype_str(digest), digits) + + def __del__(self): + _DLL.botan_hotp_destroy(self.__obj) + + def generate(self, counter): + code = c_uint32(0) + _DLL.botan_hotp_generate(self.__obj, byref(code), counter) + return code.value + + def check(self, code, counter, resync_range=0): + next_ctr = c_uint64(0) + rc = _DLL.botan_hotp_check(self.__obj, byref(next_ctr), code, counter, resync_range) + if rc == 0: + return (True, next_ctr.value) + else: + return (False, counter) + +class TOTP(object): + def __init__(self, key, digest="SHA-1", digits=6, timestep=30): + self.__obj = c_void_p(0) + _DLL.botan_totp_init(byref(self.__obj), key, len(key), _ctype_str(digest), digits, timestep) + + def __del__(self): + _DLL.botan_totp_destroy(self.__obj) + + def generate(self, timestamp=None): + if timestamp is None: + timestamp = int(system_time()) + code = c_uint32(0) + _DLL.botan_totp_generate(self.__obj, byref(code), timestamp) + return code.value + + def check(self, code, timestamp=None, acceptable_drift=0): + if timestamp is None: + timestamp = int(system_time()) + rc = _DLL.botan_totp_check(self.__obj, code, timestamp, acceptable_drift) + if rc == 0: + return True + return False + +def nist_key_wrap(kek, key): + output = create_string_buffer(len(key) + 8) + out_len = c_size_t(len(output)) + _DLL.botan_key_wrap3394(key, len(key), kek, len(kek), output, byref(out_len)) + return output[0:int(out_len.value)] + +def nist_key_unwrap(kek, wrapped): + output = create_string_buffer(len(wrapped)) + out_len = c_size_t(len(output)) + _DLL.botan_key_unwrap3394(wrapped, len(wrapped), kek, len(kek), output, byref(out_len)) + return output[0:int(out_len.value)] + +# Typedefs for compat with older versions +# Will be removed in a future major release +cipher = SymmetricCipher # pylint: disable=invalid-name +rng = RandomNumberGenerator # pylint: disable=invalid-name +hash_function = HashFunction # pylint: disable=invalid-name +message_authentication_code = MsgAuthCode # pylint: disable=invalid-name + +x509_cert = X509Cert # pylint: disable=invalid-name +public_key = PublicKey # pylint: disable=invalid-name +private_key = PrivateKey # pylint: disable=invalid-name + +pk_op_encrypt = PKEncrypt # pylint: disable=invalid-name +pk_op_decrypt = PKDecrypt # pylint: disable=invalid-name +pk_op_sign = PKSign # pylint: disable=invalid-name +pk_op_verify = PKVerify # pylint: disable=invalid-name +pk_op_key_agreement = PKKeyAgreement # pylint: disable=invalid-name |