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:
parent
34b6795015
commit
975491793b
7 changed files with 131 additions and 16 deletions
|
@ -58,6 +58,10 @@ struct wps_data * wps_init(const struct wps_config *cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_WPS_NFC
|
#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) {
|
if (cfg->wps->ap && !cfg->registrar && cfg->wps->ap_nfc_dev_pw_id) {
|
||||||
/* Keep AP PIN as alternative Device Password */
|
/* Keep AP PIN as alternative Device Password */
|
||||||
data->alt_dev_pw_id = data->dev_pw_id;
|
data->alt_dev_pw_id = data->dev_pw_id;
|
||||||
|
|
|
@ -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 * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey,
|
||||||
struct wpabuf **privkey,
|
struct wpabuf **privkey,
|
||||||
struct wpabuf **dev_pw);
|
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 */
|
/* ndef.c */
|
||||||
struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf);
|
struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf);
|
||||||
|
|
|
@ -38,8 +38,11 @@ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg)
|
||||||
wps->wps->dh_ctx = NULL;
|
wps->wps->dh_ctx = NULL;
|
||||||
pubkey = wpabuf_dup(wps->wps->dh_pubkey);
|
pubkey = wpabuf_dup(wps->wps->dh_pubkey);
|
||||||
#ifdef CONFIG_WPS_NFC
|
#ifdef CONFIG_WPS_NFC
|
||||||
} else if (wps->dev_pw_id >= 0x10 && wps->wps->ap &&
|
} else if ((wps->dev_pw_id >= 0x10 ||
|
||||||
wps->dev_pw_id == wps->wps->ap_nfc_dev_pw_id) {
|
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");
|
wpa_printf(MSG_DEBUG, "WPS: Using NFC password token DH keys");
|
||||||
if (wps->wps->ap_nfc_dh_privkey == NULL) {
|
if (wps->wps->ap_nfc_dh_privkey == NULL) {
|
||||||
wpa_printf(MSG_DEBUG,
|
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);
|
pubkey_hash, WPS_OOB_PUBKEY_HASH_LEN);
|
||||||
wpabuf_put_data(msg, 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);
|
wpabuf_put_be16(msg, dev_pw_id);
|
||||||
wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
|
if (dev_pw) {
|
||||||
dev_pw, dev_pw_len);
|
wpa_hexdump_key(MSG_DEBUG, "WPS: OOB Device Password",
|
||||||
wpabuf_put_data(msg, dev_pw, dev_pw_len);
|
dev_pw, dev_pw_len);
|
||||||
|
wpabuf_put_data(msg, dev_pw, dev_pw_len);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,10 +263,13 @@ static int wps_set_attr(struct wps_parse_attr *attr, u16 type,
|
||||||
attr->dev_password_id = pos;
|
attr->dev_password_id = pos;
|
||||||
break;
|
break;
|
||||||
case ATTR_OOB_DEVICE_PASSWORD:
|
case ATTR_OOB_DEVICE_PASSWORD:
|
||||||
if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
|
if (len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
|
||||||
WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
|
|
||||||
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 "
|
wpa_printf(MSG_DEBUG, "WPS: Invalid OOB Device "
|
||||||
"Password length %u", len);
|
"Password length %u", len);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -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);
|
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 */
|
#endif /* CONFIG_WPS_NFC */
|
||||||
|
|
|
@ -155,7 +155,8 @@ enum wps_dev_password_id {
|
||||||
DEV_PW_MACHINE_SPECIFIED = 0x0002,
|
DEV_PW_MACHINE_SPECIFIED = 0x0002,
|
||||||
DEV_PW_REKEY = 0x0003,
|
DEV_PW_REKEY = 0x0003,
|
||||||
DEV_PW_PUSHBUTTON = 0x0004,
|
DEV_PW_PUSHBUTTON = 0x0004,
|
||||||
DEV_PW_REGISTRAR_SPECIFIED = 0x0005
|
DEV_PW_REGISTRAR_SPECIFIED = 0x0005,
|
||||||
|
DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Message Type */
|
/* Message Type */
|
||||||
|
|
|
@ -1361,6 +1361,13 @@ static int wps_get_dev_password(struct wps_data *wps)
|
||||||
pin_len = 8;
|
pin_len = 8;
|
||||||
#ifdef CONFIG_WPS_NFC
|
#ifdef CONFIG_WPS_NFC
|
||||||
} else if (wps->nfc_pw_token) {
|
} 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 "
|
wpa_printf(MSG_DEBUG, "WPS: Use OOB Device Password from NFC "
|
||||||
"Password Token");
|
"Password Token");
|
||||||
pin = wps->nfc_pw_token->dev_pw;
|
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_USER_SPECIFIED &&
|
||||||
wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
|
wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
|
||||||
wps->dev_pw_id != DEV_PW_REGISTRAR_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->dev_pw_id != DEV_PW_PUSHBUTTON ||
|
||||||
!wps->wps->registrar->pbc)) {
|
!wps->wps->registrar->pbc)) {
|
||||||
wpa_printf(MSG_DEBUG, "WPS: Unsupported Device Password ID %d",
|
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
|
#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;
|
struct wps_nfc_pw_token *token;
|
||||||
const u8 *addr[1];
|
const u8 *addr[1];
|
||||||
u8 hash[WPS_HASH_LEN];
|
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);
|
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;
|
token->pk_hash_provided_oob = pk_hash_provided_oob;
|
||||||
wpa_snprintf_hex_uppercase((char *) token->dev_pw,
|
if (dev_pw) {
|
||||||
sizeof(token->dev_pw),
|
wpa_snprintf_hex_uppercase((char *) token->dev_pw,
|
||||||
dev_pw, dev_pw_len);
|
sizeof(token->dev_pw),
|
||||||
token->dev_pw_len = dev_pw_len * 2;
|
dev_pw, dev_pw_len);
|
||||||
|
token->dev_pw_len = dev_pw_len * 2;
|
||||||
|
}
|
||||||
|
|
||||||
dl_list_add(®->nfc_pw_tokens, &token->list);
|
dl_list_add(®->nfc_pw_tokens, &token->list);
|
||||||
|
|
||||||
|
@ -3573,8 +3586,7 @@ int wps_registrar_add_nfc_password_token(struct wps_registrar *reg,
|
||||||
u16 id;
|
u16 id;
|
||||||
size_t dev_pw_len;
|
size_t dev_pw_len;
|
||||||
|
|
||||||
if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 +
|
if (oob_dev_pw_len < WPS_OOB_PUBKEY_HASH_LEN + 2 ||
|
||||||
WPS_OOB_DEVICE_PASSWORD_MIN_LEN ||
|
|
||||||
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)
|
WPS_OOB_DEVICE_PASSWORD_LEN)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
Loading…
Reference in a new issue