Skip to content

Commit

Permalink
Added check for network name and DODAG ID IID (EUI-64) (ARMmbed#2373)
Browse files Browse the repository at this point in the history
- When using stored keys on NVM, supplicant now compares that
both the PAN ID and network name of the BR matches to keys.
- When RPL completes, and bootstrap indicates that to supplicant,
bootstrap now includes the BR EUI-64 from DODAG ID to indication.
If supplicant detects that BR EUI-64 does not match to keys,
it destroyes the keys. Also the BR EUI-64 received from bootstrap is
sent on EA-IE to nodes authenticating through the node. This
corrects the case when PAN ID and network name of BR stay the
same but EUI-64 changes.
  • Loading branch information
Mika Leppänen authored May 18, 2020
1 parent ee45f4b commit 3b2d906
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 23 deletions.
4 changes: 2 additions & 2 deletions source/6LoWPAN/ws/ws_bootstrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -2279,8 +2279,8 @@ static void ws_bootstrap_rpl_callback(rpl_event_t event, void *handle)
ws_eapol_relay_start(cur, EAPOL_RELAY_SOCKET_PORT, dodag_info.dodag_id, EAPOL_RELAY_SOCKET_PORT);
// Set network information to PAE
ws_pae_controller_nw_info_set(cur, cur->ws_info->network_pan_id, cur->ws_info->cfg->gen.network_name);
// Network key is valid
ws_pae_controller_nw_key_valid(cur);
// Network key is valid, indicate border router IID to controller
ws_pae_controller_nw_key_valid(cur, &dodag_info.dodag_id[8]);

// After successful DAO ACK connection to border router is verified
cur->ws_info->pan_timeout_timer = cur->ws_info->cfg->timing.pan_timeout;
Expand Down
6 changes: 3 additions & 3 deletions source/6LoWPAN/ws/ws_pae_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ int8_t ws_pae_controller_authenticate(protocol_interface_info_entry_t *interface
return 0;
}

if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64) < 0) {
if (ws_pae_supp_authenticate(controller->interface_ptr, controller->target_pan_id, controller->target_eui_64, controller->sec_keys_nw_info.network_name) < 0) {
controller->auth_completed(interface_ptr, AUTH_RESULT_ERR_UNSPEC, controller->target_eui_64);
}
#endif
Expand Down Expand Up @@ -327,7 +327,7 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr
}
}

int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
{
if (!interface_ptr) {
return -1;
Expand All @@ -338,7 +338,7 @@ int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface
return -1;
}

return ws_pae_supp_nw_key_valid(interface_ptr);
return ws_pae_supp_nw_key_valid(interface_ptr, br_iid);
}

static int8_t ws_pae_controller_nw_key_check_and_insert(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *gtks)
Expand Down
5 changes: 3 additions & 2 deletions source/6LoWPAN/ws/ws_pae_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,12 +249,13 @@ int8_t ws_pae_controller_nw_info_set(protocol_interface_info_entry_t *interface_
* ws_pae_controller_nw_key_valid network key is valid i.e. used successfully on bootstrap
*
* \param interface_ptr interface
* \param br_iid border router IID for which the keys are valid
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr);
int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid);

/**
* ws_pae_controller_border_router_addr_write write border router address
Expand All @@ -278,7 +279,7 @@ int8_t ws_pae_controller_border_router_addr_write(protocol_interface_info_entry_
* \return >= 0 success
*
*/
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64);
int8_t ws_pae_controller_border_router_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *iid);

