From 212165500de3bdb8c1edd0254c971782bf83068a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 1 Feb 2018 17:04:58 -0500 Subject: [PATCH] more --- Makefile | 8 +-- include/llarp/crypto.h | 36 ++++++++----- include/llarp/crypto_async.h | 41 +++++++++++---- llarp/crypto_async.c | 99 +++++++++++++++++++++++++++++++----- llarp/crypto_libsodium.cpp | 14 +++-- llarp/ev.cpp | 1 + test/test_async_cipher.c | 83 ++++++++++++++++++++++++++++++ test/test_async_dh.c | 22 ++++---- 8 files changed, 253 insertions(+), 51 deletions(-) create mode 100644 test/test_async_cipher.c diff --git a/Makefile b/Makefile index 44827e742..bc0150fb3 100644 --- a/Makefile +++ b/Makefile @@ -52,19 +52,21 @@ all: build format: $(FORMAT) -style=Google -i $(HDRS) $(SRCS) -build: $(EXE) +build: shared $(EXE) test: $(TEST_OBJ_CPP) $(TEST_OBJ_C) +shared: $(SHARED_LIB) $(TEST_SRC): $(STATIC_LIB) -$(TEST_OBJ_CPP): $(TEST_SRC_CPP) + +$(REPO)/test/%.cpp.bin: $(REPO)/test/%.cpp $(CXX) $(REQUIRED_CXXFLAGS) $< -o $<.bin $(TEST_LDFLAGS) mv $<.bin $<.test $<.test -$(TEST_OBJ_C): $(TEST_SRC_C) +$(REPO)/test/%.c.bin: $(REPO)/test/%.c $(CC) $(REQUIRED_CFLAGS) $< -o $<.bin $(TEST_LDFLAGS) mv $<.bin $<.test $<.test diff --git a/include/llarp/crypto.h b/include/llarp/crypto.h index 5f1a7bf1e..e232faa85 100644 --- a/include/llarp/crypto.h +++ b/include/llarp/crypto.h @@ -8,41 +8,53 @@ extern "C" { #endif #define PUBKEYSIZE 32 -#define SECKEYSIZE 32 +#define SECKEYSIZE 64 #define NOUNCESIZE 24 #define SHAREDKEYSIZE 32 #define HASHSIZE 64 #define HMACSECSIZE 32 #define SIGSIZE 64 #define TUNNOUNCESIZE 32 +#define HMACSIZE 64 typedef uint8_t llarp_pubkey_t[PUBKEYSIZE]; typedef uint8_t llarp_seckey_t[SECKEYSIZE]; typedef uint8_t llarp_nounce_t[NOUNCESIZE]; typedef uint8_t llarp_sharedkey_t[SHAREDKEYSIZE]; typedef uint8_t llarp_hash_t[HASHSIZE]; +typedef uint8_t llarp_hmac_t[HMACSIZE]; typedef uint8_t llarp_hmacsec_t[HMACSECSIZE]; typedef uint8_t llarp_sig_t[SIGSIZE]; typedef uint8_t llarp_tunnel_nounce_t[TUNNOUNCESIZE]; -struct llarp_keypair { - llarp_pubkey_t pub; - llarp_seckey_t sec; -}; - +static inline uint8_t * llarp_seckey_topublic(llarp_seckey_t k) +{ + return k + 32; +} + typedef bool (*llarp_dh_func)(llarp_sharedkey_t *, llarp_pubkey_t, llarp_tunnel_nounce_t, llarp_seckey_t); +typedef bool (*llarp_sym_cipher_func)(llarp_buffer_t, llarp_sharedkey_t, llarp_nounce_t); + +typedef bool (*llarp_hash_func)(llarp_hash_t *, llarp_buffer_t); + +typedef bool (*llarp_hmac_func)(llarp_hmac_t *, llarp_buffer_t, llarp_hmacsec_t); + +typedef bool (*llarp_sign_func)(llarp_sig_t *, llarp_seckey_t, llarp_buffer_t); +typedef bool (*llarp_verify_func)(llarp_pubkey_t, llarp_buffer_t, llarp_sig_t); + struct llarp_crypto { - bool (*xchacha20)(llarp_buffer_t, llarp_sharedkey_t, llarp_nounce_t); + llarp_sym_cipher_func xchacha20; llarp_dh_func dh_client; llarp_dh_func dh_server; - bool (*hash)(llarp_hash_t *, llarp_buffer_t); - bool (*hmac)(llarp_hash_t *, llarp_buffer_t, llarp_hmacsec_t); - bool (*sign)(llarp_sig_t *, llarp_seckey_t, llarp_buffer_t); - bool (*verify)(llarp_pubkey_t, llarp_buffer_t, llarp_sig_t); + llarp_hash_func hash; + llarp_hmac_func hmac; + llarp_sign_func sign; + llarp_verify_func verify; void (*randomize)(llarp_buffer_t); - void (*keygen)(struct llarp_keypair *); + void (*randbytes)(void *, size_t); + void (*keygen)(llarp_seckey_t *); }; void llarp_crypto_libsodium_init(struct llarp_crypto *c); diff --git a/include/llarp/crypto_async.h b/include/llarp/crypto_async.h index 1290127b8..d5fa88845 100644 --- a/include/llarp/crypto_async.h +++ b/include/llarp/crypto_async.h @@ -10,33 +10,56 @@ extern "C" { struct llarp_async_dh; -struct llarp_async_dh *llarp_async_dh_new(struct llarp_crypto *crypto, - struct llarp_ev_loop *ev, - struct llarp_threadpool *tp); +struct llarp_async_dh *llarp_async_dh_new( + llarp_seckey_t ourkey, + struct llarp_crypto *crypto, + struct llarp_ev_loop *ev, + struct llarp_threadpool *tp); void llarp_async_dh_free(struct llarp_async_dh **dh); struct llarp_dh_result; typedef void (*llarp_dh_complete_hook)(struct llarp_dh_result *); -struct llarp_dh_internal; - struct llarp_dh_result { - struct llarp_dh_internal *impl; - llarp_sharedkey_t result; + llarp_sharedkey_t sharedkey; void *user; llarp_dh_complete_hook hook; }; -void llarp_async_client_dh(struct llarp_async_dh *dh, llarp_seckey_t ourkey, +void llarp_async_client_dh(struct llarp_async_dh *dh, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void *user); -void llarp_async_server_dh(struct llarp_async_dh *dh, llarp_seckey_t ourkey, + +void llarp_async_server_dh(struct llarp_async_dh *dh, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void *user); + + struct llarp_async_cipher; + struct llarp_cipher_result; + + typedef void (*llarp_cipher_complete_hook)(struct llarp_cipher_result*); + + struct llarp_cipher_result + { + llarp_buffer_t buff; + void * user; + llarp_cipher_complete_hook hook; + }; + + struct llarp_async_cipher * llarp_async_cipher_new( + llarp_sharedkey_t key, + struct llarp_crypto *crypto, + struct llarp_ev_loop *ev, + struct llarp_threadpool *tp); + + void llarp_async_cipher_free(struct llarp_async_cipher ** c); + + void llarp_async_cipher_queue_op(struct llarp_async_cipher * c, llarp_buffer_t * buff, llarp_nounce_t n, llarp_cipher_complete_hook h, void * user); + #ifdef __cplusplus } #endif diff --git a/llarp/crypto_async.c b/llarp/crypto_async.c index cac1958da..66d43cf9f 100644 --- a/llarp/crypto_async.c +++ b/llarp/crypto_async.c @@ -7,19 +7,20 @@ struct llarp_async_dh { llarp_dh_func server; struct llarp_threadpool *tp; struct llarp_ev_caller *caller; + llarp_seckey_t ourkey; }; struct llarp_dh_internal { - llarp_dh_func func; llarp_pubkey_t theirkey; - llarp_seckey_t ourkey; + uint8_t * ourkey; llarp_tunnel_nounce_t nounce; struct llarp_dh_result result; + llarp_dh_func func; }; static void llarp_crypto_dh_work(void *user) { struct llarp_dh_internal *impl = (struct llarp_dh_internal *)user; - impl->func(&impl->result.result, impl->theirkey, impl->nounce, impl->ourkey); + impl->func(&impl->result.sharedkey, impl->theirkey, impl->nounce, impl->ourkey); } static void llarp_crypto_dh_result(struct llarp_ev_async_call *call) { @@ -29,15 +30,14 @@ static void llarp_crypto_dh_result(struct llarp_ev_async_call *call) { } static void llarp_async_dh_exec(struct llarp_async_dh *dh, llarp_dh_func func, - llarp_seckey_t ourkey, llarp_pubkey_t theirkey, + llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void *user) { struct llarp_dh_internal *impl = - llarp_g_mem.alloc(sizeof(struct llarp_dh_internal), 16); + llarp_g_mem.alloc(sizeof(struct llarp_dh_internal), 32); memcpy(impl->theirkey, theirkey, sizeof(llarp_pubkey_t)); - memcpy(impl->ourkey, ourkey, sizeof(llarp_seckey_t)); memcpy(impl->nounce, nounce, sizeof(llarp_tunnel_nounce_t)); - impl->result.impl = impl; + impl->ourkey = dh->ourkey; impl->result.user = user; impl->result.hook = result; impl->func = func; @@ -48,27 +48,30 @@ static void llarp_async_dh_exec(struct llarp_async_dh *dh, llarp_dh_func func, llarp_threadpool_queue_job(dh->tp, job); } -void llarp_async_client_dh(struct llarp_async_dh *dh, llarp_seckey_t ourkey, +void llarp_async_client_dh(struct llarp_async_dh *dh, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void *user) { - llarp_async_dh_exec(dh, dh->client, ourkey, theirkey, nounce, result, user); + llarp_async_dh_exec(dh, dh->client, theirkey, nounce, result, user); } -void llarp_async_server_dh(struct llarp_async_dh *dh, llarp_seckey_t ourkey, +void llarp_async_server_dh(struct llarp_async_dh *dh, llarp_pubkey_t theirkey, llarp_tunnel_nounce_t nounce, llarp_dh_complete_hook result, void *user) { - llarp_async_dh_exec(dh, dh->server, ourkey, theirkey, nounce, result, user); + llarp_async_dh_exec(dh, dh->server, theirkey, nounce, result, user); } -struct llarp_async_dh *llarp_async_dh_new(struct llarp_crypto *crypto, - struct llarp_ev_loop *ev, - struct llarp_threadpool *tp) { +struct llarp_async_dh *llarp_async_dh_new( + llarp_seckey_t ourkey, + struct llarp_crypto *crypto, + struct llarp_ev_loop *ev, + struct llarp_threadpool *tp) { struct llarp_async_dh *dh = llarp_g_mem.alloc(sizeof(struct llarp_async_dh), 16); dh->client = crypto->dh_client; dh->server = crypto->dh_server; + memcpy(dh->ourkey, ourkey, sizeof(llarp_seckey_t)); dh->tp = tp; dh->caller = llarp_ev_prepare_async(ev, &llarp_crypto_dh_result); return dh; @@ -81,3 +84,71 @@ void llarp_async_dh_free(struct llarp_async_dh **dh) { *dh = NULL; } } + + +struct llarp_async_cipher_internal +{ + uint8_t * key; + llarp_nounce_t nounce; + struct llarp_cipher_result result; + llarp_sym_cipher_func func; +}; + +struct llarp_async_cipher +{ + llarp_sharedkey_t key; + struct llarp_threadpool *tp; + struct llarp_ev_caller *caller; + llarp_sym_cipher_func func; +}; + +static void llarp_crypto_cipher_result(struct llarp_ev_async_call * job) +{ + struct llarp_async_cipher_internal * impl = (struct llarp_async_cipher_internal *) job->user; + impl->result.hook(&impl->result); + llarp_g_mem.free(impl); +} + +static void llarp_crypto_cipher_work(void * work) +{ + struct llarp_async_cipher_internal * impl = (struct llarp_async_cipher_internal *) work; + impl->func(impl->result.buff, impl->key, impl->nounce); +} + +void llarp_async_cipher_queue_op(struct llarp_async_cipher * c, llarp_buffer_t * buff, llarp_nounce_t n, llarp_cipher_complete_hook h, void * user) +{ + struct llarp_async_cipher_internal * impl = llarp_g_mem.alloc(sizeof(struct llarp_async_cipher_internal), 16); + impl->key = c->key; + memcpy(impl->nounce, n, sizeof(llarp_nounce_t)); + impl->result.user = user; + impl->result.buff.base = buff->base; + impl->result.buff.sz = buff->sz; + impl->result.hook = h; + impl->func = c->func; + struct llarp_thread_job job = {.caller = c->caller, + .data = impl, + .user = impl, + .work = &llarp_crypto_cipher_work}; + llarp_threadpool_queue_job(c->tp, job); +} + +struct llarp_async_cipher * llarp_async_cipher_new(llarp_sharedkey_t key, + struct llarp_crypto * crypto, + struct llarp_ev_loop * ev, + struct llarp_threadpool *tp) +{ + struct llarp_async_cipher * cipher = llarp_g_mem.alloc(sizeof(struct llarp_async_cipher), 16); + cipher->func = crypto->xchacha20; + cipher->tp = tp; + cipher->caller = llarp_ev_prepare_async(ev, &llarp_crypto_cipher_result); + memcpy(cipher->key, key, sizeof(llarp_sharedkey_t)); + return cipher; +} + +void llarp_async_cipher_free(struct llarp_async_cipher **c) { + if (*c) { + llarp_ev_caller_stop((*c)->caller); + llarp_g_mem.free(*c); + *c = NULL; + } +} diff --git a/llarp/crypto_libsodium.cpp b/llarp/crypto_libsodium.cpp index 28025dffe..540a984c0 100644 --- a/llarp/crypto_libsodium.cpp +++ b/llarp/crypto_libsodium.cpp @@ -73,10 +73,15 @@ static void randomize(llarp_buffer_t buff) { randombytes((unsigned char *)buff.base, buff.sz); } -static void keygen(struct llarp_keypair *keys) { - randombytes(keys->sec, sizeof(llarp_seckey_t)); - unsigned char sk[64]; - crypto_sign_seed_keypair(keys->pub, sk, keys->sec); +static inline void randbytes(void * ptr, size_t sz) +{ + randombytes((unsigned char*)ptr, sz); +} + +static void keygen(llarp_seckey_t *keys) { + unsigned char seed[32]; + uint8_t * pk = llarp_seckey_topublic(*keys); + crypto_sign_seed_keypair(pk, *keys, seed); } } // namespace sodium } // namespace llarp @@ -92,6 +97,7 @@ void llarp_crypto_libsodium_init(struct llarp_crypto *c) { c->sign = llarp::sodium::sign; c->verify = llarp::sodium::verify; c->randomize = llarp::sodium::randomize; + c->randbytes = llarp::sodium::randbytes; c->keygen = llarp::sodium::keygen; } } diff --git a/llarp/ev.cpp b/llarp/ev.cpp index 86f0ceed5..40691052f 100644 --- a/llarp/ev.cpp +++ b/llarp/ev.cpp @@ -34,6 +34,7 @@ struct llarp_ev_caller { auto &front = pending.front(); front->work(front); pending.pop(); + delete front; } } diff --git a/test/test_async_cipher.c b/test/test_async_cipher.c new file mode 100644 index 000000000..7814615e0 --- /dev/null +++ b/test/test_async_cipher.c @@ -0,0 +1,83 @@ +#include +#include + +#include + +struct bench_main { + size_t completed; + size_t num; + size_t jobs; + struct llarp_ev_loop *ev; + struct llarp_async_cipher *cipher; + struct llarp_crypto crypto; +}; + +static void handle_cipher_complete(struct llarp_cipher_result *res) { + struct bench_main *m = (struct bench_main *)res->user; + size_t sz = m->jobs; + m->completed++; + size_t left = m->num - m->completed; + if (m->completed % 10000 == 0) printf("completed %ld and %ld left\n", m->completed, left); + if (m->completed == m->num) + { + llarp_ev_loop_stop(m->ev); + } + else if(m->completed % sz == 0) + { + llarp_nounce_t nounce; + while(sz--) + { + m->crypto.randbytes(nounce, sizeof(llarp_nounce_t)); + llarp_async_cipher_queue_op(m->cipher, &res->buff, nounce, + handle_cipher_complete, m); + } + } +} + +int main(int argc, char *argv[]) { + struct bench_main b_main; + struct llarp_threadpool *tp; + + llarp_mem_jemalloc(); + llarp_crypto_libsodium_init(&b_main.crypto); + llarp_ev_loop_alloc(&b_main.ev); + + tp = llarp_init_threadpool(8); + + b_main.num = 10000000; + b_main.jobs = 10000; + b_main.completed = 0; + llarp_sharedkey_t key; + b_main.crypto.randbytes(key, sizeof(llarp_sharedkey_t)); + + b_main.cipher = llarp_async_cipher_new(key, &b_main.crypto, b_main.ev, tp); + llarp_threadpool_start(tp); + + llarp_nounce_t nounce; + llarp_buffer_t n_buff; + n_buff.base = nounce; + n_buff.cur = n_buff.base; + n_buff.sz = sizeof(llarp_nounce_t); + size_t sz = b_main.jobs; + printf("starting %ld jobs\n", sz); + /* do work here */ + while (sz--) { + llarp_buffer_t * msg = llarp_g_mem.alloc(sizeof(llarp_buffer_t), 8); + msg->base = llarp_g_mem.alloc(1024, 1024); + msg->sz = 1024; + msg->cur = msg->base; + b_main.crypto.randomize(*msg); + b_main.crypto.randbytes(nounce, sizeof(llarp_nounce_t)); + llarp_async_cipher_queue_op(b_main.cipher, msg, nounce, + handle_cipher_complete, &b_main); + } + llarp_ev_loop_run(b_main.ev); + + llarp_threadpool_join(tp); + llarp_async_cipher_free(&b_main.cipher); + + llarp_ev_loop_free(&b_main.ev); + llarp_free_threadpool(&tp); + printf("did %ld of %ld work\n", b_main.completed, b_main.num); + return 0; +} diff --git a/test/test_async_dh.c b/test/test_async_dh.c index f258571c1..74829fc02 100644 --- a/test/test_async_dh.c +++ b/test/test_async_dh.c @@ -12,10 +12,11 @@ struct dh_bench_main { static void handle_dh_complete(struct llarp_dh_result *res) { struct dh_bench_main *m = (struct dh_bench_main *)res->user; + m->completed++; - if (m->completed % 1000 == 0) printf("completed %ld\n", m->completed); - if (m->completed == m->num) { - printf("we done\n"); + if (m->completed % 10000 == 0) printf("completed %ld\n", m->completed); + if (m->completed == m->num) + { llarp_ev_loop_stop(m->ev); } } @@ -30,29 +31,32 @@ int main(int argc, char *argv[]) { llarp_ev_loop_alloc(&dh_main.ev); tp = llarp_init_threadpool(8); - dh_main.dh = llarp_async_dh_new(&crypto, dh_main.ev, tp); - llarp_threadpool_start(tp); - dh_main.num = 1000000; + dh_main.num = 100000; dh_main.completed = 0; - struct llarp_keypair ourkey; - struct llarp_keypair theirkey; + llarp_seckey_t ourkey; + llarp_seckey_t theirkey; crypto.keygen(&ourkey); crypto.keygen(&theirkey); + dh_main.dh = llarp_async_dh_new(ourkey, &crypto, dh_main.ev, tp); + llarp_threadpool_start(tp); + llarp_tunnel_nounce_t nounce; llarp_buffer_t n_buff; n_buff.base = nounce; n_buff.cur = n_buff.base; n_buff.sz = sizeof(llarp_tunnel_nounce_t); + uint8_t * theirpubkey = llarp_seckey_topublic(theirkey); + size_t sz = dh_main.num; printf("starting %ld dh jobs\n", sz); /* do work here */ while (sz--) { crypto.randomize(n_buff); - llarp_async_client_dh(dh_main.dh, ourkey.sec, theirkey.pub, nounce, + llarp_async_client_dh(dh_main.dh, theirpubkey, nounce, handle_dh_complete, &dh_main); } printf("started %ld dh jobs\n", dh_main.num);