]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P NFC: Static handover with NFC Tag on client
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 8 Sep 2013 16:45:04 +0000 (09:45 -0700)
committerJouni Malinen <j@w1.fi>
Mon, 27 Jan 2014 19:44:30 +0000 (21:44 +0200)
This adds a new P2P Invitation mechanism to invite a P2P Device with an
NFC Tag to an already operating group when the GO with NFC Device reads
the NFC Tag. The P2P Device with the NFC Tag will then accept invitation
and connect to the group automatically using its OOB Device Password.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_i.h
src/p2p/p2p_invitation.c
src/p2p/p2p_parse.c
wpa_supplicant/p2p_supplicant.c

index c553e238cc3888d9b8a757818389194bf72bc8a1..ca347e7b63105ce38e26ad95a86fc482e0524bd7 100644 (file)
@@ -1762,7 +1762,8 @@ static void p2p_invite_start(void *eloop_ctx, void *timeout_ctx)
        if (p2p->invite_peer == NULL)
                return;
        p2p->cfg->stop_listen(p2p->cfg->cb_ctx);
-       p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr);
+       p2p_invite_send(p2p, p2p->invite_peer, p2p->invite_go_dev_addr,
+                       p2p->invite_dev_pw_id);
 }
 
 
@@ -3277,7 +3278,7 @@ static void p2p_timeout_invite_listen(struct p2p_data *p2p)
        if (p2p->invite_peer && p2p->invite_peer->invitation_reqs < 100) {
                p2p_set_state(p2p, P2P_INVITE);
                p2p_invite_send(p2p, p2p->invite_peer,
-                               p2p->invite_go_dev_addr);
+                               p2p->invite_go_dev_addr, p2p->invite_dev_pw_id);
        } else {
                if (p2p->invite_peer) {
                        p2p_dbg(p2p, "Invitation Request retry limit reached");
index 3d8ee1f99924b78298654591ba3043e42faf537b..08e7176c1d436113a0de1a16f622d67f6c136c5f 100644 (file)
@@ -708,6 +708,8 @@ struct p2p_config {
         *      persistent group (instead of invitation to join an active
         *      group)
         * @channels: Available operating channels for the group
+        * @dev_pw_id: Device Password ID for NFC static handover or -1 if not
+        *      used
         * Returns: Status code (P2P_SC_*)
         *
         * This optional callback can be used to implement persistent reconnect
@@ -729,7 +731,8 @@ struct p2p_config {
                                 const u8 *go_dev_addr, const u8 *ssid,
                                 size_t ssid_len, int *go, u8 *group_bssid,
                                 int *force_freq, int persistent_group,
-                                const struct p2p_channels *channels);
+                                const struct p2p_channels *channels,
+                                int dev_pw_id);
 
        /**
         * invitation_received - Callback on Invitation Request RX
@@ -1104,12 +1107,14 @@ enum p2p_invite_role {
  * @persistent_group: Whether this is to reinvoke a persistent group
  * @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if
  *     force_freq == 0)
+ * @dev_pw_id: Device Password ID from OOB Device Password (NFC) static handover
+ *     case or -1 if not used
  * Returns: 0 on success, -1 on failure
  */
 int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
               const u8 *bssid, const u8 *ssid, size_t ssid_len,
               unsigned int force_freq, const u8 *go_dev_addr,
-              int persistent_group, unsigned int pref_freq);
+              int persistent_group, unsigned int pref_freq, int dev_pw_id);
 
 /**
  * p2p_presence_req - Request GO presence
index 1150d405137aee1c3cc5688ea04f0af3ea0b0a3c..6ebaa846d6ab298eb106e67656b11fa13ce8d111 100644 (file)
@@ -243,6 +243,7 @@ struct p2p_data {
 
        const u8 *invite_go_dev_addr;
        u8 invite_go_dev_addr_buf[ETH_ALEN];
+       int invite_dev_pw_id;
 
        /**
         * sd_peer - Pointer to Service Discovery peer
@@ -522,6 +523,7 @@ struct p2p_message {
 
        /* WPS IE */
        u16 dev_password_id;
+       int dev_password_id_present;
        u16 wps_config_methods;
        const u8 *wps_pri_dev_type;
        const u8 *wps_sec_dev_type_list;
@@ -699,7 +701,7 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
 void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
                                 const u8 *data, size_t len);
 int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
-                   const u8 *go_dev_addr);
+                   const u8 *go_dev_addr, int dev_pw_id);
 void p2p_invitation_req_cb(struct p2p_data *p2p, int success);
 void p2p_invitation_resp_cb(struct p2p_data *p2p, int success);
 
index 2734386e3e2fe188f56bc8c8b1cf1f8a66428831..98cfb3303c021cd78496e8e3ded3aae8f426fc26 100644 (file)
@@ -16,7 +16,8 @@
 
 static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
                                                struct p2p_device *peer,
