summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-08-10 16:20:54 -0700
committerirungentoo <irungentoo@gmail.com>2013-08-10 16:20:54 -0700
commit8e05bcb5f92c69c43564e95832d3aa56075412cf (patch)
tree16bbc15380c8a2b32f0b6e19343967ab736591d9 /core
parente37fd0c607e3406aeab80b459008b3197341667e (diff)
parenta5f34764d2a7bc5442fb7dca75dae7d85e61efc4 (diff)
Merge pull request #422 from slvr/crypto-speed-boost
Cryptography speed boost
Diffstat (limited to 'core')
-rw-r--r--core/net_crypto.c104
-rw-r--r--core/net_crypto.h16
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 */
60static int incoming_connections[MAX_INCOMING]; 61static int incoming_connections[MAX_INCOMING];
61 62
63/* Use this instead of memcmp; not vulnerable to timing attacks. */
64uint8_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. */
105void 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. */
111int 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. */
162int 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 */
40uint8_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,
51int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce, 54int 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. */
60void 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. */
63int 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. */
67int 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. */
56void random_nonce(uint8_t *nonce); 72void random_nonce(uint8_t *nonce);