struct wps_credential *cred);
int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
const u8 *pubkey_hash, u16 pw_id,
- const u8 *dev_pw, size_t dev_pw_len);
+ const u8 *dev_pw, size_t dev_pw_len,
+ int pk_hash_provided_oob);
int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
const u8 *oob_dev_pw,
size_t oob_dev_pw_len);
return WPS_CONTINUE;
}
+#ifdef CONFIG_WPS_NFC
+ if (wps->peer_pubkey_hash_set) {
+ struct wpabuf *decrypted;
+ struct wps_parse_attr eattr;
+
+ decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
+ attr->encr_settings_len);
+ if (decrypted == NULL) {
+ wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt "
+ "Encrypted Settings attribute");
+ wps->state = SEND_WSC_NACK;
+ return WPS_CONTINUE;
+ }
+
+ wpa_printf(MSG_DEBUG, "WPS: Processing decrypted Encrypted "
+ "Settings attribute");
+ if (wps_parse_msg(decrypted, &eattr) < 0 ||
+ wps_process_key_wrap_auth(wps, decrypted,
+ eattr.key_wrap_auth) ||
+ wps_process_creds(wps, eattr.cred, eattr.cred_len,
+ eattr.num_cred, attr->version2 != NULL)) {
+ wpabuf_free(decrypted);
+ wps->state = SEND_WSC_NACK;
+ return WPS_CONTINUE;
+ }
+ wpabuf_free(decrypted);
+
+ wps->state = WPS_MSG_DONE;
+ return WPS_CONTINUE;
+ }
+#endif /* CONFIG_WPS_NFC */
+
wps->state = SEND_M3;
return WPS_CONTINUE;
}
u16 pw_id;
u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
size_t dev_pw_len;
+ int pk_hash_provided_oob; /* whether own PK hash was provided OOB */
};
static struct wpabuf * wps_build_m2(struct wps_data *wps)
{
struct wpabuf *msg;
+ int config_in_m2 = 0;
if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0)
return NULL;
wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
wps_build_dev_password_id(msg, wps->dev_pw_id) ||
wps_build_os_version(&wps->wps->dev, msg) ||
- wps_build_wfa_ext(msg, 0, NULL, 0) ||
- wps_build_authenticator(wps, msg)) {
+ wps_build_wfa_ext(msg, 0, NULL, 0)) {
+ wpabuf_free(msg);
+ return NULL;
+ }
+
+#ifdef CONFIG_WPS_NFC
+ if (wps->nfc_pw_token && wps->nfc_pw_token->pk_hash_provided_oob) {
+ /*
+ * Use abbreviated handshake since public key hash allowed
+ * Enrollee to validate our public key similarly to how Enrollee
+ * public key was validated. There is no need to validate Device
+ * Password in this case.
+ */
+ struct wpabuf *plain = wpabuf_alloc(500);
+ if (plain == NULL ||
+ wps_build_cred(wps, plain) ||
+ wps_build_key_wrap_auth(wps, plain) ||
+ wps_build_encr_settings(wps, msg, plain)) {
+ wpabuf_free(msg);
+ wpabuf_free(plain);
+ return NULL;
+ }
+ wpabuf_free(plain);
+ config_in_m2 = 1;
+ }
+#endif /* CONFIG_WPS_NFC */
+
+ if (wps_build_authenticator(wps, msg)) {
wpabuf_free(msg);
return NULL;
}
wps->int_reg = 1;
- wps->state = RECV_M3;
+ wps->state = config_in_m2 ? RECV_DONE : RECV_M3;
return msg;
}
int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
const u8 *pubkey_hash, u16 pw_id,
- const u8 *dev_pw, size_t dev_pw_len)
+ const u8 *dev_pw, size_t dev_pw_len,
+ int pk_hash_provided_oob)
{
struct wps_nfc_pw_token *token;
os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
token->pw_id = pw_id;
+ token->pk_hash_provided_oob = pk_hash_provided_oob;
wpa_snprintf_hex_uppercase((char *) token->dev_pw,
sizeof(token->dev_pw),
dev_pw, dev_pw_len);
wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", dev_pw, dev_pw_len);
return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
- dev_pw_len);
+ dev_pw_len, 0);
}