#include "link_intro.hpp" #include #include #include #include #include namespace llarp { bool LinkIntroMessage::DecodeKey(const llarp_buffer_t& key, llarp_buffer_t* buf) { if (key.startswith("a")) { llarp_buffer_t strbuf; if (!bencode_read_string(buf, &strbuf)) return false; if (strbuf.sz != 1) return false; return *strbuf.cur == 'i'; } if (key.startswith("n")) { if (N.BDecode(buf)) return true; llarp::LogWarn("failed to decode nonce in LIM"); return false; } if (key.startswith("p")) { return bencode_read_integer(buf, &P); } if (key.startswith("r")) { if (rc.BDecode(buf)) return true; llarp::LogWarn("failed to decode RC in LIM"); llarp::DumpBuffer(*buf); return false; } if (key.startswith("v")) { if (!bencode_read_integer(buf, &version)) return false; if (version != llarp::constants::proto_version) { llarp::LogWarn( "llarp protocol version mismatch ", version, " != ", llarp::constants::proto_version); return false; } llarp::LogDebug("LIM version ", version); return true; } if (key.startswith("z")) { return Z.BDecode(buf); } llarp::LogWarn("invalid LIM key: ", *key.cur); return false; } bool LinkIntroMessage::BEncode(llarp_buffer_t* buf) const { if (!bencode_start_dict(buf)) return false; if (!bencode_write_bytestring(buf, "a", 1)) return false; if (!bencode_write_bytestring(buf, "i", 1)) return false; if (!bencode_write_bytestring(buf, "n", 1)) return false; if (!N.BEncode(buf)) return false; if (!bencode_write_bytestring(buf, "p", 1)) return false; if (!bencode_write_uint64(buf, P)) return false; if (!bencode_write_bytestring(buf, "r", 1)) return false; if (!rc.BEncode(buf)) return false; if (!bencode_write_uint64_entry(buf, "v", 1, llarp::constants::proto_version)) return false; if (!bencode_write_bytestring(buf, "z", 1)) return false; if (!Z.BEncode(buf)) return false; return bencode_end(buf); } bool LinkIntroMessage::HandleMessage(AbstractRouter* /*router*/) const { if (!Verify()) return false; return session->GotLIM(this); } void LinkIntroMessage::Clear() { P = 0; N.Zero(); rc.Clear(); Z.Zero(); version = 0; } bool LinkIntroMessage::Sign(std::function signer) { Z.Zero(); std::array tmp; llarp_buffer_t buf(tmp); if (!BEncode(&buf)) return false; buf.sz = buf.cur - buf.base; buf.cur = buf.base; return signer(Z, buf); } bool LinkIntroMessage::Verify() const { LinkIntroMessage copy; copy = *this; copy.Z.Zero(); std::array tmp; llarp_buffer_t buf(tmp); if (!copy.BEncode(&buf)) return false; buf.sz = buf.cur - buf.base; buf.cur = buf.base; // outer signature if (!CryptoManager::instance()->verify(rc.pubkey, buf, Z)) { llarp::LogError("outer signature failure"); return false; } // verify RC if (!rc.Verify(llarp::time_now_ms())) { llarp::LogError("invalid RC in link intro"); return false; } return true; } } // namespace llarp