SAE: Fix Anti-Clogging Token request frame format
authorMasashi Honma <masashi.honma@gmail.com>
Tue, 25 Nov 2014 02:04:41 +0000 (11:04 +0900)
committerJouni Malinen <j@w1.fi>
Tue, 25 Nov 2014 14:08:53 +0000 (16:08 +0200)
This commit inserts Finite Cyclic Group to Anti-Clogging Token request
frame because IEEE Std 802.11-2012, Table 8-29 says "Finite Cyclic Group
is present if Status is zero or 76".

Signed-off-by: Masashi Honma <masashi.honma@gmail.com>
src/ap/ieee802_11.c
src/common/sae.c
src/common/sae.h
wpa_supplicant/sme.c

index 1d0fa51..1dbd996 100644 (file)
@@ -449,7 +449,7 @@ static int check_sae_token(struct hostapd_data *hapd, const u8 *addr,
 
 
 static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
-                                           const u8 *addr)
+                                           int group, const u8 *addr)
 {
        struct wpabuf *buf;
        u8 *token;
@@ -466,10 +466,12 @@ static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd,
                hapd->last_sae_token_key_update = now;
        }
 
-       buf = wpabuf_alloc(SHA256_MAC_LEN);
+       buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN);
        if (buf == NULL)
                return NULL;
 
+       wpabuf_put_le16(buf, group); /* Finite Cyclic Group */
+
        token = wpabuf_put(buf, SHA256_MAC_LEN);
        hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key),
                    addr, ETH_ALEN, token);
@@ -630,7 +632,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
        }
 
        if (auth_transaction == 1) {
-               const u8 *token = NULL;
+               const u8 *token = NULL, *pos, *end;
                size_t token_len = 0;
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                               HOSTAPD_LEVEL_DEBUG,
@@ -639,11 +641,27 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                if ((hapd->conf->mesh & MESH_ENABLED) &&
                    mgmt->u.auth.status_code ==
                    WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && sta->sae->tmp) {
+                       pos = mgmt->u.auth.variable;
+                       end = ((const u8 *) mgmt) + len;
+                       if (pos + sizeof(le16) > end) {
+                               wpa_printf(MSG_ERROR,
+                                          "SAE: Too short anti-clogging token request");
+                               resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+                               goto reply;
+                       }
+                       resp = sae_group_allowed(sta->sae,
+                                                hapd->conf->sae_groups,
+                                                WPA_GET_LE16(pos));
+                       if (resp != WLAN_STATUS_SUCCESS) {
+                               wpa_printf(MSG_ERROR,
+                                          "SAE: Invalid group in anti-clogging token request");
+                               goto reply;
+                       }
+                       pos += sizeof(le16);
+
                        wpabuf_free(sta->sae->tmp->anti_clogging_token);
                        sta->sae->tmp->anti_clogging_token =
-                               wpabuf_alloc_copy(mgmt->u.auth.variable,
-                                                 ((const u8 *) mgmt) + len -
-                                                 mgmt->u.auth.variable);
+                               wpabuf_alloc_copy(pos, end - pos);
                        if (sta->sae->tmp->anti_clogging_token == NULL) {
                                wpa_printf(MSG_ERROR,
                                           "SAE: Failed to alloc for anti-clogging token");
@@ -685,7 +703,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Request anti-clogging token from "
                                   MACSTR, MAC2STR(sta->addr));
-                       data = auth_build_token_req(hapd, sta->addr);
+                       data = auth_build_token_req(hapd, sta->sae->group,
+                                                   sta->addr);
                        resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ;
                        if (hapd->conf->mesh & MESH_ENABLED)
                                sta->sae->state = SAE_NOTHING;
index 6454b4a..87d49b6 100644 (file)
@@ -686,8 +686,7 @@ void sae_write_commit(struct sae_data *sae, struct wpabuf *buf,
 }
 
 
-static u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups,
-                            u16 group)
+u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group)
 {
        if (allowed_groups) {
                int i;
index e78bb49..89d74ab 100644 (file)
@@ -61,5 +61,6 @@ u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len,
                     const u8 **token, size_t *token_len, int *allowed_groups);
 void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf);
 int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len);
+u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group);
 
 #endif /* SAE_H */
index da8e65e..7eb8966 100644 (file)
@@ -611,6 +611,8 @@ void sme_authenticate(struct wpa_supplicant *wpa_s,
 static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                        u16 status_code, const u8 *data, size_t len)
 {
+       int *groups;
+
        wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE authentication transaction %u "
                "status code %u", auth_transaction, status_code);
 
@@ -618,10 +620,32 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
            status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ &&
            wpa_s->sme.sae.state == SAE_COMMITTED &&
            wpa_s->current_bss && wpa_s->current_ssid) {
-               wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE anti-clogging token "
-                       "requested");
+               int default_groups[] = { 19, 20, 21, 25, 26, 0 };
+               u16 group;
+
+               groups = wpa_s->conf->sae_groups;
+               if (!groups || groups[0] <= 0)
+                       groups = default_groups;
+
+               if (len < sizeof(le16)) {
+                       wpa_dbg(wpa_s, MSG_DEBUG,
+                               "SME: Too short SAE anti-clogging token request");
+                       return -1;
+               }
+               group = WPA_GET_LE16(data);
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "SME: SAE anti-clogging token requested (group %u)",
+                       group);
+               if (sae_group_allowed(&wpa_s->sme.sae, groups, group) !=
+                   WLAN_STATUS_SUCCESS) {
+                       wpa_dbg(wpa_s, MSG_ERROR,
+                               "SME: SAE group %u of anti-clogging request is invalid",
+                               group);
+                       return -1;
+               }
                wpabuf_free(wpa_s->sme.sae_token);
-               wpa_s->sme.sae_token = wpabuf_alloc_copy(data, len);
+               wpa_s->sme.sae_token = wpabuf_alloc_copy(data + sizeof(le16),
+                                                        len - sizeof(le16));
                sme_send_authentication(wpa_s, wpa_s->current_bss,
                                        wpa_s->current_ssid, 1);
                return 0;
@@ -645,7 +669,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                return -1;
 
        if (auth_transaction == 1) {
-               int *groups = wpa_s->conf->sae_groups;
+               groups = wpa_s->conf->sae_groups;
 
                wpa_dbg(wpa_s, MSG_DEBUG, "SME SAE commit");
                if (wpa_s->current_bss == NULL ||