aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/asn1/oid_lookup/default.cpp2
-rw-r--r--src/lib/ffi/ffi.cpp196
-rw-r--r--src/lib/ffi/ffi.h13
-rwxr-xr-xsrc/python/botan.py101
4 files changed, 228 insertions, 84 deletions
diff --git a/src/lib/asn1/oid_lookup/default.cpp b/src/lib/asn1/oid_lookup/default.cpp
index de04f542a..0e23b18a2 100644
--- a/src/lib/asn1/oid_lookup/default.cpp
+++ b/src/lib/asn1/oid_lookup/default.cpp
@@ -28,7 +28,7 @@ const char* default_oid_list()
// X9.62 ecPublicKey, valid for ECDSA and ECDH (RFC 3279 sec 2.3.5)
"1.2.840.10045.2.1 = ECDSA" "\n"
- //"1.3.132.1.12 = ECDH" "\n"
+ "1.3.132.1.12 = ECDH" "\n"
"1.2.643.2.2.19 = GOST-34.10" "\n"
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 937423c69..94fc546fe 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -31,6 +31,10 @@
#include <botan/ecdh.h>
#endif
+#if defined(BOTAN_HAS_CURVE_25519)
+ #include <botan/curve25519.h>
+#endif
+
#if defined(BOTAN_HAS_BCRYPT)
#include <botan/bcrypt.h>
#endif
@@ -49,7 +53,9 @@ struct botan_struct
T* get() const
{
- BOTAN_ASSERT_EQUAL(m_magic, MAGIC, "Bad magic value - memory corruption?");
+ if(m_magic != MAGIC)
+ throw std::runtime_error("Bad magic " + std::to_string(m_magic) +
+ " in ffi object expected" + std::to_string(MAGIC));
return m_obj.get();
}
private:
@@ -59,7 +65,7 @@ struct botan_struct
void log_exception(const char* func_name, const char* what)
{
- printf("botan ffi %s: %s\n", func_name, what);
+ fprintf(stderr, "%s: %s\n", func_name, what);
}
template<typename T, uint32_t M>
@@ -96,20 +102,32 @@ int apply_fn(botan_struct<T, M>* o, const char* func_name, F func)
return -1;
}
-template<typename Alloc>
-int write_output(uint8_t out[], size_t* out_len, const std::vector<uint8_t, Alloc>& buf)
+int write_output(uint8_t out[], size_t* out_len, const uint8_t buf[], size_t buf_len)
{
Botan::clear_mem(out, *out_len);
const size_t avail = *out_len;
- *out_len = buf.size();
- if(avail >= buf.size())
+ *out_len = buf_len;
+ if(avail >= buf_len)
{
- Botan::copy_mem(out, &buf[0], buf.size());
+ Botan::copy_mem(out, &buf[0], buf_len);
return 0;
}
return -1;
}
+template<typename Alloc>
+int write_vec_output(uint8_t out[], size_t* out_len, const std::vector<uint8_t, Alloc>& buf)
+ {
+ return write_output(out, out_len, &buf[0], buf.size());
+ }
+
+int write_str_output(uint8_t out[], size_t* out_len, const std::string& str)
+ {
+ return write_output(out, out_len,
+ reinterpret_cast<const uint8_t*>(str.c_str()),
+ str.size() + 1);
+ }
+
#define BOTAN_FFI_DO(T, obj, block) apply_fn(obj, BOTAN_CURRENT_FUNCTION, [=](T& obj) { do { block } while(0); return 0; })
}
@@ -261,8 +279,10 @@ int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags)
{
try
{
- if(!hash || !hash_name || flags != 0)
- return -1;
+ if(hash == nullptr || hash_name == nullptr || *hash_name == 0)
+ return BOTAN_FFI_ERROR_NULL_POINTER;
+ if(flags != 0)
+ return BOTAN_FFI_ERROR_BAD_FLAG;
if(auto h = Botan::get_hash_function(hash_name))
{
@@ -279,7 +299,7 @@ int botan_hash_init(botan_hash_t* hash, const char* hash_name, uint32_t flags)
log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
}
- return -2;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
int botan_hash_destroy(botan_hash_t hash)
@@ -634,25 +654,26 @@ int botan_kdf(const char* kdf_algo,
}
#if defined(BOTAN_HAS_BCRYPT)
-int botan_bcrypt_generate(char* out, size_t out_len, const char* pass,
- botan_rng_t rng_obj, size_t wf)
+int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
+ const char* pass,
+ botan_rng_t rng_obj, size_t wf,
+ uint32_t flags)
{
try
{
BOTAN_ASSERT_ARG_NON_NULL(out);
+ BOTAN_ASSERT_ARG_NON_NULL(out_len);
BOTAN_ASSERT_ARG_NON_NULL(pass);
+ if(flags != 0)
+ return BOTAN_FFI_ERROR_BAD_FLAG;
+
if(wf < 2 || wf > 30)
throw std::runtime_error("Bad bcrypt work factor " + std::to_string(wf));
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
-
- std::memset(out, 0, out_len);
- const std::string c = Botan::generate_bcrypt(pass, rng, wf);
- if(out_len <= c.size())
- return ENOMEM;
- std::memcpy(out, c.c_str(), c.size());
- return 0;
+ const std::string bcrypt = Botan::generate_bcrypt(pass, rng, wf);
+ return write_str_output(out, out_len, bcrypt);
}
catch(std::exception& e)
{
@@ -663,7 +684,7 @@ int botan_bcrypt_generate(char* out, size_t out_len, const char* pass,
log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
int botan_bcrypt_is_valid(const char* pass, const char* hash)
@@ -683,21 +704,26 @@ int botan_bcrypt_is_valid(const char* pass, const char* hash)
log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
#endif
-int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t n_bits)
+int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits)
{
try
{
- *key = nullptr;
+ if(key_obj == nullptr || rng_obj == nullptr)
+ return -1;
+ if(n_bits < 1024 || n_bits > 16*1024)
+ return -2;
+
+ *key_obj = nullptr;
#if defined(BOTAN_HAS_RSA)
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
- std::unique_ptr<Botan::RSA_PrivateKey> rsa(new Botan::RSA_PrivateKey(rng, n_bits));
- *key = new botan_privkey_struct(rsa.release());
+ std::unique_ptr<Botan::Private_Key> key(new Botan::RSA_PrivateKey(rng, n_bits));
+ *key_obj = new botan_privkey_struct(key.release());
return 0;
#endif
}
@@ -706,19 +732,24 @@ int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng_obj, size_t n
log_exception(BOTAN_CURRENT_FUNCTION, e.what());
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
-int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng_obj, const char* params)
+int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
{
try
{
+ if(key_obj == nullptr || rng_obj == nullptr || param_str == nullptr || *param_str == 0)
+ return -1;
+
+ *key_obj = nullptr;
+
#if defined(BOTAN_HAS_ECDSA)
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
- Botan::EC_Group grp(params);
- std::unique_ptr<Botan::ECDSA_PrivateKey> ecdsa(new Botan::ECDSA_PrivateKey(rng, grp));
- *key = new botan_privkey_struct(ecdsa.release());
+ Botan::EC_Group grp(param_str);
+ std::unique_ptr<Botan::Private_Key> key(new Botan::ECDSA_PrivateKey(rng, grp));
+ *key_obj = new botan_privkey_struct(key.release());
return 0;
#endif
}
@@ -727,18 +758,33 @@ int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng_obj, const
log_exception(BOTAN_CURRENT_FUNCTION, e.what());
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
-int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng_obj, const char* params)
+int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
{
try
{
+ if(key_obj == nullptr || rng_obj == nullptr || param_str == nullptr || *param_str == 0)
+ return -1;
+
+ *key_obj = nullptr;
+
+ const std::string params(param_str);
+
+#if defined(BOTAN_HAS_CURVE_25519)
+ if(params == "curve25519")
+ {
+ std::unique_ptr<Botan::Private_Key> key(new Botan::Curve25519_PrivateKey(safe_get(rng_obj)));
+ *key_obj = new botan_privkey_struct(key.release());
+ return 0;
+ }
+#endif
+
#if defined(BOTAN_HAS_ECDH)
- Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
Botan::EC_Group grp(params);
- std::unique_ptr<Botan::ECDH_PrivateKey> ecdh(new Botan::ECDH_PrivateKey(rng, grp));
- *key = new botan_privkey_struct(ecdh.release());
+ std::unique_ptr<Botan::Private_Key> key(new Botan::ECDH_PrivateKey(safe_get(rng_obj), grp));
+ *key_obj = new botan_privkey_struct(key.release());
return 0;
#endif
}
@@ -747,7 +793,7 @@ int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng_obj, const c
log_exception(BOTAN_CURRENT_FUNCTION, e.what());
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng_obj,
@@ -779,7 +825,7 @@ int botan_privkey_load(botan_privkey_t* key, botan_rng_t rng_obj,
return -1;
*key = nullptr;
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
int botan_privkey_destroy(botan_privkey_t key)
@@ -809,7 +855,7 @@ int botan_privkey_export_pubkey(botan_pubkey_t* pubout, botan_privkey_t key_obj)
log_exception(BOTAN_CURRENT_FUNCTION, e.what());
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
@@ -833,29 +879,44 @@ int botan_pubkey_algo_name(botan_pubkey_t key, char out[], size_t* out_len)
int botan_pubkey_export(botan_pubkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
{
return BOTAN_FFI_DO(Botan::Public_Key, key, {
- return write_output(out, out_len, Botan::X509::BER_encode(key));
+ if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
+ return write_vec_output(out, out_len, Botan::X509::BER_encode(key));
+ else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
+ return write_str_output(out, out_len, Botan::X509::PEM_encode(key));
+ else
+ return -2;
});
}
int botan_privkey_export(botan_privkey_t key, uint8_t out[], size_t* out_len, uint32_t flags)
{
return BOTAN_FFI_DO(Botan::Private_Key, key, {
- return write_output(out, out_len, Botan::PKCS8::BER_encode(key));
+ if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
+ return write_vec_output(out, out_len, Botan::PKCS8::BER_encode(key));
+ else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
+ return write_str_output(out, out_len, Botan::PKCS8::PEM_encode(key));
+ else
+ return -2;
});
}
int botan_privkey_export_encrypted(botan_privkey_t key,
uint8_t out[], size_t* out_len,
botan_rng_t rng_obj,
- const char* passphrase,
- const char* encryption_algo,
+ const char* pass,
+ const char* pbe,
uint32_t flags)
{
return BOTAN_FFI_DO(Botan::Private_Key, key, {
- auto ber = Botan::PKCS8::BER_encode(key, safe_get(rng_obj), passphrase,
- std::chrono::milliseconds(300),
- encryption_algo);
- return write_output(out, out_len, ber);
+ auto pbkdf_time = std::chrono::milliseconds(300);
+ Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
+
+ if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_DER)
+ return write_vec_output(out, out_len, Botan::PKCS8::BER_encode(key, rng, pass, pbkdf_time, pbe));
+ else if(flags == BOTAN_PRIVKEY_EXPORT_FLAG_PEM)
+ return write_str_output(out, out_len, Botan::PKCS8::PEM_encode(key, rng, pass, pbkdf_time, pbe));
+ else
+ return -2;
});
}
@@ -876,8 +937,6 @@ int botan_pubkey_fingerprint(botan_pubkey_t key, const char* hash_fn,
Botan::copy_mem(out, &z[0], *out_len);
return 0;
});
- *out_len = 0;
- return -1;
}
int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op,
@@ -890,7 +949,7 @@ int botan_pk_op_encrypt_create(botan_pk_op_encrypt_t* op,
BOTAN_ASSERT_NONNULL(op);
if(flags != 0)
- return -2;
+ return BOTAN_FFI_ERROR_BAD_FLAG;
std::unique_ptr<Botan::PK_Encryptor> pk(new Botan::PK_Encryptor_EME(safe_get(key_obj), padding));
*op = new botan_pk_op_encrypt_struct(pk.release());
@@ -916,7 +975,7 @@ int botan_pk_op_encrypt(botan_pk_op_encrypt_t op,
const uint8_t plaintext[], size_t plaintext_len)
{
return BOTAN_FFI_DO(Botan::PK_Encryptor, op, {
- return write_output(out, out_len, op.encrypt(plaintext, plaintext_len, safe_get(rng_obj)));
+ return write_vec_output(out, out_len, op.encrypt(plaintext, plaintext_len, safe_get(rng_obj)));
});
}
@@ -933,7 +992,7 @@ int botan_pk_op_decrypt_create(botan_pk_op_decrypt_t* op,
BOTAN_ASSERT_NONNULL(op);
if(flags != 0)
- return -2;
+ return BOTAN_FFI_ERROR_BAD_FLAG;
std::unique_ptr<Botan::PK_Decryptor> pk(new Botan::PK_Decryptor_EME(safe_get(key_obj), padding));
*op = new botan_pk_op_decrypt_struct(pk.release());
@@ -958,7 +1017,7 @@ int botan_pk_op_decrypt(botan_pk_op_decrypt_t op,
uint8_t ciphertext[], size_t ciphertext_len)
{
return BOTAN_FFI_DO(Botan::PK_Decryptor, op, {
- return write_output(out, out_len, op.decrypt(ciphertext, ciphertext_len));
+ return write_vec_output(out, out_len, op.decrypt(ciphertext, ciphertext_len));
});
}
@@ -975,7 +1034,7 @@ int botan_pk_op_sign_create(botan_pk_op_sign_t* op,
BOTAN_ASSERT_NONNULL(op);
if(flags != 0)
- return -2;
+ return BOTAN_FFI_ERROR_BAD_FLAG;
std::unique_ptr<Botan::PK_Signer> pk(new Botan::PK_Signer(safe_get(key_obj), hash));
*op = new botan_pk_op_sign_struct(pk.release());
@@ -986,7 +1045,7 @@ int botan_pk_op_sign_create(botan_pk_op_sign_t* op,
log_exception(BOTAN_CURRENT_FUNCTION, e.what());
}
- return -1;
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
int botan_pk_op_sign_destroy(botan_pk_op_sign_t op)
@@ -1003,7 +1062,7 @@ int botan_pk_op_sign_update(botan_pk_op_sign_t op, const uint8_t in[], size_t in
int botan_pk_op_sign_finish(botan_pk_op_sign_t op, botan_rng_t rng_obj, uint8_t out[], size_t* out_len)
{
return BOTAN_FFI_DO(Botan::PK_Signer, op, {
- return write_output(out, out_len, op.signature(safe_get(rng_obj)));
+ return write_vec_output(out, out_len, op.signature(safe_get(rng_obj)));
});
}
@@ -1017,7 +1076,7 @@ int botan_pk_op_verify_create(botan_pk_op_verify_t* op,
BOTAN_ASSERT_NONNULL(op);
if(flags != 0)
- return -2;
+ return BOTAN_FFI_ERROR_BAD_FLAG;
std::unique_ptr<Botan::PK_Verifier> pk(new Botan::PK_Verifier(safe_get(key_obj), hash));
*op = new botan_pk_op_verify_struct(pk.release());
@@ -1064,7 +1123,7 @@ int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op,
BOTAN_ASSERT_NONNULL(op);
if(flags != 0)
- return -2;
+ return BOTAN_FFI_ERROR_BAD_FLAG;
std::unique_ptr<Botan::PK_Key_Agreement> pk(new Botan::PK_Key_Agreement(safe_get(key_obj), kdf));
*op = new botan_pk_op_ka_struct(pk.release());
@@ -1084,6 +1143,27 @@ int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op)
return 0;
}
+int botan_pk_op_key_agreement_export_public(botan_privkey_t key,
+ uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::Private_Key, key, {
+ auto kak = dynamic_cast<const Botan::PK_Key_Agreement_Key*>(&key);
+ if(!kak)
+ return -2;
+ const std::vector<uint8_t> pv = kak->public_value();
+ const size_t avail = *out_len;
+ *out_len = pv.size();
+
+ if(pv.size() <= avail)
+ {
+ Botan::copy_mem(out, &pv[0], pv.size());
+ return 0;
+ }
+
+ return -1;
+ });
+ }
+
int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
uint8_t out[], size_t* out_len,
const uint8_t other_key[], size_t other_key_len,
@@ -1091,7 +1171,7 @@ int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
{
return BOTAN_FFI_DO(Botan::PK_Key_Agreement, op, {
auto k = op.derive_key(*out_len, other_key, other_key_len, salt, salt_len).bits_of();
- return write_output(out, out_len, k);
+ return write_vec_output(out, out_len, k);
});
}
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index cda2c1480..34e706e2a 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -38,6 +38,11 @@ BOTAN_DLL uint32_t botan_version_datestamp();
/*
* Error handling
*/
+#define BOTAN_FFI_ERROR_EXCEPTION_THROWN (-20)
+#define BOTAN_FFI_ERROR_BAD_FLAG (-30)
+#define BOTAN_FFI_ERROR_NULL_POINTER (-31)
+#define BOTAN_FFI_ERROR_NULL_POINTER (-31)
+
//const char* botan_error_description(int err);
/*
@@ -146,10 +151,11 @@ BOTAN_DLL int botan_kdf(const char* kdf_algo,
*/
#if defined(BOTAN_HAS_BCRYPT)
-BOTAN_DLL int botan_bcrypt_generate(char* out, size_t out_len,
+BOTAN_DLL int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
const char* pass,
botan_rng_t rng,
- size_t work_factor);
+ size_t work_factor,
+ uint32_t flags);
/**
* Returns 0 if if this password/hash combination is valid
@@ -290,6 +296,9 @@ BOTAN_DLL int botan_pk_op_key_agreement_create(botan_pk_op_ka_t* op,
uint32_t flags);
BOTAN_DLL int botan_pk_op_key_agreement_destroy(botan_pk_op_ka_t op);
+BOTAN_DLL int botan_pk_op_key_agreement_export_public(botan_privkey_t key,
+ uint8_t out[], size_t* out_len);
+
BOTAN_DLL int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
uint8_t out[], size_t* out_len,
const uint8_t other_key[], size_t other_key_len,
diff --git a/src/python/botan.py b/src/python/botan.py
index 8414308ec..2957dce29 100755
--- a/src/python/botan.py
+++ b/src/python/botan.py
@@ -44,7 +44,7 @@ RNG
"""
class rng(object):
# Can also use type "system"
- def __init__(self, rng_type = 'user'):
+ def __init__(self, rng_type = 'system'):
botan.botan_rng_init.argtypes = [c_void_p, c_char_p]
self.rng = c_void_p(0)
rc = botan.botan_rng_init(byref(self.rng), rng_type)
@@ -155,12 +155,6 @@ class cipher(object):
botan.botan_cipher_destroy.argtypes = [c_void_p]
botan.botan_cipher_destroy(self.cipher)
- def tag_length(self):
- botan.botan_cipher_tag_length.argtypes = [c_void_p,POINTER(c_size_t)]
- l = c_size_t(0)
- botan.botan_cipher_tag_size(self.cipher, byref(l))
- return l.value
-
def default_nonce_length(self):
botan.botan_cipher_default_nonce_length.argtypes = [c_void_p, POINTER(c_size_t)]
l = c_size_t(0)
@@ -234,14 +228,19 @@ class cipher(object):
Bcrypt
TODO: might not be enabled - handle that gracefully!
"""
-def generate_bcrypt(passwd, rng, work_factor = 10):
- botan.botan_bcrypt_generate.argtypes = [POINTER(c_char), c_size_t, c_char_p, c_void_p, c_size_t]
- out = create_string_buffer(61)
- rc = botan.botan_bcrypt_generate(out, sizeof(out), passwd, rng.rng, c_size_t(work_factor))
-
+def bcrypt(passwd, rng, work_factor = 10):
+ botan.botan_bcrypt_generate.argtypes = [POINTER(c_char), POINTER(c_size_t),
+ c_char_p, c_void_p, c_size_t, c_uint32]
+ out_len = c_size_t(64)
+ out = create_string_buffer(out_len.value)
+ flags = c_uint32(0)
+ rc = botan.botan_bcrypt_generate(out, byref(out_len), passwd, rng.rng, c_size_t(work_factor), flags)
if rc != 0:
raise Exception('botan bcrypt failed, error %s' % (rc))
- return str(out.raw)
+ b = out.raw[0:out_len.value]
+ if b[-1] == '\x00':
+ b = b[:-1]
+ return b
def check_bcrypt(passwd, bcrypt):
rc = botan.botan_bcrypt_is_valid(passwd, bcrypt)
@@ -250,17 +249,16 @@ def check_bcrypt(passwd, bcrypt):
"""
PBKDF
"""
-def pbkdf(algo, password, out_len, iterations, salt):
+def pbkdf(algo, password, out_len, iterations = 10000, salt = rng().get(12)):
botan.botan_pbkdf.argtypes = [c_char_p, POINTER(c_char), c_size_t, c_char_p, c_void_p, c_size_t, c_size_t]
out_buf = create_string_buffer(out_len)
botan.botan_pbkdf(algo, out_buf, out_len, password, salt, len(salt), iterations)
- return out_buf.raw
+ return (salt,iterations,out_buf.raw)
-def pbkdf_timed(algo, password, out_len, rng, ms_to_run, salt_len = 12):
+def pbkdf_timed(algo, password, out_len, ms_to_run = 300, salt = rng().get(12))
botan.botan_pbkdf_timed.argtypes = [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)]
out_buf = create_string_buffer(out_len)
- salt = rng.get(salt_len)
iterations = c_size_t(0)
botan.botan_pbkdf_timed(algo, out_buf, out_len, password, salt, len(salt), ms_to_run, byref(iterations))
return (salt,iterations.value,out_buf.raw)
@@ -434,10 +432,48 @@ class pk_op_verify(object):
return True
return False
+class pk_op_key_agreement(object):
+ def __init__(self, key, kdf):
+ botan.botan_pk_op_key_agreement_create.argtypes = [c_void_p, c_void_p, c_char_p, c_uint32]
+ botan.botan_pk_op_key_agreement_export_public.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ self.op = c_void_p(0)
+ flags = 0 # always zero in this ABI
+ botan.botan_pk_op_key_agreement_create(byref(self.op), key.privkey, kdf, flags)
+ if not self.op:
+ raise Exception("No key agreement for you")
+
+ pub = create_string_buffer(4096)
+ pub_len = c_size_t(len(pub))
+ botan.botan_pk_op_key_agreement_export_public(key.privkey, pub, byref(pub_len))
+ self.m_public_value = pub.raw[0:pub_len.value]
+
+ def __del__(self):
+ botan.botan_pk_op_key_agreement_destroy.argtypes = [c_void_p]
+ botan.botan_pk_op_key_agreement_destroy(self.op)
+
+ def public_value(self):
+ return self.m_public_value
+
+ def agree(self, other, key_len, salt):
+ botan.botan_pk_op_key_agreement.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t),
+ POINTER(c_char), c_size_t, POINTER(c_char), c_size_t]
+
+ outbuf_sz = c_size_t(key_len)
+ outbuf = create_string_buffer(outbuf_sz.value)
+ rc = botan.botan_pk_op_key_agreement(self.op, outbuf, byref(outbuf_sz), other, len(other), salt, len(salt))
+
+ if rc == -1 and outbuf_sz.value > len(outbuf):
+ outbuf = create_string_buffer(outbuf_sz.value)
+ botan.botan_pk_op_key_agreement(self.op, outbuf, byref(outbuf_sz), other, len(other), salt, len(salt))
+ return outbuf.raw[0:outbuf_sz.value]
+
"""
Tests and examples
"""
def test():
+ r = rng("user")
+
+
print version_string()
print version_major(), version_minor(), version_patch()
@@ -447,7 +483,6 @@ def test():
print pbkdf('PBKDF2(SHA-1)', '', 32, 10000, '0001020304050607'.decode('hex')).encode('hex').upper()
print '59B2B1143B4CB1059EC58D9722FB1C72471E0D85C6F7543BA5228526375B0127'
- r = rng("user")
(salt,iterations,psk) = pbkdf_timed('PBKDF2(SHA-256)', 'xyz', 32, r, 200, 12)
print salt.encode('hex'), iterations
print 'x', psk.encode('hex')
@@ -483,8 +518,8 @@ def test():
signer = pk_op_sign(rsapriv, 'EMSA4(SHA-384)')
- signer.update('mess')
- signer.update('age')
+ signer.update('messa')
+ signer.update('ge')
sig = signer.finish(r)
r.reseed(200)
@@ -494,14 +529,34 @@ def test():
verify.update('mess')
verify.update('age')
- print "correct sig accepted?", verify.check_signature(sig)
+ print "good sig accepted?", verify.check_signature(sig)
verify.update('mess of things')
verify.update('age')
print "bad sig accepted?", verify.check_signature(sig)
- key = private_key('ecdsa', 'secp256r1', r)
- blob = key.export()
+ verify.update('message')
+ print "good sig accepted?", verify.check_signature(sig)
+
+ dh_grp = 'secp256r1'
+ #dh_grp = 'curve25519'
+ dh_kdf = 'KDF2(SHA-384)'
+ a_dh_priv = private_key('ecdh', dh_grp, r)
+ a_dh_pub = a_dh_priv.get_public_key()
+
+ b_dh_priv = private_key('ecdh', dh_grp, r)
+ b_dh_pub = b_dh_priv.get_public_key()
+
+ a_dh = pk_op_key_agreement(a_dh_priv, dh_kdf)
+ b_dh = pk_op_key_agreement(b_dh_priv, dh_kdf)
+
+ print "dh pubs", a_dh.public_value().encode('hex'), b_dh.public_value().encode('hex')
+
+ a_key = a_dh.agree(b_dh.public_value(), 20, 'salt')
+ b_key = b_dh.agree(a_dh.public_value(), 20, 'salt')
+
+ print "dh shared", a_key.encode('hex'), b_key.encode('hex')
+
#f = open('key.ber','wb')
#f.write(blob)