Add support for Group formation and connection between p2p go and p2p client on successful go negotiation. Signed-off-by: Shivani Baranwal <quic_shivbara@xxxxxxxxxxx> --- src/ap/ap_drv_ops.c | 23 +++++ src/ap/ap_drv_ops.h | 5 ++ src/ap/ieee802_11.c | 15 ++++ src/ap/ieee802_11.h | 2 + src/ap/wpa_auth_ie.c | 17 ++++ src/p2p/p2p.c | 59 +++++++++++-- src/p2p/p2p.h | 22 ++++- src/p2p/p2p_group.c | 50 ++++++++++- src/p2p/p2p_i.h | 2 + wpa_supplicant/p2p_supplicant.c | 180 +++++++++++++++++++++++++++++++++++----- 10 files changed, 346 insertions(+), 29 deletions(-) diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index c473491..e22efeb 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -1250,3 +1250,26 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd, return hapd->driver->set_secure_ranging_ctx(hapd->drv_priv, ¶ms); } #endif /* CONFIG_PASN */ + +int hostapd_drv_add_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params) +{ + if (!hapd->driver || !hapd->driver->add_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->add_pmkid(hapd->drv_priv, params); +} + +int hostapd_drv_remove_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params) +{ + if (!hapd->driver || !hapd->driver->remove_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->remove_pmkid(hapd->drv_priv, params); +} + +int hostapd_drv_flush_pmkid(struct hostapd_data *hapd) +{ + if (!hapd->driver || !hapd->driver->flush_pmkid || !hapd->drv_priv) + return 0; + return hapd->driver->flush_pmkid(hapd->drv_priv); +} diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index d7e79c8..de7c4af 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -148,6 +148,11 @@ int hostapd_drv_set_secure_ranging_ctx(struct hostapd_data *hapd, u32 cipher, u8 key_len, const u8 *key, u8 ltf_keyseed_len, const u8 *ltf_keyseed, u32 action); +int hostapd_drv_add_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params); +int hostapd_drv_remove_pmkid(struct hostapd_data *hapd, + struct wpa_pmkid_params *params); +int hostapd_drv_flush_pmkid(struct hostapd_data *hapd); #include "drivers/driver.h" diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 3c5a8dd..5973056 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -8295,4 +8295,19 @@ u8 * hostapd_eid_mbssid(struct hostapd_data *hapd, u8 *eid, u8 *end, return eid; } + +int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk, + size_t pmk_len, const u8 *pmkid, int akmp) +{ + struct wpa_pmkid_params params; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = bssid; + params.pmkid = pmkid; + params.pmk = pmk; + params.pmk_len = pmk_len; + + return hostapd_drv_add_pmkid(hapd, ¶ms); +} + #endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/src/ap/ieee802_11.h b/src/ap/ieee802_11.h index dd4995f..b1a3edf 100644 --- a/src/ap/ieee802_11.h +++ b/src/ap/ieee802_11.h @@ -263,5 +263,7 @@ int hostapd_process_assoc_ml_info(struct hostapd_data *hapd, const u8 *ies, size_t ies_len, bool reassoc, int tx_link_status, bool offload); +int hostapd_add_pmkid(struct hostapd_data *hapd, const u8 *bssid, const u8 *pmk, + size_t pmk_len, const u8 *pmkid, int akmp); #endif /* IEEE802_11_H */ diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 43d9c1d..bd1bd64 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -499,6 +499,9 @@ static u32 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt) #endif /* CONFIG_SAE_PK */ } + // FIXME: Should not set it by default + capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E); + if (conf->secure_ltf) capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF); if (conf->secure_rtt) @@ -1251,6 +1254,20 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, pmkid = sm->pmksa->pmkid; break; } + + if (!is_zero_ether_addr(sm->p2p_dev_addr)) { + wpa_hexdump(MSG_DEBUG, "RSN IE: P2P DEV PMKID", + &data.pmkid[i * PMKID_LEN], PMKID_LEN); + sm->pmksa = + pmksa_cache_auth_get(wpa_auth->pmksa, + sm->p2p_dev_addr, + &data.pmkid[i * PMKID_LEN]); + if (sm->pmksa) { + pmkid = sm->pmksa->pmkid; + break; + } + } + } for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && i < data.num_pmkid; i++) { diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index ab3ccc1..8f3d76e 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -253,6 +253,7 @@ void p2p_go_neg_failed(struct p2p_data *p2p, int status) os_memset(&res, 0, sizeof(res)); res.status = status; + res.p2p2 = peer->p2p2; os_memcpy(res.peer_device_addr, peer->info.p2p_device_addr, ETH_ALEN); os_memcpy(res.peer_interface_addr, peer->intended_addr, ETH_ALEN); p2p->cfg->go_neg_completed(p2p->cfg->cb_ctx, &res); @@ -1072,7 +1073,8 @@ static void p2p_search(struct p2p_data *p2p) res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq, p2p->num_req_dev_types, p2p->req_dev_types, - p2p->find_dev_id, pw_id, p2p->include_6ghz); + p2p->find_dev_id, pw_id, p2p->include_6ghz, + false); if (res < 0) { p2p_dbg(p2p, "Scan request schedule failed"); p2p_continue_find(p2p); @@ -1299,7 +1301,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p->num_req_dev_types, p2p->req_dev_types, dev_id, DEV_PW_DEFAULT, - p2p->include_6ghz); + p2p->include_6ghz, false); break; } /* fall through */ @@ -1307,13 +1309,15 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0, p2p->num_req_dev_types, p2p->req_dev_types, dev_id, - DEV_PW_DEFAULT, p2p->include_6ghz); + DEV_PW_DEFAULT, p2p->include_6ghz, + false); break; case P2P_FIND_ONLY_SOCIAL: res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0, p2p->num_req_dev_types, p2p->req_dev_types, dev_id, - DEV_PW_DEFAULT, p2p->include_6ghz); + DEV_PW_DEFAULT, p2p->include_6ghz, + false); break; default: return -1; @@ -1861,6 +1865,16 @@ int p2p_go_params(struct p2p_data *p2p, struct p2p_go_neg_results *params) } p2p->ssid_set = 0; + params->cipher = WPA_CIPHER_CCMP; + if (p2p->cfg->pairing_config.pasn_type & 0xc) + params->cipher |= WPA_CIPHER_GCMP_256; + + if (params->p2p2) { + params->password_len = p2p->cfg->dev_password_len; + memcpy(params->password, p2p->cfg->dev_password, + p2p->cfg->dev_password_len); + } + p2p_random(params->passphrase, p2p->cfg->passphrase_len); params->passphrase[p2p->cfg->passphrase_len] = '\0'; return 0; @@ -1934,8 +1948,43 @@ void p2p_go_complete(struct p2p_data *p2p, struct p2p_device *peer) peer->go_neg_conf = NULL; #ifdef CONFIG_PASN - if (peer->p2p2 && peer->pasn) + if (peer->p2p2 && peer->pasn) { + res.p2p2 = peer->p2p2; + res.akmp = peer->pasn->akmp; + res.cipher = peer->pasn->cipher; + + if (res.akmp == WPA_KEY_MGMT_PASN) { + if (go) { + res.password_len = p2p->cfg->dev_password_len; + memcpy(res.password, p2p->cfg->dev_password, + res.password_len); + } else { + if (!peer->info.password_len) { + p2p_dbg(p2p, "Password Invalid for P2P2 group formation"); + return; + } + res.password_len = peer->info.password_len; + memcpy(res.password, peer->info.password, + res.password_len); + } + } else if (res.akmp == WPA_KEY_MGMT_SAE) { + res.password_len = peer->password_len; + memcpy(res.password, peer->password, res.password_len); + if (peer->role == P2P_ROLE_PAIRING_INITIATOR) { + pasn_initiator_pmksa_cache_get(peer->pasn->pmksa, + peer->pasn->peer_addr, + res.pmkid, res.pmk, + &res.pmk_len); + } else { + pasn_responder_pmksa_cache_get(peer->pasn->pmksa, + peer->pasn->peer_addr, + res.pmkid, res.pmk, + &res.pmk_len); + } + } + wpa_pasn_reset(peer->pasn); + } #endif /* CONFIG_PASN */ p2p_set_state(p2p, P2P_PROVISIONING); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index db2052f..65e2e0d 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -11,6 +11,7 @@ #include "common/ieee802_11_defs.h" #include "wps/wps.h" +#include "common/wpa_common.h" #define DEVICE_IDENTITY_KEY_MAX_LEN 64 #define DEVICE_IDENTITY_KEY_LEN 16 @@ -181,6 +182,22 @@ struct p2p_go_neg_results { * peer_config_timeout - Peer configuration timeout (in 10 msec units) */ unsigned int peer_config_timeout; + + bool p2p2; + + int akmp; + + int cipher; + + u8 pmkid[PMKID_LEN]; + + u8 pmk[PMK_LEN_MAX]; + + size_t pmk_len; + + char password[100]; + + size_t password_len; }; struct p2ps_provision { @@ -779,7 +796,7 @@ struct p2p_config { int (*p2p_scan)(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id, u16 pw_id, - bool include_6ghz); + bool include_6ghz, bool p2p2); /** * send_probe_resp - Transmit a Probe Response frame @@ -1993,6 +2010,7 @@ struct p2p_group_config { * p2p_group_init - Initialize P2P group * @p2p: P2P module context from p2p_init() * @config: P2P group configuration (will be freed by p2p_group_deinit()) + * @p2p2: parameter to indicate that the group formed using p2p2 * Returns: Pointer to private data or %NULL on failure * * This function is used to initialize per-group P2P module context. Currently, @@ -2000,7 +2018,7 @@ struct p2p_group_config { * create an instance of this per-group information. */ struct p2p_group * p2p_group_init(struct p2p_data *p2p, - struct p2p_group_config *config); + struct p2p_group_config *config, bool p2p2); /** * p2p_group_deinit - Deinitialize P2P group diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index c036f92..4822c28 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -40,11 +40,12 @@ struct p2p_group { int beacon_update; struct wpabuf *noa; struct wpabuf *wfd_ie; + bool p2p2; }; struct p2p_group * p2p_group_init(struct p2p_data *p2p, - struct p2p_group_config *config) + struct p2p_group_config *config, bool p2p2) { struct p2p_group *group, **groups; @@ -62,6 +63,7 @@ struct p2p_group * p2p_group_init(struct p2p_data *p2p, p2p->groups = groups; group->p2p = p2p; + group->p2p2 = p2p2; group->cfg = config; group->group_formation = 1; group->beacon_update = 1; @@ -205,11 +207,28 @@ static struct wpabuf * p2p_group_encaps_probe_resp(struct wpabuf *subelems) } +struct wpabuf * p2p_group_build_p2p2_ie(struct p2p_data *p2p, + struct wpabuf *p2p2_ie, int freq) +{ + u8 *len; + + wpabuf_put_u8(p2p2_ie, WLAN_EID_VENDOR_SPECIFIC); + len = wpabuf_put(p2p2_ie, 1); + wpabuf_put_be32(p2p2_ie, P2P2_IE_VENDOR_TYPE); + wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header"); + p2p_buf_add_pcea(p2p2_ie, p2p); + *len = (u8 *)wpabuf_put(p2p2_ie, 0) - len - 1; + + return p2p2_ie; +} + + static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) { struct wpabuf *ie; u8 *len; size_t extra = 0; + struct wpabuf *p2p2_ie; #ifdef CONFIG_WIFI_DISPLAY if (group->p2p->wfd_ie_beacon) @@ -220,7 +239,7 @@ static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]) extra += wpabuf_len(group->p2p->vendor_elem[VENDOR_ELEM_BEACON_P2P_GO]); - ie = wpabuf_alloc(257 + extra); + ie = wpabuf_alloc(500 + extra); if (ie == NULL) return NULL; @@ -240,6 +259,15 @@ static struct wpabuf * p2p_group_build_beacon_ie(struct p2p_group *group) p2p_group_add_noa(ie, group->noa); p2p_buf_update_ie_hdr(ie, len); + if (group->p2p2) { + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return NULL; + + p2p_group_build_p2p2_ie(group->p2p, p2p2_ie, group->cfg->freq); + ie = wpabuf_concat(p2p2_ie, ie); + } + return ie; } @@ -443,6 +471,7 @@ void p2p_group_buf_add_id(struct p2p_group *group, struct wpabuf *buf) static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) { struct wpabuf *p2p_subelems, *ie; + struct wpabuf *p2p2_ie; p2p_subelems = wpabuf_alloc(500); if (p2p_subelems == NULL) @@ -474,7 +503,14 @@ static struct wpabuf * p2p_group_build_probe_resp_ie(struct p2p_group *group) ie = wpabuf_concat(wfd, ie); } #endif /* CONFIG_WIFI_DISPLAY */ + if (group->p2p2) { + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return NULL; + p2p_group_build_p2p2_ie(group->p2p, p2p2_ie, group->cfg->freq); + ie = wpabuf_concat(p2p2_ie, ie); + } return ie; } @@ -648,6 +684,7 @@ struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status) struct wpabuf *resp; u8 *rlen; size_t extra = 0; + struct wpabuf *p2p2_ie; #ifdef CONFIG_WIFI_DISPLAY if (group->wfd_ie) @@ -683,6 +720,15 @@ struct wpabuf * p2p_group_assoc_resp_ie(struct p2p_group *group, u8 status) p2p_buf_add_status(resp, status); p2p_buf_update_ie_hdr(resp, rlen); + if (group->p2p2) { + p2p2_ie = wpabuf_alloc(255); + if (!p2p2_ie) + return NULL; + + p2p_group_build_p2p2_ie(group->p2p, p2p2_ie, group->cfg->freq); + resp = wpabuf_concat(p2p2_ie, resp); + } + return resp; } diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index e0d2ee0..440ed1f 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -926,6 +926,8 @@ void p2p_buf_add_pref_channel_list(struct wpabuf *buf, unsigned int size); struct wpabuf *p2p_encaps_p2p_vendor_ie(struct p2p_data *p2p, struct wpabuf *subelems, u32 ie_type); +struct wpabuf * p2p_group_build_p2p2_ie(struct p2p_data *p2p, + struct wpabuf *p2p2_ie, int freq); /* p2p_sd.c */ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p, diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 0cffb99..71aaeba 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -426,11 +426,11 @@ static int wpas_p2p_search_social_channel(struct wpa_supplicant *wpa_s, static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id, u16 pw_id, - bool include_6ghz) + bool include_6ghz, bool p2p2) { struct wpa_supplicant *wpa_s = ctx; struct wpa_driver_scan_params *params = NULL; - struct wpabuf *wps_ie, *ies; + struct wpabuf *wps_ie = NULL, *ies; unsigned int num_channels = 0; int social_channels_freq[] = { 2412, 2437, 2462, 60480 }; size_t ielen; @@ -459,11 +459,16 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, params->ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; wpa_s->wps->dev.p2p = 1; - wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev, - wpa_s->wps->uuid, WPS_REQ_ENROLLEE, - num_req_dev_types, req_dev_types); - if (wps_ie == NULL) - goto fail; + + if (!p2p2) { + wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev, + wpa_s->wps->uuid, + WPS_REQ_ENROLLEE, + num_req_dev_types, + req_dev_types); + if (wps_ie == NULL) + goto fail; + } /* * In case 6 GHz channels are requested as part of the P2P scan, only @@ -514,13 +519,20 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, } ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { + + if (wps_ie) + ielen += wpabuf_len(wps_ie); + + ies = wpabuf_alloc(ielen); + if (!ies) { wpabuf_free(wps_ie); goto fail; } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); + + if (wps_ie) { + wpabuf_put_buf(ies, wps_ie); + wpabuf_free(wps_ie); + } bands = wpas_get_bands(wpa_s, params->freqs); p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands); @@ -1757,6 +1769,80 @@ static int wpas_copy_go_neg_results(struct wpa_supplicant *wpa_s, return 0; } +static void wpas_start_gc(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *res) +{ + struct wpa_ssid *ssid; + + if (!res->ssid_len) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: SSID info not present"); + return; + } + + wpa_s->group_formation_reported = 0; + wpa_printf(MSG_DEBUG, "P2P: Start connect for peer " MACSTR + " dev_addr " MACSTR, + MAC2STR(res->peer_interface_addr), + MAC2STR(res->peer_device_addr)); + wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start connect for SSID", + res->ssid, res->ssid_len); + wpa_supplicant_ap_deinit(wpa_s); + wpas_copy_go_neg_results(wpa_s, res); + + ssid = wpa_config_add_network(wpa_s->conf); + if (ssid == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not add network for Client"); + return; + } + os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN); + wpa_config_set_network_defaults(ssid); + ssid->temporary = 1; + ssid->p2p_group = 1; + + ssid->ssid = os_zalloc(res->ssid_len); + if (!ssid->ssid) + return; + + ssid->ssid_len = res->ssid_len; + os_memcpy(ssid->ssid, res->ssid, ssid->ssid_len); + + memcpy(ssid->bssid, res->peer_interface_addr, ETH_ALEN); + + if (res->akmp == WPA_KEY_MGMT_PASN) { + ssid->auth_alg = WPA_AUTH_ALG_SAE; + ssid->sae_password = os_strdup(res->password); + } else if (res->akmp == WPA_KEY_MGMT_SAE) { + ssid->auth_alg = WPA_AUTH_ALG_OPEN; + ssid->sae_password = os_strdup(res->password); + wpa_sm_set_pmk(wpa_s->wpa, res->pmk, res->pmk_len, + res->pmkid, res->peer_interface_addr); + } + + if (res->psk_set) { + os_memcpy(ssid->psk, res->psk, 32); + ssid->psk_set = 1; + } + ssid->proto = WPA_PROTO_RSN; + ssid->key_mgmt = WPA_KEY_MGMT_SAE; + ssid->pairwise_cipher = WPA_CIPHER_CCMP; + ssid->group_cipher = WPA_CIPHER_CCMP; + if (res->cipher) { + ssid->pairwise_cipher |= res->cipher; + } + ssid->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + wpa_s->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + ssid->disabled = 0; + wpa_s->show_group_started = 1; + wpa_s->p2p_in_invitation = 1; + wpa_s->p2p_go_group_formation_completed = 0; + wpa_s->global->p2p_group_formation = wpa_s; + + wpa_s->current_ssid = ssid; + wpa_supplicant_update_scan_results(wpa_s, res->peer_interface_addr); + wpa_supplicant_select_network(wpa_s, ssid); +} + static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s, struct p2p_go_neg_results *res) @@ -1892,6 +1978,9 @@ static void p2p_go_configured(void *ctx, void *data) struct wpa_supplicant *wpa_s = ctx; struct p2p_go_neg_results *params = data; struct wpa_ssid *ssid; + struct sta_info sta; + struct sae_data *sae; + struct hostapd_data *hapd; wpa_s->ap_configured_cb = NULL; wpa_s->ap_configured_cb_ctx = NULL; @@ -1901,6 +1990,26 @@ static void p2p_go_configured(void *ctx, void *data) "P2P: p2p_go_configured() called with wpa_s->go_params == NULL"); return; } + if (wpa_s->ap_iface && params->p2p2 && + params->akmp == WPA_KEY_MGMT_SAE) { + hapd = wpa_s->ap_iface->bss[0]; + memset(&sta, 0, sizeof(struct sta_info)); + memcpy(sta.addr, params->peer_device_addr, ETH_ALEN); + sae = os_zalloc(sizeof(struct sae_data)); + if (sae) { + sta.sae = sae; + memcpy(sta.sae->pmkid, params->pmkid, PMKID_LEN); + wpa_auth_pmksa_add_sae(hapd->wpa_auth, + params->peer_device_addr, + params->pmk, params->pmk_len, + params->pmkid, WPA_KEY_MGMT_SAE); + hostapd_add_pmkid(hapd, params->peer_device_addr, + params->pmk, params->pmk_len, + params->pmkid, WPA_KEY_MGMT_SAE); + memset(&sta, 0, sizeof(struct sta_info)); + os_free(sae); + } + } p2p_go_save_group_common_freqs(wpa_s, params); p2p_go_dump_common_freqs(wpa_s); @@ -1967,13 +2076,21 @@ static void p2p_go_configured(void *ctx, void *data) return; } - wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning"); if (wpa_supplicant_ap_mac_addr_filter(wpa_s, params->peer_interface_addr)) { wpa_printf(MSG_DEBUG, "P2P: Failed to setup MAC address " "filtering"); return; } + + if (params->p2p2) { + wpas_group_formation_completed(wpa_s, 1, 0); + wpa_printf(MSG_DEBUG, "P2P2: Group formation completed, " + "First connection in progress"); + goto out; + } + + wpa_printf(MSG_DEBUG, "P2P: Setting up WPS for GO provisioning"); if (params->wps_method == WPS_PBC) { wpa_supplicant_ap_wps_pbc(wpa_s, params->peer_interface_addr, params->peer_device_addr); @@ -1994,6 +2111,7 @@ static void p2p_go_configured(void *ctx, void *data) } else if (wpa_s->p2p_pin[0]) wpa_supplicant_ap_wps_pin(wpa_s, params->peer_interface_addr, wpa_s->p2p_pin, NULL, 0, 0); +out: os_free(wpa_s->go_params); wpa_s->go_params = NULL; } @@ -2076,9 +2194,9 @@ int wpas_p2p_try_edmg_channel(struct wpa_supplicant *wpa_s, } -static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, - struct p2p_go_neg_results *params, - int group_formation) +static void wpas_start_go(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *params, + int group_formation, bool p2p2) { struct wpa_ssid *ssid; @@ -2173,6 +2291,21 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, wpa_config_update_psk(ssid); ssid->ap_max_inactivity = wpa_s->p2pdev->conf->p2p_go_max_inactivity; + if (p2p2) { + if (params->akmp == WPA_KEY_MGMT_SAE) + ssid->auth_alg = WPA_AUTH_ALG_OPEN; + else + ssid->auth_alg |= WPA_AUTH_ALG_SAE; + + ssid->key_mgmt = WPA_KEY_MGMT_SAE; + ssid->sae_password = os_strdup(params->password); + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; + wpa_s->conf->sae_pwe = SAE_PWE_HASH_TO_ELEMENT; + if (params->cipher) { + ssid->pairwise_cipher |= params->cipher; + } + } + wpa_s->ap_configured_cb = p2p_go_configured; wpa_s->ap_configured_cb_ctx = wpa_s; wpa_s->ap_configured_cb_data = wpa_s->go_params; @@ -2387,6 +2520,7 @@ wpas_p2p_init_group_interface(struct wpa_supplicant *wpa_s, int go) wpa_s->global->pending_group_iface_for_p2ps = 0; wpas_p2p_clone_config(group_wpa_s, wpa_s); + group_wpa_s->p2p2 = wpa_s->p2p2; if (wpa_s->conf->p2p_interface_random_mac_addr) { if (wpa_drv_set_mac_addr(group_wpa_s, @@ -2569,12 +2703,18 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin, sizeof(group_wpa_s->p2p_pin)); group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method; + group_wpa_s->p2p2 = res->p2p2; + group_wpa_s->p2p_bootstrap = wpa_s->p2p_bootstrap; } + if (res->role_go) { - wpas_start_wps_go(group_wpa_s, res, 1); + wpas_start_go(group_wpa_s, res, 1, res->p2p2); } else { os_get_reltime(&group_wpa_s->scan_min_time); - wpas_start_wps_enrollee(group_wpa_s, res); + if (res->p2p2) + wpas_start_gc(group_wpa_s, res); + else + wpas_start_wps_enrollee(group_wpa_s, res); } wpa_s->global->p2p_long_listen = 0; @@ -7190,7 +7330,7 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, return -1; if (freq > 0) wpa_s->p2p_go_no_pri_sec_switch = 1; - wpas_start_wps_go(wpa_s, ¶ms, 0); + wpas_start_go(wpa_s, ¶ms, 0, wpa_s->p2p2); return 0; } @@ -7407,7 +7547,7 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, p2p_channels_to_freqs(channels, params.freq_list, P2P_MAX_CHANNELS); wpa_s->p2p_first_connection_timeout = connection_timeout; - wpas_start_wps_go(wpa_s, ¶ms, 0); + wpas_start_go(wpa_s, ¶ms, 0, wpa_s->p2p2); return 0; } @@ -7489,7 +7629,7 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, cfg->ip_addr_alloc = WPA_GET_BE32(wpa_s->p2pdev->conf->ip_addr_start) != 0; - group = p2p_group_init(wpa_s->global->p2p, cfg); + group = p2p_group_init(wpa_s->global->p2p, cfg, wpa_s->p2p2); if (group == NULL) os_free(cfg); if (ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap