mirror of
https://github.com/oxen-io/lokinet
synced 2023-12-14 06:53:00 +01:00
chahca nonce size is 24 bytes
Lots of code was using 32-byte nonces for xchacha20 symmetric encryption, but this just means 8 extra bytes per packet wasted as chacha is only using the first 24 bytes of that nonce anyway. Changing this resulted in a lot of dead/dying code breaking, so this commit also removes a lot of that (and comments a couple places with TODO instead) Also nounce -> nonce where it came up.
This commit is contained in:
parent
abb2f63ec6
commit
9e9c1ea732
|
@ -12,7 +12,6 @@ endfunction()
|
|||
|
||||
lokinet_add_library(lokinet-cryptography
|
||||
crypto/crypto.cpp
|
||||
crypto/encrypted_frame.cpp
|
||||
crypto/types.cpp
|
||||
)
|
||||
|
||||
|
@ -207,7 +206,6 @@ lokinet_add_library(lokinet-config
|
|||
|
||||
# All path objects; link directly to lokinet-core
|
||||
lokinet_add_library(lokinet-path
|
||||
messages/relay.cpp
|
||||
path/abstracthophandler.cpp
|
||||
path/path.cpp
|
||||
path/path_context.cpp
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace llarp
|
|||
|
||||
static bool
|
||||
dh_client_priv(
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const SymmNonce& n)
|
||||
{
|
||||
llarp::SharedSecret dh_result;
|
||||
|
||||
|
@ -81,13 +81,13 @@ namespace llarp
|
|||
|
||||
static bool
|
||||
dh_server_priv(
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const SymmNonce& n)
|
||||
{
|
||||
llarp::SharedSecret dh_result;
|
||||
|
||||
if (dh(dh_result, pk, sk.toPublic(), pk.data(), sk))
|
||||
{
|
||||
return crypto_generichash_blake2b(shared.data(), 32, n.data(), 32, dh_result.data(), 32)
|
||||
return crypto_generichash_blake2b(shared.data(), 32, n.data(), n.size(), dh_result.data(), 32)
|
||||
!= -1;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ namespace llarp
|
|||
|
||||
if (dh(dh_result.data(), pk, sk, pk, sk))
|
||||
{
|
||||
return crypto_generichash_blake2b(shared, 32, nonce, 32, dh_result.data(), 32) != -1;
|
||||
return crypto_generichash_blake2b(shared, 32, nonce, 24, dh_result.data(), 32) != -1;
|
||||
}
|
||||
|
||||
llarp::LogWarn("crypto::dh_server - dh failed");
|
||||
|
@ -143,7 +143,7 @@ namespace llarp
|
|||
}
|
||||
|
||||
bool
|
||||
crypto::xchacha20(uint8_t* buf, size_t size, const SharedSecret& k, const TunnelNonce& n)
|
||||
crypto::xchacha20(uint8_t* buf, size_t size, const SharedSecret& k, const SymmNonce& n)
|
||||
{
|
||||
return xchacha20(buf, size, n.data(), k.data());
|
||||
}
|
||||
|
@ -155,13 +155,13 @@ namespace llarp
|
|||
}
|
||||
|
||||
// do a round of chacha for and return the nonce xor the given xor_factor
|
||||
TunnelNonce
|
||||
SymmNonce
|
||||
crypto::onion(
|
||||
unsigned char* buf,
|
||||
size_t size,
|
||||
const SharedSecret& k,
|
||||
const TunnelNonce& nonce,
|
||||
const ShortHash& xor_factor)
|
||||
const SymmNonce& nonce,
|
||||
const SymmNonce& xor_factor)
|
||||
{
|
||||
if (!crypto::xchacha20(buf, size, k, nonce))
|
||||
throw std::runtime_error{"chacha failed during onion step"};
|
||||
|
@ -171,14 +171,14 @@ namespace llarp
|
|||
|
||||
bool
|
||||
crypto::dh_client(
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const SymmNonce& n)
|
||||
{
|
||||
return dh_client_priv(shared, pk, sk, n);
|
||||
}
|
||||
/// path dh relay side
|
||||
bool
|
||||
crypto::dh_server(
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const SymmNonce& n)
|
||||
{
|
||||
return dh_server_priv(shared, pk, sk, n);
|
||||
}
|
||||
|
@ -192,20 +192,6 @@ namespace llarp
|
|||
{
|
||||
return dh_server_priv(shared_secret, other_pk, local_pk, nonce);
|
||||
}
|
||||
/// transport dh client side
|
||||
bool
|
||||
crypto::transport_dh_client(
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
|
||||
{
|
||||
return dh_client_priv(shared, pk, sk, n);
|
||||
}
|
||||
/// transport dh server side
|
||||
bool
|
||||
crypto::transport_dh_server(
|
||||
llarp::SharedSecret& shared, const PubKey& pk, const SecretKey& sk, const TunnelNonce& n)
|
||||
{
|
||||
return dh_server_priv(shared, pk, sk, n);
|
||||
}
|
||||
|
||||
bool
|
||||
crypto::shorthash(ShortHash& result, uint8_t* buf, size_t size)
|
||||
|
|
|
@ -23,36 +23,30 @@ namespace llarp
|
|||
|
||||
/// xchacha symmetric cipher
|
||||
bool
|
||||
xchacha20(uint8_t*, size_t size, const SharedSecret&, const TunnelNonce&);
|
||||
xchacha20(uint8_t*, size_t size, const SharedSecret&, const SymmNonce&);
|
||||
bool
|
||||
xchacha20(uint8_t*, size_t size, const uint8_t*, const uint8_t*);
|
||||
|
||||
TunnelNonce
|
||||
SymmNonce
|
||||
onion(
|
||||
unsigned char* buf,
|
||||
size_t size,
|
||||
const SharedSecret& k,
|
||||
const TunnelNonce& nonce,
|
||||
const ShortHash& xor_factor);
|
||||
const SymmNonce& nonce,
|
||||
const SymmNonce& xor_factor);
|
||||
|
||||
/// path dh creator's side
|
||||
bool
|
||||
dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&);
|
||||
dh_client(SharedSecret&, const PubKey&, const SecretKey&, const SymmNonce&);
|
||||
/// path dh relay side
|
||||
bool
|
||||
dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&);
|
||||
dh_server(SharedSecret&, const PubKey&, const SecretKey&, const SymmNonce&);
|
||||
bool
|
||||
dh_server(
|
||||
uint8_t* shared_secret,
|
||||
const uint8_t* other_pk,
|
||||
const uint8_t* local_pk,
|
||||
const uint8_t* nonce);
|
||||
/// transport dh client side
|
||||
bool
|
||||
transport_dh_client(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&);
|
||||
/// transport dh server side
|
||||
bool
|
||||
transport_dh_server(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&);
|
||||
/// blake2b 256 bit
|
||||
bool
|
||||
shorthash(ShortHash&, uint8_t*, size_t size);
|
||||
|
|
|
@ -1,127 +0,0 @@
|
|||
#include "encrypted_frame.hpp"
|
||||
|
||||
#include "crypto.hpp"
|
||||
|
||||
#include <llarp/util/logging.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
bool
|
||||
EncryptedFrame::DoEncrypt(const SharedSecret& shared, bool noDH)
|
||||
{
|
||||
uint8_t* hash_ptr = data();
|
||||
uint8_t* nonce_ptr = hash_ptr + SHORTHASHSIZE;
|
||||
uint8_t* pubkey_ptr = nonce_ptr + TUNNONCESIZE;
|
||||
uint8_t* body_ptr = pubkey_ptr + PUBKEYSIZE;
|
||||
|
||||
if (noDH)
|
||||
{
|
||||
crypto::randbytes(nonce_ptr, TUNNONCESIZE);
|
||||
crypto::randbytes(pubkey_ptr, PUBKEYSIZE);
|
||||
}
|
||||
|
||||
TunnelNonce nonce(nonce_ptr);
|
||||
|
||||
// encrypt body
|
||||
if (!crypto::xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce))
|
||||
{
|
||||
llarp::LogError("encrypt failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!crypto::hmac(hash_ptr, nonce_ptr, size() - SHORTHASHSIZE, shared))
|
||||
{
|
||||
llarp::LogError("Failed to generate message auth");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EncryptedFrame::EncryptInPlace(const SecretKey& ourSecretKey, const PubKey& otherPubkey)
|
||||
{
|
||||
// format of frame is
|
||||
// <32 bytes keyed hash of following data>
|
||||
// <32 bytes nonce>
|
||||
// <32 bytes pubkey>
|
||||
// <N bytes encrypted payload>
|
||||
//
|
||||
byte_t* hash = data();
|
||||
byte_t* noncePtr = hash + SHORTHASHSIZE;
|
||||
byte_t* pubkey = noncePtr + TUNNONCESIZE;
|
||||
|
||||
SharedSecret shared;
|
||||
|
||||
// set our pubkey
|
||||
memcpy(pubkey, ourSecretKey.toPublic().data(), PUBKEYSIZE);
|
||||
// randomize nonce
|
||||
crypto::randbytes(noncePtr, TUNNONCESIZE);
|
||||
TunnelNonce nonce(noncePtr);
|
||||
|
||||
// derive shared key
|
||||
if (!crypto::dh_client(shared, otherPubkey, ourSecretKey, nonce))
|
||||
{
|
||||
llarp::LogError("DH failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return DoEncrypt(shared, false);
|
||||
}
|
||||
|
||||
bool
|
||||
EncryptedFrame::DoDecrypt(const SharedSecret& shared)
|
||||
{
|
||||
uint8_t* hash_ptr = data();
|
||||
uint8_t* nonce_ptr = hash_ptr + SHORTHASHSIZE;
|
||||
uint8_t* body_ptr = hash_ptr + EncryptedFrameOverheadSize;
|
||||
|
||||
TunnelNonce nonce(nonce_ptr);
|
||||
|
||||
ShortHash digest;
|
||||
if (!crypto::hmac(digest.data(), nonce_ptr, size() - SHORTHASHSIZE, shared))
|
||||
{
|
||||
llarp::LogError("Digest failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!std::equal(digest.begin(), digest.end(), hash_ptr))
|
||||
{
|
||||
llarp::LogError("message authentication failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!crypto::xchacha20(body_ptr, size() - EncryptedFrameOverheadSize, shared, nonce))
|
||||
{
|
||||
llarp::LogError("decrypt failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
EncryptedFrame::DecryptInPlace(const SecretKey& ourSecretKey)
|
||||
{
|
||||
// format of frame is
|
||||
// <32 bytes keyed hash of following data>
|
||||
// <32 bytes nonce>
|
||||
// <32 bytes pubkey>
|
||||
// <N bytes encrypted payload>
|
||||
//
|
||||
byte_t* noncePtr = data() + SHORTHASHSIZE;
|
||||
TunnelNonce nonce(noncePtr);
|
||||
PubKey otherPubkey(noncePtr + TUNNONCESIZE);
|
||||
|
||||
SharedSecret shared;
|
||||
|
||||
// use dh_server because we are not the creator of this message
|
||||
if (!crypto::dh_server(shared, otherPubkey, ourSecretKey, nonce))
|
||||
{
|
||||
llarp::LogError("DH failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
return DoDecrypt(shared);
|
||||
}
|
||||
} // namespace llarp
|
|
@ -1,87 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "encrypted.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include <llarp/util/buffer.hpp>
|
||||
#include <llarp/util/mem.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
static constexpr size_t EncryptedFrameOverheadSize = PUBKEYSIZE + TUNNONCESIZE + SHORTHASHSIZE;
|
||||
static constexpr size_t EncryptedFrameBodySize = 128 * 6;
|
||||
static constexpr size_t EncryptedFrameSize = EncryptedFrameOverheadSize + EncryptedFrameBodySize;
|
||||
|
||||
struct EncryptedFrame : public Encrypted<EncryptedFrameSize>
|
||||
{
|
||||
EncryptedFrame() : EncryptedFrame(EncryptedFrameBodySize)
|
||||
{}
|
||||
|
||||
EncryptedFrame(size_t sz)
|
||||
: Encrypted<EncryptedFrameSize>(
|
||||
std::min(sz, EncryptedFrameBodySize) + EncryptedFrameOverheadSize)
|
||||
{}
|
||||
|
||||
void
|
||||
Resize(size_t sz)
|
||||
{
|
||||
if (sz <= EncryptedFrameSize)
|
||||
{
|
||||
_sz = sz;
|
||||
UpdateBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DoEncrypt(const SharedSecret& shared, bool noDH = false);
|
||||
|
||||
bool
|
||||
DecryptInPlace(const SecretKey& seckey);
|
||||
|
||||
bool
|
||||
DoDecrypt(const SharedSecret& shared);
|
||||
|
||||
bool
|
||||
EncryptInPlace(const SecretKey& seckey, const PubKey& other);
|
||||
};
|
||||
|
||||
template <typename User>
|
||||
struct AsyncFrameDecrypter
|
||||
{
|
||||
using User_ptr = std::shared_ptr<User>;
|
||||
using DecryptHandler = std::function<void(llarp_buffer_t*, User_ptr)>;
|
||||
|
||||
void
|
||||
Decrypt(User_ptr user)
|
||||
{
|
||||
if (target.DecryptInPlace(seckey))
|
||||
{
|
||||
auto buf = target.Buffer();
|
||||
buf->cur = buf->base + EncryptedFrameOverheadSize;
|
||||
result(buf, user);
|
||||
}
|
||||
else
|
||||
result(nullptr, user);
|
||||
}
|
||||
|
||||
AsyncFrameDecrypter(const SecretKey& secretkey, DecryptHandler h)
|
||||
: result(std::move(h)), seckey(secretkey)
|
||||
{}
|
||||
|
||||
DecryptHandler result;
|
||||
const SecretKey& seckey;
|
||||
EncryptedFrame target;
|
||||
|
||||
using WorkFunc_t = std::function<void(void)>;
|
||||
using WorkerFunction_t = std::function<void(WorkFunc_t)>;
|
||||
|
||||
void
|
||||
AsyncDecrypt(const EncryptedFrame& frame, User_ptr u, WorkerFunction_t worker)
|
||||
{
|
||||
target = frame;
|
||||
worker([this, u = std::move(u)]() mutable { Decrypt(std::move(u)); });
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
|
@ -169,10 +169,6 @@ namespace llarp
|
|||
/// PKE(result, publickey, secretkey, nonce)
|
||||
using path_dh_func = bool (*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&);
|
||||
|
||||
/// TKE(result, publickey, secretkey, nonce)
|
||||
using transport_dh_func =
|
||||
bool (*)(SharedSecret&, const PubKey&, const SecretKey&, const TunnelNonce&);
|
||||
|
||||
/// SH(result, body)
|
||||
using shorthash_func = bool (*)(ShortHash&, const llarp_buffer_t&);
|
||||
} // namespace llarp
|
||||
|
|
|
@ -1235,7 +1235,9 @@ namespace llarp
|
|||
return;
|
||||
}
|
||||
// generate hash of hop key for nonce mutation
|
||||
crypto::shorthash(hop->nonceXOR, hop->pathKey.data(), hop->pathKey.size());
|
||||
ShortHash xor_hash;
|
||||
crypto::shorthash(xor_hash, hop->pathKey.data(), hop->pathKey.size());
|
||||
hop->nonceXOR = xor_hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate
|
||||
|
||||
// set and check path lifetime
|
||||
hop->lifetime = 1ms * lifetime;
|
||||
|
@ -1641,7 +1643,7 @@ namespace llarp
|
|||
try
|
||||
{
|
||||
oxenc::bt_dict_consumer btdc{m.body()};
|
||||
auto nonce = TunnelNonce{btdc.require<ustring_view>("NONCE").data()};
|
||||
auto nonce = SymmNonce{btdc.require<ustring_view>("NONCE").data()};
|
||||
auto path_id_str = btdc.require<ustring_view>("PATHID");
|
||||
auto payload = btdc.require<std::string>("PAYLOAD");
|
||||
auto path_id = PathID_t{path_id_str.data()};
|
||||
|
@ -1675,7 +1677,7 @@ namespace llarp
|
|||
return;
|
||||
|
||||
oxenc::bt_dict_consumer resp_btdc{response.body()};
|
||||
auto nonce = TunnelNonce{resp_btdc.require<ustring_view>("NONCE").data()};
|
||||
auto nonce = SymmNonce{resp_btdc.require<ustring_view>("NONCE").data()};
|
||||
auto payload = resp_btdc.require<std::string>("PAYLOAD");
|
||||
auto resp_payload = hop->onion_and_payload(payload, path_id, nonce);
|
||||
prev_message.respond(std::move(resp_payload), false);
|
||||
|
|
|
@ -29,7 +29,9 @@ namespace llarp
|
|||
throw std::runtime_error{std::move(err)};
|
||||
}
|
||||
// generate nonceXOR value self->hop->pathKey
|
||||
crypto::shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size());
|
||||
ShortHash hash;
|
||||
crypto::shorthash(hash, hop.shared.data(), hop.shared.size());
|
||||
hop.nonceXOR = hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate
|
||||
|
||||
hop.upstream = nextHop;
|
||||
}
|
||||
|
@ -56,7 +58,7 @@ namespace llarp
|
|||
crypto::encryption_keygen(framekey);
|
||||
|
||||
SharedSecret shared;
|
||||
TunnelNonce outer_nonce;
|
||||
SymmNonce outer_nonce;
|
||||
outer_nonce.Randomize();
|
||||
|
||||
// derive (outer) shared key
|
||||
|
|
|
@ -1,123 +0,0 @@
|
|||
#include "relay.hpp"
|
||||
|
||||
#include <llarp/path/path_context.hpp>
|
||||
#include <llarp/router/router.hpp>
|
||||
#include <llarp/util/bencode.hpp>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
void
|
||||
RelayUpstreamMessage::clear()
|
||||
{
|
||||
pathid.Zero();
|
||||
enc.Clear();
|
||||
nonce.Zero();
|
||||
version = 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
RelayUpstreamMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("a", "u");
|
||||
btdp.append("p", pathid.ToView());
|
||||
btdp.append("v", llarp::constants::proto_version);
|
||||
btdp.append("x", std::string_view{reinterpret_cast<const char*>(enc.data()), enc.size()});
|
||||
btdp.append("y", std::string_view{reinterpret_cast<const char*>(nonce.data()), nonce.size()});
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(link_cat, "Error: RelayUpstreamMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
RelayUpstreamMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("x", enc, read, key, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("y", nonce, read, key, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
RelayUpstreamMessage::handle_message(Router* r) const
|
||||
{
|
||||
path::HopHandler_ptr path = r->path_context().GetPath(pathid);
|
||||
path = path ? path : r->path_context().GetTransitHop(conn->remote_rc.router_id(), pathid);
|
||||
if (path)
|
||||
{
|
||||
return path->HandleUpstream(llarp_buffer_t(enc), nonce, r);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
RelayDownstreamMessage::clear()
|
||||
{
|
||||
pathid.Zero();
|
||||
enc.Clear();
|
||||
nonce.Zero();
|
||||
version = 0;
|
||||
}
|
||||
|
||||
std::string
|
||||
RelayDownstreamMessage::bt_encode() const
|
||||
{
|
||||
oxenc::bt_dict_producer btdp;
|
||||
|
||||
try
|
||||
{
|
||||
btdp.append("a", "d");
|
||||
btdp.append("p", pathid.ToView());
|
||||
btdp.append("v", llarp::constants::proto_version);
|
||||
btdp.append("x", std::string_view{reinterpret_cast<const char*>(enc.data()), enc.size()});
|
||||
btdp.append("y", std::string_view{reinterpret_cast<const char*>(nonce.data()), nonce.size()});
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
log::critical(link_cat, "Error: RelayDownstreamMessage failed to bt encode contents!");
|
||||
}
|
||||
|
||||
return std::move(btdp).str();
|
||||
}
|
||||
|
||||
bool
|
||||
RelayDownstreamMessage::decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf)
|
||||
{
|
||||
bool read = false;
|
||||
if (!BEncodeMaybeReadDictEntry("p", pathid, read, key, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeVerifyVersion("v", version, llarp::constants::proto_version, read, key, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("x", enc, read, key, buf))
|
||||
return false;
|
||||
if (!BEncodeMaybeReadDictEntry("y", nonce, read, key, buf))
|
||||
return false;
|
||||
return read;
|
||||
}
|
||||
|
||||
bool
|
||||
RelayDownstreamMessage::handle_message(Router* r) const
|
||||
{
|
||||
path::HopHandler_ptr path = r->path_context().GetPath(pathid);
|
||||
path = path ? path : r->path_context().GetTransitHop(conn->remote_rc.router_id(), pathid);
|
||||
if (path)
|
||||
{
|
||||
return path->HandleDownstream(llarp_buffer_t(enc), nonce, r);
|
||||
}
|
||||
llarp::LogWarn("no path for downstream message id=", pathid);
|
||||
return false;
|
||||
}
|
||||
} // namespace llarp
|
|
@ -1,75 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "link_message.hpp"
|
||||
|
||||
#include <llarp/crypto/encrypted.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/path/path_types.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
/*
|
||||
Data messages to be sent via quic datagrams
|
||||
*/
|
||||
|
||||
struct RelayUpstreamMessage final : public AbstractLinkMessage
|
||||
{
|
||||
Encrypted<MAX_LINK_MSG_SIZE - 128> enc;
|
||||
TunnelNonce nonce;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
handle_message(Router* router) const override;
|
||||
|
||||
void
|
||||
clear() override;
|
||||
|
||||
const char*
|
||||
name() const override
|
||||
{
|
||||
return "RelayUpstream";
|
||||
}
|
||||
uint16_t
|
||||
priority() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct RelayDownstreamMessage final : public AbstractLinkMessage
|
||||
{
|
||||
Encrypted<MAX_LINK_MSG_SIZE - 128> enc;
|
||||
TunnelNonce nonce;
|
||||
|
||||
bool
|
||||
decode_key(const llarp_buffer_t& key, llarp_buffer_t* buf) override;
|
||||
|
||||
std::string
|
||||
bt_encode() const override;
|
||||
|
||||
bool
|
||||
handle_message(Router* router) const override;
|
||||
|
||||
void
|
||||
clear() override;
|
||||
|
||||
const char*
|
||||
name() const override
|
||||
{
|
||||
return "RelayDownstream";
|
||||
}
|
||||
|
||||
uint16_t
|
||||
priority() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
} // namespace llarp
|
|
@ -6,7 +6,7 @@ namespace llarp::path
|
|||
{
|
||||
std::string
|
||||
make_onion_payload(
|
||||
const TunnelNonce& nonce, const PathID_t& path_id, const std::string_view& inner_payload)
|
||||
const SymmNonce& nonce, const PathID_t& path_id, const std::string_view& inner_payload)
|
||||
{
|
||||
return make_onion_payload(
|
||||
nonce,
|
||||
|
@ -17,7 +17,7 @@ namespace llarp::path
|
|||
|
||||
std::string
|
||||
make_onion_payload(
|
||||
const TunnelNonce& nonce, const PathID_t& path_id, const ustring_view& inner_payload)
|
||||
const SymmNonce& nonce, const PathID_t& path_id, const ustring_view& inner_payload)
|
||||
{
|
||||
oxenc::bt_dict_producer next_dict;
|
||||
next_dict.append("NONCE", nonce.ToView());
|
||||
|
@ -26,35 +26,4 @@ namespace llarp::path
|
|||
|
||||
return std::move(next_dict).str();
|
||||
}
|
||||
|
||||
// handle data in upstream direction
|
||||
bool
|
||||
AbstractHopHandler::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r)
|
||||
{
|
||||
auto& pkt = m_UpstreamQueue.emplace_back();
|
||||
pkt.first.resize(X.sz);
|
||||
std::copy_n(X.base, X.sz, pkt.first.begin());
|
||||
pkt.second = Y;
|
||||
r->TriggerPump();
|
||||
return true;
|
||||
}
|
||||
|
||||
// handle data in downstream direction
|
||||
bool
|
||||
AbstractHopHandler::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r)
|
||||
{
|
||||
auto& pkt = m_DownstreamQueue.emplace_back();
|
||||
pkt.first.resize(X.sz);
|
||||
std::copy_n(X.base, X.sz, pkt.first.begin());
|
||||
pkt.second = Y;
|
||||
r->TriggerPump();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
AbstractHopHandler::DecayFilters(llarp_time_t now)
|
||||
{
|
||||
m_UpstreamReplayFilter.Decay(now);
|
||||
m_DownstreamReplayFilter.Decay(now);
|
||||
}
|
||||
} // namespace llarp::path
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <llarp/crypto/encrypted_frame.hpp>
|
||||
#include "path_types.hpp"
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/messages/relay.hpp>
|
||||
#include <llarp/util/decaying_hashset.hpp>
|
||||
#include <llarp/util/types.hpp>
|
||||
|
||||
|
@ -25,24 +24,18 @@ namespace llarp
|
|||
|
||||
std::string
|
||||
make_onion_payload(
|
||||
const TunnelNonce& nonce, const PathID_t& path_id, const std::string_view& inner_payload);
|
||||
const SymmNonce& nonce, const PathID_t& path_id, const std::string_view& inner_payload);
|
||||
std::string
|
||||
make_onion_payload(
|
||||
const TunnelNonce& nonce, const PathID_t& path_id, const ustring_view& inner_payload);
|
||||
const SymmNonce& nonce, const PathID_t& path_id, const ustring_view& inner_payload);
|
||||
|
||||
struct AbstractHopHandler
|
||||
{
|
||||
using TrafficEvent_t = std::pair<std::vector<byte_t>, TunnelNonce>;
|
||||
using TrafficQueue_t = std::list<TrafficEvent_t>;
|
||||
|
||||
virtual ~AbstractHopHandler() = default;
|
||||
|
||||
virtual PathID_t
|
||||
RXID() const = 0;
|
||||
|
||||
void
|
||||
DecayFilters(llarp_time_t now);
|
||||
|
||||
virtual bool
|
||||
Expired(llarp_time_t now) const = 0;
|
||||
|
||||
|
@ -61,17 +54,6 @@ namespace llarp
|
|||
send_path_control_message(
|
||||
std::string method, std::string body, std::function<void(std::string)> func) = 0;
|
||||
|
||||
/// send routing message and increment sequence number
|
||||
virtual bool
|
||||
SendRoutingMessage(std::string payload, Router* r) = 0;
|
||||
|
||||
// handle data in upstream direction
|
||||
virtual bool
|
||||
HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*);
|
||||
// handle data in downstream direction
|
||||
virtual bool
|
||||
HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*);
|
||||
|
||||
/// return timestamp last remote activity happened at
|
||||
virtual llarp_time_t
|
||||
LastRemoteActivityAt() const = 0;
|
||||
|
@ -82,29 +64,8 @@ namespace llarp
|
|||
return m_SequenceNum++;
|
||||
}
|
||||
|
||||
virtual void
|
||||
FlushUpstream(Router* r) = 0;
|
||||
|
||||
virtual void
|
||||
FlushDownstream(Router* r) = 0;
|
||||
|
||||
protected:
|
||||
uint64_t m_SequenceNum = 0;
|
||||
TrafficQueue_t m_UpstreamQueue;
|
||||
TrafficQueue_t m_DownstreamQueue;
|
||||
util::DecayingHashSet<TunnelNonce> m_UpstreamReplayFilter;
|
||||
util::DecayingHashSet<TunnelNonce> m_DownstreamReplayFilter;
|
||||
|
||||
virtual void
|
||||
UpstreamWork(TrafficQueue_t queue, Router* r) = 0;
|
||||
|
||||
virtual void
|
||||
DownstreamWork(TrafficQueue_t queue, Router* r) = 0;
|
||||
|
||||
virtual void
|
||||
HandleAllUpstream(std::vector<RelayUpstreamMessage> msgs, Router* r) = 0;
|
||||
virtual void
|
||||
HandleAllDownstream(std::vector<RelayDownstreamMessage> msgs, Router* r) = 0;
|
||||
};
|
||||
|
||||
using HopHandler_ptr = std::shared_ptr<AbstractHopHandler>;
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace llarp::path
|
|||
auto payload = std::move(btdp).str();
|
||||
|
||||
// TODO: old impl padded messages if smaller than a certain size; do we still want to?
|
||||
TunnelNonce nonce;
|
||||
SymmNonce nonce;
|
||||
nonce.Randomize();
|
||||
|
||||
// chacha and mutate nonce for each hop
|
||||
|
@ -131,13 +131,13 @@ namespace llarp::path
|
|||
return;
|
||||
}
|
||||
|
||||
TunnelNonce nonce{};
|
||||
SymmNonce nonce{};
|
||||
std::string payload;
|
||||
try
|
||||
{
|
||||
oxenc::bt_dict_consumer btdc{m.body()};
|
||||
|
||||
auto nonce = TunnelNonce{btdc.require<ustring_view>("NONCE").data()};
|
||||
auto nonce = SymmNonce{btdc.require<ustring_view>("NONCE").data()};
|
||||
auto payload = btdc.require<std::string>("PAYLOAD");
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
|
@ -164,22 +164,6 @@ namespace llarp::path
|
|||
});
|
||||
}
|
||||
|
||||
bool
|
||||
Path::HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r)
|
||||
{
|
||||
if (not m_UpstreamReplayFilter.Insert(Y))
|
||||
return false;
|
||||
return AbstractHopHandler::HandleUpstream(X, Y, r);
|
||||
}
|
||||
|
||||
bool
|
||||
Path::HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router* r)
|
||||
{
|
||||
if (not m_DownstreamReplayFilter.Insert(Y))
|
||||
return false;
|
||||
return AbstractHopHandler::HandleDownstream(X, Y, r);
|
||||
}
|
||||
|
||||
RouterID
|
||||
Path::Endpoint() const
|
||||
{
|
||||
|
@ -319,8 +303,6 @@ namespace llarp::path
|
|||
{"ready", IsReady()},
|
||||
{"txRateCurrent", m_LastTXRate},
|
||||
{"rxRateCurrent", m_LastRXRate},
|
||||
{"replayTX", m_UpstreamReplayFilter.Size()},
|
||||
{"replayRX", m_DownstreamReplayFilter.Size()},
|
||||
{"hasExit", SupportsAnyRoles(ePathRoleExit)}};
|
||||
|
||||
std::vector<util::StatusObject> hopsObj;
|
||||
|
@ -454,73 +436,6 @@ namespace llarp::path
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Path::HandleAllUpstream(std::vector<RelayUpstreamMessage> msgs, Router* r)
|
||||
{
|
||||
for (const auto& msg : msgs)
|
||||
{
|
||||
if (r->send_data_message(upstream(), msg.bt_encode()))
|
||||
{
|
||||
m_TXRate += msg.enc.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug("failed to send upstream to ", upstream());
|
||||
}
|
||||
}
|
||||
r->TriggerPump();
|
||||
}
|
||||
|
||||
void
|
||||
Path::UpstreamWork(TrafficQueue_t msgs, Router* r)
|
||||
{
|
||||
std::vector<RelayUpstreamMessage> sendmsgs(msgs.size());
|
||||
size_t idx = 0;
|
||||
for (auto& ev : msgs)
|
||||
{
|
||||
TunnelNonce n = ev.second;
|
||||
|
||||
uint8_t* buf = ev.first.data();
|
||||
size_t sz = ev.first.size();
|
||||
|
||||
for (const auto& hop : hops)
|
||||
{
|
||||
crypto::xchacha20(buf, sz, hop.shared, n);
|
||||
n ^= hop.nonceXOR;
|
||||
}
|
||||
auto& msg = sendmsgs[idx];
|
||||
std::memcpy(msg.enc.data(), buf, sz);
|
||||
msg.nonce = ev.second;
|
||||
msg.pathid = TXID();
|
||||
++idx;
|
||||
}
|
||||
r->loop()->call([self = shared_from_this(), data = std::move(sendmsgs), r]() mutable {
|
||||
self->HandleAllUpstream(std::move(data), r);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Path::FlushUpstream(Router* r)
|
||||
{
|
||||
if (not m_UpstreamQueue.empty())
|
||||
{
|
||||
r->queue_work([self = shared_from_this(),
|
||||
data = std::exchange(m_UpstreamQueue, {}),
|
||||
r]() mutable { self->UpstreamWork(std::move(data), r); });
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Path::FlushDownstream(Router* r)
|
||||
{
|
||||
if (not m_DownstreamQueue.empty())
|
||||
{
|
||||
r->queue_work([self = shared_from_this(),
|
||||
data = std::exchange(m_DownstreamQueue, {}),
|
||||
r]() mutable { self->DownstreamWork(std::move(data), r); });
|
||||
}
|
||||
}
|
||||
|
||||
/// how long we wait for a path to become active again after it times out
|
||||
constexpr auto PathReanimationTimeout = 45s;
|
||||
|
||||
|
@ -548,47 +463,6 @@ namespace llarp::path
|
|||
return fmt::format("TX={} RX={}", TXID(), RXID());
|
||||
}
|
||||
|
||||
void
|
||||
Path::DownstreamWork(TrafficQueue_t msgs, Router* r)
|
||||
{
|
||||
std::vector<RelayDownstreamMessage> sendMsgs(msgs.size());
|
||||
size_t idx = 0;
|
||||
for (auto& ev : msgs)
|
||||
{
|
||||
sendMsgs[idx].nonce = ev.second;
|
||||
|
||||
uint8_t* buf = ev.first.data();
|
||||
size_t sz = ev.first.size();
|
||||
|
||||
for (const auto& hop : hops)
|
||||
{
|
||||
sendMsgs[idx].nonce ^= hop.nonceXOR;
|
||||
crypto::xchacha20(buf, sz, hop.shared, sendMsgs[idx].nonce);
|
||||
}
|
||||
|
||||
std::memcpy(sendMsgs[idx].enc.data(), buf, sz);
|
||||
++idx;
|
||||
}
|
||||
r->loop()->call([self = shared_from_this(), msgs = std::move(sendMsgs), r]() mutable {
|
||||
self->HandleAllDownstream(std::move(msgs), r);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
Path::HandleAllDownstream(std::vector<RelayDownstreamMessage> msgs, Router* /* r */)
|
||||
{
|
||||
for (const auto& msg : msgs)
|
||||
{
|
||||
const llarp_buffer_t buf{msg.enc};
|
||||
m_RXRate += buf.sz;
|
||||
// if (HandleRoutingMessage(buf, r))
|
||||
// {
|
||||
// r->TriggerPump();
|
||||
// m_LastRecvMessage = r->now();
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/** Note: this is one of two places where AbstractRoutingMessage::bt_encode() is called, the
|
||||
other of which is llarp/path/transit_hop.cpp in TransitHop::SendRoutingMessage(). For now,
|
||||
we will default to the override of ::bt_encode() that returns an std::string. The role that
|
||||
|
@ -604,6 +478,7 @@ namespace llarp::path
|
|||
functions it calls and so on) will need to be modified to take an std::string that we can
|
||||
std::move around.
|
||||
*/
|
||||
/* TODO: replace this with sending an onion-ed data message
|
||||
bool
|
||||
Path::SendRoutingMessage(std::string payload, Router*)
|
||||
{
|
||||
|
@ -627,6 +502,7 @@ namespace llarp::path
|
|||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
template <typename Samples_t>
|
||||
static llarp_time_t
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
#include "pathset.hpp"
|
||||
|
||||
#include <llarp/constants/path.hpp>
|
||||
#include <llarp/crypto/encrypted_frame.hpp>
|
||||
#include <llarp/crypto/types.hpp>
|
||||
#include <llarp/messages/relay.hpp>
|
||||
#include <llarp/router_id.hpp>
|
||||
#include <llarp/service/intro.hpp>
|
||||
#include <llarp/util/aligned.hpp>
|
||||
|
@ -122,14 +120,6 @@ namespace llarp
|
|||
return _status;
|
||||
}
|
||||
|
||||
// handle data in upstream direction
|
||||
bool
|
||||
HandleUpstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*) override;
|
||||
// handle data in downstream direction
|
||||
|
||||
bool
|
||||
HandleDownstream(const llarp_buffer_t& X, const TunnelNonce& Y, Router*) override;
|
||||
|
||||
const std::string&
|
||||
ShortName() const;
|
||||
|
||||
|
@ -223,9 +213,6 @@ namespace llarp
|
|||
std::string body,
|
||||
std::function<void(std::string)> func = nullptr) override;
|
||||
|
||||
bool
|
||||
SendRoutingMessage(std::string payload, Router* r) override;
|
||||
|
||||
bool
|
||||
IsReady() const;
|
||||
|
||||
|
@ -252,25 +239,6 @@ namespace llarp
|
|||
std::string
|
||||
name() const;
|
||||
|
||||
void
|
||||
FlushUpstream(Router* r) override;
|
||||
|
||||
void
|
||||
FlushDownstream(Router* r) override;
|
||||
|
||||
protected:
|
||||
void
|
||||
UpstreamWork(TrafficQueue_t queue, Router* r) override;
|
||||
|
||||
void
|
||||
DownstreamWork(TrafficQueue_t queue, Router* r) override;
|
||||
|
||||
void
|
||||
HandleAllUpstream(std::vector<RelayUpstreamMessage> msgs, Router* r) override;
|
||||
|
||||
void
|
||||
HandleAllDownstream(std::vector<RelayDownstreamMessage> msgs, Router* r) override;
|
||||
|
||||
private:
|
||||
bool
|
||||
SendLatencyMessage(Router* r);
|
||||
|
|
|
@ -203,7 +203,6 @@ namespace llarp::path
|
|||
}
|
||||
else
|
||||
{
|
||||
itr->second->DecayFilters(now);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
@ -217,7 +216,6 @@ namespace llarp::path
|
|||
}
|
||||
else
|
||||
{
|
||||
itr->second->DecayFilters(now);
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include "pathset.hpp"
|
||||
#include "transit_hop.hpp"
|
||||
|
||||
#include <llarp/crypto/encrypted_frame.hpp>
|
||||
#include <llarp/ev/ev.hpp>
|
||||
#include <llarp/net/ip_address.hpp>
|
||||
#include <llarp/util/compare_ptr.hpp>
|
||||
|
|
|
@ -32,11 +32,11 @@ namespace llarp
|
|||
/// shared secret at this hop
|
||||
SharedSecret shared;
|
||||
/// hash of shared secret used for nonce mutation
|
||||
ShortHash nonceXOR;
|
||||
SymmNonce nonceXOR;
|
||||
/// next hop's router id
|
||||
RouterID upstream;
|
||||
/// nonce for key exchange
|
||||
TunnelNonce nonce;
|
||||
SymmNonce nonce;
|
||||
// lifetime
|
||||
llarp_time_t lifetime = DEFAULT_LIFETIME;
|
||||
|
||||
|
|
|
@ -93,7 +93,9 @@ namespace llarp
|
|||
throw std::runtime_error{std::move(err)};
|
||||
}
|
||||
// generate nonceXOR value self->hop->pathKey
|
||||
crypto::shorthash(hop.nonceXOR, hop.shared.data(), hop.shared.size());
|
||||
ShortHash hash;
|
||||
crypto::shorthash(hash, hop.shared.data(), hop.shared.size());
|
||||
hop.nonceXOR = hash.data(); // nonceXOR is 24 bytes, ShortHash is 32; this will truncate
|
||||
|
||||
hop.upstream = nextHop;
|
||||
}
|
||||
|
@ -120,7 +122,7 @@ namespace llarp
|
|||
crypto::encryption_keygen(framekey);
|
||||
|
||||
SharedSecret shared;
|
||||
TunnelNonce outer_nonce;
|
||||
SymmNonce outer_nonce;
|
||||
outer_nonce.Randomize();
|
||||
|
||||
// derive (outer) shared key
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#include "pathset.hpp"
|
||||
|
||||
#include "path.hpp"
|
||||
|
||||
#include <llarp/crypto/crypto.hpp>
|
||||
|
||||
namespace llarp::path
|
||||
{
|
||||
PathSet::PathSet(size_t num) : numDesiredPaths(num)
|
||||
|
@ -441,16 +442,4 @@ namespace llarp::path
|
|||
return chosen;
|
||||
}
|
||||
|
||||
void
|
||||
PathSet::UpstreamFlush(Router* r)
|
||||
{
|
||||
ForEachPath([r](const Path_ptr& p) { p->FlushUpstream(r); });
|
||||
}
|
||||
|
||||
void
|
||||
PathSet::DownstreamFlush(Router* r)
|
||||
{
|
||||
ForEachPath([r](const Path_ptr& p) { p->FlushDownstream(r); });
|
||||
}
|
||||
|
||||
} // namespace llarp::path
|
||||
|
|
|
@ -14,17 +14,11 @@ namespace llarp::path
|
|||
|
||||
TransitHop::TransitHop()
|
||||
: AbstractHopHandler{}
|
||||
, m_UpstreamGather{TRANSIT_HOP_QUEUE_SIZE}
|
||||
, m_DownstreamGather{TRANSIT_HOP_QUEUE_SIZE}
|
||||
{
|
||||
m_UpstreamGather.enable();
|
||||
m_DownstreamGather.enable();
|
||||
m_UpstreamWorkCounter = 0;
|
||||
m_DownstreamWorkCounter = 0;
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::onion(ustring& data, TunnelNonce& nonce, bool randomize) const
|
||||
TransitHop::onion(ustring& data, SymmNonce& nonce, bool randomize) const
|
||||
{
|
||||
if (randomize)
|
||||
nonce.Randomize();
|
||||
|
@ -32,7 +26,7 @@ namespace llarp::path
|
|||
}
|
||||
|
||||
void
|
||||
TransitHop::onion(std::string& data, TunnelNonce& nonce, bool randomize) const
|
||||
TransitHop::onion(std::string& data, SymmNonce& nonce, bool randomize) const
|
||||
{
|
||||
if (randomize)
|
||||
nonce.Randomize();
|
||||
|
@ -42,9 +36,9 @@ namespace llarp::path
|
|||
|
||||
std::string
|
||||
TransitHop::onion_and_payload(
|
||||
std::string& payload, PathID_t next_id, std::optional<TunnelNonce> nonce) const
|
||||
std::string& payload, PathID_t next_id, std::optional<SymmNonce> nonce) const
|
||||
{
|
||||
TunnelNonce n;
|
||||
SymmNonce n;
|
||||
auto& nref = nonce ? *nonce : n;
|
||||
onion(payload, nref, not nonce);
|
||||
|
||||
|
@ -88,6 +82,7 @@ namespace llarp::path
|
|||
functions it calls and so on) will need to be modified to take an std::string that we can
|
||||
std::move around.
|
||||
*/
|
||||
/* TODO: replace this with layer of onion + send data message
|
||||
bool
|
||||
TransitHop::SendRoutingMessage(std::string payload, Router* r)
|
||||
{
|
||||
|
@ -110,157 +105,7 @@ namespace llarp::path
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::DownstreamWork(TrafficQueue_t msgs, Router* r)
|
||||
{
|
||||
auto flushIt = [self = shared_from_this(), r]() {
|
||||
std::vector<RelayDownstreamMessage> msgs;
|
||||
while (auto maybe = self->m_DownstreamGather.tryPopFront())
|
||||
{
|
||||
msgs.push_back(*maybe);
|
||||
}
|
||||
self->HandleAllDownstream(std::move(msgs), r);
|
||||
};
|
||||
for (auto& ev : msgs)
|
||||
{
|
||||
RelayDownstreamMessage msg;
|
||||
|
||||
// const llarp_buffer_t buf(ev.first);
|
||||
uint8_t* buf = ev.first.data();
|
||||
size_t sz = ev.first.size();
|
||||
|
||||
msg.pathid = info.rxID;
|
||||
msg.nonce = ev.second ^ nonceXOR;
|
||||
|
||||
crypto::xchacha20(buf, sz, pathKey, ev.second);
|
||||
std::memcpy(msg.enc.data(), buf, sz);
|
||||
|
||||
llarp::LogDebug(
|
||||
"relay ",
|
||||
msg.enc.size(),
|
||||
" bytes downstream from ",
|
||||
info.upstream,
|
||||
" to ",
|
||||
info.downstream);
|
||||
if (m_DownstreamGather.full())
|
||||
{
|
||||
r->loop()->call(flushIt);
|
||||
}
|
||||
if (m_DownstreamGather.enabled())
|
||||
m_DownstreamGather.pushBack(msg);
|
||||
}
|
||||
r->loop()->call(flushIt);
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::UpstreamWork(TrafficQueue_t msgs, Router* r)
|
||||
{
|
||||
for (auto& ev : msgs)
|
||||
{
|
||||
RelayUpstreamMessage msg;
|
||||
|
||||
uint8_t* buf = ev.first.data();
|
||||
size_t sz = ev.first.size();
|
||||
|
||||
crypto::xchacha20(buf, sz, pathKey, ev.second);
|
||||
|
||||
msg.pathid = info.txID;
|
||||
msg.nonce = ev.second ^ nonceXOR;
|
||||
std::memcpy(msg.enc.data(), buf, sz);
|
||||
|
||||
if (m_UpstreamGather.tryPushBack(msg) != thread::QueueReturn::Success)
|
||||
break;
|
||||
}
|
||||
|
||||
// Flush it:
|
||||
r->loop()->call([self = shared_from_this(), r] {
|
||||
std::vector<RelayUpstreamMessage> msgs;
|
||||
while (auto maybe = self->m_UpstreamGather.tryPopFront())
|
||||
{
|
||||
msgs.push_back(*maybe);
|
||||
}
|
||||
self->HandleAllUpstream(std::move(msgs), r);
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::HandleAllUpstream(std::vector<RelayUpstreamMessage> msgs, Router* r)
|
||||
{
|
||||
if (IsEndpoint(r->pubkey()))
|
||||
{
|
||||
for (const auto& msg : msgs)
|
||||
{
|
||||
const llarp_buffer_t buf(msg.enc);
|
||||
if (!r->ParseRoutingMessageBuffer(buf, *this, info.rxID))
|
||||
{
|
||||
LogWarn("invalid upstream data on endpoint ", info);
|
||||
}
|
||||
m_LastActivity = r->now();
|
||||
}
|
||||
FlushDownstream(r);
|
||||
for (const auto& other : m_FlushOthers)
|
||||
{
|
||||
other->FlushDownstream(r);
|
||||
}
|
||||
m_FlushOthers.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& msg : msgs)
|
||||
{
|
||||
llarp::LogDebug(
|
||||
"relay ",
|
||||
msg.enc.size(),
|
||||
" bytes upstream from ",
|
||||
info.downstream,
|
||||
" to ",
|
||||
info.upstream);
|
||||
r->send_data_message(info.upstream, msg.bt_encode());
|
||||
}
|
||||
}
|
||||
r->TriggerPump();
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::HandleAllDownstream(std::vector<RelayDownstreamMessage> msgs, Router* r)
|
||||
{
|
||||
for (const auto& msg : msgs)
|
||||
{
|
||||
log::debug(
|
||||
path_cat,
|
||||
"Relaying {} bytes downstream from {} to {}",
|
||||
msg.enc.size(),
|
||||
info.upstream,
|
||||
info.downstream);
|
||||
// TODO: is this right?
|
||||
r->send_data_message(info.downstream, msg.bt_encode());
|
||||
}
|
||||
|
||||
r->TriggerPump();
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::FlushUpstream(Router* r)
|
||||
{
|
||||
if (not m_UpstreamQueue.empty())
|
||||
{
|
||||
r->queue_work([self = shared_from_this(),
|
||||
data = std::exchange(m_UpstreamQueue, {}),
|
||||
r]() mutable { self->UpstreamWork(std::move(data), r); });
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TransitHop::FlushDownstream(Router* r)
|
||||
{
|
||||
if (not m_DownstreamQueue.empty())
|
||||
{
|
||||
r->queue_work([self = shared_from_this(),
|
||||
data = std::exchange(m_DownstreamQueue, {}),
|
||||
r]() mutable { self->DownstreamWork(std::move(data), r); });
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
std::string
|
||||
TransitHop::ToString() const
|
||||
|
@ -272,8 +117,7 @@ namespace llarp::path
|
|||
void
|
||||
TransitHop::Stop()
|
||||
{
|
||||
m_UpstreamGather.disable();
|
||||
m_DownstreamGather.disable();
|
||||
// TODO: still need this concept?
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace llarp
|
|||
|
||||
TransitHopInfo info;
|
||||
SharedSecret pathKey;
|
||||
ShortHash nonceXOR;
|
||||
SymmNonce nonceXOR;
|
||||
llarp_time_t started = 0s;
|
||||
// 10 minutes default
|
||||
llarp_time_t lifetime = DEFAULT_LIFETIME;
|
||||
|
@ -68,16 +68,16 @@ namespace llarp
|
|||
// Does xchacha20 on `data` in-place with `nonce` and `pathKey`, then
|
||||
// mutates `nonce` = `nonce` ^ `nonceXOR` in-place.
|
||||
void
|
||||
onion(ustring& data, TunnelNonce& nonce, bool randomize = false) const;
|
||||
onion(ustring& data, SymmNonce& nonce, bool randomize = false) const;
|
||||
|
||||
void
|
||||
onion(std::string& data, TunnelNonce& nonce, bool randomize = false) const;
|
||||
onion(std::string& data, SymmNonce& nonce, bool randomize = false) const;
|
||||
|
||||
std::string
|
||||
onion_and_payload(
|
||||
std::string& payload,
|
||||
PathID_t next_id,
|
||||
std::optional<TunnelNonce> nonce = std::nullopt) const;
|
||||
std::optional<SymmNonce> nonce = std::nullopt) const;
|
||||
|
||||
PathID_t
|
||||
RXID() const override
|
||||
|
@ -142,41 +142,12 @@ namespace llarp
|
|||
std::string body,
|
||||
std::function<void(std::string)> func) override;
|
||||
|
||||
// send routing message when end of path
|
||||
bool
|
||||
SendRoutingMessage(std::string payload, Router* r) override;
|
||||
|
||||
void
|
||||
FlushUpstream(Router* r) override;
|
||||
|
||||
void
|
||||
FlushDownstream(Router* r) override;
|
||||
|
||||
void
|
||||
QueueDestroySelf(Router* r);
|
||||
|
||||
protected:
|
||||
void
|
||||
UpstreamWork(TrafficQueue_t queue, Router* r) override;
|
||||
|
||||
void
|
||||
DownstreamWork(TrafficQueue_t queue, Router* r) override;
|
||||
|
||||
void
|
||||
HandleAllUpstream(std::vector<RelayUpstreamMessage> msgs, Router* r) override;
|
||||
|
||||
void
|
||||
HandleAllDownstream(std::vector<RelayDownstreamMessage> msgs, Router* r) override;
|
||||
|
||||
private:
|
||||
void
|
||||
SetSelfDestruct();
|
||||
|
||||
std::set<std::shared_ptr<TransitHop>, ComparePtr<std::shared_ptr<TransitHop>>> m_FlushOthers;
|
||||
thread::Queue<RelayUpstreamMessage> m_UpstreamGather;
|
||||
thread::Queue<RelayDownstreamMessage> m_DownstreamGather;
|
||||
std::atomic<uint32_t> m_UpstreamWorkCounter;
|
||||
std::atomic<uint32_t> m_DownstreamWorkCounter;
|
||||
};
|
||||
} // namespace path
|
||||
|
||||
|
|
|
@ -43,6 +43,9 @@ namespace llarp::service
|
|||
AsyncKeyExchange::Encrypt(
|
||||
std::shared_ptr<AsyncKeyExchange> self, std::shared_ptr<ProtocolFrameMessage> frame)
|
||||
{
|
||||
(void)self;
|
||||
(void)frame;
|
||||
/* TODO: client<->client session ("conversation"/"convo") key exchange
|
||||
// derive ntru session key component
|
||||
SharedSecret secret;
|
||||
crypto::pqe_encrypt(frame->cipher, secret, self->introPubKey);
|
||||
|
@ -73,5 +76,6 @@ namespace llarp::service
|
|||
{
|
||||
LogError("failed to encrypt and sign");
|
||||
}
|
||||
*/
|
||||
}
|
||||
} // namespace llarp::service
|
||||
|
|
|
@ -1472,7 +1472,7 @@ namespace llarp::service
|
|||
queue.pop();
|
||||
}
|
||||
|
||||
auto r = router();
|
||||
// auto r = router();
|
||||
|
||||
// TODO: locking on this container
|
||||
// for (const auto& [addr, outctx] : _state->remote_sessions)
|
||||
|
@ -1492,8 +1492,6 @@ namespace llarp::service
|
|||
// if (item.second->SendRoutingMessage(*item.first, r))
|
||||
// ConvoTagTX(item.first->protocol_frame_msg.convo_tag);
|
||||
// }
|
||||
|
||||
UpstreamFlush(r);
|
||||
}
|
||||
|
||||
std::optional<ConvoTag>
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace llarp::service
|
|||
return std::nullopt;
|
||||
|
||||
IntroSet i{other_i};
|
||||
encrypted.nounce.Randomize();
|
||||
encrypted.nonce.Randomize();
|
||||
// set timestamp
|
||||
// TODO: round to nearest 1000 ms
|
||||
i.time_signed = now;
|
||||
|
@ -180,7 +180,7 @@ namespace llarp::service
|
|||
auto bte = i.bt_encode();
|
||||
|
||||
const SharedSecret k{i.address_keys.Addr()};
|
||||
crypto::xchacha20(reinterpret_cast<uint8_t*>(bte.data()), bte.size(), k, encrypted.nounce);
|
||||
crypto::xchacha20(reinterpret_cast<uint8_t*>(bte.data()), bte.size(), k, encrypted.nonce);
|
||||
|
||||
std::memcpy(encrypted.introsetPayload.data(), bte.data(), bte.size());
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace llarp::service
|
|||
std::string s)
|
||||
: signedAt{signed_at}
|
||||
, introsetPayload{reinterpret_cast<uint8_t*>(enc_payload.data()), enc_payload.size()}
|
||||
, nounce{reinterpret_cast<uint8_t*>(nonce.data())}
|
||||
, nonce{reinterpret_cast<uint8_t*>(nonce.data())}
|
||||
{
|
||||
derivedSigningKey = PubKey::from_string(signing_key);
|
||||
sig.from_string(std::move(s));
|
||||
|
@ -27,7 +27,7 @@ namespace llarp::service
|
|||
oxenc::bt_dict_consumer btdc{bt_payload};
|
||||
|
||||
derivedSigningKey = PubKey::from_string(btdc.require<std::string>("d"));
|
||||
nounce.from_string(btdc.require<std::string>("n"));
|
||||
nonce.from_string(btdc.require<std::string>("n"));
|
||||
signedAt = std::chrono::milliseconds{btdc.require<uint64_t>("s")};
|
||||
introsetPayload = btdc.require<ustring>("x");
|
||||
sig.from_string(btdc.require<std::string>("z"));
|
||||
|
@ -54,7 +54,7 @@ namespace llarp::service
|
|||
try
|
||||
{
|
||||
btdp.append("d", derivedSigningKey.ToView());
|
||||
btdp.append("n", nounce.ToView());
|
||||
btdp.append("n", nonce.ToView());
|
||||
btdp.append("s", signedAt.count());
|
||||
btdp.append(
|
||||
"x",
|
||||
|
@ -88,7 +88,7 @@ namespace llarp::service
|
|||
if (not BEncodeMaybeReadDictEntry("d", derivedSigningKey, read, key, buf))
|
||||
return false;
|
||||
|
||||
if (not BEncodeMaybeReadDictEntry("n", nounce, read, key, buf))
|
||||
if (not BEncodeMaybeReadDictEntry("n", nonce, read, key, buf))
|
||||
return false;
|
||||
|
||||
if (not BEncodeMaybeReadDictInt("s", signedAt, read, key, buf))
|
||||
|
@ -111,7 +111,7 @@ namespace llarp::service
|
|||
return fmt::format(
|
||||
"[EncIntroSet d={} n={} s={} x=[{} bytes] z={}]",
|
||||
derivedSigningKey,
|
||||
nounce,
|
||||
nonce,
|
||||
signedAt.count(),
|
||||
introsetPayload.size(),
|
||||
sig);
|
||||
|
@ -124,7 +124,7 @@ namespace llarp::service
|
|||
std::string payload{
|
||||
reinterpret_cast<const char*>(introsetPayload.data()), introsetPayload.size()};
|
||||
|
||||
crypto::xchacha20(reinterpret_cast<uint8_t*>(payload.data()), payload.size(), k, nounce);
|
||||
crypto::xchacha20(reinterpret_cast<uint8_t*>(payload.data()), payload.size(), k, nonce);
|
||||
|
||||
return IntroSet{payload};
|
||||
}
|
||||
|
|
|
@ -138,7 +138,7 @@ namespace llarp::service
|
|||
PubKey derivedSigningKey;
|
||||
llarp_time_t signedAt = 0s;
|
||||
ustring introsetPayload;
|
||||
TunnelNonce nounce;
|
||||
SymmNonce nonce;
|
||||
std::optional<Tag> topic;
|
||||
Signature sig;
|
||||
|
||||
|
@ -203,8 +203,8 @@ namespace llarp::service
|
|||
inline bool
|
||||
operator==(const EncryptedIntroSet& lhs, const EncryptedIntroSet& rhs)
|
||||
{
|
||||
return std::tie(lhs.signedAt, lhs.derivedSigningKey, lhs.nounce, lhs.sig)
|
||||
== std::tie(rhs.signedAt, rhs.derivedSigningKey, rhs.nounce, rhs.sig);
|
||||
return std::tie(lhs.signedAt, lhs.derivedSigningKey, lhs.nonce, lhs.sig)
|
||||
== std::tie(rhs.signedAt, rhs.derivedSigningKey, rhs.nonce, rhs.sig);
|
||||
}
|
||||
|
||||
inline bool
|
||||
|
|
|
@ -302,8 +302,7 @@ namespace llarp::service
|
|||
|
||||
// PKE (A, B, N)
|
||||
SharedSecret shared_secret;
|
||||
if (!self->m_LocalIdentity.KeyExchange(
|
||||
crypto::dh_server, shared_secret, self->msg->sender, self->frame.nonce))
|
||||
if (!crypto::dh_server(shared_secret, self->msg->sender.EncryptionPublicKey(), self->m_LocalIdentity.enckey, self->frame.nonce))
|
||||
{
|
||||
LogError("x25519 key exchange failed");
|
||||
Dump<MAX_PROTOCOL_MESSAGE_SIZE>(self->frame);
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace llarp
|
|||
PQCipherBlock cipher;
|
||||
Encrypted<2048> enc;
|
||||
uint64_t flag; // set to indicate in plaintext a nack, aka "dont try again"
|
||||
KeyExchangeNonce nonce;
|
||||
SymmNonce nonce;
|
||||
Signature sig;
|
||||
PathID_t path_id;
|
||||
service::ConvoTag convo_tag;
|
||||
|
|
Loading…
Reference in a new issue