mirror of https://github.com/oxen-io/lokinet
more hidden service stuff
This commit is contained in:
parent
02ca1796b2
commit
d38646ed54
|
@ -242,6 +242,7 @@ set(LIB_SRC
|
|||
llarp/service/address.cpp
|
||||
llarp/service/context.cpp
|
||||
llarp/service/endpoint.cpp
|
||||
llarp/service/frame.cpp
|
||||
llarp/service/lookup.cpp
|
||||
llarp/service/protocol.cpp
|
||||
llarp/service/tag.cpp
|
||||
|
|
|
@ -525,6 +525,8 @@ TODO: document this better
|
|||
|
||||
intro message (variant 1)
|
||||
|
||||
start a new session
|
||||
|
||||
{
|
||||
A: "H",
|
||||
D: "<N bytes encrypted HSD>",
|
||||
|
@ -535,6 +537,10 @@ intro message (variant 1)
|
|||
Z: "<64 bytes signature of entire message using sender's signing key>"
|
||||
}
|
||||
|
||||
D is encrypted with session key K which is derived by
|
||||
|
||||
K = PKE(H, SI.enckey, N)
|
||||
|
||||
ordered data message (variant 2)
|
||||
|
||||
{
|
||||
|
@ -552,6 +558,7 @@ data sent anonymously over the network to a recipiant from a sender.
|
|||
sent inside a HSFM encrypted with a shared secret.
|
||||
|
||||
{
|
||||
A: protocol_number_uint,
|
||||
D: "<N bytes payload>",
|
||||
I: Introduction for reply,
|
||||
S: SI of sender,
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/encrypted.hpp>
|
||||
#include <llarp/routing/message.hpp>
|
||||
#include <llarp/service/protocol.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
|
@ -12,8 +13,8 @@ namespace llarp
|
|||
struct PathTransferMessage : public IMessage
|
||||
{
|
||||
PathID_t P;
|
||||
Encrypted T;
|
||||
uint64_t V = 0;
|
||||
service::ProtocolFrame* T = nullptr;
|
||||
uint64_t V = 0;
|
||||
TunnelNonce Y;
|
||||
|
||||
PathTransferMessage();
|
||||
|
|
|
@ -81,6 +81,9 @@ namespace llarp
|
|||
Path*
|
||||
PickRandomEstablishedPath();
|
||||
|
||||
Path*
|
||||
GetPathByRouter(const RouterID& router);
|
||||
|
||||
bool
|
||||
GetCurrentIntroductions(
|
||||
std::set< llarp::service::Introduction >& intros) const;
|
||||
|
|
|
@ -43,6 +43,9 @@ namespace llarp
|
|||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* buf);
|
||||
|
||||
void
|
||||
Clear();
|
||||
|
||||
bool
|
||||
operator<(const Introduction& other) const
|
||||
{
|
||||
|
|
|
@ -36,6 +36,12 @@ namespace llarp
|
|||
llarp_threadpool*
|
||||
Worker();
|
||||
|
||||
llarp_router*
|
||||
Router()
|
||||
{
|
||||
return m_Router;
|
||||
}
|
||||
|
||||
bool
|
||||
Start();
|
||||
|
||||
|
@ -63,8 +69,11 @@ namespace llarp
|
|||
bool
|
||||
ForgetPathToService(const Address& remote);
|
||||
|
||||
byte_t*
|
||||
GetEncryptionSecretKey();
|
||||
Identity*
|
||||
GetIdentity()
|
||||
{
|
||||
return &m_Identity;
|
||||
}
|
||||
|
||||
/// context needed to initiate an outbound hidden service session
|
||||
struct OutboundContext : public llarp_pathbuilder_context
|
||||
|
@ -74,6 +83,12 @@ namespace llarp
|
|||
|
||||
/// the remote hidden service's curren intro set
|
||||
IntroSet currentIntroSet;
|
||||
/// the current selected intro
|
||||
Introduction selectedIntro;
|
||||
|
||||
/// update the current selected intro to be a new best introduction
|
||||
void
|
||||
ShiftIntroduction();
|
||||
|
||||
/// encrypt asynchronously and send to remote endpoint from us
|
||||
void
|
||||
|
@ -91,26 +106,17 @@ namespace llarp
|
|||
|
||||
private:
|
||||
void
|
||||
AsyncEncrypt(ProtocolMessage* msg,
|
||||
std::function< void(ProtocolMessage*) > result);
|
||||
void
|
||||
AsyncGenIntro(ProtocolMessage* msg,
|
||||
std::function< void(ProtocolMessage*) > result);
|
||||
AsyncEncrypt(llarp_buffer_t payload);
|
||||
|
||||
/// handle key exchange done
|
||||
void
|
||||
HandleIntroGen(ProtocolMessage* msg);
|
||||
/// send an encrypted message
|
||||
AsyncGenIntro(llarp_buffer_t payload);
|
||||
|
||||
/// send a fully encrypted hidden service frame
|
||||
void
|
||||
SendMessage(ProtocolMessage* msg);
|
||||
Send(ProtocolFrame& f);
|
||||
|
||||
uint64_t sequenceNo = 0;
|
||||
llarp::SharedSecret sharedKey;
|
||||
llarp::util::CoDelQueue<
|
||||
ProtocolMessage*, ProtocolMessage::GetTime,
|
||||
ProtocolMessage::PutTime, ProtocolMessage::Compare,
|
||||
llarp::util::DummyMutex, llarp::util::DummyLock >
|
||||
m_SendQueue;
|
||||
Endpoint* m_Parent;
|
||||
};
|
||||
|
||||
|
@ -157,6 +163,8 @@ namespace llarp
|
|||
Identity m_Identity;
|
||||
std::unordered_map< Address, OutboundContext*, Address::Hash >
|
||||
m_RemoteSessions;
|
||||
std::unordered_map< Address, PathEnsureHook, Address::Hash >
|
||||
m_PendingServiceLookups;
|
||||
uint64_t m_CurrentPublishTX = 0;
|
||||
llarp_time_t m_LastPublish = 0;
|
||||
llarp_time_t m_LastPublishAttempt = 0;
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef LLARP_SERVICE_FRAME_HPP
|
||||
#define LLARP_SERVICE_FRAME_HPP
|
||||
#include <llarp/bencode.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/encrypted.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
struct DataFrame : public llarp::IBEncodeMessage
|
||||
{
|
||||
llarp::Encrypted D;
|
||||
llarp::PubKey H;
|
||||
llarp::KeyExchangeNonce N;
|
||||
uint64_t S = 0;
|
||||
llarp::Signature Z;
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
|
||||
};
|
||||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
|
@ -3,27 +3,33 @@
|
|||
#include <llarp/time.h>
|
||||
#include <llarp/bencode.hpp>
|
||||
#include <llarp/crypto.hpp>
|
||||
#include <llarp/encrypted.hpp>
|
||||
#include <llarp/service/Info.hpp>
|
||||
#include <llarp/service/Intro.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
constexpr std::size_t MAX_PROTOCOL_MESSAGE_SIZE = 2048;
|
||||
|
||||
enum ProtocolType
|
||||
{
|
||||
eProtocolText = 0,
|
||||
eProtocolTraffic = 1
|
||||
};
|
||||
|
||||
/// inner message
|
||||
struct ProtocolMessage : public llarp::IBEncodeMessage
|
||||
{
|
||||
ProtocolMessage(ProtocolType t, uint64_t seqno);
|
||||
ProtocolMessage();
|
||||
~ProtocolMessage();
|
||||
ProtocolType proto;
|
||||
llarp_time_t queued = 0;
|
||||
std::vector< byte_t > payload;
|
||||
llarp::KeyExchangeNonce N;
|
||||
uint64_t sequenceNum;
|
||||
Introduction introReply;
|
||||
ServiceInfo sender;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
|
||||
|
@ -32,34 +38,35 @@ namespace llarp
|
|||
|
||||
void
|
||||
PutBuffer(llarp_buffer_t payload);
|
||||
};
|
||||
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const ProtocolMessage* left,
|
||||
const ProtocolMessage* right) const
|
||||
{
|
||||
return left->sequenceNum < right->sequenceNum;
|
||||
}
|
||||
};
|
||||
/// outer message
|
||||
struct ProtocolFrame : public llarp::IBEncodeMessage
|
||||
{
|
||||
llarp::Encrypted D;
|
||||
uint64_t S = 0;
|
||||
llarp::PubKey H;
|
||||
llarp::KeyExchangeNonce N;
|
||||
llarp::Signature Z;
|
||||
|
||||
struct GetTime
|
||||
{
|
||||
llarp_time_t
|
||||
operator()(const ProtocolMessage* msg) const
|
||||
{
|
||||
return msg->queued;
|
||||
}
|
||||
};
|
||||
~ProtocolFrame();
|
||||
|
||||
struct PutTime
|
||||
{
|
||||
void
|
||||
operator()(ProtocolMessage* msg, llarp_time_t now) const
|
||||
{
|
||||
msg->queued = now;
|
||||
}
|
||||
};
|
||||
bool
|
||||
EncryptAndSign(llarp_crypto* c, const ProtocolMessage* msg,
|
||||
byte_t* sharedkey, byte_t* signingkey);
|
||||
|
||||
bool
|
||||
DecryptPayloadInto(llarp_crypto* c, byte_t* sharedkey,
|
||||
ProtocolMessage* into) const;
|
||||
|
||||
bool
|
||||
DecodeKey(llarp_buffer_t key, llarp_buffer_t* val);
|
||||
|
||||
bool
|
||||
BEncode(llarp_buffer_t* buf) const;
|
||||
|
||||
bool
|
||||
Verify(llarp_crypto* c, byte_t* signingkey);
|
||||
};
|
||||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
|
|
@ -27,6 +27,18 @@ namespace llarp
|
|||
buff.sz = t.size();
|
||||
return buff;
|
||||
}
|
||||
|
||||
template < typename T >
|
||||
llarp_buffer_t
|
||||
ConstBuffer(const T& t)
|
||||
{
|
||||
llarp_buffer_t buff;
|
||||
buff.base = (byte_t*)&t[0];
|
||||
buff.cur = buff.base;
|
||||
buff.sz = t.size();
|
||||
return buff;
|
||||
}
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
#endif
|
||||
|
|
|
@ -45,6 +45,19 @@ namespace llarp
|
|||
}
|
||||
}
|
||||
|
||||
Path*
|
||||
PathSet::GetPathByRouter(const RouterID& id)
|
||||
{
|
||||
auto itr = m_Paths.begin();
|
||||
while(itr != m_Paths.end())
|
||||
{
|
||||
if(itr->first.first == id)
|
||||
return itr->second;
|
||||
++itr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t
|
||||
PathSet::NumInStatus(PathStatus st) const
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <llarp/messages/path_transfer.hpp>
|
||||
#include "../buffer.hpp"
|
||||
#include "../router.hpp"
|
||||
|
||||
namespace llarp
|
||||
|
@ -19,8 +20,13 @@ namespace llarp
|
|||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictEntry("P", P, read, key, val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
|
||||
return false;
|
||||
if(llarp_buffer_eq(key, "T"))
|
||||
{
|
||||
if(T)
|
||||
delete T;
|
||||
T = new service::ProtocolFrame();
|
||||
return T->BDecode(val);
|
||||
}
|
||||
if(!BEncodeMaybeReadDictInt("V", V, read, key, val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Y", Y, read, key, val))
|
||||
|
@ -37,8 +43,12 @@ namespace llarp
|
|||
return false;
|
||||
if(!BEncodeWriteDictEntry("P", P, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("T", T, buf))
|
||||
|
||||
if(!bencode_write_bytestring(buf, "T", 1))
|
||||
return false;
|
||||
if(!T->BEncode(buf))
|
||||
return false;
|
||||
|
||||
if(!BEncodeWriteDictInt(buf, "V", LLARP_PROTO_VERSION))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Y", Y, buf))
|
||||
|
@ -51,15 +61,31 @@ namespace llarp
|
|||
PathTransferMessage::HandleMessage(IMessageHandler* h,
|
||||
llarp_router* r) const
|
||||
{
|
||||
auto path = r->paths.GetByUpstream(r->pubkey(), P);
|
||||
if(path)
|
||||
auto path = r->paths.GetByDownstream(r->pubkey(), P);
|
||||
if(!path)
|
||||
{
|
||||
return path->HandleDownstream(T.Buffer(), Y, r);
|
||||
llarp::LogWarn("No such path for path transfer pathid=", P);
|
||||
return false;
|
||||
}
|
||||
if(!T)
|
||||
{
|
||||
llarp::LogError("no data to transfer on data message");
|
||||
return false;
|
||||
}
|
||||
llarp::LogWarn("No such local path for path transfer src=", from,
|
||||
" dst=", P);
|
||||
return false;
|
||||
}
|
||||
} // namespace routing
|
||||
|
||||
} // namespace llarp
|
||||
byte_t tmp[service::MAX_PROTOCOL_MESSAGE_SIZE];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
if(!T->BEncode(&buf))
|
||||
{
|
||||
llarp::LogWarn("failed to transfer data message, encode failed");
|
||||
return false;
|
||||
}
|
||||
// rewind
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// send
|
||||
return path->HandleDownstream(buf, Y, r);
|
||||
}
|
||||
|
||||
} // namespace routing
|
||||
} // namespace llarp
|
||||
|
|
|
@ -140,6 +140,15 @@ namespace llarp
|
|||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
void
|
||||
Introduction::Clear()
|
||||
{
|
||||
router.Zero();
|
||||
pathID.Zero();
|
||||
latency = 0;
|
||||
expiresAt = 0;
|
||||
}
|
||||
|
||||
Identity::~Identity()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -300,32 +300,80 @@ namespace llarp
|
|||
struct HiddenServiceAddressLookup : public IServiceLookup
|
||||
{
|
||||
Endpoint* endpoint;
|
||||
HiddenServiceAddressLookup(Endpoint* parent) : endpoint(parent)
|
||||
Address remote;
|
||||
uint64_t txid;
|
||||
HiddenServiceAddressLookup(Endpoint* parent, const Address& addr,
|
||||
uint64_t tx)
|
||||
: endpoint(parent), remote(addr), txid(tx)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
HandleResponse(const std::set< IntroSet >& results)
|
||||
{
|
||||
if(results.size() == 0)
|
||||
if(results.size() == 1)
|
||||
{
|
||||
auto itr = results.begin();
|
||||
endpoint->PutNewOutboundContext(*itr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: retry request?
|
||||
endpoint->PutNewOutboundContext(*results.begin());
|
||||
}
|
||||
delete this;
|
||||
return true;
|
||||
}
|
||||
|
||||
llarp::routing::IMessage*
|
||||
BuildRequestMessage()
|
||||
{
|
||||
llarp::routing::DHTMessage* msg = new llarp::routing::DHTMessage();
|
||||
msg->M.push_back(new llarp::dht::FindIntroMessage(remote, txid));
|
||||
return msg;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
Endpoint::PutNewOutboundContext(const llarp::service::IntroSet& introset)
|
||||
{
|
||||
Address addr;
|
||||
introset.A.CalculateAddress(addr);
|
||||
|
||||
// only add new session if it's not there
|
||||
if(m_RemoteSessions.find(addr) == m_RemoteSessions.end())
|
||||
{
|
||||
OutboundContext* ctx = new OutboundContext(introset, this);
|
||||
m_RemoteSessions.insert(std::make_pair(addr, ctx));
|
||||
llarp::LogInfo("Created New outbound context for ", addr.ToString());
|
||||
}
|
||||
|
||||
// inform pending
|
||||
auto itr = m_PendingServiceLookups.find(addr);
|
||||
if(itr != m_PendingServiceLookups.end())
|
||||
{
|
||||
itr->second(m_RemoteSessions.at(addr));
|
||||
m_PendingServiceLookups.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::EnsurePathToService(const Address& remote, PathEnsureHook hook,
|
||||
llarp_time_t timeoutMS)
|
||||
{
|
||||
// TODO: implement me
|
||||
return false;
|
||||
{
|
||||
auto itr = m_RemoteSessions.find(remote);
|
||||
if(itr != m_RemoteSessions.end())
|
||||
{
|
||||
hook(itr->second);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
auto itr = m_PendingServiceLookups.find(remote);
|
||||
if(itr != m_PendingServiceLookups.end())
|
||||
{
|
||||
// duplicate
|
||||
return false;
|
||||
}
|
||||
m_PendingServiceLookups.insert(std::make_pair(remote, hook));
|
||||
HiddenServiceAddressLookup* job =
|
||||
new HiddenServiceAddressLookup(this, remote, GenTXID());
|
||||
m_PendingLookups.insert(std::make_pair(job->txid, job));
|
||||
return true;
|
||||
}
|
||||
|
||||
Endpoint::OutboundContext::OutboundContext(const IntroSet& intro,
|
||||
|
@ -333,16 +381,28 @@ namespace llarp
|
|||
: llarp_pathbuilder_context(parent->m_Router, parent->m_Router->dht, 2,
|
||||
4)
|
||||
, currentIntroSet(intro)
|
||||
, m_SendQueue(parent->Name() + "::outbound_queue")
|
||||
, m_Parent(parent)
|
||||
|
||||
{
|
||||
selectedIntro.Clear();
|
||||
}
|
||||
|
||||
Endpoint::OutboundContext::~OutboundContext()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
Endpoint::OutboundContext::ShiftIntroduction()
|
||||
{
|
||||
for(const auto& intro : currentIntroSet.I)
|
||||
{
|
||||
if(intro.expiresAt > selectedIntro.expiresAt)
|
||||
{
|
||||
selectedIntro = intro;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Endpoint::OutboundContext::HandleGotIntroMessage(
|
||||
const llarp::dht::GotIntroMessage* msg)
|
||||
|
@ -355,6 +415,7 @@ namespace llarp
|
|||
if(itr->VerifySignature(crypto) && currentIntroSet.A == itr->A)
|
||||
{
|
||||
currentIntroSet = *itr;
|
||||
ShiftIntroduction();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -371,68 +432,89 @@ namespace llarp
|
|||
Endpoint::OutboundContext::AsyncEncryptAndSendTo(llarp_buffer_t data,
|
||||
ProtocolType protocol)
|
||||
{
|
||||
auto sendto =
|
||||
std::bind(&OutboundContext::SendMessage, this, std::placeholders::_1);
|
||||
ProtocolMessage* msg = new ProtocolMessage(protocol, sequenceNo);
|
||||
msg->PutBuffer(data);
|
||||
if(sequenceNo)
|
||||
{
|
||||
AsyncEncrypt(msg, sendto);
|
||||
AsyncEncrypt(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
AsyncGenIntro(msg, sendto);
|
||||
AsyncGenIntro(data);
|
||||
}
|
||||
}
|
||||
|
||||
struct AsyncKeyExchange
|
||||
struct AsyncIntroGen
|
||||
{
|
||||
llarp_logic* logic;
|
||||
llarp_crypto* crypto;
|
||||
byte_t* sharedKey;
|
||||
byte_t* remotePubkey;
|
||||
byte_t* localSeckey;
|
||||
byte_t* nonce;
|
||||
ProtocolMessage* msg = nullptr;
|
||||
std::function< void(ProtocolMessage*) > hook;
|
||||
Identity* m_LocalIdentity;
|
||||
ProtocolMessage msg;
|
||||
ProtocolFrame frame;
|
||||
std::function< void(ProtocolFrame&) > hook;
|
||||
|
||||
AsyncKeyExchange(llarp_logic* l, llarp_crypto* c, byte_t* key,
|
||||
byte_t* remote, byte_t* localSecret, byte_t* n)
|
||||
AsyncIntroGen(llarp_logic* l, llarp_crypto* c, byte_t* key,
|
||||
byte_t* remote, Identity* localident)
|
||||
: logic(l)
|
||||
, crypto(c)
|
||||
, sharedKey(key)
|
||||
, remotePubkey(remote)
|
||||
, localSeckey(localSecret)
|
||||
, nonce(n)
|
||||
, m_LocalIdentity(localident)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
Result(void* user)
|
||||
{
|
||||
AsyncIntroGen* self = static_cast< AsyncIntroGen* >(user);
|
||||
self->hook(self->frame);
|
||||
delete self;
|
||||
}
|
||||
|
||||
static void
|
||||
Work(void* user)
|
||||
{
|
||||
AsyncKeyExchange* self = static_cast< AsyncKeyExchange* >(user);
|
||||
AsyncIntroGen* self = static_cast< AsyncIntroGen* >(user);
|
||||
// randomize Nounce
|
||||
self->frame.N.Randomize();
|
||||
// derive session key
|
||||
self->crypto->dh_server(self->sharedKey, self->remotePubkey,
|
||||
self->localSeckey, self->nonce);
|
||||
self->m_LocalIdentity->enckey, self->frame.N);
|
||||
// encrypt and sign
|
||||
self->frame.EncryptAndSign(self->crypto, &self->msg, self->sharedKey,
|
||||
self->m_LocalIdentity->signkey);
|
||||
// inform result
|
||||
llarp_logic_queue_job(self->logic, {self, &Result});
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
Endpoint::OutboundContext::AsyncGenIntro(
|
||||
ProtocolMessage* msg, std::function< void(ProtocolMessage*) > result)
|
||||
Endpoint::OutboundContext::AsyncGenIntro(llarp_buffer_t payload)
|
||||
{
|
||||
msg->N.Randomize();
|
||||
AsyncKeyExchange* ex = new AsyncKeyExchange(
|
||||
m_Parent->Logic(), m_Parent->Crypto(), sharedKey,
|
||||
currentIntroSet.A.enckey, m_Parent->GetEncryptionSecretKey(), msg->N);
|
||||
AsyncIntroGen* ex =
|
||||
new AsyncIntroGen(m_Parent->Logic(), m_Parent->Crypto(), sharedKey,
|
||||
currentIntroSet.A.enckey, m_Parent->GetIdentity());
|
||||
ex->hook = std::bind(&Endpoint::OutboundContext::Send, this,
|
||||
std::placeholders::_1);
|
||||
|
||||
ex->msg.PutBuffer(payload);
|
||||
llarp_threadpool_queue_job(m_Parent->Worker(),
|
||||
{ex, &AsyncKeyExchange::Work});
|
||||
{ex, &AsyncIntroGen::Work});
|
||||
}
|
||||
|
||||
void
|
||||
Endpoint::OutboundContext::SendMessage(ProtocolMessage* msg)
|
||||
Endpoint::OutboundContext::Send(ProtocolFrame& msg)
|
||||
{
|
||||
// TODO: delete msg
|
||||
// TODO: implement me
|
||||
// in this context we assume the message contents are encrypted
|
||||
auto path = GetPathByRouter(selectedIntro.router);
|
||||
if(path)
|
||||
{
|
||||
routing::PathTransferMessage transfer;
|
||||
transfer.T = &msg;
|
||||
transfer.Y.Randomize();
|
||||
transfer.P = selectedIntro.pathID;
|
||||
path->SendRoutingMessage(&transfer, m_Parent->Router());
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -473,8 +555,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
void
|
||||
Endpoint::OutboundContext::AsyncEncrypt(
|
||||
ProtocolMessage* msg, std::function< void(ProtocolMessage*) > result)
|
||||
Endpoint::OutboundContext::AsyncEncrypt(llarp_buffer_t payload)
|
||||
{
|
||||
// TODO: implement me
|
||||
}
|
||||
|
@ -497,11 +578,5 @@ namespace llarp
|
|||
return m_Router->tp;
|
||||
}
|
||||
|
||||
byte_t*
|
||||
Endpoint::GetEncryptionSecretKey()
|
||||
{
|
||||
return m_Identity.enckey;
|
||||
}
|
||||
|
||||
} // namespace service
|
||||
} // namespace llarp
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#include <llarp/service/frame.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
}
|
||||
} // namespace llarp
|
|
@ -1,11 +1,11 @@
|
|||
#include <llarp/service/protocol.hpp>
|
||||
#include "buffer.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
namespace service
|
||||
{
|
||||
ProtocolMessage::ProtocolMessage(ProtocolType t, uint64_t seqno)
|
||||
: proto(t), sequenceNum(seqno)
|
||||
ProtocolMessage::ProtocolMessage()
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,105 @@ namespace llarp
|
|||
{
|
||||
payload.resize(buf.sz);
|
||||
memcpy(payload.data(), buf.base, buf.sz);
|
||||
payload.shrink_to_fit();
|
||||
}
|
||||
|
||||
ProtocolFrame::~ProtocolFrame()
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
ProtocolFrame::BEncode(llarp_buffer_t* buf) const
|
||||
{
|
||||
if(!bencode_start_dict(buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictMsgType(buf, "A", "H"))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("D", D, buf))
|
||||
return false;
|
||||
if(S == 0)
|
||||
{
|
||||
if(!BEncodeWriteDictEntry("H", H, buf))
|
||||
return false;
|
||||
}
|
||||
if(!BEncodeWriteDictEntry("N", N, buf))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt(buf, "S", S))
|
||||
return false;
|
||||
if(!BEncodeWriteDictInt(buf, "V", version))
|
||||
return false;
|
||||
if(!BEncodeWriteDictEntry("Z", Z, buf))
|
||||
return false;
|
||||
return bencode_end(buf);
|
||||
}
|
||||
|
||||
bool
|
||||
ProtocolFrame::DecodeKey(llarp_buffer_t key, llarp_buffer_t* val)
|
||||
{
|
||||
bool read = false;
|
||||
if(!BEncodeMaybeReadDictEntry("D", D, read, key, val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("H", H, read, key, val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("N", N, read, key, val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictInt("S", S, read, key, val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadVersion("V", version, LLARP_PROTO_VERSION, read, key,
|
||||
val))
|
||||
return false;
|
||||
if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, val))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
ProtocolFrame::EncryptAndSign(llarp_crypto* crypto,
|
||||
const ProtocolMessage* msg,
|
||||
byte_t* sessionKey, byte_t* signingkey)
|
||||
{
|
||||
// put payload and encrypt
|
||||
D = llarp::ConstBuffer(msg->payload);
|
||||
memcpy(D.data(), msg->payload.data(), D.size());
|
||||
auto dbuf = D.Buffer();
|
||||
crypto->xchacha20(*dbuf, sessionKey, N);
|
||||
// zero out signature
|
||||
Z.Zero();
|
||||
// encode
|
||||
byte_t tmp[MAX_PROTOCOL_MESSAGE_SIZE];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
if(!BEncode(&buf))
|
||||
return false;
|
||||
// rewind
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// sign
|
||||
return crypto->sign(Z, signingkey, buf);
|
||||
}
|
||||
|
||||
bool
|
||||
ProtocolFrame::Verify(llarp_crypto* crypto, byte_t* signkey)
|
||||
{
|
||||
// save signature
|
||||
llarp::Signature sig = Z;
|
||||
// zero out signature for verify
|
||||
Z.Zero();
|
||||
bool result = false;
|
||||
// serialize
|
||||
byte_t tmp[MAX_PROTOCOL_MESSAGE_SIZE];
|
||||
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
|
||||
if(BEncode(&buf))
|
||||
{
|
||||
// rewind buffer
|
||||
buf.sz = buf.cur - buf.base;
|
||||
buf.cur = buf.base;
|
||||
// verify
|
||||
result = crypto->verify(sig, buf, signkey);
|
||||
}
|
||||
// restore signature
|
||||
Z = sig;
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace service
|
||||
} // namespace llarp
|
|
@ -127,12 +127,6 @@ namespace llarp
|
|||
TransitHop::HandlePathTransferMessage(
|
||||
const llarp::routing::PathTransferMessage* msg, llarp_router* r)
|
||||
{
|
||||
auto path = r->paths.GetByDownstream(r->pubkey(), msg->P);
|
||||
if(path)
|
||||
{
|
||||
return path->HandleDownstream(msg->T.Buffer(), msg->Y, r);
|
||||
}
|
||||
llarp::LogWarn("No such path for path transfer pathid=", msg->P);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue