commit day's work

pull/209/head
Jeff Becker 5 years ago
parent 2474cf343e
commit f9d30b9b96
No known key found for this signature in database
GPG Key ID: F357B3B42F6F9B05

@ -519,6 +519,7 @@ set(LIB_SRC
llarp/ip.cpp
llarp/iwp.cpp
llarp/link/curvecp.cpp
llarp/link/dtls.cpp
llarp/link/encoder.cpp
llarp/link/server.cpp
llarp/link/session.cpp

@ -1,5 +1,6 @@
#include <crypto.hpp>
#include <fstream>
#include <iterator>
#include <buffer.hpp>
namespace llarp

@ -89,6 +89,12 @@ namespace llarp
struct SecretKey final : public AlignedBuffer< SECKEYSIZE >
{
SecretKey() : AlignedBuffer< SECKEYSIZE >(){};
explicit SecretKey(const byte_t *ptr) : AlignedBuffer< SECKEYSIZE >(ptr)
{
}
friend std::ostream &
operator<<(std::ostream &out, const SecretKey &)
{

@ -1,5 +1,7 @@
#include <link/dtls_internal.hpp>
#include <crypto.hpp>
#include <router.hpp>
#include <endian.hpp>
namespace llarp
{
@ -13,24 +15,77 @@ namespace llarp
const int LinkLayer::CipherSuite[2] = {
MBEDTLS_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 0};
Session::Session(LinkLayer *parent) : ILinkSession()
const mbedtls_x509_crt_profile LinkLayer::X509Profile = {
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256),
MBEDTLS_X509_ID_FLAG(MBEDTLS_PK_ECDSA),
MBEDTLS_X509_ID_FLAG(MBEDTLS_ECP_DP_CURVE25519), 0};
static int
Random(void *ctx, unsigned char *buf, size_t sz)
{
static_cast< llarp::Crypto * >(ctx)->randbytes(buf, sz);
return 0;
}
static int
WriteCookie(void *ctx, unsigned char **p, unsigned char *,
const unsigned char *info, size_t ilen)
{
Session *self = static_cast< Session * >(ctx);
if(!self->crypto->hmac(*p, llarp::InitBuffer(info, ilen),
self->m_Parent->CookieSec()))
return -1;
*p += 32;
return 0;
}
static int
VerifyCookie(void *ctx, const unsigned char *cookie, size_t clen,
const unsigned char *info, size_t ilen)
{
if(clen != 32)
return -1;
Session *self = static_cast< Session * >(ctx);
ShortHash check;
if(!self->crypto->hmac(check.data(), llarp::InitBuffer(info, ilen),
self->m_Parent->CookieSec()))
return -1;
if(memcmp(check.data(), cookie, clen) == 0)
return 0;
return -1;
}
Session::Session(LinkLayer *parent) : ILinkSession(), crypto(parent->crypto)
{
m_Parent = parent;
mbedtls_ssl_config_init(&m_config);
mbedtls_ssl_conf_transport(&m_config, MBEDTLS_SSL_TRANSPORT_DATAGRAM);
m_config.p_vrfy = this;
m_config.key_cert = &m_Parent->ourKeys;
m_config.p_cookie = this;
m_config.f_cookie_write = &WriteCookie;
m_config.f_cookie_check = &VerifyCookie;
}
Session::Session(LinkLayer *parent, const llarp::Addr &from)
: Session(parent)
{
remoteAddr = from;
remoteAddr = from;
m_config.f_vrfy = &InboundVerifyCert;
byte_t buf[20] = {0};
parent->crypto->randbytes(buf, sizeof(buf));
htobe16buf(buf, from.port());
memcpy(buf + 2, from.addr6()->s6_addr, 16);
mbedtls_ssl_set_client_transport_id(&m_ctx, buf, sizeof(buf));
}
Session::Session(LinkLayer *parent, const RouterContact &rc,
const AddressInfo &ai)
: Session(parent)
{
remoteRC = rc;
remoteAddr = ai;
remoteRC = rc;
remoteAddr = ai;
m_config.f_vrfy = &OutboundVerifyCert;
}
Session::~Session()
@ -43,20 +98,122 @@ namespace llarp
void
Session::Connect()
{
m_config.ciphersuite_list[0] = LinkLayer::CipherSuite;
m_config.ciphersuite_list[1] = LinkLayer::CipherSuite;
m_config.ciphersuite_list[2] = LinkLayer::CipherSuite;
m_config.ciphersuite_list[3] = LinkLayer::CipherSuite;
mbedtls_ssl_conf_endpoint(&m_config, MBEDTLS_SSL_IS_CLIENT);
Configure();
}
void
Session::Accept()
{
mbedtls_ssl_conf_endpoint(&m_config, MBEDTLS_SSL_IS_SERVER);
Configure();
}
void
Session::Configure()
{
m_config.ciphersuite_list[0] = LinkLayer::CipherSuite;
m_config.ciphersuite_list[1] = LinkLayer::CipherSuite;
m_config.ciphersuite_list[2] = LinkLayer::CipherSuite;
m_config.ciphersuite_list[3] = LinkLayer::CipherSuite;
m_config.p_dbg = nullptr;
m_config.f_dbg = &Session::Debug;
m_config.p_rng = m_Parent->crypto;
m_config.f_rng = &Random;
const auto *conf = &m_config;
mbedtls_ssl_setup(&m_ctx, conf);
}
void
Session::Recv_ll(const void *buf, size_t sz)
{
ll_recv.emplace_back(sz);
auto &back = ll_recv.back();
memcpy(back.data(), buf, sz);
}
void
Session::PumpIO()
{
llarp_time_t now = m_Parent->Now();
if(m_ctx.state == MBEDTLS_SSL_HANDSHAKE_OVER)
{
// pump inbound acks
{
auto itr = m_Inbound.begin();
while(itr != m_Inbound.end())
{
if(!itr->second.IsExpired(now))
{
if(itr->second.IsDone())
{
m_Parent->HandleMessage(this, itr->second.msg.as_buffer());
itr = m_Inbound.erase(itr);
continue;
}
else if(itr->second.ShouldRetransmit(now))
{
itr->second.TransmitAcks(&m_ctx);
}
++itr;
}
else
itr = m_Inbound.erase(itr);
}
}
// pump outbound fragments
{
auto itr = m_Outbound.begin();
while(itr != m_Outbound.end())
{
if(itr->second.IsExpired(now) || itr->second.IsDone())
{
itr = m_Outbound.erase(itr);
continue;
}
else if(itr->second.ShouldRetransmit(now))
itr->second.TransmitUnacked(&m_ctx);
++itr;
}
}
}
else
{
/// step the handshake
int res = mbedtls_ssl_handshake_step(&m_ctx);
switch(res)
{
case MBEDTLS_ERR_SSL_WANT_READ:
case MBEDTLS_ERR_SSL_WANT_WRITE:
case MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS:
case MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS:
break;
default:
// drop send queue
ll_send.clear();
// drop recv queue
ll_recv.clear();
// reset session
mbedtls_ssl_session_reset(&m_ctx);
return;
}
}
// low level sendto
while(ll_send.size())
{
m_Parent->SendTo_LL(remoteAddr, llarp::ConstBuffer(ll_send.front()));
ll_send.pop_front();
}
}
void
Session::Debug(void *, int, const char *fname, int lineno, const char *msg)
{
llarp::_Log(llarp::eLogInfo, fname, lineno, msg);
}
LinkLayer::LinkLayer(llarp::Crypto *c, const byte_t *encryptionSecretKey,
const byte_t *identitySecretKey,
llarp::GetRCFunc getrc, llarp::LinkMessageHandler h,
@ -73,12 +230,6 @@ namespace llarp
{
}
static void
Debug(void *, int, const char *fname, int line, const char *msg)
{
llarp::_Log(eLogDebug, fname, line, msg);
}
static int
Random(void *ctx, unsigned char *buf, size_t sz)
{
@ -86,6 +237,14 @@ namespace llarp
return 0;
}
bool
LinkLayer::Start(llarp::Logic *l)
{
if(!ILinkLayer::Start(l))
return false;
return crypto->shrothash(m_CookieSec, m_IdentityKey.toBuffer());
}
void
LinkLayer::RecvFrom(const llarp::Addr &from, const void *buf, size_t sz)
{
@ -133,5 +292,23 @@ namespace llarp
}
}
std::unique_ptr< ILinkLayer >
NewServerFromRouter(llarp::Router *r)
{
return std::unique_ptr< LinkLayer >(new LinkLayer(
&r->crypto, r->encryption, r->identity,
std::bind(&llarp::Router::rc, r),
std::bind(&llarp::Router::HandleRecvLinkMessageBuffer, r,
std::placeholders::_1, std::placeholders::_2),
std::bind(&llarp::Router::OnSessionEstablished, r,
std::placeholders::_1),
std::bind(&llarp::Router::CheckRenegotiateValid, r,
std::placeholders::_1, std::placeholders::_2),
std::bind(&llarp::Router::Sign, r, std::placeholders::_1,
std::placeholders::_2),
std::bind(&llarp::Router::OnConnectTimeout, r, std::placeholders::_1),
std::bind(&llarp::Router::SessionClosed, r, std::placeholders::_1)));
}
} // namespace dtls
} // namespace llarp

@ -2,10 +2,15 @@
#define LLARP_LINK_DTLS_INTERNAL_HPP
#include <link/server.hpp>
#include <link/session.hpp>
#include <link_layer.hpp>
#include <mbedtls/ssl.h>
#include <mbedtls/ssl_internal.h>
#include <mbedtls/ecp.h>
#include <mbedtls/md.h>
#include <mbedtls/x509.h>
#include <bitset>
#include <deque>
namespace llarp
{
@ -41,7 +46,6 @@ namespace llarp
void
Close();
/// outbound start
void
Connect();
@ -59,12 +63,193 @@ namespace llarp
static int
ssl_send(void *ctx, const unsigned char *buf, size_t sz);
static void
Debug(void *ctx, int lvl, const char *fname, int lineno, const char *msg);
mbedtls_ssl_config m_config;
mbedtls_ssl_context m_ctx;
mbedtls_ssl_session m_session;
LinkLayer *m_Parent;
llarp::Crypto *const crypto;
llarp::RouterContact remoteRC;
llarp::Addr remoteAddr;
using MessageBuffer_t = llarp::AlignedBuffer< MAX_LINK_MSG_SIZE >;
using Seqno_t = uint32_t;
using Proto_t = uint8_t;
using FragLen_t = uint16_t;
using Flags_t = uint8_t;
using Fragno_t = uint8_t;
using Cmd_t = uint8_t;
static constexpr size_t fragoverhead = sizeof(Proto_t) + sizeof(Cmd_t)
+ sizeof(Flags_t) + sizeof(Fragno_t) + sizeof(FragLen_t)
+ sizeof(Seqno_t);
/// keepalive command
static constexpr Cmd_t PING = 0;
/// transmit fragment command
static constexpr Cmd_t XMIT = 1;
/// fragment ack command
static constexpr Cmd_t FACK = 2;
/// maximum number of fragments
static constexpr uint8_t maxfrags = 8;
/// maximum fragment size
static constexpr size_t fragsize = MAX_LINK_MSG_SIZE / maxfrags;
struct FragmentHeader
{
/// protocol version, always LLARP_PROTO_VERSION
Proto_t version = LLARP_PROTO_VERSION;
/// fragment command type
Cmd_t cmd = 0;
/// if cmd is XMIT this is the number of fragments this message has
/// if cmd is FACK this is the fragment bitfield of the messages acked
/// otherwise 0
Flags_t flags = 0;
/// if cmd is XMIT this is the fragment index
/// if cmd is FACK this is set to 0xff to indicate message drop
/// otherwise set to 0
/// any other cmd it is set to 0
Fragno_t fragno = 0;
/// if cmd is XMIT then this is the size of the current fragment
/// if cmd is FACK then this MUST be set to 0
FragLen_t fraglen = 0;
/// if cmd is XMIT or FACK this is the sequence number of the message
/// otherwise it's 0
Seqno_t seqno = 0;
bool
Decode(llarp_buffer_t *buf)
{
if(llarp_buffer_size_left(*buf) < fragoverhead)
return false;
version = *buf->cur;
if(version != LLARP_PROTO_VERSION)
return false;
buf->cur++;
cmd = *buf->cur;
buf->cur++;
flags = *buf->cur;
buf->cur++;
fragno = *buf->cur;
buf->cur++;
llarp_buffer_read_uint16(buf, &fraglen);
llarp_buffer_read_uint32(buf, &seqno);
return fraglen <= fragsize;
}
bool
Encode(llarp_buffer_t *buf, llarp_buffer_t body)
{
if(body.sz > fragsize)
return false;
fraglen = body.sz;
if(llarp_buffer_size_left(*buf) < (fragoverhead + fraglen))
return false;
*buf->cur = LLARP_PROTO_VERSION;
buf->cur++;
*buf->cur = cmd;
buf->cur++;
*buf->cur = flags;
buf->cur++;
*buf->cur = fragno;
buf->cur++;
llarp_buffer_put_uint16(buf, fraglen);
llarp_buffer_put_uint32(buf, seqno);
memcpy(buf->cur, body.base, fraglen);
buf->cur += fraglen;
return true;
}
};
struct MessageState
{
/// default
MessageState(){};
/// inbound
MessageState(Flags_t numfrags)
{
acks.set();
if(numfrags <= maxfrags)
{
while(numfrags)
acks.reset(maxfrags - (numfrags--));
}
else // invalid value
return;
}
/// outbound
MessageState(llarp_buffer_t buf)
{
sz = std::min(buf.sz, MAX_LINK_MSG_SIZE);
memcpy(msg.data(), buf.base, sz);
size_t idx = 0;
acks.set();
while(idx * fragsize < sz)
acks.reset(idx++);
};
/// which fragments have we got
std::bitset< maxfrags > acks;
/// the message buffer
MessageBuffer_t msg;
/// the message's size
FragLen_t sz;
/// the last activity we have had
llarp_time_t lastActiveAt;
/// return true if this message is to be removed
/// because of inactivity
bool
IsExpired(llarp_time_t now) const
{
return now > lastActiveAt && now - lastActiveAt > 2000;
}
bool
IsDone() const
{
return acks.all();
}
bool
ShouldRetransmit(llarp_time_t now) const
{
if(IsDone())
return false;
return now > lastActiveAt && now - lastActiveAt > 500;
}
int
TransmitUnacked(mbedtls_ssl_context *ctx)
{
AlignedBuffer< fragoverhead + fragsize > buf;
return mbedtls_ssl_write(ctx, buf.data(), buf.size());
}
void
TransmitAcks(mbedtls_ssl_context *ctx)
{
AlignedBuffer< fragoverhead > buf;
return mbedtls_ssl_write(ctx, buf.data(), buf.size());
}
};
using MessageHolder_t = std::unordered_map< Seqno_t, MessageState >;
MessageHolder_t m_Inbound;
MessageHolder_t m_Outbound;
using Buf_t = std::vector< byte_t >;
using IOQueue_t = std::deque< Buf_t >;
IOQueue_t ll_recv;
IOQueue_t ll_send;
};
struct LinkLayer final : public llarp::ILinkLayer
@ -83,6 +268,7 @@ namespace llarp
static const mbedtls_ecp_group_id AllowedCurve[2];
static const mbedtls_md_type_t AllowedHash[2];
static const int CipherSuite[2];
static const mbedtls_x509_crt_profile X509Profile;
bool
Start(llarp::Logic *l) override;
@ -91,19 +277,40 @@ namespace llarp
NewOutboundSession(const llarp::RouterContact &rc,
const llarp::AddressInfo &ai) override;
void
Stop() override;
void
Pump() override;
bool
KeyGen(SecretKey &k) override;
const char *
Name() const override;
uint16_t
Rank() const override;
mbedtls_ssl_key_cert ourKeys;
const byte_t *
IndentityKey() const
{
return m_IdentityKey.data();
}
const AlignedBuffer< 32 > &
CookieSec() const
{
return m_CookieSec;
}
private:
bool
SignBuffer(llarp::Signature &sig, llarp_buffer_t buf) const
{
return crypto->sign(sig, m_IdentityKey, buf);
}
const byte_t *m_IdentityKey;
const llarp::SecretKey m_IdentityKey;
AlignedBuffer< 32 > m_CookieSec;
/// handle ll recv
void

@ -87,6 +87,12 @@ namespace llarp
static_cast< ILinkLayer* >(udp->user)->RecvFrom(*from, buf.base, buf.sz);
}
void
SendTo_LL(const llarp::Addr& to, llarp_buffer_t pkt)
{
llarp_ev_udp_sendto(&m_udp, to, pkt);
}
bool
Configure(llarp_ev_loop* loop, const std::string& ifname, int af,
uint16_t port);
@ -106,7 +112,7 @@ namespace llarp
bool
TryEstablishTo(RouterContact rc);
bool
virtual bool
Start(llarp::Logic* l);
void

