diff options
author | irungentoo <irungentoo@gmail.com> | 2013-08-10 16:20:54 -0700 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2013-08-10 16:20:54 -0700 |
commit | 8e05bcb5f92c69c43564e95832d3aa56075412cf (patch) | |
tree | 16bbc15380c8a2b32f0b6e19343967ab736591d9 /core | |
parent | e37fd0c607e3406aeab80b459008b3197341667e (diff) | |
parent | a5f34764d2a7bc5442fb7dca75dae7d85e61efc4 (diff) |
Merge pull request #422 from slvr/crypto-speed-boost
Cryptography speed boost
Diffstat (limited to 'core')
-rw-r--r-- | core/net_crypto.c | 104 | ||||
-rw-r--r-- | core/net_crypto.h | 16 |
2 files changed, 102 insertions, 18 deletions
diff --git a/core/net_crypto.c b/core/net_crypto.c index 406926b7..07c43c40 100644 --- a/core/net_crypto.c +++ b/core/net_crypto.c | |||
@@ -37,6 +37,7 @@ typedef struct { | |||
37 | uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */ | 37 | uint8_t sessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* our public key for this session. */ |
38 | uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */ | 38 | uint8_t sessionsecret_key[crypto_box_SECRETKEYBYTES]; /* our private key for this session. */ |
39 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ | 39 | uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */ |
40 | uint8_t shared_key[crypto_box_BEFORENMBYTES]; /* the precomputed shared key from encrypt_precompute */ | ||
40 | uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet | 41 | uint8_t status; /* 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet |
41 | (we have received a handshake but no empty data packet), 3 if the connection is established. | 42 | (we have received a handshake but no empty data packet), 3 if the connection is established. |
42 | 4 if the connection is timed out. */ | 43 | 4 if the connection is timed out. */ |
@@ -59,6 +60,17 @@ static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS]; | |||
59 | /* keeps track of the connection numbers for friends request so we can check later if they were sent */ | 60 | /* keeps track of the connection numbers for friends request so we can check later if they were sent */ |
60 | static int incoming_connections[MAX_INCOMING]; | 61 | static int incoming_connections[MAX_INCOMING]; |
61 | 62 | ||
63 | /* Use this instead of memcmp; not vulnerable to timing attacks. */ | ||
64 | uint8_t crypto_iszero(uint8_t *mem, uint32_t length) | ||
65 | { | ||
66 | uint8_t check = 0; | ||
67 | uint32_t i; | ||
68 | for (i = 0; i < length; ++i) { | ||
69 | check |= mem[i]; | ||
70 | } | ||
71 | return check; // We return zero if mem is made out of zeroes. | ||
72 | } | ||
73 | |||
62 | /* encrypts plain of length length to encrypted of length + 16 using the | 74 | /* encrypts plain of length length to encrypted of length + 16 using the |
63 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce | 75 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce |
64 | return -1 if there was a problem. | 76 | return -1 if there was a problem. |
@@ -78,12 +90,38 @@ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | |||
78 | 90 | ||
79 | /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero | 91 | /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero |
80 | apparently memcmp should not be used so we do this instead:*/ | 92 | apparently memcmp should not be used so we do this instead:*/ |
81 | uint32_t i; | 93 | if(crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) |
82 | uint32_t check = 0; | 94 | return -1; |
83 | for(i = 0; i < crypto_box_BOXZEROBYTES; ++i) { | 95 | |
84 | check |= temp_encrypted[i] ^ 0; | 96 | /* unpad the encrypted message */ |
85 | } | 97 | memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); |
86 | if(check != 0) | 98 | return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES; |
99 | } | ||
100 | |||
101 | /* Precomputes the shared key from their public_key and our secret_key. | ||
102 | This way we can avoid an expensive elliptic curve scalar multiply for each | ||
103 | encrypt/decrypt operation. | ||
104 | enc_key has to be crypto_box_BEFORENMBYTES bytes long. */ | ||
105 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key) | ||
106 | { | ||
107 | crypto_box_beforenm(enc_key, public_key, secret_key); | ||
108 | } | ||
109 | |||
110 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | ||
111 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
112 | uint8_t *plain, uint32_t length, uint8_t *encrypted) | ||
113 | { | ||
114 | if (length + crypto_box_MACBYTES > MAX_DATA_SIZE || length == 0) | ||
115 | return -1; | ||
116 | |||
117 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; | ||
118 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; | ||
119 | |||
120 | memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */ | ||
121 | |||
122 | crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, enc_key); | ||
123 | |||
124 | if(crypto_iszero(temp_encrypted, crypto_box_BOXZEROBYTES) != 0) | ||
87 | return -1; | 125 | return -1; |
88 | 126 | ||
89 | /* unpad the encrypted message */ | 127 | /* unpad the encrypted message */ |
@@ -112,12 +150,33 @@ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | |||
112 | 150 | ||
113 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero | 151 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero |
114 | apparently memcmp should not be used so we do this instead:*/ | 152 | apparently memcmp should not be used so we do this instead:*/ |
115 | uint32_t i; | 153 | if(crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) |
116 | uint32_t check = 0; | 154 | return -1; |
117 | for(i = 0; i < crypto_box_ZEROBYTES; ++i) { | 155 | |
118 | check |= temp_plain[i] ^ 0; | 156 | /* unpad the plain message */ |
119 | } | 157 | memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); |
120 | if(check != 0) | 158 | return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES; |
159 | } | ||
160 | |||
161 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | ||
162 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
163 | uint8_t *encrypted, uint32_t length, uint8_t *plain) | ||
164 | { | ||
165 | if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES) | ||
166 | return -1; | ||
167 | |||
168 | uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES]; | ||
169 | uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_BOXZEROBYTES] = {0}; | ||
170 | |||
171 | memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */ | ||
172 | |||
173 | if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, | ||
174 | nonce, enc_key) == -1) | ||
175 | return -1; | ||
176 | |||
177 | /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero | ||
178 | apparently memcmp should not be used so we do this instead:*/ | ||
179 | if(crypto_iszero(temp_plain, crypto_box_ZEROBYTES) != 0) | ||
121 | return -1; | 180 | return -1; |
122 | 181 | ||
123 | /* unpad the plain message */ | 182 | /* unpad the plain message */ |
@@ -161,9 +220,9 @@ int read_cryptpacket(int crypt_connection_id, uint8_t *data) | |||
161 | return 0; | 220 | return 0; |
162 | if (temp_data[0] != 3) | 221 | if (temp_data[0] != 3) |
163 | return -1; | 222 | return -1; |
164 | int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, | 223 | int len = decrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, |
165 | crypto_connections[crypt_connection_id].sessionsecret_key, | 224 | crypto_connections[crypt_connection_id].recv_nonce, |
166 | crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data); | 225 | temp_data + 1, length - 1, data); |
167 | if (len != -1) { | 226 | if (len != -1) { |
168 | increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); | 227 | increment_nonce(crypto_connections[crypt_connection_id].recv_nonce); |
169 | return len; | 228 | return len; |
@@ -182,9 +241,9 @@ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length) | |||
182 | if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) | 241 | if (crypto_connections[crypt_connection_id].status != CONN_ESTABLISHED) |
183 | return 0; | 242 | return 0; |
184 | uint8_t temp_data[MAX_DATA_SIZE]; | 243 | uint8_t temp_data[MAX_DATA_SIZE]; |
185 | int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key, | 244 | int len = encrypt_data_fast(crypto_connections[crypt_connection_id].shared_key, |
186 | crypto_connections[crypt_connection_id].sessionsecret_key, | 245 | crypto_connections[crypt_connection_id].sent_nonce, |
187 | crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1); | 246 | data, length, temp_data + 1); |
188 | if (len == -1) | 247 | if (len == -1) |
189 | return 0; | 248 | return 0; |
190 | temp_data[0] = 3; | 249 | temp_data[0] = 3; |
@@ -417,6 +476,9 @@ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secre | |||
417 | crypto_connections[i].sessionpublic_key) == 1) { | 476 | crypto_connections[i].sessionpublic_key) == 1) { |
418 | increment_nonce(crypto_connections[i].recv_nonce); | 477 | increment_nonce(crypto_connections[i].recv_nonce); |
419 | uint32_t zero = 0; | 478 | uint32_t zero = 0; |
479 | encrypt_precompute(crypto_connections[i].peersessionpublic_key, | ||
480 | crypto_connections[i].sessionsecret_key, | ||
481 | crypto_connections[i].shared_key); | ||
420 | crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ | 482 | crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ |
421 | write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); | 483 | write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); |
422 | crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ | 484 | crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ |
@@ -511,6 +573,9 @@ static void receive_crypto(void) | |||
511 | memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); | 573 | memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES); |
512 | increment_nonce(crypto_connections[i].sent_nonce); | 574 | increment_nonce(crypto_connections[i].sent_nonce); |
513 | uint32_t zero = 0; | 575 | uint32_t zero = 0; |
576 | encrypt_precompute(crypto_connections[i].peersessionpublic_key, | ||
577 | crypto_connections[i].sessionsecret_key, | ||
578 | crypto_connections[i].shared_key); | ||
514 | crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ | 579 | crypto_connections[i].status = CONN_ESTABLISHED; /* connection status needs to be 3 for write_cryptpacket() to work */ |
515 | write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); | 580 | write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero)); |
516 | crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ | 581 | crypto_connections[i].status = CONN_NOT_CONFIRMED; /* set it to its proper value right after. */ |
@@ -531,6 +596,9 @@ static void receive_crypto(void) | |||
531 | uint32_t zero = 0; | 596 | uint32_t zero = 0; |
532 | if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { | 597 | if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) { |
533 | increment_nonce(crypto_connections[i].recv_nonce); | 598 | increment_nonce(crypto_connections[i].recv_nonce); |
599 | encrypt_precompute(crypto_connections[i].peersessionpublic_key, | ||
600 | crypto_connections[i].sessionsecret_key, | ||
601 | crypto_connections[i].shared_key); | ||
534 | crypto_connections[i].status = CONN_ESTABLISHED; | 602 | crypto_connections[i].status = CONN_ESTABLISHED; |
535 | 603 | ||
536 | /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ | 604 | /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */ |
diff --git a/core/net_crypto.h b/core/net_crypto.h index 66634d45..135e099d 100644 --- a/core/net_crypto.h +++ b/core/net_crypto.h | |||
@@ -36,6 +36,9 @@ extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES]; | |||
36 | 36 | ||
37 | #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) | 37 | #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES) |
38 | 38 | ||
39 | /* returns zero if the buffer contains only zeros */ | ||
40 | uint8_t crypto_iszero(uint8_t* buffer, uint32_t blen); | ||
41 | |||
39 | /* encrypts plain of length length to encrypted of length + 16 using the | 42 | /* encrypts plain of length length to encrypted of length + 16 using the |
40 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce | 43 | public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce |
41 | return -1 if there was a problem. | 44 | return -1 if there was a problem. |
@@ -51,6 +54,19 @@ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | |||
51 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, | 54 | int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, |
52 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | 55 | uint8_t *encrypted, uint32_t length, uint8_t *plain); |
53 | 56 | ||
57 | /* Fast encrypt/decrypt operations. Use if this is not a one-time communication. | ||
58 | encrypt_precompute does the shared-key generation once so it does not have | ||
59 | to be preformed on every encrypt/decrypt. */ | ||
60 | void encrypt_precompute(uint8_t *public_key, uint8_t *secret_key, uint8_t *enc_key); | ||
61 | |||
62 | /* Fast encrypt. Depends on enc_key from encrypt_precompute. */ | ||
63 | int encrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
64 | uint8_t *plain, uint32_t length, uint8_t *encrypted); | ||
65 | |||
66 | /* Fast decrypt. Depends on enc_ley from encrypt_precompute. */ | ||
67 | int decrypt_data_fast(uint8_t *enc_key, uint8_t *nonce, | ||
68 | uint8_t *encrypted, uint32_t length, uint8_t *plain); | ||
69 | |||
54 | 70 | ||
55 | /* fill the given nonce with random bytes. */ | 71 | /* fill the given nonce with random bytes. */ |
56 | void random_nonce(uint8_t *nonce); | 72 | void random_nonce(uint8_t *nonce); |