mirror of https://github.com/oxen-io/lokinet
implement rc signing
This commit is contained in:
parent
0f6c0d8a56
commit
6cc469775f
|
@ -6,7 +6,7 @@ contact-file=router-contact.signed
|
|||
dir=./tmp-nodes
|
||||
|
||||
[iwp-connect]
|
||||
#named-node0=/path/to/routercontact0
|
||||
named-node0=remote-rc.signed
|
||||
#named-node1=/path/to/routercontact1
|
||||
|
||||
[iwp-links]
|
||||
|
|
|
@ -12,6 +12,7 @@ static void progress() {
|
|||
struct llarp_main
|
||||
{
|
||||
struct llarp_alloc mem;
|
||||
struct llarp_crypto crypto;
|
||||
struct llarp_router *router = nullptr;
|
||||
struct llarp_threadpool *worker = nullptr;
|
||||
struct llarp_threadpool *thread = nullptr;
|
||||
|
@ -111,17 +112,18 @@ int main(int argc, char *argv[]) {
|
|||
const char *conffname = "daemon.ini";
|
||||
if (argc > 1) conffname = argv[1];
|
||||
llarp_mem_jemalloc(&llarp.mem);
|
||||
struct llarp_alloc * mem = &llarp.mem;
|
||||
auto mem = &llarp.mem;
|
||||
llarp_new_config(&llarp.config);
|
||||
llarp_ev_loop_alloc(&llarp.mainloop);
|
||||
llarp_crypto_libsodium_init(&llarp.crypto);
|
||||
printf("%s loading config file %s\n", LLARP_VERSION, conffname);
|
||||
if (!llarp_load_config(llarp.config, conffname)) {
|
||||
struct llarp_config_iterator iter;
|
||||
llarp_config_iterator iter;
|
||||
iter.user = &llarp;
|
||||
iter.visit = iter_main_config;
|
||||
llarp_config_iter(llarp.config, &iter);
|
||||
|
||||
llarp.nodedb = llarp_nodedb_new(mem);
|
||||
llarp.nodedb = llarp_nodedb_new(mem, &llarp.crypto);
|
||||
|
||||
if (llarp.nodedb_dir[0]) {
|
||||
llarp.nodedb_dir[sizeof(llarp.nodedb_dir) - 1] = 0;
|
||||
|
@ -129,7 +131,7 @@ int main(int argc, char *argv[]) {
|
|||
if (llarp_nodedb_ensure_dir(dir)) {
|
||||
// ensure worker thread pool
|
||||
if (!llarp.worker) llarp.worker = llarp_init_threadpool(2);
|
||||
// ensure thread
|
||||
// ensure logic thread
|
||||
llarp.thread = llarp_init_threadpool(1);
|
||||
llarp.logic = llarp_init_logic(mem);
|
||||
|
||||
|
@ -140,11 +142,7 @@ int main(int argc, char *argv[]) {
|
|||
printf("starting router\n");
|
||||
llarp_run_router(llarp.router);
|
||||
// run mainloop
|
||||
struct llarp_thread_job job = {
|
||||
.user = llarp.mainloop,
|
||||
.work = &run_net
|
||||
};
|
||||
llarp_threadpool_queue_job(llarp.thread, job);
|
||||
llarp_threadpool_queue_job(llarp.thread, {llarp.mainloop, &run_net});
|
||||
printf("running\n");
|
||||
llarp.exitcode = 0;
|
||||
llarp_logic_mainloop(llarp.logic);
|
||||
|
|
|
@ -27,11 +27,13 @@ struct llarp_ai_list;
|
|||
struct llarp_ai_list *llarp_ai_list_new(struct llarp_alloc * mem);
|
||||
void llarp_ai_list_free(struct llarp_ai_list **l);
|
||||
|
||||
void llarp_ai_copy(struct llarp_ai * dst, struct llarp_ai * src);
|
||||
|
||||
bool llarp_ai_list_bencode(struct llarp_ai_list *l, llarp_buffer_t *buff);
|
||||
bool llarp_ai_list_bdecode(struct llarp_ai_list *l, llarp_buffer_t *buff);
|
||||
|
||||
struct llarp_ai llarp_ai_list_popfront(struct llarp_ai_list *l);
|
||||
void llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai *ai);
|
||||
void llarp_ai_list_pushback(struct llarp_ai_list *l, struct llarp_ai ai);
|
||||
size_t llarp_ai_list_size(struct llarp_ai_list *l);
|
||||
struct llarp_ai *llarp_ai_list_index(struct llarp_ai_list *l, ssize_t idx);
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ typedef bool (*llarp_shorthash_func)(llarp_shorthash_t *, llarp_buffer_t);
|
|||
typedef bool (*llarp_hmac_func)(uint8_t *, llarp_buffer_t,
|
||||
const uint8_t *);
|
||||
|
||||
typedef bool (*llarp_sign_func)(uint8_t *, llarp_seckey_t, llarp_buffer_t);
|
||||
typedef bool (*llarp_sign_func)(uint8_t *, const uint8_t *, llarp_buffer_t);
|
||||
|
||||
typedef bool (*llarp_verify_func)(const uint8_t *, llarp_buffer_t, const uint8_t *);
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ struct llarp_link_ev_listener {
|
|||
struct llarp_link {
|
||||
void *impl;
|
||||
const char *(*name)(void);
|
||||
void (*get_our_address)(struct llarp_link *, struct llarp_ai *);
|
||||
/*
|
||||
int (*register_listener)(struct llarp_link *, struct llarp_link_ev_listener);
|
||||
void (*deregister_listener)(struct llarp_link *, int);
|
||||
|
|
|
@ -9,7 +9,7 @@ extern "C" {
|
|||
struct llarp_nodedb;
|
||||
|
||||
/** create an empty nodedb */
|
||||
struct llarp_nodedb *llarp_nodedb_new(struct llarp_alloc * mem);
|
||||
struct llarp_nodedb *llarp_nodedb_new(struct llarp_alloc * mem, struct llarp_crypto * crypto);
|
||||
|
||||
/** free a nodedb and all loaded rc */
|
||||
void llarp_nodedb_free(struct llarp_nodedb **n);
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
const size_t MAX_RC_SIZE = 1024;
|
||||
|
||||
struct llarp_rc {
|
||||
struct llarp_ai_list *addrs;
|
||||
llarp_pubkey_t pubkey;
|
||||
|
@ -17,7 +19,7 @@ struct llarp_rc {
|
|||
bool llarp_rc_bdecode(struct llarp_alloc * mem, struct llarp_rc *rc, llarp_buffer_t *buf);
|
||||
bool llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buf);
|
||||
void llarp_rc_free(struct llarp_rc *rc);
|
||||
bool llarp_rc_verify_sig(struct llarp_rc *rc);
|
||||
bool llarp_rc_verify_sig(struct llarp_crypto * crypto, struct llarp_rc *rc);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -87,6 +87,30 @@ void llarp_ai_list_free(struct llarp_ai_list **l) {
|
|||
}
|
||||
}
|
||||
|
||||
void llarp_ai_copy(struct llarp_ai * dst, struct llarp_ai * src)
|
||||
{
|
||||
memcpy(dst, src, sizeof(struct llarp_ai));
|
||||
}
|
||||
|
||||
void llarp_ai_list_pushback(struct llarp_ai_list * l, struct llarp_ai a)
|
||||
{
|
||||
struct llarp_ai_list_node *cur = l->root;
|
||||
if(cur)
|
||||
{
|
||||
// go to the end of the list
|
||||
while(cur->next)
|
||||
cur = cur->next;
|
||||
|
||||
cur->next = l->mem->alloc(l->mem, sizeof(struct llarp_ai_list_node), 16);
|
||||
cur = cur->next;
|
||||
}
|
||||
else
|
||||
cur = l->mem->alloc(l->mem, sizeof(struct llarp_ai_list_node), 16);
|
||||
|
||||
llarp_ai_copy(&cur->data, &a);
|
||||
cur->next = 0;
|
||||
}
|
||||
|
||||
void llarp_ai_list_iterate(struct llarp_ai_list *l,
|
||||
struct llarp_ai_list_iter *itr) {
|
||||
struct llarp_ai_list_node *cur = l->root;
|
||||
|
|
|
@ -17,10 +17,10 @@ bool llarp_buffer_writef(llarp_buffer_t* buff, const char* fmt, ...) {
|
|||
size_t sz = llarp_buffer_size_left(buff);
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
written = snprintf(buff->cur, sz, fmt, args);
|
||||
written = vsnprintf(buff->cur, sz, fmt, args);
|
||||
va_end(args);
|
||||
if (written == -1) return false;
|
||||
buff->sz += written;
|
||||
buff->cur += written;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,7 +77,7 @@ static bool hmac(uint8_t *result, llarp_buffer_t buff,
|
|||
secret, HMACSECSIZE) != -1;
|
||||
}
|
||||
|
||||
static bool sign(uint8_t *result, llarp_seckey_t secret,
|
||||
static bool sign(uint8_t *result, const uint8_t * secret,
|
||||
llarp_buffer_t buff) {
|
||||
const uint8_t *base = (const uint8_t *)buff.base;
|
||||
return crypto_sign_detached(result, nullptr, base, buff.sz, secret) != -1;
|
||||
|
|
|
@ -569,6 +569,11 @@ struct server
|
|||
printf("cleanup dead\n");
|
||||
}
|
||||
|
||||
uint8_t * pubkey()
|
||||
{
|
||||
return llarp_seckey_topublic(seckey);
|
||||
}
|
||||
|
||||
bool ensure_privkey()
|
||||
{
|
||||
std::error_code ec;
|
||||
|
@ -662,10 +667,21 @@ server * link_alloc(struct llarp_alloc * mem, struct llarp_msg_muxer * muxer, co
|
|||
|
||||
const char * link_name()
|
||||
{
|
||||
return "iwp";
|
||||
return "IWP";
|
||||
}
|
||||
|
||||
|
||||
void link_get_addr(struct llarp_link * l, struct llarp_ai * addr)
|
||||
{
|
||||
server * link = static_cast<server *>(l->impl);
|
||||
llarp::Addr linkaddr(link->udp.addr);
|
||||
addr->rank = 1;
|
||||
strncpy(addr->dialect, link_name(), sizeof(addr->dialect));
|
||||
memcpy(addr->enc_key, link->pubkey(), 32);
|
||||
memcpy(addr->ip.s6_addr, linkaddr.addr.s6_addr, 16);
|
||||
addr->port = linkaddr.port;
|
||||
}
|
||||
|
||||
bool link_configure(struct llarp_link * l, struct llarp_ev_loop * netloop, const char * ifname, int af, uint16_t port)
|
||||
{
|
||||
server * link = static_cast<server*>(l->impl);
|
||||
|
@ -768,6 +784,7 @@ void iwp_link_init(struct llarp_link * link, struct llarp_iwp_args args, struct
|
|||
{
|
||||
link->impl = iwp::link_alloc(args.mem, muxer, args.keyfile, args.crypto, args.logic, args.cryptoworker);
|
||||
link->name = iwp::link_name;
|
||||
link->get_our_address = iwp::link_get_addr;
|
||||
link->configure = iwp::link_configure;
|
||||
link->start_link = iwp::link_start;
|
||||
link->stop_link = iwp::link_stop;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
bool llarp_link_initialized(struct llarp_link * link)
|
||||
{
|
||||
return link && link->impl && link->name && link->configure && link->start_link && link->stop_link && link->iter_sessions && link->try_establish && link->acquire_session_for_addr && link->mark_session_active && link->free_impl;
|
||||
return link && link->impl && link->name && link->get_our_address && link->configure && link->start_link && link->stop_link && link->iter_sessions && link->try_establish && link->acquire_session_for_addr && link->mark_session_active && link->free_impl;
|
||||
}
|
||||
|
||||
bool llarp_link_session_initialized(struct llarp_link_session * s)
|
||||
|
|
|
@ -9,9 +9,10 @@ static const char skiplist_subdirs[] = "0123456789ABCDEF";
|
|||
|
||||
struct llarp_nodedb {
|
||||
|
||||
llarp_nodedb(struct llarp_alloc * m) : mem(m) {}
|
||||
llarp_nodedb(llarp_alloc * m, llarp_crypto * c) : mem(m), crypto(c) {}
|
||||
|
||||
llarp_alloc * mem;
|
||||
llarp_crypto * crypto;
|
||||
std::map<llarp::pubkey, llarp_rc *> entries;
|
||||
|
||||
void Clear()
|
||||
|
@ -51,8 +52,9 @@ struct llarp_nodedb {
|
|||
}
|
||||
fclose(f);
|
||||
llarp_rc *rc = llarp::Alloc<llarp_rc>(mem);
|
||||
llarp::Zero(rc, sizeof(llarp_rc));
|
||||
if (llarp_rc_bdecode(mem, rc, &buff)) {
|
||||
if (llarp_rc_verify_sig(rc)) {
|
||||
if (llarp_rc_verify_sig(crypto, rc)) {
|
||||
llarp::pubkey pk;
|
||||
memcpy(pk.data(), rc->pubkey, pk.size());
|
||||
entries[pk] = rc;
|
||||
|
@ -75,10 +77,10 @@ struct llarp_nodedb {
|
|||
|
||||
extern "C" {
|
||||
|
||||
struct llarp_nodedb *llarp_nodedb_new(struct llarp_alloc * mem) {
|
||||
struct llarp_nodedb *llarp_nodedb_new(struct llarp_alloc * mem, struct llarp_crypto * crypto) {
|
||||
void * ptr = mem->alloc(mem, sizeof(llarp_nodedb), llarp::alignment<llarp_nodedb>());
|
||||
if(!ptr) return nullptr;
|
||||
return new (ptr) llarp_nodedb(mem);
|
||||
return new (ptr) llarp_nodedb(mem, crypto);
|
||||
}
|
||||
|
||||
void llarp_nodedb_free(struct llarp_nodedb **n) {
|
||||
|
|
115
llarp/router.cpp
115
llarp/router.cpp
|
@ -7,6 +7,8 @@
|
|||
#include <llarp/router.h>
|
||||
#include "str.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace llarp {
|
||||
void router_iter_config(llarp_config_iterator *iter, const char *section,
|
||||
const char *key, const char *val);
|
||||
|
@ -33,6 +35,54 @@ void llarp_router::AddLink(struct llarp_link *link) {
|
|||
|
||||
bool llarp_router::Ready() { return ready; }
|
||||
|
||||
bool llarp_router::EnsureIdentity()
|
||||
{
|
||||
std::error_code ec;
|
||||
if(!fs::exists(ident_keyfile, ec))
|
||||
{
|
||||
crypto.keygen(identity);
|
||||
std::ofstream f(ident_keyfile, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.write((char*)identity, sizeof(identity));
|
||||
}
|
||||
}
|
||||
std::ifstream f(ident_keyfile, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.read((char*)identity, sizeof(identity));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool llarp_router::SaveRC()
|
||||
{
|
||||
printf("verify rc signature... ");
|
||||
if(!llarp_rc_verify_sig(&crypto, &rc))
|
||||
{
|
||||
printf(" BAD!\n");
|
||||
return false;
|
||||
}
|
||||
printf(" OK.\n");
|
||||
|
||||
uint8_t tmp[MAX_RC_SIZE];
|
||||
llarp_buffer_t buf;
|
||||
buf.base = (char*)tmp;
|
||||
buf.cur = (char*) tmp;
|
||||
buf.sz = sizeof(tmp);
|
||||
if(llarp_rc_bencode(&rc, &buf))
|
||||
{
|
||||
std::ofstream f(our_rc_file, std::ios::binary);
|
||||
if(f.is_open())
|
||||
{
|
||||
f.write(buf.base, buf.cur - buf.base);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void llarp_router::ForEachLink(std::function<void(llarp_link *)> visitor) {
|
||||
llarp::router_links *cur = &links;
|
||||
do {
|
||||
|
@ -66,15 +116,48 @@ bool llarp_configure_router(struct llarp_router *router,
|
|||
iter.user = router;
|
||||
iter.visit = llarp::router_iter_config;
|
||||
llarp_config_iter(conf, &iter);
|
||||
return router->Ready();
|
||||
if(!router->Ready()) return false;
|
||||
return router->EnsureIdentity();
|
||||
}
|
||||
|
||||
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());
|
||||
|
||||
// zero out router contact
|
||||
llarp::Zero(&router->rc, sizeof(llarp_rc));
|
||||
// fill our address list
|
||||
router->rc.addrs = llarp_ai_list_new(router->mem);
|
||||
router->ForEachLink([router](llarp_link *link) {
|
||||
llarp_ai addr;
|
||||
link->get_our_address(link, &addr);
|
||||
llarp_ai_list_pushback(router->rc.addrs, addr);
|
||||
});
|
||||
// set public key
|
||||
memcpy(router->rc.pubkey, router->pubkey(), 32);
|
||||
|
||||
// sign router contact
|
||||
llarp_buffer_t signbuf;
|
||||
char buf[MAX_RC_SIZE];
|
||||
signbuf.base = buf;
|
||||
signbuf.cur = buf;
|
||||
signbuf.sz = sizeof(buf);
|
||||
// encode
|
||||
if(llarp_rc_bencode(&router->rc, &signbuf))
|
||||
{
|
||||
// sign
|
||||
signbuf.sz = signbuf.cur - signbuf.base;
|
||||
router->crypto.sign(router->rc.signature, router->identity, signbuf);
|
||||
if(router->SaveRC())
|
||||
{
|
||||
printf("saved router contact\n");
|
||||
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());
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("failed to generate rc\n");
|
||||
}
|
||||
|
||||
void llarp_stop_router(struct llarp_router *router) {
|
||||
|
@ -113,7 +196,7 @@ void router_iter_config(llarp_config_iterator *iter, const char *section,
|
|||
proto = std::atoi(val);
|
||||
}
|
||||
|
||||
struct llarp_link *link;
|
||||
struct llarp_link *link = nullptr;
|
||||
if (StrEq(section, "iwp-links"))
|
||||
{
|
||||
link = llarp::Alloc<llarp_link>(self->mem);
|
||||
|
@ -124,10 +207,28 @@ void router_iter_config(llarp_config_iterator *iter, const char *section,
|
|||
.crypto = &self->crypto,
|
||||
.logic = self->logic,
|
||||
.cryptoworker = self->tp,
|
||||
.keyfile=self->transport_keyfile,
|
||||
.keyfile = self->transport_keyfile.c_str(),
|
||||
};
|
||||
iwp_link_init(link, args, &self->muxer);
|
||||
}
|
||||
else if (StrEq(section, "iwp-connect"))
|
||||
{
|
||||
std::error_code ec;
|
||||
if(fs::exists(val, ec))
|
||||
self->connect.try_emplace(key, val);
|
||||
else
|
||||
printf("cannot read %s\n", val);
|
||||
return;
|
||||
}
|
||||
else if (StrEq(section, "router"))
|
||||
{
|
||||
if(StrEq(key, "contact-file"))
|
||||
{
|
||||
self->our_rc_file = val;
|
||||
printf("storing signed rc at %s\n", self->our_rc_file.c_str());
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
#define LLARP_ROUTER_HPP
|
||||
#include <llarp/link.h>
|
||||
#include <llarp/router.h>
|
||||
#include <llarp/router_contact.h>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
#include "mem.hpp"
|
||||
#include "fs.hpp"
|
||||
|
||||
namespace llarp {
|
||||
struct router_links {
|
||||
|
@ -16,8 +19,21 @@ struct router_links {
|
|||
|
||||
struct llarp_router {
|
||||
bool ready;
|
||||
const char * transport_keyfile = "transport.key";
|
||||
const char * transport_certfile = "transport.pem";
|
||||
// transient iwp encryption key
|
||||
fs::path transport_keyfile = "transport.key";
|
||||
|
||||
// nodes to connect to on startup
|
||||
std::map<std::string, fs::path> connect;
|
||||
|
||||
// long term identity key
|
||||
fs::path ident_keyfile = "identity.key";
|
||||
|
||||
// path to write our self signed rc to
|
||||
fs::path our_rc_file = "rc.signed";
|
||||
|
||||
|
||||
llarp_rc rc;
|
||||
|
||||
llarp_ev_loop * netloop;
|
||||
llarp_threadpool *tp;
|
||||
llarp_logic * logic;
|
||||
|
@ -26,6 +42,7 @@ struct llarp_router {
|
|||
llarp_msg_muxer muxer;
|
||||
llarp_path_context *paths;
|
||||
llarp_alloc * mem;
|
||||
llarp_seckey_t identity;
|
||||
|
||||
llarp_router(llarp_alloc * mem);
|
||||
~llarp_router();
|
||||
|
@ -37,6 +54,11 @@ struct llarp_router {
|
|||
void Close();
|
||||
|
||||
bool Ready();
|
||||
|
||||
bool EnsureIdentity();
|
||||
bool SaveRC();
|
||||
|
||||
uint8_t * pubkey() { return llarp_seckey_topublic(identity); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -77,9 +77,32 @@ bool llarp_rc_bdecode(struct llarp_alloc * mem, struct llarp_rc * rc, llarp_buff
|
|||
return bdecode_read_dict(buff, &r);
|
||||
}
|
||||
|
||||
bool llarp_rc_verify_sig(struct llarp_rc * rc)
|
||||
|
||||
bool llarp_rc_verify_sig(struct llarp_crypto * crypto, struct llarp_rc * rc)
|
||||
{
|
||||
return false;
|
||||
bool result = false;
|
||||
llarp_sig_t sig;
|
||||
char tmp[MAX_RC_SIZE];
|
||||
llarp_buffer_t buf;
|
||||
buf.base = tmp;
|
||||
buf.cur = tmp;
|
||||
buf.sz = sizeof(tmp);
|
||||
// copy sig
|
||||
memcpy(sig, rc->signature, sizeof(llarp_sig_t));
|
||||
// zero sig
|
||||
memset(rc->signature, 0, sizeof(llarp_sig_t));
|
||||
|
||||
// bencode
|
||||
if(llarp_rc_bencode(rc, &buf))
|
||||
{
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// verify
|
||||
result = crypto->verify(rc->pubkey, buf, sig);
|
||||
// restore sig
|
||||
memcpy(rc->signature, sig, sizeof(llarp_sig_t));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buff) {
|
||||
|
|
Loading…
Reference in New Issue