diff --git a/hostapd/wps_hostapd.c b/hostapd/wps_hostapd.c index f0a506d0c..28a184348 100644 --- a/hostapd/wps_hostapd.c +++ b/hostapd/wps_hostapd.c @@ -619,6 +619,11 @@ int hostapd_init_wps(struct hostapd_data *hapd, wps->network_key_len = conf->ssid.wep.len[0]; } + if (conf->ssid.wpa_psk) { + os_memcpy(wps->psk, conf->ssid.wpa_psk->psk, PMK_LEN); + wps->psk_set = 1; + } + if (conf->wps_state == WPS_STATE_NOT_CONFIGURED) { /* Override parameters to enable security by default */ wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK; diff --git a/src/eap_server/eap_wsc.c b/src/eap_server/eap_wsc.c index 9d14d20a4..d8371c9fd 100644 --- a/src/eap_server/eap_wsc.c +++ b/src/eap_server/eap_wsc.c @@ -127,6 +127,8 @@ static void * eap_wsc_init(struct eap_sm *sm) } cfg.assoc_wps_ie = sm->assoc_wps_ie; cfg.peer_addr = sm->peer_addr; + if (0 /* TODO: could provide option for forcing PSK format */) + cfg.use_psk_key = 1; data->wps = wps_init(&cfg); if (data->wps == NULL) { os_free(data); diff --git a/src/wps/wps.c b/src/wps/wps.c index 5be2b9abf..780f9fa39 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -104,6 +104,8 @@ struct wps_data * wps_init(const struct wps_config *cfg) if (cfg->peer_addr) os_memcpy(data->peer_dev.mac_addr, cfg->peer_addr, ETH_ALEN); + data->use_psk_key = cfg->use_psk_key; + return data; } diff --git a/src/wps/wps.h b/src/wps/wps.h index 7fc16d95e..abe22d40d 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -147,6 +147,15 @@ struct wps_config { * peer_addr: MAC address of the peer in AP; %NULL if not AP */ const u8 *peer_addr; + + /** + * use_psk_key - Use PSK format key in Credential + * + * Force PSK format to be used instead of ASCII passphrase when + * building Credential for an Enrollee. The PSK value is set in + * struct wpa_context::psk. + */ + int use_psk_key; }; struct wps_data * wps_init(const struct wps_config *cfg); @@ -554,6 +563,14 @@ struct wps_context { * If %NULL, Registrar will generate per-device PSK. In addition, AP * uses this when acting as an Enrollee to notify Registrar of the * current configuration. + * + * When using WPA/WPA2-Person, this key can be either the ASCII + * passphrase (8..63 characters) or the 32-octet PSK (64 hex + * characters). When this is set to the ASCII passphrase, the PSK can + * be provided in the psk buffer and used per-Enrollee to control which + * key type is included in the Credential (e.g., to reduce calculation + * need on low-powered devices by provisioning PSK while still allowing + * other devices to get the passphrase). */ u8 *network_key; @@ -562,6 +579,19 @@ struct wps_context { */ size_t network_key_len; + /** + * psk - The current network PSK + * + * This optional value can be used to provide the current PSK if + * network_key is set to the ASCII passphrase. + */ + u8 psk[32]; + + /** + * psk_set - Whether psk value is set + */ + int psk_set; + /** * ap_settings - AP Settings override for M7 (only used at AP) * diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index 07d302970..e036176d7 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -113,6 +113,8 @@ struct wps_data { void *ap_settings_cb_ctx; struct wps_credential *use_cred; + + int use_psk_key; }; diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 13dfa10e5..5a81c90f3 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1120,7 +1120,8 @@ static int wps_build_cred_encr_type(struct wpabuf *msg, static int wps_build_cred_network_key(struct wpabuf *msg, const struct wps_credential *cred) { - wpa_printf(MSG_DEBUG, "WPS: * Network Key"); + wpa_printf(MSG_DEBUG, "WPS: * Network Key (len=%d)", + (int) cred->key_len); wpabuf_put_be16(msg, ATTR_NETWORK_KEY); wpabuf_put_be16(msg, cred->key_len); wpabuf_put_data(msg, cred->key, cred->key_len); @@ -1233,6 +1234,12 @@ 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) { + 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) { os_memcpy(wps->cred.key, wps->wps->network_key, wps->wps->network_key_len);