From 0b0278a31245f1db65f159fddb4acc1b210b6fec Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Wed, 3 Oct 2018 07:02:56 -0400 Subject: [PATCH] we don't use crypto_async anymore --- CMakeLists.txt | 1 - include/llarp/crypto_async.h | 229 -------------- llarp/crypto_async.cpp | 574 ----------------------------------- llarp/nodedb.cpp | 2 +- 4 files changed, 1 insertion(+), 805 deletions(-) delete mode 100644 include/llarp/crypto_async.h delete mode 100644 llarp/crypto_async.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index a9d906851..2108fc82a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -322,7 +322,6 @@ set(LIB_SRC llarp/buffer.cpp llarp/config.cpp llarp/context.cpp - llarp/crypto_async.cpp llarp/crypto_libsodium.cpp llarp/dht.cpp llarp/dns.cpp diff --git a/include/llarp/crypto_async.h b/include/llarp/crypto_async.h deleted file mode 100644 index 3b4443767..000000000 --- a/include/llarp/crypto_async.h +++ /dev/null @@ -1,229 +0,0 @@ -#ifndef LLARP_CRYPTO_ASYNC_H_ -#define LLARP_CRYPTO_ASYNC_H_ -#include -#include -#include -#include -#include - -/** - * crypto_async.h - * - * asynchronous crypto functions - */ - -/// context for doing asynchronous cryptography for iwp -/// with a worker threadpool -/// defined in crypto_async.cpp -struct llarp_async_iwp; - -/// allocator -/// use crypto as cryptograph implementation -/// use logic as the callback handler thread -/// use worker as threadpool that does the heavy lifting -struct llarp_async_iwp * -llarp_async_iwp_new(struct llarp_crypto *crypto, struct llarp_logic *logic, - struct llarp_threadpool *worker); - -/// deallocator -void -llarp_async_iwp_free(struct llarp_async_iwp *iwp); - -struct iwp_async_keygen; - -/// define functor for keygen -typedef void (*iwp_keygen_hook)(struct iwp_async_keygen *); - -/// key generation request -struct iwp_async_keygen -{ - /// internal wire protocol async configuration - struct llarp_async_iwp *iwp; - /// a pointer to pass ourself to thread worker - void *user; - /// destination key buffer - uint8_t *keybuf; - /// result handler callback - iwp_keygen_hook hook; -}; - -/// generate an encryption keypair asynchronously -void -iwp_call_async_keygen(struct llarp_async_iwp *iwp, - struct iwp_async_keygen *keygen); - -struct iwp_async_intro; - -/// iwp_async_intro functor -typedef void (*iwp_intro_hook)(struct iwp_async_intro *); - -/// iwp_async_intro request -struct iwp_async_intro -{ - struct llarp_async_iwp *iwp; - void *user; - uint8_t *buf; - size_t sz; - /// nonce paramter - uint8_t nonce[32]; - /// remote public key - uint8_t remote_pubkey[32]; - /// local private key - uint8_t secretkey[64]; - /// callback - iwp_intro_hook hook; -}; - -/// asynchronously generate an intro packet -void -iwp_call_async_gen_intro(struct llarp_async_iwp *iwp, - struct iwp_async_intro *intro); - -/// asynchronously verify an intro packet -void -iwp_call_async_verify_intro(struct llarp_async_iwp *iwp, - struct iwp_async_intro *info); - -struct iwp_async_introack; - -/// introduction acknowledgement functor -typedef void (*iwp_introack_hook)(struct iwp_async_introack *); - -/// introduction acknowledgement request -struct iwp_async_introack -{ - struct llarp_async_iwp *iwp; - void *user; - uint8_t *buf; - size_t sz; - /// nonce paramter - uint8_t *nonce; - /// token paramter - uint8_t *token; - /// remote public key - uint8_t *remote_pubkey; - /// local private key - uint8_t *secretkey; - /// callback - iwp_introack_hook hook; -}; - -/// generate introduction acknowledgement packet asynchronously -void -iwp_call_async_gen_introack(struct llarp_async_iwp *iwp, - struct iwp_async_introack *introack); - -/// verify introduction acknowledgement packet asynchronously -void -iwp_call_async_verify_introack(struct llarp_async_iwp *iwp, - struct iwp_async_introack *introack); - -struct iwp_async_session_start; - -/// start session functor -typedef void (*iwp_session_start_hook)(struct iwp_async_session_start *); - -/// start session request -struct iwp_async_session_start -{ - struct llarp_async_iwp *iwp; - void *user; - uint8_t *buf; - size_t sz; - /// nonce parameter - uint8_t *nonce; - /// token parameter - uint8_t *token; - /// memory to write session key to - uint8_t *sessionkey; - /// local secrkey key - uint8_t *secretkey; - /// remote public encryption key - uint8_t *remote_pubkey; - /// result callback handler - iwp_session_start_hook hook; -}; - -/// generate session start packet asynchronously -void -iwp_call_async_gen_session_start(struct llarp_async_iwp *iwp, - struct iwp_async_session_start *start); - -/// verify session start packet asynchronously -void -iwp_call_async_verify_session_start(struct llarp_async_iwp *iwp, - struct iwp_async_session_start *start); - -struct iwp_async_frame; - -/// internal wire protocol frame request -typedef void (*iwp_async_frame_hook)(struct iwp_async_frame *); - -struct iwp_async_frame -{ - /// true if decryption succeded - bool success; - /// timestamp for CoDel - llarp_time_t created; - struct llarp_async_iwp *iwp; - /// a pointer to pass ourself - void *user; - /// current session key - byte_t *sessionkey; - /// size of the frame - size_t sz; - /// result handler - iwp_async_frame_hook hook; - /// memory holding the entire frame - byte_t buf[1500]; -}; - -#ifdef __cplusplus -#include - -struct FramePutTime -{ - void - operator()(iwp_async_frame &frame) const - { - frame.created = llarp_time_now_ms(); - } -}; -struct FrameGetTime -{ - llarp_time_t - operator()(const iwp_async_frame &frame) const - { - return frame.created; - } -}; - -struct FrameCompareTime -{ - bool - operator()(const iwp_async_frame &left, const iwp_async_frame &right) const - { - return left.created < right.created; - } -}; -#endif - -/// synchronously decrypt a frame -bool -iwp_decrypt_frame(struct iwp_async_frame *frame); - -/// synchronosuly encrypt a frame -bool -iwp_encrypt_frame(struct iwp_async_frame *frame); - -/// decrypt iwp frame asynchronously -void -iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp, - struct iwp_async_frame *frame); - -/// encrypt iwp frame asynchronously -void -iwp_call_async_frame_encrypt(struct llarp_async_iwp *iwp, - struct iwp_async_frame *frame); - -#endif diff --git a/llarp/crypto_async.cpp b/llarp/crypto_async.cpp deleted file mode 100644 index e09e1c3aa..000000000 --- a/llarp/crypto_async.cpp +++ /dev/null @@ -1,574 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "buffer.hpp" -#include "logger.hpp" -#include "mem.hpp" - -struct llarp_async_iwp -{ - struct llarp_crypto *crypto; - struct llarp_logic *logic; - struct llarp_threadpool *worker; -}; - -namespace iwp -{ - void - inform_intro(void *user) - { - iwp_async_intro *intro = static_cast< iwp_async_intro * >(user); - intro->hook(intro); - } - - void - gen_intro(void *user) - { - iwp_async_intro *intro = static_cast< iwp_async_intro * >(user); - -#ifdef neuroCryptoDebug - char ftmp[68] = {0}; - const char *hexname = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >( - intro->remote_pubkey, ftmp); - llarp::LogDebug("gen_intro remote_pubkey: ", hexname); -#endif - - llarp::SharedSecret sharedkey; - llarp_crypto *crypto = intro->iwp->crypto; - - // S = TKE(a.k, b.k, n) - crypto->transport_dh_client(sharedkey, intro->remote_pubkey, - intro->secretkey, intro->nonce); - -#ifdef neuroCryptoDebug - char ftmpShared[68] = {0}; - const char *hexShared = - llarp::HexEncode< llarp::SharedSecret, decltype(ftmpShared) >( - sharedkey, ftmpShared); - llarp::LogDebug("gen_intro sharedkey ", hexShared); -#endif - - byte_t tmp[64]; - auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); - - llarp::SymmNonce n; - // copy nonce - memcpy(n, intro->nonce, 32); // was 24 bytes - - /* - char ftmpN[68] = {0}; - const char *hexN = - llarp::HexEncode< llarp::SymmNonce, decltype(ftmpN) >(n, ftmpN); - llarp::LogDebug("gen_intro nonce ", hexN); - */ - - // e_k = HS(b.k + n) - - llarp::ShortHash e_k; - memcpy(tmp, intro->remote_pubkey, 32); - memcpy(tmp + 32, intro->nonce, 32); - crypto->shorthash(e_k, buf); - -#ifdef neuroCryptoDebug - char ftmpEk[68] = {0}; - const char *hexEk = - llarp::HexEncode< llarp::ShortHash, decltype(ftmpEk) >(e_k, ftmpEk); - llarp::LogDebug("gen_intro e_k ", hexEk, " used ", strlen(hexEk)); -#endif - - // put nonce - memcpy(intro->buf + 32, intro->nonce, 32); - - // e = SE(a.k, e_k, n[0:24]) - memcpy(intro->buf + 64, llarp::seckey_topublic(intro->secretkey), 32); - -#ifdef neuroCryptoDebug - char ftmpSk[68] = {0}; - const char *hexSk = llarp::HexEncode< llarp::PubKey, decltype(ftmpSk) >( - intro->secretkey, ftmpSk); - llarp::LogDebug("gen_intro SK ", hexSk); - - char ftmpSkPub[68] = {0}; - const char *hexSkPub = - llarp::HexEncode< llarp::PubKey, decltype(ftmpSkPub) >( - llarp::seckey_topublic(intro->secretkey), ftmpSkPub); - llarp::LogDebug("gen_intro SK pub ", hexSkPub); -#endif - - buf.base = intro->buf + 64; - buf.cur = buf.base; - buf.sz = 32; - crypto->xchacha20(buf, e_k, intro->nonce); - - // h = MDS( n + e + w0, S) - buf.base = intro->buf + 32; - buf.cur = buf.base; - buf.sz = intro->sz - 32; - crypto->hmac(intro->buf, buf, sharedkey); - -#ifdef neuroCryptoDebug - char ftmpHmac[68] = {0}; // probably could be 65 - const char *hexHmac = llarp::HexEncode< llarp::PubKey, decltype(ftmpHmac) >( - intro->buf, ftmpHmac); - llarp::LogDebug("gen_intro Hmac ", hexHmac); -#endif - - // inform result - // intro->hook(intro); - llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_intro}); - } - - void - verify_intro(void *user) - { - iwp_async_intro *intro = static_cast< iwp_async_intro * >(user); - auto crypto = intro->iwp->crypto; - llarp::SharedSecret sharedkey; - llarp::ShortHash e_K; - llarp::SharedSecret h; - byte_t tmp[64]; - const auto OurPK = llarp::seckey_topublic(intro->secretkey); - -#ifdef neuroCryptoDebug - char ftmp[68] = {0}; - const char *hexPk = - llarp::HexEncode< llarp::PubKey, decltype(ftmp) >(OurPK, ftmp); - llarp::LogDebug("intro OurPK ", hexPk); -#endif - - // e_k = HS(b.k + n) - memcpy(tmp, OurPK, 32); - memcpy(tmp + 32, intro->nonce, 32); - auto buf = llarp::StackBuffer< decltype(tmp) >(tmp); - crypto->shorthash(e_K, buf); - - buf.base = intro->remote_pubkey; - buf.cur = buf.base; - buf.sz = 32; - - // was using remote_pubkey directly (use buffer wrapper? directly?) - // memcpy(intro->remote_pubkey, intro->buf + 64, 32); - memcpy(buf.base, intro->buf + 64, 32); - - crypto->xchacha20(buf, e_K, intro->nonce); -#ifdef neuroCryptoDebug - llarp::LogInfo("handshake from ", llarp::RouterID(intro->remote_pubkey)); - - char ftmp2[68] = {0}; - const char *hexRemotePK = llarp::HexEncode< llarp::PubKey, decltype(ftmp) >( - intro->remote_pubkey, ftmp2); - llarp::LogDebug("intro remote_pubkey ", hexRemotePK); -#endif - - // S = TKE(a.k, b.k, n) - crypto->transport_dh_server(sharedkey, intro->remote_pubkey, - intro->secretkey, intro->nonce); - -#ifdef neuroCryptoDebug - char ftmpShared[68] = {0}; - const char *hexShared = - llarp::HexEncode< llarp::PubKey, decltype(ftmpShared) >(sharedkey, - ftmpShared); - llarp::LogDebug("intro sharedkey ", hexShared); -#endif - - // h = MDS( n + e + w2, S) - buf.base = intro->buf + 32; - buf.cur = buf.base; - buf.sz = intro->sz - 32; - crypto->hmac(h, buf, sharedkey); - if(memcmp(h, intro->buf, 32)) - { - llarp::LogWarn("intro HMAC failure"); - // hmac fail - delete[] intro->buf; - intro->buf = nullptr; - } - // inform result - llarp_logic_queue_job(intro->iwp->logic, {intro, &inform_intro}); - } - - void - inform_introack(void *user) - { - iwp_async_introack *introack = static_cast< iwp_async_introack * >(user); - introack->hook(introack); - } - - void - verify_introack(void *user) - { - iwp_async_introack *introack = static_cast< iwp_async_introack * >(user); - auto crypto = introack->iwp->crypto; - auto logic = introack->iwp->logic; - - llarp::ShortHash digest; - llarp::SharedSecret sharedkey; - - auto hmac = introack->buf; - auto body = introack->buf + 32; - const 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 = body; - buf.cur = 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 = nullptr; - } - else - { - buf.base = token; - buf.sz = 32; - // token = SD(S, x, n[0:24]) - crypto->xchacha20(buf, sharedkey, nonce); - // copy token - memcpy(introack->token, token, 32); - } - // introack->hook(introack); - llarp_logic_queue_job(logic, {introack, &inform_introack}); - } - - void - gen_introack(void *user) - { - iwp_async_introack *introack = static_cast< iwp_async_introack * >(user); - llarp::SharedSecret sharedkey; - auto crypto = introack->iwp->crypto; - const auto pubkey = introack->remote_pubkey; - auto secretkey = introack->secretkey; - auto nonce = introack->nonce; - // S = TKE(a.k, b.k, n) - crypto->transport_dh_server(sharedkey, pubkey, secretkey, nonce); - - // x = SE(S, token, n[0:24]) - llarp_buffer_t buf; - buf.base = introack->buf + 64; - buf.sz = 32; - buf.cur = buf.base; - memcpy(buf.base, introack->token, 32); - crypto->xchacha20(buf, sharedkey, nonce); - - // h = MDS(n + x + w1, S) - buf.base = introack->buf + 32; - buf.sz = introack->sz - 32; - buf.cur = buf.base; - crypto->hmac(introack->buf, buf, sharedkey); - // introack->hook(introack); - llarp_logic_queue_job(introack->iwp->logic, {introack, &inform_introack}); - } - - void - inform_session_start(void *user) - { - iwp_async_session_start *session = - static_cast< iwp_async_session_start * >(user); - session->hook(session); - } - - void - gen_session_start(void *user) - { - iwp_async_session_start *session = - static_cast< iwp_async_session_start * >(user); - auto crypto = session->iwp->crypto; - auto logic = session->iwp->logic; - - 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; - const auto b_K = session->remote_pubkey; - auto N = session->nonce; - auto token = session->token; - auto K = session->sessionkey; - - llarp::SharedSecret e_K; - llarp::ShortHash T; - - byte_t tmp[64]; - llarp_buffer_t buf = llarp::StackBuffer< decltype(tmp) >(tmp); - - // T = HS(token + n) - memcpy(tmp, token, 32); - memcpy(tmp + 32, N, 32); - 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 = (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 = (session->buf + 32); - buf.sz = session->sz - 32; - hmac(session->buf, buf, e_K); - // session->hook(session); - llarp_logic_queue_job(logic, {session, &inform_session_start}); - } - - void - verify_session_start(void *user) - { - iwp_async_session_start *session = - static_cast< iwp_async_session_start * >(user); - // possible repeat job - if(session->buf == nullptr) - return; - - auto crypto = session->iwp->crypto; - auto logic = session->iwp->logic; - - auto dh = crypto->transport_dh_server; - auto shorthash = crypto->shorthash; - auto hmac = crypto->hmac; - auto decrypt = crypto->xchacha20; - - auto b_sK = session->secretkey; - auto a_K = session->remote_pubkey; - auto N = session->nonce; - auto token = session->token; - auto K = session->sessionkey; - - llarp::SharedSecret e_K; - llarp::ShortHash T; - - byte_t tmp[64]; - - llarp_buffer_t buf; - - // e_K = TKE(a.k, b.k, N) - dh(e_K, a_K, b_sK, N); - // h = MDS( n + x + w2, e_K) - buf.base = session->buf + 32; - buf.cur = buf.base; - buf.sz = session->sz - 32; - hmac(tmp, buf, e_K); - if(memcmp(tmp, session->buf, 32) == 0) - { - // hmac good - buf.base = session->buf + 64; - buf.cur = buf.base; - buf.sz = 32; - // token = SD(e_K, x, n[0:24]) - decrypt(buf, e_K, N); - // ensure it's the same token - if(memcmp(buf.base, token, 32) == 0) - { - // T = HS(token + n) - memcpy(tmp, token, 32); - memcpy(tmp + 32, N, 32); - buf.base = tmp; - buf.cur = buf.base; - buf.sz = sizeof(tmp); - shorthash(T, buf); - // K = TKE(a.k, b.k, T) - dh(K, a_K, b_sK, T); - } - else // token missmatch - { - session->buf = nullptr; - } - } - else // hmac fail - session->buf = nullptr; - // session->hook(session); - llarp_logic_queue_job(logic, {session, &inform_session_start}); - } - - void - inform_frame_done(void *user) - { - iwp_async_frame *frame = static_cast< iwp_async_frame * >(user); - frame->hook(frame); - delete frame; - } - - void - hmac_then_decrypt(void *user) - { - iwp_async_frame *frame = static_cast< iwp_async_frame * >(user); - iwp_decrypt_frame(frame); - // inform result - llarp_logic_queue_job(frame->iwp->logic, {frame, &inform_frame_done}); - } - - void - encrypt_then_hmac(void *user) - { - iwp_async_frame *frame = static_cast< iwp_async_frame * >(user); - iwp_encrypt_frame(frame); - // call result RIGHT HERE - frame->hook(frame); - delete frame; - } -} // namespace iwp - -bool -iwp_decrypt_frame(struct iwp_async_frame *frame) -{ - auto crypto = frame->iwp->crypto; - byte_t *hmac = frame->buf; - byte_t *nonce = frame->buf + 32; - byte_t *body = frame->buf + 64; - - llarp::ShortHash digest; - - llarp_buffer_t buf; - buf.base = nonce; - buf.cur = buf.base; - buf.sz = frame->sz - 32; - - // h = MDS(n + x, S) - crypto->hmac(digest, buf, frame->sessionkey); - // check hmac - frame->success = memcmp(digest, hmac, 32) == 0; - if(!frame->success) - { - // [", digest, "] vs [", hmac, "] - llarp::LogWarn("crypto_async::iwp_decrypt_frame failed to decrypt"); - //} else { - // llarp::Debug("crypto_async::iwp_decrypt_frame decrypted"); - } - // x = SE(S, p, n[0:24]) - buf.base = body; - buf.cur = buf.base; - buf.sz = frame->sz - 64; - crypto->xchacha20(buf, frame->sessionkey, nonce); - - return frame->success; -} - -bool -iwp_encrypt_frame(struct iwp_async_frame *frame) -{ - auto crypto = frame->iwp->crypto; - byte_t *hmac = frame->buf; - byte_t *nonce = frame->buf + 32; - byte_t *body = frame->buf + 64; - - llarp_buffer_t buf; - buf.base = body; - buf.cur = buf.base; - buf.sz = frame->sz - 64; - - // randomize N - crypto->randbytes(nonce, 32); - // x = SE(S, p, n[0:24]) - crypto->xchacha20(buf, frame->sessionkey, nonce); - // h = MDS(n + x, S) - buf.base = nonce; - buf.cur = buf.base; - buf.sz = frame->sz - 32; - crypto->hmac(hmac, buf, frame->sessionkey); - return true; -} - -void -iwp_call_async_gen_intro(struct llarp_async_iwp *iwp, - struct iwp_async_intro *intro) -{ - intro->iwp = iwp; - 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; - 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_verify_intro(struct llarp_async_iwp *iwp, - struct iwp_async_intro *intro) -{ - intro->iwp = iwp; - llarp_threadpool_queue_job(iwp->worker, {intro, &iwp::verify_intro}); -} - -void -iwp_call_async_gen_introack(struct llarp_async_iwp *iwp, - struct iwp_async_introack *introack) -{ - introack->iwp = iwp; - llarp_threadpool_queue_job(iwp->worker, {introack, &iwp::gen_introack}); -} - -void -iwp_call_async_frame_decrypt(struct llarp_async_iwp *iwp, - struct iwp_async_frame *frame) -{ - frame->iwp = iwp; - llarp_threadpool_queue_job(iwp->worker, {frame, &iwp::hmac_then_decrypt}); -} - -void -iwp_call_async_frame_encrypt(struct llarp_async_iwp *iwp, - struct iwp_async_frame *frame) -{ - frame->iwp = iwp; - llarp_threadpool_queue_job(iwp->worker, {frame, &iwp::encrypt_then_hmac}); -} - -void -iwp_call_async_verify_session_start(struct llarp_async_iwp *iwp, - struct iwp_async_session_start *session) -{ - session->iwp = iwp; - llarp_threadpool_queue_job(iwp->worker, - {session, &iwp::verify_session_start}); -} - -struct llarp_async_iwp * -llarp_async_iwp_new(struct llarp_crypto *crypto, struct llarp_logic *logic, - struct llarp_threadpool *worker) -{ - llarp_async_iwp *iwp = new llarp_async_iwp; - if(iwp) - { - iwp->crypto = crypto; - iwp->logic = logic; - iwp->worker = worker; - } - return iwp; -} - -void -llarp_async_iwp_free(struct llarp_async_iwp *iwp) -{ - delete iwp; -} diff --git a/llarp/nodedb.cpp b/llarp/nodedb.cpp index ce69abf0e..a533b491c 100644 --- a/llarp/nodedb.cpp +++ b/llarp/nodedb.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include