Repository: randombit/botan
Pull request #1904 (2019-04-19 09:47:45)

Some cleanups in Python wrapper
No functional changes


Patch:
diff --git a/doc/manual/deprecated.rst b/doc/manual/deprecated.rst
index 97168d9f0..cefdec7a1 100644
--- a/doc/manual/deprecated.rst
+++ b/doc/manual/deprecated.rst
@@ -10,11 +10,13 @@ This is in addition to specific API calls marked with BOTAN_DEPRECATED
 in the source.
 
 - Configuring a build (with ``configure.py``) using Python2. In a future
-  major release, Python3 will be required. This will not affect the Python
-  module, which will continue to support Python2 for the forseeable future.
+  major release, Python3 will be required.
+
+- Using the Python wrapper with Python2.
 
 - Directly using an algorithm class like ``AES_128`` or ``SHA_256``. Instead
-  create the objects via a ``T::create`` call.
+  create the objects via a ``T::create`` call. A future major release may
+  make such declarations private.
 
 - Directly accessing the member variables of types calendar_point, ASN1_Attribute,
   AlgorithmIdentifier, and BER_Object
diff --git a/src/python/botan2.py b/src/python/botan2.py
index 243b5a466..8cce09ef3 100755
--- a/src/python/botan2.py
+++ b/src/python/botan2.py
@@ -4,7 +4,7 @@
 Python wrapper of the botan crypto library
 https://botan.randombit.net
 
-(C) 2015,2017,2018 Jack Lloyd
+(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)
@@ -19,7 +19,7 @@ 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_char, c_char_p
+    c_void_p, c_size_t, c_uint8, c_uint32, c_uint64, c_int, c_char_p
 
 from sys import version_info
 from time import strptime, mktime
@@ -40,7 +40,7 @@ class BotanException(Exception):
         if rc == 0:
             super(BotanException, self).__init__(message)
         else:
-            descr = botan.botan_error_description(rc).decode('ascii')
+            descr = _DLL.botan_error_description(rc).decode('ascii')
             super(BotanException, self).__init__("%s: %d (%s)" % (message, rc, descr))
 
     def error_code(self):
@@ -50,10 +50,10 @@ class BotanException(Exception):
 # Module initialization
 #
 
-def load_botan_dll(expected_version):
+def _load_botan_dll(expected_version):
 
     possible_dll_names = ['libbotan-2.dylib', 'libbotan-2.so'] + \
-                         ['libbotan-2.so.%d' % (v) for v in reversed(range(8, 16))]
+        ['libbotan-2.so.%d' % (v) for v in reversed(range(8, 16))]
 
     for dll_name in possible_dll_names:
         try:
@@ -65,247 +65,246 @@ def load_botan_dll(expected_version):
         except OSError:
             pass
 
-    return None
-
-botan = load_botan_dll(BOTAN_FFI_VERSION) # pylint: disable=invalid-name
-
-if botan is None:
     raise BotanException("Could not find a usable Botan shared object library")
 
