From 05766ed8de2df822948e4bdc279ae7c461702bf4 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 1 Sep 2013 10:08:30 +0300 Subject: [PATCH] P2P: Allow per-device PSK to be assigned "wpa_cli p2p_set per_sta_psk <0/1>" can now be used to disable/enable use of per-device PSKs in P2P groups. This is disabled by default. When enabled, a default passphrase is still generated by the GO for legacy stations, but all P2P and non-P2P devices using WPS will get a unique PSK. This gives more protection for the P2P group by preventing clients from being able to derive the unicast keys used by other clients. This is also a step towards allowing specific clients to be removed from a group reliably without having to tear down the full group to do so. Signed-hostap: Jouni Malinen --- src/ap/ap_config.h | 1 + src/ap/wps_hostapd.c | 1 + src/wps/wps.h | 8 ++++++++ src/wps/wps_registrar.c | 10 +++++++--- wpa_supplicant/ap.c | 1 + wpa_supplicant/ctrl_iface.c | 7 ++++++- wpa_supplicant/wpa_cli.c | 1 + wpa_supplicant/wpa_supplicant_i.h | 1 + 8 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index d5bfabceb..e2836456e 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -358,6 +358,7 @@ struct hostapd_bss_config { u8 *extra_cred; size_t extra_cred_len; int wps_cred_processing; + int force_per_enrollee_psk; u8 *ap_settings; size_t ap_settings_len; char *upnp_iface; diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 3304c0636..4f627c894 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -1145,6 +1145,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, cfg.dualband = 1; if (cfg.dualband) wpa_printf(MSG_DEBUG, "WPS: Dualband AP"); + cfg.force_per_enrollee_psk = conf->force_per_enrollee_psk; wps->registrar = wps_registrar_init(wps, &cfg); if (wps->registrar == NULL) { diff --git a/src/wps/wps.h b/src/wps/wps.h index dc82c4462..2e6719f40 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -382,6 +382,14 @@ struct wps_registrar_config { * dualband - Whether this is a concurrent dualband AP */ int dualband; + + /** + * force_per_enrollee_psk - Force per-Enrollee random PSK + * + * This forces per-Enrollee random PSK to be generated even if a default + * PSK is set for a network. + */ + int force_per_enrollee_psk; }; diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 318445f28..20a8b7f62 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1,6 +1,6 @@ /* * Wi-Fi Protected Setup - Registrar - * Copyright (c) 2008-2012, Jouni Malinen + * Copyright (c) 2008-2013, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -171,6 +171,7 @@ struct wps_registrar { int sel_reg_config_methods_override; int static_wep_only; int dualband; + int force_per_enrollee_psk; struct wps_registrar_device *devices; @@ -667,6 +668,7 @@ wps_registrar_init(struct wps_context *wps, reg->sel_reg_config_methods_override = -1; reg->static_wep_only = cfg->static_wep_only; reg->dualband = cfg->dualband; + reg->force_per_enrollee_psk = cfg->force_per_enrollee_psk; if (wps_set_ie(reg)) { wps_registrar_deinit(reg); @@ -1640,13 +1642,15 @@ int wps_build_cred(struct wps_data *wps, struct wpabuf *msg) wps->new_psk, wps->new_psk_len); os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len); wps->cred.key_len = wps->new_psk_len; - } else if (wps->use_psk_key && wps->wps->psk_set) { + } else if (!wps->wps->registrar->force_per_enrollee_psk && + wps->use_psk_key && wps->wps->psk_set) { char hex[65]; wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key"); wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32); os_memcpy(wps->cred.key, hex, 32 * 2); wps->cred.key_len = 32 * 2; - } else if (wps->wps->network_key) { + } else if (!wps->wps->registrar->force_per_enrollee_psk && + wps->wps->network_key) { os_memcpy(wps->cred.key, wps->wps->network_key, wps->wps->network_key_len); wps->cred.key_len = wps->wps->network_key_len; diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 2950d2d1a..99c6d8aa4 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -148,6 +148,7 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, } bss->isolate = !wpa_s->conf->p2p_intra_bss; + bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; #endif /* CONFIG_P2P */ if (ssid->ssid_len == 0) { diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 03ffde055..2abcf74c1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Control interface (shared code for all backends) - * Copyright (c) 2004-2012, Jouni Malinen + * Copyright (c) 2004-2013, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -4559,6 +4559,11 @@ static int p2p_ctrl_set(struct wpa_supplicant *wpa_s, char *cmd) max_disc_int, max_disc_tu); } + if (os_strcmp(cmd, "per_sta_psk") == 0) { + wpa_s->global->p2p_per_sta_psk = !!atoi(param); + return 0; + } + wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown P2P_SET field value '%s'", cmd); diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 8875d3b71..9817eda68 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -2076,6 +2076,7 @@ static char ** wpa_cli_complete_p2p_set(const char *str, int pos) "client_apsd", "disallow_freq", "disc_int", + "per_sta_psk", }; int i, num_fields = sizeof(fields) / sizeof(fields[0]); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 604997e57..f808f491f 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -265,6 +265,7 @@ struct wpa_global { WPA_CONC_PREF_P2P } conc_pref; unsigned int p2p_cb_on_scan_complete:1; + unsigned int p2p_per_sta_psk:1; #ifdef CONFIG_WIFI_DISPLAY int wifi_display;