Update protocol

Signed-off-by: Adrien Gallouët <adrien@gallouet.fr>
This commit is contained in:
Adrien Gallouët
2020-01-03 12:29:49 +00:00
parent e56abf5eaa
commit 6e8a3cef1e

161
mud.c
View File

@@ -62,7 +62,10 @@
#define MUD_ONE_SEC (1000 * MUD_ONE_MSEC) #define MUD_ONE_SEC (1000 * MUD_ONE_MSEC)
#define MUD_ONE_MIN (60 * MUD_ONE_SEC) #define MUD_ONE_MIN (60 * MUD_ONE_SEC)
#define MUD_U48_SIZE (6U) #define MUD_TIME_SIZE (6U)
#define MUD_TIME_BITS (MUD_TIME_SIZE * 8U)
#define MUD_TIME_MASK(X) ((X) & ((UINT64_C(1) << MUD_TIME_BITS) - 2))
#define MUD_KEY_SIZE (32U) #define MUD_KEY_SIZE (32U)
#define MUD_MAC_SIZE (16U) #define MUD_MAC_SIZE (16U)
@@ -71,19 +74,19 @@
#define MUD_MSG_SENT_MAX (5) #define MUD_MSG_SENT_MAX (5)
#define MUD_MSG_TIMEOUT (100 * MUD_ONE_MSEC) #define MUD_MSG_TIMEOUT (100 * MUD_ONE_MSEC)
#define MUD_PKT_MIN_SIZE (MUD_U48_SIZE + MUD_MAC_SIZE) #define MUD_PKT_MIN_SIZE (MUD_TIME_SIZE + MUD_MAC_SIZE)
#define MUD_PKT_MAX_SIZE (1500U) #define MUD_PKT_MAX_SIZE (1500U)
#define MUD_MTU_MIN (1280U + MUD_PKT_MIN_SIZE) #define MUD_MTU_MIN (1280U + MUD_PKT_MIN_SIZE)
#define MUD_MTU_MAX (1450U + MUD_PKT_MIN_SIZE) #define MUD_MTU_MAX (1450U + MUD_PKT_MIN_SIZE)
#define MUD_TIME_BITS (48)
#define MUD_TIME_MASK(X) ((X) & ((UINT64_C(1) << MUD_TIME_BITS) - 2))
#define MUD_CTRL_SIZE (CMSG_SPACE(MUD_PKTINFO_SIZE) + \ #define MUD_CTRL_SIZE (CMSG_SPACE(MUD_PKTINFO_SIZE) + \
CMSG_SPACE(sizeof(struct in6_pktinfo)) + \ CMSG_SPACE(sizeof(struct in6_pktinfo)) + \
CMSG_SPACE(sizeof(int))) CMSG_SPACE(sizeof(int)))
#define MUD_STORE_MSG(D,S) mud_store((D),(S),sizeof(D))
#define MUD_LOAD_MSG(S) mud_load((S),sizeof(S))
struct mud_crypto_opt { struct mud_crypto_opt {
unsigned char *dst; unsigned char *dst;
const unsigned char *src; const unsigned char *src;
@@ -110,21 +113,19 @@ struct mud_addr {
}; };
struct mud_msg { struct mud_msg {
unsigned char sent_time[MUD_U48_SIZE]; unsigned char sent_time[MUD_TIME_SIZE];
unsigned char state; unsigned char state;
struct mud_addr addr;
unsigned char pkey[MUD_PUBKEY_SIZE];
unsigned char aes; unsigned char aes;
unsigned char mtu[MUD_U48_SIZE]; unsigned char pkey[MUD_PUBKEY_SIZE];
unsigned char fwd_total[MUD_U48_SIZE]; struct {
unsigned char fwd_bytes[MUD_U48_SIZE]; unsigned char bytes[sizeof(uint64_t)];
unsigned char tx_bytes[MUD_U48_SIZE]; unsigned char total[sizeof(uint64_t)];
unsigned char tx_total[MUD_U48_SIZE]; } tx, rx, fw;
unsigned char rx_bytes[MUD_U48_SIZE]; unsigned char max_rate[sizeof(uint64_t)];
unsigned char rx_total[MUD_U48_SIZE]; unsigned char timeout[MUD_TIME_SIZE];
unsigned char tx_max_rate[MUD_U48_SIZE]; unsigned char mtu[2];
unsigned char msg_timeout[MUD_U48_SIZE];
unsigned char loss; unsigned char loss;
struct mud_addr addr;
}; };
struct mud_keyx { struct mud_keyx {
@@ -179,32 +180,32 @@ mud_encrypt_opt(const struct mud_crypto_key *k,
if (k->aes) { if (k->aes) {
unsigned char npub[AEGIS256_NPUBBYTES]; unsigned char npub[AEGIS256_NPUBBYTES];
memcpy(npub, c->dst, MUD_U48_SIZE); memcpy(npub, c->dst, MUD_TIME_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE); memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return aegis256_encrypt( return aegis256_encrypt(
c->dst + MUD_U48_SIZE, c->dst + MUD_TIME_SIZE,
NULL, NULL,
c->src, c->src,
c->size, c->size,
c->dst, c->dst,
MUD_U48_SIZE, MUD_TIME_SIZE,
npub, npub,
k->encrypt.key k->encrypt.key
); );
} else { } else {
unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES]; unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES];
memcpy(npub, c->dst, MUD_U48_SIZE); memcpy(npub, c->dst, MUD_TIME_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE); memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return crypto_aead_chacha20poly1305_encrypt( return crypto_aead_chacha20poly1305_encrypt(
c->dst + MUD_U48_SIZE, c->dst + MUD_TIME_SIZE,
NULL, NULL,
c->src, c->src,
c->size, c->size,
c->dst, c->dst,
MUD_U48_SIZE, MUD_TIME_SIZE,
NULL, NULL,
npub, npub,
k->encrypt.key k->encrypt.key
@@ -219,31 +220,31 @@ mud_decrypt_opt(const struct mud_crypto_key *k,
if (k->aes) { if (k->aes) {
unsigned char npub[AEGIS256_NPUBBYTES]; unsigned char npub[AEGIS256_NPUBBYTES];
memcpy(npub, c->src, MUD_U48_SIZE); memcpy(npub, c->src, MUD_TIME_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE); memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return aegis256_decrypt( return aegis256_decrypt(
c->dst, c->dst,
NULL, NULL,
c->src + MUD_U48_SIZE, c->src + MUD_TIME_SIZE,
c->size - MUD_U48_SIZE, c->size - MUD_TIME_SIZE,
c->src, MUD_U48_SIZE, c->src, MUD_TIME_SIZE,
npub, npub,
k->decrypt.key k->decrypt.key
); );
} else { } else {
unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES]; unsigned char npub[crypto_aead_chacha20poly1305_NPUBBYTES];
memcpy(npub, c->src, MUD_U48_SIZE); memcpy(npub, c->src, MUD_TIME_SIZE);
memset(npub + MUD_U48_SIZE, 0, sizeof(npub) - MUD_U48_SIZE); memset(npub + MUD_TIME_SIZE, 0, sizeof(npub) - MUD_TIME_SIZE);
return crypto_aead_chacha20poly1305_decrypt( return crypto_aead_chacha20poly1305_decrypt(
c->dst, c->dst,
NULL, NULL,
NULL, NULL,
c->src + MUD_U48_SIZE, c->src + MUD_TIME_SIZE,
c->size - MUD_U48_SIZE, c->size - MUD_TIME_SIZE,
c->src, MUD_U48_SIZE, c->src, MUD_TIME_SIZE,
npub, npub,
k->decrypt.key k->decrypt.key
); );
@@ -251,25 +252,42 @@ mud_decrypt_opt(const struct mud_crypto_key *k,
} }
static void static void
mud_write48(unsigned char *dst, uint64_t src) mud_store(unsigned char *dst, uint64_t src, size_t size)
{ {
dst[0] = (unsigned char)(UINT64_C(255) & (src)); #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
dst[1] = (unsigned char)(UINT64_C(255) & (src >> 8)); memcpy(dst, &src, size);
dst[2] = (unsigned char)(UINT64_C(255) & (src >> 16)); #else
dst[3] = (unsigned char)(UINT64_C(255) & (src >> 24)); dst[0] = (unsigned char)(src);
dst[4] = (unsigned char)(UINT64_C(255) & (src >> 32)); dst[1] = (unsigned char)(src >> 8);
dst[5] = (unsigned char)(UINT64_C(255) & (src >> 40)); if (size < 48) return;
dst[2] = (unsigned char)(src >> 16);
dst[3] = (unsigned char)(src >> 24);
dst[4] = (unsigned char)(src >> 32);
dst[5] = (unsigned char)(src >> 40);
if (size < 64) return;
dst[6] = (unsigned char)(src >> 48);
dst[7] = (unsigned char)(src >> 56);
#endif
} }
static uint64_t static uint64_t
mud_read48(const unsigned char *src) mud_load(const unsigned char *src, size_t size)
{ {
uint64_t ret = src[0]; uint64_t ret = 0;
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
memcpy(&ret, src, size);
#else
ret = src[0];
ret |= ((uint64_t)src[1]) << 8; ret |= ((uint64_t)src[1]) << 8;
if (size < 48) return ret;
ret |= ((uint64_t)src[2]) << 16; ret |= ((uint64_t)src[2]) << 16;
ret |= ((uint64_t)src[3]) << 24; ret |= ((uint64_t)src[3]) << 24;
ret |= ((uint64_t)src[4]) << 32; ret |= ((uint64_t)src[4]) << 32;
ret |= ((uint64_t)src[5]) << 40; ret |= ((uint64_t)src[5]) << 40;
if (size < 64) return ret;
ret |= ((uint64_t)src[6]) << 48;
ret |= ((uint64_t)src[7]) << 56;
#endif
return ret; return ret;
} }
@@ -976,7 +994,7 @@ mud_encrypt(struct mud *mud, uint64_t now,
.size = src_size, .size = src_size,
}; };
mud_write48(dst, now); mud_store(dst, now, MUD_TIME_SIZE);
if (mud->keyx.use_next) { if (mud->keyx.use_next) {
mud_encrypt_opt(&mud->keyx.next, &opt); mud_encrypt_opt(&mud->keyx.next, &opt);
@@ -1055,7 +1073,7 @@ mud_localaddr(struct sockaddr_storage *addr, struct msghdr *msg)
static int static int
mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now, mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
uint64_t sent_time, uint64_t fwd_bytes, uint64_t fwd_total, uint64_t sent_time, uint64_t fw_bytes, uint64_t fw_total,
size_t size) size_t size)
{ {
unsigned char dst[MUD_PKT_MAX_SIZE]; unsigned char dst[MUD_PKT_MAX_SIZE];
@@ -1067,8 +1085,8 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
if (size < MUD_PKT_MIN_SIZE + sizeof(struct mud_msg)) if (size < MUD_PKT_MIN_SIZE + sizeof(struct mud_msg))
size = MUD_PKT_MIN_SIZE + sizeof(struct mud_msg); size = MUD_PKT_MIN_SIZE + sizeof(struct mud_msg);
mud_write48(dst, MUD_MSG_MARK(now)); mud_store(dst, MUD_MSG_MARK(now), MUD_TIME_SIZE);
mud_write48(msg->sent_time, sent_time); MUD_STORE_MSG(msg->sent_time, sent_time);
if (path->addr.ss_family == AF_INET) { if (path->addr.ss_family == AF_INET) {
msg->addr.ff[0] = 0xFF; msg->addr.ff[0] = 0xFF;
@@ -1093,16 +1111,17 @@ mud_send_msg(struct mud *mud, struct mud_path *path, uint64_t now,
msg->aes = (unsigned char)mud->keyx.aes; msg->aes = (unsigned char)mud->keyx.aes;
if (!path->mtu.probe) if (!path->mtu.probe)
mud_write48(msg->mtu, path->mtu.ok); MUD_STORE_MSG(msg->mtu, path->mtu.ok);
MUD_STORE_MSG(msg->tx.bytes, path->tx.bytes);
MUD_STORE_MSG(msg->rx.bytes, path->rx.bytes);
MUD_STORE_MSG(msg->tx.total, path->tx.total);
MUD_STORE_MSG(msg->rx.total, path->rx.total);
MUD_STORE_MSG(msg->fw.bytes, fw_bytes);
MUD_STORE_MSG(msg->fw.total, fw_total);
MUD_STORE_MSG(msg->max_rate, path->conf.rx_max_rate);
MUD_STORE_MSG(msg->timeout, path->conf.msg_timeout);
mud_write48(msg->tx_bytes, path->tx.bytes);
mud_write48(msg->rx_bytes, path->rx.bytes);
mud_write48(msg->tx_total, path->tx.total);
mud_write48(msg->rx_total, path->rx.total);
mud_write48(msg->fwd_bytes, fwd_bytes);
mud_write48(msg->fwd_total, fwd_total);
mud_write48(msg->tx_max_rate, path->conf.rx_max_rate);
mud_write48(msg->msg_timeout, path->conf.msg_timeout);
msg->loss = (unsigned char)path->tx.loss; msg->loss = (unsigned char)path->tx.loss;
const struct mud_crypto_opt opt = { const struct mud_crypto_opt opt = {
@@ -1231,15 +1250,15 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
mud_ss_from_packet(&path->r_addr, msg); mud_ss_from_packet(&path->r_addr, msg);
const uint64_t tx_time = mud_read48(msg->sent_time); const uint64_t tx_time = MUD_LOAD_MSG(msg->sent_time);
if (tx_time) { if (tx_time) {
mud_update_stat(&path->rtt, MUD_TIME_MASK(now - tx_time)); mud_update_stat(&path->rtt, MUD_TIME_MASK(now - tx_time));
const uint64_t tx_bytes = mud_read48(msg->fwd_bytes); const uint64_t tx_bytes = MUD_LOAD_MSG(msg->fw.bytes);
const uint64_t tx_total = mud_read48(msg->fwd_total); const uint64_t tx_total = MUD_LOAD_MSG(msg->fw.total);
const uint64_t rx_bytes = mud_read48(msg->rx_bytes); const uint64_t rx_bytes = MUD_LOAD_MSG(msg->rx.bytes);
const uint64_t rx_total = mud_read48(msg->rx_total); const uint64_t rx_total = MUD_LOAD_MSG(msg->rx.total);
const uint64_t rx_time = sent_time; const uint64_t rx_time = sent_time;
if ((tx_time > path->msg.tx.time) && (tx_bytes > path->msg.tx.bytes) && if ((tx_time > path->msg.tx.time) && (tx_bytes > path->msg.tx.bytes) &&
@@ -1272,14 +1291,14 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
} }
} else { } else {
path->state = (enum mud_state)msg->state; path->state = (enum mud_state)msg->state;
path->mtu.ok = mud_read48(msg->mtu); path->mtu.ok = MUD_LOAD_MSG(msg->mtu);
path->conf.msg_timeout = mud_read48(msg->msg_timeout); path->conf.msg_timeout = MUD_LOAD_MSG(msg->timeout);
const uint64_t tx_max_rate = mud_read48(msg->tx_max_rate); const uint64_t max_rate = MUD_LOAD_MSG(msg->max_rate);
if (path->conf.tx_max_rate != tx_max_rate) { if (path->conf.tx_max_rate != max_rate) {
path->conf.tx_max_rate = tx_max_rate; path->conf.tx_max_rate = max_rate;
path->tx.rate = tx_max_rate; path->tx.rate = max_rate;
} }
path->msg.sent++; path->msg.sent++;
@@ -1300,8 +1319,8 @@ mud_recv_msg(struct mud *mud, struct mud_path *path,
} }
mud_send_msg(mud, path, now, sent_time, mud_send_msg(mud, path, now, sent_time,
mud_read48(msg->tx_bytes), MUD_LOAD_MSG(msg->tx.bytes),
mud_read48(msg->tx_total), MUD_LOAD_MSG(msg->tx.total),
size); size);
} }
@@ -1334,7 +1353,7 @@ mud_recv(struct mud *mud, void *data, size_t size)
return 0; return 0;
const uint64_t now = mud_now(mud); const uint64_t now = mud_now(mud);
const uint64_t sent_time = mud_read48(packet); const uint64_t sent_time = mud_load(packet, MUD_TIME_SIZE);
mud_unmapv4(&addr); mud_unmapv4(&addr);