mirror of
https://github.com/oxen-io/lokinet.git
synced 2024-11-05 21:20:38 +00:00
181 lines
4.5 KiB
C++
181 lines
4.5 KiB
C++
#include <iwp/linklayer.hpp>
|
|
|
|
namespace llarp
|
|
{
|
|
namespace iwp
|
|
{
|
|
LinkLayer::LinkLayer(Crypto* c, const SecretKey& enckey, GetRCFunc getrc,
|
|
LinkMessageHandler h, SessionEstablishedHandler est,
|
|
SessionRenegotiateHandler reneg, SignBufferFunc sign,
|
|
TimeoutHandler t, SessionClosedHandler closed)
|
|
: ILinkLayer(enckey, getrc, h, sign, est, reneg, t, closed), crypto(c)
|
|
{
|
|
m_FlowCookie.Randomize();
|
|
}
|
|
|
|
LinkLayer::~LinkLayer()
|
|
{
|
|
}
|
|
|
|
void
|
|
LinkLayer::Pump()
|
|
{
|
|
ILinkLayer::Pump();
|
|
}
|
|
|
|
const char*
|
|
LinkLayer::Name() const
|
|
{
|
|
return "iwp";
|
|
}
|
|
|
|
bool
|
|
LinkLayer::KeyGen(SecretKey& k)
|
|
{
|
|
k.Zero();
|
|
crypto->encryption_keygen(k);
|
|
return !k.IsZero();
|
|
}
|
|
|
|
uint16_t
|
|
LinkLayer::Rank() const
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
bool
|
|
LinkLayer::Start(Logic* l)
|
|
{
|
|
if(!ILinkLayer::Start(l))
|
|
return false;
|
|
/// TODO: change me to true when done
|
|
return false;
|
|
}
|
|
|
|
void
|
|
LinkLayer::RecvFrom(const Addr& from, const void* pkt, size_t sz)
|
|
{
|
|
m_OuterMsg.Clear();
|
|
llarp_buffer_t sigbuf(pkt, sz);
|
|
llarp_buffer_t decodebuf(pkt, sz);
|
|
if(!m_OuterMsg.Decode(&decodebuf))
|
|
{
|
|
LogError("failed to decode outer message");
|
|
return;
|
|
}
|
|
NetID ourNetID;
|
|
switch(m_OuterMsg.command)
|
|
{
|
|
case eOCMD_ObtainFlowID:
|
|
sigbuf.sz -= m_OuterMsg.Zsig.size();
|
|
if(!crypto->verify(m_OuterMsg.pubkey, sigbuf, m_OuterMsg.Zsig))
|
|
{
|
|
LogError("failed to verify signature on '",
|
|
(char)m_OuterMsg.command, "' message from ", from);
|
|
return;
|
|
}
|
|
if(!ShouldSendFlowID(from))
|
|
{
|
|
SendReject(from, "no flo 4u :^)");
|
|
return;
|
|
}
|
|
if(m_OuterMsg.netid == ourNetID)
|
|
{
|
|
if(GenFlowIDFor(m_OuterMsg.pubkey, from, m_OuterMsg.flow))
|
|
SendFlowID(from, m_OuterMsg.flow);
|
|
else
|
|
SendReject(from, "genflow fail");
|
|
}
|
|
else
|
|
SendReject(from, "bad netid");
|
|
}
|
|
}
|
|
|
|
std::shared_ptr< ILinkSession >
|
|
LinkLayer::NewOutboundSession(const RouterContact& rc,
|
|
const AddressInfo& ai)
|
|
{
|
|
(void)rc;
|
|
(void)ai;
|
|
// TODO: implement me
|
|
return {};
|
|
}
|
|
|
|
void
|
|
LinkLayer::SendFlowID(const Addr& to, const FlowID_t& flow)
|
|
{
|
|
// TODO: implement me
|
|
(void)to;
|
|
(void)flow;
|
|
}
|
|
|
|
bool
|
|
LinkLayer::VerifyFlowID(const PubKey& pk, const Addr& from,
|
|
const FlowID_t& flow) const
|
|
{
|
|
FlowID_t expected;
|
|
if(!GenFlowIDFor(pk, from, expected))
|
|
return false;
|
|
return expected == flow;
|
|
}
|
|
|
|
bool
|
|
LinkLayer::GenFlowIDFor(const PubKey& pk, const Addr& from,
|
|
FlowID_t& flow) const
|
|
{
|
|
std::array< byte_t, 128 > tmp = {{0}};
|
|
if(inet_ntop(AF_INET6, from.addr6(), (char*)tmp.data(), tmp.size())
|
|
== nullptr)
|
|
return false;
|
|
std::copy_n(pk.begin(), pk.size(), tmp.begin() + 64);
|
|
std::copy_n(m_FlowCookie.begin(), m_FlowCookie.size(),
|
|
tmp.begin() + 64 + pk.size());
|
|
llarp_buffer_t buf(tmp);
|
|
ShortHash h;
|
|
if(!crypto->shorthash(h, buf))
|
|
return false;
|
|
std::copy_n(h.begin(), flow.size(), flow.begin());
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
LinkLayer::ShouldSendFlowID(const Addr& to) const
|
|
{
|
|
(void)to;
|
|
// TODO: implement me
|
|
return false;
|
|
}
|
|
|
|
void
|
|
LinkLayer::SendReject(const Addr& to, const char* msg)
|
|
{
|
|
if(strlen(msg) > 14)
|
|
{
|
|
throw std::logic_error("reject message too big");
|
|
}
|
|
std::array< byte_t, 120 > pkt;
|
|
auto now = Now();
|
|
PubKey pk = GetOurRC().pubkey;
|
|
OuterMessage m;
|
|
m.CreateReject(msg, now, pk);
|
|
llarp_buffer_t encodebuf(pkt);
|
|
if(!m.Encode(&encodebuf))
|
|
{
|
|
LogError("failed to encode reject message to ", to);
|
|
return;
|
|
}
|
|
llarp_buffer_t signbuf(pkt.data(), pkt.size() - m.Zsig.size());
|
|
if(!Sign(m.Zsig, signbuf))
|
|
{
|
|
LogError("failed to sign reject messsage to ", to);
|
|
return;
|
|
}
|
|
std::copy_n(m.Zsig.begin(), m.Zsig.size(),
|
|
pkt.begin() + (pkt.size() - m.Zsig.size()));
|
|
llarp_buffer_t pktbuf(pkt);
|
|
SendTo_LL(to, pktbuf);
|
|
}
|
|
} // namespace iwp
|
|
|
|
} // namespace llarp
|