-#
-# ctypes function prototypes
-#
-def errcheck_for(fn_name):
-    def errcheck(rc, _func, _args):
-        # No idea what to do if return value isn't an int, just return it
-        if not isinstance(rc, int):
-            return rc
-
-        if rc >= 0:
-            return rc
-        if rc == -10: # insufficient buffer space, pass up to caller
-            return rc
-        raise BotanException('%s failed' % (fn_name), rc)
-    return errcheck
-
-def _botan_ffi_api(fn, args):
-    fn.argtypes = args
-    fn.errcheck = errcheck_for(fn.__name__)
-
-botan.botan_version_string.argtypes = []
-botan.botan_version_string.restype = c_char_p
-
-botan.botan_error_description.argtypes = [c_int]
-botan.botan_error_description.restype = c_char_p
-
-# RNG
-_botan_ffi_api(botan.botan_rng_init, [c_void_p, c_char_p])
-_botan_ffi_api(botan.botan_rng_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_rng_reseed, [c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_rng_reseed_from_rng, [c_void_p, c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_rng_add_entropy, [c_void_p, c_char_p, c_size_t])
-_botan_ffi_api(botan.botan_rng_get, [c_void_p, POINTER(c_char), c_size_t])
-
-# Hash function
-_botan_ffi_api(botan.botan_hash_init, [c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_hash_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_hash_name, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_hash_clear, [c_void_p])
-_botan_ffi_api(botan.botan_hash_output_length, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_hash_update, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_hash_final, [c_void_p, POINTER(c_char)])
-
-# MAC
-_botan_ffi_api(botan.botan_mac_init, [c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_mac_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_mac_name, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_mac_clear, [c_void_p])
-_botan_ffi_api(botan.botan_mac_output_length, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_mac_set_key, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_mac_update, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_mac_final, [c_void_p, POINTER(c_char)])
-
-# Cipher
-_botan_ffi_api(botan.botan_cipher_init, [c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_cipher_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_cipher_reset, [c_void_p])
-_botan_ffi_api(botan.botan_cipher_name, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_cipher_get_default_nonce_length, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_cipher_get_update_granularity, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_cipher_get_tag_length, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_cipher_valid_nonce_length, [c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_cipher_clear, [c_void_p])
-_botan_ffi_api(botan.botan_cipher_set_key, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_cipher_set_associated_data, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_cipher_start, [c_void_p, POINTER(c_char), c_size_t])
-
-_botan_ffi_api(botan.botan_cipher_update,
-               [c_void_p, c_uint32,
-                POINTER(c_char), c_size_t, POINTER(c_size_t),
-                POINTER(c_char), c_size_t, POINTER(c_size_t)])
-
-# Bcrypt
-_botan_ffi_api(botan.botan_bcrypt_generate, [POINTER(c_char), POINTER(c_size_t),
-                                             c_char_p, c_void_p, c_size_t, c_uint32])
-
-_botan_ffi_api(botan.botan_bcrypt_is_valid, [c_char_p, c_char_p])
-
-# PBKDF
-_botan_ffi_api(botan.botan_pbkdf, [c_char_p, POINTER(c_char), c_size_t, c_char_p, c_void_p, c_size_t, c_size_t])
-
-_botan_ffi_api(botan.botan_pbkdf_timed,
-               [c_char_p, POINTER(c_char), c_size_t, c_char_p,
-                c_void_p, c_size_t, c_size_t, POINTER(c_size_t)])
-
-# Scrypt
-_botan_ffi_api(botan.botan_scrypt,
-               [POINTER(c_char), c_size_t, c_char_p, POINTER(c_char), c_size_t,
-                c_size_t, c_size_t, c_size_t])
-
-# KDF
-_botan_ffi_api(botan.botan_kdf,
-               [c_char_p, POINTER(c_char), c_size_t, POINTER(c_char), c_size_t,
-                POINTER(c_char), c_size_t, POINTER(c_char), c_size_t])
-
-# Public key
-_botan_ffi_api(botan.botan_pubkey_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_pubkey_load, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_pubkey_estimated_strength, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_pubkey_algo_name, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_pubkey_export, [c_void_p, POINTER(c_char), POINTER(c_size_t), c_uint32])
-
-_botan_ffi_api(botan.botan_pubkey_fingerprint,
-               [c_void_p, c_char_p, POINTER(c_char), POINTER(c_size_t)])
-
-_botan_ffi_api(botan.botan_privkey_create, [c_void_p, c_char_p, c_char_p, c_void_p])
-_botan_ffi_api(botan.botan_privkey_load, [c_void_p, c_void_p, POINTER(c_char), c_size_t, POINTER(c_char)])
-_botan_ffi_api(botan.botan_privkey_algo_name, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_privkey_export_pubkey, [c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_privkey_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_privkey_export, [c_void_p, POINTER(c_char), c_void_p, c_uint32])
-
-# PK Encryption
-_botan_ffi_api(botan.botan_pk_op_encrypt_create, [c_void_p, c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_pk_op_encrypt_output_length, [c_void_p, c_size_t, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_pk_op_encrypt_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_pk_op_encrypt,
-               [c_void_p, c_void_p, POINTER(c_char), POINTER(c_size_t),
-                POINTER(c_char), c_size_t])
-
-# PK Decryption
-_botan_ffi_api(botan.botan_pk_op_decrypt_create, [c_void_p, c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_pk_op_decrypt_output_length, [c_void_p, c_size_t, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_pk_op_decrypt_destroy, [c_void_p])
-
-_botan_ffi_api(botan.botan_pk_op_decrypt,
-               [c_void_p,
-                POINTER(c_char), POINTER(c_size_t),
-                POINTER(c_char), c_size_t])
-
-# PK Signatures
-_botan_ffi_api(botan.botan_pk_op_sign_create, [c_void_p, c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_pk_op_sign_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_pk_op_sign_update, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_pk_op_sign_finish, [c_void_p, c_void_p, POINTER(c_char), POINTER(c_size_t)])
-
-# PK Verification
-_botan_ffi_api(botan.botan_pk_op_verify_create, [c_void_p, c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_pk_op_verify_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_pk_op_verify_update, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_pk_op_verify_finish, [c_void_p, POINTER(c_char), c_size_t])
-
-# MCEIES
-_botan_ffi_api(botan.botan_mceies_encrypt,
-               [c_void_p, c_void_p, c_char_p, POINTER(c_char), c_size_t,
-                POINTER(c_char), c_size_t, POINTER(c_char), POINTER(c_size_t)])
-
-_botan_ffi_api(botan.botan_mceies_decrypt,
-               [c_void_p, c_char_p, POINTER(c_char), c_size_t,
-                POINTER(c_char), c_size_t, POINTER(c_char), POINTER(c_size_t)])
-
-# Key Agreement
-_botan_ffi_api(botan.botan_pk_op_key_agreement_export_public, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_pk_op_key_agreement_create, [c_void_p, c_void_p, c_char_p, c_uint32])
-_botan_ffi_api(botan.botan_pk_op_key_agreement_destroy, [c_void_p])
-
-_botan_ffi_api(botan.botan_pk_op_key_agreement,
-               [c_void_p, POINTER(c_char), POINTER(c_size_t),
-                POINTER(c_char), c_size_t, POINTER(c_char), c_size_t])
-
-# X509 certs
-_botan_ffi_api(botan.botan_x509_cert_load_file, [POINTER(c_void_p), c_char_p])
-_botan_ffi_api(botan.botan_x509_cert_load, [POINTER(c_void_p), POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_x509_cert_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_x509_cert_get_time_starts, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_x509_cert_get_time_expires, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_x509_cert_to_string, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-
-_botan_ffi_api(botan.botan_x509_cert_get_fingerprint,
-               [c_void_p, c_char_p, POINTER(c_char), POINTER(c_size_t)])
-
-_botan_ffi_api(botan.botan_x509_cert_get_serial_number, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_x509_cert_get_authority_key_id, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_x509_cert_get_subject_key_id, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_x509_cert_get_public_key_bits, [c_void_p, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_x509_cert_get_public_key, [c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_x509_cert_get_subject_dn, [c_void_p, c_char_p, c_size_t, POINTER(c_char), POINTER(c_size_t)])
-
-# MPI
-_botan_ffi_api(botan.botan_mp_init, [c_void_p])
-_botan_ffi_api(botan.botan_mp_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_mp_to_hex, [c_void_p, POINTER(c_char)])
-_botan_ffi_api(botan.botan_mp_to_str, [c_void_p, c_uint8, POINTER(c_char), POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_mp_clear, [c_void_p])
-_botan_ffi_api(botan.botan_mp_set_from_int, [c_void_p, c_int])
-_botan_ffi_api(botan.botan_mp_set_from_mp, [c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_set_from_str, [c_void_p, POINTER(c_char)])
-_botan_ffi_api(botan.botan_mp_set_from_radix_str, [c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_mp_num_bits, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_mp_num_bytes, [c_void_p, POINTER(c_size_t)])
-_botan_ffi_api(botan.botan_mp_to_bin, [c_void_p, POINTER(c_uint8)])
-_botan_ffi_api(botan.botan_mp_from_bin, [c_void_p, POINTER(c_uint8), c_size_t])
-_botan_ffi_api(botan.botan_mp_to_uint32, [c_void_p, POINTER(c_uint32)])
-_botan_ffi_api(botan.botan_mp_is_positive, [c_void_p])
-_botan_ffi_api(botan.botan_mp_is_negative, [c_void_p])
-_botan_ffi_api(botan.botan_mp_flip_sign, [c_void_p])
-_botan_ffi_api(botan.botan_mp_is_zero, [c_void_p])
-_botan_ffi_api(botan.botan_mp_is_odd, [c_void_p])
-_botan_ffi_api(botan.botan_mp_is_even, [c_void_p])
-_botan_ffi_api(botan.botan_mp_add, [c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_sub, [c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_mul, [c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_div, [c_void_p, c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_mod_mul, [c_void_p, c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_equal, [c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_cmp, [POINTER(c_int), c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_swap, [c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_powmod, [c_void_p, c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_lshift, [c_void_p, c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_mp_rshift, [c_void_p, c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_mp_mod_inverse, [c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_rand_bits, [c_void_p, c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_mp_rand_range, [c_void_p, c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_gcd, [c_void_p, c_void_p, c_void_p])
-_botan_ffi_api(botan.botan_mp_is_prime, [c_void_p, c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_mp_get_bit, [c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_mp_set_bit, [c_void_p, c_size_t])
-_botan_ffi_api(botan.botan_mp_clear_bit, [c_void_p, c_size_t])
+def _errcheck(rc, fn, _args):
+    # No idea what to do if return value isn't an int, just return it
+    if not isinstance(rc, int):
+        return rc
+
+    if rc >= 0:
+        return rc
+    if rc == -10: # insufficient buffer space, pass up to caller
+        return rc
+    raise BotanException('%s failed' % (fn.__name__), rc)
+
+def _set_prototypes(dll):
+    # pylint: disable=too-many-statements
+    def ffi_api(fn, args):
+        fn.argtypes = args
+        fn.errcheck = _errcheck
+
+    dll.botan_version_string.argtypes = []
+    dll.botan_version_string.restype = c_char_p
+
+    dll.botan_error_description.argtypes = [c_int]
+    dll.botan_error_description.restype = c_char_p
+
+    # RNG
+    ffi_api(dll.botan_rng_init, [c_void_p, c_char_p])
+    ffi_api(dll.botan_rng_destroy, [c_void_p])
+    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_get, [c_void_p, c_char_p, c_size_t])
+
+    # Hash function
+    ffi_api(dll.botan_hash_init, [c_void_p, c_char_p, c_uint32])
+    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)])
+    ffi_api(dll.botan_hash_clear, [c_void_p])
+    ffi_api(dll.botan_hash_output_length, [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])
+
+    # MAC
+    ffi_api(dll.botan_mac_init, [c_void_p, c_char_p, c_uint32])
+    ffi_api(dll.botan_mac_destroy, [c_void_p])
+    ffi_api(dll.botan_mac_name, [c_void_p, c_char_p, POINTER(c_size_t)])
+    ffi_api(dll.botan_mac_clear, [c_void_p])
+    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])
+
+    # Cipher
+    ffi_api(dll.botan_cipher_init, [c_void_p, c_char_p, c_uint32])
+    ffi_api(dll.botan_cipher_destroy, [c_void_p])
+    ffi_api(dll.botan_cipher_reset, [c_void_p])
+    ffi_api(dll.botan_cipher_name, [c_void_p, c_char_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_get_tag_length, [c_void_p, POINTER(c_size_t)])
+    ffi_api(dll.botan_cipher_valid_nonce_length, [c_void_p, c_size_t])
+    ffi_api(dll.botan_cipher_clear, [c_void_p])
+    ffi_api(dll.botan_cipher_set_key, [c_void_p, c_char_p, c_size_t])
+    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)])
+
+    # Bcrypt
+    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])
+
+    # PBKDF
+    ffi_api(dll.botan_pbkdf, [c_char_p, c_char_p, c_size_t, c_char_p, c_void_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_void_p, c_size_t, c_size_t, POINTER(c_size_t)])
+
+    # Scrypt
+    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])
+
+    # KDF
+    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])
+
+    # Public key
+    ffi_api(dll.botan_pubkey_destroy, [c_void_p])
+    ffi_api(dll.botan_pubkey_load, [c_void_p, c_char_p, c_size_t])
+    ffi_api(dll.botan_pubkey_estimated_strength, [c_void_p, POINTER(c_size_t)])
+    ffi_api(dll.botan_pubkey_algo_name, [c_void_p, c_char_p, POINTER(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_fingerprint,
+            [c_void_p, c_char_p, c_char_p, POINTER(c_size_t)])
+
+    ffi_api(dll.botan_privkey_create, [c_void_p, c_char_p, c_char_p, c_void_p])
+    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_algo_name, [c_void_p, c_char_p, POINTER(c_size_t)])
+    ffi_api(dll.botan_privkey_export_pubkey, [c_void_p, c_void_p])
+    ffi_api(dll.botan_privkey_destroy, [c_void_p])
+    ffi_api(dll.botan_privkey_export, [c_void_p, c_char_p, c_void_p, c_uint32])
+
+    # PK Encryption
+    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_output_length, [c_void_p, c_size_t, POINTER(c_size_t)])
+    ffi_api(dll.botan_pk_op_encrypt_destroy, [c_void_p])
+    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])
+
+    # PK Decryption
+    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_output_length, [c_void_p, c_size_t, POINTER(c_size_t)])
+    ffi_api(dll.botan_pk_op_decrypt_destroy, [c_void_p])
+
+    ffi_api(dll.botan_pk_op_decrypt,
+            [c_void_p,
+             c_char_p, POINTER(c_size_t),
+             c_char_p, c_size_t])
+
+    # PK Signatures
+    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_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)])
+
+    # PK Verification
+    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])
+
+    # MCEIES
+    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)])
+
+    # Key Agreement
+    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_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,
+            [c_void_p, c_char_p, POINTER(c_size_t),
+             c_char_p, c_size_t, c_char_p, c_size_t])
+
+    # X509 certs
+    ffi_api(dll.botan_x509_cert_load_file, [POINTER(c_void_p), c_char_p])
+    ffi_api(dll.botan_x509_cert_load, [POINTER(c_void_p), c_char_p, c_size_t])
+    ffi_api(dll.botan_x509_cert_destroy, [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_to_string, [c_void_p, c_char_p, POINTER(c_size_t)])
+
+    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_subject_dn, [c_void_p, c_char_p, c_size_t, c_char_p, POINTER(c_size_t)])
+
+    # MPI
+    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, POINTER(c_uint8)])
+    ffi_api(dll.botan_mp_from_bin, [c_void_p, POINTER(c_uint8), 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, [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])
+
+    #
+    # 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])
+
+    #
+    # 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])
+
+    return dll
 
 #
-# FPE
+# Load the DLL and set prototypes on it
 #
-_botan_ffi_api(botan.botan_fpe_fe1_init, [c_void_p, c_void_p, POINTER(c_char), c_size_t, c_size_t, c_uint32])
-_botan_ffi_api(botan.botan_fpe_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_fpe_encrypt, [c_void_p, c_void_p, POINTER(c_char), c_size_t])
-_botan_ffi_api(botan.botan_fpe_decrypt, [c_void_p, c_void_p, POINTER(c_char), c_size_t])
-
-#
-# HOTP
-#
-_botan_ffi_api(botan.botan_hotp_init, [c_void_p, POINTER(c_char), c_size_t, c_char_p, c_size_t])
-_botan_ffi_api(botan.botan_hotp_destroy, [c_void_p])
-_botan_ffi_api(botan.botan_hotp_generate, [c_void_p, POINTER(c_uint32), c_uint64])
-_botan_ffi_api(botan.botan_hotp_check, [c_void_p, POINTER(c_uint64), c_uint32, c_uint64, c_size_t])
+_DLL = _set_prototypes(_load_botan_dll(BOTAN_FFI_VERSION))
 
 #
 # Internal utilities
@@ -368,16 +367,16 @@ def _hex_encode(buf):
 # Versions
 #
 def version_major():
-    return botan.botan_version_major()
+    return _DLL.botan_version_major()
 
 def version_minor():
-    return botan.botan_version_minor()
+    return _DLL.botan_version_minor()
 
 def version_patch():
-    return botan.botan_version_patch()
+    return _DLL.botan_version_patch()
 
 def version_string():
-    return botan.botan_version_string().decode('ascii')
+    return _DLL.botan_version_string().decode('ascii')
 
 #
 # RNG
@@ -386,27 +385,27 @@ class RandomNumberGenerator(object):
     # Can also use type "system"
     def __init__(self, rng_type='system'):
         self.__obj = c_void_p(0)
-        botan.botan_rng_init(byref(self.__obj), _ctype_str(rng_type))
+        _DLL.botan_rng_init(byref(self.__obj), _ctype_str(rng_type))
 
     def __del__(self):
-        botan.botan_rng_destroy(self.__obj)
+        _DLL.botan_rng_destroy(self.__obj)
 
     def handle_(self):
         return self.__obj
 
     def reseed(self, bits=256):
-        botan.botan_rng_reseed(self.__obj, bits)
+        _DLL.botan_rng_reseed(self.__obj, bits)
 
     def reseed_from_rng(self, source_rng, bits=256):
-        botan.botan_rng_reseed_from_rng(self.__obj, source_rng.handle_(), bits)
+        _DLL.botan_rng_reseed_from_rng(self.__obj, source_rng.handle_(), bits)
 
     def add_entropy(self, seed):
-        botan.botan_rng_add_entropy(self.__obj, _ctype_bits(seed), len(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)
-        botan.botan_rng_get(self.__obj, out, l)
+        _DLL.botan_rng_get(self.__obj, out, l)
         return _ctype_bufout(out)
 
 #
@@ -416,30 +415,30 @@ class HashFunction(object):
     def __init__(self, algo):
         flags = c_uint32(0) # always zero in this API version
         self.__obj = c_void_p(0)
-        botan.botan_hash_init(byref(self.__obj), _ctype_str(algo), flags)
+        _DLL.botan_hash_init(byref(self.__obj), _ctype_str(algo), flags)
 
         output_length = c_size_t(0)
-        botan.botan_hash_output_length(self.__obj, byref(output_length))
+        _DLL.botan_hash_output_length(self.__obj, byref(output_length))
         self.__output_length = output_length.value
 
     def __del__(self):
-        botan.botan_hash_destroy(self.__obj)
+        _DLL.botan_hash_destroy(self.__obj)
 
     def algo_name(self):
-        return _call_fn_returning_str(32, lambda b, bl: botan.botan_hash_name(self.__obj, b, bl))
+        return _call_fn_returning_str(32, lambda b, bl: _DLL.botan_hash_name(self.__obj, b, bl))
 
     def clear(self):
-        botan.botan_hash_clear(self.__obj)
+        _DLL.botan_hash_clear(self.__obj)
 
     def output_length(self):
         return self.__output_length
 
     def update(self, x):
-        botan.botan_hash_update(self.__obj, _ctype_bits(x), len(x))
+        _DLL.botan_hash_update(self.__obj, _ctype_bits(x), len(x))
 
     def final(self):
         out = create_string_buffer(self.output_length())
-        botan.botan_hash_final(self.__obj, out)
+        _DLL.botan_hash_final(self.__obj, out)
         return _ctype_bufout(out)
 
 #
@@ -449,29 +448,29 @@ class MsgAuthCode(object):
     def __init__(self, algo):
         flags = c_uint32(0) # always zero in this API version
         self.__obj = c_void_p(0)
-        botan.botan_mac_init(byref(self.__obj), _ctype_str(algo), flags)
+        _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)
-        botan.botan_mac_get_keyspec(self.__obj, byref(min_keylen), byref(max_keylen), byref(mod_keylen))
+        _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)
-        botan.botan_mac_output_length(self.__obj, byref(output_length))
+        _DLL.botan_mac_output_length(self.__obj, byref(output_length))
         self.__output_length = output_length.value
 
     def __del__(self):
-        botan.botan_mac_destroy(self.__obj)
+        _DLL.botan_mac_destroy(self.__obj)
 
     def clear(self):
-        botan.botan_mac_clear(self.__obj)
+        _DLL.botan_mac_clear(self.__obj)
 
     def algo_name(self):
-        return _call_fn_returning_str(32, lambda b, bl: botan.botan_mac_name(self.__obj, b, bl))
+        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
@@ -483,80 +482,80 @@ class MsgAuthCode(object):
         return self.__max_keylen
 
     def set_key(self, key):
-        botan.botan_mac_set_key(self.__obj, key, len(key))
+        _DLL.botan_mac_set_key(self.__obj, key, len(key))
 
     def update(self, x):
-        botan.botan_mac_update(self.__obj, x, len(x))
+        _DLL.botan_mac_update(self.__obj, x, len(x))
 
     def final(self):
         out = create_string_buffer(self.output_length())
-        botan.botan_mac_final(self.__obj, out)
+        _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)
-        botan.botan_cipher_init(byref(self.__obj), _ctype_str(algo), flags)
+        _DLL.botan_cipher_init(byref(self.__obj), _ctype_str(algo), flags)
 
     def __del__(self):
-        botan.botan_cipher_destroy(self.__obj)
+        _DLL.botan_cipher_destroy(self.__obj)
 
     def algo_name(self):
-        return _call_fn_returning_str(32, lambda b, bl: botan.botan_cipher_name(self.__obj, b, bl))
+        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)
-        botan.botan_cipher_get_default_nonce_length(self.__obj, byref(l))
+        _DLL.botan_cipher_get_default_nonce_length(self.__obj, byref(l))
         return l.value
 
     def update_granularity(self):
         l = c_size_t(0)
-        botan.botan_cipher_get_update_granularity(self.__obj, byref(l))
+        _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)
-        botan.botan_cipher_query_keylen(self.__obj, byref(kmin), byref(kmax))
+        _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)
-        botan.botan_cipher_get_keyspec(self.__obj, byref(l), None, None)
+        _DLL.botan_cipher_get_keyspec(self.__obj, byref(l), None, None)
         return l.value
 
     def maximum_keylength(self):
         l = c_size_t(0)
-        botan.botan_cipher_get_keyspec(self.__obj, None, byref(l), None)
+        _DLL.botan_cipher_get_keyspec(self.__obj, None, byref(l), None)
         return l.value
 
     def tag_length(self):
         l = c_size_t(0)
-        botan.botan_cipher_get_tag_length(self.__obj, byref(l))
+        _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 = botan.botan_cipher_valid_nonce_length(self.__obj, nonce_len)
+        rc = _DLL.botan_cipher_valid_nonce_length(self.__obj, nonce_len)
         return rc == 1
 
     def reset(self):
-        botan.botan_cipher_reset(self.__obj)
+        _DLL.botan_cipher_reset(self.__obj)
 
     def clear(self):
-        botan.botan_cipher_clear(self.__obj)
+        _DLL.botan_cipher_clear(self.__obj)
 
     def set_key(self, key):
-        botan.botan_cipher_set_key(self.__obj, key, len(key))
+        _DLL.botan_cipher_set_key(self.__obj, key, len(key))
 
     def set_assoc_data(self, ad):
-        botan.botan_cipher_set_associated_data(self.__obj, ad, len(ad))
+        _DLL.botan_cipher_set_associated_data(self.__obj, ad, len(ad))
 
     def start(self, nonce):
-        botan.botan_cipher_start(self.__obj, nonce, len(nonce))
+        _DLL.botan_cipher_start(self.__obj, nonce, len(nonce))
 
     def _update(self, txt, final):
 
@@ -568,9 +567,9 @@ class SymmetricCipher(object):
         out_written = c_size_t(0)
         flags = c_uint32(1 if final else 0)
 
-        botan.botan_cipher_update(self.__obj, flags,
-                                  out, out_sz, byref(out_written),
-                                  _ctype_bits(inp), inp_sz, byref(inp_consumed))
+        _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
@@ -589,15 +588,15 @@ def bcrypt(passwd, rng_obj, work_factor=10):
     out_len = c_size_t(64)
     out = create_string_buffer(out_len.value)
     flags = c_uint32(0)
-    botan.botan_bcrypt_generate(out, byref(out_len), _ctype_str(passwd),
-                                rng_obj.handle_(), c_size_t(work_factor), flags)
+    _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 = botan.botan_bcrypt_is_valid(_ctype_str(passwd), _ctype_str(passwd_hash))
+    rc = _DLL.botan_bcrypt_is_valid(_ctype_str(passwd), _ctype_str(passwd_hash))
     return rc == 0
 
 #
@@ -606,18 +605,20 @@ def check_bcrypt(passwd, passwd_hash):
 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)
-    botan.botan_pbkdf(_ctype_str(algo), out_buf, out_len,
-                      _ctype_str(password), salt, len(salt), iterations)
+    _DLL.botan_pbkdf(_ctype_str(algo), out_buf, out_len,
+                     _ctype_str(password), salt, len(salt), iterations)
     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)
-    botan.botan_pbkdf_timed(_ctype_str(algo), out_buf, out_len, _ctype_str(password),
-                            salt, len(salt), ms_to_run, byref(iterations))
+    _DLL.botan_pbkdf_timed(_ctype_str(algo), out_buf, out_len, _ctype_str(password),
+                           salt, len(salt), ms_to_run, byref(iterations))
     return (salt, iterations.value, out_buf.raw)
 
 #
@@ -625,8 +626,8 @@ def pbkdf_timed(algo, password, out_len, ms_to_run=300, salt=None):
 #
 def scrypt(out_len, password, salt, n=1024, r=8, p=8):
     out_buf = create_string_buffer(out_len)
-    botan.botan_scrypt(out_buf, out_len, _ctype_str(password),
-                       _ctype_bits(salt), len(salt), n, r, p)
+    _DLL.botan_scrypt(out_buf, out_len, _ctype_str(password),
+                      _ctype_bits(salt), len(salt), n, r, p)
 
     return out_buf.raw
 
@@ -636,10 +637,10 @@ def scrypt(out_len, password, salt, n=1024, r=8, p=8):
 def kdf(algo, secret, out_len, salt, label):
     out_buf = create_string_buffer(out_len)
     out_sz = c_size_t(out_len)
-    botan.botan_kdf(_ctype_str(algo), out_buf, out_sz,
-                    secret, len(secret),
-                    salt, len(salt),
-                    label, len(label))
+    _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)]
 
 #
