FT: Derive PMK-R1 locally if requested PMKR0Name is found
Derive PMK-R1 locally if the derived PMKR1Name is not found from the local cache, but the request is for a key that was originally generated locally (R0KH-ID matches) and the PMKR0Name is found in the local cache. This was apparently not hit in the previously used FT sequences, but this is useful to have available if a PMK-R1 entry is dropped from the local cache before PMK-R0. Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
This commit is contained in:
parent
1dc0945cc9
commit
4ddca8142e
1 changed files with 54 additions and 0 deletions
|
@ -2055,6 +2055,43 @@ static int wpa_ft_set_key_mgmt(struct wpa_state_machine *sm,
|
|||
}
|
||||
|
||||
|
||||
static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_state_machine *sm,
|
||||
const u8 *r0kh_id, size_t r0kh_id_len,
|
||||
const u8 *req_pmk_r0_name,
|
||||
const u8 *req_pmk_r1_name,
|
||||
u8 *out_pmk_r1, int *out_pairwise)
|
||||
{
|
||||
struct wpa_auth_config *conf = &wpa_auth->conf;
|
||||
const struct wpa_ft_pmk_r0_sa *r0;
|
||||
u8 pmk_r1_name[WPA_PMK_NAME_LEN];
|
||||
|
||||
if (conf->r0_key_holder_len != r0kh_id_len ||
|
||||
os_memcmp(conf->r0_key_holder, r0kh_id, conf->r0_key_holder_len) !=
|
||||
0)
|
||||
return -1; /* not our R0KH-ID */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "FT: STA R0KH-ID matching local configuration");
|
||||
if (wpa_ft_fetch_pmk_r0(sm->wpa_auth, sm->addr, req_pmk_r0_name, &r0) <
|
||||
0)
|
||||
return -1; /* no matching PMKR0Name in local cache */
|
||||
|
||||
wpa_printf(MSG_DEBUG, "FT: Requested PMKR0Name found in local cache");
|
||||
|
||||
if (wpa_derive_pmk_r1(r0->pmk_r0, r0->pmk_r0_name, conf->r1_key_holder,
|
||||
sm->addr, out_pmk_r1, pmk_r1_name) < 0)
|
||||
return -1;
|
||||
wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, PMK_LEN);
|
||||
wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
|
||||
|
||||
wpa_ft_store_pmk_r1(wpa_auth, sm->addr, out_pmk_r1, pmk_r1_name,
|
||||
sm->pairwise);
|
||||
|
||||
*out_pairwise = sm->pairwise;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
||||
const u8 *ies, size_t ies_len,
|
||||
u8 **resp_ies, size_t *resp_ies_len)
|
||||
|
@ -2132,8 +2169,22 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||
wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
|
||||
if (wpa_ft_psk_pmk_r1(sm, pmk_r1_name, pmk_r1, &pairwise) < 0)
|
||||
return WLAN_STATUS_INVALID_PMKID;
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: Generated PMK-R1 for FT-PSK locally");
|
||||
} else if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name,
|
||||
pmk_r1, &pairwise) < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: No PMK-R1 available in local cache for the requested PMKR1Name");
|
||||
if (wpa_ft_local_derive_pmk_r1(sm->wpa_auth, sm,
|
||||
parse.r0kh_id, parse.r0kh_id_len,
|
||||
parse.rsn_pmkid,
|
||||
pmk_r1_name, pmk_r1, &pairwise)
|
||||
== 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: Generated PMK-R1 based on local PMK-R0");
|
||||
goto pmk_r1_derived;
|
||||
}
|
||||
|
||||
if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FT: Did not have matching PMK-R1 and either unknown or blocked R0KH-ID or NAK from R0KH");
|
||||
|
@ -2141,8 +2192,11 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
|
|||
}
|
||||
|
||||
return -1; /* Status pending */
|
||||
} else {
|
||||
wpa_printf(MSG_DEBUG, "FT: Found PMKR1Name from local cache");
|
||||
}
|
||||
|
||||
pmk_r1_derived:
|
||||
wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN);
|
||||
sm->pmk_r1_name_valid = 1;
|
||||
os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
|
||||
|
|
Loading…
Reference in a new issue