From f3f2eeba01b678572aa01016c18d262b80f599d9 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 21 Dec 2009 12:46:19 +0200 Subject: [PATCH] WPS: Add option for forcing Registrar to use PSK format in Credential The use_psk_key parameter can now be used to force the Registrar to use PSK format instead of ASCII passphrase when building a Credential for the Enrollee. For now, this is not enabled, but it could be enabled either based on external (to WPS) configuration or automatically set based on some WPS attribute values from the Enrollee. --- hostapd/wps_hostapd.c | 5 +++++ src/eap_server/eap_wsc.c | 2 ++ src/wps/wps.c | 2 ++ src/wps/wps.h | 30 ++++++++++++++++++++++++++++++ src/wps/wps_i.h | 2 ++ src/wps/wps_registrar.c | 9 ++++++++- 6 files changed, 49 insertions(+), 1 deletion(-) 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);