@@ -653,28 +654,28 @@ class PublicKey(object): # pylint: disable=invalid-name
     @classmethod
     def load(cls, val):
         obj = c_void_p(0)
-        botan.botan_pubkey_load(byref(obj), _ctype_bits(val), len(val))
+        _DLL.botan_pubkey_load(byref(obj), _ctype_bits(val), len(val))
         return PublicKey(obj)
 
     def __del__(self):
-        botan.botan_pubkey_destroy(self.__obj)
+        _DLL.botan_pubkey_destroy(self.__obj)
 
     def handle_(self):
         return self.__obj
 
     def estimated_strength(self):
         r = c_size_t(0)
-        botan.botan_pubkey_estimated_strength(self.__obj, byref(r))
+        _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: botan.botan_pubkey_algo_name(self.__obj, b, bl))
+        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: botan.botan_pubkey_export(self.__obj, b, bl, 1))
+            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: botan.botan_pubkey_export(self.__obj, b, bl, 0))
+            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)
@@ -691,7 +692,7 @@ class PublicKey(object): # pylint: disable=invalid-name
         buf = create_string_buffer(n)
         buf_len = c_size_t(n)
 
-        botan.botan_pubkey_fingerprint(self.__obj, _ctype_str(hash_algorithm), buf, byref(buf_len))
+        _DLL.botan_pubkey_fingerprint(self.__obj, _ctype_str(hash_algorithm), buf, byref(buf_len))
         return _hex_encode(buf[0:int(buf_len.value)])
 
 #
