diff --git a/CMakeLists.txt b/CMakeLists.txt index 66772d0d8..6ccfcda24 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,7 +18,7 @@ set(LIB_SRC llarp/address_info.c llarp/buffer.cpp llarp/config.cpp - llarp/crypto_async.c + llarp/crypto_async.cpp llarp/crypto_libsodium.cpp llarp/ev.cpp llarp/exit_info.c diff --git a/include/llarp/crypto_async.h b/include/llarp/crypto_async.h index 72a78044e..b810287c6 100644 --- a/include/llarp/crypto_async.h +++ b/include/llarp/crypto_async.h @@ -9,43 +9,12 @@ extern "C" { #endif -struct llarp_async_dh; - -struct llarp_async_dh *llarp_async_dh_new( - struct llarp_alloc * mem, - llarp_seckey_t ourkey, - struct llarp_crypto *crypto, - struct llarp_threadpool *handler, - struct llarp_threadpool *worker); - -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_result { - llarp_sharedkey_t sharedkey; - void *user; - llarp_dh_complete_hook hook; -}; - -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_pubkey_t theirkey, - llarp_tunnel_nounce_t nounce, - llarp_dh_complete_hook result, void *user); - - struct llarp_async_iwp; struct llarp_async_iwp * llarp_async_iwp_new(struct llarp_alloc * mem, struct llarp_crypto * crypto, struct llarp_logic * logic, struct llarp_threadpool * worker); - struct iwp_async_keygen; @@ -122,6 +91,7 @@ typedef void (*iwp_session_start_hook)(struct iwp_async_session_start *); struct iwp_async_session_start { + struct llarp_async_iwp * iwp; void * user; uint8_t * buf; size_t sz; @@ -154,30 +124,6 @@ void iwp_call_async_frame_decrypt(struct llarp_async_iwp * iwp, struct iwp_async void iwp_call_async_frame_encrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame); - - -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( - struct llarp_alloc * mem, - llarp_sharedkey_t key, struct llarp_crypto *crypto, - struct llarp_threadpool *result, struct llarp_threadpool *worker); - -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 deleted file mode 100644 index 508f57084..000000000 --- a/llarp/crypto_async.c +++ /dev/null @@ -1,334 +0,0 @@ -#include -#include -#include - -struct llarp_async_dh { - llarp_dh_func client; - llarp_dh_func server; - struct llarp_threadpool *worker; - struct llarp_threadpool *result; - llarp_seckey_t ourkey; - struct llarp_alloc * mem; -}; - -struct llarp_dh_internal { - llarp_pubkey_t theirkey; - llarp_tunnel_nounce_t nounce; - struct llarp_dh_result result; - llarp_dh_func func; - struct llarp_async_dh *parent; -}; - -static void llarp_crypto_dh_result(void *call) { - struct llarp_dh_internal *impl = (struct llarp_dh_internal *)call; - impl->result.hook(&impl->result); - impl->parent->mem->free(impl->parent->mem, impl); -} - -static void llarp_crypto_dh_work(void *user) { - struct llarp_dh_internal *impl = (struct llarp_dh_internal *)user; - impl->func(&impl->result.sharedkey, impl->theirkey, impl->nounce, - impl->parent->ourkey); - struct llarp_thread_job job = {.user = impl, .work = &llarp_crypto_dh_result}; - llarp_threadpool_queue_job(impl->parent->result, job); -} - -static void llarp_async_dh_exec(struct llarp_async_dh *dh, llarp_dh_func func, - llarp_pubkey_t theirkey, - llarp_tunnel_nounce_t nounce, - llarp_dh_complete_hook result, void *user) { - struct llarp_dh_internal *impl = - dh->mem->alloc(dh->mem, sizeof(struct llarp_dh_internal), 32); - struct llarp_thread_job job = {.user = impl, .work = &llarp_crypto_dh_work}; - memcpy(impl->theirkey, theirkey, sizeof(llarp_pubkey_t)); - memcpy(impl->nounce, nounce, sizeof(llarp_tunnel_nounce_t)); - impl->parent = dh; - impl->result.user = user; - impl->result.hook = result; - impl->func = func; - llarp_threadpool_queue_job(dh->worker, job); -} - -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, theirkey, nounce, result, user); -} - -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, theirkey, nounce, result, user); -} - -struct llarp_async_dh *llarp_async_dh_new( - struct llarp_alloc * mem, - llarp_seckey_t ourkey, - struct llarp_crypto *crypto, - struct llarp_threadpool *result, - struct llarp_threadpool *worker) { - struct llarp_async_dh *dh = - mem->alloc(mem, sizeof(struct llarp_async_dh), 16); - dh->mem = mem; - dh->client = crypto->dh_client; - dh->server = crypto->dh_server; - memcpy(dh->ourkey, ourkey, sizeof(llarp_seckey_t)); - dh->result = result; - dh->worker = worker; - return dh; -} - -void llarp_async_dh_free(struct llarp_async_dh **dh) { - if (*dh) { - struct llarp_alloc * mem = (*dh)->mem; - mem->free(mem, *dh); - *dh = NULL; - } -} - -struct llarp_async_cipher_internal { - llarp_nounce_t nounce; - struct llarp_cipher_result result; - struct llarp_async_cipher *parent; - llarp_sym_cipher_func func; -}; - -struct llarp_async_cipher { - llarp_sharedkey_t key; - struct llarp_threadpool *worker; - struct llarp_threadpool *result; - llarp_sym_cipher_func func; - struct llarp_alloc * mem; -}; - -static void llarp_crypto_cipher_result(void *user) { - struct llarp_async_cipher_internal *impl = - (struct llarp_async_cipher_internal *)user; - struct llarp_alloc * mem = impl->parent->mem; - impl->result.hook(&impl->result); - mem->free(mem, 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->parent->key, impl->nounce); - struct llarp_thread_job job = {.user = impl, - .work = &llarp_crypto_cipher_result}; - llarp_threadpool_queue_job(impl->parent->result, job); -} - -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_alloc * mem = c->mem; - struct llarp_async_cipher_internal *impl = - mem->alloc(mem, sizeof(struct llarp_async_cipher_internal), 16); - impl->parent = c; - 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 = {.user = impl, - .work = &llarp_crypto_cipher_work}; - llarp_threadpool_queue_job(c->worker, job); -} - -struct llarp_async_cipher *llarp_async_cipher_new( - struct llarp_alloc * mem, - llarp_sharedkey_t key, struct llarp_crypto *crypto, - struct llarp_threadpool *result, struct llarp_threadpool *worker) { - - struct llarp_async_cipher *cipher = - mem->alloc(mem, sizeof(struct llarp_async_cipher), 16); - cipher->mem = mem; - cipher->func = crypto->xchacha20; - cipher->result = result; - cipher->worker = worker; - memcpy(cipher->key, key, sizeof(llarp_sharedkey_t)); - return cipher; -} - -void llarp_async_cipher_free(struct llarp_async_cipher **c) { - if (*c) { - struct llarp_alloc * mem = (*c)->mem; - mem->free(mem, *c); - *c = NULL; - } -} - -struct llarp_async_iwp -{ - struct llarp_alloc * mem; - struct llarp_crypto * crypto; - struct llarp_logic * logic; - struct llarp_threadpool * worker; -}; - -struct llarp_async_iwp * llarp_async_iwp_new(struct llarp_alloc * mem, - struct llarp_crypto * crypto, - struct llarp_logic * logic, - struct llarp_threadpool * worker) -{ - struct llarp_async_iwp * iwp = mem->alloc(mem, sizeof(struct llarp_async_iwp), 8); - if(iwp) - { - iwp->mem = mem; - iwp->crypto = crypto; - iwp->logic = logic; - iwp->worker = worker; - } - return iwp; -} - -static void iwp_inform_keygen(void * user) -{ - struct iwp_async_keygen * keygen = user; - keygen->hook(keygen); -} - -static void iwp_do_keygen(void * user) -{ - struct iwp_async_keygen * keygen = user; - keygen->iwp->crypto->keygen(keygen->keybuf); - struct llarp_thread_job job = { - .user = user, - .work = iwp_inform_keygen - }; - llarp_logic_queue_job(keygen->iwp->logic, job); -} - -void iwp_call_async_keygen(struct llarp_async_iwp * iwp, struct iwp_async_keygen * keygen) -{ - keygen->iwp = iwp; - struct llarp_thread_job job = { - .user = keygen, - .work = &iwp_do_keygen - }; - llarp_threadpool_queue_job(iwp->worker, job); -} - -static void iwp_inform_genintro(void * user) -{ - struct iwp_async_intro * intro = user; - intro->hook(intro); -} - -static void iwp_do_genintro(void * user) -{ - struct iwp_async_intro * intro = user; - llarp_sharedkey_t sharedkey; - llarp_shorthash_t e_k; - llarp_buffer_t buf; - struct llarp_crypto * crypto = intro->iwp->crypto; - uint8_t tmp[64]; - struct llarp_thread_job job = { - .user = user, - .work = &iwp_inform_genintro - }; - // S = TKE(a.k, b.k, n) - crypto->transport_dh_client(sharedkey, intro->remote_pubkey, intro->secretkey, intro->nonce); - - buf.base = (char*)tmp; - buf.sz = sizeof(tmp); - // e_k = HS(b.k + n) - memcpy(tmp, intro->remote_pubkey, 32); - memcpy(tmp + 32, intro->nonce, 32); - crypto->shorthash(&e_k, buf); - // e = SE(a.k, e_k, n[0:24]) - memcpy(intro->buf + 32, llarp_seckey_topublic(intro->secretkey), 32); - buf.base = (char*) intro->buf + 32; - buf.sz = 32; - crypto->xchacha20(buf, e_k, intro->nonce); - // h = MDS( n + e + w0, S) - buf.sz = intro->sz - 32; - crypto->hmac(intro->buf, buf, sharedkey); - // inform result - llarp_logic_queue_job(intro->iwp->logic, job); -} - -void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_intro * intro) -{ - - intro->iwp = iwp; - struct llarp_thread_job job = { - .user = intro, - .work = &iwp_do_genintro - }; - llarp_threadpool_queue_job(iwp->worker, job); -} - -static void iwp_inform_verify_introack(void * user) -{ - struct iwp_async_introack * introack = user; - introack->hook(introack); -} - - -static void iwp_do_verify_introack(void * user) -{ - struct iwp_async_introack * introack = user; - struct llarp_crypto * crypto = introack->iwp->crypto; - struct llarp_logic * logic = introack->iwp->logic; - - struct llarp_thread_job job = { - .user = user, - .work = &iwp_inform_verify_introack - }; - - llarp_hmac_t digest; - llarp_sharedkey_t sharedkey; - - uint8_t * hmac = introack->buf; - uint8_t * body = introack->buf + 32; - uint8_t * pubkey = introack->remote_pubkey; - uint8_t * secretkey = introack->secretkey; - uint8_t * nonce = introack->buf + 32; - uint8_t * token = introack->buf + 64; - size_t bodysz = introack->sz - 32; - llarp_buffer_t buf; - buf.base = (char*) body; - buf.sz = bodysz; - - // S = TKE(a.k, b.k, n) - crypto->transport_dh_client(sharedkey, pubkey, secretkey, nonce); - - // h = MDS(n + x + w1, S) - crypto->hmac(digest, buf, sharedkey); - - if(!llarp_eq(digest, hmac, 32)) - { - // fail to verify hmac - introack->buf = 0; - llarp_logic_queue_job(logic, job); - return; - } - buf.base = (char *) token; - buf.sz = 32; - // token = SD(S, x, n[0:24]) - crypto->xchacha20(buf, sharedkey, nonce); - // copy token - memcpy(introack->token, token, 32); -} - - -void iwp_call_async_verify_introack(struct llarp_async_iwp * iwp, struct iwp_async_introack * introack) -{ - introack->iwp = iwp; - struct llarp_thread_job job = { - .user = introack, - .work = &iwp_do_verify_introack - }; - llarp_threadpool_queue_job(iwp->worker, job); -} - -void iwp_call_async_gen_session_start(struct llarp_async_iwp * iwp, struct iwp_async_session_start * session) -{ - -} - -void iwp_call_async_frame_decrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame) -{ -} diff --git a/llarp/crypto_async.cpp b/llarp/crypto_async.cpp new file mode 100644 index 000000000..02bfed226 --- /dev/null +++ b/llarp/crypto_async.cpp @@ -0,0 +1,183 @@ +#include +#include +#include +#include "mem.hpp" + +struct llarp_async_iwp +{ + struct llarp_alloc * mem; + struct llarp_crypto * crypto; + struct llarp_logic * logic; + struct llarp_threadpool * worker; +}; + +void iwp_inform_keygen(void * user) +{ + iwp_async_keygen * keygen = static_cast(user); + keygen->hook(keygen); +} + +void iwp_do_keygen(void * user) +{ + iwp_async_keygen * keygen = static_cast(user); + keygen->iwp->crypto->keygen(keygen->keybuf); + llarp_thread_job job = { + .user = user, + .work = iwp_inform_keygen + }; + llarp_logic_queue_job(keygen->iwp->logic, job); +} + +void iwp_inform_genintro(void * user) +{ + iwp_async_intro * intro = static_cast(user); + intro->hook(intro); +} + +void iwp_do_genintro(void * user) +{ + iwp_async_intro * intro = static_cast(user); + llarp_sharedkey_t sharedkey; + llarp_shorthash_t e_k; + llarp_buffer_t buf; + llarp_crypto * crypto = intro->iwp->crypto; + uint8_t tmp[64]; + llarp_thread_job job = { + .user = user, + .work = &iwp_inform_genintro + }; + // S = TKE(a.k, b.k, n) + crypto->transport_dh_client(sharedkey, intro->remote_pubkey, intro->secretkey, intro->nonce); + + buf.base = (char*)tmp; + buf.sz = sizeof(tmp); + // e_k = HS(b.k + n) + memcpy(tmp, intro->remote_pubkey, 32); + memcpy(tmp + 32, intro->nonce, 32); + crypto->shorthash(&e_k, buf); + // e = SE(a.k, e_k, n[0:24]) + memcpy(intro->buf + 32, llarp_seckey_topublic(intro->secretkey), 32); + buf.base = (char*) intro->buf + 32; + buf.sz = 32; + crypto->xchacha20(buf, e_k, intro->nonce); + // h = MDS( n + e + w0, S) + buf.sz = intro->sz - 32; + crypto->hmac(intro->buf, buf, sharedkey); + // inform result + llarp_logic_queue_job(intro->iwp->logic, job); +} + + +void iwp_inform_verify_introack(void * user) +{ + iwp_async_introack * introack = static_cast(user); + introack->hook(introack); +} + + +void iwp_do_verify_introack(void * user) +{ + iwp_async_introack * introack = static_cast(user); + llarp_crypto * crypto = introack->iwp->crypto; + llarp_logic * logic = introack->iwp->logic; + + llarp_thread_job job = { + .user = user, + .work = &iwp_inform_verify_introack + }; + + llarp_hmac_t digest; + llarp_sharedkey_t sharedkey; + + uint8_t * hmac = introack->buf; + uint8_t * body = introack->buf + 32; + uint8_t * pubkey = introack->remote_pubkey; + uint8_t * secretkey = introack->secretkey; + uint8_t * nonce = introack->buf + 32; + uint8_t * token = introack->buf + 64; + size_t bodysz = introack->sz - 32; + llarp_buffer_t buf; + buf.base = (char*) body; + buf.sz = bodysz; + + // S = TKE(a.k, b.k, n) + crypto->transport_dh_client(sharedkey, pubkey, secretkey, nonce); + + // h = MDS(n + x + w1, S) + crypto->hmac(digest, buf, sharedkey); + + if(!llarp_eq(digest, hmac, 32)) + { + // fail to verify hmac + introack->buf = 0; + llarp_logic_queue_job(logic, job); + return; + } + buf.base = (char *) token; + buf.sz = 32; + // token = SD(S, x, n[0:24]) + crypto->xchacha20(buf, sharedkey, nonce); + // copy token + memcpy(introack->token, token, 32); +} + +extern "C" { + +void iwp_call_async_keygen(struct llarp_async_iwp * iwp, struct iwp_async_keygen * keygen) +{ + keygen->iwp = iwp; + struct llarp_thread_job job = { + .user = keygen, + .work = &iwp_do_keygen + }; + llarp_threadpool_queue_job(iwp->worker, job); +} + +void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_intro * intro) +{ + + intro->iwp = iwp; + struct llarp_thread_job job = { + .user = intro, + .work = &iwp_do_genintro + }; + llarp_threadpool_queue_job(iwp->worker, job); +} + +void iwp_call_async_verify_introack(struct llarp_async_iwp * iwp, struct iwp_async_introack * introack) +{ + introack->iwp = iwp; + struct llarp_thread_job job = { + .user = introack, + .work = &iwp_do_verify_introack + }; + llarp_threadpool_queue_job(iwp->worker, job); +} + +void iwp_call_async_gen_session_start(struct llarp_async_iwp * iwp, struct iwp_async_session_start * session) +{ + session->iwp = iwp; +} + +void iwp_call_async_frame_decrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame) +{ +} + + +struct llarp_async_iwp * llarp_async_iwp_new(struct llarp_alloc * mem, + struct llarp_crypto * crypto, + struct llarp_logic * logic, + struct llarp_threadpool * worker) +{ + struct llarp_async_iwp * iwp = llarp::Alloc(mem); + if(iwp) + { + iwp->mem = mem; + iwp->crypto = crypto; + iwp->logic = logic; + iwp->worker = worker; + } + return iwp; +} + +}