llsec: Permit dynamic security levels

This commit is contained in:
kkrentz 2015-12-17 03:13:32 -08:00
parent 0379af3624
commit 10d8b05bc6
22 changed files with 137 additions and 122 deletions

View file

@ -128,8 +128,10 @@ To configure TSCH, see the macros in `.h` files under `core/net/mac/tsch/` and r
To include TSCH standard-compliant security, set the following:
```
/* Enable security */
#undef LLSEC802154_CONF_SECURITY_LEVEL
#define LLSEC802154_CONF_SECURITY_LEVEL 1
#undef LLSEC802154_CONF_ENABLED
#define LLSEC802154_CONF_ENABLED 1
#undef TSCH_SECURITY_CONF_LEVEL
#define TSCH_SECURITY_CONF_LEVEL 1
/* TSCH uses explicit keys to identify k1 and k2 */
#undef LLSEC802154_CONF_USES_EXPLICIT_KEYS
#define LLSEC802154_CONF_USES_EXPLICIT_KEYS 1

View file

@ -94,7 +94,7 @@ tsch_packet_create_eack(uint8_t *buf, int buf_size,
p.src_pid = IEEE802154_PANID;
linkaddr_copy((linkaddr_t *)&p.src_addr, &linkaddr_node_addr);
#endif
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
p.fcf.security_enabled = 1;
p.aux_hdr.security_control.security_level = TSCH_SECURITY_KEY_SEC_LEVEL_ACK;
@ -103,7 +103,7 @@ tsch_packet_create_eack(uint8_t *buf, int buf_size,
p.aux_hdr.security_control.frame_counter_size = 1;
p.aux_hdr.key_index = TSCH_SECURITY_KEY_INDEX_ACK;
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
if((curr_len = frame802154_create(&p, buf)) == 0) {
return 0;
@ -166,13 +166,13 @@ tsch_packet_parse_eack(const uint8_t *buf, int buf_size,
if(frame->fcf.ie_list_present) {
int mic_len = 0;
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
/* Check if there is space for the security MIC (if any) */
mic_len = tsch_security_mic_len(frame);
if(buf_size < curr_len + mic_len) {
return 0;
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
/* Parse information elements. We need to substract the MIC length, as the exact payload len is needed while parsing */
if((ret = frame802154e_parse_information_elements(buf + curr_len, buf_size - curr_len - mic_len, ies)) == -1) {
return 0;
@ -222,7 +222,7 @@ tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno,
p.dest_addr[0] = 0xff;
p.dest_addr[1] = 0xff;
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
p.fcf.security_enabled = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0;
p.aux_hdr.security_control.security_level = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
@ -231,7 +231,7 @@ tsch_packet_create_eb(uint8_t *buf, int buf_size, uint8_t seqno,
p.aux_hdr.security_control.frame_counter_size = 1;
p.aux_hdr.key_index = packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX);
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
if((curr_len = frame802154_create(&p, buf)) == 0) {
return 0;
@ -387,14 +387,14 @@ tsch_packet_parse_eb(const uint8_t *buf, int buf_size,
if(frame->fcf.ie_list_present) {
/* Calculate space needed for the security MIC, if any, before attempting to parse IEs */
int mic_len = 0;
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(!frame_without_mic) {
mic_len = tsch_security_mic_len(frame);
if(buf_size < curr_len + mic_len) {
return 0;
}
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
/* Parse information elements. We need to substract the MIC length, as the exact payload len is needed while parsing */
if((ret = frame802154e_parse_information_elements(buf + curr_len, buf_size - curr_len - mic_len, ies)) == -1) {

View file

@ -39,22 +39,36 @@
#include "net/mac/tsch/tsch-asn.h"
#include "net/mac/tsch/tsch-private.h"
#include "net/mac/frame802154.h"
#include "net/llsec/llsec802154.h"
#include "net/mac/frame802154e-ie.h"
/******** Configuration *******/
/* To enable TSCH security:
* - set LLSEC802154_CONF_SECURITY_LEVEL
* - set LLSEC802154_CONF_ENABLED
* - set TSCH_SECURITY_CONF_LEVEL
* - set LLSEC802154_CONF_USES_EXPLICIT_KEYS
* - unset LLSEC802154_CONF_USES_FRAME_COUNTER
* */
#define TSCH_SECURITY_ENABLED (LLSEC802154_CONF_SECURITY_LEVEL != 0)
#if TSCH_SECURITY_ENABLED && !LLSEC802154_CONF_USES_EXPLICIT_KEYS
#error TSCH_SECURITY_ENABLED set but LLSEC802154_CONF_USES_EXPLICIT_KEYS unset
#endif /* TSCH_SECURITY_ENABLED */
#if TSCH_SECURITY_ENABLED && LLSEC802154_CONF_USES_FRAME_COUNTER
#error TSCH_SECURITY_ENABLED set but LLSEC802154_CONF_USES_FRAME_COUNTER set
#endif /* TSCH_SECURITY_ENABLED */
#ifdef TSCH_SECURITY_CONF_LEVEL
#define TSCH_SECURITY_LEVEL TSCH_SECURITY_CONF_LEVEL
#else /* TSCH_SECURITY_CONF_LEVEL */
#define TSCH_SECURITY_LEVEL FRAME802154_SECURITY_LEVEL_NONE
#endif /* TSCH_SECURITY_CONF_LEVEL */
#if LLSEC802154_ENABLED && !TSCH_SECURITY_LEVEL
#error LLSEC802154_ENABLED set but TSCH_SECURITY_LEVEL unset
#endif /* LLSEC802154_ENABLED */
#if !LLSEC802154_ENABLED && TSCH_SECURITY_LEVEL
#error TSCH_SECURITY_LEVEL set but LLSEC802154_ENABLED unset
#endif /* LLSEC802154_ENABLED */
#if LLSEC802154_ENABLED && !LLSEC802154_USES_EXPLICIT_KEYS
#error LLSEC802154_ENABLED set but LLSEC802154_USES_EXPLICIT_KEYS unset
#endif /* LLSEC802154_ENABLED */
#if LLSEC802154_ENABLED && LLSEC802154_USES_FRAME_COUNTER
#error LLSEC802154_ENABLED set but LLSEC802154_USES_FRAME_COUNTER set
#endif /* LLSEC802154_ENABLED */
/* K1, defined in 6TiSCH minimal, is well-known (offers no security) and used for EBs only */
#ifdef TSCH_SECURITY_CONF_K1

View file

@ -404,10 +404,10 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
} else {
/* packet payload */
static void *packet;
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
/* encrypted payload */
static uint8_t encrypted_packet[TSCH_PACKET_MAX_LEN];
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
/* packet payload length */
static uint8_t packet_len;
/* packet seqno */
@ -434,7 +434,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
packet_ready = 1;
}
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
/* If we are going to encrypt, we need to generate the output in a separate buffer and keep
* the original untouched. This is to allow for future retransmissions. */
@ -445,7 +445,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
packet = encrypted_packet;
}
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
/* prepare packet to send: copy to radio buffer */
if(packet_ready && NETSTACK_RADIO.prepare(packet, packet_len) == 0) { /* 0 means success */
@ -530,7 +530,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
ack_len = 0;
}
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(ack_len != 0) {
if(!tsch_security_parse_frame(ackbuf, ack_hdrlen, ack_len - ack_hdrlen - tsch_security_mic_len(&frame),
&frame, &current_neighbor->addr, &current_asn)) {
@ -544,7 +544,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
snprintf(log->message, sizeof(log->message),
"!failed to parse ACK"));
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
}
if(ack_len != 0) {
@ -604,11 +604,11 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
log->tx.drift = drift_correction;
log->tx.drift_used = is_drift_correction_used;
log->tx.is_data = ((((uint8_t *)(queuebuf_dataptr(current_packet->qb)))[0]) & 7) == FRAME802154_DATAFRAME;
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
log->tx.sec_level = queuebuf_attr(current_packet->qb, PACKETBUF_ATTR_SECURITY_LEVEL);
#else /* TSCH_SECURITY_ENABLED */
#else /* LLSEC802154_ENABLED */
log->tx.sec_level = 0;
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
log->tx.dest = TSCH_LOG_ID_FROM_LINKADDR(queuebuf_addr(current_packet->qb, PACKETBUF_ADDR_RECEIVER));
);
@ -712,7 +712,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
packet_duration = TSCH_PACKET_DURATION(current_input->len);
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
/* Decrypt and verify incoming frame */
if(frame_valid) {
if(tsch_security_parse_frame(
@ -731,7 +731,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
"!failed to parse frame %u %u", header_len, current_input->len));
frame_valid = 0;
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
if(frame_valid) {
if(linkaddr_cmp(&destination_address, &linkaddr_node_addr)
@ -765,12 +765,12 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
ack_len = tsch_packet_create_eack(ack_buf, sizeof(ack_buf),
&source_address, frame.seq, (int16_t)RTIMERTICKS_TO_US(estimated_drift), do_nack);
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
/* Secure ACK frame. There is only header and header IEs, therefore data len == 0. */
ack_len += tsch_security_secure_frame(ack_buf, ack_buf, ack_len, 0, &current_asn);
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
/* Copy to radio buffer */
NETSTACK_RADIO.prepare((const void *)ack_buf, ack_len);

View file

@ -141,7 +141,7 @@ int tsch_is_coordinator = 0;
/* Are we associated to a TSCH network? */
int tsch_is_associated = 0;
/* Is the PAN running link-layer security? */
int tsch_is_pan_secured = TSCH_SECURITY_ENABLED;
int tsch_is_pan_secured = LLSEC802154_ENABLED;
/* The current Absolute Slot Number (ASN) */
struct asn_t current_asn;
/* Device rank or join priority:
@ -177,7 +177,7 @@ tsch_set_coordinator(int enable)
void
tsch_set_pan_secured(int enable)
{
tsch_is_pan_secured = TSCH_SECURITY_ENABLED && enable;
tsch_is_pan_secured = LLSEC802154_ENABLED && enable;
}
/*---------------------------------------------------------------------------*/
void
@ -455,21 +455,21 @@ tsch_associate(const struct input_packet *input_eb, rtimer_clock_t timestamp)
}
#endif /* TSCH_JOIN_SECURED_ONLY */
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(!tsch_security_parse_frame(input_eb->payload, hdrlen,
input_eb->len - hdrlen - tsch_security_mic_len(&frame),
&frame, (linkaddr_t*)&frame.src_addr, &current_asn)) {
PRINTF("TSCH:! parse_eb: failed to authenticate\n");
return 0;
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
#if !TSCH_SECURITY_ENABLED
#if !LLSEC802154_ENABLED
if(frame.fcf.security_enabled == 1) {
PRINTF("TSCH:! parse_eb: we do not support security, but EB is secured\n");
return 0;
}
#endif /* !TSCH_SECURITY_ENABLED */
#endif /* !LLSEC802154_ENABLED */
#if TSCH_JOIN_MY_PANID_ONLY
/* Check if the EB comes from the PAN ID we expect */
@ -746,14 +746,14 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data)
}
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_BEACONFRAME);
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno);
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
/* Set security level, key id and index */
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_EB);
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE); /* Use 1-byte key index */
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_EB);
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
eb_len = tsch_packet_create_eb(packetbuf_dataptr(), PACKETBUF_SIZE,
tsch_packet_seqno, &hdr_len, &tsch_sync_ie_offset);
if(eb_len != 0) {
@ -907,14 +907,14 @@ send_packet(mac_callback_t sent, void *ptr)
packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, tsch_packet_seqno);
#if TSCH_SECURITY_ENABLED
#if LLSEC802154_ENABLED
if(tsch_is_pan_secured) {
/* Set security level, key id and index */
packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, TSCH_SECURITY_KEY_SEC_LEVEL_OTHER);
packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, FRAME802154_1_BYTE_KEY_ID_MODE); /* Use 1-byte key index */
packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX, TSCH_SECURITY_KEY_INDEX_OTHER);
}
#endif /* TSCH_SECURITY_ENABLED */
#endif /* LLSEC802154_ENABLED */
packet_count_before = tsch_queue_packet_count(addr);

View file

@ -84,8 +84,8 @@
#ifdef TSCH_CONF_JOIN_SECURED_ONLY
#define TSCH_JOIN_SECURED_ONLY TSCH_CONF_JOIN_SECURED_ONLY
#else
/* By default, set if TSCH_SECURITY_ENABLED is also non-zero */
#define TSCH_JOIN_SECURED_ONLY TSCH_SECURITY_ENABLED
/* By default, set if LLSEC802154_ENABLED is also non-zero */
#define TSCH_JOIN_SECURED_ONLY LLSEC802154_ENABLED
#endif
/* By default, join any PAN ID. Otherwise, wait for an EB from IEEE802154_PANID */