From 8dd9f9cdde4b865a7b611a2ed5b97a849ac945bc Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Wed, 12 Mar 2014 20:26:37 +0200 Subject: [PATCH] Allow management group cipher to be configured 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 --- hostapd/config_file.c | 14 +++++++++ hostapd/hostapd.conf | 11 +++++++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 47 ++++++++++++++++++----------- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 1 + src/ap/wpa_auth_i.h | 2 +- src/ap/wpa_auth_ie.c | 23 +++++++++++++-- src/common/wpa_common.c | 52 +++++++++++++++++++++++++++++---- src/common/wpa_common.h | 7 +++-- src/rsn_supp/wpa.c | 28 +++++++++++------- src/rsn_supp/wpa_ie.c | 5 ++-- wpa_supplicant/wpa_supplicant.c | 12 ++++++++ 14 files changed, 164 insertions(+), 41 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index f018f9632..814468d11 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -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) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 81ddabc2a..23ee1e5b5 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -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 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 3ca85a0fa..c17b016b0 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -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 */ diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index aa3a51aee..25eb4903b 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -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) */ diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 7d89edf45..4d19bb033 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -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; diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index d99db691b..3ab3e3d5d 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -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 diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index da5fea7ce..6ee9a4f83 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -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; diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index fcd5878e7..2e1bdcf48 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -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 */ }; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 7a497516f..e957c6e92 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -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; diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 27f58aa31..adb22c76e 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -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; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 5684ef3f0..c0b2caaed 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -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); diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index de86cdf65..77d7991f1 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -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; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 5eacd95b4..2329033ea 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -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 */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index bde038e27..499dcb333 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -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"); -- 2.39.2