@@ -706,7 +707,7 @@ class PrivateKey(object):
     def load(cls, val, passphrase=""):
         obj = c_void_p(0)
         rng_obj = c_void_p(0) # unused in recent versions
-        botan.botan_privkey_load(byref(obj), rng_obj, _ctype_bits(val), len(val), _ctype_str(passphrase))
+        _DLL.botan_privkey_load(byref(obj), rng_obj, _ctype_bits(val), len(val), _ctype_str(passphrase))
         return PrivateKey(obj)
 
     @classmethod
@@ -729,22 +730,21 @@ class PrivateKey(object):
             params = "%d,%d" % (params[0], params[1])
 
         obj = c_void_p(0)
-
-        botan.botan_privkey_create(byref(obj), _ctype_str(algo), _ctype_str(params), rng_obj.handle_())
+        _DLL.botan_privkey_create(byref(obj), _ctype_str(algo), _ctype_str(params), rng_obj.handle_())
         return PrivateKey(obj)
 
     def __del__(self):
-        botan.botan_privkey_destroy(self.__obj)
+        _DLL.botan_privkey_destroy(self.__obj)
 
     def handle_(self):
         return self.__obj
 
     def algo_name(self):
-        return _call_fn_returning_str(32, lambda b, bl: botan.botan_privkey_algo_name(self.__obj, b, bl))
+        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)
-        botan.botan_privkey_export_pubkey(byref(pub), self.__obj)
+        _DLL.botan_privkey_export_pubkey(byref(pub), self.__obj)
         return PublicKey(pub)
 
     def to_der(self):
