]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Allow management group cipher to be configured
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 12 Mar 2014 18:26:37 +0000 (20:26 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 14 Mar 2014 19:58:45 +0000 (21:58 +0200)
This allows hostapd to set a different management group cipher than the
previously hardcoded default BIP (AES-128-CMAC). The new configuration
file parameter group_mgmt_cipher can be set to BIP-GMAC-128,
BIP-GMAC-256, or BIP-CMAC-256 to select one of the ciphers defined in
IEEE Std 802.11ac-2013.

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
14 files changed:
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c
src/ap/wpa_auth_i.h
src/ap/wpa_auth_ie.c
src/common/wpa_common.c
src/common/wpa_common.h
src/rsn_supp/wpa.c
src/rsn_supp/wpa_ie.c
wpa_supplicant/wpa_supplicant.c

index f018f9632c06c8a5e195e2efa43999a7a1dc997f..814468d11491cb764a03c322138b3f9896bfd68e 100644 (file)
@@ -2600,6 +2600,20 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 #ifdef CONFIG_IEEE80211W
        } else if (os_strcmp(buf, "ieee80211w") == 0) {
                bss->ieee80211w = atoi(pos);
+       } else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
+               if (os_strcmp(pos, "AES-128-CMAC") == 0) {
+                       bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
+               } else if (os_strcmp(pos, "BIP-GMAC-128") == 0) {
+                       bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_128;
+               } else if (os_strcmp(pos, "BIP-GMAC-256") == 0) {
+                       bss->group_mgmt_cipher = WPA_CIPHER_BIP_GMAC_256;
+               } else if (os_strcmp(pos, "BIP-CMAC-256") == 0) {
+                       bss->group_mgmt_cipher = WPA_CIPHER_BIP_CMAC_256;
+               } else {
+                       wpa_printf(MSG_ERROR, "Line %d: invalid group_mgmt_cipher: %s",
+                                  line, pos);
+                       return 1;
+               }
        } else if (os_strcmp(buf, "assoc_sa_query_max_timeout") == 0) {
                bss->assoc_sa_query_max_timeout = atoi(pos);
                if (bss->assoc_sa_query_max_timeout == 0) {
index 81ddabc2a44c6c9ae87c71316a35c391598d3faf..23ee1e5b59440e3410a147740dc7782327c1ae0b 100644 (file)
@@ -1104,6 +1104,17 @@ own_ip_addr=127.0.0.1
 # 2 = required
 #ieee80211w=0
 
+# Group management cipher suite
+# Default: AES-128-CMAC (BIP)
+# Other options (depending on driver support):
+# BIP-GMAC-128
+# BIP-GMAC-256
+# BIP-CMAC-256
+# Note: All the stations connecting to the BSS will also need to support the
+# selected cipher. The default AES-128-CMAC is the only option that is commonly
+# available in deployed devices.
+#group_mgmt_cipher=AES-128-CMAC
+
 # Association SA Query maximum timeout (in TU = 1.024 ms; for MFP)
 # (maximum time to wait for a SA Query response)
 # dot11AssociationSAQueryMaximumTimeout, 1...4294967295
index 3ca85a0fa0a443382af9d6b8df6e9872a2e007ad..c17b016b05378eea1d87b2cd4dbc933b96fe42c3 100644 (file)
@@ -73,6 +73,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
 #ifdef CONFIG_IEEE80211W
        bss->assoc_sa_query_max_timeout = 1000;
        bss->assoc_sa_query_retry_timeout = 201;
+       bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
 #endif /* CONFIG_IEEE80211W */
 #ifdef EAP_SERVER_FAST
         /* both anonymous and authenticated provisioning */
index aa3a51aee297cb13551a35e2e9a25586adcebde1..25eb4903b26e12e072563300e056d6828424f6c0 100644 (file)
@@ -254,6 +254,7 @@ struct hostapd_bss_config {
        int wpa_key_mgmt;
 #ifdef CONFIG_IEEE80211W
        enum mfp_options ieee80211w;
+       int group_mgmt_cipher;
        /* dot11AssociationSAQueryMaximumTimeout (in TUs) */
        unsigned int assoc_sa_query_max_timeout;
        /* dot11AssociationSAQueryRetryTimeout (in TUs) */
index 7d89edf45a83f6c4afa0ef940ab95efcc919e00d..4d19bb0336a8d93426a4ab4e880c359731645c92 100644 (file)
@@ -1918,7 +1918,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
 static int ieee80211w_kde_len(struct wpa_state_machine *sm)
 {
        if (sm->mgmt_frame_prot) {
-               return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde);
+               size_t len;
+               len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+               return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
        }
 
        return 0;
@@ -1930,6 +1932,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
        struct wpa_igtk_kde igtk;
        struct wpa_group *gsm = sm->group;
        u8 rsc[WPA_KEY_RSC_LEN];
+       size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 
        if (!sm->mgmt_frame_prot)
                return pos;
@@ -1941,17 +1944,18 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
                os_memset(igtk.pn, 0, sizeof(igtk.pn));
        else
                os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
-       os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
+       os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
        if (sm->wpa_auth->conf.disable_gtk) {
                /*
                 * Provide unique random IGTK to each STA to prevent use of
                 * IGTK in the BSS.
                 */
-               if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0)
+               if (random_get_bytes(igtk.igtk, len) < 0)
                        return pos;
        }
        pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
-                         (const u8 *) &igtk, sizeof(igtk), NULL, 0);
+                         (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
+                         NULL, 0);
 
        return pos;
 }
