lokinet/llarp/service/protocol.cpp

395 lines
11 KiB
C++
Raw Normal View History

#include <llarp/logic.hpp>
#include <llarp/routing/handler.hpp>
2018-07-19 04:58:39 +00:00
#include <llarp/service/protocol.hpp>
2018-07-22 23:14:29 +00:00
#include "buffer.hpp"
2018-08-12 17:22:29 +00:00
#include "mem.hpp"
2018-07-19 04:58:39 +00:00
namespace llarp
{
namespace service
{
2018-07-22 23:14:29 +00:00
ProtocolMessage::ProtocolMessage()
2018-07-19 04:58:39 +00:00
{
2018-08-09 19:02:17 +00:00
tag.Zero();
2018-07-19 04:58:39 +00:00
}
2018-08-09 19:02:17 +00:00
ProtocolMessage::ProtocolMessage(const ConvoTag& t) : tag(t)
2018-07-19 04:58:39 +00:00
{
}
2018-08-09 19:02:17 +00:00
ProtocolMessage::~ProtocolMessage()
2018-07-19 04:58:39 +00:00
{
}
void
ProtocolMessage::PutBuffer(llarp_buffer_t buf)
{
payload.resize(buf.sz);
memcpy(payload.data(), buf.base, buf.sz);
}
2018-07-22 23:14:29 +00:00
2018-08-09 19:02:17 +00:00
void
ProtocolMessage::ProcessAsync(void* user)
{
ProtocolMessage* self = static_cast< ProtocolMessage* >(user);
if(!self->handler->HandleDataMessage(self->srcPath, self))
llarp::LogWarn("failed to handle data message from ", self->srcPath);
2018-08-09 19:02:17 +00:00
delete self;
}
bool
ProtocolMessage::DecodeKey(llarp_buffer_t k, llarp_buffer_t* buf)
{
bool read = false;
if(!BEncodeMaybeReadDictInt("a", proto, read, k, buf))
return false;
if(llarp_buffer_eq(k, "d"))
{
llarp_buffer_t strbuf;
if(!bencode_read_string(buf, &strbuf))
return false;
PutBuffer(strbuf);
return true;
}
if(!BEncodeMaybeReadDictEntry("i", introReply, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("s", sender, read, k, buf))
return false;
if(!BEncodeMaybeReadDictEntry("t", tag, read, k, buf))
return false;
if(!BEncodeMaybeReadDictInt("v", version, read, k, buf))
return false;
return read;
}
bool
ProtocolMessage::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
if(!BEncodeWriteDictInt("a", proto, buf))
return false;
if(!bencode_write_bytestring(buf, "d", 1))
return false;
if(!bencode_write_bytestring(buf, payload.data(), payload.size()))
return false;
if(!BEncodeWriteDictEntry("i", introReply, buf))
return false;
if(!BEncodeWriteDictEntry("s", sender, buf))
return false;
if(!tag.IsZero())
{
if(!BEncodeWriteDictEntry("t", tag, buf))
return false;
}
2018-09-17 15:32:37 +00:00
if(!BEncodeWriteDictInt("v", version, buf))
2018-08-09 19:02:17 +00:00
return false;
return bencode_end(buf);
}
2018-07-22 23:14:29 +00:00
ProtocolFrame::~ProtocolFrame()
{
}
bool
ProtocolFrame::BEncode(llarp_buffer_t* buf) const
{
if(!bencode_start_dict(buf))
return false;
2018-08-12 17:22:29 +00:00
if(!BEncodeWriteDictMsgType(buf, "A", "H"))
return false;
if(!C.IsZero())
2018-07-22 23:14:29 +00:00
{
if(!BEncodeWriteDictEntry("C", C, buf))
2018-07-22 23:14:29 +00:00
return false;
}
if(!BEncodeWriteDictEntry("D", D, buf))
2018-07-22 23:14:29 +00:00
return false;
if(!BEncodeWriteDictEntry("N", N, buf))
2018-07-22 23:14:29 +00:00
return false;
if(!T.IsZero())
2018-08-09 19:02:17 +00:00
{
if(!BEncodeWriteDictEntry("T", T, buf))
return false;
}
if(!BEncodeWriteDictInt("V", version, buf))
2018-07-22 23:14:29 +00:00
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;
2018-08-12 17:22:29 +00:00
if(llarp_buffer_eq(key, "A"))
{
llarp_buffer_t strbuf;
if(!bencode_read_string(val, &strbuf))
return false;
if(strbuf.sz != 1)
return false;
return *strbuf.cur == 'H';
}
2018-07-22 23:14:29 +00:00
if(!BEncodeMaybeReadDictEntry("D", D, read, key, val))
return false;
if(!BEncodeMaybeReadDictEntry("C", C, read, key, val))
2018-07-22 23:14:29 +00:00
return false;
if(!BEncodeMaybeReadDictEntry("N", N, read, key, val))
return false;
if(!BEncodeMaybeReadDictInt("S", S, read, key, val))
return false;
2018-08-09 19:02:17 +00:00
if(!BEncodeMaybeReadDictEntry("T", T, read, key, val))
return false;
2018-07-22 23:14:29 +00:00
if(!BEncodeMaybeReadVersion("V", version, LLARP_PROTO_VERSION, read, key,
val))
return false;
if(!BEncodeMaybeReadDictEntry("Z", Z, read, key, val))
return false;
return read;
}
2018-08-09 19:02:17 +00:00
bool
ProtocolFrame::DecryptPayloadInto(llarp_crypto* crypto,
const byte_t* sharedkey,
ProtocolMessage& msg) const
2018-08-09 19:02:17 +00:00
{
Encrypted tmp = D;
auto buf = tmp.Buffer();
crypto->xchacha20(*buf, sharedkey, N);
return msg.BDecode(buf);
2018-08-09 19:02:17 +00:00
}
2018-07-22 23:14:29 +00:00
bool
ProtocolFrame::EncryptAndSign(llarp_crypto* crypto,
const ProtocolMessage& msg,
const byte_t* sessionKey,
const Identity& localIdent)
2018-07-22 23:14:29 +00:00
{
byte_t tmp[MAX_PROTOCOL_MESSAGE_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
2018-08-14 21:17:18 +00:00
// encode message
if(!msg.BEncode(&buf))
2018-09-19 17:04:55 +00:00
{
llarp::LogError("message too big to encode");
2018-08-14 21:17:18 +00:00
return false;
2018-09-19 17:04:55 +00:00
}
2018-08-14 21:17:18 +00:00
// rewind
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// encrypt
crypto->xchacha20(buf, sessionKey, N);
// put encrypted buffer
D = buf;
// zero out signature
Z.Zero();
2018-09-21 12:47:07 +00:00
auto buf2 = llarp::StackBuffer< decltype(tmp) >(tmp);
2018-08-14 21:17:18 +00:00
// encode frame
2018-09-21 12:47:07 +00:00
if(!BEncode(&buf2))
2018-09-19 17:04:55 +00:00
{
llarp::LogError("frame too big to encode");
2018-09-21 12:47:07 +00:00
llarp::DumpBuffer(buf2);
2018-07-22 23:14:29 +00:00
return false;
2018-09-19 17:04:55 +00:00
}
2018-07-22 23:14:29 +00:00
// rewind
2018-09-21 12:47:07 +00:00
buf2.sz = buf2.cur - buf2.base;
buf2.cur = buf2.base;
2018-07-22 23:14:29 +00:00
// sign
2018-09-21 12:47:07 +00:00
if(!localIdent.Sign(crypto, Z, buf2))
2018-09-19 17:04:55 +00:00
{
llarp::LogError("failed to sign? wtf?!");
return false;
}
return true;
2018-07-22 23:14:29 +00:00
}
2018-08-14 21:17:18 +00:00
struct AsyncFrameDecrypt
2018-08-09 19:02:17 +00:00
{
llarp_crypto* crypto;
2018-12-10 14:14:55 +00:00
llarp::Logic* logic;
2018-08-09 19:02:17 +00:00
ProtocolMessage* msg;
const Identity& m_LocalIdentity;
2018-08-09 19:02:17 +00:00
IDataHandler* handler;
2018-09-17 16:12:42 +00:00
const ProtocolFrame frame;
2018-08-09 19:02:17 +00:00
2018-12-10 14:14:55 +00:00
AsyncFrameDecrypt(llarp::Logic* l, llarp_crypto* c,
2018-08-14 21:17:18 +00:00
const Identity& localIdent, IDataHandler* h,
2018-09-17 16:12:42 +00:00
ProtocolMessage* m, const ProtocolFrame& f)
2018-08-09 19:02:17 +00:00
: crypto(c)
, logic(l)
, msg(m)
, m_LocalIdentity(localIdent)
2018-08-09 19:02:17 +00:00
, handler(h)
, frame(f)
2018-08-09 19:02:17 +00:00
{
}
static void
Work(void* user)
{
2018-08-14 21:17:18 +00:00
AsyncFrameDecrypt* self = static_cast< AsyncFrameDecrypt* >(user);
auto crypto = self->crypto;
SharedSecret K;
SharedSecret sharedKey;
// copy
2018-09-17 16:12:42 +00:00
ProtocolFrame frame(self->frame);
if(!crypto->pqe_decrypt(self->frame.C, K,
pq_keypair_to_secret(self->m_LocalIdentity.pq)))
2018-08-09 19:02:17 +00:00
{
2018-09-17 16:12:42 +00:00
llarp::LogError("pqke failed C=", self->frame.C);
2018-08-09 19:02:17 +00:00
delete self->msg;
delete self;
return;
}
2018-08-14 21:17:18 +00:00
// decrypt
auto buf = frame.D.Buffer();
2018-09-17 16:12:42 +00:00
crypto->xchacha20(*buf, K, self->frame.N);
2018-08-09 19:02:17 +00:00
if(!self->msg->BDecode(buf))
{
llarp::LogError("failed to decode inner protocol message");
2018-08-12 17:22:29 +00:00
llarp::DumpBuffer(*buf);
2018-08-09 19:02:17 +00:00
delete self->msg;
delete self;
return;
}
// verify signature of outer message after we parsed the inner message
2018-09-17 16:12:42 +00:00
if(!self->frame.Verify(crypto, self->msg->sender))
{
2018-09-17 16:12:42 +00:00
llarp::LogError("intro frame has invalid signature Z=", self->frame.Z,
" from ", self->msg->sender.Addr());
self->frame.Dump< MAX_PROTOCOL_MESSAGE_SIZE >();
2018-09-17 15:32:37 +00:00
self->msg->Dump< MAX_PROTOCOL_MESSAGE_SIZE >();
delete self->msg;
delete self;
return;
}
byte_t tmp[64];
// K
memcpy(tmp, K, 32);
// PKE (A, B, N)
2018-09-17 16:12:42 +00:00
if(!self->m_LocalIdentity.KeyExchange(crypto->dh_server, tmp + 32,
self->msg->sender, self->frame.N))
{
llarp::LogError("x25519 key exchange failed");
2018-09-17 16:12:42 +00:00
self->frame.Dump< MAX_PROTOCOL_MESSAGE_SIZE >();
delete self->msg;
delete self;
return;
}
// S = HS( K + PKE( A, B, N))
crypto->shorthash(sharedKey, StackBuffer< decltype(tmp) >(tmp));
2018-08-09 19:02:17 +00:00
self->handler->PutIntroFor(self->msg->tag, self->msg->introReply);
self->handler->PutSenderFor(self->msg->tag, self->msg->sender);
self->handler->PutCachedSessionKeyFor(self->msg->tag, sharedKey);
2018-08-09 19:02:17 +00:00
self->msg->handler = self->handler;
2018-12-10 14:14:55 +00:00
self->logic->queue_job({self->msg, &ProtocolMessage::ProcessAsync});
2018-08-09 19:02:17 +00:00
delete self;
}
};
2018-08-14 21:17:18 +00:00
ProtocolFrame&
ProtocolFrame::operator=(const ProtocolFrame& other)
{
C = other.C;
D = other.D;
N = other.N;
Z = other.Z;
T = other.T;
2018-09-17 13:28:26 +00:00
S = other.S;
version = other.version;
2018-08-14 21:17:18 +00:00
return *this;
}
2018-08-09 19:02:17 +00:00
bool
2018-12-10 14:14:55 +00:00
ProtocolFrame::AsyncDecryptAndVerify(llarp::Logic* logic, llarp_crypto* c,
const PathID_t& srcPath,
2018-08-09 19:02:17 +00:00
llarp_threadpool* worker,
const Identity& localIdent,
2018-08-09 19:02:17 +00:00
IDataHandler* handler) const
{
2018-08-14 21:17:18 +00:00
if(T.IsZero())
2018-08-09 19:02:17 +00:00
{
llarp::LogInfo("Got protocol frame with new convo");
2018-08-09 19:02:17 +00:00
ProtocolMessage* msg = new ProtocolMessage();
msg->srcPath = srcPath;
2018-08-09 19:02:17 +00:00
// we need to dh
2018-08-14 21:17:18 +00:00
auto dh =
2018-09-17 16:12:42 +00:00
new AsyncFrameDecrypt(logic, c, localIdent, handler, msg, *this);
2018-08-14 21:17:18 +00:00
llarp_threadpool_queue_job(worker, {dh, &AsyncFrameDecrypt::Work});
2018-08-09 19:02:17 +00:00
return true;
}
const byte_t* shared = nullptr;
2018-08-09 19:02:17 +00:00
if(!handler->GetCachedSessionKeyFor(T, shared))
{
llarp::LogError("No cached session for T=", T);
return false;
}
ServiceInfo si;
if(!handler->GetSenderFor(T, si))
{
llarp::LogError("No sender for T=", T);
return false;
}
if(!Verify(c, si))
2018-08-09 19:02:17 +00:00
{
2018-09-17 15:32:37 +00:00
llarp::LogError("Signature failure from ", si.Addr());
2018-08-09 19:02:17 +00:00
return false;
}
ProtocolMessage* msg = new ProtocolMessage();
if(!DecryptPayloadInto(c, shared, *msg))
2018-08-09 19:02:17 +00:00
{
llarp::LogError("failed to decrypt message");
delete msg;
return false;
}
msg->srcPath = srcPath;
2018-08-09 19:02:17 +00:00
msg->handler = handler;
2018-12-10 14:14:55 +00:00
logic->queue_job({msg, &ProtocolMessage::ProcessAsync});
2018-08-09 19:02:17 +00:00
return true;
}
2018-09-17 15:32:37 +00:00
bool
ProtocolFrame::operator==(const ProtocolFrame& other) const
{
return C == other.C && D == other.D && N == other.N && Z == other.Z
&& T == other.T && S == other.S && version == other.version;
}
2018-07-22 23:14:29 +00:00
bool
2018-08-10 21:34:11 +00:00
ProtocolFrame::Verify(llarp_crypto* crypto, const ServiceInfo& from) const
2018-07-22 23:14:29 +00:00
{
2018-09-17 13:28:26 +00:00
ProtocolFrame copy(*this);
2018-07-22 23:14:29 +00:00
// save signature
// zero out signature for verify
2018-08-09 19:02:17 +00:00
copy.Z.Zero();
2018-07-22 23:14:29 +00:00
// serialize
byte_t tmp[MAX_PROTOCOL_MESSAGE_SIZE];
auto buf = llarp::StackBuffer< decltype(tmp) >(tmp);
2018-09-17 15:32:37 +00:00
if(!copy.BEncode(&buf))
2018-07-22 23:14:29 +00:00
{
2018-09-17 15:32:37 +00:00
llarp::LogError("bencode fail");
return false;
2018-07-22 23:14:29 +00:00
}
2018-09-17 15:32:37 +00:00
// rewind buffer
buf.sz = buf.cur - buf.base;
buf.cur = buf.base;
// verify
return from.Verify(crypto, buf, Z);
2018-07-22 23:14:29 +00:00
}
bool
ProtocolFrame::HandleMessage(llarp::routing::IMessageHandler* h,
__attribute__((unused)) llarp::Router* r) const
{
return h->HandleHiddenServiceFrame(this);
}
2018-07-19 04:58:39 +00:00
} // namespace service
} // namespace llarp