-                                               const u8 *go_dev_addr)
+                                               const u8 *go_dev_addr,
+                                               int dev_pw_id)
 {
        struct wpabuf *buf;
        u8 *len;
@@ -85,6 +86,11 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
                wpabuf_put_buf(buf, wfd_ie);
 #endif /* CONFIG_WIFI_DISPLAY */
 
+       if (dev_pw_id >= 0) {
+               /* WSC IE in Invitation Request for NFC static handover */
+               p2p_build_wps_ie(p2p, buf, dev_pw_id, 0);
+       }
+
        return buf;
 }
 
@@ -228,7 +234,8 @@ void p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa,
                status = p2p->cfg->invitation_process(
                        p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id,
                        msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
-                       &go, group_bssid, &op_freq, persistent, &intersection);
+                       &go, group_bssid, &op_freq, persistent, &intersection,
+                       msg.dev_password_id_present ? msg.dev_password_id : -1);
        }
 
        if (op_freq) {
@@ -450,12 +457,14 @@ void p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa,
 
 
 int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
-                   const u8 *go_dev_addr)
+                   const u8 *go_dev_addr, int dev_pw_id)
 {
        struct wpabuf *req;
        int freq;
 
        freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
+       if (freq <= 0)
+               freq = dev->oob_go_neg_freq;
        if (freq <= 0) {
                p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
                        MACSTR " to send Invitation Request",
@@ -463,7 +472,7 @@ int p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev,
                return -1;
        }
 
-       req = p2p_build_invitation_req(p2p, dev, go_dev_addr);
+       req = p2p_build_invitation_req(p2p, dev, go_dev_addr, dev_pw_id);
        if (req == NULL)
                return -1;
        if (p2p->state != P2P_IDLE)
@@ -528,7 +537,7 @@ void p2p_invitation_resp_cb(struct p2p_data *p2p, int success)
 int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
               const u8 *bssid, const u8 *ssid, size_t ssid_len,
               unsigned int force_freq, const u8 *go_dev_addr,
-              int persistent_group, unsigned int pref_freq)
+              int persistent_group, unsigned int pref_freq, int dev_pw_id)
 {
        struct p2p_device *dev;
 
@@ -546,9 +555,15 @@ int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
                p2p->invite_go_dev_addr = NULL;
        wpa_hexdump_ascii(MSG_DEBUG, "Invitation for SSID",
                          ssid, ssid_len);
+       if (dev_pw_id >= 0) {
+               p2p_dbg(p2p, "Invitation to use Device Password ID %d",
+                       dev_pw_id);
+       }
+       p2p->invite_dev_pw_id = dev_pw_id;
 
        dev = p2p_get_device(p2p, peer);
-       if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) {
+       if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0 &&
+                           dev->oob_go_neg_freq <= 0)) {
                p2p_dbg(p2p, "Cannot invite unknown P2P Device " MACSTR,
                        MAC2STR(peer));
                return -1;
@@ -586,5 +601,5 @@ int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
        os_memcpy(p2p->inv_ssid, ssid, ssid_len);
        p2p->inv_ssid_len = ssid_len;
        p2p->inv_persistent = persistent_group;
-       return p2p_invite_send(p2p, dev, go_dev_addr);
+       return p2p_invite_send(p2p, dev, go_dev_addr, dev_pw_id);
 }
index bc548e8d40e085a2f68e9776a178de643838d619..d6144a0ebc6de0f6bd3d2b625deeb1ca7769a76f 100644 (file)
@@ -353,6 +353,7 @@ static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
                msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
                wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
                           msg->dev_password_id);
+               msg->dev_password_id_present = 1;
        }
        if (attr.primary_dev_type) {
                char devtype[WPS_DEV_TYPE_BUFSIZE];
index b1e25ad072773ac3147cc6e96efae8cf3e6353c7..7920276bab4aa4a649aabac451109eed42867ef7 100644 (file)
@@ -1109,9 +1109,9 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
                                    struct p2p_go_neg_results *res)
 {
        wpa_printf(MSG_DEBUG, "P2P: Start WPS Enrollee for peer " MACSTR
-                  " dev_addr " MACSTR,
+                  " dev_addr " MACSTR " wps_method %d",
                   MAC2STR(res->peer_interface_addr),
-                  MAC2STR(res->peer_device_addr));
+                  MAC2STR(res->peer_device_addr), res->wps_method);
        wpa_hexdump_ascii(MSG_DEBUG, "P2P: Start WPS Enrollee for SSID",
                          res->ssid, res->ssid_len);
        wpa_supplicant_ap_deinit(wpa_s);
@@ -2901,7 +2901,8 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
                                  const u8 *go_dev_addr, const u8 *ssid,
                                  size_t ssid_len, int *go, u8 *group_bssid,
                                  int *force_freq, int persistent_group,