@@ -2457,15 +2461,16 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
 
 #ifdef CONFIG_IEEE80211W
        if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+               size_t len;
+               len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
                os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
                inc_byte_array(group->Counter, WPA_NONCE_LEN);
                if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
                                   wpa_auth->addr, group->GNonce,
-                                  group->IGTK[group->GN_igtk - 4],
-                                  WPA_IGTK_LEN) < 0)
+                                  group->IGTK[group->GN_igtk - 4], len) < 0)
                        ret = -1;
                wpa_hexdump_key(MSG_DEBUG, "IGTK",
-                               group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
+                               group->IGTK[group->GN_igtk - 4], len);
        }
 #endif /* CONFIG_IEEE80211W */
 
@@ -2582,26 +2587,27 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
 {
        struct wpa_group *gsm = sm->group;
        u8 *start = pos;
+       size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
 
        /*
         * IGTK subelement:
         * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
         */
        *pos++ = WNM_SLEEP_SUBELEM_IGTK;
-       *pos++ = 2 + 6 + WPA_IGTK_LEN;
+       *pos++ = 2 + 6 + len;
        WPA_PUT_LE16(pos, gsm->GN_igtk);
        pos += 2;
        if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
                return 0;
        pos += 6;
 
-       os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
-       pos += WPA_IGTK_LEN;
+       os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
+       pos += len;
 
        wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
                   gsm->GN_igtk);
        wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
-                       gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
+                       gsm->IGTK[gsm->GN_igtk - 4], len);
 
        return pos - start;
 }
@@ -2656,12 +2662,19 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
                ret = -1;
 
 #ifdef CONFIG_IEEE80211W
-       if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
-           wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
-                            broadcast_ether_addr, group->GN_igtk,
-                            group->IGTK[group->GN_igtk - 4],
-                            WPA_IGTK_LEN) < 0)
-               ret = -1;
+       if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+               enum wpa_alg alg;
+               size_t len;
+
+               alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
+               len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+
+               if (ret == 0 &&
+                   wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
+                                    broadcast_ether_addr, group->GN_igtk,
+                                    group->IGTK[group->GN_igtk - 4], len) < 0)
+                       ret = -1;
+       }
 #endif /* CONFIG_IEEE80211W */
 
        return ret;
