1
1
Fork 0
mirror of https://github.com/oxen-io/lokinet synced 2023-12-14 06:53:00 +01:00

add initial iwp async crypto for intro

This commit is contained in:
Jeff Becker 2018-05-18 16:08:57 -04:00
parent 4939c7a5e3
commit 14d2de8edb
No known key found for this signature in database
GPG key ID: F357B3B42F6F9B05
11 changed files with 260 additions and 73 deletions

View file

@ -139,15 +139,14 @@ int main(int argc, char *argv[]) {
if (!llarp.worker) llarp.worker = llarp_init_threadpool(2);
// ensure thread
llarp.thread = llarp_init_threadpool(1);
llarp.logic = llarp_init_logic(mem);
llarp.router = llarp_init_router(mem, llarp.worker, llarp.mainloop);
llarp.router = llarp_init_router(mem, llarp.worker, llarp.mainloop, llarp.logic);
if (llarp_configure_router(llarp.router, llarp.config)) {
llarp.logic = llarp_init_logic(mem);
signal(SIGINT, handle_signal);
printf("starting router\n");
llarp_run_router(llarp.router, llarp.logic);
llarp_run_router(llarp.router);
// run mainloop
struct llarp_thread_job job = {
.user = llarp.mainloop,

View file

@ -38,8 +38,8 @@ typedef bool (*llarp_dh_func)(llarp_sharedkey_t *, llarp_pubkey_t,
llarp_tunnel_nounce_t, llarp_seckey_t);
typedef bool (*llarp_transport_dh_func)(llarp_sharedkey_t *, llarp_pubkey_t,
llarp_seckey_t, uint8_t *);
typedef bool (*llarp_transport_dh_func)(uint8_t *, uint8_t *,
uint8_t *, uint8_t *);
typedef bool (*llarp_sym_cipher_func)(llarp_buffer_t, llarp_sharedkey_t,
llarp_nounce_t);
@ -68,7 +68,7 @@ struct llarp_crypto {
llarp_verify_func verify;
void (*randomize)(llarp_buffer_t);
void (*randbytes)(void *, size_t);
void (*keygen)(llarp_seckey_t *);
void (*keygen)(uint8_t *);
};
void llarp_crypto_libsodium_init(struct llarp_crypto *c);

View file

@ -3,6 +3,7 @@
#include <llarp/crypto.h>
#include <llarp/ev.h>
#include <llarp/threadpool.h>
#include <llarp/logic.h>
#ifdef __cplusplus
extern "C" {
@ -37,6 +38,80 @@ 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;
typedef void (*iwp_keygen_hook)(struct iwp_async_keygen *);
struct iwp_async_keygen
{
struct llarp_async_iwp * iwp;
void * user;
uint8_t * keybuf;
iwp_keygen_hook hook;
};
void iwp_call_async_keygen(struct llarp_async_iwp * iwp, struct iwp_async_keygen * keygen);
struct iwp_async_gen_intro;
typedef void (*iwp_intro_gen_hook)(struct iwp_async_gen_intro *);
struct iwp_async_gen_intro
{
struct llarp_async_iwp * iwp;
void * user;
uint8_t * buf;
size_t sz;
/** nonce paramter */
uint8_t * nonce;
/** remote public key */
uint8_t * remote_pubkey;
/** local private key */
uint8_t * secretkey;
/** resulting shared key */
uint8_t * sharedkey;
/** callback */
iwp_intro_gen_hook hook;
};
void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_gen_intro * intro);
struct iwp_async_gen_introack;
typedef void (*iwp_introack_gen_hook)(struct iwp_async_gen_introack *);
struct iwp_async_gen_introack
{
void * user;
uint8_t * buf;
size_t sz;
/** nonce paramter */
uint8_t * nonce;
/** remote public key */
uint8_t * remote_pubkey;
/** local private key */
uint8_t * secretkey;
/** callback */
iwp_introack_gen_hook hook;
};
void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_gen_intro * intro);
struct llarp_async_cipher;
struct llarp_cipher_result;

View file

@ -12,6 +12,8 @@ extern "C" {
struct llarp_iwp_args {
struct llarp_alloc * mem;
struct llarp_crypto* crypto;
struct llarp_logic * logic;
struct llarp_threadpool * cryptoworker;
const char * keyfile;
};

View file

@ -13,13 +13,13 @@ extern "C" {
struct llarp_router;
struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_threadpool *worker, struct llarp_ev_loop * netloop);
struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_threadpool *worker, struct llarp_ev_loop * netloop, struct llarp_logic *logic);
void llarp_free_router(struct llarp_router **router);
bool llarp_configure_router(struct llarp_router *router,
struct llarp_config *conf);
void llarp_run_router(struct llarp_router *router, struct llarp_logic *logic);
void llarp_run_router(struct llarp_router *router);
void llarp_stop_router(struct llarp_router *router);
/** get router's inbound link level frame queue */

View file

@ -158,3 +158,104 @@ void llarp_async_cipher_free(struct llarp_async_cipher **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_gen_intro * intro = user;
intro->hook(intro);
}
static void iwp_do_genintro(void * user)
{
struct iwp_async_gen_intro * intro = user;
llarp_shorthash_t sharedkey;
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(intro->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(&sharedkey, buf);
// e = SE(a.k, e_k, n[0:24])
memcpy(intro->buf + 64, llarp_seckey_topublic(intro->secretkey), 32);
buf.base = (char*) intro->buf + 64;
buf.sz = 32;
crypto->xchacha20(buf, sharedkey, intro->nonce);
// s = S(a.k.privkey, n + e + w0)
buf.sz = intro->sz - 64;
crypto->sign(intro->buf, intro->secretkey, buf);
// inform result
llarp_logic_queue_job(intro->iwp->logic, job);
}
void iwp_call_async_gen_intro(struct llarp_async_iwp * iwp, struct iwp_async_gen_intro * intro)
{
intro->iwp = iwp;
struct llarp_thread_job job = {
.user = intro,
.work = &iwp_do_genintro
};
llarp_threadpool_queue_job(iwp->worker, job);
}

View file

@ -10,9 +10,8 @@ static bool xchacha20(llarp_buffer_t buff, llarp_sharedkey_t k,
return crypto_stream_xchacha20_xor(base, base, buff.sz, n, k) == 0;
}
static bool dh(llarp_sharedkey_t *shared, uint8_t *client_pk,
static bool dh(uint8_t * out, uint8_t *client_pk,
uint8_t *server_pk, uint8_t *remote_key, uint8_t *local_key) {
uint8_t *out = *shared;
crypto_generichash_state h;
const size_t outsz = SHAREDKEYSIZE;
if (crypto_scalarmult(out, local_key, remote_key) == -1) return false;
@ -26,7 +25,7 @@ static bool dh(llarp_sharedkey_t *shared, uint8_t *client_pk,
static bool dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nounce_t n, llarp_seckey_t sk) {
if (dh(shared, llarp_seckey_topublic(sk), pk, pk, sk)) {
if (dh(*shared, llarp_seckey_topublic(sk), pk, pk, sk)) {
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared, SHAREDKEYSIZE, n,
TUNNOUNCESIZE) != -1;
}
@ -35,7 +34,7 @@ static bool dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
static bool dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nounce_t n, llarp_seckey_t sk) {
if (dh(shared, pk, llarp_seckey_topublic(sk), pk, sk)) {
if (dh(*shared, pk, llarp_seckey_topublic(sk), pk, sk)) {
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared, SHAREDKEYSIZE, n,
TUNNOUNCESIZE) != -1;
}
@ -43,19 +42,19 @@ static bool dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
}
static bool transport_dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_seckey_t sk, uint8_t * n) {
static bool transport_dh_client(uint8_t *shared, uint8_t * pk,
uint8_t * sk, uint8_t * n) {
if (dh(shared, llarp_seckey_topublic(sk), pk, pk, sk)) {
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared, SHAREDKEYSIZE, n,
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE, n,
NOUNCESIZE) != -1;
}
return false;
}
static bool transport_dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_seckey_t sk, uint8_t * n) {
static bool transport_dh_server(uint8_t *shared, uint8_t * pk,
uint8_t * sk, uint8_t * n) {
if (dh(shared, pk, llarp_seckey_topublic(sk), pk, sk)) {
return crypto_generichash(*shared, SHAREDKEYSIZE, *shared, SHAREDKEYSIZE, n,
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE, n,
NOUNCESIZE) != -1;
}
return false;
@ -97,10 +96,10 @@ static inline void randbytes(void *ptr, size_t sz) {
randombytes((unsigned char *)ptr, sz);
}
static void keygen(llarp_seckey_t *keys) {
static void keygen(uint8_t *keys) {
unsigned char seed[32];
uint8_t *pk = llarp_seckey_topublic(*keys);
crypto_sign_seed_keypair(pk, *keys, seed);
uint8_t *pk = llarp_seckey_topublic(keys);
crypto_sign_seed_keypair(pk, keys, seed);
}
} // namespace sodium
} // namespace llarp

View file

@ -1,5 +1,6 @@
#include <llarp/iwp.h>
#include <llarp/net.h>
#include <llarp/crypto_async.h>
#include <cassert>
#include <fstream>
@ -16,12 +17,18 @@ namespace iwp
struct session
{
llarp_udp_io * udp;
llarp_crypto * crypto;
llarp_async_iwp * iwp;
llarp_seckey_t eph_seckey;
llarp_pubkey_t remote;
llarp_sharedkey_t sessionkey;
llarp_link_session_listener establish_listener = {nullptr, nullptr, nullptr, nullptr};
llarp::Addr addr;
iwp_async_gen_intro intro;
iwp_async_gen_introack introack;
uint8_t workbuf[1024];
typedef std::vector<uint8_t> sendbuf_t;
typedef std::list<sendbuf_t> sendqueue_t;
@ -44,12 +51,14 @@ struct session
State state;
session(llarp_crypto * c, const llarp::Addr & a) :
session(llarp_udp_io * u, llarp_async_iwp * i, llarp_crypto * c, const llarp::Addr & a) :
udp(u),
crypto(c),
iwp(i),
addr(a),
state(eInitial)
{
c->keygen(&eph_seckey);
c->keygen(eph_seckey);
}
static bool sendto(llarp_link_session * s, llarp_buffer_t msg)
@ -96,48 +105,33 @@ struct session
printf("iwp intro ack\n");
}
void introduce(llarp_udp_io * udp, llarp_pubkey_t pub)
static void handle_generated_intro(iwp_async_gen_intro * i)
{
uint8_t buf[140];
size_t sz = sizeof(buf);
sz -= rand() % (sizeof(buf) - 128);
generate_intro(pub, buf, sz);
llarp_ev_udp_sendto(udp, addr, buf, sz);
printf("sent introduce of size %ld\n", sz);
session * link = static_cast<session *>(i->user);
llarp_ev_udp_sendto(link->udp, link->addr, i->buf, i->sz);
printf("sent introduce of size %ld\n", i->sz);
}
/** generate session intro for outbound session */
void generate_intro(llarp_pubkey_t remotepub, uint8_t * buf, size_t sz)
void introduce(llarp_pubkey_t pub)
{
memcpy(remote, remotepub, 32);
assert(sz >= 128);
uint8_t tmp[64];
llarp_nounce_t nounce;
llarp_buffer_t buffer;
llarp_shorthash_t e_key;
uint8_t * sig = buf;
uint8_t * n = buf + 64;
// n = RAND(32)
crypto->randbytes(n, 32);
// nounce = n[0:24]
memcpy(nounce, n, 24);
// e_k = HS(b.k + n)
memcpy(tmp, remote, 32);
memcpy(tmp +32, n, 32);
buffer.base = (char*)tmp;
buffer.sz = sizeof(tmp);
crypto->shorthash(&e_key, buffer);
// e = SE(a.k, e_k, nounce)
crypto->xchacha20(buffer, e_key, nounce);
// S = TKE(a.k, a.b, n)
crypto->transport_dh_client(&sessionkey, remote, eph_seckey, n);
memcpy(remote, pub, 32);
intro.buf = workbuf;
size_t w0sz = (rand() % 64);
intro.sz = 128 + w0sz;
// randomize w0
if(sz > 128)
crypto->randbytes(sig + 128, sz-128);
// s = S(a.k.privkey, n + e + w0)
buffer.base = (char*)n;
buffer.sz = sz - 64;
crypto->sign(sig, eph_seckey, buffer);
if(w0sz)
crypto->randbytes(intro.buf + 128, w0sz);
intro.nonce = workbuf + 64;
intro.secretkey = eph_seckey;
intro.remote_pubkey = remote;
// randomize nonce
crypto->randbytes(intro.nonce, 32);
// async generate intro packet
intro.user = this;
intro.hook = &handle_generated_intro;
iwp_call_async_gen_intro(iwp, &intro);
}
};
@ -148,6 +142,7 @@ struct server
struct llarp_crypto * crypto;
struct llarp_ev_loop * netloop;
struct llarp_msg_muxer * muxer;
struct llarp_async_iwp * iwp;
struct llarp_udp_io udp;
char keyfile[255];
uint32_t timeout_job_id;
@ -155,9 +150,17 @@ struct server
llarp_seckey_t seckey;
server(llarp_alloc * m, llarp_crypto * c, llarp_logic * l, llarp_threadpool * w)
{
mem = m;
crypto = c;
logic = l;
iwp = llarp_async_iwp_new(mem, crypto, logic, w);
}
session * create_session(llarp::Addr & src)
{
session * impl = new session(crypto, src);
session * impl = new session(&udp, iwp, crypto, src);
llarp_link_session s;
s.impl = impl;
s.sendto = session::sendto;
@ -193,7 +196,7 @@ struct server
bool keygen(const char * fname)
{
crypto->keygen(&seckey);
crypto->keygen(seckey);
std::ofstream f(fname);
if(f.is_open())
{
@ -254,14 +257,12 @@ struct server
};
server * link_alloc(struct llarp_alloc * mem, struct llarp_msg_muxer * muxer, const char * keyfile, struct llarp_crypto * crypto)
server * link_alloc(struct llarp_alloc * mem, struct llarp_msg_muxer * muxer, const char * keyfile, struct llarp_crypto * crypto, struct llarp_logic * logic, struct llarp_threadpool * worker)
{
void * ptr = mem->alloc(mem, sizeof(struct server), 8);
if(ptr)
{
server * link = new (ptr) server;
link->mem = mem;
link->crypto = crypto;
server * link = new (ptr) server(mem, crypto, logic, worker);
link->muxer = muxer;
strncpy(link->keyfile, keyfile, sizeof(link->keyfile));
return link;
@ -343,7 +344,7 @@ void link_try_establish(struct llarp_link * l, struct llarp_link_establish_job j
llarp::Addr dst(*job.ai);
session * s = link->create_session(dst);
s->establish_listener = listener;
s->introduce(&link->udp, job.ai->enc_key);
s->introduce(job.ai->enc_key);
}
void link_mark_session_active(struct llarp_link * link, struct llarp_link_session * s)
@ -376,7 +377,7 @@ extern "C" {
void iwp_link_init(struct llarp_link * link, struct llarp_iwp_args args, struct llarp_msg_muxer * muxer)
{
link->impl = iwp::link_alloc(args.mem, muxer, args.keyfile, args.crypto);
link->impl = iwp::link_alloc(args.mem, muxer, args.keyfile, args.crypto, args.logic, args.cryptoworker);
link->name = iwp::link_name;
link->configure = iwp::link_configure;
link->start_link = iwp::link_start;

View file

@ -38,6 +38,11 @@ void llarp_logic_mainloop(struct llarp_logic* logic) {
llarp_timer_run(logic->timer, logic->thread);
}
void llarp_logic_queue_job(struct llarp_logic * logic, struct llarp_thread_job job)
{
llarp_threadpool_queue_job(logic->thread, job);
}
uint32_t llarp_logic_call_later(struct llarp_logic* logic, struct llarp_timeout_job job)
{
return llarp_timer_call_later(logic->timer, job);

View file

@ -46,7 +46,7 @@ void llarp_router::Close() {
}
extern "C" {
struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_threadpool *tp, struct llarp_ev_loop * netloop) {
struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_threadpool *tp, struct llarp_ev_loop * netloop, struct llarp_logic * logic) {
void * ptr = mem->alloc(mem, sizeof(llarp_router), 16);
if(!ptr) return nullptr;
llarp_router *router = new (ptr) llarp_router(mem);
@ -54,6 +54,7 @@ struct llarp_router *llarp_init_router(struct llarp_alloc * mem, struct llarp_th
{
router->netloop = netloop;
router->tp = tp;
router->logic = logic;
llarp_crypto_libsodium_init(&router->crypto);
}
return router;
@ -68,7 +69,8 @@ bool llarp_configure_router(struct llarp_router *router,
return router->Ready();
}
void llarp_run_router(struct llarp_router *router, struct llarp_logic *logic) {
void llarp_run_router(struct llarp_router *router) {
llarp_logic * logic = router->logic;
router->ForEachLink([logic](llarp_link *link) {
int result = link->start_link(link, logic);
if (result == -1) printf("link %s failed to start\n", link->name());
@ -120,6 +122,8 @@ void router_iter_config(llarp_config_iterator *iter, const char *section,
llarp_iwp_args args = {
.mem = self->mem,
.crypto = &self->crypto,
.logic = self->logic,
.cryptoworker = self->tp,
.keyfile=self->transport_keyfile,
};
iwp_link_init(link, args, &self->muxer);

View file

@ -18,8 +18,9 @@ struct llarp_router {
bool ready;
const char * transport_keyfile = "transport.key";
const char * transport_certfile = "transport.pem";
struct llarp_ev_loop * netloop;
struct llarp_threadpool *tp;
llarp_ev_loop * netloop;
llarp_threadpool *tp;
llarp_logic * logic;
llarp::router_links links;
llarp_crypto crypto;
llarp_msg_muxer muxer;