diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 85a1fc61e..0a24ec379 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -669,6 +669,8 @@ static int hostapd_config_parse_cipher(int line, const char *value) *end = '\0'; if (os_strcmp(start, "CCMP") == 0) val |= WPA_CIPHER_CCMP; + else if (os_strcmp(start, "GCMP") == 0) + val |= WPA_CIPHER_GCMP; else if (os_strcmp(start, "TKIP") == 0) val |= WPA_CIPHER_TKIP; else if (os_strcmp(start, "WEP104") == 0) @@ -1192,10 +1194,10 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, if (conf->ieee80211n && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && - !(bss->rsn_pairwise & WPA_CIPHER_CCMP)) { + !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP))) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " - "requires CCMP to be enabled, disabling HT " + "requires CCMP/GCMP to be enabled, disabling HT " "capabilities"); } #endif /* CONFIG_IEEE80211N */ @@ -1225,7 +1227,7 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss, #ifdef CONFIG_HS20 if (bss->hs20 && (!(bss->wpa & 2) || - !(bss->rsn_pairwise & WPA_CIPHER_CCMP))) { + !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) { wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP " "configuration is required for Hotspot 2.0 " "functionality"); @@ -2941,6 +2943,9 @@ static void hostapd_set_security_params(struct hostapd_bss_config *bss) } if (pairwise & WPA_CIPHER_TKIP) bss->wpa_group = WPA_CIPHER_TKIP; + else if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == + WPA_CIPHER_GCMP) + bss->wpa_group = WPA_CIPHER_GCMP; else bss->wpa_group = WPA_CIPHER_CCMP; diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index 17e4c8082..1b8bede1a 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -618,6 +618,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, if (ret < 0 || ret >= end - pos) return pos - buf; pos += ret; + } else if (hapd->conf->wpa && + hapd->conf->wpa_group == WPA_CIPHER_GCMP) { + ret = os_snprintf(pos, end - pos, "group_cipher=GCMP\n"); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; } else if (hapd->conf->wpa && hapd->conf->wpa_group == WPA_CIPHER_TKIP) { ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n"); @@ -638,6 +644,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, return pos - buf; pos += ret; } + if (hapd->conf->rsn_pairwise & WPA_CIPHER_GCMP) { + ret = os_snprintf(pos, end - pos, "GCMP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) { ret = os_snprintf(pos, end - pos, "TKIP "); if (ret < 0 || ret >= end - pos) @@ -663,6 +675,12 @@ static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, return pos - buf; pos += ret; } + if (hapd->conf->wpa_pairwise & WPA_CIPHER_GCMP) { + ret = os_snprintf(pos, end - pos, "GCMP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) { ret = os_snprintf(pos, end - pos, "TKIP "); if (ret < 0 || ret >= end - pos) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index fd6908192..3203d4fbb 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -284,6 +284,9 @@ static void wpa_group_set_key_len(struct wpa_group *group, int cipher) case WPA_CIPHER_CCMP: group->GTK_len = 16; break; + case WPA_CIPHER_GCMP: + group->GTK_len = 16; + break; case WPA_CIPHER_TKIP: group->GTK_len = 32; break; @@ -849,7 +852,8 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || msg == GROUP_2) { u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; - if (sm->pairwise == WPA_CIPHER_CCMP) { + if (sm->pairwise == WPA_CIPHER_CCMP || + sm->pairwise == WPA_CIPHER_GCMP) { if (wpa_use_aes_cmac(sm) && ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { wpa_auth_logger(wpa_auth, sm->addr, @@ -865,7 +869,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, "did not use HMAC-SHA1-AES " - "with CCMP"); + "with CCMP/GCMP"); return; } } @@ -1240,7 +1244,7 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, version = force_version; else if (wpa_use_aes_cmac(sm)) version = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise == WPA_CIPHER_CCMP) + else if (sm->pairwise != WPA_CIPHER_TKIP) version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -1291,6 +1295,9 @@ void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, case WPA_CIPHER_CCMP: WPA_PUT_BE16(key->key_length, 16); break; + case WPA_CIPHER_GCMP: + WPA_PUT_BE16(key->key_length, 16); + break; case WPA_CIPHER_TKIP: WPA_PUT_BE16(key->key_length, 32); break; @@ -1538,6 +1545,8 @@ static enum wpa_alg wpa_alg_enum(int alg) switch (alg) { case WPA_CIPHER_CCMP: return WPA_ALG_CCMP; + case WPA_CIPHER_GCMP: + return WPA_ALG_GCMP; case WPA_CIPHER_TKIP: return WPA_ALG_TKIP; case WPA_CIPHER_WEP104: @@ -1773,7 +1782,7 @@ SM_STATE(WPA_PTK, PTKSTART) static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *pmk, struct wpa_ptk *ptk) { - size_t ptk_len = sm->pairwise == WPA_CIPHER_CCMP ? 48 : 64; + size_t ptk_len = sm->pairwise != WPA_CIPHER_TKIP ? 48 : 64; #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) return wpa_auth_derive_ptk_ft(sm, pmk, ptk, ptk_len); @@ -2093,6 +2102,9 @@ SM_STATE(WPA_PTK, PTKINITDONE) if (sm->pairwise == WPA_CIPHER_TKIP) { alg = WPA_ALG_TKIP; klen = 32; + } else if (sm->pairwise == WPA_CIPHER_GCMP) { + alg = WPA_ALG_GCMP; + klen = 16; } else { alg = WPA_ALG_CCMP; klen = 16; @@ -2790,6 +2802,8 @@ static int wpa_cipher_bits(int cipher) switch (cipher) { case WPA_CIPHER_CCMP: return 128; + case WPA_CIPHER_GCMP: + return 128; case WPA_CIPHER_TKIP: return 256; case WPA_CIPHER_WEP104: @@ -2921,6 +2935,8 @@ int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) } else if (sm->wpa == WPA_VERSION_WPA2) { if (sm->pairwise == WPA_CIPHER_CCMP) pairwise = RSN_CIPHER_SUITE_CCMP; + else if (sm->pairwise == WPA_CIPHER_GCMP) + pairwise = RSN_CIPHER_SUITE_GCMP; else if (sm->pairwise == WPA_CIPHER_TKIP) pairwise = RSN_CIPHER_SUITE_TKIP; else if (sm->pairwise == WPA_CIPHER_WEP104) diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index dedc5fd25..9f7cdae34 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -760,6 +760,9 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) } else if (sm->pairwise == WPA_CIPHER_CCMP) { alg = WPA_ALG_CCMP; klen = 16; + } else if (sm->pairwise == WPA_CIPHER_GCMP) { + alg = WPA_ALG_GCMP; + klen = 16; } else { wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip " "PTK configuration", sm->pairwise); @@ -882,7 +885,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_machine *sm, wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce", sm->ANonce, WPA_NONCE_LEN); - ptk_len = pairwise != WPA_CIPHER_CCMP ? 64 : 48; + ptk_len = pairwise == WPA_CIPHER_TKIP ? 64 : 48; wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr, sm->wpa_auth->addr, pmk_r1_name, (u8 *) &sm->PTK, ptk_len, ptk_name); diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index f68718232..b88b80aca 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -123,6 +123,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, if (conf->wpa_group == WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + } else if (conf->wpa_group == WPA_CIPHER_GCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); } else if (conf->wpa_group == WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); } else if (conf->wpa_group == WPA_CIPHER_WEP104) { @@ -153,6 +155,11 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, pos += RSN_SELECTOR_LEN; num_suites++; } + if (conf->rsn_pairwise & WPA_CIPHER_GCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); + pos += RSN_SELECTOR_LEN; + num_suites++; + } if (conf->rsn_pairwise & WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); pos += RSN_SELECTOR_LEN; @@ -453,6 +460,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, selector = RSN_CIPHER_SUITE_CCMP; if (data.pairwise_cipher & WPA_CIPHER_CCMP) selector = RSN_CIPHER_SUITE_CCMP; + else if (data.pairwise_cipher & WPA_CIPHER_GCMP) + selector = RSN_CIPHER_SUITE_GCMP; else if (data.pairwise_cipher & WPA_CIPHER_TKIP) selector = RSN_CIPHER_SUITE_TKIP; else if (data.pairwise_cipher & WPA_CIPHER_WEP104) @@ -466,6 +475,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, selector = RSN_CIPHER_SUITE_CCMP; if (data.group_cipher & WPA_CIPHER_CCMP) selector = RSN_CIPHER_SUITE_CCMP; + else if (data.group_cipher & WPA_CIPHER_GCMP) + selector = RSN_CIPHER_SUITE_GCMP; else if (data.group_cipher & WPA_CIPHER_TKIP) selector = RSN_CIPHER_SUITE_TKIP; else if (data.group_cipher & WPA_CIPHER_WEP104) @@ -607,6 +618,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, if (ciphers & WPA_CIPHER_CCMP) sm->pairwise = WPA_CIPHER_CCMP; + else if (ciphers & WPA_CIPHER_GCMP) + sm->pairwise = WPA_CIPHER_GCMP; else sm->pairwise = WPA_CIPHER_TKIP; diff --git a/src/common/defs.h b/src/common/defs.h index f057ffe33..db29b5df0 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -26,6 +26,7 @@ typedef enum { FALSE = 0, TRUE = 1 } Boolean; #ifdef CONFIG_IEEE80211W #define WPA_CIPHER_AES_128_CMAC BIT(5) #endif /* CONFIG_IEEE80211W */ +#define WPA_CIPHER_GCMP BIT(6) #define WPA_KEY_MGMT_IEEE8021X BIT(0) #define WPA_KEY_MGMT_PSK BIT(1) @@ -91,7 +92,8 @@ enum wpa_alg { WPA_ALG_TKIP, WPA_ALG_CCMP, WPA_ALG_IGTK, - WPA_ALG_PMK + WPA_ALG_PMK, + WPA_ALG_GCMP }; /** @@ -102,7 +104,8 @@ enum wpa_cipher { CIPHER_WEP40, CIPHER_TKIP, CIPHER_CCMP, - CIPHER_WEP104 + CIPHER_WEP104, + CIPHER_GCMP }; /** diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index b4f927596..cb5ff180a 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -946,6 +946,8 @@ enum p2p_sd_status { #define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 #define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 #define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 +#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07 +#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 /* AKM suite selectors */ #define WLAN_AKM_SUITE_8021X 0x000FAC01 diff --git a/src/common/wpa_common.c b/src/common/wpa_common.c index 61d586930..36febb3af 100644 --- a/src/common/wpa_common.c +++ b/src/common/wpa_common.c @@ -352,6 +352,8 @@ static int rsn_selector_to_bitfield(const u8 *s) if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) return WPA_CIPHER_AES_128_CMAC; #endif /* CONFIG_IEEE80211W */ + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP) + return WPA_CIPHER_GCMP; return 0; } @@ -908,6 +910,8 @@ const char * wpa_cipher_txt(int cipher) return "CCMP"; case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: return "CCMP+TKIP"; + case WPA_CIPHER_GCMP: + return "GCMP"; default: return "UNKNOWN"; } diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 6b50997c4..c871ae1ba 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -64,6 +64,7 @@ #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) /* EAPOL-Key Key Data Encapsulation * GroupKey and PeerKey require encryption, otherwise, encryption is optional. @@ -83,6 +84,9 @@ #ifdef CONFIG_IEEE80211W #define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9) #endif /* CONFIG_IEEE80211W */ +#define RSN_KEY_DATA_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 10) +#define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11) +#define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 82b72cdfb..cdf529833 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -765,6 +765,7 @@ struct wpa_driver_capa { #define WPA_DRIVER_CAPA_ENC_TKIP 0x00000004 #define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008 #define WPA_DRIVER_CAPA_ENC_WEP128 0x00000010 +#define WPA_DRIVER_CAPA_ENC_GCMP 0x00000020 unsigned int enc; #define WPA_DRIVER_AUTH_OPEN 0x00000001 @@ -1075,7 +1076,8 @@ struct wpa_driver_ops { * @ifname: Interface name (for multi-SSID/VLAN support) * @priv: private driver interface data * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, - * %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK); + * %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK, + * %WPA_ALG_GCMP); * %WPA_ALG_NONE clears the key. * @addr: Address of the peer STA (BSSID of the current AP when setting * pairwise key in station mode), ff:ff:ff:ff:ff:ff for @@ -1092,11 +1094,11 @@ struct wpa_driver_ops { * for Rx keys (in most cases, this is only used with broadcast * keys and set to zero for unicast keys); %NULL if not set * @seq_len: length of the seq, depends on the algorithm: - * TKIP: 6 octets, CCMP: 6 octets, IGTK: 6 octets + * TKIP: 6 octets, CCMP/GCMP: 6 octets, IGTK: 6 octets * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, * 8-byte Rx Mic Key * @key_len: length of the key buffer in octets (WEP: 5 or 13, - * TKIP: 32, CCMP: 16, IGTK: 16) + * TKIP: 32, CCMP/GCMP: 16, IGTK: 16) * * Returns: 0 on success, -1 on failure * @@ -1601,9 +1603,9 @@ struct wpa_driver_ops { * Returns: 0 on success, -1 on failure * * This function is used to fetch the last used TSC/packet number for - * a TKIP, CCMP, or BIP/IGTK key. It is mainly used with group keys, so - * there is no strict requirement on implementing support for unicast - * keys (i.e., addr != %NULL). + * a TKIP, CCMP, GCMP, or BIP/IGTK key. It is mainly used with group + * keys, so there is no strict requirement on implementing support for + * unicast keys (i.e., addr != %NULL). */ int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr, int idx, u8 *seq); diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 47e9b7869..069e0267f 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -4201,6 +4201,10 @@ static int wpa_driver_nl80211_set_key(const char *ifname, void *priv, NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP); break; + case WPA_ALG_GCMP: + NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, + WLAN_CIPHER_SUITE_GCMP); + break; case WPA_ALG_IGTK: NLA_PUT_U32(msg, NL80211_ATTR_KEY_CIPHER, WLAN_CIPHER_SUITE_AES_CMAC); @@ -4341,6 +4345,9 @@ static int nl_add_key(struct nl_msg *msg, enum wpa_alg alg, case WPA_ALG_CCMP: NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_CCMP); break; + case WPA_ALG_GCMP: + NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_GCMP); + break; case WPA_ALG_IGTK: NLA_PUT_U32(msg, NL80211_KEY_CIPHER, WLAN_CIPHER_SUITE_AES_CMAC); @@ -5476,6 +5483,8 @@ static int wpa_driver_nl80211_set_ap(void *priv, num_suites = 0; if (params->pairwise_ciphers & WPA_CIPHER_CCMP) suites[num_suites++] = WLAN_CIPHER_SUITE_CCMP; + if (params->pairwise_ciphers & WPA_CIPHER_GCMP) + suites[num_suites++] = WLAN_CIPHER_SUITE_GCMP; if (params->pairwise_ciphers & WPA_CIPHER_TKIP) suites[num_suites++] = WLAN_CIPHER_SUITE_TKIP; if (params->pairwise_ciphers & WPA_CIPHER_WEP104) @@ -5492,6 +5501,10 @@ static int wpa_driver_nl80211_set_ap(void *priv, NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, WLAN_CIPHER_SUITE_CCMP); break; + case WPA_CIPHER_GCMP: + NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, + WLAN_CIPHER_SUITE_GCMP); + break; case WPA_CIPHER_TKIP: NLA_PUT_U32(msg, NL80211_ATTR_CIPHER_SUITE_GROUP, WLAN_CIPHER_SUITE_TKIP); @@ -6753,6 +6766,9 @@ skip_auth_type: case CIPHER_CCMP: cipher = WLAN_CIPHER_SUITE_CCMP; break; + case CIPHER_GCMP: + cipher = WLAN_CIPHER_SUITE_GCMP; + break; case CIPHER_TKIP: default: cipher = WLAN_CIPHER_SUITE_TKIP; @@ -6774,6 +6790,9 @@ skip_auth_type: case CIPHER_CCMP: cipher = WLAN_CIPHER_SUITE_CCMP; break; + case CIPHER_GCMP: + cipher = WLAN_CIPHER_SUITE_GCMP; + break; case CIPHER_TKIP: default: cipher = WLAN_CIPHER_SUITE_TKIP; @@ -6916,6 +6935,9 @@ static int wpa_driver_nl80211_associate( case CIPHER_CCMP: cipher = WLAN_CIPHER_SUITE_CCMP; break; + case CIPHER_GCMP: + cipher = WLAN_CIPHER_SUITE_GCMP; + break; case CIPHER_TKIP: default: cipher = WLAN_CIPHER_SUITE_TKIP; @@ -6938,6 +6960,9 @@ static int wpa_driver_nl80211_associate( case CIPHER_CCMP: cipher = WLAN_CIPHER_SUITE_CCMP; break; + case CIPHER_GCMP: + cipher = WLAN_CIPHER_SUITE_GCMP; + break; case CIPHER_TKIP: default: cipher = WLAN_CIPHER_SUITE_TKIP; diff --git a/src/rsn_supp/peerkey.c b/src/rsn_supp/peerkey.c index 3d5aac6b6..5e4872e90 100644 --- a/src/rsn_supp/peerkey.c +++ b/src/rsn_supp/peerkey.c @@ -221,6 +221,9 @@ static int wpa_supplicant_process_smk_m2( if (cipher & WPA_CIPHER_CCMP) { wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); cipher = WPA_CIPHER_CCMP; + } else if (cipher & WPA_CIPHER_GCMP) { + wpa_printf(MSG_DEBUG, "RSN: Using GCMP for PeerKey"); + cipher = WPA_CIPHER_GCMP; } else if (cipher & WPA_CIPHER_TKIP) { wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); cipher = WPA_CIPHER_TKIP; @@ -269,6 +272,8 @@ static int wpa_supplicant_process_smk_m2( pos += 2; if (cipher == WPA_CIPHER_CCMP) RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + else if (cipher == WPA_CIPHER_GCMP) + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); else if (cipher == WPA_CIPHER_TKIP) RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); pos += RSN_SELECTOR_LEN; @@ -344,7 +349,7 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, msg->type = EAPOL_KEY_TYPE_RSN; - if (peerkey->cipher == WPA_CIPHER_CCMP) + if (peerkey->cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -352,7 +357,7 @@ static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm, key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK; WPA_PUT_BE16(msg->key_info, key_info); - if (peerkey->cipher == WPA_CIPHER_CCMP) + if (peerkey->cipher != WPA_CIPHER_TKIP) WPA_PUT_BE16(msg->key_length, 16); else WPA_PUT_BE16(msg->key_length, 32); @@ -403,7 +408,7 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, msg->type = EAPOL_KEY_TYPE_RSN; - if (peerkey->cipher == WPA_CIPHER_CCMP) + if (peerkey->cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -412,7 +417,7 @@ static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm, WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; WPA_PUT_BE16(msg->key_info, key_info); - if (peerkey->cipher == WPA_CIPHER_CCMP) + if (peerkey->cipher != WPA_CIPHER_TKIP) WPA_PUT_BE16(msg->key_length, 16); else WPA_PUT_BE16(msg->key_length, 32); @@ -500,6 +505,9 @@ static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm, if (cipher & WPA_CIPHER_CCMP) { wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey"); peerkey->cipher = WPA_CIPHER_CCMP; + } else if (cipher & WPA_CIPHER_GCMP) { + wpa_printf(MSG_DEBUG, "RSN: Using GCMP for PeerKey"); + peerkey->cipher = WPA_CIPHER_GCMP; } else if (cipher & WPA_CIPHER_TKIP) { wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey"); peerkey->cipher = WPA_CIPHER_TKIP; @@ -1016,7 +1024,7 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) return -1; } - if (sm->pairwise_cipher == WPA_CIPHER_CCMP) + if (sm->pairwise_cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -1061,6 +1069,11 @@ int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) pos += RSN_SELECTOR_LEN; count++; } + if (sm->allowed_pairwise_cipher & WPA_CIPHER_GCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); + pos += RSN_SELECTOR_LEN; + count++; + } if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); pos += RSN_SELECTOR_LEN; diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index d7d796399..bcd595105 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -91,7 +91,7 @@ void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) if (wpa_key_mgmt_ft(sm->key_mgmt) || wpa_key_mgmt_sha256(sm->key_mgmt)) ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; - else if (sm->pairwise_cipher == WPA_CIPHER_CCMP) + else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; else ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; @@ -356,7 +356,7 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, const struct wpa_eapol_key *key, struct wpa_ptk *ptk) { - size_t ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; + size_t ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64; #ifdef CONFIG_IEEE80211R if (wpa_key_mgmt_ft(sm->key_mgmt)) return wpa_derive_ptk_ft(sm, src_addr, key, ptk, ptk_len); @@ -526,6 +526,11 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, keylen = 16; rsclen = 6; break; + case WPA_CIPHER_GCMP: + alg = WPA_ALG_GCMP; + keylen = 16; + rsclen = 6; + break; case WPA_CIPHER_TKIP: alg = WPA_ALG_TKIP; keylen = 32; @@ -585,6 +590,14 @@ static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, *key_rsc_len = 6; *alg = WPA_ALG_CCMP; break; + case WPA_CIPHER_GCMP: + if (keylen != 16 || maxkeylen < 16) { + ret = -1; + break; + } + *key_rsc_len = 6; + *alg = WPA_ALG_GCMP; + break; case WPA_CIPHER_TKIP: if (keylen != 32 || maxkeylen < 32) { ret = -1; @@ -1131,6 +1144,14 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, goto failed; } break; + case WPA_CIPHER_GCMP: + if (keylen != 16) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid GCMP key length %d (src=" MACSTR + ")", keylen, MAC2STR(sm->bssid)); + goto failed; + } + break; case WPA_CIPHER_TKIP: if (keylen != 32) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, @@ -1718,6 +1739,13 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, } else goto out; } + if (sm->pairwise_cipher == WPA_CIPHER_GCMP && + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: GCMP is used, but EAPOL-Key " + "descriptor version (%d) is not 2", ver); + goto out; + } #ifdef CONFIG_PEERKEY for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { @@ -1857,6 +1885,8 @@ static int wpa_cipher_bits(int cipher) switch (cipher) { case WPA_CIPHER_CCMP: return 128; + case WPA_CIPHER_GCMP: + return 128; case WPA_CIPHER_TKIP: return 256; case WPA_CIPHER_WEP104: @@ -1906,6 +1936,8 @@ static u32 wpa_cipher_suite(struct wpa_sm *sm, int cipher) case WPA_CIPHER_CCMP: return (sm->proto == WPA_PROTO_RSN ? RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); + case WPA_CIPHER_GCMP: + return RSN_CIPHER_SUITE_GCMP; case WPA_CIPHER_TKIP: return (sm->proto == WPA_PROTO_RSN ? RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); @@ -2691,6 +2723,11 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf) gd.key_rsc_len = 6; gd.alg = WPA_ALG_CCMP; break; + case WPA_CIPHER_GCMP: + keylen = 16; + gd.key_rsc_len = 6; + gd.alg = WPA_ALG_GCMP; + break; case WPA_CIPHER_TKIP: keylen = 32; gd.key_rsc_len = 6; diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index fec95449c..bdf389b17 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -173,6 +173,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, /* Group Suite Selector */ if (sm->group_cipher == WPA_CIPHER_CCMP) RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + else if (sm->group_cipher == WPA_CIPHER_GCMP) + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); else if (sm->group_cipher == WPA_CIPHER_TKIP) RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); else { @@ -190,6 +192,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, /* Pairwise Suite List */ if (sm->pairwise_cipher == WPA_CIPHER_CCMP) RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + else if (sm->pairwise_cipher == WPA_CIPHER_GCMP) + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); else if (sm->pairwise_cipher == WPA_CIPHER_TKIP) RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); else { @@ -328,6 +332,10 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) alg = WPA_ALG_CCMP; keylen = 16; break; + case WPA_CIPHER_GCMP: + alg = WPA_ALG_GCMP; + keylen = 16; + break; case WPA_CIPHER_TKIP: alg = WPA_ALG_TKIP; keylen = 32; @@ -483,7 +491,7 @@ int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, sm->pmk_r1_name, WPA_PMK_NAME_LEN); bssid = target_ap; - ptk_len = sm->pairwise_cipher == WPA_CIPHER_CCMP ? 48 : 64; + ptk_len = sm->pairwise_cipher != WPA_CIPHER_TKIP ? 48 : 64; wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->snonce, ftie->anonce, sm->own_addr, bssid, sm->pmk_r1_name, (u8 *) &sm->ptk, ptk_len, ptk_name); @@ -577,6 +585,11 @@ static int wpa_ft_process_gtk_subelem(struct wpa_sm *sm, const u8 *gtk_elem, rsc_len = 6; alg = WPA_ALG_CCMP; break; + case WPA_CIPHER_GCMP: + keylen = 16; + rsc_len = 6; + alg = WPA_ALG_GCMP; + break; case WPA_CIPHER_TKIP: keylen = 32; rsc_len = 6; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index 56d564cd0..16268d564 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -132,6 +132,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, if (group_cipher == WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + } else if (group_cipher == WPA_CIPHER_GCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); } else if (group_cipher == WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); } else if (group_cipher == WPA_CIPHER_WEP104) { @@ -149,6 +151,8 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, *pos++ = 0; if (pairwise_cipher == WPA_CIPHER_CCMP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + } else if (pairwise_cipher == WPA_CIPHER_GCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); } else if (pairwise_cipher == WPA_CIPHER_TKIP) { RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); } else if (pairwise_cipher == WPA_CIPHER_NONE) { diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 19b106939..3798f5a63 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -218,6 +218,9 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, } if (pairwise & WPA_CIPHER_TKIP) bss->wpa_group = WPA_CIPHER_TKIP; + else if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == + WPA_CIPHER_GCMP) + bss->wpa_group = WPA_CIPHER_GCMP; else bss->wpa_group = WPA_CIPHER_CCMP; @@ -461,6 +464,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s, if (ssid->pairwise_cipher & WPA_CIPHER_CCMP) wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; + else if (ssid->pairwise_cipher & WPA_CIPHER_GCMP) + wpa_s->pairwise_cipher = WPA_CIPHER_GCMP; else if (ssid->pairwise_cipher & WPA_CIPHER_TKIP) wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; else if (ssid->pairwise_cipher & WPA_CIPHER_NONE) diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index c970745cf..be2102971 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -643,6 +643,8 @@ static int wpa_config_parse_cipher(int line, const char *value) *end = '\0'; if (os_strcmp(start, "CCMP") == 0) val |= WPA_CIPHER_CCMP; + else if (os_strcmp(start, "GCMP") == 0) + val |= WPA_CIPHER_GCMP; else if (os_strcmp(start, "TKIP") == 0) val |= WPA_CIPHER_TKIP; else if (os_strcmp(start, "WEP104") == 0) @@ -694,6 +696,16 @@ static char * wpa_config_write_cipher(int cipher) pos += ret; } + if (cipher & WPA_CIPHER_GCMP) { + ret = os_snprintf(pos, end - pos, "%sGCMP", + pos == buf ? "" : " "); + if (ret < 0 || ret >= end - pos) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + if (cipher & WPA_CIPHER_TKIP) { ret = os_snprintf(pos, end - pos, "%sTKIP", pos == buf ? "" : " "); @@ -747,7 +759,8 @@ static int wpa_config_parse_pairwise(const struct parse_data *data, val = wpa_config_parse_cipher(line, value); if (val == -1) return -1; - if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE)) { + if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | + WPA_CIPHER_NONE)) { wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " "(0x%x).", line, val); return -1; @@ -776,8 +789,8 @@ static int wpa_config_parse_group(const struct parse_data *data, val = wpa_config_parse_cipher(line, value); if (val == -1) return -1; - if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | WPA_CIPHER_WEP104 | - WPA_CIPHER_WEP40)) { + if (val & ~(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | + WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40)) { wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " "(0x%x).", line, val); return -1; diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 6f6c1ed67..4dcba598a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1428,6 +1428,13 @@ static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher) pos += ret; first = 0; } + if (cipher & WPA_CIPHER_GCMP) { + ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : "+"); + if (ret < 0 || ret >= end - pos) + return pos; + pos += ret; + first = 0; + } return pos; } @@ -2150,6 +2157,14 @@ static int ctrl_iface_get_capability_pairwise(int res, char *strict, first = 0; } + if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) { + ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + first = 0; + } + if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); if (ret < 0 || ret >= end - pos) @@ -2198,6 +2213,14 @@ static int ctrl_iface_get_capability_group(int res, char *strict, first = 0; } + if (capa->enc & WPA_DRIVER_CAPA_ENC_GCMP) { + ret = os_snprintf(pos, end - pos, "%sGCMP", first ? "" : " "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + first = 0; + } + if (capa->enc & WPA_DRIVER_CAPA_ENC_TKIP) { ret = os_snprintf(pos, end - pos, "%sTKIP", first ? "" : " "); if (ret < 0 || ret >= end - pos) diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 5ee94cd76..5668e1a1b 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1929,6 +1929,12 @@ dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, goto nomem; } + if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) { + if (!wpa_dbus_dict_string_array_add_element( + &iter_array, "gcmp")) + goto nomem; + } + if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) @@ -1970,6 +1976,12 @@ dbus_bool_t wpas_dbus_getter_capabilities(DBusMessageIter *iter, goto nomem; } + if (capa.enc & WPA_DRIVER_CAPA_ENC_GCMP) { + if (!wpa_dbus_dict_string_array_add_element( + &iter_array, "gcmp")) + goto nomem; + } + if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) { if (!wpa_dbus_dict_string_array_add_element( &iter_array, "tkip")) @@ -3182,7 +3194,7 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, { DBusMessageIter iter_dict, variant_iter; const char *group; - const char *pairwise[2]; /* max 2 pairwise ciphers is supported */ + const char *pairwise[3]; /* max 3 pairwise ciphers is supported */ const char *key_mgmt[7]; /* max 7 key managements may be supported */ int n; @@ -3225,6 +3237,9 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, case WPA_CIPHER_CCMP: group = "ccmp"; break; + case WPA_CIPHER_GCMP: + group = "gcmp"; + break; case WPA_CIPHER_WEP104: group = "wep104"; break; @@ -3242,6 +3257,8 @@ static dbus_bool_t wpas_dbus_get_bss_security_prop(DBusMessageIter *iter, pairwise[n++] = "tkip"; if (ie_data->pairwise_cipher & WPA_CIPHER_CCMP) pairwise[n++] = "ccmp"; + if (ie_data->pairwise_cipher & WPA_CIPHER_GCMP) + pairwise[n++] = "gcmp"; if (!wpa_dbus_dict_append_string_array(&iter_dict, "Pairwise", pairwise, n)) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6f44bf8a7..423bd5c5a 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -154,6 +154,11 @@ static int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, keylen = 16; alg = WPA_ALG_CCMP; break; + case WPA_CIPHER_GCMP: + os_memcpy(key, ssid->psk, 16); + keylen = 16; + alg = WPA_ALG_GCMP; + break; case WPA_CIPHER_TKIP: /* WPA-None uses the same Michael MIC key for both TX and RX */ os_memcpy(key, ssid->psk, 16 + 8); @@ -843,6 +848,8 @@ enum wpa_cipher cipher_suite2driver(int cipher) return CIPHER_WEP104; case WPA_CIPHER_CCMP: return CIPHER_CCMP; + case WPA_CIPHER_GCMP: + return CIPHER_GCMP; case WPA_CIPHER_TKIP: default: return CIPHER_TKIP; @@ -1019,6 +1026,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (sel & WPA_CIPHER_CCMP) { wpa_s->group_cipher = WPA_CIPHER_CCMP; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK CCMP"); + } else if (sel & WPA_CIPHER_GCMP) { + wpa_s->group_cipher = WPA_CIPHER_GCMP; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK GCMP"); } else if (sel & WPA_CIPHER_TKIP) { wpa_s->group_cipher = WPA_CIPHER_TKIP; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK TKIP"); @@ -1038,6 +1048,9 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, if (sel & WPA_CIPHER_CCMP) { wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK CCMP"); + } else if (sel & WPA_CIPHER_GCMP) { + wpa_s->pairwise_cipher = WPA_CIPHER_GCMP; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK GCMP"); } else if (sel & WPA_CIPHER_TKIP) { wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK TKIP");