ffi-tox 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/ProjectTox-Core/CMakeLists.txt +28 -0
  2. data/ProjectTox-Core/COPYING +674 -0
  3. data/ProjectTox-Core/INSTALL.md +91 -0
  4. data/ProjectTox-Core/README.md +54 -0
  5. data/ProjectTox-Core/core/CMakeLists.txt +17 -0
  6. data/ProjectTox-Core/core/DHT.c +1104 -0
  7. data/ProjectTox-Core/core/DHT.h +111 -0
  8. data/ProjectTox-Core/core/LAN_discovery.c +79 -0
  9. data/ProjectTox-Core/core/LAN_discovery.h +50 -0
  10. data/ProjectTox-Core/core/Lossless_UDP.c +749 -0
  11. data/ProjectTox-Core/core/Lossless_UDP.h +106 -0
  12. data/ProjectTox-Core/core/Messenger.c +581 -0
  13. data/ProjectTox-Core/core/Messenger.h +157 -0
  14. data/ProjectTox-Core/core/friend_requests.c +131 -0
  15. data/ProjectTox-Core/core/friend_requests.h +51 -0
  16. data/ProjectTox-Core/core/net_crypto.c +564 -0
  17. data/ProjectTox-Core/core/net_crypto.h +134 -0
  18. data/ProjectTox-Core/core/network.c +188 -0
  19. data/ProjectTox-Core/core/network.h +134 -0
  20. data/ProjectTox-Core/other/CMakeLists.txt +9 -0
  21. data/ProjectTox-Core/other/DHT_bootstrap.c +139 -0
  22. data/ProjectTox-Core/testing/CMakeLists.txt +18 -0
  23. data/ProjectTox-Core/testing/DHT_cryptosendfiletest.c +228 -0
  24. data/ProjectTox-Core/testing/DHT_sendfiletest.c +176 -0
  25. data/ProjectTox-Core/testing/DHT_test.c +182 -0
  26. data/ProjectTox-Core/testing/Lossless_UDP_testclient.c +214 -0
  27. data/ProjectTox-Core/testing/Lossless_UDP_testserver.c +201 -0
  28. data/ProjectTox-Core/testing/Messenger_test.c +145 -0
  29. data/ProjectTox-Core/testing/misc_tools.c +40 -0
  30. data/ProjectTox-Core/testing/misc_tools.h +29 -0
  31. data/ProjectTox-Core/testing/nTox.c +381 -0
  32. data/ProjectTox-Core/testing/nTox.h +50 -0
  33. data/ProjectTox-Core/testing/nTox_win32.c +323 -0
  34. data/ProjectTox-Core/testing/nTox_win32.h +31 -0
  35. data/ProjectTox-Core/testing/rect.py +45 -0
  36. data/ext/ffi-tox/extconf.rb +16 -0
  37. data/interfaces/libtox.i +18 -0
  38. data/lib/ffi-tox/libtox.rb +37 -0
  39. data/lib/ffi-tox.rb +1 -0
  40. metadata +116 -0
