From b4a17a6ea74b2ffba082e05c84730e979513042c Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Thu, 14 Feb 2013 20:41:14 +0200 Subject: [PATCH] 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 --- src/wps/wps.c | 11 ++++++++++- src/wps/wps_enrollee.c | 36 +++++++++++++++++++++++++++++++++++- src/wps/wps_i.h | 3 +++ src/wps/wps_registrar.c | 8 ++++++++ 4 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/wps/wps.c b/src/wps/wps.c index 257570581..ff4b20d62 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -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); diff --git a/src/wps/wps_enrollee.c b/src/wps/wps_enrollee.c index 837b9412e..9c0cebb75 100644 --- a/src/wps/wps_enrollee.c +++ b/src/wps/wps_enrollee.c @@ -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; } diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index 8110894e3..6efc3bfea 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -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 diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index b650a3c0a..57344c565 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -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 "