Move mud_keyx in mud_conf
This commit is contained in:
148
mud.c
148
mud.c
@@ -112,11 +112,6 @@ struct mud_path {
|
|||||||
struct mud_path *next;
|
struct mud_path *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mud_crypto_pub {
|
|
||||||
unsigned char send[MUD_PUB_SIZE + 1];
|
|
||||||
unsigned char recv[MUD_PUB_SIZE + 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mud_crypto_opt {
|
struct mud_crypto_opt {
|
||||||
unsigned char *dst;
|
unsigned char *dst;
|
||||||
struct {
|
struct {
|
||||||
@@ -137,7 +132,6 @@ struct mud_crypto_key {
|
|||||||
enum mud_packet_code {
|
enum mud_packet_code {
|
||||||
mud_conf,
|
mud_conf,
|
||||||
mud_stat,
|
mud_stat,
|
||||||
mud_keyx,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mud_packet {
|
struct mud_packet {
|
||||||
@@ -151,13 +145,14 @@ struct mud_packet {
|
|||||||
unsigned char kiss[MUD_SID_SIZE];
|
unsigned char kiss[MUD_SID_SIZE];
|
||||||
unsigned char mtu[MUD_U48_SIZE];
|
unsigned char mtu[MUD_U48_SIZE];
|
||||||
unsigned char backup;
|
unsigned char backup;
|
||||||
|
unsigned char public[MUD_PUB_SIZE];
|
||||||
|
unsigned char aes;
|
||||||
} conf;
|
} conf;
|
||||||
struct {
|
struct {
|
||||||
unsigned char sdt[MUD_U48_SIZE];
|
unsigned char sdt[MUD_U48_SIZE];
|
||||||
unsigned char rdt[MUD_U48_SIZE];
|
unsigned char rdt[MUD_U48_SIZE];
|
||||||
unsigned char rst[MUD_U48_SIZE];
|
unsigned char rst[MUD_U48_SIZE];
|
||||||
} stat;
|
} stat;
|
||||||
struct mud_crypto_pub public;
|
|
||||||
} data;
|
} data;
|
||||||
unsigned char _do_not_use_[MUD_MAC_SIZE];
|
unsigned char _do_not_use_[MUD_MAC_SIZE];
|
||||||
};
|
};
|
||||||
@@ -168,10 +163,14 @@ struct mud {
|
|||||||
uint64_t time_tolerance;
|
uint64_t time_tolerance;
|
||||||
struct mud_path *path;
|
struct mud_path *path;
|
||||||
struct {
|
struct {
|
||||||
uint64_t recv_time;
|
uint64_t time;
|
||||||
unsigned char secret[crypto_scalarmult_SCALARBYTES];
|
unsigned char secret[crypto_scalarmult_SCALARBYTES];
|
||||||
struct mud_crypto_pub public;
|
struct {
|
||||||
|
unsigned char local[MUD_PUB_SIZE];
|
||||||
|
unsigned char remote[MUD_PUB_SIZE];
|
||||||
|
} public;
|
||||||
struct mud_crypto_key private, last, next, current;
|
struct mud_crypto_key private, last, next, current;
|
||||||
|
int ready;
|
||||||
int use_next;
|
int use_next;
|
||||||
int aes;
|
int aes;
|
||||||
} crypto;
|
} crypto;
|
||||||
@@ -696,13 +695,23 @@ mud_create_socket(int port, int v4, int v6)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
mud_keyx_init(struct mud *mud)
|
mud_keyx_init(struct mud *mud, uint64_t now)
|
||||||
{
|
{
|
||||||
|
if (!mud_timeout(now, mud->crypto.time, MUD_KEYX_TIMEOUT))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
mud->crypto.time = now ?: mud_now();
|
||||||
|
|
||||||
|
if (mud->crypto.ready)
|
||||||
|
return 0;
|
||||||
|
|
||||||
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.local, mud->crypto.secret);
|
||||||
memset(mud->crypto.public.recv, 0, sizeof(mud->crypto.public.recv));
|
|
||||||
mud->crypto.public.send[MUD_PUB_SIZE] = mud->crypto.aes;
|
mud->crypto.ready = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mud *
|
struct mud *
|
||||||
@@ -733,7 +742,7 @@ mud_create(int port, int v4, int v6, int aes, int mtu)
|
|||||||
mud_set_key(mud, key, sizeof(key));
|
mud_set_key(mud, key, sizeof(key));
|
||||||
|
|
||||||
mud->crypto.aes = aes && crypto_aead_aes256gcm_is_available();
|
mud->crypto.aes = aes && crypto_aead_aes256gcm_is_available();
|
||||||
mud_keyx_init(mud);
|
mud_keyx_init(mud, 0);
|
||||||
|
|
||||||
randombytes_buf(mud->kiss, sizeof(mud->kiss));
|
randombytes_buf(mud->kiss, sizeof(mud->kiss));
|
||||||
|
|
||||||
@@ -830,7 +839,6 @@ mud_decrypt(struct mud *mud,
|
|||||||
|
|
||||||
if (mud_decrypt_opt(&mud->crypto.current, &opt)) {
|
if (mud_decrypt_opt(&mud->crypto.current, &opt)) {
|
||||||
if (!mud_decrypt_opt(&mud->crypto.next, &opt)) {
|
if (!mud_decrypt_opt(&mud->crypto.next, &opt)) {
|
||||||
mud_keyx_init(mud);
|
|
||||||
mud->crypto.last = mud->crypto.current;
|
mud->crypto.last = mud->crypto.current;
|
||||||
mud->crypto.current = mud->crypto.next;
|
mud->crypto.current = mud->crypto.next;
|
||||||
mud->crypto.use_next = 0;
|
mud->crypto.use_next = 0;
|
||||||
@@ -898,6 +906,9 @@ mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
|||||||
memcpy(&packet.data.conf.kiss, &mud->kiss, size);
|
memcpy(&packet.data.conf.kiss, &mud->kiss, size);
|
||||||
mud_write48(packet.data.conf.mtu, path->conf.mtu.local);
|
mud_write48(packet.data.conf.mtu, path->conf.mtu.local);
|
||||||
packet.data.conf.backup = (unsigned char)path->state.backup;
|
packet.data.conf.backup = (unsigned char)path->state.backup;
|
||||||
|
memcpy(&packet.data.conf.public, &mud->crypto.public.local,
|
||||||
|
sizeof(mud->crypto.public.local));
|
||||||
|
packet.data.conf.aes = (unsigned char)mud->crypto.aes;
|
||||||
break;
|
break;
|
||||||
case mud_stat:
|
case mud_stat:
|
||||||
size = sizeof(packet.data.stat);
|
size = sizeof(packet.data.stat);
|
||||||
@@ -905,10 +916,6 @@ mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
|||||||
mud_write48(packet.data.stat.rdt, path->rdt);
|
mud_write48(packet.data.stat.rdt, path->rdt);
|
||||||
mud_write48(packet.data.stat.rst, path->rst);
|
mud_write48(packet.data.stat.rst, path->rst);
|
||||||
break;
|
break;
|
||||||
case mud_keyx:
|
|
||||||
size = sizeof(packet.data.public);
|
|
||||||
memcpy(&packet.data.public, &mud->crypto.public, size);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct mud_crypto_opt opt = {
|
struct mud_crypto_opt opt = {
|
||||||
@@ -924,62 +931,51 @@ mud_packet_send(struct mud *mud, enum mud_packet_code code,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mud_recv_keyx(struct mud *mud, struct mud_path *path, uint64_t now,
|
mud_keyx_set(struct mud *mud, unsigned char *key, unsigned char *secret,
|
||||||
struct mud_crypto_pub *public)
|
unsigned char *pub0, unsigned char *pub1)
|
||||||
{
|
{
|
||||||
struct mud_crypto_key *key = &mud->crypto.next;
|
crypto_generichash_state state;
|
||||||
|
|
||||||
struct {
|
crypto_generichash_init(&state, mud->crypto.private.encrypt.key,
|
||||||
unsigned char secret[crypto_scalarmult_BYTES];
|
MUD_KEY_SIZE, MUD_KEY_SIZE);
|
||||||
struct mud_crypto_pub public;
|
|
||||||
} shared_send, shared_recv;
|
|
||||||
|
|
||||||
memcpy(&shared_recv.public, public, sizeof(shared_recv.public));
|
crypto_generichash_update(&state, secret, crypto_scalarmult_BYTES);
|
||||||
|
crypto_generichash_update(&state, pub0, MUD_PUB_SIZE);
|
||||||
|
crypto_generichash_update(&state, pub1, MUD_PUB_SIZE);
|
||||||
|
|
||||||
int sync_send = memcmp(shared_recv.public.recv, mud->crypto.public.send,
|
crypto_generichash_final(&state, key, MUD_KEY_SIZE);
|
||||||
sizeof(shared_recv.public.recv));
|
}
|
||||||
|
|
||||||
memcpy(shared_recv.public.recv, mud->crypto.public.send,
|
static void
|
||||||
sizeof(shared_recv.public.recv));
|
mud_keyx(struct mud *mud, unsigned char *public, int aes)
|
||||||
|
{
|
||||||
|
unsigned char secret[crypto_scalarmult_BYTES];
|
||||||
|
|
||||||
memcpy(mud->crypto.public.recv, shared_recv.public.send,
|
// XXX keyx init ?
|
||||||
sizeof(mud->crypto.public.recv));
|
|
||||||
|
|
||||||
mud->crypto.use_next = !sync_send;
|
if (crypto_scalarmult(secret, mud->crypto.secret, public))
|
||||||
|
|
||||||
if (sync_send)
|
|
||||||
mud_packet_send(mud, mud_keyx, path, now);
|
|
||||||
|
|
||||||
if (crypto_scalarmult(shared_recv.secret, mud->crypto.secret,
|
|
||||||
shared_recv.public.send))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
memcpy(shared_send.secret, shared_recv.secret,
|
mud_keyx_set(mud, mud->crypto.next.encrypt.key,
|
||||||
sizeof(shared_send.secret));
|
secret, public, mud->crypto.public.local);
|
||||||
|
|
||||||
memcpy(shared_send.public.send, shared_recv.public.recv,
|
mud_keyx_set(mud, mud->crypto.next.decrypt.key,
|
||||||
sizeof(shared_send.public.send));
|
secret, mud->crypto.public.local, public);
|
||||||
|
|
||||||
memcpy(shared_send.public.recv, shared_recv.public.send,
|
memcpy(mud->crypto.public.remote, public, MUD_PUB_SIZE);
|
||||||
sizeof(shared_send.public.recv));
|
mud->crypto.ready = 0;
|
||||||
|
|
||||||
crypto_generichash(key->encrypt.key, MUD_KEY_SIZE,
|
mud->crypto.next.aes = mud->crypto.aes && aes;
|
||||||
(unsigned char *)&shared_send, sizeof(shared_send),
|
|
||||||
mud->crypto.private.encrypt.key, MUD_KEY_SIZE);
|
|
||||||
|
|
||||||
crypto_generichash(key->decrypt.key, MUD_KEY_SIZE,
|
if (mud->crypto.next.aes) {
|
||||||
(unsigned char *)&shared_recv, sizeof(shared_recv),
|
crypto_aead_aes256gcm_beforenm((crypto_aead_aes256gcm_state *)
|
||||||
mud->crypto.private.encrypt.key, MUD_KEY_SIZE);
|
mud->crypto.next.encrypt.state,
|
||||||
|
mud->crypto.next.encrypt.key);
|
||||||
|
|
||||||
key->aes = (shared_recv.public.send[MUD_PUB_SIZE] == 1) &&
|
crypto_aead_aes256gcm_beforenm((crypto_aead_aes256gcm_state *)
|
||||||
(shared_recv.public.recv[MUD_PUB_SIZE] == 1);
|
mud->crypto.next.decrypt.state,
|
||||||
|
mud->crypto.next.decrypt.key);
|
||||||
if (key->aes) {
|
|
||||||
crypto_aead_aes256gcm_beforenm(&key->encrypt.state, key->encrypt.key);
|
|
||||||
crypto_aead_aes256gcm_beforenm(&key->decrypt.state, key->decrypt.key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mud->crypto.recv_time = now;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -1014,7 +1010,6 @@ mud_packet_check_size(unsigned char *data, size_t size)
|
|||||||
const size_t sizes[] = {
|
const size_t sizes[] = {
|
||||||
[mud_conf] = MUD_PACKET_SIZE(sizeof(packet->data.conf)),
|
[mud_conf] = MUD_PACKET_SIZE(sizeof(packet->data.conf)),
|
||||||
[mud_stat] = MUD_PACKET_SIZE(sizeof(packet->data.stat)),
|
[mud_stat] = MUD_PACKET_SIZE(sizeof(packet->data.stat)),
|
||||||
[mud_keyx] = MUD_PACKET_SIZE(sizeof(packet->data.public)),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
@@ -1048,13 +1043,22 @@ mud_packet_recv(struct mud *mud, struct mud_path *path,
|
|||||||
{
|
{
|
||||||
struct mud_packet *packet = (struct mud_packet *)data;
|
struct mud_packet *packet = (struct mud_packet *)data;
|
||||||
|
|
||||||
|
int new_keyx = 0;
|
||||||
|
|
||||||
switch (packet->hdr.code) {
|
switch (packet->hdr.code) {
|
||||||
case mud_conf:
|
case mud_conf:
|
||||||
path->conf.mtu.remote = mud_read48(packet->data.conf.mtu);
|
path->conf.mtu.remote = mud_read48(packet->data.conf.mtu);
|
||||||
path->conf.remote = !memcmp(path->conf.kiss, packet->data.conf.kiss,
|
path->conf.remote = !memcmp(path->conf.kiss, packet->data.conf.kiss,
|
||||||
sizeof(path->conf.kiss));
|
sizeof(path->conf.kiss));
|
||||||
if (path->state.active)
|
new_keyx = memcmp(mud->crypto.public.remote, packet->data.conf.public,
|
||||||
|
sizeof(mud->crypto.public.remote));
|
||||||
|
if (new_keyx)
|
||||||
|
mud_keyx(mud, packet->data.conf.public, packet->data.conf.aes);
|
||||||
|
if (path->state.active) {
|
||||||
|
if (new_keyx)
|
||||||
|
mud->crypto.use_next = 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
if (!path->conf.remote) {
|
if (!path->conf.remote) {
|
||||||
memcpy(path->conf.kiss, packet->data.conf.kiss,
|
memcpy(path->conf.kiss, packet->data.conf.kiss,
|
||||||
sizeof(path->conf.kiss));
|
sizeof(path->conf.kiss));
|
||||||
@@ -1071,9 +1075,6 @@ mud_packet_recv(struct mud *mud, struct mud_path *path,
|
|||||||
path->r_dt = path->rst - path->r_rst;
|
path->r_dt = path->rst - path->r_rst;
|
||||||
path->rtt = now - path->r_rst;
|
path->rtt = now - path->r_rst;
|
||||||
break;
|
break;
|
||||||
case mud_keyx:
|
|
||||||
mud_recv_keyx(mud, path, now, &packet->data.public);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1175,29 +1176,22 @@ mud_recv(struct mud *mud, void *data, size_t size)
|
|||||||
static void
|
static void
|
||||||
mud_update(struct mud *mud)
|
mud_update(struct mud *mud)
|
||||||
{
|
{
|
||||||
|
uint64_t now = mud_now();
|
||||||
|
int update_keyx = !mud_keyx_init(mud, now);
|
||||||
|
|
||||||
struct mud_path *path;
|
struct mud_path *path;
|
||||||
|
|
||||||
for (path = mud->path; path; path = path->next) {
|
for (path = mud->path; path; path = path->next) {
|
||||||
if (!path->state.active)
|
if (!path->state.active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
uint64_t now = mud_now();
|
if (update_keyx || mud_timeout(now, path->recv_time, mud->send_timeout))
|
||||||
|
|
||||||
if (mud_timeout(now, path->recv_time, mud->send_timeout))
|
|
||||||
path->conf.remote = 0;
|
path->conf.remote = 0;
|
||||||
|
|
||||||
if ((!path->conf.remote) &&
|
if ((!path->conf.remote) &&
|
||||||
(mud_timeout(now, path->conf.send_time, mud->send_timeout))) {
|
(mud_timeout(now, path->conf.send_time, mud->send_timeout))) {
|
||||||
mud_packet_send(mud, mud_conf, path, now);
|
mud_packet_send(mud, mud_conf, path, now);
|
||||||
path->conf.send_time = now;
|
path->conf.send_time = now;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((mud_timeout(now, path->public.send_time, mud->send_timeout)) &&
|
|
||||||
(mud_timeout(now, mud->crypto.recv_time, MUD_KEYX_TIMEOUT))) {
|
|
||||||
mud_packet_send(mud, mud_keyx, path, now);
|
|
||||||
path->public.send_time = now;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user