secure: replace random() by our own function
[olsrd.git] / lib / secure / src / olsrd_secure.c
1
2 /*
3  * Secure OLSR plugin
4  * http://www.olsr.org
5  *
6  * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or
10  * without modification, are permitted provided that the following
11  * conditions are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  *   notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above copyright
16  *   notice, this list of conditions and the following disclaimer in
17  *   the documentation and/or other materials provided with the
18  *   distribution.
19  * * Neither the name of olsrd, olsr.org nor the names of its
20  *   contributors may be used to endorse or promote products derived
21  *   from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  */
37
38 /* Adjustments made to ensure data going out is converted to network
39  * byte ordering.  Also, to ensure incoming data is converted before
40  * it is used and before checksums are calculated as well.
41  * Rusty Haddock AE5AE -- for the HSMM-MESH project.
42  */
43
44 /*
45  * Dynamic linked library for the olsr.org olsr daemon
46  */
47
48 #include "olsrd_secure.h"
49
50 #include <stdio.h>
51 #include <string.h>
52 #include <stdlib.h>
53 #include <unistd.h>
54 #include <errno.h>
55 #include <signal.h>
56 #include <assert.h>
57
58 #include "defs.h"
59 #include "ipcalc.h"
60 #include "olsr.h"
61 #include "parser.h"
62 #include "scheduler.h"
63 #include "net_olsr.h"
64 #include "olsr_random.h"
65
66 #ifdef USE_OPENSSL
67
68 /* OpenSSL stuff */
69 #include <openssl/sha.h>
70
71 #define CHECKSUM SHA1
72 #define SCHEME   SHA1_INCLUDING_KEY
73
74 #else /* USE_OPENSSL */
75
76 /* Homebrewn checksuming */
77 #include "md5.h"
78
79 static void
80 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
81 {
82   MD5_CTX context;
83
84   MD5Init(&context);
85   MD5Update(&context, data, data_len);
86   MD5Final(hashbuf, &context);
87 }
88
89 #define CHECKSUM MD5_checksum
90 #define SCHEME   MD5_INCLUDING_KEY
91
92 #endif /* USE_OPENSSL */
93
94 #ifdef OS
95 #undef OS
96 #endif /* OS */
97
98 #ifdef _WIN32
99 #define close(x) closesocket(x)
100 #undef EWOULDBLOCK
101 #define EWOULDBLOCK WSAEWOULDBLOCK
102 #define OS "Windows"
103 #endif /* _WIN32 */
104 #ifdef __linux__
105 #define OS "GNU/Linux"
106 #endif /* __linux__ */
107 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
108 #define OS "FreeBSD"
109 #endif /* defined __FreeBSD__ || defined __FreeBSD_kernel__ */
110
111 #ifndef OS
112 #define OS "Undefined"
113 #endif /* OS */
114
115 static struct timeval now;
116
117 /* Timestamp node */
118 struct stamp {
119   union olsr_ip_addr addr;
120   /* Timestamp difference */
121   int diff;
122   uint32_t challenge;
123   uint8_t validated;
124   uint32_t valtime;                     /* Validity time */
125   uint32_t conftime;                    /* Reconfiguration time */
126   struct stamp *prev;
127   struct stamp *next;
128 };
129
130 /* Seconds to cache a valid timestamp entry */
131 #define TIMESTAMP_HOLD_TIME 30
132
133 /* Seconds to cache a not verified timestamp entry */
134 #define EXCHANGE_HOLD_TIME 5
135
136 static struct stamp timestamps[HASHSIZE];
137
138 char keyfile[FILENAME_MAX + 1];
139 char aes_key[16];
140
141 /* Event function to register with the sceduler */
142 static int send_challenge(struct interface_olsr *olsr_if, const union olsr_ip_addr *);
143 static int send_cres(struct interface_olsr *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t, struct stamp *);
144 static int send_rres(struct interface_olsr *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t);
145 static int parse_challenge(struct interface_olsr *olsr_if, char *);
146 static int parse_cres(struct interface_olsr *olsr_if, char *);
147 static int parse_rres(char *);
148 static int check_auth(struct interface_olsr *olsr_if, char *, int *);
149 static int add_signature(uint8_t *, int *);
150 static int validate_packet(struct interface_olsr *olsr_if, const char *, int *);
151 static char *secure_preprocessor(char *packet, struct interface_olsr *olsr_if, union olsr_ip_addr *from_addr, int *length);
152 static void timeout_timestamps(void *);
153 static int check_timestamp(struct interface_olsr *olsr_if, const union olsr_ip_addr *, time_t);
154 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
155 static int read_key_from_file(const char *);
156
157 /**
158  *Do initialization here
159  *
160  *This function is called by the my_init
161  *function in uolsrd_plugin.c
162  */
163
164 int
165 secure_plugin_init(void)
166 {
167   int i;
168
169   /* Initialize the timestamp database */
170   for (i = 0; i < HASHSIZE; i++) {
171     timestamps[i].next = &timestamps[i];
172     timestamps[i].prev = &timestamps[i];
173   }
174   olsr_printf(1, "Timestamp database initialized\n");
175
176   if (!strlen(keyfile))
177     strscpy(keyfile, KEYFILE, sizeof(keyfile));
178
179   i = read_key_from_file(keyfile);
180
181   if (i < 0) {
182     olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
183     exit(1);
184   }
185   if (i == 0) {
186     olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
187     exit(1);
188   }
189
190   /* Register the packet transform function */
191   add_ptf(&add_signature);
192
193   olsr_preprocessor_add_function(&secure_preprocessor);
194
195   /* Register timeout - poll every 2 seconds */
196   olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &timeout_timestamps, NULL, 0);
197
198   return 1;
199 }
200
201 int
202 plugin_ipc_init(void)
203 {
204   return 1;
205 }
206
207 /*
208  * destructor - called at unload
209  */
210 void
211 secure_plugin_exit(void)
212 {
213   olsr_preprocessor_remove_function(&secure_preprocessor);
214 }
215
216 static char *
217 secure_preprocessor(char *packet, struct interface_olsr *olsr_if, union olsr_ip_addr *from_addr, int *length)
218 {
219   struct olsr *olsr = (struct olsr *)packet;
220   struct ipaddr_str buf;
221
222   /*
223    * Check for challenge/response messages
224    */
225   check_auth(olsr_if, packet, length);
226
227   /*
228    * Check signature
229    */
230
231   if (!validate_packet(olsr_if, packet, length)) {
232     olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
233     return NULL;
234   }
235
236   olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
237
238   /* Fix OLSR packet header */
239   olsr->olsr_packlen = htons(*length);
240   return packet;
241 }
242
243 /**
244  * Check a incoming OLSR packet for
245  * challenge/responses.
246  * They need not be verified as they
247  * are signed in the message.
248  *
249  */
250 static int
251 check_auth(struct interface_olsr *olsr_if, char *pck, int *size __attribute__ ((unused)))
252 {
253
254   olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
255
256   switch (pck[4]) {
257   case (TYPE_CHALLENGE):
258     parse_challenge(olsr_if, &pck[4]);
259     break;
260
261   case (TYPE_CRESPONSE):
262     parse_cres(olsr_if, &pck[4]);
263     break;
264
265   case (TYPE_RRESPONSE):
266     parse_rres(&pck[4]);
267     break;
268
269   default:
270     return 0;
271   }
272
273   return 1;
274 }
275
276 /**
277  * Packet transform function
278  * Build a SHA-1/MD5 hash of the original message
279  * + the signature message(-digest) + key
280  *
281  * Then add the signature message to the packet and
282  * increase the size
283  */
284 int
285 add_signature(uint8_t * pck, int *size)
286 {
287   struct s_olsrmsg *msg;
288 #ifdef DEBUG
289   unsigned int i;
290   int j;
291   const uint8_t *sigmsg;
292 #endif /* DEBUG */
293
294   olsr_printf(2, "[ENC]Adding signature for packet size %d\n", *size);
295   fflush(stdout);
296
297   msg = (struct s_olsrmsg *)ARM_NOWARN_ALIGN(&pck[*size]);
298   /* Update size */
299   ((struct olsr *)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
300
301   /* Fill packet header */
302   msg->olsr_msgtype = MESSAGE_TYPE;
303   msg->olsr_vtime = 0;
304   msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
305   memcpy(&msg->originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
306   msg->ttl = 1;
307   msg->hopcnt = 0;
308   msg->seqno = htons(get_msg_seqno());
309
310   /* Fill subheader */
311   msg->sig.type = ONE_CHECKSUM;
312   msg->sig.algorithm = SCHEME;
313   memset(&msg->sig.reserved, 0, 2);
314
315   /* Add timestamp */
316   msg->sig.timestamp = htonl(now.tv_sec);
317 #ifndef _WIN32
318   olsr_printf(3, "[ENC]timestamp: %lld\n", (long long)now.tv_sec);
319 #endif /* _WIN32 */
320   /* Set the new size */
321   *size += sizeof(struct s_olsrmsg);
322
323   {
324     uint8_t checksum_cache[1512 + KEYLENGTH];
325     /* Create packet + key cache */
326     /* First the OLSR packet + signature message - digest */
327     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
328     /* Then the key */
329     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
330
331     /* Create the hash */
332     CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
333   }
334
335 #ifdef DEBUG
336   olsr_printf(1, "Signature message:\n");
337
338   j = 0;
339   sigmsg = (uint8_t *) msg;
340
341   for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
342     olsr_printf(1, "  %3i", sigmsg[i]);
343     j++;
344     if (j == 4) {
345       olsr_printf(1, "\n");
346       j = 0;
347     }
348   }
349 #endif /* DEBUG */
350
351   olsr_printf(3, "[ENC] Message signed\n");
352
353   return 1;
354 }
355
356 static int
357 validate_packet(struct interface_olsr *olsr_if, const char *pck, int *size)
358 {
359   int packetsize;
360   uint8_t sha1_hash[SIGNATURE_SIZE];
361   const struct s_olsrmsg *sig;
362   time_t rec_time;
363
364 #ifdef DEBUG
365   unsigned int i;
366   int j;
367   const uint8_t *sigmsg;
368 #endif /* DEBUG */
369
370   /* Find size - signature message */
371   packetsize = *size - sizeof(struct s_olsrmsg);
372
373   if (packetsize < 4)
374     return 0;
375
376   sig = (const struct s_olsrmsg *)CONST_ARM_NOWARN_ALIGN(&pck[packetsize]);
377
378   //olsr_printf(1, "Size: %d\n", packetsize);
379
380 #ifdef DEBUG
381   olsr_printf(1, "Input message:\n");
382
383   j = 0;
384   sigmsg = (const uint8_t *)sig;
385
386   for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
387     olsr_printf(1, "  %3i", sigmsg[i]);
388     j++;
389     if (j == 4) {
390       olsr_printf(1, "\n");
391       j = 0;
392     }
393   }
394 #endif /* DEBUG */
395
396   /* Sanity check first */
397   if ((sig->olsr_msgtype != MESSAGE_TYPE) || (sig->olsr_vtime != 0)
398       || (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) || (sig->ttl != 1) || (sig->hopcnt != 0)) {
399     olsr_printf(1, "[ENC]Packet not sane!\n");
400     return 0;
401   }
402
403   /* Check scheme and type */
404   switch (sig->sig.type) {
405   case (ONE_CHECKSUM):
406     switch (sig->sig.algorithm) {
407     case (SCHEME):
408       goto one_checksum_SHA;    /* Ahhh... fix this */
409       break;
410     default:
411         break;
412     }
413     break;
414
415   default:
416     olsr_printf(1, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
417     return 0;
418   }
419   //olsr_printf(1, "Packet sane...\n");
420
421 one_checksum_SHA:
422
423   {
424     uint8_t checksum_cache[1512 + KEYLENGTH];
425     /* Create packet + key cache */
426     /* First the OLSR packet + signature message - digest */
427     memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
428     /* Then the key */
429     memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
430
431     /* generate SHA-1 */
432     CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
433   }
434
435 #ifdef DEBUG
436   olsr_printf(1, "Recevied hash:\n");
437
438   sigmsg = (const uint8_t *)sig->sig.signature;
439
440   for (i = 0; i < SIGNATURE_SIZE; i++) {
441     olsr_printf(1, " %3i", sigmsg[i]);
442   }
443   olsr_printf(1, "\n");
444
445   olsr_printf(1, "Calculated hash:\n");
446
447   sigmsg = sha1_hash;
448
449   for (i = 0; i < SIGNATURE_SIZE; i++) {
450     olsr_printf(1, " %3i", sigmsg[i]);
451   }
452   olsr_printf(1, "\n");
453 #endif /* DEBUG */
454
455   if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
456     olsr_printf(1, "[ENC]Signature missmatch\n");
457     return 0;
458   }
459
460   /* Check timestamp */
461   rec_time = ntohl(sig->sig.timestamp);
462
463   if (!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time)) {
464     struct ipaddr_str buf;
465     olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
466                 olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
467     return 0;
468   }
469 #ifndef _WIN32
470   olsr_printf(1, "[ENC]Received timestamp %lld diff: %lld\n", (long long)rec_time, (long long)now.tv_sec - (long long)rec_time);
471 #endif /* _WIN32 */
472   /* Remove signature message */
473   *size = packetsize;
474   return 1;
475 }
476
477 int
478 check_timestamp(struct interface_olsr *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
479 {
480   struct stamp *entry;
481   int diff;
482
483   entry = lookup_timestamp_entry(originator);
484
485   if (!entry) {
486     /* Initiate timestamp negotiation */
487
488     send_challenge(olsr_if, originator);
489
490     return 0;
491   }
492
493   if (!entry->validated) {
494     olsr_printf(1, "[ENC]Message from non-validated host!\n");
495     return 0;
496   }
497
498   diff = entry->diff - (now.tv_sec - tstamp);
499
500   olsr_printf(3, "[ENC]Timestamp slack: %d\n", diff);
501
502   if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
503     olsr_printf(1, "[ENC]Timestamp scew detected!!\n");
504     return 0;
505   }
506
507   /* ok - update diff */
508   entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
509
510   olsr_printf(3, "[ENC]Diff set to : %d\n", entry->diff);
511
512   /* update validtime */
513
514   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
515
516   return 1;
517 }
518
519 /**
520  * Create and send a timestamp
521  * challenge message to new_host
522  *
523  * The host is registered in the timestamps
524  * repository with valid=0
525  */
526
527 int
528 send_challenge(struct interface_olsr *olsr_if, const union olsr_ip_addr *new_host)
529 {
530   struct challengemsg cmsg;
531   struct stamp *entry;
532   uint32_t challenge, hash;
533   struct ipaddr_str buf;
534
535   olsr_printf(1, "[ENC]Building CHALLENGE message\n");
536
537   /* Set the size including OLSR packet size */
538
539   challenge = olsr_random() << 16;
540   challenge |= olsr_random();
541
542   /* initialise rrmsg */
543   memset(&cmsg, 0, sizeof(cmsg));
544
545   /* Fill challengemessage */
546   cmsg.olsr_msgtype = TYPE_CHALLENGE;
547   cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
548   memcpy(&cmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
549   cmsg.ttl = 1;
550   cmsg.seqno = htons(get_msg_seqno());
551
552   /* Fill subheader */
553   assert(olsr_cnf->ipsize == sizeof(cmsg.destination));
554   memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
555   cmsg.challenge = htonl(challenge);
556
557   olsr_printf(3, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
558
559   {
560     uint8_t checksum_cache[(sizeof(cmsg) - sizeof(cmsg.signature)) + KEYLENGTH];
561     /* Create packet + key cache */
562     /* First the OLSR packet + signature message - digest */
563     memcpy(checksum_cache, &cmsg, sizeof(cmsg) - sizeof(cmsg.signature));
564     /* Then the key */
565     memcpy(&checksum_cache[sizeof(cmsg) - sizeof(cmsg.signature)], aes_key, KEYLENGTH);
566
567     /* Create the hash */
568     CHECKSUM(checksum_cache, (sizeof(cmsg) - sizeof(cmsg.signature)) + KEYLENGTH, cmsg.signature);
569   }
570   olsr_printf(3, "[ENC]Sending timestamp request to %s challenge 0x%x\n",
571               olsr_ip_to_string(&buf, new_host), challenge);
572
573   /* Add to buffer */
574   net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
575
576   /* Send the request */
577   net_output(olsr_if);
578
579   /* Create new entry */
580   entry = malloc(sizeof(struct stamp));
581
582   entry->diff = 0;
583   entry->validated = 0;
584   entry->challenge = challenge;
585
586   memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
587
588   /* update validtime - not validated */
589   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
590
591   hash = olsr_ip_hashing(new_host);
592
593   /* Queue */
594   timestamps[hash].next->prev = entry;
595   entry->next = timestamps[hash].next;
596   timestamps[hash].next = entry;
597   entry->prev = &timestamps[hash];
598
599   return 1;
600
601 }
602
603 int
604 parse_cres(struct interface_olsr *olsr_if, char *in_msg)
605 {
606   struct c_respmsg *msg;
607   uint8_t sha1_hash[SIGNATURE_SIZE];
608   struct stamp *entry;
609   struct ipaddr_str buf;
610
611   msg = (struct c_respmsg *)ARM_NOWARN_ALIGN(in_msg);
612
613   olsr_printf(1, "[ENC]Challenge-response message received\n");
614   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
615
616   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
617     olsr_printf(3, "[ENC]Not for us...\n");
618     return 0;
619   }
620
621   olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));      /* ntohl() returns a unsignedlong onwin32 */
622
623   /* Check signature */
624
625   {
626     uint8_t checksum_cache[1512 + KEYLENGTH];
627     /* Create packet + key cache */
628     /* First the OLSR packet + signature message - digest */
629     memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
630     /* Then the key */
631     memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
632
633     /* Create the hash */
634     CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
635   }
636
637   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
638     olsr_printf(1, "[ENC]Signature missmatch in challenge-response!\n");
639     return 0;
640   }
641
642   olsr_printf(3, "[ENC]Signature verified\n");
643
644   /* Now to check the digest from the emitted challenge */
645   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
646     olsr_printf(1, "[ENC]Received challenge-response from non-registered node %s!\n",
647                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
648     return 0;
649   }
650
651   /* Generate the digest */
652   olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
653
654   {
655     uint8_t checksum_cache[1512 + KEYLENGTH];
656     uint32_t netorder_challenge;
657
658     /* First the challenge received */
659     /* But we have to calculate our hash with the challenge in
660      * network order just like the remote host did!  6-Jun-2011 AE5AE */
661     netorder_challenge = htonl(entry->challenge);
662     memcpy(checksum_cache, &netorder_challenge, sizeof(uint32_t));
663 /*     memcpy(checksum_cache, &entry->challenge, 4); */
664
665     /* Then the local IP */
666     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
667
668     /* Create the hash */
669     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
670   }
671
672   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
673     olsr_printf(1, "[ENC]Error in challenge signature from %s!\n",
674                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
675
676     return 0;
677   }
678
679   olsr_printf(3, "[ENC]Challenge-response signature ok\n");
680
681   /* Update entry! */
682
683   entry->challenge = 0;
684   entry->validated = 1;
685
686   /* Bring timestamp to host order before arith. 2011/05/31 AE5AE */
687   entry->diff = now.tv_sec - ntohl(msg->timestamp);
688
689   /* update validtime - validated entry */
690   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
691
692   olsr_printf(1, "[ENC]%s registered with diff %d!\n",
693               olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
694               entry->diff);
695
696   /* Send response-response */
697   send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator,
698             (union olsr_ip_addr *)&msg->destination, msg->challenge);
699 /*          (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge)); */
700 /* Don't give send_rres() the challenge in host order, as the checksum needs to
701  * be calculated in network order.   06-Jun-2011  AE5AE */
702
703   return 1;
704 }
705
706 int
707 parse_rres(char *in_msg)
708 {
709   struct r_respmsg *msg;
710   uint8_t sha1_hash[SIGNATURE_SIZE];
711   struct stamp *entry;
712   struct ipaddr_str buf;
713
714   msg = (struct r_respmsg *)ARM_NOWARN_ALIGN(in_msg);
715
716   olsr_printf(1, "[ENC]Response-response message received\n");
717   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
718
719   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
720     olsr_printf(1, "[ENC]Not for us...\n");
721     return 0;
722   }
723
724   /* Check signature */
725
726   {
727     uint8_t checksum_cache[1512 + KEYLENGTH];
728     /* Create packet + key cache */
729     /* First the OLSR packet + signature message - digest */
730     memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
731     /* Then the key */
732     memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
733
734     /* Create the hash */
735     CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
736   }
737
738   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
739     olsr_printf(1, "[ENC]Signature missmatch in response-response!\n");
740     return 0;
741   }
742
743   olsr_printf(3, "[ENC]Signature verified\n");
744
745   /* Now to check the digest from the emitted challenge */
746   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
747     olsr_printf(1, "[ENC]Received response-response from non-registered node %s!\n",
748                 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
749     return 0;
750   }
751
752   /* Generate the digest */
753   olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
754
755   {
756     uint8_t checksum_cache[1512 + KEYLENGTH];
757     uint32_t netorder_challenge;
758
759     /* First the challenge received */
760     /* But we have to calculate our hash with the challenge in network order!  6-Jun-2011 AE5AE */
761     netorder_challenge = htonl(entry->challenge);
762     memcpy(checksum_cache, &netorder_challenge, sizeof(uint32_t));
763 /*     memcpy(checksum_cache, &entry->challenge, 4); */
764
765     /* Then the local IP */
766     memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
767
768     /* Create the hash */
769     CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
770   }
771
772   if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
773     olsr_printf(1, "[ENC]Error in response signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
774
775     return 0;
776   }
777
778   olsr_printf(3, "[ENC]Challenge-response signature ok\n");
779
780   /* Update entry! */
781
782   entry->challenge = 0;
783   entry->validated = 1;
784
785   /* Bring timestamp to host order before arith. 2011/05/31 AE5AE */
786   entry->diff = now.tv_sec - ntohl(msg->timestamp);
787
788
789   /* update validtime - validated entry */
790   entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
791
792   olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
793               entry->diff);
794
795   return 1;
796 }
797
798 int
799 parse_challenge(struct interface_olsr *olsr_if, char *in_msg)
800 {
801   struct challengemsg *msg;
802   uint8_t sha1_hash[SIGNATURE_SIZE];
803   struct stamp *entry;
804   uint32_t hash;
805   struct ipaddr_str buf;
806
807   msg = (struct challengemsg *)ARM_NOWARN_ALIGN(in_msg);
808
809   olsr_printf(1, "[ENC]Challenge message received\n");
810   olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
811
812   if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
813     olsr_printf(1, "[ENC]Not for us...\n");
814     return 0;
815   }
816
817   /* Create entry if not registered */
818   if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
819     entry = malloc(sizeof(struct stamp));
820     memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
821
822     hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
823
824     /* Queue */
825     timestamps[hash].next->prev = entry;
826     entry->next = timestamps[hash].next;
827     timestamps[hash].next = entry;
828     entry->prev = &timestamps[hash];
829   } else {
830     /* Check configuration timeout */
831     if (!TIMED_OUT(entry->conftime)) {
832       /* If registered - do not accept! */
833       olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
834       return 0;
835     } else {
836       olsr_printf(1, "[ENC]Challenge from registered node...accepted!\n");
837     }
838   }
839
840   olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge));      /* ntohl() returns a unsignedlong onwin32 */
841
842   /* Check signature */
843
844   {
845     uint8_t checksum_cache[1512 + KEYLENGTH];
846     /* Create packet + key cache */
847     /* First the OLSR packet + signature message - digest */
848     memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
849     /* Then the key */
850     memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
851
852     /* Create the hash */
853     CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
854   }
855   if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
856     olsr_printf(1, "[ENC]Signature missmatch in challenge!\n");
857     return 0;
858   }
859
860   olsr_printf(3, "[ENC]Signature verified\n");
861
862   entry->diff = 0;
863   entry->validated = 0;
864
865   /* update validtime - not validated */
866   entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
867
868   /* Build and send response */
869
870   send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator,
871             (union olsr_ip_addr *)&msg->destination, msg->challenge, entry);
872 /*          (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry); */
873 /* Don't give send_cres() the challenge in host order, as the checksum needs to
874  * be calculated with network order.   06-Jun-2011  AE5AE */
875
876   return 1;
877 }
878
879 /**
880  * Build and transmit a challenge response
881  * message.
882  *
883  */
884 int
885 send_cres(struct interface_olsr *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in, struct stamp *entry)
886 {
887   struct c_respmsg crmsg;
888   uint32_t challenge;
889   struct ipaddr_str buf;
890
891   olsr_printf(1, "[ENC]Building CRESPONSE message\n");
892
893   challenge = olsr_random() << 16;
894   challenge |= olsr_random();
895
896   entry->challenge = challenge;
897
898   olsr_printf(3, "[ENC]Challenge-response: 0x%x\n", challenge);
899
900   /* initialise rrmsg */
901   memset(&crmsg, 0, sizeof(crmsg));
902
903   /* Fill challengemessage */
904   crmsg.olsr_msgtype = TYPE_CRESPONSE;
905   crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
906   memcpy(&crmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
907   crmsg.ttl = 1;
908   crmsg.seqno = htons(get_msg_seqno());
909
910   /* set timestamp */
911   /* but swap the byte order to the network order before sending!  2011/05/28 AE5AE */
912   crmsg.timestamp = htonl(now.tv_sec);
913 #ifndef _WIN32
914   /* Don't print htonl()'d time, use now.tv_sec 2011/05/31 AE5AE */
915 /*   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)crmsg.timestamp); */
916   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)now.tv_sec);
917 #endif /* _WIN32 */
918
919   /* Fill subheader */
920   assert(olsr_cnf->ipsize == sizeof(crmsg.destination));
921   memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
922   crmsg.challenge = htonl(challenge);
923
924   /* Create digest of received challenge + IP */
925
926   {
927     uint8_t checksum_cache[sizeof(chal_in) + olsr_cnf->ipsize];
928     /* Create packet + key cache */
929     /* First the challenge received */
930     memcpy(checksum_cache, &chal_in, sizeof(chal_in));
931     /* Then the local IP */
932     memcpy(&checksum_cache[sizeof(chal_in)], from, olsr_cnf->ipsize);
933
934     /* Create the hash */
935     CHECKSUM(checksum_cache, sizeof(chal_in) + olsr_cnf->ipsize, crmsg.res_sig);
936   }
937
938   /* Now create the digest of the message and the key */
939
940   {
941     uint8_t checksum_cache[(sizeof(crmsg) - sizeof(crmsg.signature)) + KEYLENGTH];
942     /* Create packet + key cache */
943     /* First the OLSR packet + signature message - digest */
944     memcpy(checksum_cache, &crmsg, sizeof(crmsg) - sizeof(crmsg.signature));
945     /* Then the key */
946     memcpy(&checksum_cache[sizeof(crmsg) - sizeof(crmsg.signature)], aes_key, KEYLENGTH);
947
948     /* Create the hash */
949     CHECKSUM(checksum_cache, (sizeof(crmsg) - sizeof(crmsg.signature)) + KEYLENGTH, crmsg.signature);
950   }
951
952   olsr_printf(3, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
953
954   /* Add to buffer */
955   net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
956   /* Send the request */
957   net_output(olsr_if);
958
959   return 1;
960 }
961
962 /**
963  * Build and transmit a response response
964  * message.
965  *
966  */
967 static int
968 send_rres(struct interface_olsr *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
969 {
970   struct r_respmsg rrmsg;
971   struct ipaddr_str buf;
972
973   olsr_printf(1, "[ENC]Building RRESPONSE message\n");
974
975   /* initialise rrmsg */
976   memset(&rrmsg, 0, sizeof(rrmsg));
977
978   /* Fill challengemessage */
979   rrmsg.olsr_msgtype = TYPE_RRESPONSE;
980   rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
981   memcpy(&rrmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
982   rrmsg.ttl = 1;
983   rrmsg.seqno = htons(get_msg_seqno());
984
985   /* set timestamp */
986   /* But swap the byte order to the network order!  2011/05/28 AE5AE */
987   rrmsg.timestamp = htonl(now.tv_sec);
988
989 #ifndef _WIN32
990   /* olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)rrmsg.timestamp); */
991   /* don't print htonl()'d time, use now. 2011/05/31 AE5AE */
992   olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)now.tv_sec);
993 #endif /* _WIN32 */
994   /* Fill subheader */
995   assert(olsr_cnf->ipsize == sizeof(rrmsg.destination));
996   memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
997
998   /* Create digest of received challenge + IP */
999
1000   {
1001     uint8_t checksum_cache[sizeof(chal_in) + sizeof(union olsr_ip_addr)];
1002     /* Create packet + key cache */
1003     /* First the challenge received */
1004     memcpy(checksum_cache, &chal_in, sizeof(chal_in));
1005     /* Then the local IP */
1006     memcpy(&checksum_cache[sizeof(chal_in)], from, olsr_cnf->ipsize);
1007
1008     /* Create the hash */
1009     CHECKSUM(checksum_cache, sizeof(chal_in) + olsr_cnf->ipsize, rrmsg.res_sig);
1010   }
1011
1012   /* Now create the digest of the message and the key */
1013
1014   {
1015     uint8_t checksum_cache[(sizeof(rrmsg) - sizeof(rrmsg.signature)) + KEYLENGTH];
1016     /* Create packet + key cache */
1017     /* First the OLSR packet + signature message - digest */
1018     memcpy(checksum_cache, &rrmsg, sizeof(rrmsg) - sizeof(rrmsg.signature));
1019     /* Then the key */
1020     memcpy(&checksum_cache[sizeof(rrmsg) - sizeof(rrmsg.signature)], aes_key, KEYLENGTH);
1021
1022     /* Create the hash */
1023     CHECKSUM(checksum_cache, (sizeof(rrmsg) - sizeof(rrmsg.signature)) + KEYLENGTH, rrmsg.signature);
1024   }
1025
1026   olsr_printf(3, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1027
1028   /* add to buffer */
1029   net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
1030
1031   /* Send the request */
1032   net_output(olsr_if);
1033
1034   return 1;
1035 }
1036
1037 static struct stamp *
1038 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1039 {
1040   uint32_t hash;
1041   struct stamp *entry;
1042   struct ipaddr_str buf;
1043
1044   hash = olsr_ip_hashing(adr);
1045
1046   for (entry = timestamps[hash].next; entry != &timestamps[hash]; entry = entry->next) {
1047     if (memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0) {
1048       olsr_printf(3, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
1049       return entry;
1050     }
1051   }
1052
1053   olsr_printf(1, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1054
1055   return NULL;
1056 }
1057
1058 /**
1059  *Find timed out entries and delete them
1060  *
1061  *@return nada
1062  */
1063 void
1064 timeout_timestamps(void *foo __attribute__ ((unused)))
1065 {
1066   struct stamp *tmp_list;
1067   struct stamp *entry_to_delete;
1068   int idx;
1069
1070   /* Update our local timestamp */
1071   gettimeofday(&now, NULL);
1072
1073   for (idx = 0; idx < HASHSIZE; idx++) {
1074     tmp_list = timestamps[idx].next;
1075     /*Traverse MID list */
1076     while (tmp_list != &timestamps[idx]) {
1077       /*Check if the entry is timed out */
1078       if ((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime))) {
1079         struct ipaddr_str buf;
1080         entry_to_delete = tmp_list;
1081         tmp_list = tmp_list->next;
1082
1083         olsr_printf(1, "[ENC]timestamp info for %s timed out.. deleting it\n",
1084                     olsr_ip_to_string(&buf, &entry_to_delete->addr));
1085
1086         /*Delete it */
1087         entry_to_delete->next->prev = entry_to_delete->prev;
1088         entry_to_delete->prev->next = entry_to_delete->next;
1089
1090         free(entry_to_delete);
1091       } else
1092         tmp_list = tmp_list->next;
1093     }
1094   }
1095
1096   return;
1097 }
1098
1099 static int
1100 read_key_from_file(const char *file)
1101 {
1102   FILE *kf;
1103   size_t keylen;
1104
1105   keylen = 16;
1106   kf = fopen(file, "r");
1107
1108   olsr_printf(1, "[ENC]Reading key from file \"%s\"\n", file);
1109
1110   if (kf == NULL) {
1111     olsr_printf(1, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
1112     return -1;
1113   }
1114
1115   if (fread(aes_key, 1, keylen, kf) != keylen) {
1116     olsr_printf(1, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
1117     fclose(kf);
1118     return 0;
1119   }
1120
1121   fclose(kf);
1122   return 1;
1123 }
1124
1125 /*
1126  * Local Variables:
1127  * c-basic-offset: 2
1128  * indent-tabs-mode: nil
1129  * End:
1130  */