aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-10-04 19:14:37 -0400
committerJack Lloyd <[email protected]>2015-10-04 19:14:37 -0400
commitd96833adc142c647aca4949f6f897b99480a2d79 (patch)
tree46f2c1d0ec248d00649d0c4c9c8daea51c518fdc /src
parenta5097d3ab26c61c1a44cc72cb105faaca91c7746 (diff)
parent6ab96139fa5bce258972bb3678e4c106c0bfe5bd (diff)
Merge pull request #292 from randombit/ffi-certs
Expose X.509 certificates and McEliece to C89/Python
Diffstat (limited to 'src')
-rw-r--r--src/lib/cert/x509/key_constraint.h1
-rw-r--r--src/lib/ffi/ffi.cpp283
-rw-r--r--src/lib/ffi/ffi.h204
-rw-r--r--src/lib/ffi/info.txt4
-rwxr-xr-xsrc/python/botan.py246
-rw-r--r--src/tests/test_ffi.cpp2
-rw-r--r--src/tests/test_mceliece.cpp2
7 files changed, 650 insertions, 92 deletions
diff --git a/src/lib/cert/x509/key_constraint.h b/src/lib/cert/x509/key_constraint.h
index 22ae7a32e..3509b6868 100644
--- a/src/lib/cert/x509/key_constraint.h
+++ b/src/lib/cert/x509/key_constraint.h
@@ -14,6 +14,7 @@ namespace Botan {
/**
* X.509v3 Key Constraints.
+* If updating update copy in ffi.h
*/
enum Key_Constraints {
NO_CONSTRAINTS = 0,
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 606415575..27dcc6015 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -13,11 +13,15 @@
#include <botan/pbkdf.h>
#include <botan/version.h>
#include <botan/pkcs8.h>
+#include <botan/x509cert.h>
+#include <botan/data_src.h>
#include <botan/pubkey.h>
#include <botan/data_src.h>
#include <botan/hex.h>
#include <botan/mem_ops.h>
#include <botan/x509_key.h>
+#include <botan/tls_client.h>
+#include <botan/tls_server.h>
#include <cstring>
#include <memory>
@@ -37,6 +41,15 @@
#include <botan/curve25519.h>
#endif
+#if defined(BOTAN_HAS_MCELIECE)
+ #include <botan/mceliece.h>
+#endif
+
+#if defined(BOTAN_HAS_MCEIES)
+ #include <botan/mceies.h>
+#endif
+
+
#if defined(BOTAN_HAS_BCRYPT)
#include <botan/bcrypt.h>
#endif
@@ -70,6 +83,12 @@ void log_exception(const char* func_name, const char* what)
fprintf(stderr, "%s: %s\n", func_name, what);
}
+int ffi_error_exception_thrown(const char* exn)
+ {
+ printf("exception %s\n", exn);
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
+ }
+
template<typename T, uint32_t M>
T& safe_get(botan_struct<T,M>* p)
{
@@ -106,15 +125,19 @@ int apply_fn(botan_struct<T, M>* o, const char* func_name, F func)
inline 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_len;
+
if(avail >= buf_len)
{
Botan::copy_mem(out, buf, buf_len);
return 0;
}
- return -1;
+ else
+ {
+ Botan::clear_mem(out, avail);
+ return BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE;
+ }
}
template<typename Alloc>
@@ -161,12 +184,15 @@ BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_sign_struct, Botan::PK_Signer, 0x1AF0C39F);
BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_verify_struct, Botan::PK_Verifier, 0x2B91F936);
BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_ka_struct, Botan::PK_Key_Agreement, 0x2939CAB1);
+BOTAN_FFI_DECLARE_STRUCT(botan_x509_cert_struct, Botan::X509_Certificate, 0x8F628937);
+BOTAN_FFI_DECLARE_STRUCT(botan_tls_channel_struct, Botan::TLS::Channel, 0x0212FE99);
+
/*
* Versioning
*/
uint32_t botan_ffi_api_version()
{
- return 20150210; // should match value in info.txt
+ return BOTAN_HAS_FFI;
}
const char* botan_version_string()
@@ -181,7 +207,7 @@ uint32_t botan_version_datestamp() { return Botan::version_datestamp(); }
int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len)
{
- return Botan::same_mem(x, y, len) ? 0 : 1;
+ return Botan::same_mem(x, y, len) ? 0 : -1;
}
int botan_hex_encode(const uint8_t* in, size_t len, char* out, uint32_t flags)
@@ -636,7 +662,6 @@ int botan_kdf(const char* kdf_algo,
return -1;
}
-#if defined(BOTAN_HAS_BCRYPT)
int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
const char* pass,
botan_rng_t rng_obj, size_t wf,
@@ -654,9 +679,13 @@ int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
if(wf < 2 || wf > 30)
throw std::runtime_error("Bad bcrypt work factor " + std::to_string(wf));
+#if defined(BOTAN_HAS_BCRYPT)
Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
const std::string bcrypt = Botan::generate_bcrypt(pass, rng, wf);
return write_str_output(out, out_len, bcrypt);
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
}
catch(std::exception& e)
{
@@ -674,9 +703,12 @@ int botan_bcrypt_is_valid(const char* pass, const char* hash)
{
try
{
+#if defined(BOTAN_HAS_BCRYPT)
if(Botan::check_bcrypt(pass, hash))
return 0; // success
- return 1;
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
}
catch(std::exception& e)
{
@@ -690,8 +722,6 @@ int botan_bcrypt_is_valid(const char* pass, const char* hash)
return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
-#endif
-
int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n_bits)
{
try
@@ -708,6 +738,8 @@ int botan_privkey_create_rsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, size
std::unique_ptr<Botan::Private_Key> key(new Botan::RSA_PrivateKey(rng, n_bits));
*key_obj = new botan_privkey_struct(key.release());
return 0;
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}
catch(std::exception& e)
@@ -734,6 +766,8 @@ int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, co
std::unique_ptr<Botan::Private_Key> key(new Botan::ECDSA_PrivateKey(rng, grp));
*key_obj = new botan_privkey_struct(key.release());
return 0;
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
#endif
}
catch(std::exception& e)
@@ -744,6 +778,31 @@ int botan_privkey_create_ecdsa(botan_privkey_t* key_obj, botan_rng_t rng_obj, co
return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
}
+int botan_privkey_create_mceliece(botan_privkey_t* key_obj, botan_rng_t rng_obj, size_t n, size_t t)
+ {
+ try
+ {
+ if(key_obj == nullptr || rng_obj == nullptr || n == 0 || t == 0)
+ return -1;
+
+ *key_obj = nullptr;
+
+#if defined(BOTAN_HAS_MCELIECE)
+ Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
+ std::unique_ptr<Botan::Private_Key> key(new Botan::McEliece_PrivateKey(rng, n, t));
+ *key_obj = new botan_privkey_struct(key.release());
+ return 0;
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ return BOTAN_FFI_ERROR_EXCEPTION_THROWN;
+ }
+ }
+
int botan_privkey_create_ecdh(botan_privkey_t* key_obj, botan_rng_t rng_obj, const char* param_str)
{
try
@@ -1137,5 +1196,213 @@ int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
});
}
+int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* cert_path)
+ {
+ try
+ {
+ if(!cert_obj || !cert_path)
+ return -1;
+
+ std::unique_ptr<Botan::X509_Certificate> c(new Botan::X509_Certificate(cert_path));
+
+ if(c)
+ {
+ *cert_obj = new botan_x509_cert_struct(c.release());
+ return 0;
+ }
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ }
+ catch(...)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
+ }
+
+ return -2;
+ }
+
+int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert_bits[], size_t cert_bits_len)
+ {
+ try
+ {
+ if(!cert_obj || !cert_bits)
+ return -1;
+
+ Botan::DataSource_Memory bits(cert_bits, cert_bits_len);
+
+ std::unique_ptr<Botan::X509_Certificate> c(new Botan::X509_Certificate(bits));
+
+ if(c)
+ {
+ *cert_obj = new botan_x509_cert_struct(c.release());
+ return 0;
+ }
+ }
+ catch(std::exception& e)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, e.what());
+ }
+ catch(...)
+ {
+ log_exception(BOTAN_CURRENT_FUNCTION, "unknown");
+ }
+
+ return -2;
+
+ }
+
+int botan_x509_cert_destroy(botan_x509_cert_t cert)
+ {
+ delete cert;
+ return 0;
+ }
+
+int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_str_output(out, out_len, cert.start_time()); });
+ }
+
+int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_str_output(out, out_len, cert.end_time()); });
+ }
+
+int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_vec_output(out, out_len, cert.serial_number()); });
+ }
+
+int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_str_output(out, out_len, cert.fingerprint(hash)); });
+ }
+
+int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_vec_output(out, out_len, cert.authority_key_id()); });
+ }
+
+int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_vec_output(out, out_len, cert.subject_key_id()); });
+ }
+
+int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert, uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_vec_output(out, out_len, cert.subject_public_key_bits()); });
+ }
+
+
+/*
+int botan_x509_cert_path_verify(botan_x509_cert_t cert, const char* dir)
+{
+}
+*/
+
+int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key)
+ {
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+ //return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_vec_output(out, out_len, cert.subject_public_key_bits()); });
+ }
+
+int botan_x509_cert_get_issuer_dn(botan_x509_cert_t cert,
+ const char* key, size_t index,
+ uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_str_output(out, out_len, cert.issuer_info(key).at(index)); });
+ }
+
+int botan_x509_cert_get_subject_dn(botan_x509_cert_t cert,
+ const char* key, size_t index,
+ uint8_t out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_str_output(out, out_len, cert.subject_info(key).at(index)); });
+ }
+
+int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, { return write_str_output(out, out_len, cert.to_string()); });
+ }
+
+int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage)
+ {
+ return BOTAN_FFI_DO(Botan::X509_Certificate, cert, {
+ const Botan::Key_Constraints k = static_cast<Botan::Key_Constraints>(key_usage);
+ if(cert.allowed_usage(k))
+ return 0;
+ return 1;
+ });
+ }
+
+int botan_mceies_decrypt(botan_privkey_t mce_key_obj,
+ const char* aead,
+ const uint8_t ct[], size_t ct_len,
+ const uint8_t ad[], size_t ad_len,
+ uint8_t out[], size_t* out_len)
+ {
+ try
+ {
+ Botan::Private_Key& key = safe_get(mce_key_obj);
+
+#if defined(BOTAN_HAS_MCELIECE) && defined(BOTAN_HAS_MCEIES)
+ Botan::McEliece_PrivateKey* mce = dynamic_cast<Botan::McEliece_PrivateKey*>(&key);
+ if(!mce)
+ return -2;
+
+ const Botan::secure_vector<uint8_t> pt = mceies_decrypt(*mce, ct, ct_len, ad, ad_len, aead);
+ return write_vec_output(out, out_len, pt);
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+ catch(std::exception& e)
+ {
+ return ffi_error_exception_thrown(e.what());
+ }
+ }
+
+int botan_mceies_encrypt(botan_pubkey_t mce_key_obj,
+ botan_rng_t rng_obj,
+ const char* aead,
+ const uint8_t pt[], size_t pt_len,
+ const uint8_t ad[], size_t ad_len,
+ uint8_t out[], size_t* out_len)
+ {
+ try
+ {
+ Botan::Public_Key& key = safe_get(mce_key_obj);
+ Botan::RandomNumberGenerator& rng = safe_get(rng_obj);
+
+#if defined(BOTAN_HAS_MCELIECE) && defined(BOTAN_HAS_MCEIES)
+ Botan::McEliece_PublicKey* mce = dynamic_cast<Botan::McEliece_PublicKey*>(&key);
+ if(!mce)
+ return -2;
+
+ Botan::secure_vector<uint8_t> ct = mceies_encrypt(*mce, pt, pt_len, ad, ad_len, rng, aead);
+ return write_vec_output(out, out_len, ct);
+#else
+ return BOTAN_FFI_ERROR_NOT_IMPLEMENTED;
+#endif
+ }
+ catch(std::exception& e)
+ {
+ return ffi_error_exception_thrown(e.what());
+ }
+ }
+
+/*
+int botan_tls_channel_init_client(botan_tls_channel_t* channel,
+ botan_tls_channel_output_fn output_fn,
+ botan_tls_channel_data_cb data_cb,
+ botan_tls_channel_alert_cb alert_cb,
+ botan_tls_channel_session_established session_cb,
+ const char* server_name)
+ {
+
+ }
+*/
+
}
diff --git a/src/lib/ffi/ffi.h b/src/lib/ffi/ffi.h
index a516529b4..ce2253725 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -1,4 +1,5 @@
/*
+* FFI (C89 API)
* (C) 2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
@@ -11,19 +12,55 @@
extern "C" {
#endif
-#include <botan/build.h>
-#include <stdint.h>
-#include <stddef.h>
-
/*
+This header exports some of botan's functionality via a C89
+interface. This API is uesd by the Python and OCaml bindings via those
+languages respective ctypes libraries.
+
+The API is intended to be as easy as possible to call from other
+languages, which often have easy ways to call C, because C. But some C
+code is easier to deal with than others, so to make things easy this
+API follows a few simple rules:
+
+- All interactions are via pointers to opaque structs. No need to worry about
+ structure padding issues and the like.
+
+- All functions return an int error code (except the version calls, which are
+ assumed to always have something to say).
+
+- Use simple types: size_t for lengths, const char* NULL terminated strings,
+ uint8_t for binary.
+
+- No ownership of memory transfers across the API boundary. The API will
+ consume data from const pointers, and will produce output by writing to
+ variables provided by the caller.
+
+- If exporting a value (a string or a blob) the function takes a pointer to the
+ output array and a read/write pointer to the length. If the length is insufficient, an
+ error is returned. So passing nullptr/0 allows querying the final value.
+
+ Note this does not apply to all functions, like `botan_hash_final`
+ which is not idempotent and are documented specially. But it's a
+ general theory of operation.
+
+The API is not currently documented, nor should it be considered
+stable. It is buggy as heck, most likely, and error handling is a
+mess. However the goal is to provide a long term API usable for
+language bindings, or for use by systems written in C. Suggestions on
+how to provide the cleanest API for such users would be most welcome.
+
* TODO:
* - Better error reporting
-* - User callback for exception logging
+* - User callback for exception logging?
* - Doxygen comments for all functions/params
* - X.509 certs and PKIX path validation goo
* - TLS
*/
+#include <botan/build.h>
+#include <stdint.h>
+#include <stddef.h>
+
/*
* Versioning
*/
@@ -37,22 +74,57 @@ BOTAN_DLL uint32_t botan_version_datestamp();
/*
* Error handling
+*
+* Some way of exporting these values to other languages would be useful
+
+
+ THIS FUNCTION ASSUMES BOTH ARGUMENTS ARE LITERAL STRINGS
+ so it retains only the pointers and does not make a copy.
+
+int botan_make_error(const char* msg, const char* func, int line);
+* This value is returned to callers ^^
+
+ normally called like
+ return botan_make_error(BOTAN_ERROR_STRING_NOT_IMPLEMENTED, BOTAN_FUNCTION, __LINE__);
+
+// This would seem to require both saving the message permanently
+catch(std::exception& e) {
+return botan_make_error_from_transient_string(e.what(), BOTAN_FUNCTION, __LINE__);
+}
+
+#define botan_make_error_inf(s) return botan_make_error(s, BOTAN_FUNCTION, __LINE__);
+
+Easier to return a const char* from each function directly? However,
+
+catch(std::exception& e) { return e.what(); }
+
+doesn't exactly work well either!
+
+*
+* Later call:
+* const char* botan_get_error_str(int);
+* To recover the msg, func, and line
+
*/
+#define BOTAN_FFI_ERROR_INSUFFICIENT_BUFFER_SPACE (-10)
#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)
+#define BOTAN_FFI_ERROR_NOT_IMPLEMENTED (-40)
//const char* botan_error_description(int err);
/*
-* Utility
+* Returns 0 if x[0..len] == y[0..len], or otherwise -1
*/
BOTAN_DLL int botan_same_mem(const uint8_t* x, const uint8_t* y, size_t len);
#define BOTAN_FFI_HEX_LOWER_CASE 1
BOTAN_DLL int botan_hex_encode(const uint8_t* x, size_t len, char* out, uint32_t flags);
+// TODO: botan_hex_decode
+// TODO: botan_base64_encode
+// TODO: botan_base64_decode
/*
* RNG
@@ -197,11 +269,11 @@ BOTAN_DLL int botan_kdf(const char* kdf_algo,
/*
* Bcrypt
+* *out_len should be 64 bytes
+* Output is formatted bcrypt $2a$...
*/
-#if defined(BOTAN_HAS_BCRYPT)
-
BOTAN_DLL int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
- const char* pass,
+ const char* password,
botan_rng_t rng,
size_t work_factor,
uint32_t flags);
@@ -213,8 +285,6 @@ BOTAN_DLL int botan_bcrypt_generate(uint8_t* out, size_t* out_len,
*/
BOTAN_DLL int botan_bcrypt_is_valid(const char* pass, const char* hash);
-#endif
-
/*
* Public/private key creation, import, ...
*/
@@ -225,7 +295,8 @@ BOTAN_DLL int botan_privkey_create_rsa(botan_privkey_t* key, botan_rng_t rng, si
//BOTAN_DLL int botan_privkey_create_dh(botan_privkey_t* key, botan_rng_t rng, size_t p_bits);
BOTAN_DLL int botan_privkey_create_ecdsa(botan_privkey_t* key, botan_rng_t rng, const char* params);
BOTAN_DLL int botan_privkey_create_ecdh(botan_privkey_t* key, botan_rng_t rng, const char* params);
-//BOTAN_DLL int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t);
+BOTAN_DLL int botan_privkey_create_mceliece(botan_privkey_t* key, botan_rng_t rng, size_t n, size_t t);
+
/*
* Input currently assumed to be PKCS #8 structure;
@@ -359,6 +430,82 @@ BOTAN_DLL int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
const uint8_t other_key[], size_t other_key_len,
const uint8_t salt[], size_t salt_len);
+
+/*
+*
+* @param mce_key must be a McEliece key
+* ct_len should be pt_len + n/8 + a few?
+*/
+BOTAN_DLL int botan_mceies_encrypt(botan_pubkey_t mce_key,
+ botan_rng_t rng,
+ const char* aead,
+ const uint8_t pt[], size_t pt_len,
+ const uint8_t ad[], size_t ad_len,
+ uint8_t ct[], size_t* ct_len);
+
+BOTAN_DLL int botan_mceies_decrypt(botan_privkey_t mce_key,
+ const char* aead,
+ const uint8_t ct[], size_t ct_len,
+ const uint8_t ad[], size_t ad_len,
+ uint8_t pt[], size_t* pt_len);
+
+
+
+typedef struct botan_x509_cert_struct* botan_x509_cert_t;
+BOTAN_DLL int botan_x509_cert_load(botan_x509_cert_t* cert_obj, const uint8_t cert[], size_t cert_len);
+BOTAN_DLL int botan_x509_cert_load_file(botan_x509_cert_t* cert_obj, const char* filename);
+BOTAN_DLL int botan_x509_cert_destroy(botan_x509_cert_t cert);
+
+BOTAN_DLL int botan_x509_cert_gen_selfsigned(botan_x509_cert_t* cert,
+ botan_privkey_t key,
+ botan_rng_t rng,
+ const char* common_name,
+ const char* org_name);
+
+// TODO: return botan_time_struct instead
+BOTAN_DLL int botan_x509_cert_get_time_starts(botan_x509_cert_t cert, char out[], size_t* out_len);
+BOTAN_DLL int botan_x509_cert_get_time_expires(botan_x509_cert_t cert, char out[], size_t* out_len);
+
+BOTAN_DLL int botan_x509_cert_get_fingerprint(botan_x509_cert_t cert, const char* hash, uint8_t out[], size_t* out_len);
+
+BOTAN_DLL int botan_x509_cert_get_serial_number(botan_x509_cert_t cert, uint8_t out[], size_t* out_len);
+BOTAN_DLL int botan_x509_cert_get_authority_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len);
+BOTAN_DLL int botan_x509_cert_get_subject_key_id(botan_x509_cert_t cert, uint8_t out[], size_t* out_len);
+
+BOTAN_DLL int botan_x509_cert_path_verify(botan_x509_cert_t cert,
+ const char* ca_dir);
+
+BOTAN_DLL int botan_x509_cert_get_public_key_bits(botan_x509_cert_t cert,
+ uint8_t out[], size_t* out_len);
+
+BOTAN_DLL int botan_x509_cert_get_public_key(botan_x509_cert_t cert, botan_pubkey_t* key);
+
+BOTAN_DLL int botan_x509_cert_get_issuer_dn(botan_x509_cert_t cert,
+ const char* key, size_t index,
+ uint8_t out[], size_t* out_len);
+
+BOTAN_DLL int botan_x509_cert_get_subject_dn(botan_x509_cert_t cert,
+ const char* key, size_t index,
+ uint8_t out[], size_t* out_len);
+
+BOTAN_DLL int botan_x509_cert_to_string(botan_x509_cert_t cert, char out[], size_t* out_len);
+
+// Must match values of Key_Constraints in key_constraints.h
+enum botan_x509_cert_key_constraints {
+ 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
+};
+
+BOTAN_DLL int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage);
+
/*
* TLS (WIP)
*/
@@ -366,16 +513,29 @@ BOTAN_DLL int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
typedef struct botan_tls_session_struct* botan_tls_session_t;
-BOTAN_DLL int botan_tls_session_get_version(botan_tls_session_t* session, uint16_t* tls_version);
-BOTAN_DLL int botan_tls_session_get_ciphersuite(botan_tls_session_t* session, uint16_t* ciphersuite);
+BOTAN_DLL int botan_tls_session_decrypt(botan_tls_session_t* session,
+ const byte key[], size_t key_len,
+ const byte blob[], size_t blob_len);
+
+BOTAN_DLL int botan_tls_session_get_version(botan_tls_session_t session, uint16_t* tls_version);
+BOTAN_DLL int botan_tls_session_get_ciphersuite(botan_tls_session_t session, uint16_t* ciphersuite);
+BOTAN_DLL int botan_tls_session_encrypt(botan_tls_session_t session, botan_rng_t rng, byte key[], size_t* key_len);
+
+BOTAN_DLL int botan_tls_session_get_peer_certs(botan_tls_session_t session, botan_x509_cert_t certs[], size_t* cert_len);
+
// TODO: peer certs, validation, ...
typedef struct botan_tls_channel_struct* botan_tls_channel_t;
-typedef void (*botan_tls_channel_output_fn)(void*, const uint8_t*, size_t);
-typedef void (*botan_tls_channel_data_cb)(void*, const uint8_t*, size_t);
-typedef void (*botan_tls_channel_alert_cb)(void*, uint16_t, const char*);
-typedef void (*botan_tls_channel_session_established)(void*, botan_tls_session_t);
+typedef void (*botan_tls_channel_output_fn)(void* application_data, const uint8_t* data, size_t data_len);
+
+typedef void (*botan_tls_channel_data_cb)(void* application_data, const uint8_t* data, size_t data_len);
+
+typedef void (*botan_tls_channel_alert_cb)(void* application_data, uint16_t alert_code);
+
+typedef void (*botan_tls_channel_session_established)(void* application_data,
+ botan_tls_channel_t channel,
+ botan_tls_session_t session);
BOTAN_DLL int botan_tls_channel_init_client(botan_tls_channel_t* channel,
botan_tls_channel_output_fn output_fn,
@@ -393,6 +553,11 @@ BOTAN_DLL int botan_tls_channel_init_server(botan_tls_channel_t* channel,
BOTAN_DLL int botan_tls_channel_received_data(botan_tls_channel_t chan,
const uint8_t input[], size_t len);
+/**
+* Returns 0 for client, 1 for server, negative for error
+*/
+BOTAN_DLL int botan_tls_channel_type(botan_tls_channel_t chan);
+
BOTAN_DLL int botan_tls_channel_send(botan_tls_channel_t chan,
const uint8_t input[], size_t len);
@@ -401,7 +566,6 @@ BOTAN_DLL int botan_tls_channel_close(botan_tls_channel_t chan);
BOTAN_DLL int botan_tls_channel_destroy(botan_tls_channel_t chan);
#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/src/lib/ffi/info.txt b/src/lib/ffi/info.txt
index 94a804ba0..8d6c5237e 100644
--- a/src/lib/ffi/info.txt
+++ b/src/lib/ffi/info.txt
@@ -1,4 +1,4 @@
-define FFI 20150210
+define FFI 20151001
<requires>
aead
@@ -6,6 +6,8 @@ filters
kdf
pbkdf
pubkey
+x509
+#tls
auto_rng
system_rng
</requires>
diff --git a/src/python/botan.py b/src/python/botan.py
index a28f3ddb0..04e574746 100755
--- a/src/python/botan.py
+++ b/src/python/botan.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
"""
Python wrapper of the botan crypto library
@@ -29,6 +29,40 @@ botan_api_rev = botan.botan_ffi_api_version()
if botan_api_rev != expected_api_rev:
raise Exception("Bad botan API rev got %d expected %d" % (botan_api_rev, expected_api_rev))
+# Internal utilities
+def _call_fn_returning_string(guess, fn):
+
+ buf = create_string_buffer(guess)
+ buf_len = c_size_t(len(buf))
+
+ rc = fn(buf, byref(buf_len))
+ if rc < 0:
+ if buf_len.value > len(buf):
+ #print("Calling again with %d" % (buf_len.value))
+ return _call_fn_returning_string(buf_len.value, fn)
+ else:
+ raise Exception("Call failed: %d" % (rc))
+
+ assert buf_len.value <= len(buf)
+ return str(buf.raw[0:buf_len.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 < 0:
+ if buf_len.value > len(buf):
+ #print("Calling again with %d" % (buf_len.value))
+ return _call_fn_returning_vec(buf_len.value, fn)
+ else:
+ raise Exception("Call failed: %d" % (rc))
+
+ assert buf_len.value <= len(buf)
+ return buf.raw[0:buf_len.value]
+
+
"""
Versions
"""
@@ -57,7 +91,7 @@ class rng(object):
rc = botan.botan_rng_init(byref(self.rng), rng_type)
else:
rc = botan.botan_rng_init(byref(self.rng), rng_type.encode('ascii'))
-
+
if rc != 0 or self.rng is None:
raise Exception("No rng " + algo + " for you!")
@@ -256,7 +290,6 @@ class cipher(object):
"""
Bcrypt
-TODO: might not be enabled - handle that gracefully!
"""
def bcrypt(passwd, rng, work_factor = 10):
botan.botan_bcrypt_generate.argtypes = [POINTER(c_char), POINTER(c_size_t),
@@ -322,12 +355,17 @@ class public_key(object):
def algo_name(self):
botan.botan_pubkey_algo_name.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_string(32, lambda b,bl: botan.botan_pubkey_algo_name(self.pubkey, b, bl))
- buf = create_string_buffer(64)
- buf_len = c_size_t(len(buf))
- botan.botan_pubkey_algo_name(self.pubkey, buf, byref(buf_len))
- assert buf_len.value <= len(buf)
- return buf.raw[0:buf_len.value]
+ def encoding(self, pem = False):
+ botan.botan_pubkey_export.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t), c_uint32]
+
+ flag = 1 if pem else 0
+
+ if pem:
+ return _call_fn_returning_string(0, lambda b,bl: botan.botan_pubkey_export(self.pubkey, b, bl, 1))
+ else:
+ return _call_fn_returning_string(0, lambda b,bl: botan.botan_pubkey_export(self.pubkey, b, bl, 0))
def fingerprint(self, hash = 'SHA-256'):
botan.botan_pubkey_fingerprint.argtypes = [c_void_p, c_char_p,
@@ -338,7 +376,7 @@ class public_key(object):
buf_len = c_size_t(n)
if sys.version_info[0] > 2:
hash = hash.encode('utf-8')
-
+
botan.botan_pubkey_fingerprint(self.pubkey, hash, buf, byref(buf_len))
return hexlify(buf[0:buf_len.value])
@@ -347,6 +385,7 @@ class private_key(object):
botan.botan_privkey_create_rsa.argtypes = [c_void_p, c_void_p, c_size_t]
botan.botan_privkey_create_ecdsa.argtypes = [c_void_p, c_void_p, c_char_p]
botan.botan_privkey_create_ecdh.argtypes = [c_void_p, c_void_p, c_char_p]
+ botan.botan_privkey_create_mceliece.argtypes = [c_void_p, c_void_p, c_size_t, c_size_t]
self.privkey = c_void_p(0)
if alg == 'rsa':
@@ -355,6 +394,8 @@ class private_key(object):
botan.botan_privkey_create_ecdsa(byref(self.privkey), rng.rng, param)
elif alg == 'ecdh':
botan.botan_privkey_create_ecdh(byref(self.privkey), rng.rng, param)
+ elif alg in ['mce', 'mceliece']:
+ botan.botan_privkey_create_mceliece(byref(self.privkey), rng.rng, param[0], param[1])
else:
raise Exception('Unknown public key algo ' + alg)
@@ -385,7 +426,6 @@ class private_key(object):
botan.botan_privkey_export(self.privkey, buf, byref(buf_len))
return buf[0:buf_len.value]
-
class pk_op_encrypt(object):
def __init__(self, key, padding):
botan.botan_pk_op_encrypt_create.argtypes = [c_void_p, c_void_p, c_char_p, c_uint32]
@@ -417,7 +457,7 @@ class pk_op_encrypt(object):
#print("encrypt: outbuf_sz.value=%d" % outbuf_sz.value)
return outbuf.raw[0:outbuf_sz.value]
-
+
class pk_op_decrypt(object):
def __init__(self, key, padding):
botan.botan_pk_op_decrypt_create.argtypes = [c_void_p, c_void_p, c_char_p, c_uint32]
@@ -497,6 +537,24 @@ class pk_op_verify(object):
return True
return False
+"""
+MCEIES encryption
+Must be used with McEliece keys
+"""
+def mceies_encrypt(mce, rng, aead, pt, ad):
+ botan.botan_mceies_encrypt.argtypes = [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)]
+
+ return _call_fn_returning_string(0, lambda b,bl:
+ botan.botan_mceies_encrypt(mce.pubkey, rng.rng, aead, pt, len(pt), ad, len(ad), b, bl))
+
+def mceies_decrypt(mce, aead, pt, ad):
+ botan.botan_mceies_decrypt.argtypes = [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)]
+
+ return _call_fn_returning_string(0, lambda b,bl:
+ botan.botan_mceies_decrypt(mce.privkey, aead, pt, len(pt), ad, len(ad), b, bl))
+
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]
@@ -507,10 +565,7 @@ class pk_op_key_agreement(object):
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]
+ self.m_public_value = _call_fn_returning_string(0, lambda b, bl: botan.botan_pk_op_key_agreement_export_public(key.privkey, b, bl))
def __del__(self):
botan.botan_pk_op_key_agreement_destroy.argtypes = [c_void_p]
@@ -523,28 +578,73 @@ class pk_op_key_agreement(object):
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))
+ return _call_fn_returning_string(key_len,
+ lambda b,bl: botan.botan_pk_op_key_agreement(self.op, b, bl,
+ other, len(other),
+ salt, len(salt)))
+
+class x509_cert(object):
+ def __init__(self, filename):
+ botan.botan_x509_cert_load_file.argtypes = [POINTER(c_void_p), c_char_p]
+ self.x509_cert = c_void_p(0)
+ if sys.version_info[0] > 2:
+ filename = cast(filename, c_char_p)
+ botan.botan_x509_cert_load_file(byref(self.x509_cert), filename)
+
+ def __del__(self):
+ botan.botan_x509_cert_destroy.argtypes = [c_void_p]
+ botan.botan_x509_cert_destroy(self.x509_cert)
+
+ # TODO: have these convert to a python datetime
+ def time_starts(self):
+ botan.botan_x509_cert_get_time_starts.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_string(16, lambda b,bl: botan.botan_x509_cert_get_time_starts(self.x509_cert, b, bl))
+
+ def time_expires(self):
+ botan.botan_x509_cert_get_time_expires.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_string(16, lambda b,bl: botan.botan_x509_cert_get_time_expires(self.x509_cert, b, bl))
+
+ def to_string(self):
+ botan.botan_x509_cert_to_string.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_string(0, lambda b,bl: botan.botan_x509_cert_to_string(self.x509_cert, b, bl))
+
+ def fingerprint(self, hash_algo = 'SHA-256'):
+ botan.botan_x509_cert_get_fingerprint.argtypes = [c_void_p, c_char_p,
+ POINTER(c_char), POINTER(c_size_t)]
+
+ n = hash_function(hash_algo).output_length() * 3
+ if sys.version_info[0] > 2:
+ hash_algo = hash_algo.encode('utf-8')
+
+ return _call_fn_returning_string(n, lambda b,bl: botan.botan_x509_cert_get_fingerprint(self.x509_cert, hash_algo, b, bl))
+
+ def serial_number(self):
+ botan.botan_x509_cert_get_serial_number.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_vec(0, lambda b,bl: botan.botan_x509_cert_get_serial_number(self.x509_cert, b, bl))
+
+ def authority_key_id(self):
+ botan.botan_x509_cert_get_authority_key_id.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_vec(0, lambda b,bl: botan.botan_x509_cert_get_authority_key_id(self.x509_cert, b, bl))
+
+ def subject_key_id(self):
+ botan.botan_x509_cert_get_subject_key_id.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_vec(0, lambda b,bl: botan.botan_x509_cert_get_subject_key_id(self.x509_cert, b, bl))
+
+ def subject_public_key_bits(self):
+ botan.botan_x509_cert_get_public_key_bits.argtypes = [c_void_p, POINTER(c_char), POINTER(c_size_t)]
+ return _call_fn_returning_vec(0, lambda b,bl: botan.botan_x509_cert_get_public_key_bits(self.x509_cert, b, bl))
- 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")
+ r = rng("user")
print("\n%s" % version_string().decode('utf-8'))
print("v%d.%d.%d\n" % (version_major(), version_minor(), version_patch()))
-
print("KDF2(SHA-1) %s" %
hexlify(kdf('KDF2(SHA-1)'.encode('ascii'), unhexlify('701F3480DFE95F57941F804B1B2413EF'), 7,
unhexlify('55A4E9DD5F4CA2EF82'))
@@ -559,18 +659,12 @@ def test():
print("good output %s\n" %
'59B2B1143B4CB1059EC58D9722FB1C72471E0D85C6F7543BA5228526375B0127')
-
-
(salt,iterations,psk) = pbkdf_timed('PBKDF2(SHA-256)'.encode('ascii'),
'xyz'.encode('utf-8'), 32, 200)
- if sys.version_info[0] < 3:
- print("PBKDF2(SHA-256) x=timed, y=iterated; salt = %s (len=%d) #iterations = %d\n" %
- (hexlify(salt), len(salt), iterations) )
- else:
- print("PBKDF2(SHA-256) x=timed, y=iterated; salt = %s (len=%d) #iterations = %d\n" %
- (hexlify(salt).decode('ascii'), len(salt), iterations) )
-
+ print("PBKDF2(SHA-256) x=timed, y=iterated; salt = %s (len=%d) #iterations = %d\n" %
+ (hexlify(salt).decode('ascii'), len(salt), iterations))
+
print('x %s' % hexlify(psk).decode('utf-8'))
print('y %s\n' %
(hexlify(pbkdf('PBKDF2(SHA-256)'.encode('utf-8'),
@@ -579,7 +673,7 @@ def test():
hmac = message_authentication_code('HMAC(SHA-256)'.encode('ascii'))
hmac.set_key(unhexlify('0102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20'))
hmac.update(unhexlify('616263'))
-
+
hmac_output = hmac.final()
if hmac_output != unhexlify('A21B1F5D4CF4F73A4DD939750F7A066A7F98CC131CB16A6692759021CFAB8181'):
@@ -587,7 +681,7 @@ def test():
print("vs good: \tA21B1F5D4CF4F73A4DD939750F7A066A7F98CC131CB16A6692759021CFAB8181");
else:
print("HMAC output (good): %s\n" % hexlify(hmac_output).decode('utf-8'))
-
+
print("rng output:\n\t%s\n\t%s\n\t%s\n" %
(hexlify(r.get(42)).decode('utf-8'),
hexlify(r.get(13)).decode('utf-8'),
@@ -642,13 +736,31 @@ def test():
print("OCB pt %s %d" % (hexlify(pt).decode('utf-8'), len(pt)))
print("OCB de %s %d\n" % (hexlify(dec).decode('utf-8'), len(dec)))
+
+ mce_priv = private_key('mce', [2960,57], r)
+ mce_pub = mce_priv.get_public_key()
+
+ mce_plaintext = 'mce plaintext'
+ mce_ad = 'mce AD'
+ mce_ciphertext = mceies_encrypt(mce_pub, r, 'ChaCha20Poly1305', mce_plaintext, mce_ad)
+
+ print "mce", len(mce_plaintext), len(mce_ciphertext)
+
+ mce_decrypt = mceies_decrypt(mce_priv, 'ChaCha20Poly1305', mce_ciphertext, mce_ad)
+
+ print("mce_pub %s/SHA-1 fingerprint: %s (estimated strength %s) (len %d)" %
+ (mce_pub.algo_name().decode('utf-8'), mce_pub.fingerprint("SHA-1").decode('utf-8'),
+ mce_pub.estimated_strength(), len(mce_pub.encoding())
+ )
+ )
+
rsapriv = private_key('rsa', 1536, r)
rsapub = rsapriv.get_public_key()
-
- print("rsapub %s/SHA-1 fingerprint: %s (estimated strength %s)" %
+
+ print("rsapub %s SHA-1 fingerprint: %s estimated strength %d len %d" %
(rsapub.algo_name().decode('utf-8'), rsapub.fingerprint("SHA-1").decode('utf-8'),
- rsapub.estimated_strength()
+ rsapub.estimated_strength(), len(rsapub.encoding())
)
)
@@ -656,7 +768,7 @@ def test():
enc = pk_op_encrypt(rsapub, "EME1(SHA-256)".encode('utf-8'))
ctext = enc.encrypt('foof'.encode('utf-8'), r)
- print("ptext \'%s\'" % 'foof')
+ print("ptext \'%s\'" % 'foof')
print("ctext \'%s\'" % hexlify(ctext).decode('utf-8'))
print("decrypt \'%s\'\n" % dec.decrypt(ctext).decode('utf-8'))
@@ -669,7 +781,7 @@ def test():
r.reseed(200)
print("EMSA4(SHA-384) signature: %s" % hexlify(sig).decode('utf-8'))
-
+
verify = pk_op_verify(rsapub, 'EMSA4(SHA-384)'.encode('utf-8'))
verify.update('mess'.encode('utf-8'))
@@ -683,32 +795,44 @@ def test():
verify.update('message'.encode('utf-8'))
print("good sig accepted? %s\n" % verify.check_signature(sig))
- dh_grp = 'secp256r1'.encode('utf-8')
- #dh_grp = 'curve25519'.encode('utf-8')
- dh_kdf = 'KDF2(SHA-384)'.encode('utf-8')
- a_dh_priv = private_key('ecdh', dh_grp, r)
- a_dh_pub = a_dh_priv.get_public_key()
+ for dh_grps in ['secp256r1', 'curve25519']:
+ dh_grp = dh_grps.encode('utf-8')
+ dh_kdf = 'KDF2(SHA-384)'.encode('utf-8')
+ 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("ecdh %s pubs:\n %s\n %s\n" %
+ (dh_grps,
+ hexlify(a_dh.public_value()).decode('utf-8'),
+ hexlify(b_dh.public_value()).decode('utf-8')))
- b_dh_priv = private_key('ecdh', dh_grp, r)
- b_dh_pub = b_dh_priv.get_public_key()
+ a_key = a_dh.agree(b_dh.public_value(), 20, 'salt'.encode('utf-8'))
+ b_key = b_dh.agree(a_dh.public_value(), 20, 'salt'.encode('utf-8'))
- a_dh = pk_op_key_agreement(a_dh_priv, dh_kdf)
- b_dh = pk_op_key_agreement(b_dh_priv, dh_kdf)
+ print("ecdh %s shared:\n %s\n %s\n" %
+ (dh_grps, hexlify(a_key).decode('utf-8'), hexlify(b_key).decode('utf-8')))
- print("ecdh pubs:\n %s\n %s\n" %
- (hexlify(a_dh.public_value()).decode('utf-8'),
- hexlify(b_dh.public_value()).decode('utf-8')))
+ cert = x509_cert("src/tests/data/ecc/CSCA.CSCA.csca-germany.1.crt")
+ print(cert.fingerprint("SHA-1"))
+ print("32:42:1C:C3:EC:54:D7:E9:43:EC:51:F0:19:23:BD:85:1D:F2:1B:B9")
- a_key = a_dh.agree(b_dh.public_value(), 20, 'salt'.encode('utf-8'))
- b_key = b_dh.agree(a_dh.public_value(), 20, 'salt'.encode('utf-8'))
+ print(cert.time_starts())
+ print(cert.time_expires())
- print("ecdh shared:\n %s\n %s\n" %
- (hexlify(a_key).decode('utf-8'), hexlify(b_key).decode('utf-8')))
+ print(hexlify(cert.serial_number()))
+ print(hexlify(cert.authority_key_id()))
+ print(hexlify(cert.subject_key_id()))
+ print(hexlify(cert.subject_public_key_bits()))
+ print(cert.to_string())
- #f = open('key.ber','wb')
- #f.write(blob)
- #f.close()
+ return
def main(args = None):
diff --git a/src/tests/test_ffi.cpp b/src/tests/test_ffi.cpp
index 63f8a5b20..edc06f90a 100644
--- a/src/tests/test_ffi.cpp
+++ b/src/tests/test_ffi.cpp
@@ -193,7 +193,7 @@ TEST_CASE("FFI bcrypt", "[ffi]")
CHECK_THAT(botan_bcrypt_generate(outbuf.data(), &ol, "password", rng, 10, 0), Equals(0));
botan_rng_destroy(rng);
- CHECK_THAT(botan_bcrypt_is_valid("wrong", reinterpret_cast<const char*>(outbuf.data())), Equals(1));
+ REQUIRE(botan_bcrypt_is_valid("wrong", reinterpret_cast<const char*>(outbuf.data())) < 0);
CHECK_THAT(botan_bcrypt_is_valid("password", reinterpret_cast<const char*>(outbuf.data())), Equals(0));
}
diff --git a/src/tests/test_mceliece.cpp b/src/tests/test_mceliece.cpp
index 0ed62b5ea..fc20d93f7 100644
--- a/src/tests/test_mceliece.cpp
+++ b/src/tests/test_mceliece.cpp
@@ -180,7 +180,7 @@ size_t test_mceliece()
size_t code_length = params__n__t_min_max[i];
for(size_t t = params__n__t_min_max[i+1]; t <= params__n__t_min_max[i+2]; t++)
{
- std::cout << "testing parameters n = " << code_length << ", t = " << t << std::endl;
+ //std::cout << "testing parameters n = " << code_length << ", t = " << t << std::endl;
McEliece_PrivateKey sk1(rng, code_length, t);
const McEliece_PublicKey& pk1 = sk1;