/*---------------------------------------------------------------------------*/ static enum cmd_broker_result on_command(uint8_t cmd_id, uint8_t *payload) { struct akes_nbr_entry *entry; uint8_t *max_payload; if(cmd_id != CORESEC_STRATEGY_ANNOUNCE_IDENTIFIER) { return CMD_BROKER_UNCONSUMED; } entry = akes_nbr_get_sender_entry(); if(!entry || !entry->permanent) { return CMD_BROKER_ERROR; } PRINTF("coresec-strategy: Received ANNOUNCE\n"); /* calculate CCM*-MIC location */ payload += 1 + (entry->permanent->foreign_index * ADAPTIVESEC_BROADCAST_MIC_LEN); /* check if CCM*-MIC location is within ANNOUNCE */ max_payload = ((uint8_t *)packetbuf_dataptr()) + packetbuf_datalen() - 1; if(payload + ADAPTIVESEC_BROADCAST_MIC_LEN - 1 > max_payload) { PRINTF("coresec-strategy: Out of bounds\n"); return CMD_BROKER_ERROR; } /* * check if contained CCM*-MIC is already stored, e.g., * due to duplicated ANNOUNCE */ if(is_mic_stored(payload)) { PRINTF("coresec-strategy: Already stored\n"); return CMD_BROKER_ERROR; } /* store CCM*-MIC */ memcpy(mics[next_mic_index].u8, payload, ADAPTIVESEC_BROADCAST_MIC_LEN); if(++next_mic_index == MAX_BUFFERED_MICS) { next_mic_index = 0; } return CMD_BROKER_CONSUMED; }
/*---------------------------------------------------------------------------*/ static void input(void) { struct akes_nbr_entry *entry; #if LLSEC802154_USES_AUX_HEADER && POTR_ENABLED packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL, adaptivesec_get_sec_lvl()); #endif /* LLSEC802154_USES_AUX_HEADER && POTR_ENABLED */ switch(packetbuf_attr(PACKETBUF_ATTR_FRAME_TYPE)) { case FRAME802154_CMDFRAME: cmd_broker_publish(); break; case FRAME802154_DATAFRAME: entry = akes_nbr_get_sender_entry(); if(!entry || !entry->permanent) { PRINTF("adaptivesec: Ignored incoming frame\n"); return; } #if SECRDC_WITH_SECURE_PHASE_LOCK if(packetbuf_holds_broadcast() && ADAPTIVESEC_STRATEGY.verify(entry->permanent)) { return; } #else /* SECRDC_WITH_SECURE_PHASE_LOCK */ #if ANTI_REPLAY_WITH_SUPPRESSION && !POTR_ENABLED anti_replay_restore_counter(&entry->permanent->anti_replay_info); #endif /* ANTI_REPLAY_WITH_SUPPRESSION && !POTR_ENABLED */ if(ADAPTIVESEC_STRATEGY.verify(entry->permanent) != ADAPTIVESEC_VERIFY_SUCCESS) { return; } #endif /* SECRDC_WITH_SECURE_PHASE_LOCK */ akes_nbr_prolong(entry->permanent); NETSTACK_NETWORK.input(); break; } }
/*---------------------------------------------------------------------------*/ static enum cmd_broker_result on_helloack(uint8_t *payload, int p_flag) { struct akes_nbr_entry *entry; uint8_t *secret; uint8_t key[AKES_NBR_CHALLENGE_LEN * 2]; int is_new; PRINTF("akes: Received HELLOACK\n"); if(!akes_is_acceptable_helloack()) { return CMD_BROKER_ERROR; } akes_nbr_delete_expired_tentatives(); entry = akes_nbr_get_sender_entry(); if(entry && entry->permanent && p_flag) { PRINTF("akes: No need to start a new session\n"); return CMD_BROKER_ERROR; } secret = AKES_SCHEME.get_secret_with_helloack_sender(packetbuf_addr(PACKETBUF_ADDR_SENDER)); if(!secret) { PRINTF("akes: No secret with HELLOACK sender\n"); return CMD_BROKER_ERROR; } /* copy challenges and generate key */ akes_nbr_copy_challenge(key, hello_challenge); akes_nbr_copy_challenge(key + AKES_NBR_CHALLENGE_LEN, payload); generate_pairwise_key(key, secret); #if ANTI_REPLAY_WITH_SUPPRESSION packetbuf_set_attr(PACKETBUF_ATTR_NEIGHBOR_INDEX, payload[AKES_NBR_CHALLENGE_LEN]); anti_replay_parse_counter(payload + AKES_NBR_CHALLENGE_LEN + 1); #endif /* ANTI_REPLAY_WITH_SUPPRESSION */ if(adaptivesec_verify(key)) { PRINTF("akes: Invalid HELLOACK\n"); return CMD_BROKER_ERROR; } is_new = 1; if(entry) { if(entry->permanent) { if( #if AKES_NBR_WITH_PAIRWISE_KEYS !memcmp(key, entry->permanent->pairwise_key, AES_128_KEY_LENGTH)) { #else /* AKES_NBR_WITH_PAIRWISE_KEYS */ !memcmp(payload, entry->permanent->helloack_challenge, AKES_NBR_CACHED_HELLOACK_CHALLENGE_LEN)) { #endif /* AKES_NBR_WITH_PAIRWISE_KEYS */ PRINTF("akes: Replayed HELLOACK\n"); return CMD_BROKER_ERROR; } else { akes_nbr_delete(entry, AKES_NBR_PERMANENT); is_new = 0; } } if(entry->tentative) { #if !AKES_NBR_WITH_PAIRWISE_KEYS if(!entry->tentative->meta->has_wait_timer) { PRINTF("akes: Awaiting acknowledgement of ACK\n"); return CMD_BROKER_ERROR; } #endif /* !AKES_NBR_WITH_PAIRWISE_KEYS */ if(ctimer_expired(&entry->tentative->meta->wait_timer)) { PRINTF("akes: Awaiting ACK\n"); return CMD_BROKER_ERROR; } else { PRINTF("akes: Skipping HELLOACK\n"); ctimer_stop(&entry->tentative->meta->wait_timer); akes_nbr_delete(entry, AKES_NBR_TENTATIVE); } } }
/*---------------------------------------------------------------------------*/ static enum cmd_broker_result on_hello(uint8_t *payload) { struct akes_nbr_entry *entry; clock_time_t waiting_period; PRINTF("akes: Received HELLO\n"); akes_nbr_delete_expired_tentatives(); entry = akes_nbr_get_sender_entry(); if(entry && entry->permanent) { #if ANTI_REPLAY_WITH_SUPPRESSION anti_replay_restore_counter(&entry->permanent->anti_replay_info); #endif /* ANTI_REPLAY_WITH_SUPPRESSION */ switch(ADAPTIVESEC_STRATEGY.verify(entry->permanent)) { case ADAPTIVESEC_VERIFY_SUCCESS: akes_nbr_prolong(entry->permanent); akes_trickle_on_fresh_authentic_hello(entry->permanent); return CMD_BROKER_CONSUMED; case ADAPTIVESEC_VERIFY_INAUTHENTIC: PRINTF("akes: Starting new session with permanent neighbor\n"); break; case ADAPTIVESEC_VERIFY_REPLAYED: PRINTF("akes: Replayed HELLO\n"); return CMD_BROKER_ERROR; } } if(leaky_bucket_is_full(&helloack_bucket)) { PRINTF("akes: Bucket is full\n"); return CMD_BROKER_ERROR; } if(entry && entry->tentative) { PRINTF("akes: Received HELLO from tentative neighbor\n"); return CMD_BROKER_ERROR; } /* Create tentative neighbor */ entry = akes_nbr_new(AKES_NBR_TENTATIVE); if(!entry) { PRINTF("akes: HELLO flood?\n"); return CMD_BROKER_ERROR; } leaky_bucket_pour(&helloack_bucket); akes_nbr_copy_challenge(entry->tentative->challenge, payload); waiting_period = adaptivesec_random_clock_time(MIN_HELLOACK_DELAY, MAX_HELLOACK_DELAY); entry->tentative->expiration_time = clock_seconds() + (waiting_period / CLOCK_SECOND) + AKES_ACK_DELAY; ctimer_set(&entry->tentative->meta->wait_timer, waiting_period, send_helloack, entry); #if !AKES_NBR_WITH_PAIRWISE_KEYS entry->tentative->meta->has_wait_timer = 1; #endif /* !AKES_NBR_WITH_PAIRWISE_KEYS */ PRINTF("akes: Will send HELLOACK in %lus\n", waiting_period / CLOCK_SECOND); return CMD_BROKER_CONSUMED; }