more onion routing code

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

@ -227,14 +227,14 @@ to encrypt a frame to a router with public key B.k
A.k, s = ECKG()
n = RAND(32)
S = PKE(p, A.k, B.k)
S = PKE(p, A.k, B.k, n)
1) encode and encrypt
x = BE(msg)
new_x = SE(S, n[0:24], x)
2) generate hmac
2) generate message authentication
h = MDS(n + A.k + new_x, S)

@ -76,7 +76,7 @@ namespace llarp
void
Randomize()
{
randombytes(l, sz);
randombytes(b, sz);
}
byte_t*

@ -3,6 +3,7 @@
#include <llarp/bencode.h>
#include <llarp/buffer.h>
#include <sodium.h>
namespace llarp
{
@ -20,6 +21,13 @@ namespace llarp
return bencode_write_bytestring(buf, data, size);
}
void
Randomize()
{
if(data)
randombytes(data, size);
}
bool
BDecode(llarp_buffer_t* buf)
{

@ -90,7 +90,6 @@ namespace llarp
ctx->result(ctx->target->Buffer(), ctx->context);
else
ctx->result(nullptr, ctx->context);
delete ctx->target;
}
AsyncFrameDecrypter(llarp_crypto* c, byte_t* secretkey, DecryptHandler h)