index d99db691b64769e95837ff741eb937cb6b832953..3ab3e3d5d084ed85cde9b7fa0a2bb80b0db0ee65 100644 (file)
@@ -142,6 +142,7 @@ struct wpa_auth_config {
        int tx_status;
 #ifdef CONFIG_IEEE80211W
        enum mfp_options ieee80211w;
+       int group_mgmt_cipher;
 #endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_IEEE80211R
 #define SSID_LEN 32
index da5fea7cedaae6f880e79ededd9f1a6f15c15d26..6ee9a4f83893c47784d460ed0ba6674035ed6d95 100644 (file)
@@ -49,6 +49,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
        wconf->okc = conf->okc;
 #ifdef CONFIG_IEEE80211W
        wconf->ieee80211w = conf->ieee80211w;
+       wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
 #endif /* CONFIG_IEEE80211W */
 #ifdef CONFIG_IEEE80211R
        wconf->ssid_len = conf->ssid.ssid_len;
index fcd5878e7494070ceb66908292afdb7a4fdd33f7..2e1bdcf48643a92bec0c6124a248a98aa44137d7 100644 (file)
@@ -154,7 +154,7 @@ struct wpa_group {
        Boolean first_sta_seen;
        Boolean reject_4way_hs_for_entropy;
 #ifdef CONFIG_IEEE80211W
-       u8 IGTK[2][WPA_IGTK_LEN];
+       u8 IGTK[2][WPA_IGTK_MAX_LEN];
        int GN_igtk, GM_igtk;
 #endif /* CONFIG_IEEE80211W */
 };
index 7a497516f782c14d5a5930636c9eaebef6d98179..e957c6e920714b084c072428e61f2290c396634e 100644 (file)
@@ -261,7 +261,25 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
                }
 
                /* Management Group Cipher Suite */
-               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+               switch (conf->group_mgmt_cipher) {
+               case WPA_CIPHER_AES_128_CMAC:
+                       RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+                       break;
+               case WPA_CIPHER_BIP_GMAC_128:
+                       RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128);
+                       break;
+               case WPA_CIPHER_BIP_GMAC_256:
+                       RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
+                       break;
+               case WPA_CIPHER_BIP_CMAC_256:
+                       RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256);
+                       break;
+               default:
+                       wpa_printf(MSG_DEBUG,
+                                  "Invalid group management cipher (0x%x)",
+                                  conf->group_mgmt_cipher);
+                       return -1;
+               }
                pos += RSN_SELECTOR_LEN;
        }
 #endif /* CONFIG_IEEE80211W */
@@ -586,7 +604,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
                        return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
                }
 
-               if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
+               if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher)
+               {
                        wpa_printf(MSG_DEBUG, "Unsupported management group "
                                   "cipher %d", data.mgmt_group_cipher);
                        return WPA_INVALID_MGMT_GROUP_CIPHER;
index 27f58aa3172a0aed10016fdd700d4a97f8b44f0f..adb22c76ec98dd6ffcf2ef772c664cf6e179b407 100644 (file)
@@ -368,6 +368,8 @@ static int rsn_selector_to_bitfield(const u8 *s)
                return WPA_CIPHER_BIP_GMAC_256;
        if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256)
                return WPA_CIPHER_BIP_CMAC_256;
+       if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED)
+               return WPA_CIPHER_GTK_NOT_USED;
        return 0;
 }
 
@@ -400,6 +402,26 @@ static int rsn_key_mgmt_to_bitfield(const u8 *s)
 }
 
 
