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 "