Browse Source

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 <jouni@qca.qualcomm.com>
Jouni Malinen 11 years ago
parent
commit
fdb45355d4
3 changed files with 27 additions and 2 deletions
  1. 23 0
      src/wps/wps_enrollee.c
  2. 2 0
      src/wps/wps_i.h
  3. 2 2
      src/wps/wps_registrar.c

+ 23 - 0
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);

+ 2 - 0
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 */

+ 2 - 2
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;