@@ -755,24 +755,24 @@ class PrivateKey(object):
 
     def export(self, pem=False):
         if pem:
-            return _call_fn_returning_str(4096, lambda b, bl: botan.botan_privkey_export(self.__obj, b, bl, 1))
+            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: botan.botan_privkey_export(self.__obj, b, bl, 0))
+            return _call_fn_returning_vec(4096, lambda b, bl: _DLL.botan_privkey_export(self.__obj, b, bl, 0))
 
 class PKEncrypt(object):
     def __init__(self, key, padding):
         self.__obj = c_void_p(0)
         flags = c_uint32(0) # always zero in this ABI
-        botan.botan_pk_op_encrypt_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
+        _DLL.botan_pk_op_encrypt_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
 
     def __del__(self):
-        botan.botan_pk_op_encrypt_destroy(self.__obj)
+        _DLL.botan_pk_op_encrypt_destroy(self.__obj)
 
     def encrypt(self, msg, rng_obj):
         outbuf_sz = c_size_t(0)
-        botan.botan_pk_op_encrypt_output_length(self.__obj, len(msg), byref(outbuf_sz))
+        _DLL.botan_pk_op_encrypt_output_length(self.__obj, len(msg), byref(outbuf_sz))
         outbuf = create_string_buffer(outbuf_sz.value)
