From 3bcc6e2ae547ae77f14d7d140a363cc2cc01f01a Mon Sep 17 00:00:00 2001 From: irungentoo Date: Wed, 5 Mar 2014 16:54:17 -0500 Subject: [PATCH] CPU optimizations. Use get_shared_key() in more places. --- toxcore/DHT.c | 75 ++++++++++++++++++++++++++-------------- toxcore/DHT.h | 24 ++++++++++--- toxcore/onion.c | 24 ++++++------- toxcore/onion.h | 4 +++ toxcore/onion_announce.c | 2 +- toxcore/onion_announce.h | 2 ++ toxcore/ping.c | 4 +-- 7 files changed, 89 insertions(+), 46 deletions(-) diff --git a/toxcore/DHT.c b/toxcore/DHT.c index be68116c..607a31e4 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -114,29 +114,33 @@ static int client_id_cmp(ClientPair p1, ClientPair p2) return c; } -/* Copy shared_key to decrypt DHT packet from client_id into shared_key +/* Shared key generations are costly, it is therefor smart to store commonly used + * ones so that they can re used later without being computed again. + * + * If shared key is already in shared_keys, copy it to shared_key. + * else generate it into shared_key and copy it to shared_keys */ -void DHT_get_shared_key(DHT *dht, uint8_t *shared_key, uint8_t *client_id) +void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id) { uint32_t i, num = ~0, curr = 0; for (i = 0; i < MAX_KEYS_PER_SLOT; ++i) { int index = client_id[30] * MAX_KEYS_PER_SLOT + i; - if (dht->shared_keys.keys[index].stored) { - if (memcmp(client_id, dht->shared_keys.keys[index].client_id, CLIENT_ID_SIZE) == 0) { - memcpy(shared_key, dht->shared_keys.keys[index].shared_key, crypto_box_BEFORENMBYTES); - ++dht->shared_keys.keys[index].times_requested; - dht->shared_keys.keys[index].time_last_requested = unix_time(); + if (shared_keys->keys[index].stored) { + if (memcmp(client_id, shared_keys->keys[index].client_id, CLIENT_ID_SIZE) == 0) { + memcpy(shared_key, shared_keys->keys[index].shared_key, crypto_box_BEFORENMBYTES); + ++shared_keys->keys[index].times_requested; + shared_keys->keys[index].time_last_requested = unix_time(); return; } if (num != 0) { - if (is_timeout(dht->shared_keys.keys[index].time_last_requested, KEYS_TIMEOUT)) { + if (is_timeout(shared_keys->keys[index].time_last_requested, KEYS_TIMEOUT)) { num = 0; curr = index; - } else if (num > dht->shared_keys.keys[index].times_requested) { - num = dht->shared_keys.keys[index].times_requested; + } else if (num > shared_keys->keys[index].times_requested) { + num = shared_keys->keys[index].times_requested; curr = index; } } @@ -148,17 +152,34 @@ void DHT_get_shared_key(DHT *dht, uint8_t *shared_key, uint8_t *client_id) } } - encrypt_precompute(client_id, dht->self_secret_key, shared_key); + encrypt_precompute(client_id, secret_key, shared_key); if (num != (uint32_t)~0) { - dht->shared_keys.keys[curr].stored = 1; - dht->shared_keys.keys[curr].times_requested = 1; - memcpy(dht->shared_keys.keys[curr].client_id, client_id, CLIENT_ID_SIZE); - memcpy(dht->shared_keys.keys[curr].shared_key, shared_key, crypto_box_BEFORENMBYTES); - dht->shared_keys.keys[curr].time_last_requested = unix_time(); + shared_keys->keys[curr].stored = 1; + shared_keys->keys[curr].times_requested = 1; + memcpy(shared_keys->keys[curr].client_id, client_id, CLIENT_ID_SIZE); + memcpy(shared_keys->keys[curr].shared_key, shared_key, crypto_box_BEFORENMBYTES); + shared_keys->keys[curr].time_last_requested = unix_time(); } } +/* Copy shared_key to decrypt DHT packet from client_id into shared_key + * for packets that we recieve. + */ +void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id) +{ + return get_shared_key(&dht->shared_keys_recv, shared_key, dht->self_secret_key, client_id); +} + +/* Copy shared_key to decrypt DHT packet from client_id into shared_key + * for packets that we send. + */ +void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id) +{ + return get_shared_key(&dht->shared_keys_sent, shared_key, dht->self_secret_key, client_id); +} + + /* Check if client with client_id is already in list of length length. * If it is then set its corresponding timestamp to current time. * If the id is already in the list with a different ip_port, update it. @@ -867,12 +888,13 @@ static int getnodes(DHT *dht, IP_Port ip_port, uint8_t *public_key, uint8_t *cli memcpy(plain, client_id, CLIENT_ID_SIZE); memcpy(plain + CLIENT_ID_SIZE, encrypted_message, NODES_ENCRYPTED_MESSAGE_LENGTH); - int len = encrypt_data( public_key, - dht->self_secret_key, - nonce, - plain, - CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, - encrypt ); + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + DHT_get_shared_key_sent(dht, shared_key, public_key); + int len = encrypt_data_fast( shared_key, + nonce, + plain, + CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH, + encrypt ); if (len != CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES) return -1; @@ -1036,7 +1058,7 @@ static int handle_getnodes(void *object, IP_Port source, uint8_t *packet, uint32 uint8_t plain[CLIENT_ID_SIZE + NODES_ENCRYPTED_MESSAGE_LENGTH]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; - DHT_get_shared_key(dht, shared_key, packet + 1); + DHT_get_shared_key_recv(dht, shared_key, packet + 1); int len = decrypt_data_fast( shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, @@ -1111,9 +1133,10 @@ static int handle_sendnodes_core(void *object, IP_Port source, uint8_t *packet, if (num_nodes > MAX_SENT_NODES) /* too long */ return 1; - int len = decrypt_data( - packet + 1, - dht->self_secret_key, + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + DHT_get_shared_key_sent(dht, shared_key, packet + 1); + int len = decrypt_data_fast( + shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES, num_nodes * node_format_size + NODES_ENCRYPTED_MESSAGE_LENGTH + crypto_box_MACBYTES, diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 32abdc64..da145304 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -146,7 +146,7 @@ typedef struct { /* struct to store some shared keys so we don't have to regenerate them for each request. */ #define MAX_KEYS_PER_SLOT 4 #define KEYS_TIMEOUT 600 -struct SHARED_KEYS { +typedef struct { struct { uint8_t client_id[CLIENT_ID_SIZE]; uint8_t shared_key[crypto_box_BEFORENMBYTES]; @@ -154,7 +154,7 @@ struct SHARED_KEYS { uint8_t stored; /* 0 if not, 1 if is */ uint64_t time_last_requested; } keys[256 * MAX_KEYS_PER_SLOT]; -}; +} Shared_Keys; /*----------------------------------------------------------------------------------*/ @@ -175,7 +175,8 @@ typedef struct { DHT_Friend *friends_list; uint16_t num_friends; - struct SHARED_KEYS shared_keys; + Shared_Keys shared_keys_recv; + Shared_Keys shared_keys_sent; struct PING *ping; #ifdef ENABLE_ASSOC_DHT @@ -185,10 +186,23 @@ typedef struct { } DHT; /*----------------------------------------------------------------------------------*/ -/* Copy shared_key to decrypt DHT packet from client_id into shared_key +/* Shared key generations are costly, it is therefor smart to store commonly used + * ones so that they can re used later without being computed again. + * + * If shared key is already in shared_keys, copy it to shared_key. + * else generate it into shared_key and copy it to shared_keys */ -void DHT_get_shared_key(DHT *dht, uint8_t *shared_key, uint8_t *client_id); +void get_shared_key(Shared_Keys *shared_keys, uint8_t *shared_key, uint8_t *secret_key, uint8_t *client_id); +/* Copy shared_key to decrypt DHT packet from client_id into shared_key + * for packets that we recieve. + */ +void DHT_get_shared_key_recv(DHT *dht, uint8_t *shared_key, uint8_t *client_id); + +/* Copy shared_key to decrypt DHT packet from client_id into shared_key + * for packets that we send. + */ +void DHT_get_shared_key_sent(DHT *dht, uint8_t *shared_key, uint8_t *client_id); void DHT_getnodes(DHT *dht, IP_Port *from_ipp, uint8_t *from_id, uint8_t *which_id); diff --git a/toxcore/onion.c b/toxcore/onion.c index 57001784..292f9309 100644 --- a/toxcore/onion.c +++ b/toxcore/onion.c @@ -173,10 +173,10 @@ static int handle_send_initial(void *object, IP_Port source, uint8_t *packet, ui change_symmetric_key(onion); uint8_t plain[MAX_ONION_SIZE]; - - int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, - packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + get_shared_key(&onion->shared_keys_1, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); + int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)) return 1; @@ -219,10 +219,10 @@ static int handle_send_1(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); uint8_t plain[MAX_ONION_SIZE]; - - int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, - packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + get_shared_key(&onion->shared_keys_2, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); + int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_1 + crypto_box_MACBYTES)) return 1; @@ -268,10 +268,10 @@ static int handle_send_2(void *object, IP_Port source, uint8_t *packet, uint32_t change_symmetric_key(onion); uint8_t plain[MAX_ONION_SIZE]; - - int len = decrypt_data(packet + 1 + crypto_box_NONCEBYTES, onion->dht->self_secret_key, packet + 1, - packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, - length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); + uint8_t shared_key[crypto_box_BEFORENMBYTES]; + get_shared_key(&onion->shared_keys_3, shared_key, onion->dht->self_secret_key, packet + 1 + crypto_box_NONCEBYTES); + int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, + length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2), plain); if ((uint32_t)len != length - (1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + RETURN_2 + crypto_box_MACBYTES)) return 1; diff --git a/toxcore/onion.h b/toxcore/onion.h index 951a5d1f..daaec91c 100644 --- a/toxcore/onion.h +++ b/toxcore/onion.h @@ -30,6 +30,10 @@ typedef struct { Networking_Core *net; uint8_t secret_symmetric_key[crypto_secretbox_KEYBYTES]; uint64_t timestamp; + + Shared_Keys shared_keys_1; + Shared_Keys shared_keys_2; + Shared_Keys shared_keys_3; } Onion; #define ONION_RETURN_1 (crypto_secretbox_NONCEBYTES + sizeof(IP_Port) + crypto_secretbox_MACBYTES) diff --git a/toxcore/onion_announce.c b/toxcore/onion_announce.c index 65be8b27..331e54d8 100644 --- a/toxcore/onion_announce.c +++ b/toxcore/onion_announce.c @@ -218,7 +218,7 @@ static int handle_announce_request(void *object, IP_Port source, uint8_t *packet uint8_t *packet_public_key = packet + 1 + crypto_box_NONCEBYTES; uint8_t shared_key[crypto_box_BEFORENMBYTES]; - encrypt_precompute(packet_public_key, onion_a->dht->self_secret_key, shared_key); + get_shared_key(&onion_a->shared_keys_recv, shared_key, onion_a->dht->self_secret_key, packet_public_key); uint8_t plain[ONION_PING_ID_SIZE + crypto_box_PUBLICKEYBYTES + crypto_box_PUBLICKEYBYTES + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH]; int len = decrypt_data_fast(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES, diff --git a/toxcore/onion_announce.h b/toxcore/onion_announce.h index 24240436..eaaee43f 100644 --- a/toxcore/onion_announce.h +++ b/toxcore/onion_announce.h @@ -54,6 +54,8 @@ typedef struct { Onion_Announce_Entry entries[ONION_ANNOUNCE_MAX_ENTRIES]; /* This is crypto_secretbox_KEYBYTES long just so we can use new_symmetric_key() to fill it */ uint8_t secret_bytes[crypto_secretbox_KEYBYTES]; + + Shared_Keys shared_keys_recv; } Onion_Announce; /* Create and send an onion announce request packet. diff --git a/toxcore/ping.c b/toxcore/ping.c index ff410f39..0aad3f9f 100644 --- a/toxcore/ping.c +++ b/toxcore/ping.c @@ -156,7 +156,7 @@ int send_ping_request(PING *ping, IP_Port ipp, uint8_t *client_id) uint8_t shared_key[crypto_box_BEFORENMBYTES]; // generate key to encrypt ping_id with recipient privkey - encrypt_precompute(client_id, ping->dht->self_secret_key, shared_key); + DHT_get_shared_key_sent(ping->dht, shared_key, client_id); // Generate random ping_id. ping_id = add_ping(ping, ipp, shared_key); @@ -218,7 +218,7 @@ static int handle_ping_request(void *_dht, IP_Port source, uint8_t *packet, uint uint8_t shared_key[crypto_box_BEFORENMBYTES]; // Decrypt ping_id - DHT_get_shared_key(dht, shared_key, packet + 1); + DHT_get_shared_key_recv(dht, shared_key, packet + 1); rc = decrypt_data_fast(shared_key, packet + 1 + CLIENT_ID_SIZE, packet + 1 + CLIENT_ID_SIZE + crypto_box_NONCEBYTES,