On Mi, 2016-09-21 at 10:32 +0200, Michael Braun wrote: > do I undertand correctly that this change also requires > nas_identifier to be the BSSID? That is correct. The code assumes that the nas_identifier matches the BSSID to be able to send requests without having prior knowledge about other APs in the network. Benjamin > Am 19.09.2016 17:47, schrieb Benjamin Berg: > > > > From: Benjamin Berg <benjamin.berg@xxxxxxxxxxxxx> > > > > This patch adds a new option to set a static key for the > > communication > > between the APs during 802.11r roaming. For this to work hostapd > > has to assume that both the nas_identifier and R1KH identifier > > match > > the MAC/BSSID of the hostapd instance. > > > > The advantage is that all APs can share a common configuration and > > roaming > > works throughout the network without each AP having a list of all > > other > > APs and a key for them. It is assumed that all APs can communicate > > on a > > common layer two network. > > > > Signed-off-by: Benjamin Berg <benjamin.berg@xxxxxxxxxxxxx> > > --- > > hostapd/config_file.c | 9 +++ > > src/ap/ap_config.h | 2 + > > src/ap/wpa_auth.h | 2 + > > src/ap/wpa_auth_ft.c | 173 > > +++++++++++++++++++++++++++++++++++++------------ > > src/ap/wpa_auth_glue.c | 2 + > > 5 files changed, 146 insertions(+), 42 deletions(-) > > > > diff --git a/hostapd/config_file.c b/hostapd/config_file.c > > index 5079f69..a43fa2f 100644 > > --- a/hostapd/config_file.c > > +++ b/hostapd/config_file.c > > @@ -2555,6 +2555,15 @@ static int hostapd_config_fill(struct > > hostapd_config *conf, > > line, pos); > > return 1; > > } > > + } else if (os_strcmp(buf, "ft_remote_key") == 0) { > > + > > + bss->ft_remote_trust_khid = 1; > > + > > + if (hexstr2bin(pos, bss->ft_remote_key, > > sizeof(bss->ft_remote_key))) > > { > > + wpa_printf(MSG_ERROR, "Invalid FT > > communication key: '%s'", pos); > > + return 1; > > + } > > + > > } else if (os_strcmp(buf, "pmk_r1_push") == 0) { > > bss->pmk_r1_push = atoi(pos); > > } else if (os_strcmp(buf, "ft_over_ds") == 0) { > > diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h > > index 8c8f7e2..5896f90 100644 > > --- a/src/ap/ap_config.h > > +++ b/src/ap/ap_config.h > > @@ -337,6 +337,8 @@ struct hostapd_bss_config { > > u32 reassociation_deadline; > > struct ft_remote_r0kh *r0kh_list; > > struct ft_remote_r1kh *r1kh_list; > > + int ft_remote_trust_khid; > > + u8 ft_remote_key[16]; > > int pmk_r1_push; > > int ft_over_ds; > > #endif /* CONFIG_IEEE80211R */ > > diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h > > index 0de8d97..cd70912 100644 > > --- a/src/ap/wpa_auth.h > > +++ b/src/ap/wpa_auth.h > > @@ -168,6 +168,8 @@ struct wpa_auth_config { > > u32 reassociation_deadline; > > struct ft_remote_r0kh *r0kh_list; > > struct ft_remote_r1kh *r1kh_list; > > + int ft_remote_trust_khid; > > + u8 ft_remote_key[16]; > > int pmk_r1_push; > > int ft_over_ds; > > #endif /* CONFIG_IEEE80211R */ > > diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c > > index 42242a5..a6e277d 100644 > > --- a/src/ap/wpa_auth_ft.c > > +++ b/src/ap/wpa_auth_ft.c > > @@ -300,30 +300,125 @@ static int wpa_ft_fetch_pmk_r1(struct > > wpa_authenticator *wpa_auth, > > return -1; > > } > > > > - > > -static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, > > - const u8 *ies, size_t ies_len, > > - const u8 *pmk_r0_name) > > +static int wpa_ft_r0kh_find_by_id(struct wpa_authenticator > > *wpa_auth, > > + const u8 *r0kh_id, > > + int r0kh_id_len, > > + u8 *addr, > > + u8 *key) > > { > > struct ft_remote_r0kh *r0kh; > > - struct ft_r0kh_r1kh_pull_frame frame, f; > > > > - r0kh = sm->wpa_auth->conf.r0kh_list; > > + /* First try to lookup in list. */ > > + r0kh = wpa_auth->conf.r0kh_list; > > while (r0kh) { > > - if (r0kh->id_len == sm->r0kh_id_len && > > - os_memcmp_const(r0kh->id, sm->r0kh_id, sm- > > >r0kh_id_len) == > > + if (r0kh->id_len == r0kh_id_len && > > + os_memcmp_const(r0kh->id, r0kh_id, > > r0kh_id_len) == > > 0) > > break; > > r0kh = r0kh->next; > > } > > if (r0kh == NULL) { > > - wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID", > > + /* If we trust the KHID to be a MAC, then use this > > instead. > > + **/ > > + if (wpa_auth->conf.ft_remote_trust_khid && > > r0kh_id_len == (3*6-1)) { > > + if (hwaddr_aton((char*) r0kh_id, addr)) { > > + return -1; > > + } > > + os_memcpy(key, wpa_auth- > > >conf.ft_remote_key, > > + sizeof(wpa_auth- > > >conf.ft_remote_key)); > > + } else { > > + return -1; > > + } > > + } else { > > + os_memcpy(key, r0kh->key, > > + sizeof(r0kh->key)); > > + os_memcpy(addr, r0kh->addr, > > + ETH_ALEN); > > + } > > + > > + return 0; > > +} > > + > > +static int wpa_ft_r0kh_find_by_addr(struct wpa_authenticator > > *wpa_auth, > > + const u8 *r0kh_addr, > > + u8 *key) > > +{ > > + struct ft_remote_r0kh *r0kh; > > + > > + /* First try to lookup in list. */ > > + r0kh = wpa_auth->conf.r0kh_list; > > + while (r0kh) { > > + if (os_memcmp_const(r0kh->addr, r0kh_addr, > > ETH_ALEN) == 0) > > + break; > > + r0kh = r0kh->next; > > + } > > + if (r0kh == NULL) { > > + /* If we trust the KHID to be a MAC, then use this > > instead. > > + **/ > > + if (wpa_auth->conf.ft_remote_trust_khid) { > > + os_memcpy(key, wpa_auth- > > >conf.ft_remote_key, > > + sizeof(wpa_auth- > > >conf.ft_remote_key)); > > + } else { > > + return -1; > > + } > > + } else { > > + os_memcpy(key, r0kh->key, > > + sizeof(r0kh->key)); > > + } > > + > > + return 0; > > +} > > + > > +static int wpa_ft_r1kh_find_by_addr(struct wpa_authenticator > > *wpa_auth, > > + const u8 *src_addr, > > + u8 *id, > > + u8 *key) > > +{ > > + struct ft_remote_r1kh *r1kh; > > + > > + /* First try to lookup in list. */ > > + r1kh = wpa_auth->conf.r1kh_list; > > + while (r1kh) { > > + if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == > > 0) > > + break; > > + r1kh = r1kh->next; > > + } > > + if (r1kh == NULL) { > > + /* If we trust the KHID to be a MAC, then use this > > instead. > > + **/ > > + if (wpa_auth->conf.ft_remote_trust_khid) { > > + os_memcpy(id, src_addr, ETH_ALEN); > > + os_memcpy(key, wpa_auth- > > >conf.ft_remote_key, > > + sizeof(wpa_auth- > > >conf.ft_remote_key)); > > + } else { > > + return -1; > > + } > > + } else { > > + os_memcpy(id, r1kh->id, ETH_ALEN); > > + os_memcpy(key, r1kh->key, > > + sizeof(r1kh->key)); > > + } > > + > > + return 0; > > +} > > + > > +static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm, > > + const u8 *ies, size_t ies_len, > > + const u8 *pmk_r0_name) > > +{ > > + macaddr r0kh_addr; > > + u8 r0kh_key[16]; > > + struct ft_r0kh_r1kh_pull_frame frame, f; > > + > > + if (wpa_ft_r0kh_find_by_id(sm->wpa_auth, sm->r0kh_id, > > sm->r0kh_id_len, > > + r0kh_addr, r0kh_key)) { > > + wpa_hexdump(MSG_DEBUG, "FT: Cannot pull PMK-R1 for > > R0KH", > > sm->r0kh_id, sm->r0kh_id_len); > > return -1; > > } > > > > wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to > > remote R0KH " > > - "address " MACSTR, MAC2STR(r0kh->addr)); > > + "address " MACSTR, MAC2STR(r0kh_addr)); > > > > os_memset(&frame, 0, sizeof(frame)); > > frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB; > > @@ -345,7 +440,7 @@ static int wpa_ft_pull_pmk_r1(struct > > wpa_state_machine *sm, > > os_memcpy(f.s1kh_id, sm->addr, ETH_ALEN); > > os_memset(f.pad, 0, sizeof(f.pad)); > > > > - if (aes_wrap(r0kh->key, sizeof(r0kh->key), > > + if (aes_wrap(r0kh_key, sizeof(r0kh_key), > > (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, > > f.nonce, frame.nonce) < 0) > > return -1; > > @@ -355,7 +450,7 @@ static int wpa_ft_pull_pmk_r1(struct > > wpa_state_machine *sm, > > if (sm->ft_pending_req_ies == NULL) > > return -1; > > > > - wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, > > sizeof(frame)); > > + wpa_ft_rrb_send(sm->wpa_auth, r0kh_addr, (u8 *) &frame, > > sizeof(frame)); > > > > return 0; > > } > > @@ -1313,7 +1408,8 @@ static int wpa_ft_rrb_rx_pull(struct > > wpa_authenticator *wpa_auth, > > struct ft_r0kh_r1kh_pull_frame f; > > const u8 *crypt; > > u8 *plain; > > - struct ft_remote_r1kh *r1kh; > > + u8 r1kh_id[FT_R1KH_ID_LEN]; > > + u8 r1kh_key[16]; > > struct ft_r0kh_r1kh_resp_frame resp, r; > > u8 pmk_r0[PMK_LEN]; > > int pairwise; > > @@ -1323,13 +1419,8 @@ static int wpa_ft_rrb_rx_pull(struct > > wpa_authenticator *wpa_auth, > > if (data_len < sizeof(f)) > > return -1; > > > > - r1kh = wpa_auth->conf.r1kh_list; > > - while (r1kh) { > > - if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == > > 0) > > - break; > > - r1kh = r1kh->next; > > - } > > - if (r1kh == NULL) { > > + > > + if (wpa_ft_r1kh_find_by_addr(wpa_auth, src_addr, r1kh_id, > > r1kh_key) > > != 0) { > > wpa_printf(MSG_DEBUG, "FT: No matching R1KH > > address found for " > > "PMK-R1 pull source address " MACSTR, > > MAC2STR(src_addr)); > > @@ -1341,7 +1432,7 @@ static int wpa_ft_rrb_rx_pull(struct > > wpa_authenticator *wpa_auth, > > plain = ((u8 *) &f) + offsetof(struct > > ft_r0kh_r1kh_pull_frame, > > nonce); > > /* aes_unwrap() does not support inplace decryption, so > > use a > > temporary > > * buffer for the data. */ > > - if (aes_unwrap(r1kh->key, sizeof(r1kh->key), > > + if (aes_unwrap(r1kh_key, sizeof(r1kh_key), > > (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8, > > crypt, plain) < 0) { > > wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK- > > R1 pull " > > @@ -1349,6 +1440,16 @@ static int wpa_ft_rrb_rx_pull(struct > > wpa_authenticator *wpa_auth, > > return -1; > > } > > > > + /* Ensure that R1KH-ID matches the expected value. */ > > + if (os_memcmp(r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN) != 0) { > > + wpa_printf(MSG_ERROR, "FT: PMK-R1 pull included > > R1KH_ID " > > + "(" MACSTR ") that did not match the > > packet " > > + "senders ID (" MACSTR ", MAC " MACSTR > > ")", > > + MAC2STR(f.r1kh_id), MAC2STR(r1kh_id), > > + MAC2STR(src_addr)); > > + return -1; > > + } > > + > > wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce", > > f.nonce, sizeof(f.nonce)); > > wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name", > > @@ -1382,7 +1483,7 @@ static int wpa_ft_rrb_rx_pull(struct > > wpa_authenticator *wpa_auth, > > r.pairwise = host_to_le16(pairwise); > > os_memset(r.pad, 0, sizeof(r.pad)); > > > > - if (aes_wrap(r1kh->key, sizeof(r1kh->key), > > + if (aes_wrap(r1kh_key, sizeof(r1kh_key), > > (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, > > r.nonce, resp.nonce) < 0) { > > os_memset(pmk_r0, 0, PMK_LEN); > > @@ -1449,7 +1550,7 @@ static int wpa_ft_rrb_rx_resp(struct > > wpa_authenticator *wpa_auth, > > struct ft_r0kh_r1kh_resp_frame f; > > const u8 *crypt; > > u8 *plain; > > - struct ft_remote_r0kh *r0kh; > > + u8 r0kh_key[16]; > > int pairwise, res; > > > > wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull > > response"); > > @@ -1457,14 +1558,8 @@ static int wpa_ft_rrb_rx_resp(struct > > wpa_authenticator *wpa_auth, > > if (data_len < sizeof(f)) > > return -1; > > > > - r0kh = wpa_auth->conf.r0kh_list; > > - while (r0kh) { > > - if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == > > 0) > > - break; > > - r0kh = r0kh->next; > > - } > > - if (r0kh == NULL) { > > - wpa_printf(MSG_DEBUG, "FT: No matching R0KH > > address found for " > > + if (wpa_ft_r0kh_find_by_addr(wpa_auth, src_addr, > > r0kh_key)) { > > + wpa_printf(MSG_DEBUG, "FT: No R0KH address found > > for " > > "PMK-R0 pull response source address " > > MACSTR, > > MAC2STR(src_addr)); > > return -1; > > @@ -1475,7 +1570,7 @@ static int wpa_ft_rrb_rx_resp(struct > > wpa_authenticator *wpa_auth, > > plain = ((u8 *) &f) + offsetof(struct > > ft_r0kh_r1kh_resp_frame, > > nonce); > > /* aes_unwrap() does not support inplace decryption, so > > use a > > temporary > > * buffer for the data. */ > > - if (aes_unwrap(r0kh->key, sizeof(r0kh->key), > > + if (aes_unwrap(r0kh_key, sizeof(r0kh_key), > > (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8, > > crypt, plain) < 0) { > > wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK- > > R1 pull " > > @@ -1518,7 +1613,7 @@ static int wpa_ft_rrb_rx_push(struct > > wpa_authenticator *wpa_auth, > > struct ft_r0kh_r1kh_push_frame f; > > const u8 *crypt; > > u8 *plain; > > - struct ft_remote_r0kh *r0kh; > > + u8 r0kh_key[16]; > > struct os_time now; > > os_time_t tsend; > > int pairwise; > > @@ -1528,14 +1623,8 @@ static int wpa_ft_rrb_rx_push(struct > > wpa_authenticator *wpa_auth, > > if (data_len < sizeof(f)) > > return -1; > > > > - r0kh = wpa_auth->conf.r0kh_list; > > - while (r0kh) { > > - if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == > > 0) > > - break; > > - r0kh = r0kh->next; > > - } > > - if (r0kh == NULL) { > > - wpa_printf(MSG_DEBUG, "FT: No matching R0KH > > address found for " > > + if (wpa_ft_r0kh_find_by_addr(wpa_auth, src_addr, > > r0kh_key)) { > > + wpa_printf(MSG_DEBUG, "FT: No R0KH address found > > for " > > "PMK-R0 push source address " MACSTR, > > MAC2STR(src_addr)); > > return -1; > > @@ -1547,7 +1636,7 @@ static int wpa_ft_rrb_rx_push(struct > > wpa_authenticator *wpa_auth, > > timestamp); > > /* aes_unwrap() does not support inplace decryption, so > > use a > > temporary > > * buffer for the data. */ > > - if (aes_unwrap(r0kh->key, sizeof(r0kh->key), > > + if (aes_unwrap(r0kh_key, sizeof(r0kh_key), > > (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8, > > crypt, plain) < 0) { > > wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK- > > R1 push from " > > diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c > > index 2142414..90e39a4 100644 > > --- a/src/ap/wpa_auth_glue.c > > +++ b/src/ap/wpa_auth_glue.c > > @@ -71,6 +71,8 @@ static void hostapd_wpa_auth_conf(struct > > hostapd_bss_config *conf, > > wconf->reassociation_deadline = conf- > > >reassociation_deadline; > > wconf->r0kh_list = conf->r0kh_list; > > wconf->r1kh_list = conf->r1kh_list; > > + wconf->ft_remote_trust_khid = conf->ft_remote_trust_khid; > > + os_memcpy(wconf->ft_remote_key, conf->ft_remote_key, > > sizeof(wconf->ft_remote_key)); > > wconf->pmk_r1_push = conf->pmk_r1_push; > > wconf->ft_over_ds = conf->ft_over_ds; > > #endif /* CONFIG_IEEE80211R */ > > _______________________________________________ > Hostap mailing list > Hostap@xxxxxxxxxxxxxxxxxxx > http://lists.infradead.org/mailman/listinfo/hostap >
Attachment:
signature.asc
Description: This is a digitally signed message part
_______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap