Use private key for internal packets

This commit is contained in:
Adrien Gallouët
2016-07-19 07:03:02 +00:00
parent df67357d36
commit c1b13488af

166
mud.c
View File

@@ -40,31 +40,30 @@
#define MUD_ONE_MIN (60*MUD_ONE_SEC) #define MUD_ONE_MIN (60*MUD_ONE_SEC)
#define MUD_TIME_SIZE (6U) #define MUD_TIME_SIZE (6U)
#define MUD_AD_SIZE (16U)
#define MUD_KEY_SIZE (32U) #define MUD_KEY_SIZE (32U)
#define MUD_NPUB_SIZE (MUD_TIME_SIZE) #define MUD_PACKET_MIN_SIZE (MUD_TIME_SIZE+16U)
#define MUD_NPUB_BUF_SIZE (16U) #define MUD_PACKET_MAX_SIZE (1500U)
#define MUD_PACKET_MASK (0x3FFU)
#define MUD_PACKET_COUNT ((MUD_PACKET_MASK)+1)
#define MUD_PACKET_NEXT(X) (((X)+1)&(MUD_PACKET_MASK))
#define MUD_PACKET_SIZEOF(X) ((X)+MUD_PACKET_MIN_SIZE)
#define MUD_PACKET_MIN_SIZE (MUD_NPUB_SIZE+MUD_AD_SIZE) #define MUD_PONG_SIZE MUD_PACKET_SIZEOF(MUD_TIME_SIZE*3)
#define MUD_PKEY_SIZE (crypto_scalarmult_BYTES+1)
#define MUD_PONG_DATA_SIZE (MUD_TIME_SIZE*3) #define MUD_KEYX_SIZE MUD_PACKET_SIZEOF(MUD_TIME_SIZE+2*MUD_PKEY_SIZE)
#define MUD_PONG_SIZE (MUD_PONG_DATA_SIZE+MUD_PACKET_MIN_SIZE)
#define MUD_KEYX_PUB_SIZE (crypto_scalarmult_BYTES+1)
#define MUD_KEYX_DATA_SIZE (MUD_TIME_SIZE+2*MUD_KEYX_PUB_SIZE)
#define MUD_KEYX_SIZE (MUD_KEYX_DATA_SIZE+MUD_PACKET_MIN_SIZE)
#define MUD_PING_TIMEOUT (100*MUD_ONE_MSEC)
#define MUD_PONG_TIMEOUT (100*MUD_ONE_MSEC) #define MUD_PONG_TIMEOUT (100*MUD_ONE_MSEC)
#define MUD_KEYX_TIMEOUT (60*MUD_ONE_MIN) #define MUD_KEYX_TIMEOUT (60*MUD_ONE_MIN)
#define MUD_SEND_TIMEOUT (10*MUD_ONE_SEC) #define MUD_SEND_TIMEOUT (10*MUD_ONE_SEC)
#define MUD_PING_TIMEOUT (100*MUD_ONE_MSEC)
#define MUD_TIME_TOLERANCE (10*MUD_ONE_MIN) #define MUD_TIME_TOLERANCE (10*MUD_ONE_MIN)
#define MUD_PACKET_MAX_SIZE (1500U) enum mud_msg {
#define MUD_PACKET_MASK (0x3FFU) mud_ping,
#define MUD_PACKET_COUNT ((MUD_PACKET_MASK)+1) mud_pong,
#define MUD_PACKET_NEXT(X) (((X)+1)&(MUD_PACKET_MASK)) mud_keyx,
};
struct ipaddr { struct ipaddr {
int family; int family;
@@ -112,8 +111,8 @@ struct queue {
}; };
struct public { struct public {
unsigned char send[MUD_KEYX_PUB_SIZE]; unsigned char send[MUD_PKEY_SIZE];
unsigned char recv[MUD_KEYX_PUB_SIZE]; unsigned char recv[MUD_PKEY_SIZE];
}; };
struct crypto_opt { struct crypto_opt {
@@ -122,7 +121,7 @@ struct crypto_opt {
const unsigned char *data; const unsigned char *data;
size_t size; size_t size;
} src, ad; } src, ad;
unsigned char npub[MUD_NPUB_BUF_SIZE]; unsigned char npub[16];
}; };
struct crypto_key { struct crypto_key {
@@ -624,7 +623,7 @@ void mud_keyx_init (struct mud *mud)
randombytes_buf(mud->crypto.secret, sizeof(mud->crypto.secret)); randombytes_buf(mud->crypto.secret, sizeof(mud->crypto.secret));
crypto_scalarmult_base(mud->crypto.public.send, mud->crypto.secret); crypto_scalarmult_base(mud->crypto.public.send, mud->crypto.secret);
memset(mud->crypto.public.recv, 0, sizeof(mud->crypto.public.recv)); memset(mud->crypto.public.recv, 0, sizeof(mud->crypto.public.recv));
mud->crypto.public.send[MUD_KEYX_PUB_SIZE-1] = mud->crypto.aes; mud->crypto.public.send[MUD_PKEY_SIZE-1] = mud->crypto.aes;
} }
struct mud *mud_create (int port, int v4, int v6, int aes) struct mud *mud_create (int port, int v4, int v6, int aes)
@@ -707,20 +706,24 @@ int mud_encrypt (struct mud *mud, uint64_t nonce,
return 0; return 0;
struct crypto_opt opt = { struct crypto_opt opt = {
.dst = dst+ad_size+MUD_NPUB_SIZE, .dst = dst+ad_size+MUD_TIME_SIZE,
.src = { .data = src+ad_size, .src = { .data = src+ad_size,
.size = src_size-ad_size }, .size = src_size-ad_size },
.ad = { .data = dst, .ad = { .data = dst,
.size = ad_size+MUD_NPUB_SIZE }, .size = ad_size+MUD_TIME_SIZE },
}; };
mud_write48(opt.npub, nonce); mud_write48(opt.npub, nonce);
memcpy(dst, opt.npub, MUD_NPUB_SIZE); memcpy(dst, opt.npub, MUD_TIME_SIZE);
if (src) if (src)
memcpy(dst+MUD_NPUB_SIZE, src, ad_size); memcpy(dst+MUD_TIME_SIZE, src, ad_size);
mud_encrypt_opt(&mud->crypto.current, &opt); if (nonce) {
mud_encrypt_opt(&mud->crypto.current, &opt);
} else {
mud_encrypt_opt(&mud->crypto.private, &opt);
}
return size; return size;
} }
@@ -741,14 +744,14 @@ int mud_decrypt (struct mud *mud,
struct crypto_opt opt = { struct crypto_opt opt = {
.dst = dst+ad_size, .dst = dst+ad_size,
.src = { .data = src+ad_size+MUD_NPUB_SIZE, .src = { .data = src+ad_size+MUD_TIME_SIZE,
.size = src_size-ad_size-MUD_NPUB_SIZE }, .size = src_size-ad_size-MUD_TIME_SIZE },
.ad = { .data = src, .ad = { .data = src,
.size = ad_size+MUD_NPUB_SIZE }, .size = ad_size+MUD_TIME_SIZE },
}; };
memcpy(opt.npub, src, MUD_NPUB_SIZE); memcpy(opt.npub, src, MUD_TIME_SIZE);
memcpy(dst, src+MUD_NPUB_SIZE, ad_size); memcpy(dst, src+MUD_TIME_SIZE, ad_size);
if (mud_decrypt_opt(&mud->crypto.current, &opt) && if (mud_decrypt_opt(&mud->crypto.current, &opt) &&
mud_decrypt_opt(&mud->crypto.last, &opt) && mud_decrypt_opt(&mud->crypto.last, &opt) &&
@@ -818,64 +821,33 @@ int mud_localaddr (struct ipaddr *local_addr, struct msghdr *msg, int family)
} }
static static
void mud_ping_path (struct mud *mud, struct path *path, uint64_t now) void mud_ctrl_path (struct mud *mud, enum mud_msg msg, struct path *path,
uint64_t now)
{ {
if (now-path->ping_time < MUD_PING_TIMEOUT) unsigned char data[256];
return; unsigned char ctrl[sizeof(data)+MUD_PACKET_MIN_SIZE];
size_t size = MUD_TIME_SIZE;
unsigned char ping[MUD_PACKET_MIN_SIZE];
int ret = mud_encrypt(mud, now, ping, sizeof(ping), NULL, 0, 0);
if (ret <= 0)
return;
mud_send_path(mud, path, now, ping, ret);
path->ping_time = now;
}
static
void mud_pong_path (struct mud *mud, struct path *path, uint64_t now)
{
if (now-path->pong_time < MUD_PONG_TIMEOUT)
return;
unsigned char pong[MUD_PONG_SIZE];
unsigned char data[MUD_PONG_DATA_SIZE];
mud_write48(data, now);
mud_write48(&data[MUD_TIME_SIZE], path->recv_send_time);
mud_write48(&data[MUD_TIME_SIZE*2], path->rdt);
int ret = mud_encrypt(mud, 0, pong, sizeof(pong),
data, sizeof(data), sizeof(data));
if (ret <= 0)
return;
mud_send_path(mud, path, now, pong, ret);
path->pong_time = now;
}
static
void mud_keyx_path (struct mud *mud, struct path *path, uint64_t now)
{
unsigned char keyx[MUD_KEYX_SIZE];
unsigned char data[MUD_KEYX_DATA_SIZE];
mud_write48(data, now); mud_write48(data, now);
memcpy(&data[MUD_TIME_SIZE], &mud->crypto.public, if (msg == mud_pong) {
sizeof(mud->crypto.public)); mud_write48(&data[MUD_TIME_SIZE], path->recv_send_time);
mud_write48(&data[MUD_TIME_SIZE*2], path->rdt);
size += MUD_TIME_SIZE*2;
}
int ret = mud_encrypt(mud, 0, keyx, sizeof(keyx), if (msg == mud_keyx) {
data, sizeof(data), sizeof(data)); memcpy(&data[MUD_TIME_SIZE], &mud->crypto.public,
sizeof(mud->crypto.public));
size += sizeof(mud->crypto.public);
}
int ret = mud_encrypt(mud, 0, ctrl, sizeof(ctrl), data, size, size);
if (ret <= 0) if (ret <= 0)
return; return;
mud_send_path(mud, path, now, keyx, ret); mud_send_path(mud, path, now, ctrl, ret);
mud->crypto.time = now;
} }
static static
@@ -899,7 +871,7 @@ void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now,
sizeof(shared_recv.public))) { sizeof(shared_recv.public))) {
memcpy(mud->crypto.public.recv, shared_recv.public.send, memcpy(mud->crypto.public.recv, shared_recv.public.send,
sizeof(mud->crypto.public.recv)); sizeof(mud->crypto.public.recv));
mud_keyx_path(mud, path, now); mud_ctrl_path(mud, mud_keyx, path, now);
if (!path->state.active) if (!path->state.active)
return; return;
} }
@@ -928,8 +900,8 @@ void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now,
crypto_aead_aes256gcm_beforenm(&mud->crypto.current.decrypt.state, crypto_aead_aes256gcm_beforenm(&mud->crypto.current.decrypt.state,
mud->crypto.current.decrypt.key); mud->crypto.current.decrypt.key);
if ((shared_recv.public.send[MUD_KEYX_PUB_SIZE-1] == 1) && if ((shared_recv.public.send[MUD_PKEY_SIZE-1] == 1) &&
(shared_recv.public.recv[MUD_KEYX_PUB_SIZE-1] == 1)) { (shared_recv.public.recv[MUD_PKEY_SIZE-1] == 1)) {
mud->crypto.current.aes = 1; mud->crypto.current.aes = 1;
} else { } else {
mud->crypto.current.aes = 0; mud->crypto.current.aes = 0;
@@ -968,7 +940,7 @@ int mud_pull (struct mud *mud)
ssize_t ret = recvmsg(mud->fd, &msg, 0); ssize_t ret = recvmsg(mud->fd, &msg, 0);
if (ret < (ssize_t)MUD_PACKET_MIN_SIZE) { if (ret <= (ssize_t)MUD_PACKET_MIN_SIZE) {
if (ret <= (ssize_t)0) if (ret <= (ssize_t)0)
return (int)ret; return (int)ret;
continue; continue;
@@ -980,7 +952,7 @@ int mud_pull (struct mud *mud)
int mud_packet = !send_time; int mud_packet = !send_time;
if (mud_packet) { if (mud_packet) {
if (ret < (ssize_t)(MUD_TIME_SIZE+MUD_PACKET_MIN_SIZE)) if (ret < (ssize_t)MUD_PACKET_SIZEOF(MUD_TIME_SIZE))
continue; continue;
send_time = mud_read48(&packet->data[MUD_TIME_SIZE]); send_time = mud_read48(&packet->data[MUD_TIME_SIZE]);
@@ -989,7 +961,7 @@ int mud_pull (struct mud *mud)
if (mud_dt(now, send_time) >= mud->time_tolerance) if (mud_dt(now, send_time) >= mud->time_tolerance)
continue; continue;
if (mud_packet || (ret == (ssize_t)MUD_PACKET_MIN_SIZE)) { if (mud_packet) {
unsigned char tmp[sizeof(packet->data)]; unsigned char tmp[sizeof(packet->data)];
if (mud_decrypt(mud, tmp, sizeof(tmp), if (mud_decrypt(mud, tmp, sizeof(tmp),
@@ -1008,7 +980,7 @@ int mud_pull (struct mud *mud)
(struct sockaddr *)&addr); (struct sockaddr *)&addr);
if (!path) { if (!path) {
if (ret != (ssize_t)MUD_PACKET_MIN_SIZE) if (!mud_packet)
continue; continue;
path = mud_new_path(mud, &local_addr, (struct sockaddr *)&addr); path = mud_new_path(mud, &local_addr, (struct sockaddr *)&addr);
@@ -1028,16 +1000,19 @@ int mud_pull (struct mud *mud)
path->recv_time = now; path->recv_time = now;
if (mud_packet && (ret == (ssize_t)MUD_PONG_SIZE)) { if (mud_packet && (ret == (ssize_t)MUD_PONG_SIZE)) {
uint64_t old_send_time = mud_read48(&packet->data[MUD_TIME_SIZE*2]); uint64_t st = mud_read48(&packet->data[MUD_TIME_SIZE*2]);
uint64_t dt = mud_read48(&packet->data[MUD_TIME_SIZE*3]); uint64_t dt = mud_read48(&packet->data[MUD_TIME_SIZE*3]);
path->dt = dt; path->dt = dt;
path->sdt = send_time-old_send_time; path->sdt = send_time-st;
path->rtt = now-old_send_time; path->rtt = now-st;
continue; continue;
} }
mud_pong_path(mud, path, now); if (now-path->pong_time >= MUD_PONG_TIMEOUT) {
mud_ctrl_path(mud, mud_pong, path, now);
path->pong_time = now;
}
if (mud_packet) { if (mud_packet) {
if (ret == (ssize_t)MUD_KEYX_SIZE) if (ret == (ssize_t)MUD_KEYX_SIZE)
@@ -1045,9 +1020,6 @@ int mud_pull (struct mud *mud)
continue; continue;
} }
if (ret == (ssize_t)MUD_PACKET_MIN_SIZE)
continue;
packet->size = ret; packet->size = ret;
mud->rx.end = next; mud->rx.end = next;
} }
@@ -1103,7 +1075,8 @@ int mud_push (struct mud *mud)
if (path->state.up && (now-mud->crypto.time >= MUD_KEYX_TIMEOUT)) { if (path->state.up && (now-mud->crypto.time >= MUD_KEYX_TIMEOUT)) {
mud_keyx_init(mud); mud_keyx_init(mud);
mud_keyx_path(mud, path, now); mud_ctrl_path(mud, mud_keyx, path, now);
mud->crypto.time = now;
continue; continue;
} }
@@ -1113,7 +1086,10 @@ int mud_push (struct mud *mud)
(now-path->send_time) < mud->send_timeout) (now-path->send_time) < mud->send_timeout)
continue; continue;
mud_ping_path(mud, path, now); if (now-path->ping_time >= MUD_PING_TIMEOUT) {
mud_ctrl_path(mud, mud_ping, path, now);
path->ping_time = now;
}
} }
while (mud->tx.start != mud->tx.end) { while (mud->tx.start != mud->tx.end) {