/* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t length) { if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) return -1; if (send_pending_data(con) == -1) return 0; uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; uint16_t c_length = htons(length + crypto_box_MACBYTES); memcpy(packet, &c_length, sizeof(uint16_t)); int len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if ((unsigned int)len != (sizeof(packet) - sizeof(uint16_t))) return -1; increment_nonce(con->sent_nonce); len = send(con->sock, packet, sizeof(packet), MSG_NOSIGNAL); if ((unsigned int)len == sizeof(packet)) return 1; if (len <= 0) return 0; memcpy(con->last_packet, packet, length); con->last_packet_length = sizeof(packet); con->last_packet_sent = len; return 1; }
/* return 0 if data could not be put in packet queue. * return 1 if data was put into the queue. */ int write_cryptpacket(Net_Crypto *c, int crypt_connection_id, uint8_t *data, uint32_t length) { if (crypt_connection_id_not_valid(c, crypt_connection_id)) return 0; if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) return 0; if (c->crypto_connections[crypt_connection_id].status != CRYPTO_CONN_ESTABLISHED) return 0; uint8_t temp_data[MAX_DATA_SIZE]; int len = encrypt_data_fast(c->crypto_connections[crypt_connection_id].shared_key, c->crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); if (len == -1) return 0; temp_data[0] = 3; if (write_packet(c->lossless_udp, c->crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) return 0; increment_nonce(c->crypto_connections[crypt_connection_id].sent_nonce); return 1; }
int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, uint8_t *plain, uint32_t length, uint8_t *encrypted) { uint8_t k[crypto_box_BEFORENMBYTES]; encrypt_precompute(public_key, secret_key, k); return encrypt_data_fast(k, nonce, plain, length, encrypted); }
/* return 1 on success. * return 0 if could not send packet. * return -1 on failure (connection must be killed). */ static int write_packet_TCP_secure_connection(TCP_Secure_Connection *con, uint8_t *data, uint16_t length) { if (length + crypto_box_MACBYTES > MAX_PACKET_SIZE) return -1; uint8_t packet[sizeof(uint16_t) + length + crypto_box_MACBYTES]; length = htons(length); memcpy(packet, &length, sizeof(uint16_t)); uint32_t len = encrypt_data_fast(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); if (len != (sizeof(packet) - sizeof(uint16_t))) return -1; increment_nonce(con->sent_nonce); len = send(con->sock, packet, sizeof(packet), 0); if (len == sizeof(packet)) return 1; if (len <= 0) return 0; return -1; }
/* return 0 if data could not be put in packet queue return 1 if data was put into the queue */ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) { if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS) return 0; if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1) return 0; if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) return 0; uint8_t temp_data[MAX_DATA_SIZE]; int len = encrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); if (len == -1) return 0; temp_data[0] = 3; if (write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0) return 0; increment_nonce(crypto_connections[crypt_connection_id].sent_nonce); return 1; }
/* return 1 if everything went well. * return -1 if the connection must be killed. */ static int handle_TCP_handshake(TCP_Secure_Connection *con, uint8_t *data, uint16_t length, uint8_t *self_secret_key) { if (length != TCP_CLIENT_HANDSHAKE_SIZE) return -1; if (con->status != TCP_STATUS_CONNECTED) return -1; uint8_t shared_key[crypto_box_BEFORENMBYTES]; encrypt_precompute(data, self_secret_key, shared_key); uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; int len = decrypt_data_fast(shared_key, data + crypto_box_PUBLICKEYBYTES, data + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES, plain); if (len != TCP_HANDSHAKE_PLAIN_SIZE) return -1; memcpy(con->public_key, data, crypto_box_PUBLICKEYBYTES); uint8_t temp_secret_key[crypto_box_SECRETKEYBYTES]; uint8_t resp_plain[TCP_HANDSHAKE_PLAIN_SIZE]; crypto_box_keypair(resp_plain, temp_secret_key); random_nonce(con->sent_nonce); memcpy(resp_plain + crypto_box_PUBLICKEYBYTES, con->sent_nonce, crypto_box_NONCEBYTES); memcpy(con->recv_nonce, plain + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES); uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; new_nonce(response); len = encrypt_data_fast(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, response + crypto_box_NONCEBYTES); if (len != TCP_HANDSHAKE_PLAIN_SIZE + crypto_box_MACBYTES) return -1; if (TCP_SERVER_HANDSHAKE_SIZE != send(con->sock, response, TCP_SERVER_HANDSHAKE_SIZE, MSG_NOSIGNAL)) return -1; encrypt_precompute(plain, temp_secret_key, con->shared_key); con->status = TCP_STATUS_UNCONFIRMED; return 1; }
int main(int argc, char *argv[]) { const int numtrials = 10000; unsigned char pk1[crypto_box_PUBLICKEYBYTES]; unsigned char sk1[crypto_box_SECRETKEYBYTES]; unsigned char pk2[crypto_box_PUBLICKEYBYTES]; unsigned char sk2[crypto_box_SECRETKEYBYTES]; unsigned char k1[crypto_box_BEFORENMBYTES]; unsigned char k2[crypto_box_BEFORENMBYTES]; unsigned char n[crypto_box_NONCEBYTES]; unsigned char m[500]; unsigned char c[sizeof(m) + ENCRYPTION_PADDING]; unsigned char k[crypto_box_BEFORENMBYTES]; int trialno; double starttime; double endtime; double slow_time; double fast_time; double keygen_time; double precompute_time; // Pregenerate crypto_box_keypair(pk1, sk1); crypto_box_keypair(pk2, sk2); encrypt_precompute(pk1, sk2, k1); encrypt_precompute(pk2, sk1, k2); rand_bytes(m, sizeof(m)); rand_bytes(n, sizeof(n)); printf("starting slow...\n"); starttime = get_time(); for (trialno = 0; trialno < numtrials; trialno++) { encrypt_data(pk1, sk2, n, m, sizeof(m), c); decrypt_data(pk2, sk1, n, c, sizeof(c), m); } endtime = get_time(); slow_time = endtime - starttime; printf("starting fast...\n"); starttime = get_time(); for (trialno = 0; trialno < numtrials; trialno++) { encrypt_data_fast(k1, n, m, sizeof(m), c); decrypt_data_fast(k2, n, c, sizeof(c), m); } endtime = get_time(); fast_time = endtime - starttime; printf("starting keygen...\n"); starttime = get_time(); for (trialno = 0; trialno < numtrials; trialno++) { crypto_box_keypair(pk1, sk1); crypto_box_keypair(pk2, sk2); } endtime = get_time(); keygen_time = endtime - starttime; printf("starting precompute...\n"); starttime = get_time(); for (trialno = 0; trialno < numtrials; trialno++) { encrypt_precompute(pk1, sk2, k); encrypt_precompute(pk2, sk1, k); } endtime = get_time(); precompute_time = endtime - starttime; printf("\n"); printf("trials: %i\n", 2 * numtrials); printf("\n"); printf("slow time: %f sec\n", slow_time); printf("fast time: %f sec\n", fast_time); printf("keygen time: %f sec\n", keygen_time); printf("precompute time: %f sec\n", precompute_time); printf("\n"); printf("Speed boost: %.1f%%\n", slow_time * 100 / fast_time); printf("\n"); printf("slow: %.1f per second\n", 2 * numtrials / slow_time); printf("fast: %.1f per second\n", 2 * numtrials / fast_time); return 0; }