multithreaded iwp cryptography

pull/830/head
Jeff Becker 5 years ago
parent 0d3c07999a
commit 88cde21b9b
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -14,10 +14,14 @@ namespace llarp
: ILinkLayer(routerEncSecret, getrc, h, sign, est, reneg, timeout,
closed)
, permitInbound{allowInbound}
, m_CryptoWorker(4, 1024 * 8, "iwp-worker")
{
}
LinkLayer::~LinkLayer() = default;
LinkLayer::~LinkLayer()
{
m_CryptoWorker.stop();
}
void
LinkLayer::Pump()
@ -66,10 +70,24 @@ namespace llarp
return 2;
}
void
LinkLayer::QueueWork(std::function< void(void) > func)
{
m_CryptoWorker.addJob(func);
}
bool
LinkLayer::Start(std::shared_ptr< Logic > l)
{
return ILinkLayer::Start(l);
if(!ILinkLayer::Start(l))
return false;
return m_CryptoWorker.start();
}
void
LinkLayer::Stop()
{
ILinkLayer::Stop();
}
void

@ -6,6 +6,7 @@
#include <crypto/encrypted.hpp>
#include <crypto/types.hpp>
#include <link/server.hpp>
#include <util/thread/thread_pool.hpp>
namespace llarp
{
@ -37,6 +38,9 @@ namespace llarp
const char *
Name() const override;
void
Stop() override;
uint16_t
Rank() const override;
@ -49,9 +53,13 @@ namespace llarp
void
UnmapAddr(const Addr &addr);
void
QueueWork(std::function< void(void) > work);
private:
std::unordered_map< Addr, RouterID, Addr::Hash > m_AuthedAddrs;
const bool permitInbound;
thread::ThreadPool m_CryptoWorker;
};
using LinkLayer_ptr = std::shared_ptr< LinkLayer >;

