]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS NFC: Update NFC connection handover design
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 2 Apr 2013 15:30:58 +0000 (18:30 +0300)
committerJouni Malinen <j@w1.fi>
Mon, 27 Jan 2014 19:10:55 +0000 (21:10 +0200)
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>

src/wps/wps.c
src/wps/wps.h
src/wps/wps_attr_build.c
src/wps/wps_attr_parse.c
src/wps/wps_common.c
src/wps/wps_defs.h
src/wps/wps_registrar.c

index 80343c8a3de43fb0f9fd49231dbd1451f36e7747..a38a6dbee31efa2983065b6fccd7f686515edab6 100644 (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;
index c093b26d1ad5e1041c805f1331611050cb3ff2fe..66242ca43c3600b573bf9fb85746caf225fbfbb1 100644 (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);
index 666c98d20d5b9c34f04d2d809b8827843613c528..2f0c47c3d3bf4252d5b7733972edf0cdd503fe21 100644 (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;
 }
index 3999b1b88108d64dce872ef17b22d803011eda14..f4e2e3853914393a253e8b0452f10926f424a417 100644 (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;
index b1eb682eae7fe2c3378496d38d5cf2873654f124..1c0e3ed5a35b4dd73063ebbeabab1f5676e8233c 100644 (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 */
index 1249606418d03bab3d8e3c8e1b4b028389716df8..a736f2756815239d572c3f4e7532bf3c82e037a8 100644 (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 */
index b8709b9f7b2a5434c03ab3a0adaf48376454a337..f8f2ae19a11f4a3a924414d6a10f442cb2b89b98 100644 (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;