summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2014-04-28 20:14:07 -0400
committerirungentoo <irungentoo@gmail.com>2014-04-28 20:14:07 -0400
commitb9370d519ff87020cf32f3d04b6a2c4eebcc9563 (patch)
treee98aa27e47a6e09716681bce04e62aed5c889a21
parent50cea69f5705a7a01e31417bae29feb920bfdd59 (diff)
Added some functions to create/handle middle level protocol packets.
-rw-r--r--docs/Tox_middle_level_network_protocol.txt27
-rw-r--r--toxcore/crypto_core.c13
-rw-r--r--toxcore/crypto_core.h4
-rw-r--r--toxcore/net_crypto.c123
4 files changed, 161 insertions, 6 deletions
diff --git a/docs/Tox_middle_level_network_protocol.txt b/docs/Tox_middle_level_network_protocol.txt
index be8253cd..49ad330c 100644
--- a/docs/Tox_middle_level_network_protocol.txt
+++ b/docs/Tox_middle_level_network_protocol.txt
@@ -42,13 +42,13 @@ cookie request packet:
42[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24 42[uint8_t 24][Senders DHT Public key (32 bytes)][Random nonce (24
43bytes)][Encrypted message containing: [Senders real public key (32 43bytes)][Encrypted message containing: [Senders real public key (32
44bytes)][Recievers real public key (32 bytes)]] 44bytes)][Recievers real public key (32 bytes)]]
45Encrypted message is encrypted with sender DHT private key, recievers DHT public 45Encrypted message is encrypted with sender DHT private key, recievers DHT
46key and the nonce. 46public key and the nonce.
47 47
48cookie response packet: 48cookie response packet:
49[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: [Cookie]] 49[uint8_t 25][Random nonce (24 bytes)][Encrypted message containing: [Cookie]]
50Encrypted message is encrypted with sender DHT private key, recievers DHT public 50Encrypted message is encrypted with sender DHT private key, recievers DHT
51key and the nonce. 51public key and the nonce.
52 52
53The Cookie should be basically: 53The Cookie should be basically:
54[nonce][encrypted data:[uint64_t time][Senders real public key (32 54[nonce][encrypted data:[uint64_t time][Senders real public key (32
@@ -61,3 +61,22 @@ nonce][session public key of the peer (32 bytes)]]
61The handshake packet is encrypted using the real private key of the sender, the 61The handshake packet is encrypted using the real private key of the sender, the
62real private key of the reciever and the nonce. 62real private key of the reciever and the nonce.
63 63
64
65Alice wants to connect to bob.
66
67Alice sends a cookie request packet to bob and gets a cookie response back.
68
69Alice then generates a nonce and a temporary public/private keypair.
70
71Alice then takes that nonce and just generated private key and the obtained
72cookie and puts them in a handshake packet which she sends to bob.
73
74Bob gets the handshake packet, accepts the connection request, then generates a
75nonce and a temporary public/private keypair and sends a handshake packet back
76with this just generated information and with the cookie field being random
77data/zeros.
78
79Both then use these temporary keys to generate the session key with which every
80data packet sent and recieved will be encrypted and decrypted. The nonce sent
81in the handshake will be used to encrypt the first data packet sent, the nonce
82+ 1 the second, the nonce + 2 the third and so on.
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.