more onion routing stuff

pull/1/head
Jeff Becker 6 years ago
parent a947806b57
commit ec53cab169
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -1,2 +1,3 @@
{
"editor.formatOnSave": true
}

@ -83,6 +83,7 @@ set(LIB_SRC
llarp/crypto_async.cpp
llarp/crypto_libsodium.cpp
llarp/dht.cpp
llarp/encrypted_frame.cpp
llarp/ev.cpp
llarp/exit_info.cpp
llarp/exit_route.c
@ -95,6 +96,7 @@ set(LIB_SRC
llarp/mem.cpp
llarp/net.cpp
llarp/nodedb.cpp
llarp/path.cpp
llarp/relay_ack.cpp
llarp/relay_commit.cpp
llarp/relay_up_down.cpp

@ -4,6 +4,7 @@
#include <stdio.h>
#include <string.h>
#include <experimental/filesystem>
#include <llarp/crypto.hpp>
namespace fs = std::experimental::filesystem;
@ -205,7 +206,7 @@ main(int argc, char *argv[])
llarp_seckey_t identity;
llarp_findOrCreateIdentity(&crypt, ident_keyfile.c_str(), identity);
// get identity public key
uint8_t *pubkey = llarp_seckey_topublic(identity);
uint8_t *pubkey = llarp::seckey_topublic(identity);
llarp_rc_set_pubkey(&tmp, pubkey);
// this causes a segfault
llarp_rc_sign(&crypt, identity, &tmp);
@ -253,7 +254,7 @@ main(int argc, char *argv[])
llarp_seckey_t identity;
llarp_findOrCreateIdentity(&crypt, ident_keyfile.c_str(), identity);
// get identity public key
uint8_t *pubkey = llarp_seckey_topublic(identity);
uint8_t *pubkey = llarp::seckey_topublic(identity);
llarp_rc_set_pubkey(&tmp, pubkey);
llarp_rc_sign(&crypt, identity, &tmp);
// set filename

@ -38,15 +38,10 @@ typedef byte_t llarp_hmacsec_t[HMACSECSIZE];
typedef byte_t llarp_sig_t[SIGSIZE];
typedef byte_t llarp_tunnel_nonce_t[TUNNONCESIZE];
/// get public key from secret
byte_t *
llarp_seckey_topublic(byte_t *secret);
/// label functors
/// PKE(result, publickey, nonce, secretkey)
typedef bool (*llarp_dh_func)(llarp_sharedkey_t *, llarp_pubkey_t,
llarp_tunnel_nonce_t, llarp_seckey_t);
typedef bool (*llarp_path_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *);
/// TKE(result publickey, secretkey, nonce)
typedef bool (*llarp_transport_dh_func)(byte_t *, byte_t *, byte_t *, byte_t *);
@ -77,9 +72,9 @@ struct llarp_crypto
/// xchacha symettric cipher
llarp_sym_cipher_func xchacha20;
/// path dh creator's side
llarp_dh_func dh_client;
llarp_path_dh_func dh_client;
/// path dh relay side
llarp_dh_func dh_server;
llarp_path_dh_func dh_server;
/// transport dh client side
llarp_transport_dh_func transport_dh_client;
/// transport dh server side

@ -0,0 +1,34 @@
#ifndef LLARP_CRYPTO_HPP
#define LLARP_CRYPTO_HPP
#include <llarp/crypto.h>
#include <llarp/mem.h>
#include <llarp/threadpool.h>
#include <llarp/aligned.hpp>
namespace llarp
{
const byte_t*
seckey_topublic(const byte_t* secret);
byte_t*
seckey_topublic(byte_t* secret);
typedef AlignedBuffer< 32 > SharedSecret;
typedef AlignedBuffer< 32 > KeyExchangeNonce;
typedef AlignedBuffer< PUBKEYSIZE > PubKey;
struct PubKeyHash
{
std::size_t
operator()(PubKey const& a) const noexcept
{
size_t sz = 0;
memcpy(&sz, a.data(), sizeof(size_t));
return sz;
}
};
}
#endif

@ -1,12 +1,69 @@
#ifndef LLARP_ENCRYPTED_FRAME_HPP
#define LLARP_ENCRYPTED_FRAME_HPP
#include <llarp/crypto.h>
#include <llarp/mem.h>
#include <vector>
#include <llarp/threadpool.h>
namespace llarp
{
typedef std::vector< byte_t > EncryptedFrame;
struct EncryptedFrame
{
EncryptedFrame();
EncryptedFrame(const byte_t* buf, size_t sz);
~EncryptedFrame();
bool
DecryptInPlace(const byte_t* ourSecretKey, llarp_crypto* crypto);
llarp_buffer_t*
Buffer()
{
return &m_Buffer;
}
private:
byte_t* m_Buf;
size_t m_Sz;
llarp_buffer_t m_Buffer;
};
template < typename User >
struct AsyncFrameDecrypter
{
typedef void (*DecryptHandler)(llarp_buffer_t*, User*);
static void
Decrypt(void* user)
{
AsyncFrameDecrypter< User >* ctx =
static_cast< AsyncFrameDecrypter< User >* >(user);
if(ctx->target->DecryptInPlace(ctx->seckey, ctx->crypto))
ctx->result(ctx->target->Buffer(), ctx->context);
else
ctx->result(nullptr, ctx->context);
}
AsyncFrameDecrypter(llarp_crypto* c, const byte_t* secretkey,
DecryptHandler h)
: result(h), crypto(c), seckey(secretkey)
{
}
DecryptHandler result;
User* context;
llarp_crypto* crypto;
const byte_t* seckey;
EncryptedFrame* target;
void
AsyncDecrypt(llarp_threadpool* worker, EncryptedFrame* frame, User* user)
{
target = frame;
context = user;
llarp_threadpool_queue_job(worker, {this, &Decrypt});
}
};
}
#endif

@ -3,14 +3,13 @@
#include <llarp/bencode.h>
#include <llarp/link.h>
#include <llarp/aligned.hpp>
#include <llarp/router_id.hpp>
#include <queue>
#include <vector>
namespace llarp
{
typedef AlignedBuffer< 32 > RouterID;
struct ILinkMessage;

@ -3,6 +3,7 @@
#include <llarp/crypto.h>
#include <llarp/encrypted_frame.hpp>
#include <llarp/link_message.hpp>
#include <llarp/path_types.hpp>
#include <vector>
namespace llarp
@ -11,16 +12,20 @@ namespace llarp
{
llarp_pubkey_t commkey;
llarp_pubkey_t nextHop;
llarp_tunnel_nonce_t nonce;
uint64_t lifetime;
uint64_t pathid;
llarp_tunnel_nonce_t tunnelNonce;
PathID_t txid;
PathSymKey_t downstreamReplyKey;
SymmNonce_t downstreamReplyNonce;
uint64_t version;
bool
BDecode(llarp_buffer_t *buf);
static bool
OnKey(dict_reader *r, llarp_buffer_t *buf);
bool
BEncode(llarp_buffer_t *buf);
BEncode(llarp_buffer_t *buf) const;
};
struct LR_AcceptRecord
@ -30,10 +35,10 @@ namespace llarp
std::vector< byte_t > padding;
bool
BDecode(llarp_buffer_t *buf);
DecodeKey(llarp_buffer_t key, llarp_buffer_t *buf);
bool
BEncode(llarp_buffer_t *buf);
BEncode(llarp_buffer_t *buf) const;
};
struct LR_StatusMessage
@ -45,7 +50,7 @@ namespace llarp
BDecode(llarp_buffer_t *buf);
bool
BEncode(llarp_buffer_t *buf);
BEncode(llarp_buffer_t *buf) const;
};
struct LR_CommitMessage : public ILinkMessage
@ -70,42 +75,6 @@ namespace llarp
bool
HandleMessage(llarp_router *router) const;
};
struct AsyncPathDecryption
{
static void
Decrypted(void *data);
LR_CommitMessage lrcm;
LR_CommitRecord ourRecord;
llarp_threadpool *worker = nullptr;
llarp_crypto *crypto = nullptr;
llarp_logic *logic = nullptr;
llarp_thread_job result;
void
AsyncDecryptOurHop();
};
struct AsyncPathEncryption
{
static void
EncryptedFrame(void *data);
std::vector< LR_CommitRecord > hops;
LR_CommitMessage lrcm;
llarp_threadpool *worker = nullptr;
llarp_crypto *crypto = nullptr;
llarp_logic *logic = nullptr;
llarp_thread_job result;
void
AsyncEncrypt();
private:
void
EncryptNext();
};
}
#endif