@ -1,11 +1,33 @@
#ifndef LLARP_MESSAGES_RELAY_ACK_HPP
#define LLARP_MESSAGES_RELAY_ACK_HPP
#include <llarp/crypto.hpp>
#include <llarp/encrypted_frame.hpp>
#include <llarp/link_message.hpp>
#include <llarp/path_types.hpp>
namespace llarp
{
struct LR_AckRecord
{
PubKey pubkey;
TunnelNonce nonce;
PathID_t rxPathID;
uint64_t version = 0;
bool
BEncode(llarp_buffer_t* buf) const;
bool
BDecode(llarp_buffer_t* buf);
};
struct LR_AckMessage : public ILinkMessage
{
std::vector< EncryptedFrame > acks;
EncryptedFrame lasthopFrame;
PathID_t txPathID;
uint64_t version = 0;
LR_AckMessage(const RouterID& from);
~LR_AckMessage();

@ -50,6 +50,9 @@ namespace llarp
std::vector< EncryptedAck > acks;
uint64_t version;
LR_CommitMessage() : ILinkMessage()
{
}
LR_CommitMessage(const RouterID &from) : ILinkMessage(from)
{
}

@ -63,6 +63,8 @@ namespace llarp
struct TransitHop
{
TransitHop() = default;
SharedSecret rxKey;
SharedSecret txKey;
llarp_time_t started;
@ -218,14 +220,76 @@ namespace llarp
bool
HandleRelayAck(const LR_AckMessage* msg);
void
PutPendingRelayCommit(const RouterID& router, const PathID_t& txid,
const TransitHopInfo& info, const TransitHop& hop);
bool
HasPendingRelayCommit(const RouterID& upstream, const PathID_t& txid);
bool
ForwardLRCM(const RouterID& nextHop, std::deque< EncryptedFrame >& frames,
std::deque< EncryptedAck >& acks, EncryptedFrame& lastFrame);
bool
HopIsUs(const PubKey& k) const;
typedef std::unordered_map< TransitHopInfo, TransitHop,
TransitHopInfo::Hash >
TransitHopsMap_t;
typedef std::pair< std::mutex, TransitHopsMap_t > SyncTransitMap_t;
struct PendingPathKey
{
RouterID upstream;
PathID_t txID;
PendingPathKey(const RouterID& up, const PathID_t& id)
: upstream(up), txID(id)
{
}
bool
operator==(const PendingPathKey& other) const
{
return upstream == other.upstream && txID == other.txID;
}
struct Hash
{
std::size_t
operator()(PendingPathKey const& a) const
{
std::size_t idx0, idx1;
memcpy(&idx0, a.upstream, sizeof(std::size_t));
memcpy(&idx1, a.txID, sizeof(std::size_t));
return idx0 ^ idx1;
}
};
};
typedef std::pair< TransitHopInfo, TransitHop > PendingCommit_t;
typedef std::pair< std::mutex,
std::unordered_map< PendingPathKey, PendingCommit_t,
PendingPathKey::Hash > >
SyncPendingCommitMap_t;
llarp_threadpool*
Worker();
llarp_crypto*
Crypto();
byte_t*
EncryptionSecretKey();
private:
llarp_router* m_Router;
std::mutex m_TransitPathsMutex;
TransitHopsMap_t m_TransitPaths;
SyncTransitMap_t m_TransitPaths;
SyncPendingCommitMap_t m_WaitingForAcks;
bool m_AllowTransit;
};
}

@ -1,3 +1,4 @@
#include <deque>
#include <llarp/encrypted_frame.hpp>
#include <llarp/path.hpp>
#include "router.hpp"
@ -23,26 +24,24 @@ namespace llarp
{
typedef AsyncFrameDecrypter< LRCMFrameDecrypt > Decrypter;
Decrypter* decrypter;
std::vector< EncryptedFrame > leftovers;
EncryptedFrame ourFrame;
std::deque< EncryptedFrame > frames;
std::deque< EncryptedAck > acks;
EncryptedFrame lastFrame;
PathContext* context;
RouterID from;
LR_CommitRecord record;
LRCMFrameDecrypt(PathContext* ctx, Decrypter* dec,
const LR_CommitMessage* commit)
: decrypter(dec), context(ctx), from(commit->remote)
: decrypter(dec)
, lastFrame(commit->lasthopFrame)
, 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;
}
for(const auto& f : commit->frames)
frames.push_front(f);
for(const auto& a : commit->acks)
acks.push_front(a);
}
~LRCMFrameDecrypt()
@ -53,30 +52,62 @@ namespace llarp
static void
HandleDecrypted(llarp_buffer_t* buf, LRCMFrameDecrypt* self)
{
if(buf)
if(!buf)
{
llarp::Error("LRCM decrypt failed from ", self->from);
delete self;
return;
}
llarp::Debug("decrypted LRCM from ", self->from);
// successful decrypt
if(!self->record.BDecode(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);
llarp::Error("malformed frame inside LRCM from ", self->from);
delete self;
return;
}
TransitHopInfo info(self->from, self->record);
if(self->context->HasTransitHop(info))
{
llarp::Error("duplicate transit hop ", info);
delete self;
return;
}
TransitHop hop;
// choose rx id
// TODO: check for duplicates
info.rxID.Randomize();
// generate tx key as we are in a worker thread
auto DH = self->context->Crypto()->dh_server;
if(!DH(hop.txKey, self->record.commkey,
self->context->EncryptionSecretKey(), self->record.tunnelNonce))
{
llarp::Error("LRCM DH Failed ", info);
delete self;
return;
}
if(self->context->HopIsUs(self->record.nextHop))
{
// we are the farthest hop
llarp::Info("We are the farthest hop for ", info);
}
else
llarp::Debug("malformed frame inside LRCM from ", self->from);
delete self;
{
llarp::Info("Accepted ", info);
self->context->PutPendingRelayCommit(info.upstream, info.txID, info,
hop);
size_t sz = self->frames.front().size;
// we pop the front element it was ours
self->frames.pop_front();
// put random on the end
// TODO: should this be an encrypted frame?
self->frames.emplace_back(sz);
self->frames.back().Randomize();
// forward upstream
self->context->ForwardLRCM(info.upstream, self->frames, self->acks,
self->lastFrame);
}
}
};
@ -101,16 +132,93 @@ namespace llarp
LRCMFrameDecrypt* frames = new LRCMFrameDecrypt(this, decrypter, commit);
// decrypt frames async
decrypter->AsyncDecrypt(m_Router->tp, &frames->ourFrame, frames);
decrypter->AsyncDecrypt(m_Router->tp, &frames->frames.front(), frames);
return true;
}
llarp_threadpool*
PathContext::Worker()
{
return m_Router->tp;
}
llarp_crypto*
PathContext::Crypto()
{
return &m_Router->crypto;
}
byte_t*
PathContext::EncryptionSecretKey()
{
return m_Router->encryption;
}
bool
PathContext::HopIsUs(const PubKey& k) const
{
return memcmp(k, m_Router->pubkey(), PUBKEYSIZE) == 0;
}
bool
PathContext::ForwardLRCM(const RouterID& nextHop,
std::deque< EncryptedFrame >& frames,
std::deque< EncryptedAck >& acks,
EncryptedFrame& lastHop)
{
LR_CommitMessage* msg = new LR_CommitMessage;
while(frames.size())
{
msg->frames.push_back(frames.front());
frames.pop_front();
}
while(acks.size())
{
msg->acks.push_back(acks.front());
acks.pop_front();
}
msg->lasthopFrame = lastHop;
return m_Router->SendToOrQueue(nextHop, {msg});
}
template < typename Map_t, typename Value_t >
bool
MapHas(Map_t& map, const Value_t& val)
{
std::unique_lock< std::mutex > lock(map.first);
return map.second.find(val) != map.second.end();
}
template < typename Map_t, typename Key_t, typename Value_t >
void
MapPut(Map_t& map, const Key_t& k, const Value_t& v)
{
std::unique_lock< std::mutex > lock(map.first);
map.second[k] = v;
}
bool
PathContext::HasTransitHop(const TransitHopInfo& info)
{
std::unique_lock< std::mutex > lock(m_TransitPathsMutex);
return m_TransitPaths.find(info) != m_TransitPaths.end();
return MapHas(m_TransitPaths, info);
}
void
PathContext::PutPendingRelayCommit(const RouterID& upstream,
const PathID_t& txid,
const TransitHopInfo& info,
const TransitHop& hop)
{
MapPut(m_WaitingForAcks, PendingPathKey(upstream, txid),
std::make_pair(info, hop));
}
bool
PathContext::HasPendingRelayCommit(const RouterID& upstream,
const PathID_t& txid)
{
return MapHas(m_WaitingForAcks, PendingPathKey(upstream, txid));
}
TransitHopInfo::TransitHopInfo(const RouterID& down,

@ -1,28 +1,91 @@
#include <llarp/messages/relay_ack.hpp>
namespace llarp
#include "router.hpp"
namespace llarp
{
LR_AckMessage::LR_AckMessage(const RouterID & from) : ILinkMessage(from)
bool
LR_AckRecord::BEncode(llarp_buffer_t* buf) const
{
return false;
}
bool
LR_AckRecord::BDecode(llarp_buffer_t* buf)
{
return false;
}
LR_AckMessage::LR_AckMessage(const RouterID& from) : ILinkMessage(from)
{
}
LR_AckMessage::~LR_AckMessage()
{
}
bool LR_AckMessage::BEncode(llarp_buffer_t * buf) const
bool
LR_AckMessage::BEncode(llarp_buffer_t* buf) const
{
return false;
}
bool LR_AckMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t * buf)
bool
LR_AckMessage::DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf)
{
return false;
}
bool LR_AckMessage::HandleMessage(llarp_router * router) const
struct LRAM_Decrypt
{
return false;
typedef AsyncFrameDecrypter< LRAM_Decrypt > Decrypter;
llarp_router* router;
Decrypter* decrypt;
std::vector< EncryptedFrame > frames;
LR_AckRecord record;
LRAM_Decrypt(llarp_router* r, byte_t* seckey,
const std::vector< EncryptedFrame >& f)
: router(r), frames(f)
{
decrypt = new Decrypter(&r->crypto, seckey, &Decrypted);
}
~LRAM_Decrypt()
{
delete decrypt;
}
static void
Decrypted(llarp_buffer_t* buf, LRAM_Decrypt* self)
{
if(!buf)
{
llarp::Error("Failed to decrypt LRAM frame");
delete self;
return;
}
if(!self->record.BDecode(buf))
{
llarp::Error("LRAR invalid format");
delete self;
return;
}
}
};
bool
LR_AckMessage::HandleMessage(llarp_router* router) const
{
if(!router->paths.HasPendingRelayCommit(remote, txPathID))
{
llarp::Warn("got LRAM from ", remote,
" with no previous LRCM txid=", txPathID);
return false;
}
// TODO: use different private key for different path contexts as client
LRAM_Decrypt* lram = new LRAM_Decrypt(router, router->encryption, acks);
lram->decrypt->AsyncDecrypt(router->tp, &lram->frames[0], lram);
return true;
}
}
Loading…
Cancel
Save