WPS NFC: Update NFC connection handover design

The new Device Password ID 7 is used to indicate that NFC connection
handover is used with DH public key hash from both devices being
exchanged over the NFC connection handover messages. This allows an
abbreviated M1-M2 handshake to be used since Device Password does not
need to be used when DH is authenticated with the out-of-band
information (validation of the public key against the hash).

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Jouni Malinen 2013-04-02 18:30:58 +03:00 committed by Jouni Malinen
parent 34b6795015
commit 975491793b
7 changed files with 131 additions and 16 deletions

View file

@ -58,6 +58,10 @@ struct wps_data * wps_init(const struct wps_config *cfg)
}
#ifdef CONFIG_WPS_NFC
if (cfg->pin == NULL &&
cfg->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)
data->dev_pw_id = cfg->dev_pw_id;
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;

View file

@ -859,6 +859,10 @@ struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey,
struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
struct wpabuf **privkey,
struct wpabuf **dev_pw);
struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
struct wpabuf *nfc_dh_pubkey);
struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
struct wpabuf *nfc_dh_pubkey);
/* ndef.c */
struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf);

View file

@ -38,8 +38,11 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
wps->wps->dh_ctx = NULL;
pubkey = wpabuf_dup(wps->wps->dh_pubkey);
#ifdef CONFIG_WPS_NFC
} else if (wps->dev_pw_id >= 0x10 && wps->wps->ap &&
wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) {
} else if ((wps->dev_pw_id >= 0x10 ||
wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) &&
wps->wps->ap &&
(wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id ||
wps->wps->ap_nfc_dh_pubkey)) {
wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
if (wps->wps->ap_nfc_dh_privkey == NULL) {
wpa_printf(MSG_DEBUG,
@ -399,9 +402,11 @@ int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id,
pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
wpabuf_put_data(msg, pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
wpabuf_put_be16(msg, dev_pw_id);
wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
dev_pw, dev_pw_len);
wpabuf_put_data(msg, dev_pw, dev_pw_len);
if (dev_pw) {
wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
dev_pw, dev_pw_len);
wpabuf_put_data(msg, dev_pw, dev_pw_len);
}
return 0;
}

View file

@ -263,10 +263,13 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
attr->dev_password_id = pos;
break;
case ATTR_OOB_DEVICE_PASSWORD:
if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_LEN) {
WPS_OOB_DEVICE_PASSWORD_LEN ||
(len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_MIN_LEN &&
WPA_GET_BE16(pos + WPS_OOB_PUBKEY_HASH_LEN) !=
DEV_PW_NFC_CONNECTION_HANDOVER)) {
wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
"Password length %u", len);
return -1;

View file

@ -671,4 +671,90 @@ struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
return wps_nfc_token_build(ndef, *id, *pubkey, *dev_pw);
}
struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx,
struct wpabuf *nfc_dh_pubkey)
{
struct wpabuf *msg;
void *len;
if (ctx == NULL)
return NULL;
wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
"handover request");
if (nfc_dh_pubkey == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
"configured");
return NULL;
}
msg = wpabuf_alloc(1000);
if (msg == NULL)
return msg;
len = wpabuf_put(msg, 2);
if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
nfc_dh_pubkey, NULL, 0) ||
wps_build_uuid_e(msg, ctx->uuid) ||
wps_build_wfa_ext(msg, 0, NULL, 0)) {
wpabuf_free(msg);
return NULL;
}
WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
return msg;
}
static int wps_build_ssid(struct wpabuf *msg, struct wps_context *wps)
{
wpa_printf(MSG_DEBUG, "WPS: * SSID");
wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID in Connection Handover Select",
wps->ssid, wps->ssid_len);
wpabuf_put_be16(msg, ATTR_SSID);
wpabuf_put_be16(msg, wps->ssid_len);
wpabuf_put_data(msg, wps->ssid, wps->ssid_len);
return 0;
}
struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx,
struct wpabuf *nfc_dh_pubkey)
{
struct wpabuf *msg;
void *len;
if (ctx == NULL)
return NULL;
wpa_printf(MSG_DEBUG, "WPS: Building attributes for NFC connection "
"handover select");
if (nfc_dh_pubkey == NULL) {
wpa_printf(MSG_DEBUG, "WPS: No NFC OOB Device Password "
"configured");
return NULL;
}
msg = wpabuf_alloc(1000);
if (msg == NULL)
return msg;
len = wpabuf_put(msg, 2);
if (wps_build_oob_dev_pw(msg, DEV_PW_NFC_CONNECTION_HANDOVER,
nfc_dh_pubkey, NULL, 0) ||
wps_build_ssid(msg, ctx) ||
wps_build_wfa_ext(msg, 0, NULL, 0)) {
wpabuf_free(msg);
return NULL;
}
WPA_PUT_BE16(len, wpabuf_len(msg) - 2);
return msg;
}
#endif /* CONFIG_WPS_NFC */

View file

@ -155,7 +155,8 @@ enum wps_dev_password_id {
DEV_PW_MACHINE_SPECIFIED = 0x0002,
DEV_PW_REKEY = 0x0003,
DEV_PW_PUSHBUTTON = 0x0004,
DEV_PW_REGISTRAR_SPECIFIED = 0x0005
DEV_PW_REGISTRAR_SPECIFIED = 0x0005,
DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007
};
/* Message Type */

View file

@ -1361,6 +1361,13 @@ static int wps_get_dev_password(struct wps_data *wps)
pin_len = 8;
#ifdef CONFIG_WPS_NFC
} else if (wps->nfc_pw_token) {
if (wps->nfc_pw_token->pw_id == DEV_PW_NFC_CONNECTION_HANDOVER)
{
wpa_printf(MSG_DEBUG, "WPS: Using NFC connection "
"handover and abbreviated WPS handshake "
"without Device Password");
return 0;
}
wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC "
"Password Token");
pin = wps->nfc_pw_token->dev_pw;
@ -2556,6 +2563,9 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
#ifdef CONFIG_WPS_NFC
wps->dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER &&
#endif /* CONFIG_WPS_NFC */
(wps->dev_pw_id != DEV_PW_PUSHBUTTON ||
!wps->wps->registrar->pbc)) {
wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d",
@ -2565,7 +2575,8 @@ static enum wps_process_res wps_process_m1(struct wps_data *wps,
}
#ifdef CONFIG_WPS_NFC
if (wps->dev_pw_id >= 0x10) {
if (wps->dev_pw_id >= 0x10 ||
wps->dev_pw_id == DEV_PW_NFC_CONNECTION_HANDOVER) {
struct wps_nfc_pw_token *token;
const u8 *addr[1];
u8 hash[WPS_HASH_LEN];
@ -3541,10 +3552,12 @@ int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg,
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);
token->dev_pw_len = dev_pw_len * 2;
if (dev_pw) {
wpa_snprintf_hex_uppercase((char *) token->dev_pw,
sizeof(token->dev_pw),
dev_pw, dev_pw_len);
token->dev_pw_len = dev_pw_len * 2;
}
dl_list_add(&reg->nfc_pw_tokens, &token->list);
@ -3573,8 +3586,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
u16 id;
size_t dev_pw_len;
if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
oob_dev_pw_len > WPS_OOB_PUBKEY_HASH_LEN + 2 +
WPS_OOB_DEVICE_PASSWORD_LEN)
return -1;