summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorirungentoo <irungentoo@gmail.com>2013-07-05 17:00:39 -0400
committerirungentoo <irungentoo@gmail.com>2013-07-05 17:00:39 -0400
commita480c0195a78f56116b3bf58fe17d930bf4e64f4 (patch)
treec549b6347e28b8570ed27b5c53b768b8f7b11a61
parent358f46f6483f0c24186272914952e44221c76871 (diff)
Crypto done(still need to test it a bit more thought)
Replaced chars with uint8_t Added a new test program. Added some functions to Lossless UDP. And some other stuff.
-rw-r--r--core/DHT.c44
-rw-r--r--core/DHT.h16
-rw-r--r--core/Lossless_UDP.c65
-rw-r--r--core/Lossless_UDP.h19
-rw-r--r--core/net_crypto.c622
-rw-r--r--core/net_crypto.h108
-rw-r--r--core/network.c8
-rw-r--r--core/network.h4
-rw-r--r--testing/DHT_cryptosendfiletest.c251
-rw-r--r--testing/DHT_test.c6
10 files changed, 1087 insertions, 56 deletions
diff --git a/core/DHT.c b/core/DHT.c
index 5c63146f..d5af3a08 100644
--- a/core/DHT.c
+++ b/core/DHT.c
@@ -27,13 +27,13 @@
27 27
28#include "DHT.h" 28#include "DHT.h"
29 29
30char self_client_id[CLIENT_ID_SIZE]; 30uint8_t self_client_id[CLIENT_ID_SIZE];
31 31
32//Compares client_id1 and client_id2 with client_id 32//Compares client_id1 and client_id2 with client_id
33//return 0 if both are same distance 33//return 0 if both are same distance
34//return 1 if client_id1 is closer. 34//return 1 if client_id1 is closer.
35//return 2 if client_id2 is closer. 35//return 2 if client_id2 is closer.
36int id_closest(char * client_id, char * client_id1, char * client_id2)//tested 36int id_closest(uint8_t * client_id, uint8_t * client_id1, uint8_t * client_id2)//tested
37{ 37{
38 uint32_t i; 38 uint32_t i;
39 for(i = 0; i < CLIENT_ID_SIZE; i++) 39 for(i = 0; i < CLIENT_ID_SIZE; i++)
@@ -58,7 +58,7 @@ int id_closest(char * client_id, char * client_id1, char * client_id2)//tested
58//if the ip_port is already in the list but associated to a different ip, change it. 58//if the ip_port is already in the list but associated to a different ip, change it.
59//return True(1) or False(0) 59//return True(1) or False(0)
60//TODO: maybe optimize this. 60//TODO: maybe optimize this.
61int client_in_list(Client_data * list, uint32_t length, char * client_id, IP_Port ip_port) 61int client_in_list(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port)
62{ 62{
63 uint32_t i, j; 63 uint32_t i, j;
64 uint32_t temp_time = unix_time(); 64 uint32_t temp_time = unix_time();
@@ -92,7 +92,7 @@ int client_in_list(Client_data * list, uint32_t length, char * client_id, IP_Por
92 92
93//check if client with client_id is already in node format list of length length. 93//check if client with client_id is already in node format list of length length.
94//return True(1) or False(0) 94//return True(1) or False(0)
95int client_in_nodelist(Node_format * list, uint32_t length, char * client_id) 95int client_in_nodelist(Node_format * list, uint32_t length, uint8_t * client_id)
96{ 96{
97 uint32_t i, j; 97 uint32_t i, j;
98 for(i = 0; i < length; i++) 98 for(i = 0; i < length; i++)
@@ -126,7 +126,7 @@ int client_in_nodelist(Node_format * list, uint32_t length, char * client_id)
126//Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request: 126//Find MAX_SENT_NODES nodes closest to the client_id for the send nodes request:
127//put them in the nodes_list and return how many were found. 127//put them in the nodes_list and return how many were found.
128//TODO: Make this function much more efficient. 128//TODO: Make this function much more efficient.
129int get_close_nodes(char * client_id, Node_format * nodes_list) 129int get_close_nodes(uint8_t * client_id, Node_format * nodes_list)
130{ 130{
131 uint32_t i, j, k; 131 uint32_t i, j, k;
132 int num_nodes=0; 132 int num_nodes=0;
@@ -191,7 +191,7 @@ int get_close_nodes(char * client_id, Node_format * nodes_list)
191//replace first bad (or empty) node with this one 191//replace first bad (or empty) node with this one
192//return 0 if successfull 192//return 0 if successfull
193//return 1 if not (list contains no bad nodes) 193//return 1 if not (list contains no bad nodes)
194int replace_bad(Client_data * list, uint32_t length, char * client_id, IP_Port ip_port)//tested 194int replace_bad(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port)//tested
195{ 195{
196 uint32_t i; 196 uint32_t i;
197 uint32_t temp_time = unix_time(); 197 uint32_t temp_time = unix_time();
@@ -210,7 +210,7 @@ int replace_bad(Client_data * list, uint32_t length, char * client_id, IP_Port i
210} 210}
211 211
212//replace the first good node that is further to the comp_client_id than that of the client_id in the list 212//replace the first good node that is further to the comp_client_id than that of the client_id in the list
213int replace_good(Client_data * list, uint32_t length, char * client_id, IP_Port ip_port, char * comp_client_id) 213int replace_good(Client_data * list, uint32_t length, uint8_t * client_id, IP_Port ip_port, uint8_t * comp_client_id)
214{ 214{
215 uint32_t i; 215 uint32_t i;
216 uint32_t temp_time = unix_time(); 216 uint32_t temp_time = unix_time();
@@ -230,7 +230,7 @@ int replace_good(Client_data * list, uint32_t length, char * client_id, IP_Port
230} 230}
231 231
232//Attempt to add client with ip_port and client_id to the friends client list and close_clientlist 232//Attempt to add client with ip_port and client_id to the friends client list and close_clientlist
233void addto_lists(IP_Port ip_port, char * client_id) 233void addto_lists(IP_Port ip_port, uint8_t * client_id)
234{ 234{
235 uint32_t i; 235 uint32_t i;
236 236
@@ -414,7 +414,7 @@ int pingreq(IP_Port ip_port)
414 return 1; 414 return 1;
415 } 415 }
416 416
417 char data[5 + CLIENT_ID_SIZE]; 417 uint8_t data[5 + CLIENT_ID_SIZE];
418 data[0] = 0; 418 data[0] = 0;
419 memcpy(data + 1, &ping_id, 4); 419 memcpy(data + 1, &ping_id, 4);
420 memcpy(data + 5, self_client_id, CLIENT_ID_SIZE); 420 memcpy(data + 5, self_client_id, CLIENT_ID_SIZE);
@@ -427,7 +427,7 @@ int pingreq(IP_Port ip_port)
427//send a ping response 427//send a ping response
428int pingres(IP_Port ip_port, uint32_t ping_id) 428int pingres(IP_Port ip_port, uint32_t ping_id)
429{ 429{
430 char data[5 + CLIENT_ID_SIZE]; 430 uint8_t data[5 + CLIENT_ID_SIZE];
431 data[0] = 1; 431 data[0] = 1;
432 432
433 memcpy(data + 1, &ping_id, 4); 433 memcpy(data + 1, &ping_id, 4);
@@ -438,7 +438,7 @@ int pingres(IP_Port ip_port, uint32_t ping_id)
438} 438}
439 439
440//send a getnodes request 440//send a getnodes request
441int getnodes(IP_Port ip_port, char * client_id) 441int getnodes(IP_Port ip_port, uint8_t * client_id)
442{ 442{
443 if(is_gettingnodes(ip_port, 0)) 443 if(is_gettingnodes(ip_port, 0))
444 { 444 {
@@ -452,7 +452,7 @@ int getnodes(IP_Port ip_port, char * client_id)
452 return 1; 452 return 1;
453 } 453 }
454 454
455 char data[5 + CLIENT_ID_SIZE*2]; 455 uint8_t data[5 + CLIENT_ID_SIZE*2];
456 data[0] = 2; 456 data[0] = 2;
457 457
458 memcpy(data + 1, &ping_id, 4); 458 memcpy(data + 1, &ping_id, 4);
@@ -465,9 +465,9 @@ int getnodes(IP_Port ip_port, char * client_id)
465 465
466 466
467//send a send nodes response 467//send a send nodes response
468int sendnodes(IP_Port ip_port, char * client_id, uint32_t ping_id) 468int sendnodes(IP_Port ip_port, uint8_t * client_id, uint32_t ping_id)
469{ 469{
470 char data[5 + CLIENT_ID_SIZE + (CLIENT_ID_SIZE + sizeof(IP_Port))*MAX_SENT_NODES]; 470 uint8_t data[5 + CLIENT_ID_SIZE + (CLIENT_ID_SIZE + sizeof(IP_Port))*MAX_SENT_NODES];
471 Node_format nodes_list[MAX_SENT_NODES]; 471 Node_format nodes_list[MAX_SENT_NODES];
472 472
473 int num_nodes = get_close_nodes(client_id, nodes_list); 473 int num_nodes = get_close_nodes(client_id, nodes_list);
@@ -493,7 +493,7 @@ int sendnodes(IP_Port ip_port, char * client_id, uint32_t ping_id)
493//Packet handling functions 493//Packet handling functions
494//One to handle each types of packets we recieve 494//One to handle each types of packets we recieve
495//return 0 if handled correctly, 1 if packet is bad. 495//return 0 if handled correctly, 1 if packet is bad.
496int handle_pingreq(char * packet, uint32_t length, IP_Port source)//tested 496int handle_pingreq(uint8_t * packet, uint32_t length, IP_Port source)//tested
497{ 497{
498 if(length != 5 + CLIENT_ID_SIZE) 498 if(length != 5 + CLIENT_ID_SIZE)
499 { 499 {
@@ -518,7 +518,7 @@ int handle_pingreq(char * packet, uint32_t length, IP_Port source)//tested
518 518
519} 519}
520 520
521int handle_pingres(char * packet, uint32_t length, IP_Port source) 521int handle_pingres(uint8_t * packet, uint32_t length, IP_Port source)
522{ 522{
523 if(length != (5 + CLIENT_ID_SIZE)) 523 if(length != (5 + CLIENT_ID_SIZE))
524 { 524 {
@@ -536,7 +536,7 @@ int handle_pingres(char * packet, uint32_t length, IP_Port source)
536 536
537} 537}
538 538
539int handle_getnodes(char * packet, uint32_t length, IP_Port source) 539int handle_getnodes(uint8_t * packet, uint32_t length, IP_Port source)
540{ 540{
541 if(length != (5 + CLIENT_ID_SIZE*2)) 541 if(length != (5 + CLIENT_ID_SIZE*2))
542 { 542 {
@@ -559,7 +559,7 @@ int handle_getnodes(char * packet, uint32_t length, IP_Port source)
559 559
560} 560}
561 561
562int handle_sendnodes(char * packet, uint32_t length, IP_Port source)//tested 562int handle_sendnodes(uint8_t * packet, uint32_t length, IP_Port source)//tested
563{ 563{
564 if(length > (5 + CLIENT_ID_SIZE + MAX_SENT_NODES * (CLIENT_ID_SIZE + sizeof(IP_Port))) || 564 if(length > (5 + CLIENT_ID_SIZE + MAX_SENT_NODES * (CLIENT_ID_SIZE + sizeof(IP_Port))) ||
565 (length - 5 - CLIENT_ID_SIZE) % (CLIENT_ID_SIZE + sizeof(IP_Port)) != 0) 565 (length - 5 - CLIENT_ID_SIZE) % (CLIENT_ID_SIZE + sizeof(IP_Port)) != 0)
@@ -593,7 +593,7 @@ int handle_sendnodes(char * packet, uint32_t length, IP_Port source)//tested
593 593
594 594
595 595
596int addfriend(char * client_id) 596int addfriend(uint8_t * client_id)
597{ 597{
598 //TODO:Maybe make the array of friends dynamic instead of a static array with MAX_FRIENDS 598 //TODO:Maybe make the array of friends dynamic instead of a static array with MAX_FRIENDS
599 if(MAX_FRIENDS > num_friends) 599 if(MAX_FRIENDS > num_friends)
@@ -610,7 +610,7 @@ int addfriend(char * client_id)
610 610
611 611
612 612
613int delfriend(char * client_id) 613int delfriend(uint8_t * client_id)
614{ 614{
615 uint32_t i; 615 uint32_t i;
616 for(i = 0; i < num_friends; i++) 616 for(i = 0; i < num_friends; i++)
@@ -630,7 +630,7 @@ int delfriend(char * client_id)
630 630
631 631
632//TODO: Optimize this. 632//TODO: Optimize this.
633IP_Port getfriendip(char * client_id) 633IP_Port getfriendip(uint8_t * client_id)
634{ 634{
635 uint32_t i, j; 635 uint32_t i, j;
636 IP_Port empty = {{{0}}, 0}; 636 IP_Port empty = {{{0}}, 0};
@@ -660,7 +660,7 @@ IP_Port getfriendip(char * client_id)
660 660
661 661
662 662
663int DHT_handlepacket(char * packet, uint32_t length, IP_Port source) 663int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
664{ 664{
665 switch (packet[0]) { 665 switch (packet[0]) {
666 case 0: 666 case 0:
diff --git a/core/DHT.h b/core/DHT.h
index 3238191c..be8b8722 100644
--- a/core/DHT.h
+++ b/core/DHT.h
@@ -36,7 +36,7 @@
36 36
37typedef struct 37typedef struct
38{ 38{
39 char client_id[CLIENT_ID_SIZE]; 39 uint8_t client_id[CLIENT_ID_SIZE];
40 IP_Port ip_port; 40 IP_Port ip_port;
41 uint32_t timestamp; 41 uint32_t timestamp;
42 uint32_t last_pinged; 42 uint32_t last_pinged;
@@ -45,7 +45,7 @@ typedef struct
45#define MAX_FRIEND_CLIENTS 8 45#define MAX_FRIEND_CLIENTS 8
46typedef struct 46typedef struct
47{ 47{
48 char client_id[CLIENT_ID_SIZE]; 48 uint8_t client_id[CLIENT_ID_SIZE];
49 Client_data client_list[MAX_FRIEND_CLIENTS]; 49 Client_data client_list[MAX_FRIEND_CLIENTS];
50 50
51}Friend; 51}Friend;
@@ -53,7 +53,7 @@ typedef struct
53 53
54typedef struct 54typedef struct
55{ 55{
56 char client_id[CLIENT_ID_SIZE]; 56 uint8_t client_id[CLIENT_ID_SIZE];
57 IP_Port ip_port; 57 IP_Port ip_port;
58}Node_format; 58}Node_format;
59 59
@@ -70,13 +70,13 @@ typedef struct
70//client_id must be CLIENT_ID_SIZE bytes long. 70//client_id must be CLIENT_ID_SIZE bytes long.
71//returns 0 if success 71//returns 0 if success
72//returns 1 if failure (friends list is full) 72//returns 1 if failure (friends list is full)
73int addfriend(char * client_id); 73int addfriend(uint8_t * client_id);
74 74
75//Delete a friend from the friends list 75//Delete a friend from the friends list
76//client_id must be CLIENT_ID_SIZE bytes long. 76//client_id must be CLIENT_ID_SIZE bytes long.
77//returns 0 if success 77//returns 0 if success
78//returns 1 if failure (client_id not in friends list) 78//returns 1 if failure (client_id not in friends list)
79int delfriend(char * client_id); 79int delfriend(uint8_t * client_id);
80 80
81 81
82//Get ip of friend 82//Get ip of friend
@@ -86,7 +86,7 @@ int delfriend(char * client_id);
86//returns ip if success 86//returns ip if success
87//returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.) 87//returns ip of 0 if failure (This means the friend is either offline or we have not found him yet.)
88//returns ip of 1 if friend is not in list. 88//returns ip of 1 if friend is not in list.
89IP_Port getfriendip(char * client_id); 89IP_Port getfriendip(uint8_t * client_id);
90 90
91 91
92//Run this function at least a couple times per second (It's the main loop) 92//Run this function at least a couple times per second (It's the main loop)
@@ -95,7 +95,7 @@ void doDHT();
95//if we recieve a DHT packet we call this function so it can be handled. 95//if we recieve a DHT packet we call this function so it can be handled.
96//Return 0 if packet is handled correctly. 96//Return 0 if packet is handled correctly.
97//return 1 if it didn't handle the packet or if the packet was shit. 97//return 1 if it didn't handle the packet or if the packet was shit.
98int DHT_handlepacket(char * packet, uint32_t length, IP_Port source); 98int DHT_handlepacket(uint8_t * packet, uint32_t length, IP_Port source);
99 99
100//Use this function to bootstrap the client 100//Use this function to bootstrap the client
101//Sends a get nodes request to the given ip port 101//Sends a get nodes request to the given ip port
@@ -109,7 +109,7 @@ void bootstrap(IP_Port ip_port);
109//Global variables 109//Global variables
110 110
111//Our client id 111//Our client id
112extern char self_client_id[CLIENT_ID_SIZE]; 112extern uint8_t self_client_id[CLIENT_ID_SIZE];
113 113
114 114
115//TODO: Move these out of here and put them into the .c file. 115//TODO: Move these out of here and put them into the .c file.
diff --git a/core/Lossless_UDP.c b/core/Lossless_UDP.c
index bcbfb18a..b249760a 100644
--- a/core/Lossless_UDP.c
+++ b/core/Lossless_UDP.c
@@ -47,18 +47,19 @@
47 47
48typedef struct 48typedef struct
49{ 49{
50 char data[MAX_DATA_SIZE]; 50 uint8_t data[MAX_DATA_SIZE];
51 uint16_t size; 51 uint16_t size;
52}Data; 52}Data;
53 53
54typedef struct 54typedef struct
55{ 55{
56 IP_Port ip_port; 56 IP_Port ip_port;
57 char status;//0 if connection is dead, 1 if attempting handshake, 57 uint8_t status;//0 if connection is dead, 1 if attempting handshake,
58 //2 if handshake is done (we start sending SYNC packets) 58 //2 if handshake is done (we start sending SYNC packets)
59 //3 if we are sending SYNC packets and can send data 59 //3 if we are sending SYNC packets and can send data
60 //4 if the connection has timed out.
60 61
61 char inbound; //1 or 2 if connection was initiated by someone else, 0 if not. 62 uint8_t inbound; //1 or 2 if connection was initiated by someone else, 0 if not.
62 //2 if incoming_connection() has not returned it yet, 1 if it has. 63 //2 if incoming_connection() has not returned it yet, 1 if it has.
63 64
64 uint16_t SYNC_rate;//current SYNC packet send rate packets per second. 65 uint16_t SYNC_rate;//current SYNC packet send rate packets per second.
@@ -66,6 +67,7 @@ typedef struct
66 uint64_t last_SYNC; //time at which our last SYNC packet was sent. 67 uint64_t last_SYNC; //time at which our last SYNC packet was sent.
67 uint64_t last_sent; //time at which our last data or handshake packet was sent. 68 uint64_t last_sent; //time at which our last data or handshake packet was sent.
68 uint64_t last_recv; //time at which we last recieved something from the other 69 uint64_t last_recv; //time at which we last recieved something from the other
70 uint64_t killat; //time at which to kill the connection
69 Data sendbuffer[MAX_QUEUE_NUM];//packet send buffer. 71 Data sendbuffer[MAX_QUEUE_NUM];//packet send buffer.
70 Data recvbuffer[MAX_QUEUE_NUM];//packet recieve buffer. 72 Data recvbuffer[MAX_QUEUE_NUM];//packet recieve buffer.
71 uint32_t handshake_id1; 73 uint32_t handshake_id1;
@@ -160,6 +162,7 @@ int new_connection(IP_Port ip_port)
160 connections[i].SYNC_rate = SYNC_RATE; 162 connections[i].SYNC_rate = SYNC_RATE;
161 connections[i].data_rate = DATA_SYNC_RATE; 163 connections[i].data_rate = DATA_SYNC_RATE;
162 connections[i].last_recv = current_time(); 164 connections[i].last_recv = current_time();
165 connections[i].killat = ~0;
163 connections[i].send_counter = 0; 166 connections[i].send_counter = 0;
164 return i; 167 return i;
165 } 168 }
@@ -187,6 +190,7 @@ int new_inconnection(IP_Port ip_port)
187 connections[i].SYNC_rate = SYNC_RATE; 190 connections[i].SYNC_rate = SYNC_RATE;
188 connections[i].data_rate = DATA_SYNC_RATE; 191 connections[i].data_rate = DATA_SYNC_RATE;
189 connections[i].last_recv = current_time(); 192 connections[i].last_recv = current_time();
193 connections[i].killat = ~0;
190 connections[i].send_counter = 127; 194 connections[i].send_counter = 127;
191 return i; 195 return i;
192 } 196 }
@@ -225,11 +229,28 @@ int kill_connection(int connection_id)
225 return -1; 229 return -1;
226} 230}
227 231
232//kill connection in seconds seconds.
233//return -1 if it can not kill the connection.
234//return 0 if it will kill it
235int kill_connection_in(int connection_id, uint32_t seconds)
236{
237 if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
238 {
239 if(connections[connection_id].status > 0)
240 {
241 connections[connection_id].killat = current_time() + 1000000UL*seconds;
242 return 0;
243 }
244 }
245 return -1;
246}
247
228//check if connection is connected 248//check if connection is connected
229//return 0 no. 249//return 0 no.
230//return 1 if attempting handshake 250//return 1 if attempting handshake
231//return 2 if handshake is done 251//return 2 if handshake is done
232//return 3 if fully connected 252//return 3 if fully connected
253//return 4 if timed out and wating to be killed
233int is_connected(int connection_id) 254int is_connected(int connection_id)
234{ 255{
235 if(connection_id >= 0 && connection_id < MAX_CONNECTIONS) 256 if(connection_id >= 0 && connection_id < MAX_CONNECTIONS)
@@ -262,9 +283,19 @@ uint32_t recvqueue(int connection_id)
262 return connections[connection_id].recv_packetnum - connections[connection_id].successful_read; 283 return connections[connection_id].recv_packetnum - connections[connection_id].successful_read;
263} 284}
264 285
286//returns the id of the next packet in the queue
287//return -1 if no packet in queue
288char id_packet(int connection_id)
289{
290 if(recvqueue(connection_id) != 0 && connections[connection_id].status != 0)
291 {
292 return connections[connection_id].recvbuffer[connections[connection_id].successful_read % MAX_QUEUE_NUM].data[0];
293 }
294 return -1;
295}
265//return 0 if there is no received data in the buffer. 296//return 0 if there is no received data in the buffer.
266//return length of received packet if successful 297//return length of received packet if successful
267int read_packet(int connection_id, char * data) 298int read_packet(int connection_id, uint8_t * data)
268{ 299{
269 if(recvqueue(connection_id) != 0) 300 if(recvqueue(connection_id) != 0)
270 { 301 {
@@ -280,7 +311,7 @@ int read_packet(int connection_id, char * data)
280 311
281//return 0 if data could not be put in packet queue 312//return 0 if data could not be put in packet queue
282//return 1 if data was put into the queue 313//return 1 if data was put into the queue
283int write_packet(int connection_id, char * data, uint32_t length) 314int write_packet(int connection_id, uint8_t * data, uint32_t length)
284{ 315{
285 if(length > MAX_DATA_SIZE) 316 if(length > MAX_DATA_SIZE)
286 { 317 {
@@ -338,7 +369,7 @@ uint32_t missing_packets(int connection_id, uint32_t * requested)
338 369
339int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2) 370int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_id2)
340{ 371{
341 char packet[1 + 4 + 4]; 372 uint8_t packet[1 + 4 + 4];
342 uint32_t temp; 373 uint32_t temp;
343 374
344 packet[0] = 16; 375 packet[0] = 16;
@@ -354,7 +385,7 @@ int send_handshake(IP_Port ip_port, uint32_t handshake_id1, uint32_t handshake_i
354int send_SYNC(uint32_t connection_id) 385int send_SYNC(uint32_t connection_id)
355{ 386{
356 387
357 char packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)]; 388 uint8_t packet[(BUFFER_PACKET_NUM*4 + 4 + 4 + 2)];
358 uint16_t index = 0; 389 uint16_t index = 0;
359 390
360 IP_Port ip_port = connections[connection_id].ip_port; 391 IP_Port ip_port = connections[connection_id].ip_port;
@@ -382,7 +413,7 @@ int send_data_packet(uint32_t connection_id, uint32_t packet_num)
382{ 413{
383 uint32_t index = packet_num % MAX_QUEUE_NUM; 414 uint32_t index = packet_num % MAX_QUEUE_NUM;
384 uint32_t temp; 415 uint32_t temp;
385 char packet[1 + 4 + MAX_DATA_SIZE]; 416 uint8_t packet[1 + 4 + MAX_DATA_SIZE];
386 packet[0] = 18; 417 packet[0] = 18;
387 temp = htonl(packet_num); 418 temp = htonl(packet_num);
388 memcpy(packet + 1, &temp, 4); 419 memcpy(packet + 1, &temp, 4);
@@ -421,7 +452,7 @@ int send_DATA(uint32_t connection_id)
421//Packet handling functions 452//Packet handling functions
422//One to handle each type of packets we recieve 453//One to handle each type of packets we recieve
423//return 0 if handled correctly, 1 if packet is bad. 454//return 0 if handled correctly, 1 if packet is bad.
424int handle_handshake(char * packet, uint32_t length, IP_Port source) 455int handle_handshake(uint8_t * packet, uint32_t length, IP_Port source)
425{ 456{
426 if(length != (1 + 4 + 4)) 457 if(length != (1 + 4 + 4))
427 { 458 {
@@ -538,7 +569,7 @@ int handle_SYNC3(int connection_id, uint8_t counter, uint32_t recv_packetnum, ui
538 return 1; 569 return 1;
539} 570}
540 571
541int handle_SYNC(char * packet, uint32_t length, IP_Port source) 572int handle_SYNC(uint8_t * packet, uint32_t length, IP_Port source)
542{ 573{
543 574
544 if(!SYNC_valid(length)) 575 if(!SYNC_valid(length))
@@ -578,7 +609,7 @@ int handle_SYNC(char * packet, uint32_t length, IP_Port source)
578 609
579//add a packet to the recieved buffer and set the recv_packetnum of the connection to its proper value. 610//add a packet to the recieved buffer and set the recv_packetnum of the connection to its proper value.
580//return 1 if data was too big, 0 if not. 611//return 1 if data was too big, 0 if not.
581int add_recv(int connection_id, uint32_t data_num, char * data, uint16_t size) 612int add_recv(int connection_id, uint32_t data_num, uint8_t * data, uint16_t size)
582{ 613{
583 if(size > MAX_DATA_SIZE) 614 if(size > MAX_DATA_SIZE)
584 { 615 {
@@ -616,7 +647,7 @@ int add_recv(int connection_id, uint32_t data_num, char * data, uint16_t size)
616 return 0; 647 return 0;
617} 648}
618 649
619int handle_data(char * packet, uint32_t length, IP_Port source) 650int handle_data(uint8_t * packet, uint32_t length, IP_Port source)
620{ 651{
621 int connection = getconnection_id(source); 652 int connection = getconnection_id(source);
622 653
@@ -641,7 +672,7 @@ int handle_data(char * packet, uint32_t length, IP_Port source)
641//END of packet handling functions 672//END of packet handling functions
642 673
643 674
644int LosslessUDP_handlepacket(char * packet, uint32_t length, IP_Port source) 675int LosslessUDP_handlepacket(uint8_t * packet, uint32_t length, IP_Port source)
645{ 676{
646 677
647 switch (packet[0]) { 678 switch (packet[0]) {
@@ -681,7 +712,13 @@ void doNew()
681 712
682 } 713 }
683 //kill all timed out connections 714 //kill all timed out connections
684 if( connections[i].status > 0 && (connections[i].last_recv + CONNEXION_TIMEOUT * 1000000UL) < temp_time) 715 if( connections[i].status > 0 && (connections[i].last_recv + CONNEXION_TIMEOUT * 1000000UL) < temp_time &&
716 connections[i].status != 4)
717 {
718 //kill_connection(i);
719 connections[i].status = 4;
720 }
721 if(connections[i].status > 0 && connections[i].killat < temp_time)
685 { 722 {
686 kill_connection(i); 723 kill_connection(i);
687 } 724 }
diff --git a/core/Lossless_UDP.h b/core/Lossless_UDP.h
index 8bdeb43e..18224088 100644
--- a/core/Lossless_UDP.h
+++ b/core/Lossless_UDP.h
@@ -41,6 +41,10 @@
41//if there already was an existing connection to that ip_port return its number. 41//if there already was an existing connection to that ip_port return its number.
42int new_connection(IP_Port ip_port); 42int new_connection(IP_Port ip_port);
43 43
44//get connection id from IP_Port
45//return -1 if there are no connections like we are looking for
46//return id if it found it
47int getconnection_id(IP_Port ip_port);
44 48
45//returns an integer corresponding to the next connection in our imcoming connection list 49//returns an integer corresponding to the next connection in our imcoming connection list
46//return -1 if there are no new incoming connections in the list. 50//return -1 if there are no new incoming connections in the list.
@@ -51,20 +55,28 @@ int incoming_connection();
51//return 0 if killed successfully 55//return 0 if killed successfully
52int kill_connection(int connection_id); 56int kill_connection(int connection_id);
53 57
58//kill connection in seconds seconds.
59//return -1 if it can not kill the connection.
60//return 0 if it will kill it
61int kill_connection_in(int connection_id, uint32_t seconds);
54 62
55//returns the ip_port of the corresponding connection. 63//returns the ip_port of the corresponding connection.
56//return 0 if there is no such connection. 64//return 0 if there is no such connection.
57IP_Port connection_ip(int connection_id); 65IP_Port connection_ip(int connection_id);
58 66
67//returns the id of the next packet in the queue
68//return -1 if no packet in queue
69char id_packet(int connection_id);
59 70
60//return 0 if there is no received data in the buffer. 71//return 0 if there is no received data in the buffer.
61//return length of recieved packet if successful 72//return length of recieved packet if successful
62int read_packet(int connection_id, char * data); 73int read_packet(int connection_id, uint8_t * data);
63 74
64 75
65//return 0 if data could not be put in packet queue 76//return 0 if data could not be put in packet queue
66//return 1 if data was put into the queue 77//return 1 if data was put into the queue
67int write_packet(int connection_id, char * data, uint32_t length); 78int write_packet(int connection_id, uint8_t * data, uint32_t length);
79
68 80
69 81
70//returns the number of packets in the queue waiting to be successfully sent. 82//returns the number of packets in the queue waiting to be successfully sent.
@@ -80,6 +92,7 @@ uint32_t recvqueue(int connection_id);
80//return 1 if attempting handshake 92//return 1 if attempting handshake
81//return 2 if handshake is done 93//return 2 if handshake is done
82//return 3 if fully connected 94//return 3 if fully connected
95//return 4 if timed out and wating to be killed
83int is_connected(int connection_id); 96int is_connected(int connection_id);
84 97
85 98
@@ -91,6 +104,6 @@ void doLossless_UDP();
91//if we receive a Lossless_UDP packet we call this function so it can be handled. 104//if we receive a Lossless_UDP packet we call this function so it can be handled.
92//Return 0 if packet is handled correctly. 105//Return 0 if packet is handled correctly.
93//return 1 if it didn't handle the packet or if the packet was shit. 106//return 1 if it didn't handle the packet or if the packet was shit.
94int LosslessUDP_handlepacket(char * packet, uint32_t length, IP_Port source); 107int LosslessUDP_handlepacket(uint8_t * packet, uint32_t length, IP_Port source);
95 108
96#endif 109#endif
diff --git a/core/net_crypto.c b/core/net_crypto.c
new file mode 100644
index 00000000..38a72205
--- /dev/null
+++ b/core/net_crypto.c
@@ -0,0 +1,622 @@
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*/
9
10
11#include "net_crypto.h"
12
13
14//Our public and secret keys.
15uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
16uint8_t self_secret_key[crypto_box_SECRETKEYBYTES];
17
18
19typedef struct
20{
21 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
22 uint8_t recv_nonce[crypto_box_NONCEBYTES];//nonce of recieved packets
23 uint8_t sent_nonce[crypto_box_NONCEBYTES];//nonce of sent packets.
24 uint8_t status;//0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
25 //(we have recieved a hanshake but no empty data packet), 3 if the connection is established.
26 //4 if the connection is timed out.
27 uint16_t number; //Lossless_UDP connection number corresponding to this connection.
28
29}Crypto_Connection;
30
31#define MAX_CRYPTO_CONNECTIONS 256
32
33Crypto_Connection crypto_connections[MAX_CRYPTO_CONNECTIONS];
34
35#define MAX_FRIEND_REQUESTS 32
36
37//keeps track of the connection numbers for friends request so we can check later if they were sent
38int outbound_friendrequests[MAX_FRIEND_REQUESTS];
39
40#define MAX_INCOMING 64
41
42//keeps track of the connection numbers for friends request so we can check later if they were sent
43int incoming_connections[MAX_INCOMING];
44
45//encrypts plain of length length to encrypted of length + 16 using the
46//public key(32 bytes) of the reciever and a 24 byte nonce
47//return -1 if there was a problem.
48//return length of encrypted data if everything was fine.
49int encrypt_data(uint8_t * public_key, uint8_t * nonce, uint8_t * plain, uint32_t length, uint8_t * encrypted)
50{
51 if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE || length == 0)
52 {
53 return -1;
54 }
55
56 uint8_t temp_plain[MAX_DATA_SIZE + crypto_box_ZEROBYTES - crypto_box_BOXZEROBYTES] = {0};
57 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES];
58 uint8_t zeroes[crypto_box_BOXZEROBYTES] = {0};
59
60 memcpy(temp_plain + crypto_box_ZEROBYTES, plain, length);//pad the message with 32 0 bytes.
61
62 crypto_box(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, public_key, self_secret_key);
63
64 //if encryption is successful the first crypto_box_BOXZEROBYTES of the message will be zero
65 if(memcmp(temp_encrypted, zeroes, crypto_box_BOXZEROBYTES) != 0)
66 {
67 return -1;
68 }
69 //unpad the encrypted message
70 memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
71 return length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES;
72}
73
74//decrypts encrypted of length length to plain of length length - 16 using the
75//public key(32 bytes) of the sender and a 24 byte nonce
76//return -1 if there was a problem(decryption failed)
77//return length of plain data if everything was fine.
78int decrypt_data(uint8_t * public_key, uint8_t * nonce, uint8_t * encrypted, uint32_t length, uint8_t * plain)
79{
80 if(length > MAX_DATA_SIZE || length <= crypto_box_BOXZEROBYTES)
81 {
82 return -1;
83 }
84 uint8_t temp_plain[MAX_DATA_SIZE - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES];
85 uint8_t temp_encrypted[MAX_DATA_SIZE + crypto_box_ZEROBYTES] = {0};
86 uint8_t zeroes[crypto_box_ZEROBYTES] = {0};
87
88 memcpy(temp_encrypted + crypto_box_BOXZEROBYTES, encrypted, length);//pad the message with 16 0 bytes.
89
90 if(crypto_box_open(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES,
91 nonce, public_key, self_secret_key) == -1)
92 {
93 return -1;
94 }
95 //if decryption is successful the first crypto_box_ZEROBYTES of the message will be zero
96 if(memcmp(temp_plain, zeroes, crypto_box_ZEROBYTES) != 0)
97 {
98 return -1;
99 }
100 //unpad the plain message
101 memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES);
102 return length - crypto_box_ZEROBYTES + crypto_box_BOXZEROBYTES;
103}
104
105//increment the given nonce by 1
106void increment_nonce(uint8_t * nonce)
107{
108 uint32_t i;
109 for(i = 0; i < crypto_box_NONCEBYTES; i++)
110 {
111 nonce[i]++;
112 if(nonce[i] != 0)
113 {
114 break;
115 }
116 }
117}
118
119//fill the given nonce with random bytes.
120//TODO: make this more optimized
121void random_nonce(uint8_t * nonce)
122{
123 uint32_t i;
124 for(i = 0; i < crypto_box_NONCEBYTES; i++)
125 {
126 nonce[i] = random_int() % 256;
127 }
128}
129
130//return 0 if there is no received data in the buffer
131//return -1 if the packet was discarded.
132//return length of recieved data if successful
133int read_cryptpacket(int crypt_connection_id, uint8_t * data)
134{
135 if(crypto_connections[crypt_connection_id].status != 3)
136 {
137 return 0;
138 }
139 uint8_t temp_data[MAX_DATA_SIZE];
140 int length = read_packet(crypto_connections[crypt_connection_id].number, temp_data);
141 if(length == 0)
142 {
143 return 0;
144 }
145 if(temp_data[0] != 3)
146 {
147 return -1;
148 }
149 int len = decrypt_data(crypto_connections[crypt_connection_id].public_key,
150 crypto_connections[crypt_connection_id].recv_nonce, temp_data + 1, length - 1, data);
151 if(len != -1)
152 {
153 increment_nonce(crypto_connections[crypt_connection_id].recv_nonce);
154 return len;
155 }
156 return -1;
157}
158
159
160//return 0 if data could not be put in packet queue
161//return 1 if data was put into the queue
162int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length)
163{
164 if(length - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES > MAX_DATA_SIZE - 1)
165 {
166 return 0;
167 }
168 if(crypto_connections[crypt_connection_id].status != 3)
169 {
170 return 0;
171 }
172 uint8_t temp_data[MAX_DATA_SIZE];
173 int len = encrypt_data(crypto_connections[crypt_connection_id].public_key,
174 crypto_connections[crypt_connection_id].sent_nonce, data, length, temp_data + 1);
175 if(len == -1)
176 {
177 return 0;
178 }
179 temp_data[0] = 3;
180 if(write_packet(crypto_connections[crypt_connection_id].number, temp_data, len + 1) == 0)
181 {
182 return 0;
183 }
184 increment_nonce(crypto_connections[crypt_connection_id].sent_nonce);
185 return 1;
186}
187
188//send a friend request to peer with public_key and ip_port.
189//Data represents the data we send with the friends request.
190//returns -1 on failure
191//returns a positive friend request id that can be used later to see if it was sent correctly on success.
192int send_friendrequest(uint8_t * public_key, IP_Port ip_port, uint8_t * data, uint32_t length)
193{
194 if(length > MAX_DATA_SIZE - 1 - crypto_box_PUBLICKEYBYTES - crypto_box_NONCEBYTES)
195 {
196 return -1;
197 }
198 uint32_t i;
199 for(i = 0; i < MAX_FRIEND_REQUESTS; i++)
200 {
201 if(outbound_friendrequests[i] == -1)
202 {
203 break;
204 }
205 }
206 if(i == MAX_FRIEND_REQUESTS)
207 {
208 return -1;
209 }
210 uint8_t temp_data[MAX_DATA_SIZE];
211 uint8_t nonce[crypto_box_NONCEBYTES];
212 random_nonce(nonce);
213 int len = encrypt_data(public_key, nonce, data, length, 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
214 if(len == -1)
215 {
216 return -1;
217 }
218 temp_data[0] = 1;
219 memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES);
220 memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
221 int id = new_connection(ip_port);
222 if(id == -1)
223 {
224 return -1;
225 }
226 if(write_packet(id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES) == 1)
227 {
228 outbound_friendrequests[i] = id;
229 return i;
230 }
231 return -1;
232}
233
234//return -1 if failure
235//return 0 if connection is still trying to send the request.
236//return 1 if sent correctly
237//return 2 if connection timed out
238int check_friendrequest(int friend_request)
239{
240 if(friend_request < 0 || friend_request > MAX_FRIEND_REQUESTS)
241 {
242 return -1;
243 }
244 if(outbound_friendrequests[friend_request] == -1)
245 {
246 return -1;
247 }
248 if(sendqueue(outbound_friendrequests[friend_request]) == 0)
249 {
250 kill_connection(outbound_friendrequests[friend_request]);
251 outbound_friendrequests[friend_request] = -1;
252 return 1;
253 }
254 int status = is_connected(outbound_friendrequests[friend_request]);
255 if(status == 4)
256 {
257 kill_connection(outbound_friendrequests[friend_request]);
258 outbound_friendrequests[friend_request] = -1;
259 return 2;
260 }
261 if(status == 0)
262 {
263 outbound_friendrequests[friend_request] = -1;
264 return 2;
265 }
266 return 0;
267}
268
269//Send a crypto handshake packet containing an encrypted secret nonce to peer with connection_id and public_key
270//the packet is encrypted with a random nonce which is sent in plain text with the packet
271int send_cryptohandshake(int connection_id, uint8_t * public_key, uint8_t * secret_nonce)
272{
273 uint8_t temp_data[MAX_DATA_SIZE];
274 uint8_t nonce[crypto_box_NONCEBYTES];
275 random_nonce(nonce);
276 int len = encrypt_data(public_key, nonce, secret_nonce, crypto_box_NONCEBYTES,
277 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + temp_data);
278 if(len == -1)
279 {
280 return 0;
281 }
282 temp_data[0] = 2;
283 memcpy(temp_data + 1, self_public_key, crypto_box_PUBLICKEYBYTES);
284 memcpy(temp_data + 1 + crypto_box_PUBLICKEYBYTES, nonce, crypto_box_NONCEBYTES);
285 return write_packet(connection_id, temp_data, len + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES);
286}
287
288//Extract secret nonce and public_key from a packet(data) with length length
289//return 1 if successful
290//return 0 if failure
291int handle_cryptohandshake(uint8_t * public_key, uint8_t * secret_nonce, uint8_t * data, uint16_t length)
292{
293 int pad = (- crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES);
294 if(length != 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + crypto_box_NONCEBYTES + pad)
295 {
296 return 0;
297 }
298 if(data[0] != 2)
299 {
300 return 0;
301 }
302 memcpy(public_key, data + 1, crypto_box_PUBLICKEYBYTES);
303 int len = decrypt_data(public_key, data + 1 + crypto_box_PUBLICKEYBYTES,
304 data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES, crypto_box_NONCEBYTES + pad, secret_nonce);
305 if(len != crypto_box_NONCEBYTES)
306 {
307 return 0;
308 }
309 return 1;
310}
311
312
313//puts the public key of the friend if public_key, the data from the request
314//in data if a friend request was sent to us and returns the length of the data.
315//return -1 if no valid friend requests.
316int handle_friendrequest(uint8_t * public_key, uint8_t * data)
317{
318 uint32_t i;
319 for(i = 0; i < MAX_INCOMING; i++)
320 {
321 if(incoming_connections[i] != -1)
322 {
323 if(id_packet(incoming_connections[i]) == 1)
324 {
325 uint8_t temp_data[MAX_DATA_SIZE];
326 uint16_t len = read_packet(incoming_connections[i], temp_data);
327 if(len > crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + 1
328 - crypto_box_BOXZEROBYTES + crypto_box_ZEROBYTES)
329 {
330 memcpy(public_key, temp_data + 1, crypto_box_PUBLICKEYBYTES);
331 uint8_t nonce[crypto_box_NONCEBYTES];
332 memcpy(nonce, temp_data + 1 + crypto_box_PUBLICKEYBYTES, crypto_box_NONCEBYTES);
333 int len1 = decrypt_data(public_key, nonce, temp_data + 1 + crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES,
334 len - (crypto_box_PUBLICKEYBYTES + crypto_box_NONCEBYTES + 1), data);
335 if(len1 != -1)
336 {
337 kill_connection_in(incoming_connections[i], 1); //conection is useless now, kill it in 1 seconds
338 incoming_connections[i] = -1;
339 return len1;
340 }
341 }
342 kill_connection(incoming_connections[i]); //conection is useless now, kill it.
343 incoming_connections[i] = -1;
344 }
345 }
346 }
347 return -1;
348}
349
350
351//Start a secure connection with other peer who has public_key and ip_port
352//returns -1 if failure
353//returns crypt_connection_id of the initialized connection if everything went well.
354int crypto_connect(uint8_t * public_key, IP_Port ip_port)
355{
356 uint32_t i;
357 if(getconnection_id(ip_port) != -1)
358 {
359 return -1;
360 }
361 for(i = 0; i < MAX_CRYPTO_CONNECTIONS; i++)
362 {
363 if(crypto_connections[i].status == 0)
364 {
365 int id = new_connection(ip_port);
366 if(id == -1)
367 {
368 return -1;
369 }
370 crypto_connections[i].number = id;
371 crypto_connections[i].status = 1;
372 random_nonce(crypto_connections[i].recv_nonce);
373 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
374 if(send_cryptohandshake(id, public_key, crypto_connections[i].recv_nonce) == 1)
375 {
376 increment_nonce(crypto_connections[i].recv_nonce);
377 return i;
378 }
379 return -1;//this should never happen.
380 }
381 }
382 return -1;
383}
384
385//handle an incoming connection
386//return -1 if no crypto inbound connection
387//return incomming connection id (Lossless_UDP one) if there is an incomming crypto connection
388//Put the public key of the peer in public_key and the secret_nonce from the handshake into secret_nonce
389//to accept it see: accept_crypto_inbound(...)
390//to refuse it just call kill_connection(...) on the connection id
391int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce)
392{
393 uint32_t i;
394 for(i = 0; i < MAX_INCOMING; i++)
395 {
396 if(incoming_connections[i] != -1)
397 {
398 if(id_packet(incoming_connections[i]) == 2)
399 {
400 uint8_t temp_data[MAX_DATA_SIZE];
401 uint16_t len = read_packet(incoming_connections[i], temp_data);
402 if(handle_cryptohandshake(public_key, secret_nonce, temp_data, len))
403 {
404 int connection_id = incoming_connections[i];
405 incoming_connections[i] = -1;//remove this connection from the incoming connection list.
406 return connection_id;
407 }
408 }
409 }
410 }
411 return -1;
412}
413
414//kill a crypto connection
415//return 0 if killed successfully
416//return 1 if there was a problem.
417int crypto_kill(int crypt_connection_id)
418{
419 if(crypt_connection_id < 0 || crypt_connection_id >= MAX_CRYPTO_CONNECTIONS)
420 {
421 return 1;
422 }
423 if(crypto_connections[crypt_connection_id].status != 0)
424 {
425 crypto_connections[crypt_connection_id].status = 0;
426 kill_connection(crypto_connections[crypt_connection_id].number);
427 return 0;
428 }
429 return 1;
430}
431
432
433//accept an incoming connection using the parameters provided by crypto_inbound
434//return -1 if not successful
435//returns the crypt_connection_id if successful
436int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * secret_nonce)
437{
438 uint32_t i;
439 if(connection_id == -1)
440 {
441 return -1;
442 }
443 for(i = 0; i < MAX_CRYPTO_CONNECTIONS; i++)
444 {
445 if(crypto_connections[i].status == 0)
446 {
447 crypto_connections[i].number = connection_id;
448 crypto_connections[i].status = 2;
449 random_nonce(crypto_connections[i].recv_nonce);
450 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
451 increment_nonce(crypto_connections[i].sent_nonce);
452 memcpy(crypto_connections[i].public_key, public_key, crypto_box_PUBLICKEYBYTES);
453 if(send_cryptohandshake(connection_id, public_key, crypto_connections[i].recv_nonce) == 1)
454 {
455 increment_nonce(crypto_connections[i].recv_nonce);
456 uint32_t zero = 0;
457 crypto_connections[i].status = 3;//connection status needs to be 3 for write_cryptpacket() to work
458 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
459 crypto_connections[i].status = 2;//set it to its proper value right after.
460 return i;
461 }
462 return -1;//this should never happen.
463 }
464 }
465 return -1;
466}
467
468//return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
469//(we have recieved a hanshake but no empty data packet), 3 if the connection is established.
470//4 if the connection is timed out and wating to be killed
471int is_cryptoconnected(int crypt_connection_id)
472{
473 if(crypt_connection_id >= 0 && crypt_connection_id < MAX_CRYPTO_CONNECTIONS)
474 {
475 return crypto_connections[crypt_connection_id].status;
476 }
477 return 0;
478}
479
480
481//Generate our public and private keys
482//Only call this function the first time the program starts.
483void new_keys()
484{
485 crypto_box_keypair(self_public_key,self_secret_key);
486}
487
488//TODO: optimize this
489//adds an incoming connection to the incoming_connection list.
490//returns 0 if successful
491//returns 1 if failure
492int new_incoming(int id)
493{
494 uint32_t i;
495 for(i = 0; i < MAX_INCOMING; i++)
496 {
497 if(incoming_connections[i] == -1)
498 {
499 incoming_connections[i] = id;
500 return 0;
501 }
502 }
503 return 1;
504}
505
506//TODO: optimize this
507//handle all new incoming connections.
508void handle_incomings()
509{
510 int income;
511 while(1)
512 {
513 income = incoming_connection();
514 if(income == -1)
515 {
516 break;
517 }
518 if(new_incoming(income))
519 {
520 break;
521 }
522 }
523}
524
525//handle recieved packets for not yet established crypto connections.
526void recieve_crypto()
527{
528 uint32_t i;
529 for(i = 0; i < MAX_CRYPTO_CONNECTIONS; i++)
530 {
531 if(crypto_connections[i].status == 1)
532 {
533 if(id_packet(crypto_connections[i].number) == 2)//handle handshake packet.
534 {
535 uint8_t temp_data[MAX_DATA_SIZE];
536 uint8_t secret_nonce[crypto_box_NONCEBYTES];
537 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
538 uint16_t len = read_packet(crypto_connections[i].number, temp_data);
539 if(handle_cryptohandshake(public_key, secret_nonce, temp_data, len))
540 {
541 if(memcmp(public_key, crypto_connections[i].public_key, crypto_box_PUBLICKEYBYTES) == 0)
542 {
543 memcpy(crypto_connections[i].sent_nonce, secret_nonce, crypto_box_NONCEBYTES);
544 increment_nonce(crypto_connections[i].sent_nonce);
545 uint32_t zero = 0;
546 crypto_connections[i].status = 3;//connection status needs to be 3 for write_cryptpacket() to work
547 write_cryptpacket(i, ((uint8_t *)&zero), sizeof(zero));
548 crypto_connections[i].status = 2;//set it to its proper value right after.
549 }
550 }
551 }
552 else if(id_packet(crypto_connections[i].number) != -1)
553 {
554 //This should not happen
555 //kill the connection if it does
556 crypto_kill(crypto_connections[i].number);
557 }
558
559 }
560 if(crypto_connections[i].status == 2)
561 {
562 if(id_packet(crypto_connections[i].number) == 3)
563 {
564 uint8_t temp_data[MAX_DATA_SIZE];
565 uint8_t data[MAX_DATA_SIZE];
566 int length = read_packet(crypto_connections[i].number, temp_data);
567 int len = decrypt_data(crypto_connections[i].public_key,
568 crypto_connections[i].recv_nonce, temp_data + 1, length - 1, data);
569 uint32_t zero = 0;
570 if(len == sizeof(uint32_t) && memcmp(((uint8_t *)&zero), data, sizeof(uint32_t)) == 0)
571 {
572 increment_nonce(crypto_connections[i].recv_nonce);
573 crypto_connections[i].status = 3;
574 }
575 else
576 {
577 //This should not happen
578 //kill the connection if it does
579 crypto_kill(crypto_connections[i].number);
580 }
581 }
582 else if(id_packet(crypto_connections[i].number) != -1)
583 {
584 //This should not happen
585 //kill the connection if it does
586 crypto_kill(crypto_connections[i].number);
587 }
588 }
589 }
590}
591
592//run this to (re)initialize net_crypto
593//sets all the global connection variables to their default values.
594void initNetCrypto()
595{
596 memset(crypto_connections, 0 ,sizeof(crypto_connections));
597 memset(outbound_friendrequests, -1 ,sizeof(outbound_friendrequests));
598 memset(incoming_connections, -1 ,sizeof(incoming_connections));
599}
600
601void killTimedout()
602{
603 uint32_t i;
604 for(i = 0; i < MAX_CRYPTO_CONNECTIONS; i++)
605 {
606 if(is_connected(crypto_connections[i].number) == 4)
607 {
608 crypto_connections[i].status = 4;
609 }
610 }
611}
612
613//main loop
614void doNetCrypto()
615{
616 //TODO:check if friend requests were sent correctly
617 //handle new incoming connections
618 //handle friend requests
619 handle_incomings();
620 recieve_crypto();
621 killTimedout();
622}
diff --git a/core/net_crypto.h b/core/net_crypto.h
new file mode 100644
index 00000000..850bcd13
--- /dev/null
+++ b/core/net_crypto.h
@@ -0,0 +1,108 @@
1/* net_crypto.h
2*
3* Functions for the core network crypto.
4*
5*/
6
7#ifndef NET_CRYPTO_H
8#define NET_CRYPTO_H
9
10#include "Lossless_UDP.h"
11
12//TODO: move this to network.h
13#ifndef WIN32
14#include "../nacl/build/Linux/include/amd64/crypto_box.h"
15#endif
16//Our public key.
17extern uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
18
19
20
21//encrypts plain of length length to encrypted of length + 16 using the
22//public key(32 bytes) of the reciever and a 24 byte nonce
23//return -1 if there was a problem.
24//return length of encrypted data if everything was fine.
25int encrypt_data(uint8_t * public_key, uint8_t * nonce, uint8_t * plain, uint32_t length, uint8_t * encrypted);
26
27
28//decrypts encrypted of length length to plain of length length - 16 using the
29//public key(32 bytes) of the sender and a 24 byte nonce
30//return -1 if there was a problem(decryption failed)
31//return length of plain data if everything was fine.
32int decrypt_data(uint8_t * public_key, uint8_t * nonce, uint8_t * encrypted, uint32_t length, uint8_t * plain);
33
34
35//return 0 if there is no received data in the buffer
36//return -1 if the packet was discarded.
37//return length of recieved data if successful
38int read_cryptpacket(int crypt_connection_id, uint8_t * data);
39
40
41//return 0 if data could not be put in packet queue
42//return 1 if data was put into the queue
43int write_cryptpacket(int crypt_connection_id, uint8_t * data, uint32_t length);
44
45//send a friend request to peer with public_key and ip_port.
46//Data represents the data we send with the friends request.
47//returns -1 on failure
48//returns a positive friend request id that can be used later to see if it was sent correctly on success.
49int send_friendrequest(uint8_t * public_key, IP_Port ip_port, uint8_t * data, uint32_t length);
50
51
52//return -1 if failure
53//return 0 if connection is still trying to send the request.
54//return 1 if sent correctly
55//return 2 if connection timed out
56int check_friendrequest(int friend_request);
57
58
59//puts the public key of the friend if public_key, the data from the request
60//in data if a friend request was sent to us and returns the length of the data.
61//return -1 if no valid friend requests.
62int handle_friendrequest(uint8_t * public_key, uint8_t * data);
63
64
65//Start a secure connection with other peer who has public_key and ip_port
66//returns -1 if failure
67//returns crypt_connection_id of the initialized connection if everything went well.
68int crypto_connect(uint8_t * public_key, IP_Port ip_port);
69
70
71//kill a crypto connection
72//return 0 if killed successfully
73//return 1 if there was a problem.
74int crypto_kill(int crypt_connection_id);
75
76//handle an incoming connection
77//return -1 if no crypto inbound connection
78//return incomming connection id (Lossless_UDP one) if there is an incomming crypto connection
79//Put the public key of the peer in public_key and the secret_nonce from the handshake into secret_nonce
80//to accept it see: accept_crypto_inbound(...)
81//to refuse it just call kill_connection(...) on the connection id
82int crypto_inbound(uint8_t * public_key, uint8_t * secret_nonce);
83
84
85//accept an incoming connection using the parameters provided by crypto_inbound
86//return -1 if not successful
87//returns the crypt_connection_id if successful
88int accept_crypto_inbound(int connection_id, uint8_t * public_key, uint8_t * secret_nonce);
89
90//return 0 if no connection, 1 we have sent a handshake, 2 if connexion is not confirmed yet
91//(we have recieved a hanshake but no empty data packet), 3 if the connection is established.
92//4 if the connection is timed out and wating to be killed
93int is_cryptoconnected(int crypt_connection_id);
94
95
96//Generate our public and private keys
97//Only call this function the first time the program starts.
98void new_keys();
99
100//run this to (re)initialize net_crypto
101//sets all the global connection variables to their default values.
102void initNetCrypto();
103
104//main loop
105void doNetCrypto();
106
107
108#endif
diff --git a/core/network.c b/core/network.c
index 601066cd..6b5f9970 100644
--- a/core/network.c
+++ b/core/network.c
@@ -63,10 +63,10 @@ static int sock;
63 63
64//Basic network functions: 64//Basic network functions:
65//Function to send packet(data) of length length to ip_port 65//Function to send packet(data) of length length to ip_port
66int sendpacket(IP_Port ip_port, char * data, uint32_t length) 66int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length)
67{ 67{
68 ADDR addr = {AF_INET, ip_port.port, ip_port.ip}; 68 ADDR addr = {AF_INET, ip_port.port, ip_port.ip};
69 return sendto(sock, data, length, 0, (struct sockaddr *)&addr, sizeof(addr)); 69 return sendto(sock,(char *) data, length, 0, (struct sockaddr *)&addr, sizeof(addr));
70 70
71} 71}
72 72
@@ -74,7 +74,7 @@ int sendpacket(IP_Port ip_port, char * data, uint32_t length)
74//the packet data into data 74//the packet data into data
75//the packet length into length. 75//the packet length into length.
76//dump all empty packets. 76//dump all empty packets.
77int recievepacket(IP_Port * ip_port, char * data, uint32_t * length) 77int recievepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length)
78{ 78{
79 ADDR addr; 79 ADDR addr;
80 #ifdef WIN32 80 #ifdef WIN32
@@ -82,7 +82,7 @@ int recievepacket(IP_Port * ip_port, char * data, uint32_t * length)
82 #else 82 #else
83 uint32_t addrlen = sizeof(addr); 83 uint32_t addrlen = sizeof(addr);
84 #endif 84 #endif
85 (*(int32_t *)length) = recvfrom(sock, data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen); 85 (*(int32_t *)length) = recvfrom(sock,(char *) data, MAX_UDP_PACKET_SIZE, 0, (struct sockaddr *)&addr, &addrlen);
86 if(*(int32_t *)length <= 0) 86 if(*(int32_t *)length <= 0)
87 { 87 {
88 //nothing received 88 //nothing received
diff --git a/core/network.h b/core/network.h
index c8fdce5c..9606d237 100644
--- a/core/network.h
+++ b/core/network.h
@@ -95,12 +95,12 @@ uint32_t random_int();
95//Basic network functions: 95//Basic network functions:
96 96
97//Function to send packet(data) of length length to ip_port 97//Function to send packet(data) of length length to ip_port
98int sendpacket(IP_Port ip_port, char * data, uint32_t length); 98int sendpacket(IP_Port ip_port, uint8_t * data, uint32_t length);
99 99
100//Function to recieve data, ip and port of sender is put into ip_port 100//Function to recieve data, ip and port of sender is put into ip_port
101//the packet data into data 101//the packet data into data
102//the packet length into length. 102//the packet length into length.
103int recievepacket(IP_Port * ip_port, char * data, uint32_t * length); 103int recievepacket(IP_Port * ip_port, uint8_t * data, uint32_t * length);
104 104
105//initialize networking 105//initialize networking
106//bind to ip and port 106//bind to ip and port
diff --git a/testing/DHT_cryptosendfiletest.c b/testing/DHT_cryptosendfiletest.c
new file mode 100644
index 00000000..787e279e
--- /dev/null
+++ b/testing/DHT_cryptosendfiletest.c
@@ -0,0 +1,251 @@
1/* DHT cryptosendfiletest
2 *
3 * This program sends or recieves a friend request.
4 *
5 * it also sends the encrypted data from a file to another client.
6 * Receives the file data that that client sends us.
7 *
8 * NOTE: this program simulates 33% packet loss.
9 *
10 * This is how I compile it: gcc -O2 -Wall -o test ../core/Lossless_UDP.c ../core/network.c ../core/net_crypto.c ../core/DHT.c ../nacl/build/Linux/lib/amd64/* DHT_cryptosendfiletest.c
11*
12 *
13 * Command line arguments are the ip and port of a node (for bootstrapping).
14 *
15 * Saves all received data to: received.txt
16 *
17 * EX: ./test 127.0.0.1 33445 filename.txt
18 */
19#include "../core/network.h"
20#include "../core/DHT.h"
21#include "../core/net_crypto.h"
22
23#include <string.h>
24
25//Sleep function (x = milliseconds)
26#ifdef WIN32
27
28#define c_sleep(x) Sleep(1*x)
29
30#else
31#include <unistd.h>
32#include <arpa/inet.h>
33#define c_sleep(x) usleep(1000*x)
34
35#endif
36
37#define PORT 33445
38
39void printip(IP_Port ip_port)
40{
41 printf("\nIP: %u.%u.%u.%u Port: %u\n",ip_port.ip.c[0],ip_port.ip.c[1],ip_port.ip.c[2],ip_port.ip.c[3],ntohs(ip_port.port));
42}
43
44
45//horrible function from one of my first C programs.
46//only here because I was too lazy to write a proper one.
47unsigned char * hex_string_to_bin(char hex_string[])
48{
49 unsigned char * val = malloc(strlen(hex_string));
50 char * pos = hex_string;
51 int i=0;
52 while(i < strlen(hex_string))
53 {
54 sscanf(pos,"%2hhx",&val[i]);
55 pos+=2;
56 i++;
57 }
58 return val;
59}
60
61uint8_t self_public_key[crypto_box_PUBLICKEYBYTES];
62
63int main(int argc, char *argv[])
64{
65 if (argc < 4) {
66 printf("usage %s ip port filename(of file to send)\n", argv[0]);
67 exit(0);
68 }
69 new_keys();
70 printf("OUR ID: ");
71 uint32_t i;
72 for(i = 0; i < 32; i++)
73 {
74 if(self_public_key[i] < 16)
75 printf("0");
76 printf("%hhX",self_public_key[i]);
77 }
78 printf("\n");
79
80 memcpy(self_client_id, self_public_key, 32);
81
82 char temp_id[128];
83 printf("Enter the client_id of the friend to connect to (32 bytes HEX format):\n");
84 scanf("%s", temp_id);
85
86 uint8_t friend_id[32];
87 memcpy(friend_id, hex_string_to_bin(temp_id), 32);
88
89
90 //memcpy(self_client_id, "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 32);
91
92
93 addfriend(friend_id);
94 IP_Port friend_ip;
95 int connection = -1;
96 int inconnection = -1;
97
98 uint8_t acceptedfriend_public_key[crypto_box_PUBLICKEYBYTES];
99 int friendrequest = -1;
100 uint8_t request_data[512];
101
102 //initialize networking
103 //bind to ip 0.0.0.0:PORT
104 IP ip;
105 ip.i = 0;
106 init_networking(ip, PORT);
107 initNetCrypto();
108
109
110
111 perror("Initialization");
112 IP_Port bootstrap_ip_port;
113 bootstrap_ip_port.port = htons(atoi(argv[2]));
114 bootstrap_ip_port.ip.i = inet_addr(argv[1]);
115 bootstrap(bootstrap_ip_port);
116
117 IP_Port ip_port;
118 uint8_t data[MAX_UDP_PACKET_SIZE];
119 uint32_t length;
120
121 uint8_t buffer1[128];
122 int read1 = 0;
123 uint8_t buffer2[128];
124 int read2 = 0;
125 FILE *file1 = fopen(argv[3], "rb");
126 if ( file1==NULL ){printf("Error opening file.\n");return 1;}
127 FILE *file2 = fopen("received.txt", "wb");
128 if ( file2==NULL ){return 1;}
129 read1 = fread(buffer1, 1, 128, file1);
130
131 while(1)
132 {
133
134 while(recievepacket(&ip_port, data, &length) != -1)
135 {
136 if(rand() % 3 != 1)//simulate packet loss
137 {
138 if(DHT_handlepacket(data, length, ip_port) && LosslessUDP_handlepacket(data, length, ip_port))
139 {
140 //if packet is not recognized
141 printf("Received unhandled packet with length: %u\n", length);
142 }
143 else
144 {
145 printf("Received handled packet with length: %u\n", length);
146 }
147 }
148 }
149 friend_ip = getfriendip((uint8_t *)friend_id);
150 if(friend_ip.ip.i != 0)
151 {
152 if(connection == -1 && friendrequest == -1)
153 {
154 printf("Sending friend request to peer:");
155 printip(friend_ip);
156 friendrequest = send_friendrequest(friend_id, friend_ip, "Hello World", 12);
157 //connection = crypto_connect((uint8_t *)friend_id, friend_ip);
158 //connection = new_connection(friend_ip);
159 }
160 if(check_friendrequest(friendrequest) == 1)
161 {
162 printf("Started connecting to friend:");
163 connection = crypto_connect((uint8_t *)friend_id, friend_ip);
164 }
165 }
166 if(inconnection == -1)
167 {
168 uint8_t secret_nonce[crypto_box_NONCEBYTES];
169 uint8_t public_key[crypto_box_PUBLICKEYBYTES];
170 inconnection = crypto_inbound(public_key, secret_nonce);
171 inconnection = accept_crypto_inbound(inconnection, acceptedfriend_public_key, secret_nonce);
172 //inconnection = incoming_connection();
173 if(inconnection != -1)
174 {
175 printf("Someone connected to us:\n");
176 // printip(connection_ip(inconnection));
177 }
178 }
179 if(handle_friendrequest(acceptedfriend_public_key, request_data) > 1)
180 {
181 printf("RECIEVED FRIEND REQUEST: %s\n", request_data);
182 }
183
184 //if someone connected to us write what he sends to a file
185 //also send him our file.
186 if(inconnection != -1)
187 {
188 if(write_cryptpacket(inconnection, buffer1, read1))
189 {
190 printf("Wrote data1.\n");
191 read1 = fread(buffer1, 1, 128, file1);
192 }
193 read2 = read_cryptpacket(inconnection, buffer2);
194 if(read2 != 0)
195 {
196 printf("Received data1.\n");
197 if(!fwrite(buffer2, read2, 1, file2))
198 {
199 printf("file write error1\n");
200 }
201 if(read2 < 128)
202 {
203 printf("Closed file1 %u\n", read2);
204 fclose(file2);
205 }
206 }
207 else if(is_cryptoconnected(inconnection) == 4)//if buffer is empty and the connection timed out.
208 {
209 crypto_kill(inconnection);
210 }
211 }
212 //if we are connected to a friend send him data from the file.
213 //also put what he sends us in a file.
214 if(is_cryptoconnected(connection) >= 3)
215 {
216 if(write_cryptpacket(0, buffer1, read1))
217 {
218 printf("Wrote data2.\n");
219 read1 = fread(buffer1, 1, 128, file1);
220 }
221 read2 = read_cryptpacket(0, buffer2);
222 if(read2 != 0)
223 {
224 printf("Received data2.\n");
225 if(!fwrite(buffer2, read2, 1, file2))
226 {
227 printf("file write error2\n");
228 }
229 if(read2 < 128)
230 {
231 printf("Closed file2 %u\n", read2);
232 fclose(file2);
233 }
234 }
235 else if(is_cryptoconnected(connection) == 4)//if buffer is empty and the connection timed out.
236 {
237 crypto_kill(connection);
238 }
239 }
240 doDHT();
241 doLossless_UDP();
242 doNetCrypto();
243 //print_clientlist();
244 //print_friendlist();
245 //c_sleep(300);
246 c_sleep(1);
247 }
248
249 shutdown_networking();
250 return 0;
251} \ No newline at end of file
diff --git a/testing/DHT_test.c b/testing/DHT_test.c
index 4c1a9cd8..9100c01a 100644
--- a/testing/DHT_test.c
+++ b/testing/DHT_test.c
@@ -80,7 +80,7 @@ void print_friendlist()
80 } 80 }
81} 81}
82 82
83void printpacket(char * data, uint32_t length, IP_Port ip_port) 83void printpacket(uint8_t * data, uint32_t length, IP_Port ip_port)
84{ 84{
85 uint32_t i; 85 uint32_t i;
86 printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length); 86 printf("UNHANDLED PACKET RECEIVED\nLENGTH:%u\nCONTENTS:\n", length);
@@ -102,7 +102,7 @@ int main(int argc, char *argv[])
102 printf("usage %s ip port client_id(of friend to find ip_port of)\n", argv[0]); 102 printf("usage %s ip port client_id(of friend to find ip_port of)\n", argv[0]);
103 exit(0); 103 exit(0);
104 } 104 }
105 addfriend(argv[3]); 105 addfriend((uint8_t *)argv[3]);
106 106
107 //initialize networking 107 //initialize networking
108 //bind to ip 0.0.0.0:PORT 108 //bind to ip 0.0.0.0:PORT
@@ -125,7 +125,7 @@ int main(int argc, char *argv[])
125 bootstrap(bootstrap_ip_port); 125 bootstrap(bootstrap_ip_port);
126 126
127 IP_Port ip_port; 127 IP_Port ip_port;
128 char data[MAX_UDP_PACKET_SIZE]; 128 uint8_t data[MAX_UDP_PACKET_SIZE];
129 uint32_t length; 129 uint32_t length;
130 130
131 while(1) 131 while(1)