Use a new more robust key exchange

This commit is contained in:
Adrien Gallouët
2016-07-20 15:13:22 +00:00
parent c1b13488af
commit 1fe5190e8a

104
mud.c
View File

@@ -39,10 +39,11 @@
#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_TIME_SIZE (6U) #define MUD_TIME_SIZE (6U)
#define MUD_KEY_SIZE (32U) #define MUD_KEY_SIZE (32U)
#define MUD_MAC_SIZE (16U)
#define MUD_PACKET_MIN_SIZE (MUD_TIME_SIZE+16U) #define MUD_PACKET_MIN_SIZE (MUD_TIME_SIZE+MUD_MAC_SIZE)
#define MUD_PACKET_MAX_SIZE (1500U) #define MUD_PACKET_MAX_SIZE (1500U)
#define MUD_PACKET_MASK (0x3FFU) #define MUD_PACKET_MASK (0x3FFU)
#define MUD_PACKET_COUNT ((MUD_PACKET_MASK)+1) #define MUD_PACKET_COUNT ((MUD_PACKET_MASK)+1)
@@ -136,7 +137,8 @@ struct crypto {
uint64_t time; uint64_t time;
unsigned char secret[crypto_scalarmult_SCALARBYTES]; unsigned char secret[crypto_scalarmult_SCALARBYTES];
struct public public; struct public public;
struct crypto_key private, last, current; struct crypto_key private, last, next, current;
int use_next;
int aes; int aes;
}; };
@@ -533,11 +535,9 @@ int mud_set_key (struct mud *mud, unsigned char *key, size_t size)
memcpy(mud->crypto.private.encrypt.key, key, MUD_KEY_SIZE); memcpy(mud->crypto.private.encrypt.key, key, MUD_KEY_SIZE);
memcpy(mud->crypto.private.decrypt.key, key, MUD_KEY_SIZE); memcpy(mud->crypto.private.decrypt.key, key, MUD_KEY_SIZE);
memcpy(mud->crypto.last.encrypt.key, key, MUD_KEY_SIZE); mud->crypto.current = mud->crypto.private;
memcpy(mud->crypto.last.decrypt.key, key, MUD_KEY_SIZE); mud->crypto.next = mud->crypto.private;
mud->crypto.last = mud->crypto.private;
memcpy(mud->crypto.current.encrypt.key, key, MUD_KEY_SIZE);
memcpy(mud->crypto.current.decrypt.key, key, MUD_KEY_SIZE);
return 0; return 0;
} }
@@ -720,7 +720,11 @@ int mud_encrypt (struct mud *mud, uint64_t nonce,
memcpy(dst+MUD_TIME_SIZE, src, ad_size); memcpy(dst+MUD_TIME_SIZE, src, ad_size);
if (nonce) { if (nonce) {
mud_encrypt_opt(&mud->crypto.current, &opt); if (mud->crypto.use_next) {
mud_encrypt_opt(&mud->crypto.next, &opt);
} else {
mud_encrypt_opt(&mud->crypto.current, &opt);
}
} else { } else {
mud_encrypt_opt(&mud->crypto.private, &opt); mud_encrypt_opt(&mud->crypto.private, &opt);
} }
@@ -753,10 +757,18 @@ int mud_decrypt (struct mud *mud,
memcpy(opt.npub, src, MUD_TIME_SIZE); memcpy(opt.npub, src, MUD_TIME_SIZE);
memcpy(dst, src+MUD_TIME_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) && if (!mud_decrypt_opt(&mud->crypto.next, &opt)) {
mud_decrypt_opt(&mud->crypto.private, &opt)) mud_keyx_init(mud);
return -1; mud->crypto.last = mud->crypto.current;
mud->crypto.current = mud->crypto.next;
mud->crypto.use_next = 0;
} else {
if (mud_decrypt_opt(&mud->crypto.last, &opt) &&
mud_decrypt_opt(&mud->crypto.private, &opt))
return -1;
}
}
return size; return size;
} }
@@ -854,6 +866,8 @@ static
void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now, void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now,
unsigned char *data) unsigned char *data)
{ {
struct crypto_key *key = &mud->crypto.next;
struct { struct {
unsigned char secret[crypto_scalarmult_BYTES]; unsigned char secret[crypto_scalarmult_BYTES];
struct public public; struct public public;
@@ -861,20 +875,22 @@ void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now,
memcpy(&shared_recv.public, data, sizeof(shared_recv.public)); memcpy(&shared_recv.public, data, sizeof(shared_recv.public));
memcpy(shared_send.public.send, shared_recv.public.recv, int sync_send = memcmp(shared_recv.public.recv, mud->crypto.public.send,
sizeof(shared_send.public.send)); sizeof(shared_recv.public.recv));
memcpy(shared_send.public.recv, shared_recv.public.send, int sync_recv = memcmp(mud->crypto.public.recv, shared_recv.public.send,
sizeof(shared_send.public.recv)); sizeof(mud->crypto.public.recv));
if (memcmp(&shared_send.public, &mud->crypto.public, memcpy(shared_recv.public.recv, mud->crypto.public.send,
sizeof(shared_recv.public))) { sizeof(shared_recv.public.recv));
memcpy(mud->crypto.public.recv, shared_recv.public.send,
sizeof(mud->crypto.public.recv)); memcpy(mud->crypto.public.recv, shared_recv.public.send,
sizeof(mud->crypto.public.recv));
mud->crypto.use_next = !sync_send;
if (sync_send)
mud_ctrl_path(mud, mud_keyx, path, now); mud_ctrl_path(mud, mud_keyx, path, now);
if (!path->state.active)
return;
}
if (crypto_scalarmult(shared_recv.secret, mud->crypto.secret, if (crypto_scalarmult(shared_recv.secret, mud->crypto.secret,
shared_recv.public.send)) shared_recv.public.send))
@@ -883,29 +899,25 @@ void mud_recv_keyx (struct mud *mud, struct path *path, uint64_t now,
memcpy(shared_send.secret, shared_recv.secret, memcpy(shared_send.secret, shared_recv.secret,
sizeof(shared_send.secret)); sizeof(shared_send.secret));
memcpy(&mud->crypto.last, &mud->crypto.current, memcpy(shared_send.public.send, shared_recv.public.recv,
sizeof(mud->crypto.last)); sizeof(shared_send.public.send));
crypto_generichash(mud->crypto.current.encrypt.key, MUD_KEY_SIZE, memcpy(shared_send.public.recv, shared_recv.public.send,
sizeof(shared_send.public.recv));
crypto_generichash(key->encrypt.key, MUD_KEY_SIZE,
(unsigned char *)&shared_send, sizeof(shared_send), (unsigned char *)&shared_send, sizeof(shared_send),
mud->crypto.private.encrypt.key, MUD_KEY_SIZE); mud->crypto.private.encrypt.key, MUD_KEY_SIZE);
crypto_generichash(mud->crypto.current.decrypt.key, MUD_KEY_SIZE, crypto_generichash(key->decrypt.key, MUD_KEY_SIZE,
(unsigned char *)&shared_recv, sizeof(shared_recv), (unsigned char *)&shared_recv, sizeof(shared_recv),
mud->crypto.private.encrypt.key, MUD_KEY_SIZE); mud->crypto.private.encrypt.key, MUD_KEY_SIZE);
crypto_aead_aes256gcm_beforenm(&mud->crypto.current.encrypt.state, crypto_aead_aes256gcm_beforenm(&key->encrypt.state, key->encrypt.key);
mud->crypto.current.encrypt.key); crypto_aead_aes256gcm_beforenm(&key->decrypt.state, key->decrypt.key);
crypto_aead_aes256gcm_beforenm(&mud->crypto.current.decrypt.state, key->aes = (shared_recv.public.send[MUD_PKEY_SIZE-1] == 1) &&
mud->crypto.current.decrypt.key); (shared_recv.public.recv[MUD_PKEY_SIZE-1] == 1);
if ((shared_recv.public.send[MUD_PKEY_SIZE-1] == 1) &&
(shared_recv.public.recv[MUD_PKEY_SIZE-1] == 1)) {
mud->crypto.current.aes = 1;
} else {
mud->crypto.current.aes = 0;
}
} }
int mud_pull (struct mud *mud) int mud_pull (struct mud *mud)
@@ -964,8 +976,15 @@ int mud_pull (struct mud *mud)
if (mud_packet) { if (mud_packet) {
unsigned char tmp[sizeof(packet->data)]; unsigned char tmp[sizeof(packet->data)];
if (mud_decrypt(mud, tmp, sizeof(tmp), struct crypto_opt opt = {
packet->data, ret, ret) == -1) .dst = tmp,
.src = { .data = packet->data+ret-MUD_MAC_SIZE,
.size = MUD_MAC_SIZE },
.ad = { .data = packet->data,
.size = ret-MUD_MAC_SIZE },
};
if (mud_decrypt_opt(&mud->crypto.private, &opt))
continue; continue;
} }
@@ -1074,7 +1093,6 @@ int mud_push (struct mud *mud)
continue; continue;
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_ctrl_path(mud, mud_keyx, path, now); mud_ctrl_path(mud, mud_keyx, path, now);
mud->crypto.time = now; mud->crypto.time = now;
continue; continue;