@@ -0,0 +1,564 @@
1
+ /* net_crypto.c
2
+ *
3
+ * Functions for the core network crypto.
4
+ * See also: docs/Crypto.txt
5
+ *
6
+ * NOTE: This code has to be perfect. We don't mess around with encryption.
7
+ *
8
+ * Copyright (C) 2013 Tox project All Rights Reserved.
9
+ *
10
+ * This file is part of Tox.
11
+ *
12
+ * Tox is free software: you can redistribute it and/or modify
13
+ * it under the terms of the GNU General Public License as published by
14
+ * the Free Software Foundation, either version 3 of the License, or
15
+ * (at your option) any later version.
16
+ *
17
+ * Tox is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
+ * GNU General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU General Public License
23
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
24
+ *
25
+ */
26
+
27
+ #include "net_crypto.h"
28
+
29
+ /* Our public and secret keys. */
30
+ uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
31
+ uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
32
+
33
+ typedef struct {
34
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES]; /* the real public key of the peer. */
35
+ uint8_t recv_nonce[crypto_box_NONCEBYTES]; /* nonce of received packets */
36
+ uint8_t sent_nonce[crypto_box_NONCEBYTES]; /* nonce of sent packets. */
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. */
39
+ uint8_t peersessionpublic_key[crypto_box_PUBLICKEYBYTES]; /* The public key of the peer. */
40
+ 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
+ 4 if the connection is timed out. */
43
+ uint16_t number; /* Lossless_UDP connection number corresponding to this connection. */
44
+
45
+ } Crypto_Connection;
46
+
47
+ #define MAX_CRYPTO_CONNECTIONS 256
48
+
49
+ static Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS];
50
+
51
+ #define MAX_INCOMING 64
52
+
53
+ /* keeps track of the connection numbers for friends request so we can check later if they were sent */
54
+ static int incoming_connections[MAX_INCOMING];
55
+
56
+ /* encrypts plain of length length to encrypted of length + 16 using the
57
+ public key(32 bytes) of the receiver and the secret key of the sender and a 24 byte nonce
58
+ return -1 if there was a problem.
59
+ return length of encrypted data if everything was fine. */
60
+ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
61
+ uint8_t *plain, uint32_t length, uint8_t *encrypted)
62
+ {
63
+ if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0)
64
+ return -1;
65
+
66
+ uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0};
67
+ uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES];
68
+ uint8_t zeroes[crypto_box_BOXZEROBYTES] = {0};
69
+
70
+ memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length); /* pad the message with 32 0 bytes. */
71
+
72
+ crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, secret_key);
73
+
74
+ /* if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero */
75
+ if (memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0)
76
+ return -1;
77
+
78
+ /* unpad the encrypted message */
79
+ memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
80
+ return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
81
+ }
82
+
83
+ /* decrypts encrypted of length length to plain of length length - 16 using the
84
+ public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce
85
+ return -1 if there was a problem(decryption failed)
86
+ return length of plain data if everything was fine. */
87
+ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
88
+ uint8_t *encrypted, uint32_t length, uint8_t *plain)
89
+ {
90
+ if (length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
91
+ return -1;
92
+
93
+ uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES];
94
+ uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0};
95
+ uint8_t zeroes[crypto_box_ZEROBYTES] = {0};
96
+
97
+ memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length); /* pad the message with 16 0 bytes. */
98
+
99
+ if (crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES,
100
+ nonce, public_key, secret_key) == -1)
101
+ return -1;
102
+
103
+ /* if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero */
104
+ if (memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0)
105
+ return -1;
106
+
107
+ /* unpad the plain message */
108
+ memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES);
109
+ return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
110
+ }
111
+
112
+ /* increment the given nonce by 1 */
113
+ void increment_nonce(uint8_t *nonce)
114
+ {
115
+ uint32_t i;
116
+ for (i = 0; i < crypto_box_NONCEBYTES; ++i) {
117
+ ++nonce[i];
118
+ if(nonce[i] != 0)
119
+ break;
120
+ }
121
+ }
122
+
123
+ /* fill the given nonce with random bytes. */
124
+ void random_nonce(uint8_t *nonce)
125
+ {
126
+ uint32_t i, temp;
127
+ for (i = 0; i < crypto_box_NONCEBYTES / 4; ++i) {
128
+ temp = random_int();
129
+ memcpy(nonce + 4 * i, &temp, 4);
130
+ }
131
+ }
132
+
133
+ /* return 0 if there is no received data in the buffer
134
+ return -1 if the packet was discarded.
135
+ return length of received data if successful */
136
+ int read_cryptpacket(int crypt_connection_id, uint8_t *data)
137
+ {
138
+ if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
139
+ return 0;
140
+ if (crypto_connections[crypt_connection_id].status != 3)
141
+ return 0;
142
+ uint8_t temp_data[MAX_DATA_SIZE];
143
+ int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
144
+ if (length == 0)
145
+ return 0;
146
+ if (temp_data[0] != 3)
147
+ return -1;
148
+ int len = decrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
149
+ crypto_connections[crypt_connection_id].sessionsecret_key,
150
+ crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data);
151
+ if (len != -1) {
152
+ increment_nonce(crypto_connections[crypt_connection_id].recv_nonce);
153
+ return len;
154
+ }
155
+ return -1;
156
+ }
157
+
158
+ /* return 0 if data could not be put in packet queue
159
+ return 1 if data was put into the queue */
160
+ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length)
161
+ {
162
+ if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
163
+ return 0;
164
+ if (length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
165
+ return 0;
166
+ if (crypto_connections[crypt_connection_id].status != 3)
167
+ return 0;
168
+ uint8_t temp_data[MAX_DATA_SIZE];
169
+ int len = encrypt_data(crypto_connections[crypt_connection_id].peersessionpublic_key,
170
+ crypto_connections[crypt_connection_id].sessionsecret_key,
171
+ crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1);
172
+ if (len == -1)
173
+ return 0;
174
+ temp_data[0] = 3;
175
+ if (write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
176
+ return 0;
177
+ increment_nonce(crypto_connections[crypt_connection_id].sent_nonce);
178
+ return 1;
179
+ }
180
+
181
+ /* create a request to peer with public_key.
182
+ packet must be an array of MAX_DATA_SIZE big.
183
+ Data represents the data we send with the request with length being the length of the data.
184
+ request_id is the id of the request (32 = friend request, 254 = ping request)
185
+ returns -1 on failure
186
+ returns the length of the created packet on success */
187
+ int create_request(uint8_t *packet, uint8_t *public_key, uint8_t *data, uint32_t length, uint8_t request_id)
188
+ {
189
+ if (MAX_DATA_SIZE < length + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + ENCRYPTION_PADDING)
190
+ return -1;
191
+ uint8_t nonce[crypto_box_NONCEBYTES];
192
+ random_nonce(nonce);
193
+ int len = encrypt_data(public_key, self_secret_key, nonce, data, length,
194
+ 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + packet);
195
+ if (len == -1)
196
+ return -1;
197
+ packet[0] = request_id;
198
+ memcpy(packet + 1, public_key, crypto_box_PUBLICKEYBYTES);
199
+ memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES, self_public_key, crypto_box_PUBLICKEYBYTES);
200
+ memcpy(packet + 1 + crypto_box_PUBLICKEYBYTES * 2, nonce, crypto_box_NONCEBYTES);
201
+
202
+ return len + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES;
203
+ }
204
+
205
+ /* puts the senders public key in the request in public_key, the data from the request
206
+ in data if a friend or ping request was sent to us and returns the length of the data.
207
+ packet is the request packet and length is its length
208
+ return -1 if not valid request. */
209
+ int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t length)
210
+ {
211
+
212
+ if (length > crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1 + ENCRYPTION_PADDING &&
213
+ length <= MAX_DATA_SIZE + ENCRYPTION_PADDING &&
214
+ memcmp(packet + 1, self_public_key, crypto_box_PUBLICKEYBYTES) == 0) {
215
+ memcpy(public_key, packet + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_PUBLICKEYBYTES);
216
+ uint8_t nonce[crypto_box_NONCEBYTES];
217
+ memcpy(nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2, crypto_box_NONCEBYTES);
218
+ int len1 = decrypt_data(public_key, self_secret_key, nonce, packet + 1 + crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES,
219
+ length - (crypto_box_PUBLICKEYBYTES * 2 + crypto_box_NONCEBYTES + 1), data);
220
+ if(len1 == -1)
221
+ return -1;
222
+ return len1;
223
+ } else
224
+ return -1;
225
+ }
226
+
227
+ /* Send a crypto handshake packet containing an encrypted secret nonce and session public key
228
+ to peer with connection_id and public_key
229
+ the packet is encrypted with a random nonce which is sent in plain text with the packet */
230
+ int send_cryptohandshake(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
231
+ {
232
+ uint8_t temp_data[MAX_DATA_SIZE];
233
+ uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
234
+ uint8_t nonce[crypto_box_NONCEBYTES];
235
+
236
+ random_nonce(nonce);
237
+ memcpy(temp, secret_nonce, crypto_box_NONCEBYTES);
238
+ memcpy(temp + crypto_box_NONCEBYTES, session_key, crypto_box_PUBLICKEYBYTES);
239
+
240
+ int len = encrypt_data(public_key, self_secret_key, nonce, temp, crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES,
241
+ 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
242
+ if (len == -1)
243
+ return 0;
244
+ temp_data[0] = 2;
245
+ memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES);
246
+ memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
247
+ return write_packet(connection_id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
248
+ }
249
+
250
+ /* Extract secret nonce, session public key and public_key from a packet(data) with length length
251
+ return 1 if successful
252
+ return 0 if failure */
253
+ int handle_cryptohandshake(uint8_t *public_key, uint8_t *secret_nonce,
254
+ uint8_t *session_key, uint8_t *data, uint16_t length)
255
+ {
256
+ int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
257
+ if (length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES
258
+ + crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad) {
259
+ return 0;
260
+ }
261
+ if (data[0] != 2)
262
+ return 0;
263
+ uint8_t temp[crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES];
264
+
265
+ memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES);
266
+
267
+ int len = decrypt_data(public_key, self_secret_key, data + 1 + crypto_box_PUBLICKEYBYTES,
268
+ data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
269
+ crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES + pad, temp);
270
+
271
+ if (len != crypto_box_NONCEBYTES + crypto_box_PUBLICKEYBYTES)
272
+ return 0;
273
+
274
+ memcpy(secret_nonce, temp, crypto_box_NONCEBYTES);
275
+ memcpy(session_key, temp + crypto_box_NONCEBYTES, crypto_box_PUBLICKEYBYTES);
276
+ return 1;
277
+ }
278
+
279
+ /* get crypto connection id from public key of peer
280
+ return -1 if there are no connections like we are looking for
281
+ return id if it found it */
282
+ int getcryptconnection_id(uint8_t *public_key)
283
+ {
284
+ uint32_t i;
285
+ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
286
+ if (crypto_connections[i].status > 0)
287
+ if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
288
+ return i;
289
+ }
290
+ return -1;
291
+ }
292
+
293
+ /* Start a secure connection with other peer who has public_key and ip_port
294
+ returns -1 if failure
295
+ returns crypt_connection_id of the initialized connection if everything went well. */
296
+ int crypto_connect(uint8_t *public_key, IP_Port ip_port)
297
+ {
298
+ uint32_t i;
299
+ int id = getcryptconnection_id(public_key);
300
+ if (id != -1) {
301
+ IP_Port c_ip = connection_ip(crypto_connections[id].number);
302
+ if(c_ip.ip.i == ip_port.ip.i && c_ip.port == ip_port.port)
303
+ return -1;
304
+ }
305
+ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
306
+ if (crypto_connections[i].status == 0) {
307
+ int id = new_connection(ip_port);
308
+ if (id == -1)
309
+ return -1;
310
+ crypto_connections[i].number = id;
311
+ crypto_connections[i].status = 1;
312
+ random_nonce(crypto_connections[i].recv_nonce);
313
+ memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
314
+ crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);
315
+
316
+ if (send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce,
317
+ crypto_connections[i].sessionpublic_key) == 1) {
318
+ increment_nonce(crypto_connections[i].recv_nonce);
319
+ return i;
320
+ }
321
+ return -1; /* this should never happen. */
322
+ }
323
+ }
324
+ return -1;
325
+ }
326
+
327
+ /* handle an incoming connection
328
+ return -1 if no crypto inbound connection
329
+ return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection
330
+ Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
331
+ and the session public key for the connection in session_key
332
+ to accept it see: accept_crypto_inbound(...)
333
+ to refuse it just call kill_connection(...) on the connection id */
334
+ int crypto_inbound(uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
335
+ {
336
+ uint32_t i;
337
+ for (i = 0; i < MAX_INCOMING; ++i) {
338
+ if (incoming_connections[i] != -1) {
339
+ if (is_connected(incoming_connections[i]) == 4 || is_connected(incoming_connections[i]) == 0) {
340
+ kill_connection(incoming_connections[i]);
341
+ incoming_connections[i] = -1;
342
+ continue;
343
+ }
344
+ if (id_packet(incoming_connections[i]) == 2) {
345
+ uint8_t temp_data[MAX_DATA_SIZE];
346
+ uint16_t len = read_packet(incoming_connections[i], temp_data);
347
+ if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) {
348
+ int connection_id = incoming_connections[i];
349
+ incoming_connections[i] = -1; /* remove this connection from the incoming connection list. */
350
+ return connection_id;
351
+ }
352
+ }
353
+ }
354
+ }
355
+ return -1;
356
+ }
357
+
358
+ /* kill a crypto connection
359
+ return 0 if killed successfully
360
+ return 1 if there was a problem. */
361
+ int crypto_kill(int crypt_connection_id)
362
+ {
363
+ if (crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
364
+ return 1;
365
+ if (crypto_connections[crypt_connection_id].status != 0) {
366
+ crypto_connections[crypt_connection_id].status = 0;
367
+ kill_connection(crypto_connections[crypt_connection_id].number);
368
+ crypto_connections[crypt_connection_id].number = ~0;
369
+ return 0;
370
+ }
371
+ return 1;
372
+ }
373
+
374
+ /* accept an incoming connection using the parameters provided by crypto_inbound
375
+ return -1 if not successful
376
+ returns the crypt_connection_id if successful */
377
+ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t *secret_nonce, uint8_t *session_key)
378
+ {
379
+ uint32_t i;
380
+ if (connection_id == -1)
381
+ return -1;
382
+ /*
383
+ if(getcryptconnection_id(public_key) != -1)
384
+ {
385
+ return -1;
386
+ }*/
387
+ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
388
+ if(crypto_connections[i].status == 0) {
389
+ crypto_connections[i].number = connection_id;
390
+ crypto_connections[i].status = 2;
391
+ random_nonce(crypto_connections[i].recv_nonce);
392
+ memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
393
+ memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
394
+ increment_nonce(crypto_connections[i].sent_nonce);
395
+ memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
396
+
397
+ crypto_box_keypair(crypto_connections[i].sessionpublic_key, crypto_connections[i].sessionsecret_key);
398
+
399
+ if (send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce,
400
+ crypto_connections[i].sessionpublic_key) == 1) {
401
+ increment_nonce(crypto_connections[i].recv_nonce);
402
+ uint32_t zero = 0;
403
+ crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */
404
+ write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
405
+ crypto_connections[i].status = 2; /* set it to its proper value right after. */
406
+ return i;
407
+ }
408
+ return -1; /* this should never happen. */
409
+ }
410
+ }
411
+ return -1;
412
+ }
413
+
414
+ /* return 0 if no connection, 1 we have sent a handshake, 2 if connection is not confirmed yet
415
+ (we have received a handshake but no empty data packet), 3 if the connection is established.
416
+ 4 if the connection is timed out and waiting to be killed */
417
+ int is_cryptoconnected(int crypt_connection_id)
418
+ {
419
+ if (crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS)
420
+ return crypto_connections[crypt_connection_id].status;
421
+ return 0;
422
+ }
423
+
424
+ /* Generate our public and private keys
425
+ Only call this function the first time the program starts. */
426
+ void new_keys()
427
+ {
428
+ crypto_box_keypair(self_public_key,self_secret_key);
429
+ }
430
+
431
+ /* save the public and private keys to the keys array
432
+ Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
433
+ void save_keys(uint8_t *keys)
434
+ {
435
+ memcpy(keys, self_public_key, crypto_box_PUBLICKEYBYTES);
436
+ memcpy(keys + crypto_box_PUBLICKEYBYTES, self_secret_key, crypto_box_SECRETKEYBYTES);
437
+ }
438
+
439
+ /* load the public and private keys from the keys array
440
+ Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
441
+ void load_keys(uint8_t *keys)
442
+ {
443
+ memcpy(self_public_key, keys, crypto_box_PUBLICKEYBYTES);
444
+ memcpy(self_secret_key, keys + crypto_box_PUBLICKEYBYTES, crypto_box_SECRETKEYBYTES);
445
+ }
446
+
447
+ /* TODO: optimize this
448
+ adds an incoming connection to the incoming_connection list.
449
+ returns 0 if successful
450
+ returns 1 if failure */
451
+ int new_incoming(int id)
452
+ {
453
+ uint32_t i;
454
+ for (i = 0; i < MAX_INCOMING; ++i) {
455
+ if (incoming_connections[i] == -1) {
456
+ incoming_connections[i] = id;
457
+ return 0;
458
+ }
459
+ }
460
+ return 1;
461
+ }
462
+
463
+ /* TODO: optimize this
464
+ handle all new incoming connections. */
465
+ static void handle_incomings()
466
+ {
467
+ int income;
468
+ while (1) {
469
+ income = incoming_connection();
470
+ if(income == -1 || new_incoming(income) )
471
+ break;
472
+ }
473
+ }
474
+
475
+ /* handle received packets for not yet established crypto connections. */
476
+ static void receive_crypto()
477
+ {
478
+ uint32_t i;
479
+ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
480
+ if (crypto_connections[i].status == 1) {
481
+ uint8_t temp_data[MAX_DATA_SIZE];
482
+ uint8_t secret_nonce[crypto_box_NONCEBYTES];
483
+ uint8_t public_key[crypto_box_PUBLICKEYBYTES];
484
+ uint8_t session_key[crypto_box_PUBLICKEYBYTES];
485
+ uint16_t len;
486
+ if (id_packet(crypto_connections[i].number) == 1)
487
+ /* if the packet is a friend request drop it (because we are already friends) */
488
+ len = read_packet(crypto_connections[i].number, temp_data);
489
+ if (id_packet(crypto_connections[i].number) == 2) { /* handle handshake packet. */
490
+ len = read_packet(crypto_connections[i].number, temp_data);
491
+ if (handle_cryptohandshake(public_key, secret_nonce, session_key, temp_data, len)) {
492
+ if (memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0) {
493
+ memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
494
+ memcpy(crypto_connections[i].peersessionpublic_key, session_key, crypto_box_PUBLICKEYBYTES);
495
+ increment_nonce(crypto_connections[i].sent_nonce);
496
+ uint32_t zero = 0;
497
+ crypto_connections[i].status = 3; /* connection status needs to be 3 for write_cryptpacket() to work */
498
+ write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
499
+ crypto_connections[i].status = 2; /* set it to its proper value right after. */
500
+ }
501
+ }
502
+ } else if (id_packet(crypto_connections[i].number) != -1) // This should not happen kill the connection if it does
503
+ crypto_kill(crypto_connections[i].number);
504
+
505
+ }
506
+ if (crypto_connections[i].status == 2) {
507
+ if (id_packet(crypto_connections[i].number) == 3) {
508
+ uint8_t temp_data[MAX_DATA_SIZE];
509
+ uint8_t data[MAX_DATA_SIZE];
510
+ int length = read_packet(crypto_connections[i].number, temp_data);
511
+ int len = decrypt_data(crypto_connections[i].peersessionpublic_key,
512
+ crypto_connections[i].sessionsecret_key,
513
+ crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
514
+ uint32_t zero = 0;
515
+ if (len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0) {
516
+ increment_nonce(crypto_connections[i].recv_nonce);
517
+ crypto_connections[i].status = 3;
518
+
519
+ /* connection is accepted so we disable the auto kill by setting it to about 1 month from now. */
520
+ kill_connection_in(crypto_connections[i].number, 3000000);
521
+ } else
522
+ crypto_kill(crypto_connections[i].number); // This should not happen kill the connection if it does
523
+ } else if(id_packet(crypto_connections[i].number) != -1)
524
+ /* This should not happen
525
+ kill the connection if it does */
526
+ crypto_kill(crypto_connections[i].number);
527
+ }
528
+ }
529
+ }
530
+
531
+ /* run this to (re)initialize net_crypto
532
+ sets all the global connection variables to their default values. */
533
+ void initNetCrypto()
534
+ {
535
+ memset(crypto_connections, 0 ,sizeof(crypto_connections));
536
+ memset(incoming_connections, -1 ,sizeof(incoming_connections));
537
+ uint32_t i;
538
+ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i)
539
+ crypto_connections[i].number = ~0;
540
+ }
541
+
542
+ static void killTimedout()
543
+ {
544
+ uint32_t i;
545
+ for (i = 0; i < MAX_CRYPTO_CONNECTIONS; ++i) {
546
+ if (crypto_connections[i].status != 0 && is_connected(crypto_connections[i].number) == 4)
547
+ crypto_connections[i].status = 4;
548
+ else if (is_connected(crypto_connections[i].number) == 4) {
549
+ kill_connection(crypto_connections[i].number);
550
+ crypto_connections[i].number = ~0;
551
+ }
552
+ }
553
+ }
554
+
555
+ /* main loop */
556
+ void doNetCrypto()
557
+ {
558
+ /* TODO:check if friend requests were sent correctly
559
+ handle new incoming connections
560
+ handle friend requests */
561
+ handle_incomings();
562
+ receive_crypto();
563
+ killTimedout();
564
+ }
@@ -0,0 +1,134 @@
1
+ /* net_crypto.h
2
+ *
3
+ * Functions for the core network crypto.
4
+ *
5
+ * Copyright (C) 2013 Tox project All Rights Reserved.
6
+ *
7
+ * This file is part of Tox.
8
+ *
9
+ * Tox is free software: you can redistribute it and/or modify
10
+ * it under the terms of the GNU General Public License as published by
11
+ * the Free Software Foundation, either version 3 of the License, or
12
+ * (at your option) any later version.
13
+ *
14
+ * Tox is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
+ * GNU General Public License for more details.
18
+ *
19
+ * You should have received a copy of the GNU General Public License
20
+ * along with Tox. If not, see <http://www.gnu.org/licenses/>.
21
+ *
22
+ */
23
+
24
+ #ifndef NET_CRYPTO_H
25
+ #define NET_CRYPTO_H
26
+
27
+ #include "Lossless_UDP.h"
28
+
29
+ #ifdef __cplusplus
30
+ extern "C" {
31
+ #endif
32
+
33
+ /* Our public key. */
34
+ extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
35
+ extern uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
36
+
37
+ #define ENCRYPTION_PADDING (crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES)
38
+
39
+ /* 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
41
+ return -1 if there was a problem.
42
+ return length of encrypted data if everything was fine. */
43
+ int encrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
44
+ uint8_t *plain, uint32_t length, uint8_t *encrypted);
45
+
46
+
47
+ /* decrypts encrypted of length length to plain of length length - 16 using the
48
+ public key(32 bytes) of the sender, the secret key of the receiver and a 24 byte nonce
49
+ return -1 if there was a problem(decryption failed)
50
+ return length of plain data if everything was fine. */
51
+ int decrypt_data(uint8_t *public_key, uint8_t *secret_key, uint8_t *nonce,
52
+ uint8_t *encrypted, uint32_t length, uint8_t *plain);
53
+
54
+
55
+ /* fill the given nonce with random bytes. */
56
+ void random_nonce(uint8_t *nonce);
57
+
58
+ /* return 0 if there is no received data in the buffer
59
+ return -1 if the packet was discarded.
60
+ return length of received data if successful */
61
+ int read_cryptpacket(int crypt_connection_id, uint8_t *data);
62
+
63
+ /* return 0 if data could not be put in packet queue
64
+ return 1 if data was put into the queue */
65
+ int write_cryptpacket(int crypt_connection_id, uint8_t *data, uint32_t length);
66
+
67
+ /* create a request to peer with public_key.
68
+ packet must be an array of MAX_DATA_SIZE big.
69
+ Data represents the data we send with the request with length being the length of the data.
70
+ request_id is the id of the request (32 = friend request, 254 = ping request)
71
+ returns -1 on failure
72
+ returns the length of the created packet on success */
73
+ int create_request(uint8_t *packet, uint8_t * public_key, uint8_t *data, uint32_t length, uint8_t request_id);
74
+
75
+ /* puts the senders public key in the request in public_key, the data from the request
76
+ in data if a friend or ping request was sent to us and returns the length of the data.
77
+ packet is the request packet and length is its length
78
+ return -1 if not valid request. */
79
+ int handle_request(uint8_t *public_key, uint8_t *data, uint8_t *packet, uint16_t length);
80
+
81
+ /* Start a secure connection with other peer who has public_key and ip_port
82
+ returns -1 if failure
83
+ returns crypt_connection_id of the initialized connection if everything went well. */
84
+ int crypto_connect(uint8_t *public_key, IP_Port ip_port);
85
+
86
+ /* kill a crypto connection
87
+ return 0 if killed successfully
88
+ return 1 if there was a problem. */
89
+ int crypto_kill(int crypt_connection_id);
90
+
91
+ /* handle an incoming connection
92
+ return -1 if no crypto inbound connection
93
+ return incoming connection id (Lossless_UDP one) if there is an incoming crypto connection
94
+ Put the public key of the peer in public_key, the secret_nonce from the handshake into secret_nonce
95
+ and the session public key for the connection in session_key
96
+ to accept it see: accept_crypto_inbound(...)
97
+ to refuse it just call kill_connection(...) on the connection id */
98
+ int crypto_inbound(uint8_t *public_key, uint8_t * secret_nonce, uint8_t *session_key);
99
+
100
+ /* accept an incoming connection using the parameters provided by crypto_inbound
101
+ return -1 if not successful
102
+ returns the crypt_connection_id if successful */
103
+ int accept_crypto_inbound(int connection_id, uint8_t *public_key, uint8_t * secret_nonce, uint8_t *session_key);
104
+
105
+ /* return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
106
+ (we have received a handshake but no empty data packet), 3 if the connection is established.
107
+ 4 if the connection is timed out and waiting to be killed */
108
+ int is_cryptoconnected(int crypt_connection_id);
109
+
110
+
111
+ /* Generate our public and private keys
112
+ Only call this function the first time the program starts. */
113
+ void new_keys();
114
+
115
+ /* save the public and private keys to the keys array
116
+ Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
117
+ void save_keys(uint8_t * keys);
118
+
119
+ /* load the public and private keys from the keys array
120
+ Length must be crypto_box_PUBLICKEYBYTES + crypto_box_SECRETKEYBYTES */
121
+ void load_keys(uint8_t * keys);
122
+
123
+ /* run this to (re)initialize net_crypto
124
+ sets all the global connection variables to their default values. */
125
+ void initNetCrypto();
126
+
127
+ /* main loop */
128
+ void doNetCrypto();
129
+
130
+ #ifdef __cplusplus
131
+ }
132
+ #endif
133
+
134
+ #endif