-        botan.botan_pk_op_encrypt(self.__obj, rng_obj.handle_(), outbuf, byref(outbuf_sz), msg, len(msg))
+        _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)]
 
 
@@ -780,51 +780,51 @@ class PKDecrypt(object):
     def __init__(self, key, padding):
         self.__obj = c_void_p(0)
         flags = c_uint32(0) # always zero in this ABI
-        botan.botan_pk_op_decrypt_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
+        _DLL.botan_pk_op_decrypt_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
 
     def __del__(self):
-        botan.botan_pk_op_decrypt_destroy(self.__obj)
+        _DLL.botan_pk_op_decrypt_destroy(self.__obj)
 
     def decrypt(self, msg):
         outbuf_sz = c_size_t(0)
-        botan.botan_pk_op_decrypt_output_length(self.__obj, len(msg), byref(outbuf_sz))
+        _DLL.botan_pk_op_decrypt_output_length(self.__obj, len(msg), byref(outbuf_sz))
         outbuf = create_string_buffer(outbuf_sz.value)
-        botan.botan_pk_op_decrypt(self.__obj, outbuf, byref(outbuf_sz), _ctype_bits(msg), len(msg))
+        _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):
         self.__obj = c_void_p(0)
         flags = c_uint32(0) # always zero in this ABI
-        botan.botan_pk_op_sign_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
+        _DLL.botan_pk_op_sign_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
 
     def __del__(self):
-        botan.botan_pk_op_sign_destroy(self.__obj)
+        _DLL.botan_pk_op_sign_destroy(self.__obj)
 
     def update(self, msg):
-        botan.botan_pk_op_sign_update(self.__obj, _ctype_str(msg), len(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)
-        botan.botan_pk_op_sign_output_length(self.__obj, byref(outbuf_sz))
+        _DLL.botan_pk_op_sign_output_length(self.__obj, byref(outbuf_sz))
         outbuf = create_string_buffer(outbuf_sz.value)
-        botan.botan_pk_op_sign_finish(self.__obj, rng_obj.handle_(), outbuf, byref(outbuf_sz))
+        _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):
         self.__obj = c_void_p(0)
         flags = c_uint32(0) # always zero in this ABI
-        botan.botan_pk_op_verify_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
+        _DLL.botan_pk_op_verify_create(byref(self.__obj), key.handle_(), _ctype_str(padding), flags)
 
     def __del__(self):
-        botan.botan_pk_op_verify_destroy(self.__obj)
+        _DLL.botan_pk_op_verify_destroy(self.__obj)
 
     def update(self, msg):
-        botan.botan_pk_op_verify_update(self.__obj, _ctype_bits(msg), len(msg))
+        _DLL.botan_pk_op_verify_update(self.__obj, _ctype_bits(msg), len(msg))
 
     def check_signature(self, signature):
-        rc = botan.botan_pk_op_verify_finish(self.__obj, _ctype_bits(signature), len(signature))
+        rc = _DLL.botan_pk_op_verify_finish(self.__obj, _ctype_bits(signature), len(signature))
         if rc == 0:
             return True
         return False
@@ -833,22 +833,22 @@ class PKKeyAgreement(object):
     def __init__(self, key, kdf_name):
         self.__obj = c_void_p(0)
         flags = c_uint32(0) # always zero in this ABI
-        botan.botan_pk_op_key_agreement_create(byref(self.__obj), key.handle_(), kdf_name, flags)
+        _DLL.botan_pk_op_key_agreement_create(byref(self.__obj), key.handle_(), kdf_name, flags)
 
         self.m_public_value = _call_fn_returning_vec(
-            0, lambda b, bl: botan.botan_pk_op_key_agreement_export_public(key.handle_(), b, bl))
+            0, lambda b, bl: _DLL.botan_pk_op_key_agreement_export_public(key.handle_(), b, bl))
 
     def __del__(self):
-        botan.botan_pk_op_key_agreement_destroy(self.__obj)
+        _DLL.botan_pk_op_key_agreement_destroy(self.__obj)
 
     def public_value(self):
         return self.m_public_value
 
     def agree(self, other, key_len, salt):
         return _call_fn_returning_vec(key_len, lambda b, bl:
-                                      botan.botan_pk_op_key_agreement(self.__obj, b, bl,
-                                                                      other, len(other),
-                                                                      salt, len(salt)))
+                                      _DLL.botan_pk_op_key_agreement(self.__obj, b, bl,
+                                                                     other, len(other),
+                                                                     salt, len(salt)))
 
 #
 # MCEIES encryption