/**
* ws_pae_controller_gtk_update update GTKs (test interface)
Expand Down
57 changes: 43 additions & 14 deletions source/6LoWPAN/ws/ws_pae_supp.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,8 @@ typedef struct {
uint16_t initial_key_retry_timer; /**< Timer to trigger initial EAPOL-Key 1st retry */
trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */
trickle_params_t auth_trickle_params; /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap */
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap start */
uint8_t comp_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap after bootstrap completed */
sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */
sec_timer_cfg_t *sec_timer_cfg; /**< Timer configuration */
sec_prot_cfg_t *sec_prot_cfg; /**< Protocol Configuration */
Expand All @@ -106,8 +107,9 @@ typedef struct {
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
bool auth_requested : 1; /**< Authentication has been requested by the bootstrap */
bool timer_running : 1; /**< Timer is running */
bool new_br_eui_64_set : 1; /**< Border router address has been set */
bool new_br_eui_64_set : 1; /**< Border router address has been set after bootstrap start */
bool new_br_eui_64_fresh : 1; /**< Border router address is fresh (set during this authentication attempt) */
bool comp_br_eui_64_set : 1; /**< Border router address has been set after bootstrap completed */
bool entry_address_active: 1; /**< EAPOL target address is set */
bool tx_failure_on_initial_key: 1; /**< TX failure has happened on initial EAPOL-key sequence */
} pae_supp_t;
Expand All @@ -124,7 +126,7 @@ static void ws_pae_supp_free(pae_supp_t *pae_supp);
static void ws_pae_supp_authenticate_response(pae_supp_t *pae_supp, auth_result_e result);
static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp);
static void ws_pae_supp_nvm_update(pae_supp_t *pae_supp);
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id);
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name);
static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp);
static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr);
static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data);
Expand Down Expand Up @@ -180,24 +182,25 @@ static bool ws_pae_supp_address_is_set(pae_supp_t *pae_supp)
return pae_supp->entry_address_active;
}

int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64)
int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64, char *dest_network_name)
{
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) {
return -1;
}

if (ws_pae_supp_nw_keys_valid_check(pae_supp, dest_pan_id) >= 0) {
if (ws_pae_supp_nw_keys_valid_check(pae_supp, dest_pan_id, dest_network_name) >= 0) {
pae_supp->auth_completed(interface_ptr, AUTH_RESULT_OK, NULL);
return 0;
}

// Delete GTKs
sec_prot_keys_gtks_init(pae_supp->sec_keys_nw_info->gtks);

/* PAN ID has changed, delete key data associated with border router
/* Network name or PAN ID has changed, delete key data associated with border router
i.e PMK, PTK, EA-IE data (border router EUI-64) */
if (pae_supp->sec_keys_nw_info->key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info->key_pan_id != dest_pan_id) {
if (strcmp(pae_supp->sec_keys_nw_info->network_name, dest_network_name) != 0 ||
(pae_supp->sec_keys_nw_info->key_pan_id != 0xFFFF && pae_supp->sec_keys_nw_info->key_pan_id != dest_pan_id)) {
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
Expand All @@ -207,6 +210,7 @@ int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr,

// Prepare to receive new border router address
pae_supp->new_br_eui_64_fresh = false;
pae_supp->comp_br_eui_64_set = false;

// Stores target/parent address
kmp_address_init(KMP_ADDR_EUI_64, &pae_supp->target_addr, dest_eui_64);
Expand Down Expand Up @@ -247,24 +251,46 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
return -1;
}

// Check if there is border router EUI-64 on used on 4WH PTK generation
uint8_t *br_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);
if (!br_eui_64) {
return -1;
// Check if there is border router EUI-64 indicated by the bootstrap when bootstrap completed
if (!pae_supp->comp_br_eui_64_set) {
return -1;
}
br_eui_64 = pae_supp->comp_br_eui_64;
}

memcpy(eui_64, br_eui_64, 8);

return 0;
}

int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr)
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid)
{
pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr);
if (!pae_supp) {
return -1;
}

tr_info("NW key valid");
tr_info("NW key valid indication");

// Store border router EUI-64 received on bootstrap complete
memcpy(pae_supp->comp_br_eui_64, br_iid, 8);
pae_supp->comp_br_eui_64[0] ^= 0x02;
pae_supp->comp_br_eui_64_set = true;

