diff options
author | Jack Lloyd <[email protected]> | 2015-10-01 23:46:00 -0400 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2015-10-01 23:46:00 -0400 |
commit | 7612e065a76501f7888f62edd10e061bd9e71e2f (patch) | |
tree | 35f1966ae1acd5401d1e4950be755bb8d182c282 /src/lib/ffi | |
parent | 7bbee7e62e65d5de1d46b912b73440070feab0ff (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.cpp | 134 | ||||
-rw-r--r-- | src/lib/ffi/ffi.h | 107 | ||||
-rw-r--r-- | src/lib/ffi/info.txt | 3 |
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> |