/*---------------------------------------------------------------------------*/ static int verify_broadcast(struct akes_nbr *sender) { uint8_t mic[ADAPTIVESEC_BROADCAST_MIC_LEN]; #if WITH_BROADCAST_ENCRYPTION adaptivesec_aead(sender->group_key, 1, mic, 0); #endif /* WITH_BROADCAST_ENCRYPTION */ adaptivesec_aead(sender->pairwise_key, 0, mic, 0); return !is_mic_stored(mic); }
/** * Payload format: * | 0x0d | 0x00 | CCM*-MIC for neighbor 0 | ... | CCM*-MIC for last neighbor | */ static void prepare_announce(void) { struct akes_nbr_entry *next; uint8_t announced_mics[NBR_TABLE_MAX_NEIGHBORS * ADAPTIVESEC_BROADCAST_MIC_LEN]; uint8_t *payload; uint8_t announced_mics_len; uint8_t max_index; max_index = 0; next = akes_nbr_head(); while(next) { if(next->permanent) { adaptivesec_aead(next->permanent->pairwise_key, 0, announced_mics + (next->local_index * ADAPTIVESEC_BROADCAST_MIC_LEN), 1); if(next->local_index > max_index) { max_index = next->local_index; } } next = akes_nbr_next(next); } /* reset packetbuf for sending a command frame */ payload = adaptivesec_prepare_command(CORESEC_STRATEGY_ANNOUNCE_IDENTIFIER, &linkaddr_null); /* write payload */ /* TODO We currently assume that all MICs fit within a single ANNOUNCE command */ payload[0] = 0; announced_mics_len = (max_index + 1) * ADAPTIVESEC_BROADCAST_MIC_LEN; memcpy(payload + 1, announced_mics, announced_mics_len); packetbuf_set_datalen(1 + 1 + announced_mics_len); }
/*---------------------------------------------------------------------------*/ static int on_frame_created(void) { uint8_t sec_lvl; enum akes_nbr_status status; struct akes_nbr_entry *entry; uint8_t *dataptr; uint8_t datalen; sec_lvl = adaptivesec_get_sec_lvl(); if(sec_lvl && !packetbuf_holds_broadcast()) { status = akes_get_receiver_status(); entry = akes_nbr_get_receiver_entry(); if(!entry || !entry->refs[status]) { return 0; } dataptr = packetbuf_dataptr(); datalen = packetbuf_datalen(); adaptivesec_aead(entry->refs[status]->pairwise_key, sec_lvl & (1 << 2), dataptr + datalen, 1); packetbuf_set_datalen(datalen + ADAPTIVESEC_UNICAST_MIC_LEN); } return 1; }
/*---------------------------------------------------------------------------*/ static void send_broadcast(mac_callback_t sent, void *ptr) { struct queuebuf *qb; qb = queuebuf_new_from_packetbuf(); if(!qb || (NETSTACK_FRAMER.create() < 0)) { PRINTF("coresec-strategy: Did not send broadcast\n"); if(qb) { queuebuf_free(qb); } sent(ptr, MAC_TX_ERR, 0); return; } prepare_announce(); adaptivesec_send_command_frame(); watchdog_periodic(); queuebuf_to_packetbuf(qb); queuebuf_free(qb); #if WITH_BROADCAST_ENCRYPTION { uint8_t ignore[ADAPTIVESEC_BROADCAST_MIC_LEN]; if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) { adaptivesec_aead(adaptivesec_group_key, 1, ignore, 1); } } #endif /* WITH_BROADCAST_ENCRYPTION */ NETSTACK_MAC.send(sent, ptr); }
/*---------------------------------------------------------------------------*/ static int decrypt_verify_broadcast(struct neighbor *sender) { uint8_t mic[ADAPTIVESEC_BROADCAST_MIC_LEN]; if((packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 3) != (ADAPTIVESEC_BROADCAST_SEC_LVL & 3)) { PRINTF("coresec-strategy: Wrong security level\n"); return 0; } #if WITH_BROADCAST_ENCRYPTION if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & (1 << 2)) { adaptivesec_aead(sender->group_key, 1, mic, 0); } #endif /* WITH_BROADCAST_ENCRYPTION */ adaptivesec_aead(sender->pairwise_key, 0, mic, 0); return is_mic_stored(mic); }
/*---------------------------------------------------------------------------*/ int adaptivesec_verify(uint8_t *key) { int shall_decrypt; uint8_t generated_mic[MAX(ADAPTIVESEC_UNICAST_MIC_LEN, ADAPTIVESEC_BROADCAST_MIC_LEN)]; shall_decrypt = adaptivesec_get_sec_lvl() & (1 << 2); packetbuf_set_datalen(packetbuf_datalen() - adaptivesec_mic_len()); adaptivesec_aead(key, shall_decrypt, generated_mic, 0); return memcmp(generated_mic, ((uint8_t *) packetbuf_dataptr()) + packetbuf_datalen(), adaptivesec_mic_len()); }
/*---------------------------------------------------------------------------*/ static void send_broadcast(mac_callback_t sent, void *ptr) { struct queuebuf *qb; #if ANTI_REPLAY_WITH_SUPPRESSION uint16_t frame_counter_bytes_0_1; uint16_t frame_counter_bytes_2_3; uint8_t seqno; frame_counter_bytes_0_1 = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1); frame_counter_bytes_2_3 = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3); seqno = packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO); adaptivesec_add_security_header(NULL); #endif /* ANTI_REPLAY_WITH_SUPPRESSION */ qb = queuebuf_new_from_packetbuf(); if(!qb || (NETSTACK_FRAMER.create() < 0)) { PRINTF("coresec-strategy: Did not send broadcast\n"); if(qb) { queuebuf_free(qb); } sent(ptr, MAC_TX_ERR, 0); return; } prepare_announce(); #if ANTI_REPLAY_WITH_SUPPRESSION packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, frame_counter_bytes_0_1); packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, frame_counter_bytes_2_3); packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, seqno); #endif /* ANTI_REPLAY_WITH_SUPPRESSION */ adaptivesec_send_command_frame(); watchdog_periodic(); queuebuf_to_packetbuf(qb); queuebuf_free(qb); #if WITH_BROADCAST_ENCRYPTION { uint8_t ignore[ADAPTIVESEC_BROADCAST_MIC_LEN]; if(adaptivesec_get_sec_lvl() & (1 << 2)) { adaptivesec_aead(adaptivesec_group_key, 1, ignore, 1); } } #endif /* WITH_BROADCAST_ENCRYPTION */ NETSTACK_MAC.send(sent, ptr); }