From 975491793b3b4a0bd33bf783773bed5abb85fea8 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 2 Apr 2013 18:30:58 +0300 Subject: [PATCH] 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 --- src/wps/wps.c | 4 ++ src/wps/wps.h | 4 ++ src/wps/wps_attr_build.c | 15 ++++--- src/wps/wps_attr_parse.c | 9 +++-- src/wps/wps_common.c | 86 ++++++++++++++++++++++++++++++++++++++++ src/wps/wps_defs.h | 3 +- src/wps/wps_registrar.c | 26 ++++++++---- 7 files changed, 131 insertions(+), 16 deletions(-) diff --git a/src/wps/wps.c b/src/wps/wps.c index 80343c8a3..a38a6dbee 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -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; diff --git a/src/wps/wps.h b/src/wps/wps.h index c093b26d1..66242ca43 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -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); diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index 666c98d20..2f0c47c3d 100644 --- a/src/wps/wps_attr_build.c +++ b/src/wps/wps_attr_build.c @@ -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; } diff --git a/src/wps/wps_attr_parse.c b/src/wps/wps_attr_parse.c index 3999b1b88..f4e2e3853 100644 --- a/src/wps/wps_attr_parse.c +++ b/src/wps/wps_attr_parse.c @@ -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; diff --git a/src/wps/wps_common.c b/src/wps/wps_common.c index b1eb682ea..1c0e3ed5a 100644 --- a/src/wps/wps_common.c +++ b/src/wps/wps_common.c @@ -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 */ diff --git a/src/wps/wps_defs.h b/src/wps/wps_defs.h index 124960641..a736f2756 100644 --- a/src/wps/wps_defs.h +++ b/src/wps/wps_defs.h @@ -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 */ diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index b8709b9f7..f8f2ae19a 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -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(®->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;