From fdb45355d43060f593243272d73a401d8842c289 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 13 Mar 2014 13:26:21 +0200 Subject: [PATCH] WPS: Extend per-station PSK to support ER case as well When wpa_psk_file is used instead of wpa_psk/wpa_passphrase, each WPS Enrollee was given a unique PSK. This did not work for the station-as-Registrar case where ER would learn the current AP settings instead of enrolling itself (i.e., when using the AP PIN instead of station PIN). That case can be covered with a similar design, so generate a per-device PSK when building M7 as an AP in wpa_psk_file configuration. Signed-off-by: Jouni Malinen --- src/wps/wps_enrollee.c | 23 +++++++++++++++++++++++ src/wps/wps_i.h | 2 ++ src/wps/wps_registrar.c | 4 ++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 70d6a1781..89f136645 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -265,6 +265,29 @@ static int wps_build_cred_encr_type(struct wps_data *wps, struct wpabuf *msg) static int wps_build_cred_network_key(struct wps_data *wps, struct wpabuf *msg) { + if ((wps->wps->ap_auth_type & (WPS_AUTH_WPAPSK | WPS_AUTH_WPA2PSK)) && + wps->wps->network_key_len == 0) { + char hex[65]; + u8 psk[32]; + /* Generate a random per-device PSK */ + if (random_get_bytes(psk, sizeof(psk)) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "WPS: Generated per-device PSK", + psk, sizeof(psk)); + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%u)", + (unsigned int) wps->new_psk_len * 2); + wpa_snprintf_hex(hex, sizeof(hex), psk, sizeof(psk)); + wpabuf_put_be16(msg, ATTR_NETWORK_KEY); + wpabuf_put_be16(msg, sizeof(psk) * 2); + wpabuf_put_data(msg, hex, sizeof(psk) * 2); + if (wps->wps->registrar) { + wps_cb_new_psk(wps->wps->registrar, + wps->peer_dev.mac_addr, + wps->p2p_dev_addr, psk, sizeof(psk)); + } + return 0; + } + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%u)", (unsigned int) wps->wps->network_key_len); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index 22070db9b..f7154f873 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -212,5 +212,7 @@ int wps_registrar_pbc_overlap(struct wps_registrar *reg, const u8 *addr, const u8 *uuid_e); void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, struct wps_nfc_pw_token *token); +int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len); #endif /* WPS_I_H */ diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 6d879be27..900dd5a1f 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1170,8 +1170,8 @@ void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, } -static int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, - const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len) +int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len) { if (reg->new_psk_cb == NULL) return 0;