-                                 const struct p2p_channels *channels)
+                                 const struct p2p_channels *channels,
+                                 int dev_pw_id)
 {
        struct wpa_supplicant *wpa_s = ctx;
        struct wpa_ssid *s;
@@ -2920,6 +2921,21 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid,
                                   "authorized invitation");
                        goto accept_inv;
                }
+
+#ifdef CONFIG_WPS_NFC
+               if (dev_pw_id >= 0 && wpa_s->parent->p2p_nfc_tag_enabled &&
+                   dev_pw_id == wpa_s->parent->p2p_oob_dev_pw_id) {
+                       wpa_printf(MSG_DEBUG, "P2P: Accept invitation based on local enabled NFC Tag");
+                       wpa_s->parent->p2p_wps_method = WPS_NFC;
+                       wpa_s->parent->pending_join_wps_method = WPS_NFC;
+                       os_memcpy(wpa_s->parent->pending_join_dev_addr,
+                                 go_dev_addr, ETH_ALEN);
+                       os_memcpy(wpa_s->parent->pending_join_iface_addr,
+                                 bssid, ETH_ALEN);
+                       goto accept_inv;
+               }
+#endif /* CONFIG_WPS_NFC */
+
                /*
                 * Do not accept the invitation automatically; notify user and
                 * request approval.
@@ -5722,7 +5738,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
 
        return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
                          ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr,
-                         1, pref_freq);
+                         1, pref_freq, -1);
 }
 
 
@@ -5796,7 +5812,7 @@ int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
 
        return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
                          ssid->ssid, ssid->ssid_len, force_freq,
-                         go_dev_addr, persistent, pref_freq);
+                         go_dev_addr, persistent, pref_freq, -1);
 }
 
 
@@ -7158,12 +7174,15 @@ static int wpas_p2p_nfc_join_group(struct wpa_supplicant *wpa_s,
 
 
 static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s,
-                                 struct p2p_nfc_params *params)
+                                 struct p2p_nfc_params *params, int tag)
 {
+       int res, persistent;
+       struct wpa_ssid *ssid;
+
        wpa_printf(MSG_DEBUG, "P2P: Authorize join-group based on NFC "
                   "connection handover");
        for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
-               struct wpa_ssid *ssid = wpa_s->current_ssid;
+               ssid = wpa_s->current_ssid;
                if (ssid == NULL)
                        continue;
                if (ssid->mode != WPAS_MODE_P2P_GO)
@@ -7183,11 +7202,38 @@ static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s,
                wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known");
                return -1;
        }
-       return wpas_ap_wps_add_nfc_pw(
+       res = wpas_ap_wps_add_nfc_pw(
                wpa_s, wpa_s->parent->p2p_oob_dev_pw_id,
                wpa_s->parent->p2p_oob_dev_pw,
                wpa_s->parent->p2p_peer_oob_pk_hash_known ?
                wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL);
+       if (res)
+               return res;
+
+       if (!tag) {
+               wpa_printf(MSG_DEBUG, "P2P: Negotiated handover - wait for peer to join without invitation");
+               return 0;
+       }
+
+       if (!params->peer ||
+           !(params->peer->dev_capab & P2P_DEV_CAPAB_INVITATION_PROCEDURE))
+               return 0;
+
+       wpa_printf(MSG_DEBUG, "P2P: Static handover - invite peer " MACSTR
+                  " to join", MAC2STR(params->peer->p2p_device_addr));
+
+       wpa_s->global->p2p_invite_group = wpa_s;
+       persistent = ssid->p2p_persistent_group &&
+               wpas_p2p_get_persistent(wpa_s->parent,
+                                       params->peer->p2p_device_addr,
+                                       ssid->ssid, ssid->ssid_len);
+       wpa_s->parent->pending_invite_ssid_id = -1;
+
+       return p2p_invite(wpa_s->global->p2p, params->peer->p2p_device_addr,
+                         P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr,
+                         ssid->ssid, ssid->ssid_len, ssid->frequency,
+                         wpa_s->global->p2p_dev_addr, persistent, 0,
+                         wpa_s->parent->p2p_oob_dev_pw_id);
 }
 
 
@@ -7378,7 +7424,7 @@ static int wpas_p2p_nfc_connection_handover(struct wpa_supplicant *wpa_s,
        case JOIN_GROUP:
                return wpas_p2p_nfc_join_group(wpa_s, &params);
        case AUTH_JOIN:
-               return wpas_p2p_nfc_auth_join(wpa_s, &params);
+               return wpas_p2p_nfc_auth_join(wpa_s, &params, tag);
        case INIT_GO_NEG:
                return wpas_p2p_nfc_init_go_neg(wpa_s, &params);
        case RESP_GO_NEG: