From 374353d31bc083def45eddc214d7b02b2427b4c2 Mon Sep 17 00:00:00 2001 From: Vinay Gannevaram Date: Sat, 11 Jan 2025 11:38:10 +0530 Subject: [PATCH] P2P2: SSID randomization on group reinvoke P2P R2 allows the GO to randomize SSID and Group BSSID when a group is reinvoked. Add support to fetch the group details based on the device identity block info of the peer with which the group reinvoke is initiated. As the previous SSID of the network is no longer valid, fetch the network details based on the ID of the device identity block. Signed-off-by: Vinay Gannevaram --- src/p2p/p2p.c | 15 +++++++- src/p2p/p2p.h | 11 +++++- src/p2p/p2p_i.h | 2 + src/p2p/p2p_invitation.c | 40 ++++++++++++++++++-- wpa_supplicant/config.c | 29 +++++++++++++++ wpa_supplicant/config.h | 2 + wpa_supplicant/p2p_supplicant.c | 65 +++++++++++++++++++++++++++++++-- 7 files changed, 154 insertions(+), 10 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 1afdc0ad6..8ff26dc65 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -4304,7 +4304,8 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p) p2p_dbg(p2p, "Invitation Request retry limit reached"); if (p2p->cfg->invitation_result) p2p->cfg->invitation_result( - p2p->cfg->cb_ctx, -1, NULL, NULL, + p2p->cfg->cb_ctx, -1, NULL, 0, NULL, + NULL, p2p->invite_peer->info.p2p_device_addr, 0, 0, NULL, NULL, 0); } @@ -6197,6 +6198,18 @@ void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, } +int p2p_get_dik_id(struct p2p_data *p2p, const u8 *peer) +{ + struct p2p_device *dev; + + dev = p2p_get_device(p2p, peer); + if (!dev) + return 0; + + return dev->info.dik_id; +} + + #ifdef CONFIG_PASN int p2p_config_sae_password(struct p2p_data *p2p, const char *pw) diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 8203a68ae..0089d784a 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1091,6 +1091,8 @@ struct p2p_config { * used * @p2p2: Whether invitation request was wrapped in PASN authentication * received from a P2P2 device + * @new_ssid: Pointer to hold new SSID + * @new_ssid_len: Length of new SSID buffer in octets * Returns: Status code (P2P_SC_*) * * This optional callback can be used to implement persistent reconnect @@ -1113,7 +1115,8 @@ struct p2p_config { size_t ssid_len, int *go, u8 *group_bssid, int *force_freq, int persistent_group, const struct p2p_channels *channels, - int dev_pw_id, bool p2p2); + int dev_pw_id, bool p2p2, const u8 **new_ssid, + size_t *new_ssid_len); /** * invitation_received - Callback on Invitation Request RX @@ -1142,6 +1145,8 @@ struct p2p_config { * invitation_result - Callback on Invitation result * @ctx: Callback context from cb_ctx * @status: Negotiation result (Status Code) + * @new_ssid: New SSID received in invitation response + * @new_ssid_len: Length of new SSID received * @bssid: P2P Group BSSID or %NULL if not received * @channels: Available operating channels for the group * @addr: Peer address @@ -1155,7 +1160,8 @@ struct p2p_config { * (P2P_SC_SUCCESS) indicating success or -1 to indicate a timeout or a * local failure in transmitting the Invitation Request. */ - void (*invitation_result)(void *ctx, int status, const u8 *bssid, + void (*invitation_result)(void *ctx, int status, const u8 *new_ssid, + size_t new_ssid_len, const u8 *bssid, const struct p2p_channels *channels, const u8 *addr, int freq, int peer_oper_freq, const u8 *pmkid, const u8 *pmk, @@ -2734,6 +2740,7 @@ int p2p_channel_to_freq(int op_class, int channel); struct wpabuf * p2p_usd_elems(struct p2p_data *p2p); void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len, const u8 *peer_addr, unsigned int freq); +int p2p_get_dik_id(struct p2p_data *p2p, const u8 *peer); void p2p_set_pairing_setup(struct p2p_data *p2p, int pairing_setup); void p2p_set_pairing_cache(struct p2p_data *p2p, int pairing_cache); diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 4b0be618a..a2b763b9f 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -203,6 +203,8 @@ struct p2p_device { int inv_freq; int inv_peer_oper_freq; u8 inv_bssid[ETH_ALEN]; + u8 inv_ssid[SSID_MAX_LEN]; + size_t inv_ssid_len; bool inv_all_channels; }; diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c index 766b63e65..90c4f63bb 100644 --- a/src/p2p/p2p_invitation.c +++ b/src/p2p/p2p_invitation.c @@ -117,7 +117,9 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p, u8 dialog_token, u8 status, const u8 *group_bssid, u8 reg_class, u8 channel, - struct p2p_channels *channels) + struct p2p_channels *channels, + const u8 *ssid, + size_t ssid_len) { struct wpabuf *buf; u8 *len; @@ -162,6 +164,18 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p, reg_class, channel); if (group_bssid) p2p_buf_add_group_bssid(buf, group_bssid); + + if (ssid_len && ssid) { + const u8 *dev_addr; + + if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT) + dev_addr = peer->info.p2p_device_addr; + else + dev_addr = p2p->cfg->dev_addr; + + p2p_buf_add_group_id(buf, dev_addr, ssid, ssid_len); + } + if (channels) { bool is_6ghz_capab; @@ -196,6 +210,8 @@ struct wpabuf * p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, u8 group_bssid[ETH_ALEN], *bssid; int op_freq = 0; u8 reg_class = 0, channel = 0; + const u8 *new_ssid; + size_t new_ssid_len = 0; struct p2p_channels all_channels, intersection, *channels = NULL; int persistent; @@ -272,7 +288,7 @@ struct wpabuf * p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN, &go, group_bssid, &op_freq, persistent, &intersection, msg.dev_password_id_present ? msg.dev_password_id : -1, - p2p2); + p2p2, &new_ssid, &new_ssid_len); } if (go) { @@ -401,7 +417,8 @@ fail: else bssid = NULL; resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status, - bssid, reg_class, channel, channels); + bssid, reg_class, channel, channels, + new_ssid, new_ssid_len); /* * Store copy of invitation data to be used when processing TX status @@ -413,7 +430,12 @@ fail: p2p->inv_group_bssid_ptr = p2p->inv_group_bssid; } else p2p->inv_group_bssid_ptr = NULL; - if (msg.group_id) { + + if (p2p2 && new_ssid_len) { + os_memcpy(p2p->inv_ssid, new_ssid, new_ssid_len); + p2p->inv_ssid_len = new_ssid_len; + os_memcpy(p2p->inv_go_dev_addr, p2p->cfg->dev_addr, ETH_ALEN); + } else if (msg.group_id) { if (msg.group_id_len - ETH_ALEN <= SSID_MAX_LEN) { os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN); @@ -593,10 +615,17 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa, if (msg.group_bssid) os_memcpy(dev->inv_bssid, msg.group_bssid, ETH_ALEN); + if (msg.group_id) { + dev->inv_ssid_len = msg.group_id_len - ETH_ALEN; + os_memcpy(dev->inv_ssid, + msg.group_id + ETH_ALEN, + dev->inv_ssid_len); + } goto out; } p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status, + NULL, 0, msg.group_bssid, channels, sa, freq, peer_oper_freq, NULL, NULL, 0); @@ -638,6 +667,7 @@ void p2p_start_invitation_connect(struct p2p_data *p2p, struct p2p_device *dev) p2p_dbg(p2p, "Invitation connect: msg status %d", dev->inv_status); if (p2p->cfg->invitation_result) p2p->cfg->invitation_result(p2p->cfg->cb_ctx, dev->inv_status, + dev->inv_ssid, dev->inv_ssid_len, dev->inv_bssid, inv_channels, dev->info.p2p_device_addr, dev->inv_freq, @@ -650,6 +680,8 @@ void p2p_start_invitation_connect(struct p2p_data *p2p, struct p2p_device *dev) p2p_clear_timeout(p2p); p2p_set_state(p2p, P2P_IDLE); + os_memset(dev->inv_ssid, 0, sizeof(dev->inv_ssid)); + dev->inv_ssid_len = 0; p2p->invite_peer = NULL; } #endif /* CONFIG_PASN */ diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 551701af5..6dfb3165a 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -3190,6 +3190,35 @@ struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) } +#ifdef CONFIG_P2P +/** + * wpa_config_get_network_with_dik_id - Get configured network based on ID of + * device identity block + * @config: Configuration data from wpa_config_read() + * @dik_id: DIK ID to search for + * Returns: Network configuration or %NULL if not found + */ +struct wpa_ssid * wpa_config_get_network_with_dik_id(struct wpa_config *config, + int dik_id) +{ + struct wpa_ssid *ssid; + + for (ssid = config->ssid; ssid; ssid = ssid->next) { + if (ssid->disabled != 2) + continue; + + if (ssid->go_dik_id == dik_id) + return ssid; + + if (int_array_includes(ssid->p2p2_client_list, dik_id)) + return ssid; + } + + return NULL; +} +#endif /* CONFIG_P2P */ + + /** * wpa_config_add_network - Add a new network with empty configuration * @config: Configuration data from wpa_config_read() diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 8dac97932..ca227a82e 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -1921,6 +1921,8 @@ void wpa_config_foreach_network(struct wpa_config *config, void (*func)(void *, struct wpa_ssid *), void *arg); struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id); +struct wpa_ssid * wpa_config_get_network_with_dik_id(struct wpa_config *config, + int dik_id); struct wpa_ssid * wpa_config_add_network(struct wpa_config *config); int wpa_config_remove_network(struct wpa_config *config, int id); void wpa_config_set_network_defaults(struct wpa_ssid *ssid); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 95f4e4e62..8d472f0d6 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -3665,7 +3665,8 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid, size_t ssid_len, int *go, u8 *group_bssid, int *force_freq, int persistent_group, const struct p2p_channels *channels, - int dev_pw_id, bool p2p2) + int dev_pw_id, bool p2p2, const u8 **new_ssid, + size_t *new_ssid_len) { struct wpa_supplicant *wpa_s = ctx; struct wpa_ssid *s; @@ -3735,7 +3736,41 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid, break; } - if (!s) { + if (p2p2) { + int dik_id; + u8 go_ssid[SSID_MAX_LEN]; + + dik_id = p2p_get_dik_id(wpa_s->global->p2p, sa); + s = wpa_config_get_network_with_dik_id(wpa_s->conf, dik_id); + if (!s) { + wpa_printf(MSG_DEBUG, "P2P2: Invitation from " MACSTR + " requested reinvocation of an unknown group", + MAC2STR(sa)); + return P2P_SC_FAIL_UNKNOWN_GROUP; + } + os_free(s->ssid); + if (s->mode == WPAS_MODE_P2P_GO) { + p2p_build_ssid(wpa_s->global->p2p, go_ssid, + &s->ssid_len); + s->ssid = os_memdup(go_ssid, s->ssid_len); + if (!s->ssid) { + s->ssid_len = 0; + return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; + } + wpa_printf(MSG_DEBUG, + "P2P: New random SSID for the group: %s", + wpa_ssid_txt(s->ssid, s->ssid_len)); + *new_ssid = s->ssid; + *new_ssid_len = s->ssid_len; + } else { + s->ssid_len = ssid_len; + s->ssid = os_memdup(ssid, ssid_len); + if (!s->ssid) { + s->ssid_len = 0; + return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; + } + } + } else if (!s) { wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR " requested reinvocation of an unknown group", MAC2STR(sa)); @@ -3980,7 +4015,8 @@ static void wpas_remove_persistent_client(struct wpa_supplicant *wpa_s, } -static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, +static void wpas_invitation_result(void *ctx, int status, const u8 *new_ssid, + size_t new_ssid_len, const u8 *bssid, const struct p2p_channels *channels, const u8 *peer, int neg_freq, int peer_oper_freq, const u8 *pmkid, @@ -4067,6 +4103,16 @@ static void wpas_invitation_result(void *ctx, int status, const u8 *bssid, return; } + if (new_ssid && new_ssid_len) { + os_free(ssid->ssid); + ssid->ssid = os_memdup(new_ssid, new_ssid_len); + if (!ssid->ssid) { + ssid->ssid_len = 0; + return; + } + ssid->ssid_len = new_ssid_len; + } + /* * The peer could have missed our ctrl::ack frame for Invitation * Response and continue retransmitting the frame. To reduce the @@ -8674,6 +8720,19 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, else os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN); + if (wpa_s->global->p2p && p2p2 && !ssid && peer_addr) { + int dik_id; + + dik_id = p2p_get_dik_id(wpa_s->global->p2p, peer_addr); + ssid = wpa_config_get_network_with_dik_id(wpa_s->conf, dik_id); + if (!ssid) { + wpa_printf(MSG_DEBUG, + "P2P: Could not find SSID for P2P2 peer " + MACSTR, MAC2STR(peer_addr)); + return -1; + } + } + wpa_s->p2p_persistent_go_freq = freq; wpa_s->p2p_go_ht40 = !!ht40; wpa_s->p2p_go_vht = !!vht; -- 2.47.2