@ -1,27 +0,0 @@
#ifndef LLARP_PATH_H
#define LLARP_PATH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <llarp/types.h>
typedef uint64_t llarp_path_id_t;
struct llarp_transit_hop
{
llarp_path_id_t id;
llarp_sharedkey_t symkey;
llarp_pubkey_t nextHop;
llarp_pubkey_t prevHop;
uint64_t started;
uint64_t lifetime;
llarp_proto_version_t version;
};
struct llarp_path_context;
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,233 @@
#ifndef LLARP_PATH_HPP
#define LLARP_PATH_HPP
#include <llarp/router.h>
#include <llarp/time.h>
#include <llarp/aligned.hpp>
#include <llarp/crypto.hpp>
#include <llarp/messages/relay_ack.hpp>
#include <llarp/messages/relay_commit.hpp>
#include <llarp/path_types.hpp>
#include <llarp/router_id.hpp>
#include <mutex>
#include <unordered_map>
#include <vector>
namespace llarp
{
struct TransitHopInfo
{
TransitHopInfo() = default;
TransitHopInfo(const RouterID& down, const LR_CommitRecord& record);
PathID_t rxID;
PathID_t txID;
RouterID upstream;
RouterID downstream;
friend std::ostream&
operator<<(std::ostream& out, const TransitHopInfo& info)
{
out << "<Transit Hop rxid=" << info.rxID << " txid=" << info.txID;
out << " upstream=" << info.upstream << " downstream=" << info.downstream;
return out << ">";
}
bool
operator==(const TransitHopInfo& other) const
{
return rxID == other.rxID && txID == other.txID
&& upstream == other.upstream && downstream == other.downstream;
}
bool
operator!=(const TransitHopInfo& other) const
{
return !(*this == other);
}
struct Hash
{
std::size_t
operator()(TransitHopInfo const& a) const
{
std::size_t idx0, idx1, idx2, idx3;
memcpy(&idx0, a.upstream, sizeof(std::size_t));
memcpy(&idx1, a.downstream, sizeof(std::size_t));
memcpy(&idx2, a.rxID, sizeof(std::size_t));
memcpy(&idx3, a.txID, sizeof(std::size_t));
return idx0 ^ idx1 ^ idx2 ^ idx3;
}
};
};
struct TransitHop
{
PathSymKey_t rxKey;
PathSymKey_t txKey;
llarp_time_t started;
llarp_proto_version_t version;
};
struct PathHopConfig
{
/// path id
PathID_t txID;
/// router identity key
PubKey encryptionKey;
/// shared secret at this hop
PathSymKey_t shared;
/// nonce for key exchange
PathNonce_t nonce;
};
struct Path
{
typedef std::vector< PathHopConfig > HopList;
HopList hops;
llarp_time_t buildStarted;
};
template < typename User >
struct AsyncPathKeyExchangeContext
{
Path path;
typedef void (*Handler)(AsyncPathKeyExchangeContext*);
User* user = nullptr;
Handler result = nullptr;
const byte_t* secretkey = nullptr;
size_t idx = 0;
llarp_threadpool* worker = nullptr;
llarp_path_dh_func dh = nullptr;
static void
GenerateNextKey(void* user)
{
AsyncPathKeyExchangeContext< User >* ctx =
static_cast< AsyncPathKeyExchangeContext< User >* >(user);
auto& hop = ctx->path.hops[ctx->idx];
ctx->dh(hop.shared, hop.encryptionKey, hop.nonce, ctx->secretkey);
++ctx->idx;
if(ctx->idx < ctx.path.hops.size())
{
llarp_threadpool_queue_job(ctx->worker, {ctx, &GenerateNextKey});
}
else
{
ctx->Done();
}
}
AsyncPathKeyExchangeContext(const byte_t* secret, llarp_crypto* crypto)
: secretkey(secret), dh(crypto->dh_client)
{
}
void
Done()
{
idx = 0;
result(this);
}
/// Generate all keys asynchronously and call hadler when done
void
AsyncGenerateKeys(llarp_threadpool* pool, User* u, Handler func) const
{
user = u;
result = func;
worker = pool;
llarp_threadpool_queue_job(pool, {this, &GenerateNextKey});
}
};
enum PathBuildStatus
{
ePathBuildSuccess,
ePathBuildTimeout,
ePathBuildReject
};
/// path selection algorithm
struct IPathSelectionAlgorithm
{
virtual ~IPathSelectionAlgorithm(){};
/// select full path given an empty hop list to end at target
virtual bool
SelectFullPathTo(Path::HopList& hops, const RouterID& target) = 0;
/// report to path builder the result of a path build
/// can be used to "improve" path building algoirthm in the
/// future
virtual void
ReportPathBuildStatus(const Path::HopList& hops, const RouterID& target,
PathBuildStatus status){};
};
class PathBuildJob
{
public:
PathBuildJob(llarp_router* router, IPathSelectionAlgorithm* selector);
~PathBuildJob();
void
Start();
private:
typedef AsyncPathKeyExchangeContext< PathBuildJob > KeyExchanger;
LR_CommitMessage*
BuildLRCM();
static void
KeysGenerated(KeyExchanger* ctx);
llarp_router* router;
IPathSelectionAlgorithm* m_HopSelector;
KeyExchanger m_KeyExchanger;
};
/// a pool of paths for a hidden service
struct PathPool
{
PathPool(llarp_router* router);
~PathPool();
/// build a new path to a router by identity key
PathBuildJob*
BuildNewPathTo(const RouterID& router);
};
struct PathContext
{
PathContext(llarp_router* router);
~PathContext();
void
AllowTransit();
void
RejectTransit();
bool
HasTransitHop(const TransitHopInfo& info);
bool
HandleRelayCommit(const LR_CommitMessage* msg);
bool
HandleRelayAck(const LR_AckMessage* msg);
typedef std::unordered_map< TransitHopInfo, TransitHop,
TransitHopInfo::Hash >
TransitHopsMap_t;
private:
llarp_router* m_Router;
std::mutex m_TransitPathsMutex;
TransitHopsMap_t m_TransitPaths;
bool m_AllowTransit;
};
}
#endif