@ -45,8 +45,7 @@
#define UTUN_OPT_IFNAME 2
static int
fucky_tuntap_sys_start(struct device *dev, __attribute__((unused)) int mode,
int tun)
tuntap_sys_start(struct device *dev, int, int)
{
uint32_t namesz = IFNAMSIZ;
char name[IFNAMSIZ + 1];
@ -57,8 +56,6 @@ fucky_tuntap_sys_start(struct device *dev, __attribute__((unused)) int mode,
if(fd == -1)
return fd;
snprintf(name, sizeof(name), "utun%i", tun);
struct ctl_info info;
memset(&info, 0, sizeof(info));
strncpy(info.ctl_name, APPLE_UTUN, strlen(APPLE_UTUN));
@ -77,7 +74,7 @@ fucky_tuntap_sys_start(struct device *dev, __attribute__((unused)) int mode,
addr.sc_len = sizeof(addr);
addr.sc_family = AF_SYSTEM;
addr.ss_sysaddr = AF_SYS_CONTROL;
addr.sc_unit = tun + 1;
addr.sc_unit = 0;
if(connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
@ -95,24 +92,6 @@ fucky_tuntap_sys_start(struct device *dev, __attribute__((unused)) int mode,
return fd;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun)
{
int fd = -1;
while(tun < 128)
{
// yes linear complexity here
// sue me but I blame apple
fd = fucky_tuntap_sys_start(dev, mode, tun);
if(fd != -1)
{
return fd;
}
++tun;
}
return -1;
}
void
tuntap_sys_destroy(struct device *dev)
{

Loading…
Cancel
Save