@@ -856,14 +856,14 @@ class PKKeyAgreement(object):
 #
 def mceies_encrypt(mce, rng_obj, aead, pt, ad):
     return _call_fn_returning_vec(len(pt) + 1024, lambda b, bl:
-                                  botan.botan_mceies_encrypt(mce.handle_(),
-                                                             rng_obj.handle_(),
-                                                             _ctype_str(aead),
-                                                             _ctype_bits(pt),
-                                                             len(pt),
-                                                             _ctype_bits(ad),
-                                                             len(ad),
-                                                             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):
 
@@ -871,13 +871,13 @@ def mceies_decrypt(mce, aead, ct, ad):
     #ll = c_size_t(ll)
 
     return _call_fn_returning_vec(len(ct), lambda b, bl:
-                                  botan.botan_mceies_decrypt(mce.handle_(),
-                                                             _ctype_str(aead),
-                                                             _ctype_bits(ct),
-                                                             len(ct),
-                                                             _ctype_bits(ad),
-                                                             len(ad),
-                                                             b, bl))
+                                  _DLL.botan_mceies_decrypt(mce.handle_(),
+                                                            _ctype_str(aead),
+                                                            _ctype_bits(ct),
+                                                            len(ct),
+                                                            _ctype_bits(ad),
+                                                            len(ad),
+                                                            b, bl))
 
 
 #
@@ -891,17 +891,17 @@ class X509Cert(object): # pylint: disable=invalid-name
             raise BotanException("Both filename and buf given")
         elif filename is not None:
             self.__obj = c_void_p(0)
-            botan.botan_x509_cert_load_file(byref(self.__obj), _ctype_str(filename))
+            _DLL.botan_x509_cert_load_file(byref(self.__obj), _ctype_str(filename))
         elif buf is not None:
             self.__obj = c_void_p(0)
-            botan.botan_x509_cert_load(byref(self.__obj), _ctype_bits(buf), len(buf))
+            _DLL.botan_x509_cert_load(byref(self.__obj), _ctype_bits(buf), len(buf))
 
     def __del__(self):
-        botan.botan_x509_cert_destroy(self.__obj)
+        _DLL.botan_x509_cert_destroy(self.__obj)
 
     def time_starts(self):
         starts = _call_fn_returning_str(
-            16, lambda b, bl: botan.botan_x509_cert_get_time_starts(self.__obj, b, bl))
+            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")
@@ -915,7 +915,7 @@ class X509Cert(object): # pylint: disable=invalid-name
 
     def time_expires(self):
         expires = _call_fn_returning_str(
-            16, lambda b, bl: botan.botan_x509_cert_get_time_expires(self.__obj, b, bl))
+            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")
@@ -929,37 +929,37 @@ class X509Cert(object): # pylint: disable=invalid-name
 
     def to_string(self):
         return _call_fn_returning_str(
-            4096, lambda b, bl: botan.botan_x509_cert_to_string(self.__obj, b, bl))
+            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: botan.botan_x509_cert_get_fingerprint(self.__obj, _ctype_str(hash_algo), b, bl))
+            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: botan.botan_x509_cert_get_serial_number(self.__obj, b, bl))
+            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: botan.botan_x509_cert_get_authority_key_id(self.__obj, b, bl))
+            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: botan.botan_x509_cert_get_subject_key_id(self.__obj, b, bl))
+            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: botan.botan_x509_cert_get_public_key_bits(self.__obj, b, bl))
+            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)
-        botan.botan_x509_cert_get_public_key(self.__obj, byref(pub))
+        _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: botan.botan_x509_cert_get_subject_dn(self.__obj, _ctype_str(key), index, b, bl))
+            0, lambda b, bl: _DLL.botan_x509_cert_get_subject_dn(self.__obj, _ctype_str(key), index, b, bl))
 
 
 class MPI(object):
@@ -967,27 +967,27 @@ class MPI(object):
     def __init__(self, initial_value=None):
 
         self.__obj = c_void_p(0)
-        botan.botan_mp_init(byref(self.__obj))
+        _DLL.botan_mp_init(byref(self.__obj))
 
         if initial_value is None:
             pass # left as zero
         elif isinstance(initial_value, MPI):
-            botan.botan_mp_set_from_mp(self.__obj, initial_value.handle_())
+            _DLL.botan_mp_set_from_mp(self.__obj, initial_value.handle_())
         elif isinstance(initial_value, str):
-            botan.botan_mp_set_from_str(self.__obj, _ctype_str(initial_value))
+            _DLL.botan_mp_set_from_str(self.__obj, _ctype_str(initial_value))
         else:
             # For int or long (or whatever else), try converting to string:
-            botan.botan_mp_set_from_str(self.__obj, _ctype_str(str(initial_value)))
+            _DLL.botan_mp_set_from_str(self.__obj, _ctype_str(str(initial_value)))
 
     def __del__(self):
-        botan.botan_mp_destroy(self.__obj)
+        _DLL.botan_mp_destroy(self.__obj)
 
     def handle_(self):
         return self.__obj
 
     def __int__(self):
         out = create_string_buffer(2*self.byte_count() + 1)
-        botan.botan_mp_to_hex(self.__obj, out)
+        _DLL.botan_mp_to_hex(self.__obj, out)
         val = int(out.value, 16)
         if self.is_negative():
             return -val
@@ -999,27 +999,27 @@ class MPI(object):
         out_len = c_size_t(self.bit_count() // 2)
         out = create_string_buffer(out_len.value)
 
-        botan.botan_mp_to_str(self.__obj, c_uint8(10), out, byref(out_len))
+        _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)
+            s = _ctype_to_str(out)
         if s[0] == '0':
             return s[1:]
         else:
             return s
 
     def is_negative(self):
-        rc = botan.botan_mp_is_negative(self.__obj)
+        rc = _DLL.botan_mp_is_negative(self.__obj)
         return rc == 1
 
     def flip_sign(self):
-        botan.botan_mp_flip_sign(self.__obj)
+        _DLL.botan_mp_flip_sign(self.__obj)
 
     def cmp(self, other):
         r = c_int(0)
-        botan.botan_mp_cmp(byref(r), self.__obj, other.handle_())
+        _DLL.botan_mp_cmp(byref(r), self.__obj, other.handle_())
         return r.value
 
     def __eq__(self, other):
@@ -1042,139 +1042,140 @@ class MPI(object):
 
     def __add__(self, other):
         r = MPI()
-        botan.botan_mp_add(r.handle_(), self.__obj, other.handle_())
+        _DLL.botan_mp_add(r.handle_(), self.__obj, other.handle_())
         return r
 
     def __iadd__(self, other):