@ -0,0 +1,17 @@
#ifndef LLARP_PATH_TYPES_HPP
#define LLARP_PATH_TYPES_HPP
#include <llarp/aligned.hpp>
namespace llarp
{
typedef AlignedBuffer< 16 > PathID_t;
typedef AlignedBuffer< 32 > PathSymKey_t;
typedef AlignedBuffer< 32 > PathNonce_t;
typedef AlignedBuffer< 24 > SymmNonce_t;
}
#endif

@ -24,6 +24,13 @@ llarp_init_router(struct llarp_threadpool *worker,
void
llarp_free_router(struct llarp_router **router);
/// send raw message to router we have a session with
/// return false on message not sent becasue we don't have a session otherwise
/// return true
bool
llarp_rotuer_sendto(struct llarp_router *router, const byte_t *pubkey,
llarp_buffer_t buf);
bool
llarp_router_try_connect(struct llarp_router *router, struct llarp_rc *remote);

@ -15,6 +15,9 @@ struct llarp_alloc;
struct llarp_rc
{
struct llarp_ai_list *addrs;
// public encryption public key
llarp_pubkey_t enckey;
// public signing public key
llarp_pubkey_t pubkey;
struct llarp_xi_list *exits;
llarp_sig_t signature;
@ -39,7 +42,7 @@ void
llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
struct llarp_ai_list *addr);
void
llarp_rc_set_pubkey(struct llarp_rc *rc, uint8_t *pubkey);
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubkey);
void
llarp_rc_sign(struct llarp_crypto *crypto, const byte_t *seckey,

@ -0,0 +1,11 @@
#ifndef LLARP_ROUTER_ID_HPP
#define LLARP_ROUTER_ID_HPP
#include <llarp/aligned.hpp>
namespace llarp
{
typedef AlignedBuffer< 32 > RouterID;
}
#endif

@ -0,0 +1,21 @@
#ifndef LLARP_ROUTING_ENDPOINT_HPP
#define LLARP_ROUTING_ENDPOINT_HPP
#include <llarp/aligned.hpp>
#include <llarp/buffer.h>
namespace llarp
{
typedef AlignedBuffer<32> RoutingEndpoint_t;
/// Interface for end to end crypto between endpoints
struct IRoutingEndpoint
{
virtual ~IRoutingEndpoint() {};
};
}
#endif

@ -1,23 +1 @@
#ifndef LLARP_CRYPTO_HPP
#define LLARP_CRYPTO_HPP
#include <llarp/crypto.h>
#include <llarp/aligned.hpp>
namespace llarp
{
typedef AlignedBuffer< PUBKEYSIZE > pubkey;
struct pubkeyhash
{
std::size_t
operator()(pubkey const& a) const noexcept
{
size_t sz = 0;
memcpy(&sz, a.data(), sizeof(size_t));
return sz;
}
};
}
#endif
#include <llarp/crypto.hpp>

@ -1,6 +1,7 @@
#include <llarp/crypto_async.h>
#include <llarp/mem.h>
#include <string.h>
#include <llarp/crypto.hpp>
#include "buffer.hpp"
#include "mem.hpp"
@ -56,7 +57,7 @@ namespace iwp
memcpy(tmp + 32, intro->nonce, 32);
crypto->shorthash(e_k, buf);
// e = SE(a.k, e_k, n[0:24])
memcpy(intro->buf + 64, llarp_seckey_topublic(intro->secretkey), 32);
memcpy(intro->buf + 64, llarp::seckey_topublic(intro->secretkey), 32);
buf.base = intro->buf + 64;
buf.cur = buf.base;
buf.sz = 32;
@ -80,7 +81,7 @@ namespace iwp
llarp_hmac_t h;
llarp_nonce_t N;
byte_t tmp[64];
auto OurPK = llarp_seckey_topublic(intro->secretkey);
auto OurPK = llarp::seckey_topublic(intro->secretkey);
// e_k = HS(b.k + n)
memcpy(tmp, OurPK, 32);
memcpy(tmp + 32, intro->nonce, 32);

@ -1,6 +1,7 @@
#include <assert.h>
#include <llarp/crypto.h>
#include <sodium.h>
#include <llarp/crypto.hpp>
#include "mem.hpp"
namespace llarp
@ -33,26 +34,24 @@ namespace llarp
}
static bool
dh_client(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nonce_t n, llarp_seckey_t sk)
dh_client(byte_t *shared, byte_t *pk, byte_t *n, byte_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, TUNNONCESIZE)
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE,
n, TUNNONCESIZE)
!= -1;
}
return false;
}
static bool
dh_server(llarp_sharedkey_t *shared, llarp_pubkey_t pk,
llarp_tunnel_nonce_t n, llarp_seckey_t sk)
dh_server(byte_t *shared, byte_t *pk, byte_t *n, byte_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, TUNNONCESIZE)
return crypto_generichash(shared, SHAREDKEYSIZE, shared, SHAREDKEYSIZE,
n, TUNNONCESIZE)
!= -1;
}
return false;
@ -62,7 +61,7 @@ namespace llarp
transport_dh_client(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
llarp_sharedkey_t dh_result;
if(dh(dh_result, llarp_seckey_topublic(sk), pk, pk, sk))
if(dh(dh_result, llarp::seckey_topublic(sk), pk, pk, sk))
{
return crypto_generichash(shared, 32, n, 32, dh_result, 32) != -1;
}
@ -73,7 +72,7 @@ namespace llarp
transport_dh_server(uint8_t *shared, uint8_t *pk, uint8_t *sk, uint8_t *n)
{
llarp_sharedkey_t dh_result;
if(dh(dh_result, pk, llarp_seckey_topublic(sk), pk, sk))
if(dh(dh_result, pk, llarp::seckey_topublic(sk), pk, sk))
{
return crypto_generichash(shared, 32, n, 32, dh_result, 32) != -1;
}
@ -138,16 +137,28 @@ namespace llarp
static void
enckeygen(uint8_t *keys)
{
randombytes(keys, 32);
crypto_scalarmult_curve25519_base(keys + 32, keys);
crypto_box_keypair(keys + 32, keys);
}
} // namespace sodium
const byte_t *
seckey_topublic(const byte_t *sec)
{
return sec + 32;
}
byte_t *
seckey_topublic(byte_t *sec)
{
return sec + 32;
}
} // namespace llarp
extern "C" {
uint8_t *
llarp_seckey_topublic(uint8_t *secret)
const byte_t *
llarp_seckey_topublic(const byte_t *secret)
{
return secret + 32;
}

@ -0,0 +1,31 @@
#include <llarp/encrypted_frame.hpp>
namespace llarp
{
EncryptedFrame::EncryptedFrame() : m_Buf(nullptr), m_Sz(0)
{
}
EncryptedFrame::EncryptedFrame(const byte_t* buf, size_t sz)
{
m_Sz = sz;
m_Buf = new byte_t[m_Sz];
memcpy(m_Buf, buf, sz);
m_Buffer.base = m_Buf;
m_Buffer.cur = m_Buf;
m_Buffer.sz = sz;
}
EncryptedFrame::~EncryptedFrame()
{
if(m_Buf)
delete[] m_Buf;
}
bool
EncryptedFrame::DecryptInPlace(const byte_t* ourSecretKey,
llarp_crypto* crypto)
{
return false;
}
}

@ -2,6 +2,7 @@
#include <llarp/iwp.h>
#include <llarp/net.h>
#include <llarp/time.h>
#include <llarp/crypto.hpp>
#include "link/encoder.hpp"
#include <sodium/crypto_sign_ed25519.h>
@ -19,7 +20,6 @@
#include <vector>
#include "buffer.hpp"
#include "crypto.hpp"
#include "fs.hpp"
#include "logger.hpp"
#include "mem.hpp"
@ -1233,7 +1233,7 @@ namespace iwp
LinkMap_t m_sessions;
mtx_t m_sessions_Mutex;
typedef std::unordered_map< llarp::pubkey, llarp::Addr, llarp::pubkeyhash >
typedef std::unordered_map< llarp::PubKey, llarp::Addr, llarp::PubKeyHash >
SessionMap_t;
SessionMap_t m_Connected;
@ -1257,7 +1257,7 @@ namespace iwp
// set that src address has identity pubkey
void
MapAddr(const llarp::Addr &src, llarp::pubkey identity)
MapAddr(const llarp::Addr &src, const llarp::PubKey &identity)
{
lock_t lock(m_Connected_Mutex);
m_Connected[identity] = src;
@ -1267,7 +1267,7 @@ namespace iwp
HasSessionToRouter(llarp_link *l, const byte_t *pubkey)
{
server *serv = static_cast< server * >(l->impl);
llarp::pubkey pk(pubkey);
llarp::PubKey pk(pubkey);
lock_t lock(serv->m_Connected_Mutex);
return serv->m_Connected.find(pk) != serv->m_Connected.end();
}
@ -1413,7 +1413,7 @@ namespace iwp
uint8_t *
pubkey()
{
return llarp_seckey_topublic(seckey);
return llarp::seckey_topublic(seckey);
}
bool

@ -1,9 +1,9 @@
#include <llarp/nodedb.h>
#include <llarp/crypto.hpp>
#include <llarp/router_contact.h>
#include <fstream>
#include <map>
#include <unordered_map>
#include "buffer.hpp"
#include "crypto.hpp"
#include "fs.hpp"
#include "mem.hpp"
@ -16,7 +16,7 @@ struct llarp_nodedb
}
llarp_crypto *crypto;
std::map< llarp::pubkey, llarp_rc * > entries;
std::unordered_map< llarp::PubKey, llarp_rc * , llarp::PubKeyHash> entries;
void
Clear()
@ -81,8 +81,7 @@ struct llarp_nodedb
{
if(llarp_rc_verify_sig(crypto, rc))
{
llarp::pubkey pk;
memcpy(pk.data(), rc->pubkey, pk.size());
llarp::PubKey pk(&rc->pubkey[0]);
entries[pk] = rc;
return true;
}

@ -0,0 +1,121 @@
#include <llarp/encrypted_frame.hpp>
#include <llarp/path.hpp>
#include "router.hpp"
namespace llarp
{
PathContext::PathContext(llarp_router* router)
: m_Router(router), m_AllowTransit(false)
{
}
PathContext::~PathContext()
{
}
void
PathContext::AllowTransit()
{
m_AllowTransit = true;
}
struct LRCMFrameDecrypt
{
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
Decrypter* decrypter;
std::vector< EncryptedFrame > leftovers;
EncryptedFrame ourFrame;
PathContext* context;
RouterID from;
LR_CommitRecord record;
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
const LR_CommitMessage* commit)
: decrypter(dec), context(ctx), from(commit->remote)
{
auto sz = commit->frames.size();
size_t idx = 0;
while(idx < sz)
{
if(sz == 0)
ourFrame = commit->frames[idx];
else
leftovers.push_back(commit->frames[idx]);
++idx;
}
}
~LRCMFrameDecrypt()
{
delete decrypter;
}
static void
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
{
if(buf)
{
llarp::Debug("decrypted LRCM from ", self->from);
// successful decrypt
if(self->record.BDecode(buf))
{
TransitHopInfo info(self->from, self->record);
if(self->context->HasTransitHop(info))
{
// duplicate hop
llarp::Warn("duplicate transit hop ", info);
}
else
{
// accepted
return;
}
}
else
llarp::Error("malformed LR Commit Record from ", self->from);
}
else
llarp::Debug("malformed frame inside LRCM from ", self->from);
delete self;
}
};
bool
PathContext::HandleRelayCommit(const LR_CommitMessage* commit)
{
if(!m_AllowTransit)
{
llarp::Error("got LRCM from ", commit->remote,
" when not allowing transit traffic");
return false;
}
if(commit->frames.size() <= 1)
{
llarp::Error("got LRCM with too few frames from ", commit->remote);
return false;
}
LRCMFrameDecrypt::Decrypter* decrypter =
new LRCMFrameDecrypt::Decrypter(&m_Router->crypto, m_Router->encryption,
&LRCMFrameDecrypt::HandleDecrypted);
// copy frames so we own them
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(this, decrypter, commit);
// decrypt frames async
decrypter->AsyncDecrypt(m_Router->tp, &frames->ourFrame, frames);
return true;
}
bool
PathContext::HasTransitHop(const TransitHopInfo& info)
{
std::unique_lock< std::mutex > lock(m_TransitPathsMutex);
return m_TransitPaths.find(info) != m_TransitPaths.end();
}
TransitHopInfo::TransitHopInfo(const RouterID& down,
const LR_CommitRecord& record)
: txID(record.txid), upstream(record.nextHop), downstream(down)
{
}
}

@ -1,4 +1,6 @@
#include <llarp/messages/relay_commit.hpp>
#include "logger.hpp"
#include "router.hpp"
namespace llarp
{
@ -23,7 +25,100 @@ namespace llarp
bool
LR_CommitMessage::HandleMessage(llarp_router* router) const
{
// TODO: implement
return router->paths.HandleRelayCommit(this);
}
bool
LR_CommitRecord::BEncode(llarp_buffer_t* buf) const
{
return false;
}
bool
LR_CommitRecord::OnKey(dict_reader* r, llarp_buffer_t* key)
{
if(!key)
return true;
llarp_buffer_t strbuf;
LR_CommitRecord* self = static_cast< LR_CommitRecord* >(r->user);
if(llarp_buffer_eq(*key, "c"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(self->commkey, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "i"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(self->nextHop, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "n"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_tunnel_nonce_t))
return false;
memcpy(self->tunnelNonce, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "p"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != self->txid.size())
return false;
memcpy(self->txid, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "s"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != self->downstreamReplyKey.size())
return false;
memcpy(self->downstreamReplyKey, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "u"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != self->downstreamReplyNonce.size())
return false;
memcpy(self->downstreamReplyNonce, strbuf.base, strbuf.sz);
return true;
}
if(llarp_buffer_eq(*key, "v"))
{
if(!bencode_read_integer(r->buffer, &self->version))
return false;
return self->version == LLARP_PROTO_VERSION;
}
return false;
}
bool
LR_CommitRecord::BDecode(llarp_buffer_t* buf)
{
dict_reader r;
r.user = this;
r.on_key = &OnKey;
return bencode_read_dict(buf, &r);
}
}

@ -29,7 +29,8 @@ namespace llarp
} // namespace llarp
llarp_router::llarp_router()
: ready(false), dht(llarp_dht_context_new(this)), inbound_msg_parser(this)
: ready(false), paths(this), inbound_msg_parser(this)
{
llarp_rc_clear(&rc);
}
@ -98,7 +99,7 @@ llarp_router::SendToOrQueue(const llarp::RouterID &remote,
for(const auto &msg : msgs)
{
outboundMesssageQueue[remote].push(msg);
outboundMesssageQueue[remote.data()].push(msg);
}
FlushOutboundFor(remote, chosen);
return true;
@ -154,9 +155,38 @@ llarp_router::try_connect(fs::path rcfile)
bool
llarp_router::EnsureIdentity()
{
if(!EnsureEncryptionKey())
return false;
return llarp_findOrCreateIdentity(&crypto, ident_keyfile.c_str(), identity);
}
bool
llarp_router::EnsureEncryptionKey()
{
std::error_code ec;
if(!fs::exists(encryption_keyfile, ec))
{
llarp::Info("generating encryption key");
crypto.encryption_keygen(encryption);
std::ofstream f(encryption_keyfile, std::ios::binary);
if(!f.is_open())
{
llarp::Error("could not save encryption private key to ",
encryption_keyfile, " ", ec);
return false;
}
f.write((char *)encryption, sizeof(llarp_seckey_t));
}
std::ifstream f(encryption_keyfile, std::ios::binary);
if(!f.is_open())
{
llarp::Error("could not read ", encryption_keyfile);
return false;
}
f.read((char *)encryption, sizeof(llarp_seckey_t));
return true;
}
void
llarp_router::AddInboundLink(struct llarp_link *link)
{
@ -257,27 +287,28 @@ llarp_router::on_verify_server_rc(llarp_async_verify_rc *job)
llarp::Debug("rc verified");
// track valid router in dht
llarp::pubkey pubkey;
memcpy(&pubkey[0], job->rc.pubkey, pubkey.size());
llarp::PubKey pk(job->rc.pubkey);
// refresh valid routers RC value if it's there
auto v = router->validRouters.find(pubkey);
auto v = router->validRouters.find(pk);
if(v != router->validRouters.end())
{
// free previous RC members
llarp_rc_free(&v->second);
}
router->validRouters[pubkey] = job->rc;
router->validRouters[pk] = job->rc;
// TODO: update nodedb here (?)
// track valid router in dht
llarp_dht_put_local_router(router->dht, &router->validRouters[pubkey]);
if(router->dht)
llarp_dht_put_local_router(router->dht, &router->validRouters[pk]);
// this was an outbound establish job
if(ctx->establish_job->session)
{
auto session = ctx->establish_job->session;
router->FlushOutboundFor(pubkey, session->get_parent(session));
router->FlushOutboundFor(pk, session->get_parent(session));
}
llarp_rc_free(&job->rc);
delete job;
@ -450,7 +481,8 @@ llarp_router::Run()
link->get_our_address(link, &addr);
llarp_ai_list_pushback(rc.addrs, &addr);
};
// set public key
// set public keys
memcpy(rc.enckey, llarp::seckey_topublic(encryption), sizeof(llarp_pubkey_t));
llarp_rc_set_pubkey(&rc, pubkey());
llarp_rc_sign(&crypto, identity, &rc);
@ -460,31 +492,49 @@ llarp_router::Run()
return;
}
llarp::pubkey ourPubkey = pubkey();
llarp::Info("our router has public key ", ourPubkey);
llarp_dht_context_start(dht, ourPubkey);
llarp::Debug("starting outbound link");
if(!outboundLink->start_link(outboundLink, logic))
{
llarp::Warn("outbound link failed to start");
}
int IBLinksStarted = 0;
// start links
for(auto link : inboundLinks)
{
if(link->start_link(link, logic))
{
llarp::Debug("Link ", link->name(), " started");
IBLinksStarted++;
}
else
llarp::Warn("Link ", link->name(), " failed to start");
}
if(IBLinksStarted > 0)
{
// initialize as service node
InitServiceNode();
}
llarp_logic_call_later(logic, {1000, this, &ConnectAll});
ScheduleTicker(500);
}
void
llarp_router::InitServiceNode()
{
llarp::PubKey ourPubkey = pubkey();
llarp::Info("starting dht context as ", ourPubkey);
dht = llarp_dht_context_new(this);
llarp_dht_context_start(dht, ourPubkey);
llarp::Info("accepting transit traffic");
paths.AllowTransit();
}
void
llarp_router::ConnectAll(void *user, uint64_t orig, uint64_t left)
{
@ -649,7 +699,7 @@ llarp_rc_set_addrs(struct llarp_rc *rc, struct llarp_alloc *mem,
}
void
llarp_rc_set_pubkey(struct llarp_rc *rc, uint8_t *pubkey)
llarp_rc_set_pubkey(struct llarp_rc *rc, const uint8_t *pubkey)
{
// set public key
memcpy(rc->pubkey, pubkey, 32);
@ -820,6 +870,10 @@ namespace llarp
}
else if(StrEq(section, "router"))
{
if(StrEq(key, "encryption-privkey"))
{
self->encryption_keyfile = val;
}
if(StrEq(key, "contact-file"))
{
self->our_rc_file = val;

@ -3,9 +3,9 @@
#include <llarp/dht.h>
#include <llarp/link.h>
#include <llarp/nodedb.h>
#include <llarp/path.h>
#include <llarp/router.h>
#include <llarp/router_contact.h>
#include <llarp/path.hpp>
#include <functional>
#include <list>
@ -41,6 +41,8 @@ struct llarp_router
// long term identity key
fs::path ident_keyfile = "identity.key";
fs::path encryption_keyfile = "encryption.key";
// path to write our self signed rc to
fs::path our_rc_file = "rc.signed";
@ -51,10 +53,11 @@ struct llarp_router
llarp_threadpool *tp;
llarp_logic *logic;
llarp_crypto crypto;
llarp_path_context *paths;
llarp::PathContext paths;
llarp_seckey_t identity;
llarp_seckey_t encryption;
llarp_threadpool *disk;
llarp_dht_context *dht;
llarp_dht_context *dht = nullptr;
llarp_nodedb *nodedb;
@ -74,11 +77,11 @@ struct llarp_router
typedef std::queue< llarp::ILinkMessage * > MessageQueue;
/// outbound message queue
std::unordered_map< llarp::pubkey, MessageQueue, llarp::pubkeyhash >
std::unordered_map< llarp::PubKey, MessageQueue, llarp::PubKeyHash >
outboundMesssageQueue;
/// loki verified routers
std::unordered_map< llarp::pubkey, llarp_rc, llarp::pubkeyhash > validRouters;
std::unordered_map< llarp::PubKey, llarp_rc, llarp::PubKeyHash > validRouters;
llarp_router();
~llarp_router();
@ -92,6 +95,10 @@ struct llarp_router
bool
InitOutboundLink();
/// initialize us as a service node
void
InitServiceNode();
void
Close();
@ -107,13 +114,16 @@ struct llarp_router
bool
EnsureIdentity();
bool
EnsureEncryptionKey();
bool
SaveRC();
uint8_t *
pubkey()
const byte_t *
pubkey() const
{
return llarp_seckey_topublic(identity);
return llarp::seckey_topublic(identity);
}
void

@ -45,6 +45,16 @@ llarp_rc_decode_dict(struct dict_reader *r, llarp_buffer_t *key)
return llarp_ai_list_bdecode(rc->addrs, r->buffer);
}
if(llarp_buffer_eq(*key, "e"))
{
if(!bencode_read_string(r->buffer, &strbuf))
return false;
if(strbuf.sz != sizeof(llarp_pubkey_t))
return false;
memcpy(rc->enckey, strbuf.base, sizeof(llarp_pubkey_t));
return true;
}
if(llarp_buffer_eq(*key, "k"))
{
if(!bencode_read_string(r->buffer, &strbuf))
@ -98,6 +108,7 @@ llarp_rc_copy(struct llarp_rc *dst, const struct llarp_rc *src)
llarp_rc_free(dst);
llarp_rc_clear(dst);
memcpy(dst->pubkey, src->pubkey, sizeof(llarp_pubkey_t));
memcpy(dst->enckey, src->enckey, sizeof(llarp_pubkey_t));
memcpy(dst->signature, src->signature, sizeof(llarp_sig_t));
dst->last_updated = src->last_updated;
@ -164,7 +175,14 @@ llarp_rc_bencode(struct llarp_rc *rc, llarp_buffer_t *buff)
if(!llarp_ai_list_bencode(rc->addrs, buff))
return false;
}
/* write pubkey */
/* write encryption pubkey */
if(!bencode_write_bytestring(buff, "e", 1))
return false;
if(!bencode_write_bytestring(buff, rc->enckey, sizeof(llarp_pubkey_t)))
return false;
/* write signing pubkey */
if(!bencode_write_bytestring(buff, "k", 1))
return false;
if(!bencode_write_bytestring(buff, rc->pubkey, sizeof(llarp_pubkey_t)))

Loading…
Cancel
Save