WPS NFC: Use abbreviated handshake if both PK hashes delivered OOB

When both the Registrar and Enrollee public key hashes are delivered
out-of-band (in NFC connection handover), use abbreviated WPS handshake
(skip M3-M8).

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-02-24 17:30:18 +02:00 committed by Jouni Malinen
parent 57630e658b
commit 34b6795015
3 changed files with 69 additions and 6 deletions

View file

@ -806,7 +806,8 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
struct wps_credential *cred); struct wps_credential *cred);
int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
const u8 *pubkey_hash, u16 pw_id, 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, int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
const u8 *oob_dev_pw, const u8 *oob_dev_pw,
size_t oob_dev_pw_len); size_t oob_dev_pw_len);

View file

@ -946,6 +946,38 @@ static enum wps_process_res wps_process_m2(struct wps_data *wps,
return WPS_CONTINUE; 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; wps->state = SEND_M3;
return WPS_CONTINUE; return WPS_CONTINUE;
} }

View file

@ -34,6 +34,7 @@ struct wps_nfc_pw_token {
u16 pw_id; u16 pw_id;
u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1]; u8 dev_pw[WPS_OOB_DEVICE_PASSWORD_LEN * 2 + 1];
size_t dev_pw_len; size_t dev_pw_len;
int pk_hash_provided_oob; /* whether own PK hash was provided OOB */
}; };
@ -1777,6 +1778,7 @@ static struct wpabuf * wps_build_ap_cred(struct wps_data *wps)
static struct wpabuf * wps_build_m2(struct wps_data *wps) static struct wpabuf * wps_build_m2(struct wps_data *wps)
{ {
struct wpabuf *msg; struct wpabuf *msg;
int config_in_m2 = 0;
if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0) if (random_get_bytes(wps->nonce_r, WPS_NONCE_LEN) < 0)
return NULL; return NULL;
@ -1807,14 +1809,40 @@ static struct wpabuf * wps_build_m2(struct wps_data *wps)
wps_build_config_error(msg, WPS_CFG_NO_ERROR) || wps_build_config_error(msg, WPS_CFG_NO_ERROR) ||
wps_build_dev_password_id(msg, wps->dev_pw_id) || wps_build_dev_password_id(msg, wps->dev_pw_id) ||
wps_build_os_version(&wps->wps->dev, msg) || wps_build_os_version(&wps->wps->dev, msg) ||
wps_build_wfa_ext(msg, 0, NULL, 0) || wps_build_wfa_ext(msg, 0, NULL, 0)) {
wps_build_authenticator(wps, msg)) { 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); wpabuf_free(msg);
return NULL; return NULL;
} }
wps->int_reg = 1; wps->int_reg = 1;
wps->state = RECV_M3; wps->state = config_in_m2 ? RECV_DONE : RECV_M3;
return msg; return msg;
} }
@ -3496,7 +3524,8 @@ int wps_registrar_config_ap(struct wps_registrar *reg,
int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
const u8 *pubkey_hash, u16 pw_id, 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; struct wps_nfc_pw_token *token;
@ -3511,6 +3540,7 @@ int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN); os_memcpy(token->pubkey_hash, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
token->pw_id = pw_id; token->pw_id = pw_id;
token->pk_hash_provided_oob = pk_hash_provided_oob;
wpa_snprintf_hex_uppercase((char *) token->dev_pw, wpa_snprintf_hex_uppercase((char *) token->dev_pw,
sizeof(token->dev_pw), sizeof(token->dev_pw),
dev_pw, dev_pw_len); dev_pw, dev_pw_len);
@ -3563,7 +3593,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
wpa_hexdump_key(MSG_DEBUG, "WPS: Device Password", 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, return wps_registrar_add_nfc_pw_token(reg, hash, id, dev_pw,
dev_pw_len); dev_pw_len, 0);
} }