aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/ffi
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2015-10-01 23:46:00 -0400
committerJack Lloyd <[email protected]>2015-10-01 23:46:00 -0400
commit7612e065a76501f7888f62edd10e061bd9e71e2f (patch)
tree35f1966ae1acd5401d1e4950be755bb8d182c282 /src/lib/ffi
parent7bbee7e62e65d5de1d46b912b73440070feab0ff (diff)
Add McEliece keygen and MCEIES to C89 API. Plus random fiddling
Diffstat (limited to 'src/lib/ffi')
-rw-r--r--src/lib/ffi/ffi.cpp134
-rw-r--r--src/lib/ffi/ffi.h107
-rw-r--r--src/lib/ffi/info.txt3
3 files changed, 212 insertions, 32 deletions
diff --git a/src/lib/ffi/ffi.cpp b/src/lib/ffi/ffi.cpp
index 608bd291b..27dcc6015 100644
--- a/src/lib/ffi/ffi.cpp
+++ b/src/lib/ffi/ffi.cpp
@@ -20,6 +20,8 @@
#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>
@@ -39,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
@@ -72,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)
{
@@ -108,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>
@@ -164,6 +185,7 @@ BOTAN_FFI_DECLARE_STRUCT(botan_pk_op_verify_struct, Botan::PK_Verifier, 0x2B91F9
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
@@ -185,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)
@@ -681,10 +703,12 @@ int botan_bcrypt_is_valid(const char* pass, const char* hash)
{
try
{
- #define BOTAN_
+#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)
{
@@ -714,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)
@@ -740,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)
@@ -750,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
@@ -1250,8 +1303,7 @@ 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)
{
- *key = nullptr;
- return -1;
+ 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()); });
}
@@ -1284,5 +1336,73 @@ int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int key_usage
});
}
+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 1402ec129..18a41938b 100644
--- a/src/lib/ffi/ffi.h
+++ b/src/lib/ffi/ffi.h
@@ -13,10 +13,14 @@ extern "C" {
#endif
/*
-This header exports some of botan's functionality via a C89 interface. 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:
+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.
@@ -24,20 +28,25 @@ others, so to make things easy this API follows a few simple rules:
- All functions return an int error code (except the version calls, which are
assumed to always have something to say).
-- No ownership of memory transfers across the API boundary. The API will write
- to buffers provided by the caller, or return opaque pointers which may not be
- dereferenced.
+- 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 it is insufficient, an
- error is returned. So passing nullptr/0
+ 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.
-This API is uesd by the Python and OCaml bindings via those languages respective
-ctypes libraries.
+ 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. However the goal is to provide a long term API
-usable for language bindings, or for use by systems written in C. Suggestions on
+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:
@@ -68,6 +77,7 @@ BOTAN_DLL uint32_t botan_version_datestamp();
*
* 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.
@@ -77,14 +87,26 @@ int botan_make_error(const char* msg, const char* func, int line);
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)
@@ -93,7 +115,7 @@ int botan_make_error(const char* msg, const char* func, int line);
//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);
@@ -271,7 +293,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;
@@ -406,6 +429,26 @@ BOTAN_DLL int botan_pk_op_key_agreement(botan_pk_op_ka_t op,
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);
@@ -439,7 +482,6 @@ 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);
@@ -469,17 +511,29 @@ BOTAN_DLL int botan_x509_cert_allowed_usage(botan_x509_cert_t cert, unsigned int
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
+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,
@@ -497,6 +551,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);
diff --git a/src/lib/ffi/info.txt b/src/lib/ffi/info.txt
index 52885e8e1..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
@@ -7,6 +7,7 @@ kdf
pbkdf
pubkey
x509
+#tls
auto_rng
system_rng
</requires>