]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FILS: Allow FILS HLP requests to be added
authorJouni Malinen <jouni@qca.qualcomm.com>
Sun, 29 Jan 2017 12:07:20 +0000 (14:07 +0200)
committerJouni Malinen <j@w1.fi>
Sun, 29 Jan 2017 12:32:17 +0000 (14:32 +0200)
The new wpa_supplicant control interface commands FILS_HLP_REQ_FLUSH and
FILS_HLP_REQ_ADD can now be used to request FILS HLP requests to be
added to the (Re)Association Request frame whenever FILS authentication
is used.

FILS_HLP_REQ_ADD parameters use the following format:
<destination MAC address> <hexdump of payload starting from ethertype>

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
wpa_supplicant/ctrl_iface.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index b2fc0ba7d149625c0a0f70e3cfd8c355e59ca244..696ea04a309bf12d7aff1984c5f24bca36f056c8 100644 (file)
@@ -3483,11 +3483,18 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len)
 
 struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
                                     size_t *kek_len, const u8 **snonce,
-                                    const u8 **anonce)
+                                    const u8 **anonce,
+                                    const struct wpabuf **hlp,
+                                    unsigned int num_hlp)
 {
        struct wpabuf *buf;
+       size_t len;
+       unsigned int i;
 
-       buf = wpabuf_alloc(1000);
+       len = 1000;
+       for (i = 0; hlp && i < num_hlp; i++)
+               len += 10 + wpabuf_len(hlp[i]);
+       buf = wpabuf_alloc(len);
        if (!buf)
                return NULL;
 
@@ -3510,7 +3517,34 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
        wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
        wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
 
-       /* TODO: FILS HLP Container */
+       /* FILS HLP Container */
+       for (i = 0; hlp && i < num_hlp; i++) {
+               const u8 *pos = wpabuf_head(hlp[i]);
+               size_t left = wpabuf_len(hlp[i]);
+
+               wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+               if (left <= 254)
+                       len = 1 + left;
+               else
+                       len = 255;
+               wpabuf_put_u8(buf, len); /* Length */
+               /* Element ID Extension */
+               wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_HLP_CONTAINER);
+               /* Destination MAC Address, Source MAC Address, HLP Packet.
+                * HLP Packet is in MSDU format (i.e., included the LLC/SNAP
+                * header when LPD is used). */
+               wpabuf_put_data(buf, pos, len - 1);
+               pos += len - 1;
+               left -= len - 1;
+               while (left) {
+                       wpabuf_put_u8(buf, WLAN_EID_FRAGMENT);
+                       len = left > 255 ? 255 : left;
+                       wpabuf_put_u8(buf, len);
+                       wpabuf_put_data(buf, pos, len);
+                       pos += len;
+                       left -= len;
+               }
+       }
 
        /* TODO: FILS IP Address Assignment */
 
index c9f278aab166e0902a1aa575a09576fd2c0558d6..f0eeec8101b8c0cb9173e38f20ab80c041764cce 100644 (file)
@@ -436,7 +436,9 @@ struct wpabuf * fils_build_auth(struct wpa_sm *sm);
 int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len);
 struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
                                     size_t *kek_len, const u8 **snonce,
-                                    const u8 **anonce);
+                                    const u8 **anonce,
+                                    const struct wpabuf **hlp,
+                                    unsigned int num_hlp);
 int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len);
 int wpa_fils_is_completed(struct wpa_sm *sm);
 
