diff --git a/.travis.yml b/.travis.yml index 2ebcdf4b3..695a6fe54 100644 --- a/.travis.yml +++ b/.travis.yml @@ -106,3 +106,4 @@ env: - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' + - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' diff --git a/Makefile.include b/Makefile.include index 4b1443a13..09f69e43f 100644 --- a/Makefile.include +++ b/Makefile.include @@ -62,7 +62,7 @@ MODULES += core/sys core/dev core/lib CONTIKI_SOURCEFILES += $(CONTIKIFILES) -CONTIKIDIRS += ${addprefix $(CONTIKI)/core/,dev lib net net/mac net/rime \ +CONTIKIDIRS += ${addprefix $(CONTIKI)/core/,dev lib net net/llsec net/mac net/rime \ net/rpl sys cfs ctk lib/ctk loader . } oname = ${patsubst %.c,%.o,${patsubst %.S,%.o,$(1)}} diff --git a/core/contiki-default-conf.h b/core/contiki-default-conf.h index 4dfecd921..93fb2a839 100644 --- a/core/contiki-default-conf.h +++ b/core/contiki-default-conf.h @@ -73,6 +73,18 @@ /* #define NETSTACK_CONF_MAC csma_driver */ #endif /* NETSTACK_CONF_MAC */ +/* NETSTACK_CONF_LLSEC specifies the link layer security driver. */ +#ifndef NETSTACK_CONF_LLSEC +#define NETSTACK_CONF_LLSEC nullsec_driver +#endif /* NETSTACK_CONF_LLSEC */ + +/* To avoid unnecessary complexity, we assume the common case of + a constant LoWPAN-wide IEEE 802.15.4 security level, which + can be specified by defining LLSEC802154_CONF_SECURITY_LEVEL. */ +#ifndef LLSEC802154_CONF_SECURITY_LEVEL +#define LLSEC802154_CONF_SECURITY_LEVEL 0 +#endif /* LLSEC802154_CONF_SECURITY_LEVEL */ + /* NETSTACK_CONF_NETWORK specifies the network layer and can be either sicslowpan_driver, for IPv6 networking, or rime_driver, for the custom Rime network stack. */ @@ -208,13 +220,12 @@ #define SICSLOWPAN_CONF_FRAG 1 #endif /* SICSLOWPAN_CONF_FRAG */ -/* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD specifies the maximum size of - packets before they get fragmented. The default is 127 bytes (the - maximum size of a 802.15.4 frame) - 25 bytes (for the 802.15.4 MAC - layer header). This can be increased for systems with larger packet - sizes. */ +/* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD is the maximum available size for + frame headers, link layer security-related overhead, as well as + 6LoWPAN payload. By default, SICSLOWPAN_CONF_MAC_MAX_PAYLOAD is + 127 bytes (MTU of 802.15.4) - 2 bytes (Footer of 802.15.4). */ #ifndef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD -#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD (127 - 25) +#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD (127 - 2) #endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ /* SICSLOWPAN_CONF_COMPRESSION_THRESHOLD sets a lower threshold for diff --git a/core/lib/aes-128.c b/core/lib/aes-128.c new file mode 100644 index 000000000..473adf6fc --- /dev/null +++ b/core/lib/aes-128.c @@ -0,0 +1,198 @@ +/* --COPYRIGHT--,BSD + * Copyright (c) 2011, Texas Instruments Incorporated + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of Texas Instruments Incorporated nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * --/COPYRIGHT--*/ +/* + * TI_aes_128_encr_only.c + * + * Created on: Nov 3, 2011 + * Author: Eric Peeters + */ + +/** + * \file + * Wrapped AES-128 implementation from Texas Instruments. + * \author + * Konrad Krentz + */ + +#include "lib/aes-128.h" +#include + +static const uint8_t sbox[256] = { +0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, +0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, +0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, +0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, +0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, +0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, +0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, +0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, +0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, +0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, +0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, +0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, +0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, +0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, +0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, +0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 }; + +static uint8_t round_keys[11][AES_128_KEY_LENGTH]; + +/*---------------------------------------------------------------------------*/ +/* multiplies by 2 in GF(2) */ +static uint8_t +galois_mul2(uint8_t value) +{ + if(value >> 7) { + value = value << 1; + return value ^ 0x1b; + } else { + return value << 1; + } +} +/*---------------------------------------------------------------------------*/ +static void +set_key(uint8_t *key) +{ + uint8_t i; + uint8_t j; + uint8_t rcon; + + rcon = 0x01; + memcpy(round_keys[0], key, AES_128_KEY_LENGTH); + for(i = 1; i <= 10; i++) { + round_keys[i][0] = sbox[round_keys[i - 1][13]] ^ round_keys[i - 1][0] ^ rcon; + round_keys[i][1] = sbox[round_keys[i - 1][14]] ^ round_keys[i - 1][1]; + round_keys[i][2] = sbox[round_keys[i - 1][15]] ^ round_keys[i - 1][2]; + round_keys[i][3] = sbox[round_keys[i - 1][12]] ^ round_keys[i - 1][3]; + for(j = 4; j < AES_128_BLOCK_SIZE; j++) { + round_keys[i][j] = round_keys[i - 1][j] ^ round_keys[i][j - 4]; + } + rcon = galois_mul2(rcon); + } +} +/*---------------------------------------------------------------------------*/ +static void +encrypt(uint8_t *state) +{ + uint8_t buf1, buf2, buf3, buf4, round, i; + + /* round 0 */ + /* AddRoundKey */ + for(i = 0; i < AES_128_BLOCK_SIZE; i++) { + state[i] = state[i] ^ round_keys[0][i]; + } + + for(round = 1; round <= 10; round++) { + /* ByteSub */ + for(i = 0; i < AES_128_BLOCK_SIZE; i++) { + state[i] = sbox[state[i]]; + } + + /* ShiftRow */ + buf1 = state[1]; + state[1] = state[5]; + state[5] = state[9]; + state[9] = state[13]; + state[13] = buf1; + + buf1 = state[2]; + buf2 = state[6]; + state[2] = state[10]; + state[6] = state[14]; + state[10] = buf1; + state[14] = buf2; + + buf1 = state[15]; + state[15] = state[11]; + state[11] = state[7]; + state[7] = state[3]; + state[3] = buf1; + + /* last round skips MixColumn */ + if(round < 10) { + /* MixColumn */ + for(i = 0; i < 4; i++) { + buf4 = (i << 2); + buf1 = state[buf4] ^ state[buf4 + 1] ^ state[buf4 + 2] ^ state[buf4 + 3]; + buf2 = state[buf4]; + buf3 = state[buf4] ^ state[buf4 + 1]; + buf3 = galois_mul2(buf3); + + state[buf4] = state[buf4] ^ buf3 ^ buf1; + + buf3 = state[buf4 + 1] ^ state[buf4 + 2]; + buf3 = galois_mul2(buf3); + state[buf4 + 1] = state[buf4 + 1] ^ buf3 ^ buf1; + + buf3 = state[buf4 + 2] ^ state[buf4 + 3]; + buf3 = galois_mul2(buf3); + state[buf4 + 2] = state[buf4 + 2] ^ buf3 ^ buf1; + + buf3 = state[buf4 + 3] ^ buf2; + buf3 = galois_mul2(buf3); + state[buf4 + 3] = state[buf4 + 3] ^ buf3 ^ buf1; + } + } + + /* AddRoundKey */ + for(i = 0; i < AES_128_BLOCK_SIZE; i++) { + state[i] = state[i] ^ round_keys[round][i]; + } + } +} +/*---------------------------------------------------------------------------*/ +void +aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len) +{ + uint8_t block[AES_128_BLOCK_SIZE]; + + memset(block, 0, AES_128_BLOCK_SIZE); + memcpy(block, plaintext_and_result, plaintext_len); + AES_128.encrypt(block); + memcpy(plaintext_and_result, block, plaintext_len); +} +/*---------------------------------------------------------------------------*/ +void +aes_128_set_padded_key(uint8_t *key, uint8_t key_len) +{ + uint8_t block[AES_128_BLOCK_SIZE]; + + memset(block, 0, AES_128_BLOCK_SIZE); + memcpy(block, key, key_len); + AES_128.set_key(block); +} +/*---------------------------------------------------------------------------*/ +const struct aes_128_driver aes_128_driver = { + set_key, + encrypt +}; +/*---------------------------------------------------------------------------*/ diff --git a/dev/cc2420/cc2420-aes.h b/core/lib/aes-128.h similarity index 54% rename from dev/cc2420/cc2420-aes.h rename to core/lib/aes-128.h index df54f97d2..a16155b4f 100644 --- a/dev/cc2420/cc2420-aes.h +++ b/core/lib/aes-128.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, Swedish Institute of Computer Science. + * Copyright (c) 2013, Hasso-Plattner-Institut. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,44 +32,51 @@ /** * \file - * Interface to the CC2420 AES encryption/decryption functions + * AES-128. * \author - * Adam Dunkels + * Konrad Krentz */ -#ifndef CC2420_AES_H_ -#define CC2420_AES_H_ +#ifndef AES_H_ +#define AES_H_ + +#include "contiki.h" + +#define AES_128_BLOCK_SIZE 16 +#define AES_128_KEY_LENGTH 16 + +#ifdef AES_128_CONF +#define AES_128 AES_128_CONF +#else /* AES_128_CONF */ +#define AES_128 aes_128_driver +#endif /* AES_128_CONF */ /** - * \brief Setup an AES key - * \param key A pointer to a 16-byte AES key - * \param index The key index: either 0 or 1. - * - * This function sets up an AES key with the CC2420 - * chip. The AES key can later be used with the - * cc2420_aes_cipher() function to encrypt or decrypt - * data. - * - * The CC2420 can store two separate keys in its - * memory. The keys are indexed as 0 or 1 and the key - * index is given by the 'index' parameter. - * + * Structure of AES drivers. */ -void cc2420_aes_set_key(const uint8_t *key, int index); - +struct aes_128_driver { + + /** + * \brief Sets the current key. + */ + void (* set_key)(uint8_t *key); + + /** + * \brief Encrypts. + */ + void (* encrypt)(uint8_t *plaintext_and_result); +}; /** - * \brief Encrypt/decrypt data with AES - * \param data A pointer to the data to be encrypted/decrypted - * \param len The length of the data to be encrypted/decrypted - * \param key_index The key to use. The key must have previously been set up with cc2420_aes_set_key(). - * - * This function encrypts/decrypts data with AES. A - * pointer to the data is passed as a parameter, and the - * function overwrites the data with the encrypted data. - * + * \brief Pads the plaintext with zeroes before calling AES_128.encrypt */ -void cc2420_aes_cipher(uint8_t *data, int len, int key_index); +void aes_128_padded_encrypt(uint8_t *plaintext_and_result, uint8_t plaintext_len); +/** + * \brief Pads the key with zeroes before calling AES_128.set_key + */ +void aes_128_set_padded_key(uint8_t *key, uint8_t key_len); -#endif /* CC2420_AES_H_ */ +extern const struct aes_128_driver AES_128; + +#endif /* AES_H_ */ diff --git a/core/net/ipv6/sicslowpan.c b/core/net/ipv6/sicslowpan.c index e69bdd88b..133d66e4b 100644 --- a/core/net/ipv6/sicslowpan.c +++ b/core/net/ipv6/sicslowpan.c @@ -155,11 +155,13 @@ void uip_log(char *msg); /** @} */ -/** \brief Size of the 802.15.4 payload (127byte - 25 for MAC header) */ +/** \brief Maximum available size for frame headers, + link layer security-related overhead, as well as + 6LoWPAN payload. */ #ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD #define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD #else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ -#define MAC_MAX_PAYLOAD 102 +#define MAC_MAX_PAYLOAD (127 - 2) #endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */ @@ -1341,7 +1343,7 @@ send_packet(linkaddr_t *dest) /* Provide a callback function to receive the result of a packet transmission. */ - NETSTACK_MAC.send(&packet_sent, NULL); + NETSTACK_LLSEC.send(&packet_sent, NULL); /* If we are sending multiple packets in a row, we need to let the watchdog know that we are still alive. */ @@ -1361,6 +1363,7 @@ static uint8_t output(const uip_lladdr_t *localdest) { int framer_hdrlen; + int max_payload; /* The MAC address of the destination of the packet */ linkaddr_t dest; @@ -1443,8 +1446,9 @@ output(const uip_lladdr_t *localdest) #else /* USE_FRAMER_HDRLEN */ framer_hdrlen = 21; #endif /* USE_FRAMER_HDRLEN */ + max_payload = MAC_MAX_PAYLOAD - framer_hdrlen - NETSTACK_LLSEC.get_overhead(); - if((int)uip_len - (int)uncomp_hdr_len > (int)MAC_MAX_PAYLOAD - framer_hdrlen - (int)packetbuf_hdr_len) { + if((int)uip_len - (int)uncomp_hdr_len > max_payload - (int)packetbuf_hdr_len) { #if SICSLOWPAN_CONF_FRAG struct queuebuf *q; /* @@ -1477,7 +1481,7 @@ output(const uip_lladdr_t *localdest) /* Copy payload and send */ packetbuf_hdr_len += SICSLOWPAN_FRAG1_HDR_LEN; - packetbuf_payload_len = (MAC_MAX_PAYLOAD - framer_hdrlen - packetbuf_hdr_len) & 0xfffffff8; + packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8; PRINTFO("(len %d, tag %d)\n", packetbuf_payload_len, my_tag); memcpy(packetbuf_ptr + packetbuf_hdr_len, (uint8_t *)UIP_IP_BUF + uncomp_hdr_len, packetbuf_payload_len); @@ -1513,7 +1517,7 @@ output(const uip_lladdr_t *localdest) /* uip_htons((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len); */ SET16(PACKETBUF_FRAG_PTR, PACKETBUF_FRAG_DISPATCH_SIZE, ((SICSLOWPAN_DISPATCH_FRAGN << 8) | uip_len)); - packetbuf_payload_len = (MAC_MAX_PAYLOAD - framer_hdrlen - packetbuf_hdr_len) & 0xfffffff8; + packetbuf_payload_len = (max_payload - packetbuf_hdr_len) & 0xfffffff8; while(processed_ip_out_len < uip_len) { PRINTFO("sicslowpan output: fragment "); PACKETBUF_FRAG_PTR[PACKETBUF_FRAG_OFFSET] = processed_ip_out_len >> 3; diff --git a/core/net/linkaddr.h b/core/net/linkaddr.h index cbfc43a95..06f4c34cb 100644 --- a/core/net/linkaddr.h +++ b/core/net/linkaddr.h @@ -64,8 +64,15 @@ typedef union { unsigned char u8[LINKADDR_SIZE]; +#if LINKADDR_SIZE == 2 + uint16_t u16; +#endif /* LINKADDR_SIZE == 2 */ } linkaddr_t; +typedef union { + uint8_t u8[8]; + uint16_t u16[4]; +} linkaddr_extended_t; /** * \brief Copy a Rime address diff --git a/core/net/llsec/anti-replay.c b/core/net/llsec/anti-replay.c new file mode 100644 index 000000000..0500f7a87 --- /dev/null +++ b/core/net/llsec/anti-replay.c @@ -0,0 +1,110 @@ +/** + * \addtogroup llsec802154 + * @{ + */ + +/* + * Copyright (c) 2014, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Protects against replay attacks by comparing with the last + * unicast or broadcast frame counter of the sender. + * \author + * Konrad Krentz + */ + +#include "net/llsec/anti-replay.h" +#include "net/packetbuf.h" + +/* This node's current frame counter value */ +static uint32_t counter; + +/*---------------------------------------------------------------------------*/ +void +anti_replay_set_counter(void) +{ + frame802154_frame_counter_t reordered_counter; + + reordered_counter.u32 = LLSEC802154_HTONL(++counter); + + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, reordered_counter.u16[0]); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, reordered_counter.u16[1]); +} +/*---------------------------------------------------------------------------*/ +uint32_t +anti_replay_get_counter(void) +{ + frame802154_frame_counter_t disordered_counter; + + disordered_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); + disordered_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); + + return LLSEC802154_HTONL(disordered_counter.u32); +} +/*---------------------------------------------------------------------------*/ +void +anti_replay_init_info(struct anti_replay_info *info) +{ + info->last_broadcast_counter + = info->last_unicast_counter + = anti_replay_get_counter(); +} +/*---------------------------------------------------------------------------*/ +int +anti_replay_was_replayed(struct anti_replay_info *info) +{ + uint32_t received_counter; + + received_counter = anti_replay_get_counter(); + + if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { + /* broadcast */ + if(received_counter <= info->last_broadcast_counter) { + return 1; + } else { + info->last_broadcast_counter = received_counter; + return 0; + } + } else { + /* unicast */ + if(received_counter <= info->last_unicast_counter) { + return 1; + } else { + info->last_unicast_counter = received_counter; + return 0; + } + } +} +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/core/net/llsec/anti-replay.h b/core/net/llsec/anti-replay.h new file mode 100644 index 000000000..637243660 --- /dev/null +++ b/core/net/llsec/anti-replay.h @@ -0,0 +1,79 @@ +/** + * \addtogroup llsec802154 + * @{ + */ + +/* + * Copyright (c) 2014, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Interface to anti-replay mechanisms. + * \author + * Konrad Krentz + */ + +#ifndef ANTI_REPLAY_H +#define ANTI_REPLAY_H + +#include "contiki.h" + +struct anti_replay_info { + uint32_t last_broadcast_counter; + uint32_t last_unicast_counter; +}; + +/** + * \brief Sets the frame counter packetbuf attributes. + */ +void anti_replay_set_counter(void); + +/** + * \brief Gets the frame counter from packetbuf. + */ +uint32_t anti_replay_get_counter(void); + +/** + * \brief Initializes the anti-replay information about the sender + */ +void anti_replay_init_info(struct anti_replay_info *info); + +/** + * \brief Checks if received frame was replayed + * \param last_counters Anti-replay information about the sender + * \retval 0 <-> received frame was not replayed + */ +int anti_replay_was_replayed(struct anti_replay_info *info); + +#endif /* ANTI_REPLAY_H */ + +/** @} */ diff --git a/core/net/llsec/ccm.c b/core/net/llsec/ccm.c new file mode 100644 index 000000000..afae5ed25 --- /dev/null +++ b/core/net/llsec/ccm.c @@ -0,0 +1,190 @@ +/** + * \addtogroup llsec802154 + * @{ + */ + +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * AES_128-based CCM* implementation. + * \author + * Konrad Krentz + */ + +#include "net/llsec/ccm.h" +#include "net/llsec/llsec802154.h" +#include "net/packetbuf.h" +#include "lib/aes-128.h" +#include + +/*---------------------------------------------------------------------------*/ +static void +set_nonce(uint8_t *nonce, + uint8_t flags, + const uint8_t *extended_source_address, + uint8_t counter) +{ + /* 1 byte|| 8 bytes || 4 bytes || 1 byte || 2 bytes */ + /* flags || extended_source_address || frame_counter || sec_lvl || counter */ + + nonce[0] = flags; + memcpy(nonce + 1, extended_source_address, 8); + nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8; + nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff; + nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8; + nonce[12] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff; + nonce[13] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); + nonce[14] = 0; + nonce[15] = counter; +} +/*---------------------------------------------------------------------------*/ +/* XORs the block m[pos] ... m[pos + 15] with K_{counter} */ +static void +ctr_step(const uint8_t *extended_source_address, + uint8_t pos, + uint8_t *m_and_result, + uint8_t m_len, + uint8_t counter) +{ + uint8_t a[AES_128_BLOCK_SIZE]; + uint8_t i; + + set_nonce(a, CCM_ENCRYPTION_FLAGS, extended_source_address, counter); + AES_128.encrypt(a); + + for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) { + m_and_result[pos + i] ^= a[i]; + } +} +/*---------------------------------------------------------------------------*/ +static void +mic(const uint8_t *extended_source_address, + uint8_t *result, + uint8_t mic_len) +{ + uint8_t x[AES_128_BLOCK_SIZE]; + uint8_t pos; + uint8_t i; + uint8_t a_len; + uint8_t *a; +#if LLSEC802154_USES_ENCRYPTION + uint8_t shall_encrypt; + uint8_t m_len; + uint8_t *m; + + shall_encrypt = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2); + if(shall_encrypt) { + a_len = packetbuf_hdrlen(); + m_len = packetbuf_datalen(); + } else { + a_len = packetbuf_totlen(); + m_len = 0; + } + set_nonce(x, + CCM_AUTH_FLAGS(a_len, mic_len), + extended_source_address, + m_len); +#else /* LLSEC802154_USES_ENCRYPTION */ + a_len = packetbuf_totlen(); + set_nonce(x, + CCM_AUTH_FLAGS(a_len, mic_len), + extended_source_address, + 0); +#endif /* LLSEC802154_USES_ENCRYPTION */ + AES_128.encrypt(x); + + a = packetbuf_hdrptr(); + if(a_len) { + x[1] = x[1] ^ a_len; + for(i = 2; (i - 2 < a_len) && (i < AES_128_BLOCK_SIZE); i++) { + x[i] ^= a[i - 2]; + } + + AES_128.encrypt(x); + + pos = 14; + while(pos < a_len) { + for(i = 0; (pos + i < a_len) && (i < AES_128_BLOCK_SIZE); i++) { + x[i] ^= a[pos + i]; + } + pos += AES_128_BLOCK_SIZE; + AES_128.encrypt(x); + } + } + +#if LLSEC802154_USES_ENCRYPTION + if(shall_encrypt) { + m = a + a_len; + pos = 0; + while(pos < m_len) { + for(i = 0; (pos + i < m_len) && (i < AES_128_BLOCK_SIZE); i++) { + x[i] ^= m[pos + i]; + } + pos += AES_128_BLOCK_SIZE; + AES_128.encrypt(x); + } + } +#endif /* LLSEC802154_USES_ENCRYPTION */ + + ctr_step(extended_source_address, 0, x, AES_128_BLOCK_SIZE, 0); + + memcpy(result, x, mic_len); +} +/*---------------------------------------------------------------------------*/ +static void +ctr(const uint8_t *extended_source_address) +{ + uint8_t m_len; + uint8_t *m; + uint8_t pos; + uint8_t counter; + + m_len = packetbuf_datalen(); + m = (uint8_t *) packetbuf_dataptr(); + + pos = 0; + counter = 1; + while(pos < m_len) { + ctr_step(extended_source_address, pos, m, m_len, counter++); + pos += AES_128_BLOCK_SIZE; + } +} +/*---------------------------------------------------------------------------*/ +const struct ccm_driver ccm_driver = { + mic, + ctr +}; +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/core/net/llsec/ccm.h b/core/net/llsec/ccm.h new file mode 100644 index 000000000..cd4eca8f1 --- /dev/null +++ b/core/net/llsec/ccm.h @@ -0,0 +1,85 @@ +/** + * \addtogroup llsec802154 + * @{ + */ + +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * CCM* header file. + * \author + * Konrad Krentz + */ + +#ifndef CCM_H_ +#define CCM_H_ + +#include "contiki.h" +#include "net/mac/frame802154.h" + +/* see RFC 3610 */ +#define CCM_AUTH_FLAGS(Adata, M) ((Adata ? (1 << 6) : 0) | (((M - 2) >> 1) << 3) | 1) +#define CCM_ENCRYPTION_FLAGS 1 + +#ifdef CCM_CONF +#define CCM CCM_CONF +#else /* CCM_CONF */ +#define CCM ccm_driver +#endif /* CCM_CONF */ + +/** + * Structure of CCM drivers. + */ +struct ccm_driver { + + /** + * \brief Generates a MIC over the frame in the packetbuf. + * \param result The generated MIC will be put here + * \param mic_len <= 16; set to LLSEC802154_MIC_LENGTH to be compliant + */ + void (* mic)(const uint8_t *extended_source_address, + uint8_t *result, + uint8_t mic_len); + + /** + * \brief XORs the frame in the packetbuf with the key stream. + */ + void (* ctr)(const uint8_t *extended_source_address); +}; + +extern const struct ccm_driver CCM; + +#endif /* CCM_H_ */ + +/** @} */ diff --git a/core/net/llsec/llsec.h b/core/net/llsec/llsec.h new file mode 100644 index 000000000..965a1b06d --- /dev/null +++ b/core/net/llsec/llsec.h @@ -0,0 +1,95 @@ +/** + * \defgroup llsec Link Layer Security + * + * Layer for implementing link layer security. + * + * NETSTACK_LLSEC sits in between NETSTACK_MAC and NETSTACK_NETWORK + * protocols. All NETSTACK_MAC protocols invoke NETSTACK_LLSEC.input() + * for incoming packets. Likewise, all NETSTACK_NETWORK protocols + * invoke NETSTACK_LLSEC.send(...) for outgoing packets. + * + * The bootstrap function of llsec_drivers can be used to defer the start + * of upper layers so as to bootstrap pairwise keys. Only contiki-sky-main.c + * supports this at the moment. + * + * @{ + */ + +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Link layer security header file. + * \author + * Konrad Krentz + */ + +#ifndef LLSEC_H_ +#define LLSEC_H_ + +#include "net/mac/mac.h" + +typedef void (* llsec_on_bootstrapped_t)(void); + +/** + * The structure of a link layer security driver. + */ +struct llsec_driver { + char *name; + + /** Bootstraps link layer security and thereafter starts upper layers. */ + void (* bootstrap)(llsec_on_bootstrapped_t on_bootstrapped); + + /** Secures outgoing frames before passing them to NETSTACK_MAC. */ + void (* send)(mac_callback_t sent_callback, void *ptr); + + /** + * Once the NETSTACK_FRAMER wrote the headers, the LLSEC driver + * can generate a MIC over the entire frame. + * \return Returns != 0 <-> success + */ + int (* on_frame_created)(void); + + /** + * Decrypts incoming frames; + * filters out injected or replayed frames. + */ + void (* input)(void); + + /** Returns the security-related overhead per frame in bytes */ + uint8_t (* get_overhead)(void); +}; + +#endif /* LLSEC_H_ */ + +/** @} */ diff --git a/core/net/llsec/llsec802154.h b/core/net/llsec/llsec802154.h new file mode 100644 index 000000000..4a9b8eee8 --- /dev/null +++ b/core/net/llsec/llsec802154.h @@ -0,0 +1,90 @@ +/** + * \addtogroup llsec + * @{ + */ + +/** + * \defgroup llsec802154 + * + * Common functionality of 802.15.4-compliant llsec_drivers. + * + * @{ + */ + +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Common functionality of 802.15.4-compliant llsec_drivers. + * \author + * Konrad Krentz + */ + +#ifndef LLSEC802154_H_ +#define LLSEC802154_H_ + +#include "net/mac/frame802154.h" +#include "net/ip/uip.h" + +#ifdef LLSEC802154_CONF_SECURITY_LEVEL +#define LLSEC802154_SECURITY_LEVEL LLSEC802154_CONF_SECURITY_LEVEL +#else /* LLSEC802154_CONF_SECURITY_LEVEL */ +#define LLSEC802154_SECURITY_LEVEL FRAME802154_SECURITY_LEVEL_NONE +#endif /* LLSEC802154_CONF_SECURITY_LEVEL */ + +#define LLSEC802154_MIC_LENGTH ((LLSEC802154_SECURITY_LEVEL & 3) * 4) + +#ifdef LLSEC802154_CONF_USES_ENCRYPTION +#define LLSEC802154_USES_ENCRYPTION LLSEC802154_CONF_USES_ENCRYPTION +#else /* LLSEC802154_CONF_USES_ENCRYPTION */ +#define LLSEC802154_USES_ENCRYPTION (LLSEC802154_SECURITY_LEVEL & (1 << 2)) +#endif /* LLSEC802154_CONF_USES_ENCRYPTION */ + +#ifdef LLSEC802154_CONF_USES_EXPLICIT_KEYS +#define LLSEC802154_USES_EXPLICIT_KEYS LLSEC802154_CONF_USES_EXPLICIT_KEYS +#else /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */ +#define LLSEC802154_USES_EXPLICIT_KEYS 0 +#endif /* LLSEC802154_CONF_USES_EXPLICIT_KEYS */ + +#if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN +#define LLSEC802154_HTONS(n) (n) +#define LLSEC802154_HTONL(n) (n) +#else /* UIP_CONF_BYTE_ORDER == UIP_LITTLE_ENDIAN */ +#define LLSEC802154_HTONS(n) (uint16_t)((((uint16_t) (n)) << 8) | (((uint16_t) (n)) >> 8)) +#define LLSEC802154_HTONL(n) (((uint32_t)UIP_HTONS(n) << 16) | UIP_HTONS((uint32_t)(n) >> 16)) +#endif /* UIP_CONF_BYTE_ORDER == UIP_LITTLE_ENDIAN */ + +#endif /* LLSEC802154_H_ */ + +/** @} */ +/** @} */ diff --git a/core/net/llsec/noncoresec/noncoresec.c b/core/net/llsec/noncoresec/noncoresec.c new file mode 100644 index 000000000..1d0015645 --- /dev/null +++ b/core/net/llsec/noncoresec/noncoresec.c @@ -0,0 +1,221 @@ +/** + * \addtogroup noncoresec + * @{ + */ + +/* + * Copyright (c) 2014, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * 802.15.4 security implementation, which uses a network-wide key + * \author + * Konrad Krentz + */ + +#include "net/llsec/noncoresec/noncoresec.h" +#include "net/llsec/anti-replay.h" +#include "net/llsec/llsec802154.h" +#include "net/llsec/ccm.h" +#include "net/mac/frame802154.h" +#include "net/netstack.h" +#include "net/packetbuf.h" +#include "net/nbr-table.h" +#include "net/linkaddr.h" +#include "lib/aes-128.h" +#include + +#define WITH_ENCRYPTION (LLSEC802154_SECURITY_LEVEL & (1 << 2)) + +#ifdef NONCORESEC_CONF_KEY +#define NONCORESEC_KEY NONCORESEC_CONF_KEY +#else /* NONCORESEC_CONF_KEY */ +#define NONCORESEC_KEY { 0x00 , 0x01 , 0x02 , 0x03 , \ + 0x04 , 0x05 , 0x06 , 0x07 , \ + 0x08 , 0x09 , 0x0A , 0x0B , \ + 0x0C , 0x0D , 0x0E , 0x0F } +#endif /* NONCORESEC_CONF_KEY */ + +#define SECURITY_HEADER_LENGTH 5 + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +#define PRINTF(...) +#endif /* DEBUG */ + +/* network-wide CCM* key */ +static uint8_t key[16] = NONCORESEC_KEY; +NBR_TABLE(struct anti_replay_info, anti_replay_table); + +/*---------------------------------------------------------------------------*/ +static const uint8_t * +get_extended_address(const linkaddr_t *addr) +#if LINKADDR_SIZE == 2 +{ + /* workaround for short addresses: derive EUI64 as in RFC 6282 */ + static linkaddr_extended_t template = { { 0x00 , 0x00 , 0x00 , + 0xFF , 0xFE , 0x00 , 0x00 , 0x00 } }; + + template.u16[3] = LLSEC802154_HTONS(addr->u16); + + return template.u8; +} +#else /* LINKADDR_SIZE == 2 */ +{ + return addr->u8; +} +#endif /* LINKADDR_SIZE == 2 */ +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); + anti_replay_set_counter(); + NETSTACK_MAC.send(sent, ptr); +} +/*---------------------------------------------------------------------------*/ +static int +on_frame_created(void) +{ + uint8_t *dataptr; + uint8_t data_len; + + dataptr = packetbuf_dataptr(); + data_len = packetbuf_datalen(); + + CCM.mic(get_extended_address(&linkaddr_node_addr), dataptr + data_len, LLSEC802154_MIC_LENGTH); +#if WITH_ENCRYPTION + CCM.ctr(get_extended_address(&linkaddr_node_addr)); +#endif /* WITH_ENCRYPTION */ + packetbuf_set_datalen(data_len + LLSEC802154_MIC_LENGTH); + + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ + uint8_t generated_mic[LLSEC802154_MIC_LENGTH]; + uint8_t *received_mic; + const linkaddr_t *sender; + struct anti_replay_info* info; + + if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != LLSEC802154_SECURITY_LEVEL) { + PRINTF("noncoresec: received frame with wrong security level\n"); + return; + } + sender = packetbuf_addr(PACKETBUF_ADDR_SENDER); + if(linkaddr_cmp(sender, &linkaddr_node_addr)) { + PRINTF("noncoresec: frame from ourselves\n"); + return; + } + + packetbuf_set_datalen(packetbuf_datalen() - LLSEC802154_MIC_LENGTH); + +#if WITH_ENCRYPTION + CCM.ctr(get_extended_address(sender)); +#endif /* WITH_ENCRYPTION */ + CCM.mic(get_extended_address(sender), generated_mic, LLSEC802154_MIC_LENGTH); + + received_mic = ((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(); + if(memcmp(generated_mic, received_mic, LLSEC802154_MIC_LENGTH) != 0) { + PRINTF("noncoresec: received nonauthentic frame %"PRIu32"\n", + anti_replay_get_counter()); + return; + } + + info = nbr_table_get_from_lladdr(anti_replay_table, sender); + if(!info) { + info = nbr_table_add_lladdr(anti_replay_table, sender); + if(!info) { + PRINTF("noncoresec: could not get nbr_table_item\n"); + return; + } + + /* + * Locking avoids replay attacks due to removed neighbor table items. + * Unfortunately, an attacker can mount a memory-based DoS attack + * on this by replaying broadcast frames from other network parts. + * However, this is not an issue as long as the network size does not + * exceed NBR_TABLE_MAX_NEIGHBORS. + * + * To avoid locking, we could swap anti-replay information + * to external flash. Locking is also unnecessary when using + * pairwise session keys, as done in coresec. + */ + if(!nbr_table_lock(anti_replay_table, info)) { + nbr_table_remove(anti_replay_table, info); + PRINTF("noncoresec: could not lock\n"); + return; + } + + anti_replay_init_info(info); + } else { + if(anti_replay_was_replayed(info)) { + PRINTF("noncoresec: received replayed frame %"PRIu32"\n", + anti_replay_get_counter()); + return; + } + } + + NETSTACK_NETWORK.input(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +get_overhead(void) +{ + return SECURITY_HEADER_LENGTH + LLSEC802154_MIC_LENGTH; +} +/*---------------------------------------------------------------------------*/ +static void +bootstrap(llsec_on_bootstrapped_t on_bootstrapped) +{ + AES_128.set_key(key); + nbr_table_register(anti_replay_table, NULL); + on_bootstrapped(); +} +/*---------------------------------------------------------------------------*/ +const struct llsec_driver noncoresec_driver = { + "noncoresec", + bootstrap, + send, + on_frame_created, + input, + get_overhead +}; +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/core/net/llsec/noncoresec/noncoresec.h b/core/net/llsec/noncoresec/noncoresec.h new file mode 100644 index 000000000..9f7f6383e --- /dev/null +++ b/core/net/llsec/noncoresec/noncoresec.h @@ -0,0 +1,63 @@ +/** + * \addtogroup llsec + * @{ + */ + +/** + * \defgroup noncoresec + * + * Noncompromise-resilient 802.15.4 security + * + * @{ + */ + +/* + * Copyright (c) 2014, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * 802.15.4 security implementation, which uses a network-wide key + * \author + * Konrad Krentz + */ + +#ifndef NONCORESEC_H_ +#define NONCORESEC_H_ + +#include "net/llsec/llsec.h" + +extern const struct llsec_driver noncoresec_driver; + +#endif /* NONCORESEC_H_ */ + +/** @} */ +/** @} */ diff --git a/core/net/llsec/nullsec.c b/core/net/llsec/nullsec.c new file mode 100644 index 000000000..040e9ed76 --- /dev/null +++ b/core/net/llsec/nullsec.c @@ -0,0 +1,92 @@ +/** + * \addtogroup nullsec + * @{ + */ + +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Insecure link layer security driver. + * \author + * Konrad Krentz + */ + +#include "net/llsec/nullsec.h" +#include "net/mac/frame802154.h" +#include "net/netstack.h" +#include "net/packetbuf.h" + +/*---------------------------------------------------------------------------*/ +static void +bootstrap(llsec_on_bootstrapped_t on_bootstrapped) +{ + on_bootstrapped(); +} +/*---------------------------------------------------------------------------*/ +static void +send(mac_callback_t sent, void *ptr) +{ + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME); + NETSTACK_MAC.send(sent, ptr); +} +/*---------------------------------------------------------------------------*/ +static int +on_frame_created(void) +{ + return 1; +} +/*---------------------------------------------------------------------------*/ +static void +input(void) +{ + NETSTACK_NETWORK.input(); +} +/*---------------------------------------------------------------------------*/ +static uint8_t +get_overhead(void) +{ + return 0; +} +/*---------------------------------------------------------------------------*/ +const struct llsec_driver nullsec_driver = { + "nullsec", + bootstrap, + send, + on_frame_created, + input, + get_overhead +}; +/*---------------------------------------------------------------------------*/ + +/** @} */ diff --git a/core/net/llsec/nullsec.h b/core/net/llsec/nullsec.h new file mode 100644 index 000000000..df592e985 --- /dev/null +++ b/core/net/llsec/nullsec.h @@ -0,0 +1,63 @@ +/** + * \addtogroup llsec + * @{ + */ + +/** + * \defgroup nullsec + * + * Insecure link layer security driver. + * + * @{ + */ + +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Insecure link layer security driver. + * \author + * Konrad Krentz + */ + +#ifndef NULLSEC_H_ +#define NULLSEC_H_ + +#include "net/llsec/llsec.h" + +extern const struct llsec_driver nullsec_driver; + +#endif /* NULLSEC_H_ */ + +/** @} */ +/** @} */ diff --git a/core/net/mac/contikimac/contikimac-framer.c b/core/net/mac/contikimac/contikimac-framer.c new file mode 100644 index 000000000..86121df5e --- /dev/null +++ b/core/net/mac/contikimac/contikimac-framer.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2014, Fraunhofer Heinrich-Hertz-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * Creates and parses the ContikiMAC header. + * \author + * Konrad Krentz + */ + +#include "net/mac/contikimac/contikimac-framer.h" +#include "net/packetbuf.h" +#include "net/netstack.h" +#include + +#define CONTIKIMAC_ID 0x00 + +/* SHORTEST_PACKET_SIZE is the shortest packet that ContikiMAC + allows. Packets have to be a certain size to be able to be detected + by two consecutive CCA checks, and here is where we define this + shortest size. + Padded packets will have the wrong ipv6 checksum unless CONTIKIMAC_HEADER + is used (on both sides) and the receiver will ignore them. + With no header, reduce to transmit a proper multicast RPL DIS. */ +#ifdef CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE +#define SHORTEST_PACKET_SIZE CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE +#else /* CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE */ +#define SHORTEST_PACKET_SIZE 43 +#endif /* CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE */ + +#ifdef CONTIKIMAC_FRAMER_CONF_DECORATED_FRAMER +#define DECORATED_FRAMER CONTIKIMAC_FRAMER_CONF_DECORATED_FRAMER +#else /* CONTIKIMAC_FRAMER_CONF_DECORATED_FRAMER */ +#define DECORATED_FRAMER framer_802154 +#endif /* CONTIKIMAC_FRAMER_CONF_DECORATED_FRAMER */ + +extern const struct framer DECORATED_FRAMER; + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#else +#define PRINTF(...) +#endif + +/* 2-byte header for recovering padded packets. + Wireshark will not understand such packets at present. */ +struct hdr { + uint8_t id; + uint8_t len; +}; + +/*---------------------------------------------------------------------------*/ +static int +create(void) +{ + struct hdr *chdr; + int hdr_len; + + if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) { + PRINTF("contikimac-framer: too large header\n"); + return FRAMER_FAILED; + } + chdr = packetbuf_hdrptr(); + chdr->id = CONTIKIMAC_ID; + chdr->len = 0; + + hdr_len = DECORATED_FRAMER.create(); + if(hdr_len < 0) { + PRINTF("contikimac-framer: decorated framer failed\n"); + return FRAMER_FAILED; + } + + return hdr_len + sizeof(struct hdr); +} +/*---------------------------------------------------------------------------*/ +static void +pad(void) +{ + int transmit_len; + uint8_t *ptr; + uint8_t zeroes_count; + + transmit_len = packetbuf_totlen(); + if(transmit_len < SHORTEST_PACKET_SIZE) { + /* Padding required */ + zeroes_count = SHORTEST_PACKET_SIZE - transmit_len; + ptr = packetbuf_dataptr(); + memset(ptr + packetbuf_datalen(), 0, zeroes_count); + packetbuf_set_datalen(packetbuf_datalen() + zeroes_count); + } +} +/*---------------------------------------------------------------------------*/ +static int +create_and_secure(void) +{ + struct hdr *chdr; + int hdr_len; + + hdr_len = create(); + if(hdr_len < 0) { + return FRAMER_FAILED; + } + + packetbuf_compact(); + if(!NETSTACK_LLSEC.on_frame_created()) { + PRINTF("contikimac-framer: securing failed\n"); + return FRAMER_FAILED; + } + + chdr = (struct hdr *)(((uint8_t *) packetbuf_dataptr()) - sizeof(struct hdr)); + chdr->len = packetbuf_datalen(); + pad(); + + return hdr_len; +} +/*---------------------------------------------------------------------------*/ +static int +parse(void) +{ + int hdr_len; + struct hdr *chdr; + + hdr_len = DECORATED_FRAMER.parse(); + if(hdr_len < 0) { + return FRAMER_FAILED; + } + + chdr = packetbuf_dataptr(); + if(chdr->id != CONTIKIMAC_ID) { + PRINTF("contikimac-framer: CONTIKIMAC_ID is missing\n"); + return FRAMER_FAILED; + } + + if(!packetbuf_hdrreduce(sizeof(struct hdr))) { + PRINTF("contikimac-framer: packetbuf_hdrreduce failed\n"); + return FRAMER_FAILED; + } + + packetbuf_set_datalen(chdr->len); + chdr->len = 0; + + return hdr_len + sizeof(struct hdr); +} +/*---------------------------------------------------------------------------*/ +const struct framer contikimac_framer = { + create, + create_and_secure, + parse +}; +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/contikimac/contikimac-framer.h b/core/net/mac/contikimac/contikimac-framer.h new file mode 100644 index 000000000..5bc84f67f --- /dev/null +++ b/core/net/mac/contikimac/contikimac-framer.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014, Fraunhofer Heinrich-Hertz-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/** + * \file + * Creates and parses the ContikiMAC header. + * \author + * Konrad Krentz + */ + +#ifndef CONTIKIMAC_FRAMER_H_ +#define CONTIKIMAC_FRAMER_H_ + +#include "net/mac/framer.h" + +extern const struct framer contikimac_framer; + +#endif /* CONTIKIMAC_FRAMER_H_ */ diff --git a/core/net/mac/contikimac/contikimac.c b/core/net/mac/contikimac/contikimac.c index 3c655314a..e46f51bff 100644 --- a/core/net/mac/contikimac/contikimac.c +++ b/core/net/mac/contikimac/contikimac.c @@ -61,13 +61,6 @@ #else /* CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION */ #define WITH_PHASE_OPTIMIZATION 1 #endif /* CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION */ -/* Two byte header added to allow recovery of padded short packets */ -/* Wireshark will not understand such packets at present */ -#ifdef CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER -#define WITH_CONTIKIMAC_HEADER CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER -#else -#define WITH_CONTIKIMAC_HEADER 1 -#endif /* More aggressive radio sleeping when channel is busy with other traffic */ #ifndef WITH_FAST_SLEEP #define WITH_FAST_SLEEP 1 @@ -90,15 +83,6 @@ #define WITH_PHASE_OPTIMIZATION 0 #endif -#if WITH_CONTIKIMAC_HEADER -#define CONTIKIMAC_ID 0x00 - -struct hdr { - uint8_t id; - uint8_t len; -}; -#endif /* WITH_CONTIKIMAC_HEADER */ - /* CYCLE_TIME for channel cca checks, in rtimer ticks. */ #ifdef CONTIKIMAC_CONF_CYCLE_TIME #define CYCLE_TIME (CONTIKIMAC_CONF_CYCLE_TIME) @@ -211,21 +195,6 @@ static int we_are_receiving_burst = 0; to a neighbor for which we have a phase lock. */ #define MAX_PHASE_STROBE_TIME RTIMER_ARCH_SECOND / 60 - -/* SHORTEST_PACKET_SIZE is the shortest packet that ContikiMAC - allows. Packets have to be a certain size to be able to be detected - by two consecutive CCA checks, and here is where we define this - shortest size. - Padded packets will have the wrong ipv6 checksum unless CONTIKIMAC_HEADER - is used (on both sides) and the receiver will ignore them. - With no header, reduce to transmit a proper multicast RPL DIS. */ -#ifdef CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE -#define SHORTEST_PACKET_SIZE CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE -#else -#define SHORTEST_PACKET_SIZE 43 -#endif - - #define ACK_LEN 3 #include @@ -528,7 +497,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, rtimer_clock_t encounter_time = 0; int strobes; uint8_t got_strobe_ack = 0; - int hdrlen, len; + int len; uint8_t is_broadcast = 0; uint8_t is_reliable = 0; uint8_t is_known_receiver = 0; @@ -537,10 +506,7 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, int ret; uint8_t contikimac_was_on; uint8_t seqno; -#if WITH_CONTIKIMAC_HEADER - struct hdr *chdr; -#endif /* WITH_CONTIKIMAC_HEADER */ - + /* Exit if RDC and radio were explicitly turned off */ if(!contikimac_is_on && !contikimac_keep_radio_on) { PRINTF("contikimac: radio is turned off\n"); @@ -583,65 +549,17 @@ send_packet(mac_callback_t mac_callback, void *mac_callback_ptr, is_reliable = packetbuf_attr(PACKETBUF_ATTR_RELIABLE) || packetbuf_attr(PACKETBUF_ATTR_ERELIABLE); - packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); - -#if WITH_CONTIKIMAC_HEADER - hdrlen = packetbuf_totlen(); - if(packetbuf_hdralloc(sizeof(struct hdr)) == 0) { - /* Failed to allocate space for contikimac header */ - PRINTF("contikimac: send failed, too large header\n"); - return MAC_TX_ERR_FATAL; + if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) { + packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); + if(NETSTACK_FRAMER.create_and_secure() < 0) { + PRINTF("contikimac: framer failed\n"); + return MAC_TX_ERR_FATAL; + } } - chdr = packetbuf_hdrptr(); - chdr->id = CONTIKIMAC_ID; - chdr->len = hdrlen; - /* Create the MAC header for the data packet. */ - hdrlen = NETSTACK_FRAMER.create(); - if(hdrlen < 0) { - /* Failed to send */ - PRINTF("contikimac: send failed, too large header\n"); - packetbuf_hdr_remove(sizeof(struct hdr)); - return MAC_TX_ERR_FATAL; - } - hdrlen += sizeof(struct hdr); -#else - /* Create the MAC header for the data packet. */ - hdrlen = NETSTACK_FRAMER.create(); - if(hdrlen < 0) { - /* Failed to send */ - PRINTF("contikimac: send failed, too large header\n"); - return MAC_TX_ERR_FATAL; - } -#endif - - /* Make sure that the packet is longer or equal to the shortest - packet length. */ transmit_len = packetbuf_totlen(); - if(transmit_len < SHORTEST_PACKET_SIZE) { - /* Pad with zeroes */ - uint8_t *ptr; - ptr = packetbuf_dataptr(); - memset(ptr + packetbuf_datalen(), 0, SHORTEST_PACKET_SIZE - packetbuf_totlen()); - - PRINTF("contikimac: shorter than shortest (%d)\n", packetbuf_totlen()); - transmit_len = SHORTEST_PACKET_SIZE; - } - - - packetbuf_compact(); - -#ifdef NETSTACK_ENCRYPT - NETSTACK_ENCRYPT(); -#endif /* NETSTACK_ENCRYPT */ - - transmit_len = packetbuf_totlen(); - NETSTACK_RADIO.prepare(packetbuf_hdrptr(), transmit_len); - - /* Remove the MAC-layer header since it will be recreated next time around. */ - packetbuf_hdr_remove(hdrlen); - + if(!is_broadcast && !is_receiver_awake) { #if WITH_PHASE_OPTIMIZATION ret = phase_wait(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), @@ -865,33 +783,55 @@ qsend_packet(mac_callback_t sent, void *ptr) static void qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) { - struct rdc_buf_list *curr = buf_list; + struct rdc_buf_list *curr; struct rdc_buf_list *next; int ret; int is_receiver_awake; - if(curr == NULL) { + if(buf_list == NULL) { return; } /* Do not send during reception of a burst */ if(we_are_receiving_burst) { /* Prepare the packetbuf for callback */ - queuebuf_to_packetbuf(curr->buf); + queuebuf_to_packetbuf(buf_list->buf); /* Return COLLISION so the MAC may try again later */ mac_call_sent_callback(sent, ptr, MAC_TX_COLLISION, 1); return; } + + /* Create and secure frames in advance */ + curr = buf_list; + do { + next = list_item_next(curr); + queuebuf_to_packetbuf(curr->buf); + if(!packetbuf_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED)) { + /* create and secure this frame */ + if(next != NULL) { + packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1); + } + packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); + if(NETSTACK_FRAMER.create_and_secure() < 0) { + PRINTF("contikimac: framer failed\n"); + mac_call_sent_callback(sent, ptr, MAC_TX_ERR_FATAL, 1); + return; + } + + packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1); + queuebuf_update_from_packetbuf(curr->buf); + } + curr = next; + } while(next != NULL); + /* The receiver needs to be awoken before we send */ is_receiver_awake = 0; + curr = buf_list; do { /* A loop sending a burst of packets from buf_list */ next = list_item_next(curr); /* Prepare the packetbuf */ queuebuf_to_packetbuf(curr->buf); - if(next != NULL) { - packetbuf_set_attr(PACKETBUF_ATTR_PENDING, 1); - } - + /* Send the current packet */ ret = send_packet(sent, ptr, curr, is_receiver_awake); if(ret != MAC_TX_DEFERRED) { @@ -908,7 +848,7 @@ qsend_list(mac_callback_t sent, void *ptr, struct rdc_buf_list *buf_list) /* The transmission failed, we stop the burst */ next = NULL; } - } while(next != NULL); + } while((next != NULL) && packetbuf_attr(PACKETBUF_ATTR_PENDING)); } /*---------------------------------------------------------------------------*/ /* Timer callback triggered when receiving a burst, after having @@ -931,23 +871,7 @@ input_packet(void) /* printf("cycle_start 0x%02x 0x%02x\n", cycle_start, cycle_start % CYCLE_TIME);*/ -#ifdef NETSTACK_DECRYPT - NETSTACK_DECRYPT(); -#endif /* NETSTACK_DECRYPT */ - if(packetbuf_totlen() > 0 && NETSTACK_FRAMER.parse() >= 0) { - -#if WITH_CONTIKIMAC_HEADER - struct hdr *chdr; - chdr = packetbuf_dataptr(); - if(chdr->id != CONTIKIMAC_ID) { - PRINTF("contikimac: failed to parse hdr (%u)\n", packetbuf_totlen()); - return; - } - packetbuf_hdrreduce(sizeof(struct hdr)); - packetbuf_set_datalen(chdr->len); -#endif /* WITH_CONTIKIMAC_HEADER */ - if(packetbuf_datalen() > 0 && packetbuf_totlen() > 0 && (linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), @@ -958,6 +882,8 @@ input_packet(void) broadcast address. */ /* If FRAME_PENDING is set, we are receiving a packets in a burst */ + /* TODO To prevent denial-of-sleep attacks, the transceiver should + be disabled upon receipt of an unauthentic frame. */ we_are_receiving_burst = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(we_are_receiving_burst) { on(); @@ -969,6 +895,7 @@ input_packet(void) ctimer_stop(&ct); } +#if RDC_WITH_DUPLICATE_DETECTION /* Check for duplicate packet. */ if(mac_sequence_is_duplicate()) { /* Drop the packet. */ @@ -976,6 +903,7 @@ input_packet(void) return; } mac_sequence_register_seqno(); +#endif /* RDC_WITH_DUPLICATE_DETECTION */ #if CONTIKIMAC_CONF_COMPOWER /* Accumulate the power consumption for the packet reception. */ diff --git a/core/net/mac/csma.c b/core/net/mac/csma.c index c07f5887a..379f86ba4 100644 --- a/core/net/mac/csma.c +++ b/core/net/mac/csma.c @@ -396,7 +396,7 @@ send_packet(mac_callback_t sent, void *ptr) static void input_packet(void) { - NETSTACK_NETWORK.input(); + NETSTACK_LLSEC.input(); } /*---------------------------------------------------------------------------*/ static int diff --git a/core/net/mac/frame802154.c b/core/net/mac/frame802154.c index fa7a46962..d98be6269 100644 --- a/core/net/mac/frame802154.c +++ b/core/net/mac/frame802154.c @@ -63,6 +63,7 @@ #include "sys/cc.h" #include "net/mac/frame802154.h" +#include "net/llsec/llsec802154.h" #include /** @@ -91,6 +92,23 @@ addr_len(uint8_t mode) } } /*----------------------------------------------------------------------------*/ +#if LLSEC802154_USES_EXPLICIT_KEYS +static uint8_t +get_key_id_len(uint8_t key_id_mode) +{ + switch(key_id_mode) { + case FRAME802154_1_BYTE_KEY_ID_MODE: + return 1; + case FRAME802154_5_BYTE_KEY_ID_MODE: + return 5; + case FRAME802154_9_BYTE_KEY_ID_MODE: + return 9; + default: + return 0; + } +} +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ +/*----------------------------------------------------------------------------*/ static void field_len(frame802154_t *p, field_length_t *flen) { @@ -120,28 +138,16 @@ field_len(frame802154_t *p, field_length_t *flen) flen->dest_addr_len = addr_len(p->fcf.dest_addr_mode & 3); flen->src_addr_len = addr_len(p->fcf.src_addr_mode & 3); +#if LLSEC802154_SECURITY_LEVEL /* Aux security header */ if(p->fcf.security_enabled & 1) { - /* TODO Aux security header not yet implemented */ -#if 0 - switch(p->aux_hdr.security_control.key_id_mode) { - case 0: - flen->aux_sec_len = 5; /* minimum value */ - break; - case 1: - flen->aux_sec_len = 6; - break; - case 2: - flen->aux_sec_len = 10; - break; - case 3: - flen->aux_sec_len = 14; - break; - default: - break; - } -#endif + flen->aux_sec_len = 5 +#if LLSEC802154_USES_EXPLICIT_KEYS + + get_key_id_len(p->aux_hdr.security_control.key_id_mode); +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ + ; } +#endif /* LLSEC802154_SECURITY_LEVEL */ } /*----------------------------------------------------------------------------*/ /** @@ -171,70 +177,79 @@ frame802154_hdrlen(frame802154_t *p) * * \param buf Pointer to the buffer to use for the frame. * - * \param buf_len The length of the buffer to use for the frame. - * - * \return The length of the frame header or 0 if there was - * insufficient space in the buffer for the frame headers. + * \return The length of the frame header */ int -frame802154_create(frame802154_t *p, uint8_t *buf, int buf_len) +frame802154_create(frame802154_t *p, uint8_t *buf) { int c; field_length_t flen; - uint8_t *tx_frame_buffer; uint8_t pos; +#if LLSEC802154_USES_EXPLICIT_KEYS + uint8_t key_id_mode; +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ field_len(p, &flen); - - if(3 + flen.dest_pid_len + flen.dest_addr_len + - flen.src_pid_len + flen.src_addr_len + flen.aux_sec_len > buf_len) { - /* Too little space for headers. */ - return 0; - } - + /* OK, now we have field lengths. Time to actually construct */ - /* the outgoing frame, and store it in tx_frame_buffer */ - tx_frame_buffer = buf; - tx_frame_buffer[0] = (p->fcf.frame_type & 7) | + /* the outgoing frame, and store it in buf */ + buf[0] = (p->fcf.frame_type & 7) | ((p->fcf.security_enabled & 1) << 3) | ((p->fcf.frame_pending & 1) << 4) | ((p->fcf.ack_required & 1) << 5) | ((p->fcf.panid_compression & 1) << 6); - tx_frame_buffer[1] = ((p->fcf.dest_addr_mode & 3) << 2) | + buf[1] = ((p->fcf.dest_addr_mode & 3) << 2) | ((p->fcf.frame_version & 3) << 4) | ((p->fcf.src_addr_mode & 3) << 6); /* sequence number */ - tx_frame_buffer[2] = p->seq; + buf[2] = p->seq; pos = 3; /* Destination PAN ID */ if(flen.dest_pid_len == 2) { - tx_frame_buffer[pos++] = p->dest_pid & 0xff; - tx_frame_buffer[pos++] = (p->dest_pid >> 8) & 0xff; + buf[pos++] = p->dest_pid & 0xff; + buf[pos++] = (p->dest_pid >> 8) & 0xff; } /* Destination address */ for(c = flen.dest_addr_len; c > 0; c--) { - tx_frame_buffer[pos++] = p->dest_addr[c - 1]; + buf[pos++] = p->dest_addr[c - 1]; } /* Source PAN ID */ if(flen.src_pid_len == 2) { - tx_frame_buffer[pos++] = p->src_pid & 0xff; - tx_frame_buffer[pos++] = (p->src_pid >> 8) & 0xff; + buf[pos++] = p->src_pid & 0xff; + buf[pos++] = (p->src_pid >> 8) & 0xff; } /* Source address */ for(c = flen.src_addr_len; c > 0; c--) { - tx_frame_buffer[pos++] = p->src_addr[c - 1]; + buf[pos++] = p->src_addr[c - 1]; } +#if LLSEC802154_SECURITY_LEVEL /* Aux header */ if(flen.aux_sec_len) { - /* TODO Aux security header not yet implemented */ -/* pos += flen.aux_sec_len; */ + buf[pos++] = p->aux_hdr.security_control.security_level +#if LLSEC802154_USES_EXPLICIT_KEYS + | (p->aux_hdr.security_control.key_id_mode << 3) +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ + ; + memcpy(buf + pos, p->aux_hdr.frame_counter.u8, 4); + pos += 4; + +#if LLSEC802154_USES_EXPLICIT_KEYS + key_id_mode = p->aux_hdr.security_control.key_id_mode; + if(key_id_mode) { + c = (key_id_mode - 1) * 4; + memcpy(buf + pos, p->aux_hdr.key_source.u8, c); + pos += c; + buf[pos++] = p->aux_hdr.key_index; + } +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } +#endif /* LLSEC802154_SECURITY_LEVEL */ return (int)pos; } @@ -254,6 +269,9 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf) uint8_t *p; frame802154_fcf_t fcf; int c; +#if LLSEC802154_USES_EXPLICIT_KEYS + uint8_t key_id_mode; +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ if(len < 3) { return 0; @@ -336,11 +354,30 @@ frame802154_parse(uint8_t *data, int len, frame802154_t *pf) linkaddr_copy((linkaddr_t *)&(pf->src_addr), &linkaddr_null); pf->src_pid = 0; } - + +#if LLSEC802154_SECURITY_LEVEL if(fcf.security_enabled) { - /* TODO aux security header, not yet implemented */ -/* return 0; */ + pf->aux_hdr.security_control.security_level = p[0] & 7; +#if LLSEC802154_USES_EXPLICIT_KEYS + pf->aux_hdr.security_control.key_id_mode = (p[0] >> 3) & 3; +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ + p += 1; + + memcpy(pf->aux_hdr.frame_counter.u8, p, 4); + p += 4; + +#if LLSEC802154_USES_EXPLICIT_KEYS + key_id_mode = pf->aux_hdr.security_control.key_id_mode; + if(key_id_mode) { + c = (key_id_mode - 1) * 4; + memcpy(pf->aux_hdr.key_source.u8, p, c); + p += c; + pf->aux_hdr.key_index = p[0]; + p += 1; + } +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ } +#endif /* LLSEC802154_SECURITY_LEVEL */ /* header length */ c = p - data; diff --git a/core/net/mac/frame802154.h b/core/net/mac/frame802154.h index 87358f6d9..1e97a41df 100644 --- a/core/net/mac/frame802154.h +++ b/core/net/mac/frame802154.h @@ -66,9 +66,9 @@ #ifdef IEEE802154_CONF_PANID #define IEEE802154_PANID IEEE802154_CONF_PANID -#else +#else /* IEEE802154_CONF_PANID */ #define IEEE802154_PANID 0xABCD -#endif +#endif /* IEEE802154_CONF_PANID */ /* Macros & Defines */ @@ -96,9 +96,19 @@ #define FRAME802154_IEEE802154_2003 (0x00) #define FRAME802154_IEEE802154_2006 (0x01) -#define FRAME802154_SECURITY_LEVEL_NONE (0) -#define FRAME802154_SECURITY_LEVEL_128 (3) +#define FRAME802154_SECURITY_LEVEL_NONE (0) +#define FRAME802154_SECURITY_LEVEL_MIC_32 (1) +#define FRAME802154_SECURITY_LEVEL_MIC_64 (2) +#define FRAME802154_SECURITY_LEVEL_MIC_128 (3) +#define FRAME802154_SECURITY_LEVEL_ENC (4) +#define FRAME802154_SECURITY_LEVEL_ENC_MIC_32 (5) +#define FRAME802154_SECURITY_LEVEL_ENC_MIC_64 (6) +#define FRAME802154_SECURITY_LEVEL_ENC_MIC_128 (7) +#define FRAME802154_IMPLICIT_KEY (0) +#define FRAME802154_1_BYTE_KEY_ID_MODE (1) +#define FRAME802154_5_BYTE_KEY_ID_MODE (2) +#define FRAME802154_9_BYTE_KEY_ID_MODE (3) /** * @brief The IEEE 802.15.4 frame has a number of constant/fixed fields that @@ -135,11 +145,23 @@ typedef struct { uint8_t reserved; /**< 3 bit. Reserved bits */ } frame802154_scf_t; +typedef union { + uint32_t u32; + uint16_t u16[2]; + uint8_t u8[4]; +} frame802154_frame_counter_t; + +typedef union { + uint16_t u16[4]; + uint8_t u8[8]; +} frame802154_key_source_t; + /** \brief 802.15.4 Aux security header */ typedef struct { - frame802154_scf_t security_control; /**< Security control bitfield */ - uint32_t frame_counter; /**< Frame counter, used for security */ - uint8_t key[9]; /**< The key itself, or an index to the key */ + frame802154_scf_t security_control; /**< Security control bitfield */ + frame802154_frame_counter_t frame_counter; /**< Frame counter, used for security */ + frame802154_key_source_t key_source; /**< Key Source subfield */ + uint8_t key_index; /**< Key Index subfield */ } frame802154_aux_hdr_t; /** \brief Parameters used by the frame802154_create() function. These @@ -147,21 +169,21 @@ typedef struct { * specification for details. */ typedef struct { - frame802154_fcf_t fcf; /**< Frame control field */ - uint8_t seq; /**< Sequence number */ - uint16_t dest_pid; /**< Destination PAN ID */ - uint8_t dest_addr[8]; /**< Destination address */ - uint16_t src_pid; /**< Source PAN ID */ - uint8_t src_addr[8]; /**< Source address */ - frame802154_aux_hdr_t aux_hdr; /**< Aux security header */ - uint8_t *payload; /**< Pointer to 802.15.4 frame payload */ - int payload_len; /**< Length of payload field */ + frame802154_fcf_t fcf; /**< Frame control field */ + uint8_t seq; /**< Sequence number */ + uint16_t dest_pid; /**< Destination PAN ID */ + uint8_t dest_addr[8]; /**< Destination address */ + uint16_t src_pid; /**< Source PAN ID */ + uint8_t src_addr[8]; /**< Source address */ + frame802154_aux_hdr_t aux_hdr; /**< Aux security header */ + uint8_t *payload; /**< Pointer to 802.15.4 payload */ + int payload_len; /**< Length of payload field */ } frame802154_t; /* Prototypes */ int frame802154_hdrlen(frame802154_t *p); -int frame802154_create(frame802154_t *p, uint8_t *buf, int buf_len); +int frame802154_create(frame802154_t *p, uint8_t *buf); int frame802154_parse(uint8_t *data, int length, frame802154_t *pf); /** @} */ diff --git a/core/net/mac/framer-802154.c b/core/net/mac/framer-802154.c index a0aea598b..f1da770a7 100644 --- a/core/net/mac/framer-802154.c +++ b/core/net/mac/framer-802154.c @@ -38,6 +38,7 @@ #include "net/mac/framer-802154.h" #include "net/mac/frame802154.h" +#include "net/llsec/llsec802154.h" #include "net/packetbuf.h" #include "lib/random.h" #include @@ -90,7 +91,7 @@ static int create_frame(int type, int do_create) { frame802154_t params; - int len; + int hdr_len; /* init to zeros */ memset(¶ms, 0, sizeof(params)); @@ -101,8 +102,7 @@ create_frame(int type, int do_create) } /* Build the FCF. */ - params.fcf.frame_type = FRAME802154_DATAFRAME; - params.fcf.security_enabled = 0; + params.fcf.frame_type = packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE); params.fcf.frame_pending = packetbuf_attr(PACKETBUF_ATTR_PENDING); if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), &linkaddr_null)) { params.fcf.ack_required = 0; @@ -111,8 +111,23 @@ create_frame(int type, int do_create) } params.fcf.panid_compression = 0; - /* Insert IEEE 802.15.4 (2003) version bit. */ - params.fcf.frame_version = FRAME802154_IEEE802154_2003; + /* Insert IEEE 802.15.4 (2006) version bits. */ + params.fcf.frame_version = FRAME802154_IEEE802154_2006; + +#if LLSEC802154_SECURITY_LEVEL + if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL)) { + params.fcf.security_enabled = 1; + } + /* Setting security-related attributes */ + params.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL); + params.aux_hdr.frame_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); + params.aux_hdr.frame_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); +#if LLSEC802154_USES_EXPLICIT_KEYS + params.aux_hdr.security_control.key_id_mode = packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE); + params.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX); + params.aux_hdr.key_source.u16[0] = packetbuf_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1); +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ +#endif /* LLSEC802154_SECURITY_LEVEL */ /* Increment and set the data sequence number. */ if(!do_create) { @@ -123,6 +138,10 @@ create_frame(int type, int do_create) params.seq = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); } else { + /* Ensure that the sequence number 0 is not used as it would bypass the above check. */ + if(mac_dsn == 0) { + mac_dsn++; + } params.seq = mac_dsn++; packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, params.seq); } @@ -172,21 +191,21 @@ create_frame(int type, int do_create) params.payload = packetbuf_dataptr(); params.payload_len = packetbuf_datalen(); - len = frame802154_hdrlen(¶ms); + hdr_len = frame802154_hdrlen(¶ms); if(!do_create) { /* Only calculate header length */ - return len; + return hdr_len; - } else if(packetbuf_hdralloc(len)) { - frame802154_create(¶ms, packetbuf_hdrptr(), len); + } else if(packetbuf_hdralloc(hdr_len)) { + frame802154_create(¶ms, packetbuf_hdrptr()); PRINTF("15.4-OUT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); - PRINTF("%d %u (%u)\n", len, packetbuf_datalen(), packetbuf_totlen()); + PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); - return len; + return hdr_len; } else { - PRINTF("15.4-OUT: too large header: %u\n", len); + PRINTF("15.4-OUT: too large header: %u\n", hdr_len); return FRAMER_FAILED; } } @@ -207,13 +226,16 @@ static int parse(void) { frame802154_t frame; - int len; - len = packetbuf_datalen(); - if(frame802154_parse(packetbuf_dataptr(), len, &frame) && - packetbuf_hdrreduce(len - frame.payload_len)) { + int hdr_len; + + hdr_len = frame802154_parse(packetbuf_dataptr(), packetbuf_datalen(), &frame); + + if(hdr_len && packetbuf_hdrreduce(hdr_len)) { + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type); + if(frame.fcf.dest_addr_mode) { if(frame.dest_pid != mac_src_pan_id && - frame.dest_pid != FRAME802154_BROADCASTPANDID) { + frame.dest_pid != FRAME802154_BROADCASTPANDID) { /* Packet to another PAN */ PRINTF("15.4: for another pan %u\n", frame.dest_pid); return FRAMER_FAILED; @@ -226,17 +248,34 @@ parse(void) packetbuf_set_attr(PACKETBUF_ATTR_PENDING, frame.fcf.frame_pending); /* packetbuf_set_attr(PACKETBUF_ATTR_RELIABLE, frame.fcf.ack_required);*/ packetbuf_set_attr(PACKETBUF_ATTR_PACKET_ID, frame.seq); + +#if LLSEC802154_SECURITY_LEVEL + if(frame.fcf.security_enabled) { + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, frame.aux_hdr.security_control.security_level); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame.aux_hdr.frame_counter.u16[0]); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame.aux_hdr.frame_counter.u16[1]); +#if LLSEC802154_USES_EXPLICIT_KEYS + packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, frame.aux_hdr.security_control.key_id_mode); + packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, frame.aux_hdr.key_index); + packetbuf_set_attr(PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, frame.aux_hdr.key_source.u16[0]); +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ + } +#endif /* LLSEC802154_SECURITY_LEVEL */ PRINTF("15.4-IN: %2X", frame.fcf.frame_type); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER)); PRINTADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER)); - PRINTF("%u (%u)\n", packetbuf_datalen(), len); - - return len - frame.payload_len; + PRINTF("%d %u (%u)\n", hdr_len, packetbuf_datalen(), packetbuf_totlen()); + + return hdr_len; } return FRAMER_FAILED; } /*---------------------------------------------------------------------------*/ const struct framer framer_802154 = { - hdr_length, create, parse + hdr_length, + create, + framer_canonical_create_and_secure, + parse }; +/*---------------------------------------------------------------------------*/ diff --git a/core/net/mac/framer-nullmac.c b/core/net/mac/framer-nullmac.c index bec94eba5..6d53e3f8d 100644 --- a/core/net/mac/framer-nullmac.c +++ b/core/net/mac/framer-nullmac.c @@ -97,5 +97,8 @@ parse(void) } /*---------------------------------------------------------------------------*/ const struct framer framer_nullmac = { - hdr_length, create, parse + hdr_length, + create, + framer_canonical_create_and_secure, + parse }; diff --git a/core/net/mac/framer.c b/core/net/mac/framer.c new file mode 100644 index 000000000..fa7e9b4c1 --- /dev/null +++ b/core/net/mac/framer.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014, Fraunhofer Heinrich-Hertz-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include "net/mac/framer.h" +#include "net/packetbuf.h" +#include "net/netstack.h" + +/*---------------------------------------------------------------------------*/ +int +framer_canonical_create_and_secure(void) +{ + int hdr_len; + + hdr_len = NETSTACK_FRAMER.create(); + if(hdr_len >= 0) { + packetbuf_compact(); + if(!NETSTACK_LLSEC.on_frame_created()) { + return FRAMER_FAILED; + } + } + return hdr_len; +} +/*---------------------------------------------------------------------------*/ \ No newline at end of file diff --git a/core/net/mac/framer.h b/core/net/mac/framer.h index 5ed419292..ce99aad1f 100644 --- a/core/net/mac/framer.h +++ b/core/net/mac/framer.h @@ -47,8 +47,13 @@ struct framer { int (* length)(void); int (* create)(void); + + /** Creates the frame and calls LLSEC.on_frame_created() */ + int (* create_and_secure)(void); int (* parse)(void); }; +int framer_canonical_create_and_secure(void); + #endif /* FRAMER_H_ */ diff --git a/core/net/mac/nullmac.c b/core/net/mac/nullmac.c index f65fedfdb..4e542651a 100644 --- a/core/net/mac/nullmac.c +++ b/core/net/mac/nullmac.c @@ -54,7 +54,7 @@ send_packet(mac_callback_t sent, void *ptr) static void packet_input(void) { - NETSTACK_NETWORK.input(); + NETSTACK_LLSEC.input(); } /*---------------------------------------------------------------------------*/ static int diff --git a/core/net/mac/nullrdc.c b/core/net/mac/nullrdc.c index 7e7be6004..7f92495e8 100644 --- a/core/net/mac/nullrdc.c +++ b/core/net/mac/nullrdc.c @@ -120,16 +120,11 @@ send_one_packet(mac_callback_t sent, void *ptr) packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1); #endif /* NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW */ - if(NETSTACK_FRAMER.create() < 0) { + if(NETSTACK_FRAMER.create_and_secure() < 0) { /* Failed to allocate space for headers */ PRINTF("nullrdc: send failed, too large header\n"); ret = MAC_TX_ERR_FATAL; } else { - -#ifdef NETSTACK_ENCRYPT - NETSTACK_ENCRYPT(); -#endif /* NETSTACK_ENCRYPT */ - #if NULLRDC_802154_AUTOACK int is_broadcast; uint8_t dsn; @@ -275,9 +270,6 @@ packet_input(void) original_datalen = packetbuf_datalen(); original_dataptr = packetbuf_dataptr(); -#ifdef NETSTACK_DECRYPT - NETSTACK_DECRYPT(); -#endif /* NETSTACK_DECRYPT */ #if NULLRDC_802154_AUTOACK if(packetbuf_datalen() == ACK_LEN) { @@ -298,6 +290,7 @@ packet_input(void) int duplicate = 0; #if NULLRDC_802154_AUTOACK || NULLRDC_802154_AUTOACK_HW +#if RDC_WITH_DUPLICATE_DETECTION /* Check for duplicate packet. */ duplicate = mac_sequence_is_duplicate(); if(duplicate) { @@ -307,8 +300,10 @@ packet_input(void) } else { mac_sequence_register_seqno(); } +#endif /* RDC_WITH_DUPLICATE_DETECTION */ #endif /* NULLRDC_802154_AUTOACK */ +/* TODO We may want to acknowledge only authentic frames */ #if NULLRDC_SEND_802154_ACK { frame802154_t info154; diff --git a/core/net/mac/phase.c b/core/net/mac/phase.c index 9176061b7..ff20ae978 100644 --- a/core/net/mac/phase.c +++ b/core/net/mac/phase.c @@ -217,6 +217,7 @@ phase_wait(const linkaddr_t *neighbor, rtimer_clock_t cycle_time, p = memb_alloc(&queued_packets_memb); if(p != NULL) { if(buf_list == NULL) { + packetbuf_set_attr(PACKETBUF_ATTR_IS_CREATED_AND_SECURED, 1); p->q = queuebuf_new_from_packetbuf(); } p->mac_callback = mac_callback; diff --git a/core/net/mac/rdc.h b/core/net/mac/rdc.h index 9a47605b7..0818a9b40 100644 --- a/core/net/mac/rdc.h +++ b/core/net/mac/rdc.h @@ -44,6 +44,16 @@ #include "contiki-conf.h" #include "net/mac/mac.h" +#ifdef RDC_CONF_WITH_DUPLICATE_DETECTION +#define RDC_WITH_DUPLICATE_DETECTION RDC_CONF_WITH_DUPLICATE_DETECTION +#else /* RDC_CONF_WITH_DUPLICATE_DETECTION */ +/* As frames can be spoofed, the RDC layer should not discard a + frame because it has seen its sequence number already. Replay + protection should be implemented at the LLSEC layer where the + authenticity of frames is verified. */ +#define RDC_WITH_DUPLICATE_DETECTION !LLSEC802154_CONF_SECURITY_LEVEL +#endif /* RDC_CONF_WITH_DUPLICATE_DETECTION */ + /* List of packets to be sent by RDC layer */ struct rdc_buf_list { struct rdc_buf_list *next; diff --git a/core/net/mac/sicslowmac/sicslowmac.c b/core/net/mac/sicslowmac/sicslowmac.c index 2c7562f29..56db88ff5 100644 --- a/core/net/mac/sicslowmac/sicslowmac.c +++ b/core/net/mac/sicslowmac/sicslowmac.c @@ -157,7 +157,7 @@ send_packet(mac_callback_t sent, void *ptr) len = frame802154_hdrlen(¶ms); if(packetbuf_hdralloc(len)) { int ret; - frame802154_create(¶ms, packetbuf_hdrptr(), len); + frame802154_create(¶ms, packetbuf_hdrptr()); PRINTF("6MAC-UT: %2X", params.fcf.frame_type); PRINTADDR(params.dest_addr); diff --git a/core/net/netstack.c b/core/net/netstack.c index c7dc8336c..35e7f2c48 100644 --- a/core/net/netstack.c +++ b/core/net/netstack.c @@ -46,9 +46,5 @@ netstack_init(void) NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); - -#ifdef NETSTACK_ENCRYPTION_INIT - NETSTACK_ENCRYPTION_INIT(); -#endif /* NETSTACK_ENCRYPTION_INIT */ } /*---------------------------------------------------------------------------*/ diff --git a/core/net/netstack.h b/core/net/netstack.h index aa5f7be1e..4bb252c8f 100644 --- a/core/net/netstack.h +++ b/core/net/netstack.h @@ -28,6 +28,7 @@ * * This file is part of the Contiki operating system. * + * $Id: netstack.h,v 1.6 2010/10/03 20:37:32 adamdunkels Exp $ */ /** @@ -50,6 +51,14 @@ #endif /* NETSTACK_CONF_NETWORK */ #endif /* NETSTACK_NETWORK */ +#ifndef NETSTACK_LLSEC +#ifdef NETSTACK_CONF_LLSEC +#define NETSTACK_LLSEC NETSTACK_CONF_LLSEC +#else /* NETSTACK_CONF_LLSEC */ +#define NETSTACK_LLSEC nullsec_driver +#endif /* NETSTACK_CONF_LLSEC */ +#endif /* NETSTACK_LLSEC */ + #ifndef NETSTACK_MAC #ifdef NETSTACK_CONF_MAC #define NETSTACK_MAC NETSTACK_CONF_MAC @@ -96,6 +105,7 @@ #endif /* NETSTACK_CONF_FRAMER */ #endif /* NETSTACK_FRAMER */ +#include "net/llsec/llsec.h" #include "net/mac/mac.h" #include "net/mac/rdc.h" #include "net/mac/framer.h" @@ -115,6 +125,7 @@ struct network_driver { }; extern const struct network_driver NETSTACK_NETWORK; +extern const struct llsec_driver NETSTACK_LLSEC; extern const struct rdc_driver NETSTACK_RDC; extern const struct mac_driver NETSTACK_MAC; extern const struct radio_driver NETSTACK_RADIO; diff --git a/core/net/packetbuf.c b/core/net/packetbuf.c index 94e8a4966..2248936d6 100644 --- a/core/net/packetbuf.c +++ b/core/net/packetbuf.c @@ -244,7 +244,16 @@ packetbuf_datalen(void) uint8_t packetbuf_hdrlen(void) { - return PACKETBUF_HDR_SIZE - hdrptr; + uint8_t hdrlen; + + hdrlen = PACKETBUF_HDR_SIZE - hdrptr; + if(hdrlen) { + /* outbound packet */ + return hdrlen; + } else { + /* inbound packet */ + return bufptr; + } } /*---------------------------------------------------------------------------*/ uint16_t diff --git a/core/net/packetbuf.h b/core/net/packetbuf.h index ab84da8fe..17abc5709 100644 --- a/core/net/packetbuf.h +++ b/core/net/packetbuf.h @@ -54,6 +54,7 @@ #include "contiki-conf.h" #include "net/linkaddr.h" +#include "net/llsec/llsec802154.h" /** * \brief The size of the packetbuf, in bytes @@ -132,7 +133,7 @@ void *packetbuf_dataptr(void); void *packetbuf_hdrptr(void); /** - * \brief Get the length of the header in the packetbuf, for outbound packets + * \brief Get the length of the header in the packetbuf * \return Length of the header in the packetbuf * * For outbound packets, the packetbuf consists of two @@ -347,7 +348,8 @@ enum { PACKETBUF_ATTR_MAX_MAC_TRANSMISSIONS, PACKETBUF_ATTR_MAC_SEQNO, PACKETBUF_ATTR_MAC_ACK, - + PACKETBUF_ATTR_IS_CREATED_AND_SECURED, + /* Scope 1 attributes: used between two neighbors only. */ PACKETBUF_ATTR_RELIABLE, PACKETBUF_ATTR_PACKET_ID, @@ -356,6 +358,17 @@ enum { PACKETBUF_ATTR_MAX_REXMIT, PACKETBUF_ATTR_NUM_REXMIT, PACKETBUF_ATTR_PENDING, + PACKETBUF_ATTR_FRAME_TYPE, +#if LLSEC802154_SECURITY_LEVEL + PACKETBUF_ATTR_SECURITY_LEVEL, + PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, + PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, +#if LLSEC802154_USES_EXPLICIT_KEYS + PACKETBUF_ATTR_KEY_ID_MODE, + PACKETBUF_ATTR_KEY_INDEX, + PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1, +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ +#endif /* LLSEC802154_SECURITY_LEVEL */ /* Scope 2 attributes: used between end-to-end nodes. */ PACKETBUF_ATTR_HOPS, @@ -373,6 +386,24 @@ enum { PACKETBUF_ATTR_MAX }; +/* Define surrogates when 802.15.4 security is off */ +#if !LLSEC802154_SECURITY_LEVEL +enum { + PACKETBUF_ATTR_SECURITY_LEVEL, + PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, + PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3 +}; +#endif /* LLSEC802154_SECURITY_LEVEL */ + +/* Define surrogates when not using explicit keys */ +#if !LLSEC802154_USES_EXPLICIT_KEYS +enum { + PACKETBUF_ATTR_KEY_ID_MODE, + PACKETBUF_ATTR_KEY_INDEX, + PACKETBUF_ATTR_KEY_SOURCE_BYTES_0_1 +}; +#endif /* LLSEC802154_USES_EXPLICIT_KEYS */ + #define PACKETBUF_NUM_ADDRS 4 #define PACKETBUF_NUM_ATTRS (PACKETBUF_ATTR_MAX - PACKETBUF_NUM_ADDRS) #define PACKETBUF_ADDR_FIRST PACKETBUF_ADDR_SENDER diff --git a/core/net/queuebuf.c b/core/net/queuebuf.c index 8cb8708b3..8e5cb06f7 100644 --- a/core/net/queuebuf.c +++ b/core/net/queuebuf.c @@ -405,6 +405,19 @@ queuebuf_update_attr_from_packetbuf(struct queuebuf *buf) } /*---------------------------------------------------------------------------*/ void +queuebuf_update_from_packetbuf(struct queuebuf *buf) +{ + struct queuebuf_data *buframptr = queuebuf_load_to_ram(buf); + packetbuf_attr_copyto(buframptr->attrs, buframptr->addrs); + buframptr->len = packetbuf_copyto(buframptr->data); +#if WITH_SWAP + if(buf->location == IN_CFS) { + queuebuf_flush_tmpdata(); + } +#endif +} +/*---------------------------------------------------------------------------*/ +void queuebuf_free(struct queuebuf *buf) { if(memb_inmemb(&bufmem, buf)) { diff --git a/core/net/queuebuf.h b/core/net/queuebuf.h index a1727342d..94fdb2105 100644 --- a/core/net/queuebuf.h +++ b/core/net/queuebuf.h @@ -96,6 +96,7 @@ struct queuebuf *queuebuf_new_from_packetbuf_debug(const char *file, int line); struct queuebuf *queuebuf_new_from_packetbuf(void); #endif /* QUEUEBUF_DEBUG */ void queuebuf_update_attr_from_packetbuf(struct queuebuf *b); +void queuebuf_update_from_packetbuf(struct queuebuf *b); void queuebuf_to_packetbuf(struct queuebuf *b); void queuebuf_free(struct queuebuf *b); diff --git a/core/net/rime/rime.c b/core/net/rime/rime.c index 8a45e8177..0117b4988 100644 --- a/core/net/rime/rime.c +++ b/core/net/rime/rime.c @@ -180,7 +180,7 @@ rime_output(struct channel *c) if(chameleon_create(c)) { packetbuf_compact(); - NETSTACK_MAC.send(packet_sent, c); + NETSTACK_LLSEC.send(packet_sent, c); return 1; } return 0; diff --git a/cpu/mc1322x/contiki-maca.c b/cpu/mc1322x/contiki-maca.c index 916ac8a22..29357de28 100644 --- a/cpu/mc1322x/contiki-maca.c +++ b/cpu/mc1322x/contiki-maca.c @@ -229,7 +229,7 @@ int contiki_maca_read(void *buf, unsigned short bufsize) { } #endif PRINTF("\n\r"); - free_packet(p); + maca_free_packet(p); return bufsize; } else { return 0; diff --git a/cpu/mc1322x/lib/include/maca.h b/cpu/mc1322x/lib/include/maca.h index 5f1083f38..29e74f319 100644 --- a/cpu/mc1322x/lib/include/maca.h +++ b/cpu/mc1322x/lib/include/maca.h @@ -71,7 +71,7 @@ extern volatile uint8_t prm_mode; void tx_packet(volatile packet_t *p); volatile packet_t* rx_packet(void); volatile packet_t* get_free_packet(void); -void free_packet(volatile packet_t *p); +void maca_free_packet(volatile packet_t *p); void free_all_packets(void); extern volatile packet_t *rx_head, *tx_head; diff --git a/cpu/mc1322x/lib/maca.c b/cpu/mc1322x/lib/maca.c index c39b27ccb..92cf99b42 100644 --- a/cpu/mc1322x/lib/maca.c +++ b/cpu/mc1322x/lib/maca.c @@ -300,7 +300,7 @@ void bound_check(volatile packet_t *p) { /* public packet routines */ /* heads are to the right */ /* ends are to the left */ -void free_packet(volatile packet_t *p) { +void maca_free_packet(volatile packet_t *p) { safe_irq_disable(MACA); BOUND_CHECK(p); @@ -495,7 +495,7 @@ void free_all_packets(void) { free_head = 0; for(i=0; ileft; if(tx_head == 0) { tx_end = 0; } - free_packet(p); + maca_free_packet(p); // print_packets("free tx head"); irq_restore(); diff --git a/cpu/mc1322x/tests/autoack-rx.c b/cpu/mc1322x/tests/autoack-rx.c index 03de59249..518e9ed7a 100644 --- a/cpu/mc1322x/tests/autoack-rx.c +++ b/cpu/mc1322x/tests/autoack-rx.c @@ -94,7 +94,7 @@ void main(void) { /* print and free the packet */ printf("autoack-rx --- "); print_packet(p); - free_packet(p); + maca_free_packet(p); } if(uart1_can_get()) { diff --git a/cpu/mc1322x/tests/autoack-tx.c b/cpu/mc1322x/tests/autoack-tx.c index 205c18a49..0a1d257f5 100644 --- a/cpu/mc1322x/tests/autoack-tx.c +++ b/cpu/mc1322x/tests/autoack-tx.c @@ -139,7 +139,7 @@ void main(void) { if(p) { printf("RX: "); print_packet(p); - free_packet(p); + maca_free_packet(p); } } diff --git a/cpu/mc1322x/tests/per.c b/cpu/mc1322x/tests/per.c index f3a795b96..4e21714a7 100644 --- a/cpu/mc1322x/tests/per.c +++ b/cpu/mc1322x/tests/per.c @@ -146,7 +146,7 @@ void main(void) { print_packet(p); type = get_packet_type((packet_t *) p); addr = 0; /* FIXME */ - free_packet(p); + maca_free_packet(p); /* pick a new address if someone else is using ours */ if(addr == my_addr) { my_addr = random_short_addr(); diff --git a/cpu/mc1322x/tests/rftest-rx.c b/cpu/mc1322x/tests/rftest-rx.c index 2f3d5cf71..a9e9062cf 100644 --- a/cpu/mc1322x/tests/rftest-rx.c +++ b/cpu/mc1322x/tests/rftest-rx.c @@ -87,7 +87,7 @@ void main(void) { /* print and free the packet */ printf("rftest-rx --- "); print_packet(p); - free_packet(p); + maca_free_packet(p); } if(uart1_can_get()) { diff --git a/cpu/mc1322x/tests/rftest-tx.c b/cpu/mc1322x/tests/rftest-tx.c index 4ac413902..25cd3a254 100644 --- a/cpu/mc1322x/tests/rftest-tx.c +++ b/cpu/mc1322x/tests/rftest-tx.c @@ -94,7 +94,7 @@ void main(void) { check_maca(); while((p = rx_packet())) { - if(p) free_packet(p); + if(p) maca_free_packet(p); } p = get_free_packet(); diff --git a/dev/cc2420/cc2420-aes.c b/dev/cc2420/cc2420-aes.c deleted file mode 100644 index 3f0ad199c..000000000 --- a/dev/cc2420/cc2420-aes.c +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (c) 2008, Swedish Institute of Computer Science. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This file is part of the Contiki operating system. - * - */ - -/** - * \file - * AES encryption functions. - * \author - * Adam Dunkels - */ - -#include "contiki.h" -#include "cc2420.h" -#include "cc2420-aes.h" -#include "dev/spi.h" - -#define KEYLEN 16 -#define MAX_DATALEN 16 - -#define CC2420_WRITE_RAM_REV(buffer,adr,count) \ - do { \ - uint8_t i; \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE_FAST(0x80 | (adr & 0x7f)); \ - SPI_WRITE_FAST((adr >> 1) & 0xc0); \ - for(i = (count); i > 0; i--) { \ - SPI_WRITE_FAST(((uint8_t*)(buffer))[i - 1]); \ - } \ - SPI_WAITFORTx_ENDED(); \ - CC2420_SPI_DISABLE(); \ - } while(0) - -#define MIN(a,b) ((a) < (b)? (a): (b)) - -/*---------------------------------------------------------------------------*/ -void -cc2420_aes_set_key(const uint8_t *key, int index) -{ - switch(index) { - case 0: - CC2420_WRITE_RAM_REV(key, CC2420RAM_KEY0, KEYLEN); - break; - case 1: - CC2420_WRITE_RAM_REV(key, CC2420RAM_KEY1, KEYLEN); - break; - } -} -/*---------------------------------------------------------------------------*/ -/* Encrypt at most 16 bytes of data. */ -static void -cipher16(uint8_t *data, int len) -{ - uint8_t status; - - len = MIN(len, MAX_DATALEN); - - CC2420_WRITE_RAM(data, CC2420RAM_SABUF, len); - CC2420_STROBE(CC2420_SAES); - /* Wait for the encryption to finish */ - do { - CC2420_GET_STATUS(status); - } while(status & BV(CC2420_ENC_BUSY)); - CC2420_READ_RAM(data, CC2420RAM_SABUF, len); -} -/*---------------------------------------------------------------------------*/ -void -cc2420_aes_cipher(uint8_t *data, int len, int key_index) -{ - int i; - uint16_t secctrl0; - - CC2420_READ_REG(CC2420_SECCTRL0, secctrl0); - - secctrl0 &= ~(CC2420_SECCTRL0_SAKEYSEL0 | CC2420_SECCTRL0_SAKEYSEL1); - - switch(key_index) { - case 0: - secctrl0 |= CC2420_SECCTRL0_SAKEYSEL0; - break; - case 1: - secctrl0 |= CC2420_SECCTRL0_SAKEYSEL1; - break; - } - CC2420_WRITE_REG(CC2420_SECCTRL0, secctrl0); - - for(i = 0; i < len; i = i + MAX_DATALEN) { - cipher16(data + i, MIN(len - i, MAX_DATALEN)); - } -} -/*---------------------------------------------------------------------------*/ diff --git a/dev/cc2420/cc2420.c b/dev/cc2420/cc2420.c index 6662eb1f1..1e0ce8c75 100644 --- a/dev/cc2420/cc2420.c +++ b/dev/cc2420/cc2420.c @@ -52,12 +52,6 @@ #define WITH_SEND_CCA 1 -#define FOOTER_LEN 2 - -#ifndef CC2420_CONF_CHECKSUM -#define CC2420_CONF_CHECKSUM 0 -#endif /* CC2420_CONF_CHECKSUM */ - #ifndef CC2420_CONF_CHANNEL #define CC2420_CONF_CHANNEL 26 #endif /* CC2420_CONF_CHANNEL */ @@ -66,26 +60,28 @@ #define CC2420_CONF_CCA_THRESH -45 #endif /* CC2420_CONF_CCA_THRESH */ - #ifndef CC2420_CONF_AUTOACK #define CC2420_CONF_AUTOACK 0 #endif /* CC2420_CONF_AUTOACK */ -#if CC2420_CONF_CHECKSUM -#include "lib/crc16.h" -#define CHECKSUM_LEN 2 -#else -#define CHECKSUM_LEN 0 -#endif /* CC2420_CONF_CHECKSUM */ - -#define AUX_LEN (CHECKSUM_LEN + FOOTER_LEN) - - +#define CHECKSUM_LEN 2 +#define FOOTER_LEN 2 #define FOOTER1_CRC_OK 0x80 #define FOOTER1_CORRELATION 0x7f +#ifdef CC2420_CONF_RSSI_OFFSET +#define RSSI_OFFSET CC2420_CONF_RSSI_OFFSET +#else /* CC2420_CONF_RSSI_OFFSET */ /* The RSSI_OFFSET is approximate -45 (see CC2420 specification) */ #define RSSI_OFFSET -45 +#endif /* CC2420_CONF_RSSI_OFFSET */ + +enum write_ram_order { + /* Begin with writing the first given byte */ + WRITE_RAM_IN_ORDER, + /* Begin with writing the last given byte */ + WRITE_RAM_REVERSE +}; #define DEBUG 0 #if DEBUG @@ -135,17 +131,6 @@ rtimer_clock_t cc2420_time_of_arrival, cc2420_time_of_departure; int cc2420_authority_level_of_sender; -int cc2420_packets_seen, cc2420_packets_read; - -/* static uint8_t volatile pending; */ - -#define BUSYWAIT_UNTIL(cond, max_time) \ - do { \ - rtimer_clock_t t0; \ - t0 = RTIMER_NOW(); \ - while(!(cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (max_time))); \ - } while(0) - volatile uint8_t cc2420_sfd_counter; volatile uint16_t cc2420_sfd_start_time; volatile uint16_t cc2420_sfd_end_time; @@ -168,7 +153,6 @@ static int cc2420_send(const void *data, unsigned short len); static int cc2420_receiving_packet(void); static int pending_packet(void); static int cc2420_cca(void); -/*static int detected_energy(void);*/ signed char cc2420_last_rssi; uint8_t cc2420_last_correlation; @@ -204,7 +188,7 @@ get_value(radio_param_t param, radio_value_t *value) return RADIO_RESULT_OK; case RADIO_PARAM_RSSI: /* Return the RSSI value in dBm */ - *value = cc2420_rssi() + RSSI_OFFSET; + *value = cc2420_rssi(); return RADIO_RESULT_OK; case RADIO_CONST_CHANNEL_MIN: *value = 11; @@ -281,8 +265,6 @@ const struct radio_driver cc2420_driver = cc2420_transmit, cc2420_send, cc2420_read, - /* cc2420_set_channel, */ - /* detected_energy, */ cc2420_cca, cc2420_receiving_packet, pending_packet, @@ -295,29 +277,141 @@ const struct radio_driver cc2420_driver = }; /*---------------------------------------------------------------------------*/ +/* Sends a strobe */ static void strobe(enum cc2420_register regname) { - CC2420_STROBE(regname); + CC2420_SPI_ENABLE(); + SPI_WRITE(regname); + CC2420_SPI_DISABLE(); } /*---------------------------------------------------------------------------*/ - -static void -getrxdata(void *buf, int len) +/* Reads a register */ +static uint16_t +getreg(enum cc2420_register regname) { - CC2420_READ_FIFO_BUF(buf, len); + uint16_t value; + + CC2420_SPI_ENABLE(); + SPI_WRITE(regname | 0x40); + value = (uint8_t)SPI_RXBUF; + SPI_TXBUF = 0; + SPI_WAITFOREORx(); + value = SPI_RXBUF << 8; + SPI_TXBUF = 0; + SPI_WAITFOREORx(); + value |= SPI_RXBUF; + CC2420_SPI_DISABLE(); + + return value; } +/*---------------------------------------------------------------------------*/ +/** + * Writes to a register. + * Note: the SPI_WRITE(0) seems to be needed for getting the + * write reg working on the Z1 / MSP430X platform + */ static void -getrxbyte(uint8_t *byte) +setreg(enum cc2420_register regname, uint16_t value) { - CC2420_READ_FIFO_BYTE(*byte); + CC2420_SPI_ENABLE(); + SPI_WRITE_FAST(regname); + SPI_WRITE_FAST((uint8_t) (value >> 8)); + SPI_WRITE_FAST((uint8_t) (value & 0xff)); + SPI_WAITFORTx_ENDED(); + SPI_WRITE(0); + CC2420_SPI_DISABLE(); } +/*---------------------------------------------------------------------------*/ +static void +read_ram(uint8_t *buffer, uint16_t adr, uint16_t count) +{ + uint8_t i; + + CC2420_SPI_ENABLE(); + SPI_WRITE(0x80 | ((adr) & 0x7f)); + SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20); + SPI_RXBUF; + for(i = 0; i < count; i++) { + SPI_READ(((uint8_t*) buffer)[i]); + } + CC2420_SPI_DISABLE(); +} +/*---------------------------------------------------------------------------*/ +/* Write to RAM in the CC2420 */ +static void +write_ram(const uint8_t *buffer, + uint16_t adr, + uint16_t count, + enum write_ram_order order) +{ + uint8_t i; + + CC2420_SPI_ENABLE(); + SPI_WRITE_FAST(0x80 | (adr & 0x7f)); + SPI_WRITE_FAST((adr >> 1) & 0xc0); + if(order == WRITE_RAM_IN_ORDER) { + for(i = 0; i < count; i++) { + SPI_WRITE_FAST((buffer)[i]); + } + } else { + for(i = count; i > 0; i--) { + SPI_WRITE_FAST((buffer)[i - 1]); + } + } + SPI_WAITFORTx_ENDED(); + CC2420_SPI_DISABLE(); +} +/*---------------------------------------------------------------------------*/ +static void +write_fifo_buf(const uint8_t *buffer, uint16_t count) +{ + uint8_t i; + + CC2420_SPI_ENABLE(); + SPI_WRITE_FAST(CC2420_TXFIFO); + for(i = 0; i < count; i++) { + SPI_WRITE_FAST((buffer)[i]); + } + SPI_WAITFORTx_ENDED(); + CC2420_SPI_DISABLE(); +} +/*---------------------------------------------------------------------------*/ +/* Returns the current status */ +static uint8_t +get_status(void) +{ + uint8_t status; + + CC2420_SPI_ENABLE(); + SPI_WRITE(CC2420_SNOP); + status = SPI_RXBUF; + CC2420_SPI_DISABLE(); + + return status; +} +/*---------------------------------------------------------------------------*/ +static void +getrxdata(uint8_t *buffer, int count) +{ + uint8_t i; + + CC2420_SPI_ENABLE(); + SPI_WRITE(CC2420_RXFIFO | 0x40); + (void) SPI_RXBUF; + for(i = 0; i < count; i++) { + SPI_READ(buffer[i]); + } + clock_delay(1); + CC2420_SPI_DISABLE(); +} +/*---------------------------------------------------------------------------*/ static void flushrx(void) { uint8_t dummy; - getrxbyte(&dummy); + getrxdata(&dummy, 1); strobe(CC2420_SFLUSHRX); strobe(CC2420_SFLUSHRX); if(dummy) { @@ -325,39 +419,34 @@ flushrx(void) } } /*---------------------------------------------------------------------------*/ -static unsigned int -status(void) +static void +wait_for_status(uint8_t status_bit) { - uint8_t status; - CC2420_GET_STATUS(status); - return status; + rtimer_clock_t t0; + t0 = RTIMER_NOW(); + while(!(get_status() & status_bit) + && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 10))); } /*---------------------------------------------------------------------------*/ static void -wait_for_status(unsigned int mask) +wait_for_transmission(void) { - BUSYWAIT_UNTIL((status() & mask), RTIMER_SECOND / 10); + rtimer_clock_t t0; + t0 = RTIMER_NOW(); + while((get_status() & BV(CC2420_TX_ACTIVE)) + && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 10))); } /*---------------------------------------------------------------------------*/ -static void -wait_for_not_status(unsigned int mask) -{ - BUSYWAIT_UNTIL(!(status() & mask), RTIMER_SECOND / 10); -} -/*---------------------------------------------------------------------------*/ -static uint8_t locked, lock_on, lock_off; - static void on(void) { CC2420_ENABLE_FIFOP_INT(); strobe(CC2420_SRXON); - wait_for_status(BV(CC2420_XOSC16M_STABLE)); - ENERGEST_ON(ENERGEST_TYPE_LISTEN); receive_on = 1; } +/*---------------------------------------------------------------------------*/ static void off(void) { @@ -365,7 +454,7 @@ off(void) receive_on = 0; /* Wait for transmission to end before turning radio off. */ - wait_for_not_status(BV(CC2420_TX_ACTIVE)); + wait_for_transmission(); ENERGEST_OFF(ENERGEST_TYPE_LISTEN); strobe(CC2420_SRFOFF); @@ -376,6 +465,7 @@ off(void) } } /*---------------------------------------------------------------------------*/ +static uint8_t locked, lock_on, lock_off; #define GET_LOCK() locked++ static void RELEASE_LOCK(void) { if(locked == 1) { @@ -391,26 +481,47 @@ static void RELEASE_LOCK(void) { locked--; } /*---------------------------------------------------------------------------*/ -static unsigned -getreg(enum cc2420_register regname) +static void +init_security(void) { - unsigned reg; - CC2420_READ_REG(regname, reg); - return reg; + /* only use key 0 */ + setreg(CC2420_SECCTRL0, 0); + setreg(CC2420_SECCTRL1, 0); } /*---------------------------------------------------------------------------*/ static void -setreg(enum cc2420_register regname, unsigned value) +set_key(uint8_t *key) { - CC2420_WRITE_REG(regname, value); + GET_LOCK(); + + write_ram(key, CC2420RAM_KEY0, 16, WRITE_RAM_REVERSE); + + RELEASE_LOCK(); } /*---------------------------------------------------------------------------*/ static void -write_ram(const void *buf, uint16_t addr, int count) +encrypt(uint8_t *plaintext_and_result) { - CC2420_WRITE_RAM(buf, addr, count); + GET_LOCK(); + + write_ram(plaintext_and_result, + CC2420RAM_SABUF, + 16, + WRITE_RAM_IN_ORDER); + + strobe(CC2420_SAES); + while(get_status() & BV(CC2420_ENC_BUSY)); + + read_ram(plaintext_and_result, CC2420RAM_SABUF, 16); + + RELEASE_LOCK(); } /*---------------------------------------------------------------------------*/ +const struct aes_128_driver cc2420_aes_128_driver = { + set_key, + encrypt +}; +/*---------------------------------------------------------------------------*/ static void set_txpower(uint8_t power) { @@ -422,6 +533,7 @@ set_txpower(uint8_t power) } /*---------------------------------------------------------------------------*/ #define AUTOACK (1 << 4) +#define AUTOCRC (1 << 5) #define ADR_DECODE (1 << 11) #define RXFIFO_PROTECTION (1 << 9) #define CORR_THR(n) (((n) & 0x1f) << 6) @@ -451,6 +563,8 @@ cc2420_init(void) /* Turn on the crystal oscillator. */ strobe(CC2420_SXOSCON); + /* And wait until it stabilizes */ + wait_for_status(BV(CC2420_XOSC16M_STABLE)); /* Turn on/off automatic packet acknowledgment and address decoding. */ reg = getreg(CC2420_MDMCTRL0); @@ -460,6 +574,12 @@ cc2420_init(void) #else reg &= ~(AUTOACK | ADR_DECODE); #endif /* CC2420_CONF_AUTOACK */ + + /* Enabling CRC in hardware; this is required by AUTOACK anyway + and provides us with RSSI and link quality indication (LQI) + information. */ + reg |= AUTOCRC; + setreg(CC2420_MDMCTRL0, reg); /* Set transmission turnaround time to the lower setting (8 symbols @@ -479,10 +599,7 @@ cc2420_init(void) /* Set the FIFOP threshold to maximum. */ setreg(CC2420_IOCFG0, FIFOP_THR(127)); - /* Turn off "Security enable" (page 32). */ - reg = getreg(CC2420_SECCTRL0); - reg &= ~RXFIFO_PROTECTION; - setreg(CC2420_SECCTRL0, reg); + init_security(); cc2420_set_pan_addr(0xffff, 0x0000, NULL); cc2420_set_channel(CC2420_CONF_CHANNEL); @@ -498,10 +615,7 @@ static int cc2420_transmit(unsigned short payload_len) { int i, txpower; -#if CC2420_CONF_CHECKSUM - uint16_t checksum; -#endif /* CC2420_CONF_CHECKSUM */ - + GET_LOCK(); txpower = 0; @@ -540,11 +654,11 @@ cc2420_transmit(unsigned short payload_len) if(packetbuf_attr(PACKETBUF_ATTR_PACKET_TYPE) == PACKETBUF_ATTR_PACKET_TYPE_TIMESTAMP) { /* Write timestamp to last two bytes of packet in TXFIFO. */ - write_ram(&sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2); + write_ram((uint8_t *) &sfd_timestamp, CC2420RAM_TXFIFO + payload_len - 1, 2, WRITE_RAM_IN_ORDER); } } - if(!(status() & BV(CC2420_TX_ACTIVE))) { + if(!(get_status() & BV(CC2420_TX_ACTIVE))) { /* SFD went high but we are not transmitting. This means that we just started receiving a packet, so we drop the transmission. */ @@ -557,7 +671,7 @@ cc2420_transmit(unsigned short payload_len) ENERGEST_ON(ENERGEST_TYPE_TRANSMIT); /* We wait until transmission has ended so that we get an accurate measurement of the transmission time.*/ - wait_for_not_status(BV(CC2420_TX_ACTIVE)); + wait_for_transmission(); #ifdef ENERGEST_CONF_LEVELDEVICE_LEVELS ENERGEST_OFF_LEVEL(ENERGEST_TYPE_TRANSMIT,cc2420_get_txpower()); @@ -599,9 +713,7 @@ static int cc2420_prepare(const void *payload, unsigned short payload_len) { uint8_t total_len; -#if CC2420_CONF_CHECKSUM - uint16_t checksum; -#endif /* CC2420_CONF_CHECKSUM */ + GET_LOCK(); PRINTF("cc2420: sending %d bytes\n", payload_len); @@ -614,16 +726,10 @@ cc2420_prepare(const void *payload, unsigned short payload_len) /* Write packet to TX FIFO. */ strobe(CC2420_SFLUSHTX); -#if CC2420_CONF_CHECKSUM - checksum = crc16_data(payload, payload_len, 0); -#endif /* CC2420_CONF_CHECKSUM */ - total_len = payload_len + AUX_LEN; - CC2420_WRITE_FIFO_BUF(&total_len, 1); - CC2420_WRITE_FIFO_BUF(payload, payload_len); -#if CC2420_CONF_CHECKSUM - CC2420_WRITE_FIFO_BUF(&checksum, CHECKSUM_LEN); -#endif /* CC2420_CONF_CHECKSUM */ - + total_len = payload_len + CHECKSUM_LEN; + write_fifo_buf(&total_len, 1); + write_fifo_buf(payload, payload_len); + RELEASE_LOCK(); return 0; } @@ -656,7 +762,7 @@ cc2420_off(void) we don't actually switch the radio off now, but signal that the driver should switch off the radio once the packet has been received and processed, by setting the 'lock_off' variable. */ - if(status() & BV(CC2420_TX_ACTIVE)) { + if(get_status() & BV(CC2420_TX_ACTIVE)) { lock_off = 1; } else { off(); @@ -701,13 +807,9 @@ cc2420_set_channel(int c) channel = c; f = 5 * (c - 11) + 357 + 0x4000; - /* - * Writing RAM requires crystal oscillator to be stable. - */ - wait_for_status(BV(CC2420_XOSC16M_STABLE)); - + /* Wait for any transmission to end. */ - wait_for_not_status(BV(CC2420_TX_ACTIVE)); + wait_for_transmission(); setreg(CC2420_FSCTRL, f); @@ -726,30 +828,13 @@ cc2420_set_pan_addr(unsigned pan, unsigned addr, const uint8_t *ieee_addr) { - uint16_t f = 0; - uint8_t tmp[2]; - GET_LOCK(); - /* - * Writing RAM requires crystal oscillator to be stable. - */ - wait_for_status(BV(CC2420_XOSC16M_STABLE)); - - tmp[0] = pan & 0xff; - tmp[1] = pan >> 8; - write_ram(&tmp, CC2420RAM_PANID, 2); - - tmp[0] = addr & 0xff; - tmp[1] = addr >> 8; - write_ram(&tmp, CC2420RAM_SHORTADDR, 2); + write_ram((uint8_t *) &pan, CC2420RAM_PANID, 2, WRITE_RAM_IN_ORDER); + write_ram((uint8_t *) &addr, CC2420RAM_SHORTADDR, 2, WRITE_RAM_IN_ORDER); + if(ieee_addr != NULL) { - uint8_t tmp_addr[8]; - /* LSB first, MSB last for 802.15.4 addresses in CC2420 */ - for (f = 0; f < 8; f++) { - tmp_addr[7 - f] = ieee_addr[f]; - } - write_ram(tmp_addr, CC2420RAM_IEEEADDR, 8); + write_ram(ieee_addr, CC2420RAM_IEEEADDR, 8, WRITE_RAM_REVERSE); } RELEASE_LOCK(); } @@ -764,8 +849,6 @@ cc2420_interrupt(void) process_poll(&cc2420_process); last_packet_timestamp = cc2420_sfd_start_time; - /* pending++; */ - cc2420_packets_seen++; return 1; } /*---------------------------------------------------------------------------*/ @@ -796,99 +879,60 @@ PROCESS_THREAD(cc2420_process, ev, data) static int cc2420_read(void *buf, unsigned short bufsize) { - uint8_t footer[2]; + uint8_t footer[FOOTER_LEN]; uint8_t len; -#if CC2420_CONF_CHECKSUM - uint16_t checksum; -#endif /* CC2420_CONF_CHECKSUM */ if(!CC2420_FIFOP_IS_1) { return 0; } - /* if(!pending) { - return 0; - }*/ - - /* pending = 0; */ GET_LOCK(); - cc2420_packets_read++; - - getrxbyte(&len); + getrxdata(&len, 1); if(len > CC2420_MAX_PACKET_LEN) { /* Oops, we must be out of sync. */ - flushrx(); RIMESTATS_ADD(badsynch); - RELEASE_LOCK(); - return 0; - } - - if(len <= AUX_LEN) { - flushrx(); + } else if(len <= FOOTER_LEN) { RIMESTATS_ADD(tooshort); - RELEASE_LOCK(); - return 0; - } - - if(len - AUX_LEN > bufsize) { - flushrx(); + } else if(len - FOOTER_LEN > bufsize) { RIMESTATS_ADD(toolong); - RELEASE_LOCK(); - return 0; - } - - getrxdata(buf, len - AUX_LEN); -#if CC2420_CONF_CHECKSUM - getrxdata(&checksum, CHECKSUM_LEN); -#endif /* CC2420_CONF_CHECKSUM */ - getrxdata(footer, FOOTER_LEN); - -#if CC2420_CONF_CHECKSUM - if(checksum != crc16_data(buf, len - AUX_LEN, 0)) { - PRINTF("checksum failed 0x%04x != 0x%04x\n", - checksum, crc16_data(buf, len - AUX_LEN, 0)); - } - - if(footer[1] & FOOTER1_CRC_OK && - checksum == crc16_data(buf, len - AUX_LEN, 0)) { -#else - if(footer[1] & FOOTER1_CRC_OK) { -#endif /* CC2420_CONF_CHECKSUM */ - cc2420_last_rssi = footer[0]; - cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; - - - packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi); - packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation); - - RIMESTATS_ADD(llrx); - } else { - RIMESTATS_ADD(badcrc); - len = AUX_LEN; - } - - if(CC2420_FIFOP_IS_1) { - if(!CC2420_FIFO_IS_1) { - /* Clean up in case of FIFO overflow! This happens for every - * full length frame and is signaled by FIFOP = 1 and FIFO = - * 0. */ - flushrx(); + getrxdata((uint8_t *) buf, len - FOOTER_LEN); + getrxdata(footer, FOOTER_LEN); + + if(footer[1] & FOOTER1_CRC_OK) { + cc2420_last_rssi = footer[0] + RSSI_OFFSET; + cc2420_last_correlation = footer[1] & FOOTER1_CORRELATION; + + packetbuf_set_attr(PACKETBUF_ATTR_RSSI, cc2420_last_rssi); + packetbuf_set_attr(PACKETBUF_ATTR_LINK_QUALITY, cc2420_last_correlation); + + RIMESTATS_ADD(llrx); } else { - /* Another packet has been received and needs attention. */ - process_poll(&cc2420_process); + RIMESTATS_ADD(badcrc); + len = FOOTER_LEN; } + + if(CC2420_FIFOP_IS_1) { + if(!CC2420_FIFO_IS_1) { + /* Clean up in case of FIFO overflow! This happens for every + * full length frame and is signaled by FIFOP = 1 and FIFO = + * 0. */ + flushrx(); + } else { + /* Another packet has been received and needs attention. */ + process_poll(&cc2420_process); + } + } + + RELEASE_LOCK(); + return len - FOOTER_LEN; } - + + flushrx(); RELEASE_LOCK(); - - if(len < AUX_LEN) { - return 0; - } - - return len - AUX_LEN; + return 0; } /*---------------------------------------------------------------------------*/ void @@ -927,7 +971,8 @@ cc2420_rssi(void) } wait_for_status(BV(CC2420_RSSI_VALID)); - rssi = (int)((signed char)getreg(CC2420_RSSI)); + rssi = (int)((signed char) getreg(CC2420_RSSI)); + rssi += RSSI_OFFSET; if(radio_was_off) { cc2420_off(); @@ -936,14 +981,6 @@ cc2420_rssi(void) return rssi; } /*---------------------------------------------------------------------------*/ -/* -static int -detected_energy(void) -{ - return cc2420_rssi(); -} -*/ -/*---------------------------------------------------------------------------*/ static int cc2420_cca(void) { diff --git a/dev/cc2420/cc2420.h b/dev/cc2420/cc2420.h index 0aaacae27..985fc4213 100644 --- a/dev/cc2420/cc2420.h +++ b/dev/cc2420/cc2420.h @@ -36,6 +36,7 @@ * \author * Adam Dunkels * Joakim Eriksson + * Konrad Krentz */ #ifndef CC2420_H_ @@ -45,6 +46,7 @@ #include "dev/spi.h" #include "dev/radio.h" #include "cc2420_const.h" +#include "lib/aes-128.h" int cc2420_init(void); @@ -88,116 +90,6 @@ int cc2420_off(void); void cc2420_set_cca_threshold(int value); -/************************************************************************/ -/* Additional SPI Macros for the CC2420 */ -/************************************************************************/ -/* Send a strobe to the CC2420 */ -#define CC2420_STROBE(s) \ - do { \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE(s); \ - CC2420_SPI_DISABLE(); \ - } while (0) - -/* Write to a register in the CC2420 */ -/* Note: the SPI_WRITE(0) seems to be needed for getting the */ -/* write reg working on the Z1 / MSP430X platform */ -#define CC2420_WRITE_REG(adr,data) \ - do { \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE_FAST(adr); \ - SPI_WRITE_FAST((uint8_t)((data) >> 8)); \ - SPI_WRITE_FAST((uint8_t)(data & 0xff)); \ - SPI_WAITFORTx_ENDED(); \ - SPI_WRITE(0); \ - CC2420_SPI_DISABLE(); \ - } while(0) - -/* Read a register in the CC2420 */ -#define CC2420_READ_REG(adr,data) \ - do { \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE(adr | 0x40); \ - data = (uint8_t)SPI_RXBUF; \ - SPI_TXBUF = 0; \ - SPI_WAITFOREORx(); \ - data = SPI_RXBUF << 8; \ - SPI_TXBUF = 0; \ - SPI_WAITFOREORx(); \ - data |= SPI_RXBUF; \ - CC2420_SPI_DISABLE(); \ - } while(0) - -#define CC2420_READ_FIFO_BYTE(data) \ - do { \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE(CC2420_RXFIFO | 0x40); \ - (void)SPI_RXBUF; \ - SPI_READ(data); \ - clock_delay(1); \ - CC2420_SPI_DISABLE(); \ - } while(0) - -#define CC2420_READ_FIFO_BUF(buffer,count) \ - do { \ - uint8_t i; \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE(CC2420_RXFIFO | 0x40); \ - (void)SPI_RXBUF; \ - for(i = 0; i < (count); i++) { \ - SPI_READ(((uint8_t *)(buffer))[i]); \ - } \ - clock_delay(1); \ - CC2420_SPI_DISABLE(); \ - } while(0) - -#define CC2420_WRITE_FIFO_BUF(buffer,count) \ - do { \ - uint8_t i; \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE_FAST(CC2420_TXFIFO); \ - for(i = 0; i < (count); i++) { \ - SPI_WRITE_FAST(((uint8_t *)(buffer))[i]); \ - } \ - SPI_WAITFORTx_ENDED(); \ - CC2420_SPI_DISABLE(); \ - } while(0) - -/* Write to RAM in the CC2420 */ -#define CC2420_WRITE_RAM(buffer,adr,count) \ - do { \ - uint8_t i; \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE_FAST(0x80 | ((adr) & 0x7f)); \ - SPI_WRITE_FAST(((adr) >> 1) & 0xc0); \ - for(i = 0; i < (count); i++) { \ - SPI_WRITE_FAST(((uint8_t*)(buffer))[i]); \ - } \ - SPI_WAITFORTx_ENDED(); \ - CC2420_SPI_DISABLE(); \ - } while(0) - -/* Read from RAM in the CC2420 */ -#define CC2420_READ_RAM(buffer,adr,count) \ - do { \ - uint8_t i; \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE(0x80 | ((adr) & 0x7f)); \ - SPI_WRITE((((adr) >> 1) & 0xc0) | 0x20); \ - SPI_RXBUF; \ - for(i = 0; i < (count); i++) { \ - SPI_READ(((uint8_t*)(buffer))[i]); \ - } \ - CC2420_SPI_DISABLE(); \ - } while(0) - -/* Read status of the CC2420 */ -#define CC2420_GET_STATUS(s) \ - do { \ - CC2420_SPI_ENABLE(); \ - SPI_WRITE(CC2420_SNOP); \ - s = SPI_RXBUF; \ - CC2420_SPI_DISABLE(); \ - } while (0) +extern const struct aes_128_driver cc2420_aes_128_driver; #endif /* CC2420_H_ */ diff --git a/examples/ipv6/slip-radio/no-framer.c b/examples/ipv6/slip-radio/no-framer.c index b6ca7d06a..e3aed93b7 100644 --- a/examples/ipv6/slip-radio/no-framer.c +++ b/examples/ipv6/slip-radio/no-framer.c @@ -123,5 +123,8 @@ parse(void) } /*---------------------------------------------------------------------------*/ const struct framer no_framer = { - hdr_length, create, parse + hdr_length, + create, + framer_canonical_create_and_secure, + parse }; diff --git a/examples/ipv6/slip-radio/slip-radio.c b/examples/ipv6/slip-radio/slip-radio.c index 5223d57a6..255cfefb5 100644 --- a/examples/ipv6/slip-radio/slip-radio.c +++ b/examples/ipv6/slip-radio/slip-radio.c @@ -125,7 +125,7 @@ slip_radio_cmd_handler(const uint8_t *data, int len) /* parse frame before sending to get addresses, etc. */ no_framer.parse(); - NETSTACK_MAC.send(packet_sent, &packet_ids[packet_pos]); + NETSTACK_LLSEC.send(packet_sent, &packet_ids[packet_pos]); packet_pos++; if(packet_pos >= sizeof(packet_ids)) { diff --git a/examples/llsec/ccm-tests/encryption/Makefile b/examples/llsec/ccm-tests/encryption/Makefile new file mode 100644 index 000000000..0fd359f16 --- /dev/null +++ b/examples/llsec/ccm-tests/encryption/Makefile @@ -0,0 +1,14 @@ +CONTIKI_PROJECT = tests +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +WITH_UIP6=1 +UIP_CONF_IPV6=1 +CFLAGS+= -DUIP_CONF_IPV6_RPL + +#linker optimizations +SMALL=1 + +include $(CONTIKI)/Makefile.include diff --git a/examples/llsec/ccm-tests/encryption/project-conf.h b/examples/llsec/ccm-tests/encryption/project-conf.h new file mode 100644 index 000000000..613619373 --- /dev/null +++ b/examples/llsec/ccm-tests/encryption/project-conf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Testing CTR + * \author + * Konrad Krentz + */ + +#define LLSEC802154_CONF_SECURITY_LEVEL 6 diff --git a/examples/llsec/ccm-tests/encryption/tests.c b/examples/llsec/ccm-tests/encryption/tests.c new file mode 100644 index 000000000..6c9ca295f --- /dev/null +++ b/examples/llsec/ccm-tests/encryption/tests.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Testing CTR + * \author + * Konrad Krentz + */ + +#include "contiki.h" +#include "net/packetbuf.h" +#include "net/netstack.h" +#include "net/llsec/llsec802154.h" +#include "net/llsec/ccm.h" +#include "net/mac/frame802154.h" +#include "lib/aes-128.h" +#include +#include + +/*---------------------------------------------------------------------------*/ +/* Test vector C.2.1.2 from IEEE 802.15.4-2006 */ +static void +test_sec_lvl_6() +{ + uint8_t key[16] = { 0xC0 , 0xC1 , 0xC2 , 0xC3 , + 0xC4 , 0xC5 , 0xC6 , 0xC7 , + 0xC8 , 0xC9 , 0xCA , 0xCB , + 0xCC , 0xCD , 0xCE , 0xCF }; + uint8_t extended_source_address[8] = { 0xAC , 0xDE , 0x48 , 0x00 , + 0x00 , 0x00 , 0x00 , 0x01 }; + uint8_t data[30] = { 0x2B , 0xDC , 0x84 , 0x21 , 0x43 , + /* Destination Address */ + 0x02 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC , + /* PAN-ID */ + 0xFF , 0xFF , + /* Source Address */ + 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC , + /* Security Level */ + 0x06 , + /* Frame Counter */ + 0x05 , 0x00 , 0x00 , 0x00 , + 0x01 , 0xCE }; + uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x4F , 0xDE , 0x52 , 0x90 , + 0x61 , 0xF9 , 0xC6 , 0xF1 }; + frame802154_frame_counter_t counter; + uint8_t mic[LLSEC802154_MIC_LENGTH]; + + printf("Testing verification ... "); + + packetbuf_clear(); + packetbuf_set_datalen(30); + memcpy(packetbuf_hdrptr(), data, 30); + counter.u32 = 5; + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]); + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); + packetbuf_hdrreduce(29); + + AES_128.set_key(key); + CCM.mic(extended_source_address, mic, LLSEC802154_MIC_LENGTH); + + if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) { + printf("Success\n"); + } else { + printf("Failure\n"); + } + + printf("Testing encryption ... "); + + CCM.ctr(extended_source_address); + if(((uint8_t *) packetbuf_hdrptr())[29] == 0xD8) { + printf("Success\n"); + } else { + printf("Failure\n"); + } + + printf("Testing decryption ... "); + CCM.ctr(extended_source_address); + if(((uint8_t *) packetbuf_hdrptr())[29] == 0xCE) { + printf("Success\n"); + } else { + printf("Failure\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS(ccm_encryption_tests_process, "CCM* encryption tests process"); +AUTOSTART_PROCESSES(&ccm_encryption_tests_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ccm_encryption_tests_process, ev, data) +{ + PROCESS_BEGIN(); + + test_sec_lvl_6(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/llsec/ccm-tests/verification/Makefile b/examples/llsec/ccm-tests/verification/Makefile new file mode 100644 index 000000000..0fd359f16 --- /dev/null +++ b/examples/llsec/ccm-tests/verification/Makefile @@ -0,0 +1,14 @@ +CONTIKI_PROJECT = tests +all: $(CONTIKI_PROJECT) + +CONTIKI = ../../../.. +CFLAGS += -DPROJECT_CONF_H=\"project-conf.h\" + +WITH_UIP6=1 +UIP_CONF_IPV6=1 +CFLAGS+= -DUIP_CONF_IPV6_RPL + +#linker optimizations +SMALL=1 + +include $(CONTIKI)/Makefile.include diff --git a/examples/llsec/ccm-tests/verification/project-conf.h b/examples/llsec/ccm-tests/verification/project-conf.h new file mode 100644 index 000000000..9f8776b90 --- /dev/null +++ b/examples/llsec/ccm-tests/verification/project-conf.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Testing CCM* MICs + * \author + * Konrad Krentz + */ + +#define LLSEC802154_CONF_SECURITY_LEVEL 2 diff --git a/examples/llsec/ccm-tests/verification/tests.c b/examples/llsec/ccm-tests/verification/tests.c new file mode 100644 index 000000000..2c9d6dbc9 --- /dev/null +++ b/examples/llsec/ccm-tests/verification/tests.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2013, Hasso-Plattner-Institut. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file is part of the Contiki operating system. + * + */ + +/** + * \file + * Testing CCM*-MICs + * \author + * Konrad Krentz + */ + +#include "contiki.h" +#include "net/packetbuf.h" +#include "net/netstack.h" +#include "net/llsec/llsec802154.h" +#include "net/llsec/ccm.h" +#include "net/mac/frame802154.h" +#include "lib/aes-128.h" +#include +#include + +/*---------------------------------------------------------------------------*/ +/* Test vector C.1 from FIPS Pub 197 */ +static void +test_aes_128() +{ + uint8_t key[16] = { 0x00 , 0x01 , 0x02 , 0x03 , + 0x04 , 0x05 , 0x06 , 0x07 , + 0x08 , 0x09 , 0x0A , 0x0B , + 0x0C , 0x0D , 0x0E , 0x0F }; + uint8_t data[16] = { 0x00 , 0x11 , 0x22 , 0x33 , + 0x44 , 0x55 , 0x66 , 0x77 , + 0x88 , 0x99 , 0xAA , 0xBB , + 0xCC , 0xDD , 0xEE , 0xFF }; + uint8_t oracle[16] = { 0x69 , 0xC4 , 0xE0 , 0xD8 , + 0x6A , 0x7B , 0x04 , 0x30 , + 0xD8 , 0xCD , 0xB7 , 0x80 , + 0x70 , 0xB4 , 0xC5 , 0x5A }; + + printf("Testing AES-128 ... "); + + AES_128.set_key(key); + AES_128.encrypt(data); + + if(memcmp(data, oracle, 16) == 0) { + printf("Success\n"); + } else { + printf("Failure\n"); + } +} +/*---------------------------------------------------------------------------*/ +/* Test vector C.2.1.2 from IEEE 802.15.4-2006 */ +static void +test_sec_lvl_2() +{ + uint8_t key[16] = { 0xC0 , 0xC1 , 0xC2 , 0xC3 , + 0xC4 , 0xC5 , 0xC6 , 0xC7 , + 0xC8 , 0xC9 , 0xCA , 0xCB , + 0xCC , 0xCD , 0xCE , 0xCF }; + uint8_t extended_source_address[8] = { 0xAC , 0xDE , 0x48 , 0x00 , + 0x00 , 0x00 , 0x00 , 0x01 }; + uint8_t data[26] = { 0x08 , 0xD0 , 0x84 , 0x21 , 0x43 , + /* Source Address */ + 0x01 , 0x00 , 0x00 , 0x00 , 0x00 , 0x48 , 0xDE , 0xAC , + /* Security Level*/ + 0x02 , + /* Frame Counter */ + 0x05 , 0x00 , 0x00 , 0x00 , + /* Payload */ + 0x55 , 0xCF , 0x00 , 0x00 , 0x51 , 0x52 , 0x53 , 0x54 }; + uint8_t oracle[LLSEC802154_MIC_LENGTH] = { 0x22 , 0x3B , 0xC1 , 0xEC , + 0x84 , 0x1A , 0xB5 , 0x53 }; + frame802154_frame_counter_t counter; + uint8_t mic[LLSEC802154_MIC_LENGTH]; + + printf("Testing verification ... "); + + packetbuf_clear(); + packetbuf_set_datalen(26); + memcpy(packetbuf_hdrptr(), data, 26); + counter.u32 = 5; + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, counter.u16[0]); + packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, counter.u16[1]); + packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, LLSEC802154_SECURITY_LEVEL); + packetbuf_hdrreduce(18); + + AES_128.set_key(key); + CCM.mic(extended_source_address, mic, LLSEC802154_MIC_LENGTH); + + if(memcmp(mic, oracle, LLSEC802154_MIC_LENGTH) == 0) { + printf("Success\n"); + } else { + printf("Failure\n"); + } +} +/*---------------------------------------------------------------------------*/ +PROCESS(ccm_verification_tests_process, "CCM* verification tests process"); +AUTOSTART_PROCESSES(&ccm_verification_tests_process); +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(ccm_verification_tests_process, ev, data) +{ + PROCESS_BEGIN(); + + test_aes_128(); + test_sec_lvl_2(); + + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ diff --git a/examples/ravenusbstick/Makefile.ravenusbstick b/examples/ravenusbstick/Makefile.ravenusbstick index 9f8bc1ef0..f1237125f 100644 --- a/examples/ravenusbstick/Makefile.ravenusbstick +++ b/examples/ravenusbstick/Makefile.ravenusbstick @@ -10,7 +10,7 @@ CFLAGS=-DUIP_CONF_IPV6=0 -DUIP_CONF_IPV6_RPL=0 CONTIKI = ../.. -MODULES+=core/net/mac/sicslowmac core/net/mac +MODULES+=core/net/mac/sicslowmac core/net/mac core/net/llsec PROJECT_SOURCEFILES += fakeuip.c diff --git a/platform/avr-atmega128rfa1/contiki-conf.h b/platform/avr-atmega128rfa1/contiki-conf.h index e8324b1a4..bb08df5a3 100644 --- a/platform/avr-atmega128rfa1/contiki-conf.h +++ b/platform/avr-atmega128rfa1/contiki-conf.h @@ -237,10 +237,8 @@ typedef unsigned short uip_stats_t; #define NETSTACK_CONF_RDC contikimac_driver /* Default is two CCA separated by 500 usec */ #define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 -/* Wireshark won't decode with the header, but padded packets will fail ipv6 checksum */ -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 /* So without the header this needed for RPL mesh to form */ -#define CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length +#define CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length /* Not tested much yet */ #define WITH_PHASE_OPTIMIZATION 0 #define CONTIKIMAC_CONF_COMPOWER 1 diff --git a/platform/avr-raven/Makefile.avr-raven b/platform/avr-raven/Makefile.avr-raven index d13307c0b..465e4e7ac 100644 --- a/platform/avr-raven/Makefile.avr-raven +++ b/platform/avr-raven/Makefile.avr-raven @@ -35,4 +35,5 @@ AVRDUDE_MCU=m1284p include $(CONTIKIAVR)/Makefile.avr include $(CONTIKIAVR)/radio/Makefile.radio -MODULES += core/net/ipv6 core/net/ipv4 core/net/ip core/net/mac core/net core/net/rime core/net/mac/sicslowmac +MODULES += core/net/ipv6 core/net/ipv4 core/net/ip core/net/mac core/net core/net/rime core/net/mac/sicslowmac \ + core/net/llsec diff --git a/platform/avr-raven/contiki-conf.h b/platform/avr-raven/contiki-conf.h index cff7988d7..c6ef38eba 100644 --- a/platform/avr-raven/contiki-conf.h +++ b/platform/avr-raven/contiki-conf.h @@ -253,10 +253,8 @@ typedef unsigned short uip_stats_t; #define NETSTACK_CONF_RDC contikimac_driver /* Default is two CCA separated by 500 usec */ #define NETSTACK_CONF_RDC_CHANNEL_CHECK_RATE 8 -/* Wireshark won't decode with the header, but padded packets will fail ipv6 checksum */ -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 /* So without the header this needed for RPL mesh to form */ -#define CONTIKIMAC_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length +#define CONTIKIMAC_FRAMER_CONF_SHORTEST_PACKET_SIZE 43-18 //multicast RPL DIS length /* Not tested much yet */ #define WITH_PHASE_OPTIMIZATION 0 #define CONTIKIMAC_CONF_COMPOWER 1 diff --git a/platform/avr-ravenusb/Makefile.avr-ravenusb b/platform/avr-ravenusb/Makefile.avr-ravenusb index 977b8e26d..8777e1b97 100644 --- a/platform/avr-ravenusb/Makefile.avr-ravenusb +++ b/platform/avr-ravenusb/Makefile.avr-ravenusb @@ -68,7 +68,8 @@ include $(CONTIKIAVR)/radio/Makefile.radio ifndef CONTIKI_NO_NET MODULES+=core/net/ip core/net/ipv4 core/net core/net/ipv6 \ - core/net/rime core/net/mac core/net/mac/sicslowmac + core/net/rime core/net/mac core/net/mac/sicslowmac \ + core/net/llsec else vpath %.c $(CONTIKI)/core/net/ipv6 CONTIKI_SOURCEFILES += sicslowpan.c linkaddr.c diff --git a/platform/cc2530dk/Makefile.cc2530dk b/platform/cc2530dk/Makefile.cc2530dk index a163a2aef..8423843eb 100644 --- a/platform/cc2530dk/Makefile.cc2530dk +++ b/platform/cc2530dk/Makefile.cc2530dk @@ -47,4 +47,5 @@ CONTIKI_CPU=$(CONTIKI)/cpu/cc253x include $(CONTIKI_CPU)/Makefile.cc253x # Default modules -MODULES += core/net/ip core/net/ipv6 core/net/rime core/net core/net/mac core/net/rpl +MODULES += core/net/ip core/net/ipv6 core/net/rime core/net core/net/mac core/net/rpl \ + core/net/llsec diff --git a/platform/cc2538dk/Makefile.cc2538dk b/platform/cc2538dk/Makefile.cc2538dk index 41ccbf507..e5c5a7ab9 100644 --- a/platform/cc2538dk/Makefile.cc2538dk +++ b/platform/cc2538dk/Makefile.cc2538dk @@ -28,7 +28,8 @@ CONTIKI_CPU=$(CONTIKI)/cpu/cc2538 include $(CONTIKI_CPU)/Makefile.cc2538 MODULES += core/net core/net/ipv6 core/net/mac core/net/ip \ - core/net/rpl core/net/rime core/net/mac/contikimac + core/net/rpl core/net/rime core/net/mac/contikimac \ + core/net/llsec BSL = $(CONTIKI)/tools/cc2538-bsl/cc2538-bsl.py diff --git a/platform/cc2538dk/contiki-conf.h b/platform/cc2538dk/contiki-conf.h index ecab2ecb8..141a62ce2 100644 --- a/platform/cc2538dk/contiki-conf.h +++ b/platform/cc2538dk/contiki-conf.h @@ -308,7 +308,6 @@ typedef uint32_t rtimer_clock_t; #define NULLRDC_802154_AUTOACK_HW 1 /* Configure ContikiMAC for when it's selected */ -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 #define CONTIKIMAC_CONF_WITH_PHASE_OPTIMIZATION 0 #define WITH_FAST_SLEEP 1 diff --git a/platform/cooja/Makefile.cooja b/platform/cooja/Makefile.cooja index 047ca9d99..4492c2341 100644 --- a/platform/cooja/Makefile.cooja +++ b/platform/cooja/Makefile.cooja @@ -90,4 +90,5 @@ ifeq ($(UIP_CONF_IPV6),1) endif # UIP_CONF_IPV6 MODULES += core/net core/net/ip core/net/ipv4 \ - core/net/ipv6 core/net/mac core/net/rime core/net/rpl + core/net/ipv6 core/net/mac core/net/rime core/net/rpl \ + core/net/llsec diff --git a/platform/cooja/net/uip-driver.c b/platform/cooja/net/uip-driver.c index 39dbd6e01..1b2fb5c4d 100644 --- a/platform/cooja/net/uip-driver.c +++ b/platform/cooja/net/uip-driver.c @@ -51,7 +51,7 @@ uip_driver_send(void) /* XXX we should provide a callback function that is called when the packet is sent. For now, we just supply a NULL pointer. */ - NETSTACK_MAC.send(NULL, NULL); + NETSTACK_LLSEC.send(NULL, NULL); return 1; } /*--------------------------------------------------------------------*/ diff --git a/platform/econotag/Makefile.econotag b/platform/econotag/Makefile.econotag index 8e6939f9c..e6a8cbdd6 100644 --- a/platform/econotag/Makefile.econotag +++ b/platform/econotag/Makefile.econotag @@ -21,4 +21,5 @@ endif include $(CONTIKIMC1322X)/Makefile.mc1322x MODULES+=core/net/ip core/net/ipv4 core/net core/net/rpl \ - core/net/ipv6 core/net/rime core/net/mac + core/net/ipv6 core/net/rime core/net/mac \ + core/net/llsec diff --git a/platform/ev-aducrf101mkxz/Makefile.ev-aducrf101mkxz b/platform/ev-aducrf101mkxz/Makefile.ev-aducrf101mkxz index 261f5fe51..dfa36785e 100644 --- a/platform/ev-aducrf101mkxz/Makefile.ev-aducrf101mkxz +++ b/platform/ev-aducrf101mkxz/Makefile.ev-aducrf101mkxz @@ -62,4 +62,5 @@ MODULES += \ core/net/ipv6 \ core/net/rime \ core/net/mac \ - core/net/mac/sicslowmac + core/net/mac/sicslowmac \ + core/net/llsec diff --git a/platform/eval-adf7xxxmb4z/Makefile.eval-adf7xxxmb4z b/platform/eval-adf7xxxmb4z/Makefile.eval-adf7xxxmb4z index ff62e000f..0d7ec1faa 100644 --- a/platform/eval-adf7xxxmb4z/Makefile.eval-adf7xxxmb4z +++ b/platform/eval-adf7xxxmb4z/Makefile.eval-adf7xxxmb4z @@ -63,4 +63,5 @@ run: $(CONTIKI_PROJECT).$(TARGET).srec ~/adi-contiki/github/rl78flash/rl78flash -vv -i -m3 $(PROG_UART) -b500000 -a $< MODULES+=core/net/ip core/net/ipv4 core/net core/net/rpl \ - core/net/ipv6 core/net/rime core/net/mac core/net/mac/sicslowmac + core/net/ipv6 core/net/rime core/net/mac core/net/mac/sicslowmac \ + core/net/llsec diff --git a/platform/exp5438/Makefile.exp5438 b/platform/exp5438/Makefile.exp5438 index 07fe040fc..e62f9aec4 100644 --- a/platform/exp5438/Makefile.exp5438 +++ b/platform/exp5438/Makefile.exp5438 @@ -3,7 +3,7 @@ MODULES += core/net core/net/ip core/net/ipv6 core/net/ipv4 \ core/net/mac core/net/rpl core/net/rime core/net/mac/contikimac \ - dev/cc2420 + core/net/llsec dev/cc2420 ifdef IAR CFLAGS+=-e --vla -Ohz --multiplier=32 --multiplier_location=4C0 --hw_workaround=CPU40 --core=430X --data_model small --double=32 -D__MSP430F5438A__=1 diff --git a/platform/exp5438/contiki-conf.h b/platform/exp5438/contiki-conf.h index c03fccfdb..29901103a 100644 --- a/platform/exp5438/contiki-conf.h +++ b/platform/exp5438/contiki-conf.h @@ -44,7 +44,6 @@ larger than a specified size, if no ContikiMAC header should be used. */ #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 #define CXMAC_CONF_ANNOUNCEMENTS 0 #define XMAC_CONF_ANNOUNCEMENTS 0 diff --git a/platform/mbxxx/Makefile.mbxxx b/platform/mbxxx/Makefile.mbxxx index 68905e295..d60a6b044 100644 --- a/platform/mbxxx/Makefile.mbxxx +++ b/platform/mbxxx/Makefile.mbxxx @@ -22,4 +22,5 @@ ifeq ($(HOST_OS),Windows) endif MODULES+=core/net/ip core/net/ipv4 core/net core/net/ipv6 \ - core/net/rpl core/net/rime core/net/mac core/net/mac/contikimac + core/net/rpl core/net/rime core/net/mac core/net/mac/contikimac \ + core/net/llsec diff --git a/platform/mbxxx/contiki-conf.h b/platform/mbxxx/contiki-conf.h index c732fe8ac..e724450ac 100644 --- a/platform/mbxxx/contiki-conf.h +++ b/platform/mbxxx/contiki-conf.h @@ -125,7 +125,6 @@ larger than a specified size, if no ContikiMAC header should be used. */ #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 #define UIP_CONF_UDP 1 diff --git a/platform/micaz/Makefile.micaz b/platform/micaz/Makefile.micaz index cdfea9e74..b4fe59da5 100644 --- a/platform/micaz/Makefile.micaz +++ b/platform/micaz/Makefile.micaz @@ -46,4 +46,5 @@ ifneq ($(strip $(HAVE_PRGBOARD_FILE)), ) endif MODULES += core/net core/net/ip core/net/ipv6 core/net/ipv4 core/net/rime \ - core/net/mac core/net/rpl core/net/mac/cxmac dev/cc2420 + core/net/mac core/net/rpl core/net/mac/cxmac \ + core/net/llsec dev/cc2420 diff --git a/platform/native/Makefile.native b/platform/native/Makefile.native index cda1488c1..f84fa6c46 100644 --- a/platform/native/Makefile.native +++ b/platform/native/Makefile.native @@ -47,4 +47,4 @@ CURSES_LIBS ?= -lncurses TARGET_LIBFILES += $(CURSES_LIBS) MODULES+=core/net/ip core/net/ipv4 core/net core/net/ipv6 core/net/rime \ - core/net/mac core/net/rpl core/ctk + core/net/mac core/net/rpl core/ctk core/net/llsec diff --git a/platform/seedeye/contiki-conf.h b/platform/seedeye/contiki-conf.h index 9b04cbbc8..f0cce7acb 100644 --- a/platform/seedeye/contiki-conf.h +++ b/platform/seedeye/contiki-conf.h @@ -87,8 +87,6 @@ typedef uint32_t rtimer_clock_t; #define RDC_CONF_HARDWARE_CSMA 1 -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 - #ifdef WITH_UIP6 #define UIP_CONF_ROUTER 1 #ifndef UIP_CONF_IPV6_RPL diff --git a/platform/sensinode/Makefile.sensinode b/platform/sensinode/Makefile.sensinode index b61eb24c5..9bb421234 100644 --- a/platform/sensinode/Makefile.sensinode +++ b/platform/sensinode/Makefile.sensinode @@ -88,4 +88,5 @@ include $(CONTIKI)/cpu/cc2430/Makefile.cc2430 contiki-$(TARGET).a:# $(addprefix $(OBJECTDIR)/,symbols.rel) -MODULES += core/net/ipv6 core/net/ip core/net/rime core/net core/net/mac core/net/rpl +MODULES += core/net/ipv6 core/net/ip core/net/rime core/net core/net/mac core/net/rpl \ + core/net/llsec diff --git a/platform/sky/Makefile.common b/platform/sky/Makefile.common index 2f8b32dc0..0c121b25a 100644 --- a/platform/sky/Makefile.common +++ b/platform/sky/Makefile.common @@ -1,7 +1,7 @@ # $Id: Makefile.common,v 1.3 2010/08/24 16:24:11 joxe Exp $ ARCH=spi.c ds2411.c xmem.c i2c.c node-id.c sensors.c cfs-coffee.c \ - cc2420.c cc2420-aes.c cc2420-arch.c cc2420-arch-sfd.c \ + cc2420.c cc2420-arch.c cc2420-arch-sfd.c \ sky-sensors.c uip-ipchksum.c \ uart1.c slip_uart1.c uart1-putchar.c diff --git a/platform/sky/Makefile.sky b/platform/sky/Makefile.sky index bcceba92f..ebde4c8bd 100644 --- a/platform/sky/Makefile.sky +++ b/platform/sky/Makefile.sky @@ -13,4 +13,5 @@ include $(CONTIKI)/platform/sky/Makefile.common MODULES += core/net/ipv6 core/net/ipv4 core/net/rime core/net/mac \ core/net core/net/ip core/net/rpl \ core/net/mac/contikimac core/net/mac/cxmac \ + core/net/llsec core/net/llsec/noncoresec \ dev/cc2420 dev/sht11 dev/ds2411 diff --git a/platform/sky/contiki-conf.h b/platform/sky/contiki-conf.h index 9e7c83b40..c99645898 100644 --- a/platform/sky/contiki-conf.h +++ b/platform/sky/contiki-conf.h @@ -48,7 +48,6 @@ larger than a specified size, if no ContikiMAC header should be used. */ #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 #define CXMAC_CONF_ANNOUNCEMENTS 0 #define XMAC_CONF_ANNOUNCEMENTS 0 @@ -212,7 +211,9 @@ #define UIP_CONF_TCP_SPLIT 0 - +#ifndef AES_128_CONF +#define AES_128_CONF cc2420_aes_128_driver +#endif /* AES_128_CONF */ /* include the project config */ /* PROJECT_CONF_H might be defined in the project Makefile */ diff --git a/platform/sky/contiki-sky-main.c b/platform/sky/contiki-sky-main.c index 4df32e57e..639d0d108 100644 --- a/platform/sky/contiki-sky-main.c +++ b/platform/sky/contiki-sky-main.c @@ -97,6 +97,13 @@ static uint8_t is_gateway; #include "experiment-setup.h" #endif +#define DEBUG 1 +#if DEBUG +#define PRINTF(...) printf(__VA_ARGS__) +#else /* DEBUG */ +#define PRINTF(...) +#endif /* DEBUG */ + void init_platform(void); /*---------------------------------------------------------------------------*/ @@ -144,11 +151,11 @@ set_rime_addr(void) } #endif linkaddr_set_node_addr(&addr); - printf("Rime started with address "); + PRINTF("Rime started with address "); for(i = 0; i < sizeof(addr.u8) - 1; i++) { - printf("%d.", addr.u8[i]); + PRINTF("%d.", addr.u8[i]); } - printf("%d\n", addr.u8[i]); + PRINTF("%d\n", addr.u8[i]); } /*---------------------------------------------------------------------------*/ #if !PROCESS_CONF_NO_PROCESS_NAMES @@ -171,9 +178,9 @@ set_gateway(void) { if(!is_gateway) { leds_on(LEDS_RED); - printf("%d.%d: making myself the IP network gateway.\n\n", + PRINTF("%d.%d: making myself the IP network gateway.\n\n", linkaddr_node_addr.u8[0], linkaddr_node_addr.u8[1]); - printf("IPv4 address of the gateway: %d.%d.%d.%d\n\n", + PRINTF("IPv4 address of the gateway: %d.%d.%d.%d\n\n", uip_ipaddr_to_quad(&uip_hostaddr)); uip_over_mesh_set_gateway(&linkaddr_node_addr); uip_over_mesh_make_announced_gateway(); @@ -182,6 +189,65 @@ set_gateway(void) } #endif /* WITH_UIP */ /*---------------------------------------------------------------------------*/ +static void +start_autostart_processes() +{ +#if !PROCESS_CONF_NO_PROCESS_NAMES + print_processes(autostart_processes); +#endif /* !PROCESS_CONF_NO_PROCESS_NAMES */ + autostart_start(autostart_processes); +} +/*---------------------------------------------------------------------------*/ +#if WITH_UIP6 +static void +start_uip6() +{ + NETSTACK_NETWORK.init(); + + process_start(&tcpip_process, NULL); + +#if DEBUG + PRINTF("Tentative link-local IPv6 address "); + { + uip_ds6_addr_t *lladdr; + int i; + lladdr = uip_ds6_get_link_local(-1); + for(i = 0; i < 7; ++i) { + PRINTF("%02x%02x:", lladdr->ipaddr.u8[i * 2], + lladdr->ipaddr.u8[i * 2 + 1]); + } + PRINTF("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); + } +#endif /* DEBUG */ + + if(!UIP_CONF_IPV6_RPL) { + uip_ipaddr_t ipaddr; + int i; + uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); + uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); + uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); + PRINTF("Tentative global IPv6 address "); + for(i = 0; i < 7; ++i) { + PRINTF("%02x%02x:", + ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); + } + PRINTF("%02x%02x\n", + ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); + } +} +#endif /* WITH_UIP6 */ +/*---------------------------------------------------------------------------*/ +static void +start_network_layer() +{ +#if WITH_UIP6 + start_uip6(); +#endif /* WITH_UIP6 */ + start_autostart_processes(); + /* To support link layer security in combination with WITH_UIP and + * TIMESYNCH_CONF_ENABLED further things may need to be moved here */ +} +/*---------------------------------------------------------------------------*/ #if WITH_TINYOS_AUTO_IDS uint16_t TOS_NODE_ID = 0x1234; /* non-zero */ uint16_t TOS_LOCAL_ADDRESS = 0x1234; /* non-zero */ @@ -262,21 +328,21 @@ main(int argc, char **argv) linkaddr_node_addr.u8[1]; memset(longaddr, 0, sizeof(longaddr)); linkaddr_copy((linkaddr_t *)&longaddr, &linkaddr_node_addr); - printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", + PRINTF("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x ", longaddr[0], longaddr[1], longaddr[2], longaddr[3], longaddr[4], longaddr[5], longaddr[6], longaddr[7]); cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr); } - printf(CONTIKI_VERSION_STRING " started. "); + PRINTF(CONTIKI_VERSION_STRING " started. "); if(node_id > 0) { - printf("Node id is set to %u.\n", node_id); + PRINTF("Node id is set to %u.\n", node_id); } else { - printf("Node id is not set.\n"); + PRINTF("Node id is not set.\n"); } - /* printf("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", + /* PRINTF("MAC %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", ds2411_id[0], ds2411_id[1], ds2411_id[2], ds2411_id[3], ds2411_id[4], ds2411_id[5], ds2411_id[6], ds2411_id[7]);*/ @@ -284,58 +350,28 @@ main(int argc, char **argv) memcpy(&uip_lladdr.addr, ds2411_id, sizeof(uip_lladdr.addr)); /* Setup nullmac-like MAC for 802.15.4 */ /* sicslowpan_init(sicslowmac_init(&cc2420_driver)); */ -/* printf(" %s channel %u\n", sicslowmac_driver.name, CC2420_CONF_CCA_THRESH); */ +/* PRINTF(" %s channel %u\n", sicslowmac_driver.name, CC2420_CONF_CCA_THRESH); */ /* Setup X-MAC for 802.15.4 */ queuebuf_init(); NETSTACK_RDC.init(); NETSTACK_MAC.init(); - NETSTACK_NETWORK.init(); - printf("%s %s, channel check rate %lu Hz, radio channel %u, CCA threshold %i\n", - NETSTACK_MAC.name, NETSTACK_RDC.name, + PRINTF("%s %s %s, channel check rate %lu Hz, radio channel %u, CCA threshold %i\n", + NETSTACK_LLSEC.name, NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0 ? 1: NETSTACK_RDC.channel_check_interval()), CC2420_CONF_CHANNEL, CC2420_CONF_CCA_THRESH); - process_start(&tcpip_process, NULL); - - printf("Tentative link-local IPv6 address "); - { - uip_ds6_addr_t *lladdr; - int i; - lladdr = uip_ds6_get_link_local(-1); - for(i = 0; i < 7; ++i) { - printf("%02x%02x:", lladdr->ipaddr.u8[i * 2], - lladdr->ipaddr.u8[i * 2 + 1]); - } - printf("%02x%02x\n", lladdr->ipaddr.u8[14], lladdr->ipaddr.u8[15]); - } - - if(!UIP_CONF_IPV6_RPL) { - uip_ipaddr_t ipaddr; - int i; - uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); - uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); - uip_ds6_addr_add(&ipaddr, 0, ADDR_TENTATIVE); - printf("Tentative global IPv6 address "); - for(i = 0; i < 7; ++i) { - printf("%02x%02x:", - ipaddr.u8[i * 2], ipaddr.u8[i * 2 + 1]); - } - printf("%02x%02x\n", - ipaddr.u8[7 * 2], ipaddr.u8[7 * 2 + 1]); - } - #else /* WITH_UIP6 */ NETSTACK_RDC.init(); NETSTACK_MAC.init(); NETSTACK_NETWORK.init(); - printf("%s %s, channel check rate %lu Hz, radio channel %u\n", - NETSTACK_MAC.name, NETSTACK_RDC.name, + PRINTF("%s %s %s, channel check rate %lu Hz, radio channel %u\n", + NETSTACK_LLSEC.name, NETSTACK_MAC.name, NETSTACK_RDC.name, CLOCK_SECOND / (NETSTACK_RDC.channel_check_interval() == 0? 1: NETSTACK_RDC.channel_check_interval()), CC2420_CONF_CHANNEL); @@ -377,7 +413,7 @@ main(int argc, char **argv) uip_over_mesh_set_gateway_netif(&slipif); uip_fw_default(&meshif); uip_over_mesh_init(UIP_OVER_MESH_CHANNEL); - printf("uIP started with IP address %d.%d.%d.%d\n", + PRINTF("uIP started with IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&hostaddr)); } #endif /* WITH_UIP */ @@ -387,12 +423,7 @@ main(int argc, char **argv) watchdog_start(); -#if !PROCESS_CONF_NO_PROCESS_NAMES - print_processes(autostart_processes); -#else /* !PROCESS_CONF_NO_PROCESS_NAMES */ - putchar('\n'); /* include putchar() */ -#endif /* !PROCESS_CONF_NO_PROCESS_NAMES */ - autostart_start(autostart_processes); + NETSTACK_LLSEC.bootstrap(start_network_layer); /* * This is the scheduler loop. diff --git a/platform/wismote/Makefile.wismote b/platform/wismote/Makefile.wismote index e9d474446..0a86ea9e6 100644 --- a/platform/wismote/Makefile.wismote +++ b/platform/wismote/Makefile.wismote @@ -56,4 +56,5 @@ contiki-$(TARGET).a: ${addprefix $(OBJECTDIR)/,symbols.o} MODULES += core/net core/net/ip core/net/ipv6 core/net/ipv4 core/net/mac \ core/net/rime core/net/mac/contikimac core/net/rpl \ + core/net/llsec \ dev/cc2520 dev/sht11 diff --git a/platform/wismote/contiki-conf.h b/platform/wismote/contiki-conf.h index 12b2396de..d37f8f3e6 100644 --- a/platform/wismote/contiki-conf.h +++ b/platform/wismote/contiki-conf.h @@ -42,7 +42,6 @@ larger than a specified size, if no ContikiMAC header should be used. */ #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 #define CXMAC_CONF_ANNOUNCEMENTS 0 #define XMAC_CONF_ANNOUNCEMENTS 0 diff --git a/platform/z1/Makefile.common b/platform/z1/Makefile.common index 6247fa383..899d141c8 100644 --- a/platform/z1/Makefile.common +++ b/platform/z1/Makefile.common @@ -13,7 +13,7 @@ endif CLEAN += symbols.c symbols.h ARCH=msp430.c leds.c watchdog.c xmem.c \ - spi.c cc2420.c cc2420-aes.c cc2420-arch.c cc2420-arch-sfd.c\ + spi.c cc2420.c cc2420-arch.c cc2420-arch-sfd.c\ node-id.c sensors.c button-sensor.c cfs-coffee.c \ radio-sensor.c uart0.c uart0-putchar.c uip-ipchksum.c \ slip.c slip_uart0.c \ diff --git a/platform/z1/Makefile.z1 b/platform/z1/Makefile.z1 index 3d9482748..0079373d7 100644 --- a/platform/z1/Makefile.z1 +++ b/platform/z1/Makefile.z1 @@ -11,4 +11,5 @@ endif MODULES += core/net core/net/ip core/net/ipv6 core/net/ipv4 core/net/rpl \ core/net/rime core/net/mac core/net/mac/contikimac \ + core/net/llsec \ dev/cc2420 dev/sht11 diff --git a/platform/z1/contiki-conf.h b/platform/z1/contiki-conf.h index c69ff7e40..4445b53f5 100644 --- a/platform/z1/contiki-conf.h +++ b/platform/z1/contiki-conf.h @@ -51,7 +51,6 @@ larger than a specified size, if no ContikiMAC header should be used. */ #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD 63 -#define CONTIKIMAC_CONF_WITH_CONTIKIMAC_HEADER 0 #define CC2420_CONF_AUTOACK 1 #define NETSTACK_RDC_CHANNEL_CHECK_RATE 8 diff --git a/regression-tests/18-llsec/01-ccm-tests.csc b/regression-tests/18-llsec/01-ccm-tests.csc new file mode 100644 index 000000000..0d0d8343a --- /dev/null +++ b/regression-tests/18-llsec/01-ccm-tests.csc @@ -0,0 +1,187 @@ + + + [APPS_DIR]/mrm + [APPS_DIR]/mspsim + [APPS_DIR]/avrora + [APPS_DIR]/serial_socket + [APPS_DIR]/collect-view + [APPS_DIR]/powertracker + + llsec validation + 123456 + 1000000 + + org.contikios.cooja.radiomediums.UDGM + 50.0 + 100.0 + 1.0 + 1.0 + + + 40000 + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype139 + Verification + [CONTIKI_DIR]/examples/llsec/ccm-tests/verification/tests.c + make tests.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + org.contikios.cooja.contikimote.ContikiMoteType + mtype792 + Encryption + [CONTIKI_DIR]/examples/llsec/ccm-tests/encryption/tests.c + make tests.cooja TARGET=cooja + org.contikios.cooja.interfaces.Position + org.contikios.cooja.interfaces.Battery + org.contikios.cooja.contikimote.interfaces.ContikiVib + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + org.contikios.cooja.contikimote.interfaces.ContikiRS232 + org.contikios.cooja.contikimote.interfaces.ContikiBeeper + org.contikios.cooja.interfaces.RimeAddress + org.contikios.cooja.contikimote.interfaces.ContikiIPAddress + org.contikios.cooja.contikimote.interfaces.ContikiRadio + org.contikios.cooja.contikimote.interfaces.ContikiButton + org.contikios.cooja.contikimote.interfaces.ContikiPIR + org.contikios.cooja.contikimote.interfaces.ContikiClock + org.contikios.cooja.contikimote.interfaces.ContikiLED + org.contikios.cooja.contikimote.interfaces.ContikiCFS + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + org.contikios.cooja.interfaces.Mote2MoteRelations + org.contikios.cooja.interfaces.MoteAttributes + false + + + + org.contikios.cooja.interfaces.Position + 8.103036578104216 + 28.0005728229897 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 1 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype139 + + + + org.contikios.cooja.interfaces.Position + 87.3441626132979 + 25.080887412193555 + 0.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiMoteID + 2 + + + org.contikios.cooja.contikimote.interfaces.ContikiRadio + 250.0 + + + org.contikios.cooja.contikimote.interfaces.ContikiEEPROM + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== + + mtype792 + + + + org.contikios.cooja.plugins.SimControl + 280 + 4 + 160 + 400 + 0 + + + org.contikios.cooja.plugins.Visualizer + + true + org.contikios.cooja.plugins.skins.IDVisualizerSkin + org.contikios.cooja.plugins.skins.GridVisualizerSkin + org.contikios.cooja.plugins.skins.TrafficVisualizerSkin + org.contikios.cooja.plugins.skins.UDGMVisualizerSkin + 4.451315754531486 0.0 0.0 4.451315754531486 -18.43281074329661 54.85882989079608 + + 400 + 3 + 400 + 1 + 1 + + + org.contikios.cooja.plugins.LogListener + + Success + + + + 1520 + 2 + 240 + 400 + 160 + + + org.contikios.cooja.plugins.Notes + + A simple test script that runs the tests in examples/llsec/ccm-tests/ + true + + 1240 + 0 + 160 + 680 + 0 + + + org.contikios.cooja.plugins.ScriptRunner + + + true + + 600 + 1 + 700 + 288 + 199 + + + diff --git a/regression-tests/18-llsec/Makefile b/regression-tests/18-llsec/Makefile new file mode 100644 index 000000000..272bc7da1 --- /dev/null +++ b/regression-tests/18-llsec/Makefile @@ -0,0 +1 @@ +include ../Makefile.simulation-test