diff --git a/doc/iwp_v0.txt b/doc/iwp_v0.txt index bc6fed171..8622ee2b5 100644 --- a/doc/iwp_v0.txt +++ b/doc/iwp_v0.txt @@ -78,18 +78,19 @@ dropping if it does not match. 2) session start -Alice uses the token from bob to start the wire session +Alice uses the token from the previous message to start the wire session 32 bytes hmac, h 32 bytes nounce, n 32 bytes ciphertext, x variadic byttes padding, w2 -T = HS(token + n) w2 = "[insert variable length random padding here]" +e_K = TKE(a.k, b.k, n) +x = SE(e_K, token, n[0:24]) +h = MDS(n + x + w2, e_K) +T = HS(token + n) K = TKE(a.k, b.k, T) -x = SE(K, token, n[0:24]) -h = MDS(n + x + w2, K) Alice transmits ( h + n + x + w2 ) Bob recieves ( h + n + x + w2) and verifies that h == MDS(n + x, k) silently diff --git a/include/llarp/crypto_async.h b/include/llarp/crypto_async.h index b810287c6..a1aa89c0e 100644 --- a/include/llarp/crypto_async.h +++ b/include/llarp/crypto_async.h @@ -98,6 +98,8 @@ struct iwp_async_session_start uint8_t * nonce; uint8_t * token; uint8_t * sessionkey; + uint8_t * secretkey; + uint8_t * remote_pubkey; iwp_session_start_hook hook; }; diff --git a/llarp/crypto_async.cpp b/llarp/crypto_async.cpp index 02bfed226..c434a9c15 100644 --- a/llarp/crypto_async.cpp +++ b/llarp/crypto_async.cpp @@ -11,30 +11,33 @@ struct llarp_async_iwp struct llarp_threadpool * worker; }; -void iwp_inform_keygen(void * user) +namespace iwp +{ + +void inform_keygen(void * user) { iwp_async_keygen * keygen = static_cast(user); keygen->hook(keygen); } -void iwp_do_keygen(void * user) +void 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 + .work = &inform_keygen }; llarp_logic_queue_job(keygen->iwp->logic, job); } -void iwp_inform_genintro(void * user) +void inform_gen_intro(void * user) { iwp_async_intro * intro = static_cast(user); intro->hook(intro); } -void iwp_do_genintro(void * user) +void gen_intro(void * user) { iwp_async_intro * intro = static_cast(user); llarp_sharedkey_t sharedkey; @@ -44,7 +47,7 @@ void iwp_do_genintro(void * user) uint8_t tmp[64]; llarp_thread_job job = { .user = user, - .work = &iwp_inform_genintro + .work = &inform_gen_intro }; // S = TKE(a.k, b.k, n) crypto->transport_dh_client(sharedkey, intro->remote_pubkey, intro->secretkey, intro->nonce); @@ -68,33 +71,33 @@ void iwp_do_genintro(void * user) } -void iwp_inform_verify_introack(void * user) +void inform_verify_introack(void * user) { iwp_async_introack * introack = static_cast(user); introack->hook(introack); } -void iwp_do_verify_introack(void * user) +void verify_introack(void * user) { iwp_async_introack * introack = static_cast(user); - llarp_crypto * crypto = introack->iwp->crypto; - llarp_logic * logic = introack->iwp->logic; + auto crypto = introack->iwp->crypto; + auto logic = introack->iwp->logic; llarp_thread_job job = { .user = user, - .work = &iwp_inform_verify_introack + .work = &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; + auto hmac = introack->buf; + auto body = introack->buf + 32; + auto pubkey = introack->remote_pubkey; + auto secretkey = introack->secretkey; + auto nonce = introack->buf + 32; + auto token = introack->buf + 64; size_t bodysz = introack->sz - 32; llarp_buffer_t buf; buf.base = (char*) body; @@ -109,7 +112,7 @@ void iwp_do_verify_introack(void * user) if(!llarp_eq(digest, hmac, 32)) { // fail to verify hmac - introack->buf = 0; + introack->buf = nullptr; llarp_logic_queue_job(logic, job); return; } @@ -119,6 +122,67 @@ void iwp_do_verify_introack(void * user) crypto->xchacha20(buf, sharedkey, nonce); // copy token memcpy(introack->token, token, 32); + llarp_logic_queue_job(logic, job); +} + + void inform_gen_session_start(void * user) + { + iwp_async_session_start * session = static_cast(user); + session->hook(session); + } + + void gen_session_start(void * user) + { + iwp_async_session_start * session = static_cast(user); + auto crypto = session->iwp->crypto; + + auto dh = crypto->transport_dh_client; + auto shorthash = crypto->shorthash; + auto hmac = crypto->hmac; + auto encrypt = crypto->xchacha20; + + auto logic = session->iwp->logic; + auto a_sK = session->secretkey; + auto b_K = session->remote_pubkey; + auto N = session->nonce; + auto token = session->token; + auto K = session->sessionkey; + + llarp_sharedkey_t e_K; + llarp_shorthash_t T; + llarp_buffer_t buf; + + uint8_t tmp[64]; + + // T = HS(token + n) + memcpy(tmp, token, 32); + memcpy(tmp + 32, N, 32); + buf.base = (char *) tmp; + buf.sz = 64; + shorthash(&T, buf); + + // e_K = TKE(a.k, b.k, N) + dh(e_K, b_K, a_sK, N); + // K = TKE(a.k, b.k, T) + dh(K, b_K, a_sK, T); + + // x = SE(e_K, token, n[0:24]) + buf.base = (char *) (session->buf + 64); + buf.sz = 32; + memcpy(buf.base, token, 32); + encrypt(buf, e_K, N); + + // h = MDS(n + x + w2, e_K) + buf.base = (char*) (session->buf + 32); + buf.sz = session->sz - 32; + hmac(session->buf, buf, e_K); + + // K = TKE(a.k, b.k, T) + dh(K, b_K, a_sK, T); + + llarp_logic_queue_job(logic, {user, &inform_gen_session_start}); + } + } extern "C" { @@ -126,37 +190,25 @@ 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); + llarp_threadpool_queue_job(iwp->worker, {keygen, &iwp::keygen}); } 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); + llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::gen_intro}); } 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); + llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::verify_introack}); } void iwp_call_async_gen_session_start(struct llarp_async_iwp * iwp, struct iwp_async_session_start * session) { session->iwp = iwp; + llarp_threadpool_queue_job(iwp->worker, {session, &iwp::gen_session_start}); } void iwp_call_async_frame_decrypt(struct llarp_async_iwp * iwp, struct iwp_async_frame * frame)