index 39d2ff9ce03b6d9228aa97877a1921faf53e78f1..ead5fe63875c81424a1062efd8de53253bcef8ff 100644 (file)
@@ -9153,6 +9153,40 @@ static int wpas_ctrl_iface_mesh_pmksa_add(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
 
 
+#ifdef CONFIG_FILS
+static int wpas_ctrl_iface_fils_hlp_req_add(struct wpa_supplicant *wpa_s,
+                                           const char *cmd)
+{
+       struct fils_hlp_req *req;
+       const char *pos;
+
+       /* format: <dst> <packet starting from ethertype> */
+
+       req = os_zalloc(sizeof(*req));
+       if (!req)
+               return -1;
+
+       if (hwaddr_aton(cmd, req->dst))
+               goto fail;
+
+       pos = os_strchr(cmd, ' ');
+       if (!pos)
+               goto fail;
+       pos++;
+       req->pkt = wpabuf_parse_bin(pos);
+       if (!req->pkt)
+               goto fail;
+
+       dl_list_add_tail(&wpa_s->fils_hlp_req, &req->list);
+       return 0;
+fail:
+       wpabuf_free(req->pkt);
+       os_free(req);
+       return -1;
+}
+#endif /* CONFIG_FILS */
+
+
 static int wpas_ctrl_cmd_debug_level(const char *cmd)
 {
        if (os_strcmp(cmd, "PING") == 0 ||
@@ -9881,6 +9915,13 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "GET_PREF_FREQ_LIST ", 19) == 0) {
                reply_len = wpas_ctrl_iface_get_pref_freq_list(
                        wpa_s, buf + 19, reply, reply_size);
+#ifdef CONFIG_FILS
+       } else if (os_strncmp(buf, "FILS_HLP_REQ_ADD ", 17) == 0) {
+               if (wpas_ctrl_iface_fils_hlp_req_add(wpa_s, buf + 17))
+                       reply_len = -1;
+       } else if (os_strcmp(buf, "FILS_HLP_REQ_FLUSH") == 0) {
+               wpas_flush_fils_hlp_req(wpa_s);
+#endif /* CONFIG_FILS */
        } else {
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
                reply_len = 16;
index f478836dbe3c9396538600a52c18ddf4d7442808..744bc7b663d4fe91e27581395c30adb59f80b666 100644 (file)
@@ -995,10 +995,35 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
        if (auth_type == WLAN_AUTH_FILS_SK) {
                struct wpabuf *buf;
                const u8 *snonce, *anonce;
+               const unsigned int max_hlp = 20;
+               struct wpabuf *hlp[max_hlp];
+               unsigned int i, num_hlp = 0;
+               struct fils_hlp_req *req;
+
+               dl_list_for_each(req, &wpa_s->fils_hlp_req, struct fils_hlp_req,
+                                list) {
+                       hlp[num_hlp] = wpabuf_alloc(2 * ETH_ALEN + 6 +
+                                             wpabuf_len(req->pkt));
+                       if (!hlp[num_hlp])
+                               break;
+                       wpabuf_put_data(hlp[num_hlp], req->dst, ETH_ALEN);
+                       wpabuf_put_data(hlp[num_hlp], wpa_s->own_addr,
+                                       ETH_ALEN);
+                       wpabuf_put_data(hlp[num_hlp],
+                                       "\xaa\xaa\x03\x00\x00\x00", 6);
+                       wpabuf_put_buf(hlp[num_hlp], req->pkt);
+                       num_hlp++;
+                       if (num_hlp >= max_hlp)
+                               break;
+               }
 
                buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
                                           &params.fils_kek_len, &snonce,
-                                          &anonce);
+                                          &anonce,
+                                          (const struct wpabuf **) hlp,
+                                          num_hlp);
+               for (i = 0; i < num_hlp; i++)
+                       wpabuf_free(hlp[i]);
                if (!buf)
                        return;
                /* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
index bc59c6760990843ac190ab3a01bec9f5738f6fd8..39d57663c70c2cad4a7c98c65e2f1b8e77c9964f 100644 (file)
@@ -420,6 +420,19 @@ static void free_bss_tmp_disallowed(struct wpa_supplicant *wpa_s)
 }
 
 
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s)
+{
+       struct fils_hlp_req *req;
+
+       while ((req = dl_list_first(&wpa_s->fils_hlp_req, struct fils_hlp_req,
+                                   list)) != NULL) {
+               dl_list_del(&req->list);
+               wpabuf_free(req->pkt);
+               os_free(req);
+       }
+}
+
+
 static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 {
        int i;
@@ -602,6 +615,8 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
        }
 #endif /* CONFIG_MESH */
 #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
+
+       wpas_flush_fils_hlp_req(wpa_s);
 }
 
 
@@ -3719,6 +3734,7 @@ wpa_supplicant_alloc(struct wpa_supplicant *parent)
        wpa_s->sched_scanning = 0;
 
        dl_list_init(&wpa_s->bss_tmp_disallowed);
+       dl_list_init(&wpa_s->fils_hlp_req);
 
        return wpa_s;
 }
index 2fb32e28fe1b500c938d5588b6aacf5ff23e3091..cb6484783aad060f7d8dcafcdae5f91e4a78a75b 100644 (file)
@@ -466,6 +466,12 @@ struct external_pmksa_cache {
        void *pmksa_cache;
 };
 
+struct fils_hlp_req {
+       struct dl_list list;
+       u8 dst[ETH_ALEN];
+       struct wpabuf *pkt;
+};
+
 /**
  * struct wpa_supplicant - Internal data for wpa_supplicant interface
  *
@@ -747,7 +753,7 @@ struct wpa_supplicant {
                u8 ssid[SSID_MAX_LEN];
                size_t ssid_len;
                int freq;
-               u8 assoc_req_ie[300];
+               u8 assoc_req_ie[1500];
                size_t assoc_req_ie_len;
                int mfp;
                int ft_used;
@@ -1103,6 +1109,9 @@ struct wpa_supplicant {
        struct os_reltime lci_time;
 
        struct os_reltime beacon_rep_scan;
+
+       /* FILS HLP requests (struct fils_hlp_req) */
+       struct dl_list fils_hlp_req;
 };
 
 
@@ -1227,6 +1236,7 @@ int wpas_beacon_rep_scan_process(struct wpa_supplicant *wpa_s,
                                 struct wpa_scan_results *scan_res,
                                 struct scan_info *info);
 void wpas_clear_beacon_rep_data(struct wpa_supplicant *wpa_s);
+void wpas_flush_fils_hlp_req(struct wpa_supplicant *wpa_s);
 
 
 /* MBO functions */