summaryrefslogtreecommitdiff
path: root/toxcore
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore')
-rw-r--r--toxcore/crypto_core.c13
-rw-r--r--toxcore/crypto_core.h4
-rw-r--r--toxcore/net_crypto.c123
3 files changed, 138 insertions, 2 deletions
diff --git a/toxcore/crypto_core.c b/toxcore/crypto_core.c
index 59053bc4..6e8b747a 100644
--- a/toxcore/crypto_core.c
+++ b/toxcore/crypto_core.c
@@ -42,6 +42,19 @@ uint8_t crypto_iszero(uint8_t *mem, uint32_t length)
42 return check; // We return zero if mem is made out of zeroes. 42 return check; // We return zero if mem is made out of zeroes.
43} 43}
44 44
45/* Use this instead of memcmp; not vulnerable to timing attacks.
46 returns 0 if both mem locations of length are equal. */
47unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length)
48{
49 unsigned int i, check = 0;;
50
51 for (i = 0; i < length; ++i) {
52 check |= mem1[i] ^ mem2[i];
53 }
54
55 return check;
56}
57
45/* Precomputes the shared key from their public_key and our secret_key. 58/* Precomputes the shared key from their public_key and our secret_key.
46 * This way we can avoid an expensive elliptic curve scalar multiply for each 59 * This way we can avoid an expensive elliptic curve scalar multiply for each
47 * encrypt/decrypt operation. 60 * encrypt/decrypt operation.
diff --git a/toxcore/crypto_core.h b/toxcore/crypto_core.h
index a862635e..de8656c7 100644
--- a/toxcore/crypto_core.h
+++ b/toxcore/crypto_core.h
@@ -29,6 +29,10 @@
29/* return zero if the buffer contains only zeros. */ 29/* return zero if the buffer contains only zeros. */
30uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen); 30uint8_t crypto_iszero(uint8_t *buffer, uint32_t blen);
31 31
32/* Use this instead of memcmp; not vulnerable to timing attacks.
33 returns 0 if both mem locations of length are equal. */
34unsigned int crypto_cmp(uint8_t *mem1, uint8_t *mem2, uint32_t length);
35
32/* Encrypts plain of length length to encrypted of length + 16 using the 36/* Encrypts plain of length length to encrypted of length + 16 using the
33 * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce. 37 * public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce.
34 * 38 *
diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c
index 3d36e8e0..97533512 100644
--- a/toxcore/net_crypto.c
+++ b/toxcore/net_crypto.c
@@ -94,7 +94,7 @@ static int create_cookie(uint8_t *cookie, uint8_t *bytes, uint8_t *encryption_ke
94 94
95#define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + crypto_box_MACBYTES) 95#define COOKIE_RESPONSE_LENGTH (1 + crypto_box_NONCEBYTES + COOKIE_LENGTH + crypto_box_MACBYTES)
96 96
97/* Open cookie of length COOKIE_LENGTH from bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key 97/* Open cookie of length COOKIE_LENGTH to bytes of length COOKIE_REQUEST_PLAIN_LENGTH using encryption_key
98 * 98 *
99 * return -1 on failure. 99 * return -1 on failure.
100 * return 0 on success. 100 * return 0 on success.
@@ -172,7 +172,7 @@ static int handle_cookie_request(Net_Crypto *c, uint8_t *request_plain, uint8_t
172 */ 172 */
173static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *packet, uint32_t length) 173static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *packet, uint32_t length)
174{ 174{
175 Net_Crypto *c = c; 175 Net_Crypto *c = object;
176 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH]; 176 uint8_t request_plain[COOKIE_REQUEST_PLAIN_LENGTH];
177 uint8_t shared_key[crypto_box_BEFORENMBYTES]; 177 uint8_t shared_key[crypto_box_BEFORENMBYTES];
178 178
@@ -190,6 +190,125 @@ static int udp_handle_cookie_request(void *object, IP_Port source, uint8_t *pack
190 return 0; 190 return 0;
191} 191}
192 192
193/* Handle a cookie response packet of length encrypted with shared_key.
194 * put the cookie in the response in cookie
195 *
196 * cookie must be of length COOKIE_LENGTH.
197 *
198 * return -1 on failure.
199 * return COOKIE_LENGTH on success.
200 */
201static int handle_cookie_response(Net_Crypto *c, uint8_t *cookie, uint8_t *packet, uint32_t length, uint8_t *shared_key)
202{
203 if (length != COOKIE_RESPONSE_LENGTH)
204 return -1;
205
206 int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + crypto_box_NONCEBYTES,
207 length - (1 + crypto_box_NONCEBYTES), cookie);
208
209 if (len != COOKIE_LENGTH)
210 return -1;
211
212 return COOKIE_LENGTH;
213}
214
215#define HANDSHAKE_PACKET_LENGTH (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + crypto_box_MACBYTES)
216
217/* Create a handshake packet and put it in packet.
218 * cookie must be COOKIE_LENGTH bytes.
219 * packet must be of size HANDSHAKE_PACKET_LENGTH or bigger.
220 *
221 * return -1 on failure.
222 * return HANDSHAKE_PACKET_LENGTH on success.
223 */
224static int create_crypto_handshake(Net_Crypto *c, uint8_t *packet, uint8_t *cookie, uint8_t *nonce, uint8_t *session_pk,
225 uint8_t *peer_real_pk)
226{
227 uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
228 memcpy(plain, nonce, crypto_box_NONCEBYTES);
229 memcpy(plain + crypto_box_NONCEBYTES, session_pk, crypto_box_PUBLICKEYBYTES);
230 new_nonce(packet + 1 + COOKIE_LENGTH);
231 int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
232 packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES);
233
234 if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES))
235 return -1;
236
237 packet[0] = NET_PACKET_CRYPTO_HS;
238 memcpy(packet + 1, cookie, COOKIE_LENGTH);
239
240 return HANDSHAKE_PACKET_LENGTH;
241}
242
243/* Handle a crypto handshake packet of length.
244 * put the nonce contained in the packet in nonce,
245 * the session public key in session_pk and
246 * the real public key of the peer in peer_real_pk.
247 *
248 * nonce must be at least crypto_box_NONCEBYTES
249 * session_pk must be at least crypto_box_PUBLICKEYBYTES
250 * peer_real_pk must be at least crypto_box_PUBLICKEYBYTES
251 *
252 * return -1 on failure.
253 * return 0 on success.
254 */
255static int handle_crypto_handshake(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *peer_real_pk,
256 uint8_t *packet, uint32_t length)
257{
258 if (length != HANDSHAKE_PACKET_LENGTH)
259 return -1;
260
261 uint8_t cookie_plain[COOKIE_REQUEST_PLAIN_LENGTH];
262
263 if (open_cookie(cookie_plain, packet + 1, c->secret_symmetric_key) != 0)
264 return -1;
265
266 if (crypto_cmp(cookie_plain + crypto_box_PUBLICKEYBYTES, c->self_public_key, crypto_box_PUBLICKEYBYTES) != 0)
267 return -1;
268
269 uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
270 int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
271 packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES,
272 HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain);
273
274 if (len != sizeof(plain))
275 return -1;
276
277 memcpy(nonce, plain, crypto_box_NONCEBYTES);
278 memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES);
279 memcpy(peer_real_pk, cookie_plain, crypto_box_PUBLICKEYBYTES);
280 return 0;
281}
282
283/* Handle a crypto handshake packet of length without opening the cookie from peer
284 * with the real public key peer_real_pk.
285 * put the nonce contained in the packet in nonce and the session public key in
286 * session_pk.
287 *
288 * nonce must be at least crypto_box_NONCEBYTES
289 * session_pk must be at least crypto_box_PUBLICKEYBYTES
290 *
291 * return -1 on failure.
292 * return 0 on success.
293 */
294static int handle_crypto_handshake_nocookie(Net_Crypto *c, uint8_t *nonce, uint8_t *session_pk, uint8_t *packet,
295 uint32_t length, uint8_t *peer_real_pk)
296{
297 if (length != HANDSHAKE_PACKET_LENGTH)
298 return -1;
299
300 uint8_t plain[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
301 int len = decrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
302 packet + 1 + COOKIE_LENGTH + crypto_box_NONCEBYTES,
303 HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + crypto_box_NONCEBYTES), plain);
304
305 if (len != sizeof(plain))
306 return -1;
307
308 memcpy(nonce, plain, crypto_box_NONCEBYTES);
309 memcpy(session_pk, plain + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES);
310 return 0;
311}
193/* return 0 if there is no received data in the buffer. 312/* return 0 if there is no received data in the buffer.
194 * return -1 if the packet was discarded. 313 * return -1 if the packet was discarded.
195 * return length of received data if successful. 314 * return length of received data if successful.