@ -123,26 +123,36 @@ namespace llarp
void
Session::EncryptAndSend(const llarp_buffer_t& data)
{
std::vector< byte_t > pkt;
pkt.resize(data.sz + PacketOverhead);
CryptoManager::instance()->randbytes(pkt.data(), pkt.size());
llarp_buffer_t pktbuf(pkt);
pktbuf.base += PacketOverhead;
pktbuf.cur = pktbuf.base;
pktbuf.sz -= PacketOverhead;
byte_t* nonce_ptr = pkt.data() + HMACSIZE;
CryptoManager::instance()->xchacha20_alt(pktbuf, data, m_SessionKey,
nonce_ptr);
pktbuf.base = nonce_ptr;
pktbuf.sz = data.sz + 32;
CryptoManager::instance()->hmac(pkt.data(), pktbuf, m_SessionKey);
m_EncryptNext.emplace_back(data.sz + PacketOverhead);
auto& pkt = m_EncryptNext.back();
std::copy_n(data.base, data.sz, pkt.begin() + PacketOverhead);
if(!IsEstablished())
EncryptWorker(std::move(m_EncryptNext));
}
pktbuf.base = pkt.data();
pktbuf.cur = pkt.data();
pktbuf.sz = pkt.size();
Send_LL(pktbuf);
void
Session::EncryptWorker(CryptoQueue_t msgs)
{
LogDebug("encrypt worker ", msgs.size(), " messages");
for(auto& pkt : msgs)
{
llarp_buffer_t pktbuf(pkt);
byte_t* nonce_ptr = pkt.data() + HMACSIZE;
CryptoManager::instance()->randbytes(nonce_ptr,
PacketOverhead - HMACSECSIZE);
pktbuf.base += PacketOverhead;
pktbuf.cur = pktbuf.base;
pktbuf.sz -= PacketOverhead;
CryptoManager::instance()->xchacha20_alt(pktbuf, pktbuf, m_SessionKey,
nonce_ptr);
pktbuf.base = nonce_ptr;
pktbuf.sz = pkt.size() - HMACSIZE;
CryptoManager::instance()->hmac(pkt.data(), pktbuf, m_SessionKey);
pktbuf.base = pkt.data();
pktbuf.cur = pkt.data();
pktbuf.sz = pkt.size();
Send_LL(pktbuf);
}
}
void
@ -233,6 +243,16 @@ namespace llarp
}
}
}
if(!m_EncryptNext.empty())
m_Parent->QueueWork(std::bind(&Session::EncryptWorker,
shared_from_this(),
std::move(m_EncryptNext)));
if(!m_DecryptNext.empty())
m_Parent->QueueWork(std::bind(&Session::DecryptWorker,
shared_from_this(),
std::move(m_DecryptNext)));
}
bool
@ -332,14 +352,6 @@ namespace llarp
{
TunnelNonce N;
N.Randomize();
if(not CryptoManager::instance()->transport_dh_client(
m_SessionKey, m_ChosenAI.pubkey,
m_Parent->RouterEncryptionSecret(), N))
{
LogError("failed to transport_dh_client on outbound session to ",
m_RemoteAddr);
return;
}
std::vector< byte_t > req;
req.resize(Introduction::SIZE - Signature::SIZE);
const auto pk = m_Parent->GetOurRC().pubkey;
@ -360,6 +372,14 @@ namespace llarp
const llarp_buffer_t buf(req);
EncryptAndSend(buf);
m_State = State::Introduction;
if(not CryptoManager::instance()->transport_dh_client(
m_SessionKey, m_ChosenAI.pubkey,
m_Parent->RouterEncryptionSecret(), N))
{
LogError("failed to transport_dh_client on outbound session to ",
m_RemoteAddr);
return;
}
LogDebug("sent intro to ", m_RemoteAddr);
}
@ -504,44 +524,71 @@ namespace llarp
void
Session::HandleSessionData(const llarp_buffer_t& buf)
{
std::vector< byte_t > result;
if(not DecryptMessage(buf, result))
{
LogError("failed to decrypt session data from ", m_RemoteAddr);
return;
}
if(result[0] != LLARP_PROTO_VERSION)
m_DecryptNext.emplace_back(buf.sz);
auto& pkt = m_DecryptNext.back();
std::copy_n(buf.base, buf.sz, pkt.begin());
}
void
Session::DecryptWorker(CryptoQueue_t msgs)
{
CryptoQueue_t recvMsgs;
for(const auto& pkt : msgs)
{
LogError("protocol version missmatch ", int(result[0]),
" != ", LLARP_PROTO_VERSION);
return;
std::vector< byte_t > result;
const llarp_buffer_t buf(pkt);
if(not DecryptMessage(buf, result))
{
LogError("failed to decrypt session data from ", m_RemoteAddr);
continue;
}
if(result[0] != LLARP_PROTO_VERSION)
{
LogError("protocol version missmatch ", int(result[0]),
" != ", LLARP_PROTO_VERSION);
continue;
}
recvMsgs.emplace_back(std::move(result));
}
LogDebug("command ", int(result[1]), " from ", m_RemoteAddr);
switch(result[1])
LogDebug("decrypted ", recvMsgs.size(), " packets from ", m_RemoteAddr);
m_Parent->logic()->queue_func(std::bind(
&Session::HandlePlaintext, shared_from_this(), std::move(recvMsgs)));
}
void
Session::HandlePlaintext(CryptoQueue_t msgs)
{
for(auto& result : msgs)
{
case Command::eXMIT:
HandleXMIT(std::move(result));
return;
case Command::eDATA:
HandleDATA(std::move(result));
return;
case Command::eACKS:
HandleACKS(std::move(result));
return;
case Command::ePING:
HandlePING(std::move(result));
return;
case Command::eNACK:
HandleNACK(std::move(result));
return;
case Command::eCLOS:
HandleCLOS(std::move(result));
return;
case Command::eMACK:
HandleMACK(std::move(result));
return;
LogDebug("command ", int(result[1]), " from ", m_RemoteAddr);
switch(result[1])
{
case Command::eXMIT:
HandleXMIT(std::move(result));
break;
case Command::eDATA:
HandleDATA(std::move(result));
break;
case Command::eACKS:
HandleACKS(std::move(result));
break;
case Command::ePING:
HandlePING(std::move(result));
break;
case Command::eNACK:
HandleNACK(std::move(result));
break;
case Command::eCLOS:
HandleCLOS(std::move(result));
break;
case Command::eMACK:
HandleMACK(std::move(result));
break;
default:
LogError("invalid command ", int(result[1]), " from ",
m_RemoteAddr);
}
}
LogError("invalid command ", int(result[1]));
}
void

@ -167,6 +167,20 @@ namespace llarp
/// list of rx messages to send in next set of multiacks
std::vector< uint64_t > m_SendMACKS;
using CryptoQueue_t = std::vector< std::vector< byte_t > >;
CryptoQueue_t m_EncryptNext;
CryptoQueue_t m_DecryptNext;
void
EncryptWorker(CryptoQueue_t msgs);
void
DecryptWorker(CryptoQueue_t msgs);
void
HandlePlaintext(CryptoQueue_t msgs);
void
HandleGotIntro(const llarp_buffer_t& buf);

Loading…
Cancel
Save