+static int wpa_cipher_valid_group(int cipher)
+{
+       return wpa_cipher_valid_pairwise(cipher) ||
+               cipher == WPA_CIPHER_WEP104 ||
+               cipher == WPA_CIPHER_WEP40 ||
+               cipher == WPA_CIPHER_GTK_NOT_USED;
+}
+
+
+#ifdef CONFIG_IEEE80211W
+int wpa_cipher_valid_mgmt_group(int cipher)
+{
+       return cipher == WPA_CIPHER_AES_128_CMAC ||
+               cipher == WPA_CIPHER_BIP_GMAC_128 ||
+               cipher == WPA_CIPHER_BIP_GMAC_256 ||
+               cipher == WPA_CIPHER_BIP_CMAC_256;
+}
+#endif /* CONFIG_IEEE80211W */
+
+
 /**
  * wpa_parse_wpa_ie_rsn - Parse RSN IE
  * @rsn_ie: Buffer containing RSN IE
@@ -455,13 +477,11 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
 
        if (left >= RSN_SELECTOR_LEN) {
                data->group_cipher = rsn_selector_to_bitfield(pos);
-#ifdef CONFIG_IEEE80211W
-               if (data->group_cipher == WPA_CIPHER_AES_128_CMAC) {
-                       wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as group "
-                                  "cipher", __func__);
+               if (!wpa_cipher_valid_group(data->group_cipher)) {
+                       wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x",
+                                  __func__, data->group_cipher);
                        return -1;
                }
-#endif /* CONFIG_IEEE80211W */
                pos += RSN_SELECTOR_LEN;
                left -= RSN_SELECTOR_LEN;
        } else if (left > 0) {
@@ -546,7 +566,7 @@ int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len,
 #ifdef CONFIG_IEEE80211W
        if (left >= 4) {
                data->mgmt_group_cipher = rsn_selector_to_bitfield(pos);
-               if (data->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
+               if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) {
                        wpa_printf(MSG_DEBUG, "%s: Unsupported management "
                                   "group cipher 0x%x", __func__,
                                   data->mgmt_group_cipher);
@@ -1103,9 +1123,13 @@ int wpa_cipher_key_len(int cipher)
        switch (cipher) {
        case WPA_CIPHER_CCMP_256:
        case WPA_CIPHER_GCMP_256:
+       case WPA_CIPHER_BIP_GMAC_256:
+       case WPA_CIPHER_BIP_CMAC_256:
                return 32;
        case WPA_CIPHER_CCMP:
        case WPA_CIPHER_GCMP:
+       case WPA_CIPHER_AES_128_CMAC:
+       case WPA_CIPHER_BIP_GMAC_128:
                return 16;
        case WPA_CIPHER_TKIP:
                return 32;
@@ -1153,6 +1177,14 @@ int wpa_cipher_to_alg(int cipher)
        case WPA_CIPHER_WEP104:
        case WPA_CIPHER_WEP40:
                return WPA_ALG_WEP;
+       case WPA_CIPHER_AES_128_CMAC:
+               return WPA_ALG_IGTK;
+       case WPA_CIPHER_BIP_GMAC_128:
+               return WPA_ALG_BIP_GMAC_128;
+       case WPA_CIPHER_BIP_GMAC_256:
+               return WPA_ALG_BIP_GMAC_256;
+       case WPA_CIPHER_BIP_CMAC_256:
+               return WPA_ALG_BIP_CMAC_256;
        }
        return WPA_ALG_NONE;
 }
@@ -1193,6 +1225,14 @@ u32 wpa_cipher_to_suite(int proto, int cipher)
                        RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE);
        if (cipher & WPA_CIPHER_GTK_NOT_USED)
                return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED;
+       if (cipher & WPA_CIPHER_AES_128_CMAC)
+               return RSN_CIPHER_SUITE_AES_128_CMAC;
+       if (cipher & WPA_CIPHER_BIP_GMAC_128)
+               return RSN_CIPHER_SUITE_BIP_GMAC_128;
+       if (cipher & WPA_CIPHER_BIP_GMAC_256)
+               return RSN_CIPHER_SUITE_BIP_GMAC_256;
+       if (cipher & WPA_CIPHER_BIP_CMAC_256)
+               return RSN_CIPHER_SUITE_BIP_CMAC_256;
        return 0;
 }
 
index 5684ef3f00d7e6555330f046b304064cb92f0ea9..c0b2caaed86c16ca64db3308a80bfd395cdbee74 100644 (file)
@@ -77,9 +77,7 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
 #endif
 #define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4)
 #define RSN_CIPHER_SUITE_WEP104 RSN_SELECTOR(0x00, 0x0f, 0xac, 5)
-#ifdef CONFIG_IEEE80211W
 #define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6)
-#endif /* CONFIG_IEEE80211W */
 #define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7)
 #define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8)
 #define RSN_CIPHER_SUITE_GCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 9)
@@ -130,6 +128,7 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13)
 
 #ifdef CONFIG_IEEE80211W
 #define WPA_IGTK_LEN 16
+#define WPA_IGTK_MAX_LEN 32
 #endif /* CONFIG_IEEE80211W */
 
 
@@ -285,10 +284,11 @@ struct rsn_error_kde {
 } STRUCT_PACKED;
 
 #ifdef CONFIG_IEEE80211W
+#define WPA_IGTK_KDE_PREFIX_LEN (2 + 6)
 struct wpa_igtk_kde {
        u8 keyid[2];
        u8 pn[6];
-       u8 igtk[WPA_IGTK_LEN];
+       u8 igtk[WPA_IGTK_MAX_LEN];
 } STRUCT_PACKED;
 #endif /* CONFIG_IEEE80211W */
 
@@ -409,6 +409,7 @@ int wpa_cipher_key_len(int cipher);
 int wpa_cipher_rsc_len(int cipher);
 int wpa_cipher_to_alg(int cipher);
 int wpa_cipher_valid_pairwise(int cipher);