-        botan.botan_mp_add(self.__obj, self.__obj, other.handle_())
+        _DLL.botan_mp_add(self.__obj, self.__obj, other.handle_())
         return self
 
     def __sub__(self, other):
         r = MPI()
-        botan.botan_mp_sub(r.handle_(), self.__obj, other.handle_())
+        _DLL.botan_mp_sub(r.handle_(), self.__obj, other.handle_())
         return r
 
     def __isub__(self, other):
-        botan.botan_mp_sub(self.__obj, self.__obj, other.handle_())
+        _DLL.botan_mp_sub(self.__obj, self.__obj, other.handle_())
         return self
 
     def __mul__(self, other):
         r = MPI()
-        botan.botan_mp_mul(r.handle_(), self.__obj, other.handle_())
+        _DLL.botan_mp_mul(r.handle_(), self.__obj, other.handle_())
         return r
 
     def __imul__(self, other):
-        botan.botan_mp_mul(self.__obj, self.__obj, other.handle_())
+        _DLL.botan_mp_mul(self.__obj, self.__obj, other.handle_())
         return self
 
     def __divmod__(self, other):
         d = MPI()
         q = MPI()
-        botan.botan_mp_div(d.handle_(), q.handle_(), self.__obj, other.handle_())
+        _DLL.botan_mp_div(d.handle_(), q.handle_(), self.__obj, other.handle_())
         return (d, q)
 
     def __mod__(self, other):
         d = MPI()
         q = MPI()
-        botan.botan_mp_div(d.handle_(), q.handle_(), self.__obj, other.handle_())
+        _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()
-        botan.botan_mp_lshift(r.handle_(), self.__obj, shift)
+        _DLL.botan_mp_lshift(r.handle_(), self.__obj, shift)
         return r
 
     def __ilshift__(self, shift):
         shift = c_size_t(shift)
-        botan.botan_mp_lshift(self.__obj, self.__obj, shift)
+        _DLL.botan_mp_lshift(self.__obj, self.__obj, shift)
         return self
 
     def __rshift__(self, shift):
         shift = c_size_t(shift)
         r = MPI()
-        botan.botan_mp_rshift(r.handle_(), self.__obj, shift)
+        _DLL.botan_mp_rshift(r.handle_(), self.__obj, shift)
         return r
 
     def __irshift__(self, shift):
         shift = c_size_t(shift)
-        botan.botan_mp_rshift(self.__obj, self.__obj, shift)
+        _DLL.botan_mp_rshift(self.__obj, self.__obj, shift)
         return self
 
     def pow_mod(self, exponent, modulus):
         r = MPI()
-        botan.botan_mp_powmod(r.handle_(), self.__obj, exponent.handle_(), modulus.handle_())
+        _DLL.botan_mp_powmod(r.handle_(), self.__obj, exponent.handle_(), modulus.handle_())
         return r
 
     def is_prime(self, rng_obj, prob=128):
-        return botan.botan_mp_is_prime(self.__obj, rng_obj.handle_(), c_size_t(prob)) == 1
+        return _DLL.botan_mp_is_prime(self.__obj, rng_obj.handle_(), c_size_t(prob)) == 1
 
     def inverse_mod(self, modulus):
         r = MPI()
-        botan.botan_mp_mod_inverse(r.handle_(), self.__obj, modulus.handle_())
+        _DLL.botan_mp_mod_inverse(r.handle_(), self.__obj, modulus.handle_())
         return r
 
     def bit_count(self):
         b = c_size_t(0)
-        botan.botan_mp_num_bits(self.__obj, byref(b))
+        _DLL.botan_mp_num_bits(self.__obj, byref(b))
         return b.value
 
     def byte_count(self):
         b = c_size_t(0)
-        botan.botan_mp_num_bytes(self.__obj, byref(b))
+        _DLL.botan_mp_num_bytes(self.__obj, byref(b))
         return b.value
 
     def get_bit(self, bit):
-        return botan.botan_mp_get_bit(self.__obj, c_size_t(bit)) == 1
+        return _DLL.botan_mp_get_bit(self.__obj, c_size_t(bit)) == 1
 
     def clear_bit(self, bit):
-        botan.botan_mp_clear_bit(self.__obj, c_size_t(bit))
+        _DLL.botan_mp_clear_bit(self.__obj, c_size_t(bit))
 
     def set_bit(self, bit):
-        botan.botan_mp_set_bit(self.__obj, c_size_t(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)
-        botan.botan_fpe_fe1_init(byref(self.__obj), modulus.handle_(), key, len(key), c_size_t(rounds), flags)
+        _DLL.botan_fpe_fe1_init(byref(self.__obj), modulus.handle_(), key, len(key), c_size_t(rounds), flags)
 
     def __del__(self):
-        botan.botan_fpe_destroy(self.__obj)
+        _DLL.botan_fpe_destroy(self.__obj)
 
     def encrypt(self, msg, tweak):
         r = MPI(msg)
-        botan.botan_fpe_encrypt(self.__obj, r.handle_(), _ctype_bits(tweak), len(tweak))
+        _DLL.botan_fpe_encrypt(self.__obj, r.handle_(), _ctype_bits(tweak), len(tweak))
         return r
 
     def decrypt(self, msg, tweak):
         r = MPI(msg)
-        botan.botan_fpe_decrypt(self.__obj, r.handle_(), _ctype_bits(tweak), len(tweak))
+        _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)
-        botan.botan_hotp_init(byref(self.__obj), key, len(key), _ctype_str(digest), digits)
+        _DLL.botan_hotp_init(byref(self.__obj), key, len(key), _ctype_str(digest), digits)
 
     def __del__(self):
-        botan.botan_hotp_destroy(self.__obj)
+        _DLL.botan_hotp_destroy(self.__obj)
 
     def generate(self, counter):
         code = c_uint32(0)
-        botan.botan_hotp_generate(self.__obj, byref(code), counter)
+        _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 = botan.botan_hotp_check(self.__obj, byref(next_ctr), code, counter, resync_range)
+        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)
 
 # 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


Test patch:
diff --git a/src/scripts/test_python.py b/src/scripts/test_python.py
index dd434531e..b6e8ca9d6 100644
--- a/src/scripts/test_python.py
+++ b/src/scripts/test_python.py
@@ -102,6 +102,12 @@ class BotanPythonTests(unittest.TestCase):
         user_rng.add_entropy('seed material...')
 
     def test_hash(self):
+
+        try:
+            h = botan2.HashFunction('NoSuchHash')
+        except botan2.BotanException as e:
+            self.assertEqual(str(e), "botan_hash_init failed: -40 (Not implemented)")
+
         h = botan2.HashFunction('SHA-256')
         self.assertEqual(h.algo_name(), 'SHA-256')
         assert h.output_length() == 32