// Get the EUI-64 used on 4WH handshake PTK generation
uint8_t *ptk_eui_64 = sec_prot_keys_ptk_eui_64_get(&pae_supp->entry.sec_keys);

/* If border router EUI-64 received on bootstrap complete does not match to
EUI-64 stored with keys, delete keys */
if (memcmp(ptk_eui_64, pae_supp->comp_br_eui_64, 8) != 0) {
tr_warn("Delete keys: PTK EUI-64 %s does not match to BR EUI-64 %s", tr_array(ptk_eui_64, 8), tr_array(pae_supp->comp_br_eui_64, 8));
sec_prot_keys_pmk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_delete(&pae_supp->entry.sec_keys);
sec_prot_keys_ptk_eui_64_delete(&pae_supp->entry.sec_keys);
}

// Stored keys are valid
pae_supp->nw_keys_used_cnt = 0;
Expand Down Expand Up @@ -461,7 +487,7 @@ static int8_t ws_pae_supp_initial_key_send(pae_supp_t *pae_supp)
return 0;
}

static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id)
static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan_id, char *dest_network_name)
{
// Checks how many times authentication has been tried with current network keys
if (pae_supp->nw_keys_used_cnt >= STORED_KEYS_MAXIMUM_USE_COUNT) {
Expand All @@ -476,9 +502,11 @@ static int8_t ws_pae_supp_nw_keys_valid_check(pae_supp_t *pae_supp, uint16_t pan
return -1;
}

/* Checks if keys match to PAN ID and that needed keys exists (PMK, PTK and a GTK),
and calls inserts function that will update the network keys as needed */
if ((pan_id == pae_supp->sec_keys_nw_info->key_pan_id) &&
/* Checks if keys match to network name and PAN ID and that needed keys exists (PMK,
PTK and a GTK), and calls inserts function that will update the network keys as
needed */
if ((strcmp(dest_network_name, pae_supp->sec_keys_nw_info->network_name) == 0 &&
pan_id == pae_supp->sec_keys_nw_info->key_pan_id) &&
(sec_prot_keys_gtk_count(pae_supp->sec_keys_nw_info->gtks) > 0) &&
(sec_prot_keys_pmk_get(&pae_supp->entry.sec_keys) != NULL) &&
(sec_prot_keys_ptk_get(&pae_supp->entry.sec_keys) != NULL)) {
Expand Down Expand Up @@ -542,6 +570,7 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
pae_supp->timer_running = false;
pae_supp->new_br_eui_64_set = false;
pae_supp->new_br_eui_64_fresh = false;
pae_supp->comp_br_eui_64_set = false;
pae_supp->entry_address_active = false;

ws_pae_lib_supp_init(&pae_supp->entry);
Expand Down
6 changes: 4 additions & 2 deletions source/6LoWPAN/ws/ws_pae_supp.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ void ws_pae_supp_slow_timer(uint16_t seconds);
* \param interface_ptr interface
* \param dest_pan_id EAPOL target PAN ID
* \param dest_eui_64 EAPOL target
* \param dest_network_name EAPOL target network name
*
* \return < 0 failure
* \return 0 authentication done, continue
* \return > 0 authentication started
*
*/
int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64);
int8_t ws_pae_supp_authenticate(protocol_interface_info_entry_t *interface_ptr, uint16_t dest_pan_id, uint8_t *dest_eui_64, char *dest_network_name);

/**
* ws_pae_supp_border_router_addr_write write border router address
Expand Down Expand Up @@ -117,12 +118,13 @@ int8_t ws_pae_supp_border_router_addr_read(protocol_interface_info_entry_t *inte
* ws_pae_supp_nw_key_valid network key is valid i.e. used successfully on bootstrap
*
* \param interface_ptr interface
* \param br_iid border router IID for which the keys are valid
*
* \return < 0 failure
* \return >= 0 success
*
*/
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr);
int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid);

/**
* ws_pae_supp_gtk_hash_update GTK hash has been updated (on PAN configuration)
Expand Down

0 comments on commit 3b2d906

Please sign in to comment.