6 * Copyright (c) 2004, Andreas Tonnesen(andreto@olsr.org)
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the following
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
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.
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.
39 * Dynamic linked library for the olsr.org olsr daemon
42 #include "olsrd_secure.h"
55 #include "scheduler.h"
61 #include <openssl/sha.h>
64 #define SCHEME SHA1_INCLUDING_KEY
68 /* Homebrewn checksuming */
72 MD5_checksum(const uint8_t * data, const uint16_t data_len, uint8_t * hashbuf)
77 MD5Update(&context, data, data_len);
78 MD5Final(hashbuf, &context);
81 #define CHECKSUM MD5_checksum
82 #define SCHEME MD5_INCLUDING_KEY
91 #define close(x) closesocket(x)
93 #define EWOULDBLOCK WSAEWOULDBLOCK
97 #define OS "GNU/Linux"
99 #if defined __FreeBSD__ || defined __FreeBSD_kernel__
104 #define OS "Undefined"
107 static struct timeval now;
111 union olsr_ip_addr addr;
112 /* Timestamp difference */
116 uint32_t valtime; /* Validity time */
117 uint32_t conftime; /* Reconfiguration time */
122 /* Seconds to cache a valid timestamp entry */
123 #define TIMESTAMP_HOLD_TIME 30
125 /* Seconds to cache a not verified timestamp entry */
126 #define EXCHANGE_HOLD_TIME 5
128 static struct stamp timestamps[HASHSIZE];
130 char keyfile[FILENAME_MAX + 1];
133 /* Event function to register with the sceduler */
135 static void olsr_event(void);
137 static int send_challenge(struct interface *olsr_if, const union olsr_ip_addr *);
138 static int send_cres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t, struct stamp *);
139 static int send_rres(struct interface *olsr_if, union olsr_ip_addr *, union olsr_ip_addr *, uint32_t);
140 static int parse_challenge(struct interface *olsr_if, char *);
141 static int parse_cres(struct interface *olsr_if, char *);
142 static int parse_rres(char *);
143 static int check_auth(struct interface *olsr_if, char *, int *);
145 static int ipc_send(char *, int);
147 static int add_signature(uint8_t *, int *);
148 static int validate_packet(struct interface *olsr_if, const char *, int *);
149 static char *secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length);
150 static void timeout_timestamps(void *);
151 static int check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *, time_t);
152 static struct stamp *lookup_timestamp_entry(const union olsr_ip_addr *);
153 static int read_key_from_file(const char *);
156 *Do initialization here
158 *This function is called by the my_init
159 *function in uolsrd_plugin.c
163 secure_plugin_init(void)
167 /* Initialize the timestamp database */
168 for (i = 0; i < HASHSIZE; i++) {
169 timestamps[i].next = ×tamps[i];
170 timestamps[i].prev = ×tamps[i];
172 olsr_printf(1, "Timestamp database initialized\n");
174 if (!strlen(keyfile))
175 strscpy(keyfile, KEYFILE, sizeof(keyfile));
177 i = read_key_from_file(keyfile);
180 olsr_printf(1, "[ENC]Could not read key from file %s!\nExitting!\n\n", keyfile);
184 olsr_printf(1, "[ENC]There was a problem reading key from file %s. Is the key long enough?\nExitting!\n\n", keyfile);
188 /* Register the packet transform function */
189 add_ptf(&add_signature);
191 olsr_preprocessor_add_function(&secure_preprocessor);
193 /* Register timeout - poll every 2 seconds */
194 olsr_start_timer(2 * MSEC_PER_SEC, 0, OLSR_TIMER_PERIODIC, &timeout_timestamps, NULL, 0);
200 plugin_ipc_init(void)
206 * destructor - called at unload
209 secure_plugin_exit(void)
211 olsr_preprocessor_remove_function(&secure_preprocessor);
228 ipc_send(char *data __attribute__ ((unused)), int size __attribute__ ((unused)))
235 secure_preprocessor(char *packet, struct interface *olsr_if, union olsr_ip_addr *from_addr, int *length)
237 struct olsr *olsr = (struct olsr *)packet;
238 struct ipaddr_str buf;
241 * Check for challenge/response messages
243 check_auth(olsr_if, packet, length);
249 if (!validate_packet(olsr_if, packet, length)) {
250 olsr_printf(1, "[ENC]Rejecting packet from %s\n", olsr_ip_to_string(&buf, from_addr));
254 olsr_printf(1, "[ENC]Packet from %s OK size %d\n", olsr_ip_to_string(&buf, from_addr), *length);
256 /* Fix OLSR packet header */
257 olsr->olsr_packlen = htons(*length);
262 * Check a incoming OLSR packet for
263 * challenge/responses.
264 * They need not be verified as they
265 * are signed in the message.
269 check_auth(struct interface *olsr_if, char *pck, int *size __attribute__ ((unused)))
272 olsr_printf(3, "[ENC]Checking packet for challenge response message...\n");
275 case (TYPE_CHALLENGE):
276 parse_challenge(olsr_if, &pck[4]);
279 case (TYPE_CRESPONSE):
280 parse_cres(olsr_if, &pck[4]);
283 case (TYPE_RRESPONSE):
295 * Packet transform function
296 * Build a SHA-1/MD5 hash of the original message
297 * + the signature message(-digest) + key
299 * Then add the signature message to the packet and
303 add_signature(uint8_t * pck, int *size)
305 struct s_olsrmsg *msg;
309 const uint8_t *sigmsg;
312 olsr_printf(2, "[ENC]Adding signature for packet size %d\n", *size);
315 msg = (struct s_olsrmsg *)(ARM_NOWARN_ALIGN)&pck[*size];
317 ((struct olsr *)pck)->olsr_packlen = htons(*size + sizeof(struct s_olsrmsg));
319 /* Fill packet header */
320 msg->olsr_msgtype = MESSAGE_TYPE;
322 msg->olsr_msgsize = htons(sizeof(struct s_olsrmsg));
323 memcpy(&msg->originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
326 msg->seqno = htons(get_msg_seqno());
329 msg->sig.type = ONE_CHECKSUM;
330 msg->sig.algorithm = SCHEME;
331 memset(&msg->sig.reserved, 0, 2);
334 msg->sig.timestamp = htonl(now.tv_sec);
336 olsr_printf(3, "[ENC]timestamp: %lld\n", (long long)now.tv_sec);
338 /* Set the new size */
339 *size += sizeof(struct s_olsrmsg);
342 uint8_t checksum_cache[512 + KEYLENGTH];
343 /* Create packet + key cache */
344 /* First the OLSR packet + signature message - digest */
345 memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
347 memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
349 /* Create the hash */
350 CHECKSUM(checksum_cache, (*size - SIGNATURE_SIZE) + KEYLENGTH, &pck[*size - SIGNATURE_SIZE]);
354 olsr_printf(1, "Signature message:\n");
357 sigmsg = (uint8_t *) msg;
359 for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
360 olsr_printf(1, " %3i", sigmsg[i]);
363 olsr_printf(1, "\n");
369 olsr_printf(3, "[ENC] Message signed\n");
375 validate_packet(struct interface *olsr_if, const char *pck, int *size)
378 uint8_t sha1_hash[SIGNATURE_SIZE];
379 const struct s_olsrmsg *sig;
385 const uint8_t *sigmsg;
388 /* Find size - signature message */
389 packetsize = *size - sizeof(struct s_olsrmsg);
394 sig = (const struct s_olsrmsg *)(const ARM_NOWARN_ALIGN)&pck[packetsize];
396 //olsr_printf(1, "Size: %d\n", packetsize);
399 olsr_printf(1, "Input message:\n");
402 sigmsg = (const uint8_t *)sig;
404 for (i = 0; i < sizeof(struct s_olsrmsg); i++) {
405 olsr_printf(1, " %3i", sigmsg[i]);
408 olsr_printf(1, "\n");
414 /* Sanity check first */
415 if ((sig->olsr_msgtype != MESSAGE_TYPE) || (sig->olsr_vtime != 0)
416 || (sig->olsr_msgsize != ntohs(sizeof(struct s_olsrmsg))) || (sig->ttl != 1) || (sig->hopcnt != 0)) {
417 olsr_printf(1, "[ENC]Packet not sane!\n");
421 /* Check scheme and type */
422 switch (sig->sig.type) {
424 switch (sig->sig.algorithm) {
426 goto one_checksum_SHA; /* Ahhh... fix this */
433 olsr_printf(1, "[ENC]Unsupported sceme: %d enc: %d!\n", sig->sig.type, sig->sig.algorithm);
436 //olsr_printf(1, "Packet sane...\n");
441 uint8_t checksum_cache[512 + KEYLENGTH];
442 /* Create packet + key cache */
443 /* First the OLSR packet + signature message - digest */
444 memcpy(checksum_cache, pck, *size - SIGNATURE_SIZE);
446 memcpy(&checksum_cache[*size - SIGNATURE_SIZE], aes_key, KEYLENGTH);
449 CHECKSUM(checksum_cache, *size - SIGNATURE_SIZE + KEYLENGTH, sha1_hash);
453 olsr_printf(1, "Recevied hash:\n");
455 sigmsg = (const uint8_t *)sig->sig.signature;
457 for (i = 0; i < SIGNATURE_SIZE; i++) {
458 olsr_printf(1, " %3i", sigmsg[i]);
460 olsr_printf(1, "\n");
462 olsr_printf(1, "Calculated hash:\n");
466 for (i = 0; i < SIGNATURE_SIZE; i++) {
467 olsr_printf(1, " %3i", sigmsg[i]);
469 olsr_printf(1, "\n");
472 if (memcmp(sha1_hash, sig->sig.signature, SIGNATURE_SIZE) != 0) {
473 olsr_printf(1, "[ENC]Signature missmatch\n");
477 /* Check timestamp */
478 rec_time = ntohl(sig->sig.timestamp);
480 if (!check_timestamp(olsr_if, (const union olsr_ip_addr *)&sig->originator, rec_time)) {
481 struct ipaddr_str buf;
482 olsr_printf(1, "[ENC]Timestamp missmatch in packet from %s!\n",
483 olsr_ip_to_string(&buf, (const union olsr_ip_addr *)&sig->originator));
487 olsr_printf(1, "[ENC]Received timestamp %lld diff: %lld\n", (long long)rec_time, (long long)now.tv_sec - (long long)rec_time);
489 /* Remove signature message */
495 check_timestamp(struct interface *olsr_if, const union olsr_ip_addr *originator, time_t tstamp)
500 entry = lookup_timestamp_entry(originator);
503 /* Initiate timestamp negotiation */
505 send_challenge(olsr_if, originator);
510 if (!entry->validated) {
511 olsr_printf(1, "[ENC]Message from non-validated host!\n");
515 diff = entry->diff - (now.tv_sec - tstamp);
517 olsr_printf(3, "[ENC]Timestamp slack: %d\n", diff);
519 if ((diff > UPPER_DIFF) || (diff < LOWER_DIFF)) {
520 olsr_printf(1, "[ENC]Timestamp scew detected!!\n");
524 /* ok - update diff */
525 entry->diff = ((now.tv_sec - tstamp) + entry->diff) ? ((now.tv_sec - tstamp) + entry->diff) / 2 : 0;
527 olsr_printf(3, "[ENC]Diff set to : %d\n", entry->diff);
529 /* update validtime */
531 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
537 * Create and send a timestamp
538 * challenge message to new_host
540 * The host is registered in the timestamps
541 * repository with valid=0
545 send_challenge(struct interface *olsr_if, const union olsr_ip_addr *new_host)
547 struct challengemsg cmsg;
549 uint32_t challenge, hash;
550 struct ipaddr_str buf;
552 olsr_printf(1, "[ENC]Building CHALLENGE message\n");
554 /* Set the size including OLSR packet size */
556 challenge = rand() << 16;
559 /* Fill challengemessage */
560 cmsg.olsr_msgtype = TYPE_CHALLENGE;
562 cmsg.olsr_msgsize = htons(sizeof(struct challengemsg));
563 memcpy(&cmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
566 cmsg.seqno = htons(get_msg_seqno());
569 memcpy(&cmsg.destination, new_host, olsr_cnf->ipsize);
570 cmsg.challenge = htonl(challenge);
572 olsr_printf(3, "[ENC]Size: %lu\n", (unsigned long)sizeof(struct challengemsg));
575 uint8_t checksum_cache[512 + KEYLENGTH];
576 /* Create packet + key cache */
577 /* First the OLSR packet + signature message - digest */
578 memcpy(checksum_cache, &cmsg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
580 memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
582 /* Create the hash */
583 CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, cmsg.signature);
585 olsr_printf(3, "[ENC]Sending timestamp request to %s challenge 0x%x\n", olsr_ip_to_string(&buf, new_host), challenge);
588 net_outbuffer_push(olsr_if, &cmsg, sizeof(struct challengemsg));
590 /* Send the request */
593 /* Create new entry */
594 entry = malloc(sizeof(struct stamp));
597 entry->validated = 0;
598 entry->challenge = challenge;
600 memcpy(&entry->addr, new_host, olsr_cnf->ipsize);
602 /* update validtime - not validated */
603 entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
605 hash = olsr_ip_hashing(new_host);
608 timestamps[hash].next->prev = entry;
609 entry->next = timestamps[hash].next;
610 timestamps[hash].next = entry;
611 entry->prev = ×tamps[hash];
618 parse_cres(struct interface *olsr_if, char *in_msg)
620 struct c_respmsg *msg;
621 uint8_t sha1_hash[SIGNATURE_SIZE];
623 struct ipaddr_str buf;
625 msg = (struct c_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
627 olsr_printf(1, "[ENC]Challenge-response message received\n");
628 olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
630 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
631 olsr_printf(3, "[ENC]Not for us...\n");
635 olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
637 /* Check signature */
640 uint8_t checksum_cache[512 + KEYLENGTH];
641 /* Create packet + key cache */
642 /* First the OLSR packet + signature message - digest */
643 memcpy(checksum_cache, msg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
645 memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
647 /* Create the hash */
648 CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
651 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
652 olsr_printf(1, "[ENC]Signature missmatch in challenge-response!\n");
656 olsr_printf(3, "[ENC]Signature verified\n");
658 /* Now to check the digest from the emitted challenge */
659 if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
660 olsr_printf(1, "[ENC]Received challenge-response from non-registered node %s!\n",
661 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
665 /* Generate the digest */
666 olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
669 uint8_t checksum_cache[512 + KEYLENGTH];
670 /* First the challenge received */
671 memcpy(checksum_cache, &entry->challenge, 4);
672 /* Then the local IP */
673 memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
675 /* Create the hash */
676 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
679 if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
680 olsr_printf(1, "[ENC]Error in challenge signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
685 olsr_printf(3, "[ENC]Challenge-response signature ok\n");
689 entry->challenge = 0;
690 entry->validated = 1;
691 entry->diff = now.tv_sec - msg->timestamp;
693 /* update validtime - validated entry */
694 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
696 olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
699 /* Send response-response */
700 send_rres(olsr_if, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge));
706 parse_rres(char *in_msg)
708 struct r_respmsg *msg;
709 uint8_t sha1_hash[SIGNATURE_SIZE];
711 struct ipaddr_str buf;
713 msg = (struct r_respmsg *)(ARM_NOWARN_ALIGN)in_msg;
715 olsr_printf(1, "[ENC]Response-response message received\n");
716 olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
718 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
719 olsr_printf(1, "[ENC]Not for us...\n");
723 /* Check signature */
726 uint8_t checksum_cache[512 + KEYLENGTH];
727 /* Create packet + key cache */
728 /* First the OLSR packet + signature message - digest */
729 memcpy(checksum_cache, msg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
731 memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
733 /* Create the hash */
734 CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
737 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
738 olsr_printf(1, "[ENC]Signature missmatch in response-response!\n");
742 olsr_printf(3, "[ENC]Signature verified\n");
744 /* Now to check the digest from the emitted challenge */
745 if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
746 olsr_printf(1, "[ENC]Received response-response from non-registered node %s!\n",
747 olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
751 /* Generate the digest */
752 olsr_printf(3, "[ENC]Entry-challenge 0x%x\n", entry->challenge);
755 uint8_t checksum_cache[512 + KEYLENGTH];
756 /* First the challenge received */
757 memcpy(checksum_cache, &entry->challenge, 4);
758 /* Then the local IP */
759 memcpy(&checksum_cache[sizeof(uint32_t)], &msg->originator, olsr_cnf->ipsize);
761 /* Create the hash */
762 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, sha1_hash);
765 if (memcmp(msg->res_sig, sha1_hash, SIGNATURE_SIZE) != 0) {
766 olsr_printf(1, "[ENC]Error in response signature from %s!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator));
771 olsr_printf(3, "[ENC]Challenge-response signature ok\n");
775 entry->challenge = 0;
776 entry->validated = 1;
777 entry->diff = now.tv_sec - msg->timestamp;
779 /* update validtime - validated entry */
780 entry->valtime = GET_TIMESTAMP(TIMESTAMP_HOLD_TIME * 1000);
782 olsr_printf(1, "[ENC]%s registered with diff %d!\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->originator),
789 parse_challenge(struct interface *olsr_if, char *in_msg)
791 struct challengemsg *msg;
792 uint8_t sha1_hash[SIGNATURE_SIZE];
795 struct ipaddr_str buf;
797 msg = (struct challengemsg *)(ARM_NOWARN_ALIGN)in_msg;
799 olsr_printf(1, "[ENC]Challenge message received\n");
800 olsr_printf(3, "[ENC]To: %s\n", olsr_ip_to_string(&buf, (union olsr_ip_addr *)&msg->destination));
802 if (if_ifwithaddr((union olsr_ip_addr *)&msg->destination) == NULL) {
803 olsr_printf(1, "[ENC]Not for us...\n");
807 /* Create entry if not registered */
808 if ((entry = lookup_timestamp_entry((const union olsr_ip_addr *)&msg->originator)) == NULL) {
809 entry = malloc(sizeof(struct stamp));
810 memcpy(&entry->addr, &msg->originator, olsr_cnf->ipsize);
812 hash = olsr_ip_hashing((union olsr_ip_addr *)&msg->originator);
815 timestamps[hash].next->prev = entry;
816 entry->next = timestamps[hash].next;
817 timestamps[hash].next = entry;
818 entry->prev = ×tamps[hash];
820 /* Check configuration timeout */
821 if (!TIMED_OUT(entry->conftime)) {
822 /* If registered - do not accept! */
823 olsr_printf(1, "[ENC]Challenge from registered node...dropping!\n");
826 olsr_printf(1, "[ENC]Challenge from registered node...accepted!\n");
830 olsr_printf(3, "[ENC]Challenge: 0x%lx\n", (unsigned long)ntohl(msg->challenge)); /* ntohl() returns a unsignedlong onwin32 */
832 /* Check signature */
835 uint8_t checksum_cache[512 + KEYLENGTH];
836 /* Create packet + key cache */
837 /* First the OLSR packet + signature message - digest */
838 memcpy(checksum_cache, msg, sizeof(struct challengemsg) - SIGNATURE_SIZE);
840 memcpy(&checksum_cache[sizeof(struct challengemsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
842 /* Create the hash */
843 CHECKSUM(checksum_cache, (sizeof(struct challengemsg) - SIGNATURE_SIZE) + KEYLENGTH, sha1_hash);
845 if (memcmp(sha1_hash, &msg->signature, SIGNATURE_SIZE) != 0) {
846 olsr_printf(1, "[ENC]Signature missmatch in challenge!\n");
850 olsr_printf(3, "[ENC]Signature verified\n");
853 entry->validated = 0;
855 /* update validtime - not validated */
856 entry->conftime = GET_TIMESTAMP(EXCHANGE_HOLD_TIME * 1000);
858 /* Build and send response */
860 send_cres(olsr_if, (union olsr_ip_addr *)&msg->originator, (union olsr_ip_addr *)&msg->destination, ntohl(msg->challenge), entry);
866 * Build and transmit a challenge response
871 send_cres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in, struct stamp *entry)
873 struct c_respmsg crmsg;
875 struct ipaddr_str buf;
877 olsr_printf(1, "[ENC]Building CRESPONSE message\n");
879 challenge = rand() << 16;
882 entry->challenge = challenge;
884 olsr_printf(3, "[ENC]Challenge-response: 0x%x\n", challenge);
886 /* Fill challengemessage */
887 crmsg.olsr_msgtype = TYPE_CRESPONSE;
888 crmsg.olsr_vtime = 0;
889 crmsg.olsr_msgsize = htons(sizeof(struct c_respmsg));
890 memcpy(&crmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
893 crmsg.seqno = htons(get_msg_seqno());
896 crmsg.timestamp = now.tv_sec;
898 olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)crmsg.timestamp);
902 memcpy(&crmsg.destination, to, olsr_cnf->ipsize);
903 crmsg.challenge = htonl(challenge);
905 /* Create digest of received challenge + IP */
908 uint8_t checksum_cache[512 + KEYLENGTH];
909 /* Create packet + key cache */
910 /* First the challenge received */
911 memcpy(checksum_cache, &chal_in, 4);
912 /* Then the local IP */
913 memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
915 /* Create the hash */
916 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, crmsg.res_sig);
919 /* Now create the digest of the message and the key */
922 uint8_t checksum_cache[512 + KEYLENGTH];
923 /* Create packet + key cache */
924 /* First the OLSR packet + signature message - digest */
925 memcpy(checksum_cache, &crmsg, sizeof(struct c_respmsg) - SIGNATURE_SIZE);
927 memcpy(&checksum_cache[sizeof(struct c_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
929 /* Create the hash */
930 CHECKSUM(checksum_cache, (sizeof(struct c_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, crmsg.signature);
933 olsr_printf(3, "[ENC]Sending challenge response to %s challenge 0x%x\n", olsr_ip_to_string(&buf, to), challenge);
936 net_outbuffer_push(olsr_if, &crmsg, sizeof(struct c_respmsg));
937 /* Send the request */
944 * Build and transmit a response response
949 send_rres(struct interface *olsr_if, union olsr_ip_addr *to, union olsr_ip_addr *from, uint32_t chal_in)
951 struct r_respmsg rrmsg;
952 struct ipaddr_str buf;
954 olsr_printf(1, "[ENC]Building RRESPONSE message\n");
956 /* Fill challengemessage */
957 rrmsg.olsr_msgtype = TYPE_RRESPONSE;
958 rrmsg.olsr_vtime = 0;
959 rrmsg.olsr_msgsize = htons(sizeof(struct r_respmsg));
960 memcpy(&rrmsg.originator, &olsr_cnf->main_addr, olsr_cnf->ipsize);
963 rrmsg.seqno = htons(get_msg_seqno());
966 rrmsg.timestamp = now.tv_sec;
969 olsr_printf(3, "[ENC]Timestamp %lld\n", (long long)rrmsg.timestamp);
972 memcpy(&rrmsg.destination, to, olsr_cnf->ipsize);
974 /* Create digest of received challenge + IP */
977 uint8_t checksum_cache[512 + KEYLENGTH];
978 /* Create packet + key cache */
979 /* First the challenge received */
980 memcpy(checksum_cache, &chal_in, 4);
981 /* Then the local IP */
982 memcpy(&checksum_cache[sizeof(uint32_t)], from, olsr_cnf->ipsize);
984 /* Create the hash */
985 CHECKSUM(checksum_cache, sizeof(uint32_t) + olsr_cnf->ipsize, rrmsg.res_sig);
988 /* Now create the digest of the message and the key */
991 uint8_t checksum_cache[512 + KEYLENGTH];
992 /* Create packet + key cache */
993 /* First the OLSR packet + signature message - digest */
994 memcpy(checksum_cache, &rrmsg, sizeof(struct r_respmsg) - SIGNATURE_SIZE);
996 memcpy(&checksum_cache[sizeof(struct r_respmsg) - SIGNATURE_SIZE], aes_key, KEYLENGTH);
998 /* Create the hash */
999 CHECKSUM(checksum_cache, (sizeof(struct r_respmsg) - SIGNATURE_SIZE) + KEYLENGTH, rrmsg.signature);
1002 olsr_printf(3, "[ENC]Sending response response to %s\n", olsr_ip_to_string(&buf, to));
1005 net_outbuffer_push(olsr_if, &rrmsg, sizeof(struct r_respmsg));
1007 /* Send the request */
1008 net_output(olsr_if);
1013 static struct stamp *
1014 lookup_timestamp_entry(const union olsr_ip_addr *adr)
1017 struct stamp *entry;
1018 struct ipaddr_str buf;
1020 hash = olsr_ip_hashing(adr);
1022 for (entry = timestamps[hash].next; entry != ×tamps[hash]; entry = entry->next) {
1023 if (memcmp(&entry->addr, adr, olsr_cnf->ipsize) == 0) {
1024 olsr_printf(3, "[ENC]Match for %s\n", olsr_ip_to_string(&buf, adr));
1029 olsr_printf(1, "[ENC]No match for %s\n", olsr_ip_to_string(&buf, adr));
1035 *Find timed out entries and delete them
1040 timeout_timestamps(void *foo __attribute__ ((unused)))
1042 struct stamp *tmp_list;
1043 struct stamp *entry_to_delete;
1046 /* Update our local timestamp */
1047 gettimeofday(&now, NULL);
1049 for (idx = 0; idx < HASHSIZE; idx++) {
1050 tmp_list = timestamps[idx].next;
1051 /*Traverse MID list */
1052 while (tmp_list != ×tamps[idx]) {
1053 /*Check if the entry is timed out */
1054 if ((TIMED_OUT(tmp_list->valtime)) && (TIMED_OUT(tmp_list->conftime))) {
1055 struct ipaddr_str buf;
1056 entry_to_delete = tmp_list;
1057 tmp_list = tmp_list->next;
1059 olsr_printf(1, "[ENC]timestamp info for %s timed out.. deleting it\n", olsr_ip_to_string(&buf, &entry_to_delete->addr));
1062 entry_to_delete->next->prev = entry_to_delete->prev;
1063 entry_to_delete->prev->next = entry_to_delete->next;
1065 free(entry_to_delete);
1067 tmp_list = tmp_list->next;
1075 read_key_from_file(const char *file)
1081 kf = fopen(file, "r");
1083 olsr_printf(1, "[ENC]Reading key from file \"%s\"\n", file);
1086 olsr_printf(1, "[ENC]Could not open keyfile %s!\nError: %s\n", file, strerror(errno));
1090 if (fread(aes_key, 1, keylen, kf) != keylen) {
1091 olsr_printf(1, "[ENC]Could not read key from keyfile %s!\nError: %s\n", file, strerror(errno));
1103 * indent-tabs-mode: nil