+int wpa_cipher_valid_mgmt_group(int cipher);
 u32 wpa_cipher_to_suite(int proto, int cipher);
 int rsn_cipher_put_suites(u8 *pos, int ciphers);
 int wpa_cipher_put_suites(u8 *pos, int ciphers);
index de86cdf653c3e2056e900bd4580d40c729085d14..77d7991f162035c7207c43f4295f8e02ff211cfe 100644 (file)
@@ -742,13 +742,15 @@ static int ieee80211w_set_keys(struct wpa_sm *sm,
                               struct wpa_eapol_ie_parse *ie)
 {
 #ifdef CONFIG_IEEE80211W
-       if (sm->mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC)
+       if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher))
                return 0;
 
        if (ie->igtk) {
+               size_t len;
                const struct wpa_igtk_kde *igtk;
                u16 keyidx;
-               if (ie->igtk_len != sizeof(*igtk))
+               len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+               if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
                        return -1;
                igtk = (const struct wpa_igtk_kde *) ie->igtk;
                keyidx = WPA_GET_LE16(igtk->keyid);
@@ -756,15 +758,16 @@ static int ieee80211w_set_keys(struct wpa_sm *sm,
                        "pn %02x%02x%02x%02x%02x%02x",
                        keyidx, MAC2STR(igtk->pn));
                wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
-                               igtk->igtk, WPA_IGTK_LEN);
+                               igtk->igtk, len);
                if (keyidx > 4095) {
                        wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
                                "WPA: Invalid IGTK KeyID %d", keyidx);
                        return -1;
                }
-               if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr,
+               if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
+                                  broadcast_ether_addr,
                                   keyidx, 0, igtk->pn, sizeof(igtk->pn),
-                                  igtk->igtk, WPA_IGTK_LEN) < 0) {
+                                  igtk->igtk, len) < 0) {
                        wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
                                "WPA: Failed to configure IGTK to the driver");
                        return -1;
@@ -1097,7 +1100,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm,
                goto failed;
        }
 
-       if (ie.igtk && ie.igtk_len != sizeof(struct wpa_igtk_kde)) {
+       if (ie.igtk &&
+           wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) &&
+           ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN +
+           (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) {
                wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
                        "WPA: Invalid IGTK KDE length %lu",
                        (unsigned long) ie.igtk_len);
@@ -2748,17 +2754,19 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf)
                }
 #ifdef CONFIG_IEEE80211W
        } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
+               keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
                os_memcpy(igd.keyid, buf + 2, 2);
                os_memcpy(igd.pn, buf + 4, 6);
 
                keyidx = WPA_GET_LE16(igd.keyid);
-               os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN);
+               os_memcpy(igd.igtk, buf + 10, keylen);
 
                wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
-                               igd.igtk, WPA_IGTK_LEN);
-               if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr,
+                               igd.igtk, keylen);
+               if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
+                                  broadcast_ether_addr,
                                   keyidx, 0, igd.pn, sizeof(igd.pn),
-                                  igd.igtk, WPA_IGTK_LEN) < 0) {
+                                  igd.igtk, keylen) < 0) {
                        wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
                                   "WNM mode");
                        return -1;
index 5eacd95b41dbc2aa9f230724973b9652c0a5087c..2329033ea0f4004389071ca48b4181d3337ab3cd 100644 (file)
@@ -201,7 +201,7 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
        }
 
 #ifdef CONFIG_IEEE80211W
-       if (mgmt_group_cipher == WPA_CIPHER_AES_128_CMAC) {
+       if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher)) {
                if (!sm->cur_pmksa) {
                        /* PMKID Count */
                        WPA_PUT_LE16(pos, 0);
@@ -209,7 +209,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len,
                }
 
                /* Management Group Cipher Suite */
-               RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+               RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN,
+                                                         mgmt_group_cipher));
                pos += RSN_SELECTOR_LEN;
        }
 #endif /* CONFIG_IEEE80211W */
index bde038e27537864c10a95517790167544b9d88ca..499dcb3331cb6faea514ce3bfcdfceaf2c10f0bc 100644 (file)
@@ -1114,6 +1114,18 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
                wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
                        "AES-128-CMAC");
+       } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
+               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+                       "BIP-GMAC-128");
+       } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
+               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+                       "BIP-GMAC-256");
+       } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
+               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
+                       "BIP-CMAC-256");
        } else {
                wpa_s->mgmt_group_cipher = 0;
                wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");