WPS: Allow Device Password to be changed from M1 to M2

Registrar is allowed to propose another Device Password ID in M2. Make
Enrollee validate Device Password ID in M2 to check if this happened.
This commit adds support for changing from NFC password token to default
PIN for the case where the AP is the Enrollee and has both the NFC
password token and AP PIN enabled at the same time.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-02-14 20:41:14 +02:00 committed by Jouni Malinen
parent 38a5ad6728
commit b4a17a6ea7
4 changed files with 56 additions and 2 deletions

View file

@ -53,12 +53,18 @@ struct wps_data * wps_init(const struct wps_config *cfg)
}
os_memcpy(data->dev_password, cfg->pin, cfg->pin_len);
data->dev_password_len = cfg->pin_len;
wpa_hexdump_key(MSG_DEBUG, "WPS: AP PIN dev_password",
data->dev_password, data->dev_password_len);
}
#ifdef CONFIG_WPS_NFC
if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
/* Keep AP PIN as alternative Device Password */
data->alt_dev_pw_id = data->dev_pw_id;
data->alt_dev_password = data->dev_password;
data->alt_dev_password_len = data->dev_password_len;
data->dev_pw_id = cfg->wps->ap_nfc_dev_pw_id;
os_free(data->dev_password);
data->dev_password =
os_malloc(wpabuf_len(cfg->wps->ap_nfc_dev_pw));
if (data->dev_password == NULL) {
@ -69,6 +75,8 @@ struct wps_data * wps_init(const struct wps_config *cfg)
wpabuf_head(cfg->wps->ap_nfc_dev_pw),
wpabuf_len(cfg->wps->ap_nfc_dev_pw));
data->dev_password_len = wpabuf_len(cfg->wps->ap_nfc_dev_pw);
wpa_hexdump_key(MSG_DEBUG, "WPS: NFC dev_password",
data->dev_password, data->dev_password_len);
}
#endif /* CONFIG_WPS_NFC */
@ -155,6 +163,7 @@ void wps_deinit(struct wps_data *data)
wpabuf_free(data->dh_pubkey_r);
wpabuf_free(data->last_msg);
os_free(data->dev_password);
os_free(data->alt_dev_password);
os_free(data->new_psk);
wps_device_data_free(&data->peer_dev);
os_free(data->new_ap_settings);

View file

@ -837,6 +837,39 @@ static int wps_process_ap_settings_e(struct wps_data *wps,
}
static int wps_process_dev_pw_id(struct wps_data *wps, const u8 *dev_pw_id)
{
u16 id;
if (dev_pw_id == NULL) {
wpa_printf(MSG_DEBUG, "WPS: Device Password ID");
return -1;
}
id = WPA_GET_BE16(dev_pw_id);
if (wps->dev_pw_id == id) {
wpa_printf(MSG_DEBUG, "WPS: Device Password ID %u", id);
return 0;
}
wpa_printf(MSG_DEBUG, "WPS: Registrar trying to change Device Password "
"ID from %u to %u", wps->dev_pw_id, id);
if (wps->alt_dev_password && wps->alt_dev_pw_id == id) {
wpa_printf(MSG_DEBUG, "WPS: Found a matching Device Password");
os_free(wps->dev_password);
wps->dev_pw_id = wps->alt_dev_pw_id;
wps->dev_password = wps->alt_dev_password;
wps->dev_password_len = wps->alt_dev_password_len;
wps->alt_dev_password = NULL;
wps->alt_dev_password_len = 0;
return 0;
}
return -1;
}
static enum wps_process_res wps_process_m2(struct wps_data *wps,
const struct wpabuf *msg,
struct wps_parse_attr *attr)
@ -852,7 +885,8 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
if (wps_process_registrar_nonce(wps, attr->registrar_nonce) ||
wps_process_enrollee_nonce(wps, attr->enrollee_nonce) ||
wps_process_uuid_r(wps, attr->uuid_r)) {
wps_process_uuid_r(wps, attr->uuid_r) ||
wps_process_dev_pw_id(wps, attr->dev_password_id)) {
wps->state = SEND_WSC_NACK;
return WPS_CONTINUE;
}

View file

@ -71,6 +71,9 @@ struct wps_data {
size_t dev_password_len;
u16 dev_pw_id;
int pbc;
u8 *alt_dev_password;
size_t alt_dev_password_len;
u16 alt_dev_pw_id;
/**
* request_type - Request Type attribute from (Re)AssocReq

View file

@ -1358,6 +1358,14 @@ static int wps_get_dev_password(struct wps_data *wps)
} else {
pin = wps_registrar_get_pin(wps->wps->registrar, wps->uuid_e,
&pin_len);
if (pin && wps->dev_pw_id >= 0x10) {
wpa_printf(MSG_DEBUG, "WPS: No match for OOB Device "
"Password ID, but PIN found");
/*
* See whether Enrollee is willing to use PIN instead.
*/
wps->dev_pw_id = DEV_PW_DEFAULT;
}
}
if (pin == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No Device Password available for "