58#include "net/mac/ccm-star-packetbuf.h"
61#define LOG_MODULE "CSMA"
62#define LOG_LEVEL LOG_LEVEL_MAC
64#if LOG_LEVEL == LOG_LEVEL_DBG
65static const char * HEX =
"0123456789ABCDEF";
68#if LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER
70#if LLSEC802154_USES_EXPLICIT_KEYS
71#define LLSEC_KEY_INDEX (FRAME802154_IMPLICIT_KEY == packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE) \
73 : packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX))
74#define LLSEC_KEY_MODE (packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE))
76#define LLSEC_KEY_INDEX (0)
77#define LLSEC_KEY_MODE (FRAME802154_IMPLICIT_KEY)
86static aes_key_t keys[CSMA_LLSEC_MAXKEYS];
90csma_security_set_key(uint8_t index,
const uint8_t *key)
92 if(key != NULL && index < CSMA_LLSEC_MAXKEYS) {
93 memcpy(keys[index].u8, key, 16);
99#define N_KEYS (sizeof(keys) / sizeof(aes_key))
102aead(uint8_t hdrlen,
int forward)
105 uint8_t nonce[CCM_STAR_NONCE_LENGTH];
112 uint8_t generated_mic[LLSEC802154_MIC_LEN(
113 FRAME802154_SECURITY_LEVEL_ENC_MIC_128)];
117 uint8_t with_encryption;
119 key_index = LLSEC_KEY_INDEX;
120 if(key_index >= CSMA_LLSEC_MAXKEYS) {
121 LOG_ERR(
"Key not available: %u\n", key_index);
125 key = &keys[key_index];
127 ccm_star_packetbuf_set_nonce(nonce, forward);
132 (packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4) ? 1 : 0;
134 if(with_encryption) {
137 m_len = totlen - hdrlen;
145 result = forward ? mic : generated_mic;
147 CCM_STAR.set_key(key->u8);
151 result, LLSEC802154_PACKETBUF_MIC_LEN(),
156 + LLSEC802154_PACKETBUF_MIC_LEN());
159 return memcmp(generated_mic, mic, LLSEC802154_PACKETBUF_MIC_LEN()) == 0;
169 packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
170 if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0 &&
171 LLSEC_KEY_INDEX != 0xffff) {
175 hdr_len = framer_802154.create();
180 if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0) {
181#if LOG_LEVEL == LOG_LEVEL_DBG
187 LOG_DBG_(
"%c%c", HEX[(p[i] >> 4) & 0x0f], HEX[p[i] & 0x0f]);
192 if(!aead(hdr_len, 1)) {
193 LOG_ERR(
"failed to encrypt packet to ");
194 LOG_ERR_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
196 return FRAMER_FAILED;
198 LOG_INFO(
"LLSEC-OUT:");
199 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
201 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
203 packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL), LLSEC_KEY_INDEX);
205#if LOG_LEVEL == LOG_LEVEL_DBG
209 LOG_DBG_(
"%c%c", HEX[(p[i] >> 4) & 0x0f], HEX[p[i] & 0x0f]);
222 if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0 &&
223 LLSEC_KEY_INDEX != 0xffff) {
224 return framer_802154.length() + LLSEC802154_PACKETBUF_MIC_LEN();
226 return framer_802154.length();
234 hdr_len = framer_802154.parse();
239 if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) == 0) {
242 #ifdef LLSEC802154_REJECT_INSECURE
243 return FRAMER_FAILED;
250 LOG_INFO(
"LLSEC-IN: ");
251 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
253 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
259 if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != CSMA_LLSEC_SECURITY_LEVEL) {
260 LOG_INFO(
"received frame with wrong security level (%u) from ",
261 packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL));
262 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
264 return FRAMER_FAILED;
267 if(LLSEC_KEY_MODE != CSMA_LLSEC_KEY_ID_MODE) {
268 LOG_INFO(
"received frame with wrong key id mode (%u) from ", LLSEC_KEY_MODE);
269 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
271 return FRAMER_FAILED;
275 LOG_INFO(
"frame from ourselves\n");
276 return FRAMER_FAILED;
280 LOG_ERR(
"MIC error - too little data in frame!\n");
281 return FRAMER_FAILED;
285 if(!aead(hdr_len, 0)) {
286 LOG_INFO(
"received unauthentic frame %u from ",
288 LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
290 return FRAMER_FAILED;
297const struct framer csma_security_framer = {
Interface to anti-replay mechanisms.
LLSEC802154 Security related configuration.
The 802.15.4 standard CSMA protocol (nonbeacon-enabled)
802.15.4 frame creation and parsing functions
A MAC framer for IEEE 802.15.4.
linkaddr_t linkaddr_node_addr
The link-layer address of the node.
bool linkaddr_cmp(const linkaddr_t *addr1, const linkaddr_t *addr2)
Compare two link-layer addresses.
uint32_t anti_replay_get_counter(void)
Gets the frame counter from packetbuf.
void anti_replay_set_counter(void)
Sets the frame counter packetbuf attributes.
void packetbuf_set_datalen(uint16_t len)
Set the length of the data in the packetbuf.
uint16_t packetbuf_totlen(void)
Get the total length of the header and data in the packetbuf.
uint16_t packetbuf_datalen(void)
Get the length of the data in the packetbuf.
void * packetbuf_hdrptr(void)
Get a pointer to the header in the packetbuf, for outbound packets.
Common functionality of 802.15.4-compliant llsec_drivers.
Header file for the logging system.
Include file for the Contiki low-layer network stack (NETSTACK)
Header file for the Packet buffer (packetbuf) management.