]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add support for using GCMP cipher from IEEE 802.11ad
authorJouni Malinen <jouni@qca.qualcomm.com>
Wed, 29 Aug 2012 08:52:15 +0000 (11:52 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 29 Aug 2012 08:52:15 +0000 (11:52 +0300)
This allows both hostapd and wpa_supplicant to be used to derive and
configure keys for GCMP. This is quite similar to CCMP key
configuration, but a different cipher suite and somewhat different rules
are used in cipher selection. It should be noted that GCMP is not
included in default parameters at least for now, so explicit
pairwise/group configuration is needed to enable it. This may change in
the future to allow GCMP to be selected automatically in cases where
CCMP could have been used.

This commit does not included changes to WPS or P2P to allow GCMP to be
used.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

20 files changed:
hostapd/config_file.c
hostapd/ctrl_iface.c
src/ap/wpa_auth.c
src/ap/wpa_auth_ft.c
src/ap/wpa_auth_ie.c
src/common/defs.h
src/common/ieee802_11_defs.h
src/common/wpa_common.c
src/common/wpa_common.h
src/drivers/driver.h
src/drivers/driver_nl80211.c
src/rsn_supp/peerkey.c
src/rsn_supp/wpa.c
src/rsn_supp/wpa_ft.c
src/rsn_supp/wpa_ie.c
wpa_supplicant/ap.c
wpa_supplicant/config.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/wpa_supplicant.c

index 85a1fc61e1fba424a9ace8b6b8a63d31732ba6c2..0a24ec379027e4747a500a9060a8f65efd06fd31 100644 (file)
@@ -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;
 
index 17e4c8082ac5ea9b540339306fab3385de2fed5e..1b8bede1adc2a4028d05873404aef286228ef8da 100644 (file)
@@ -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)
index fd69081924e1929b331eab3ddd023ba4474cf84d..3203d4fbbe825a9133ee45c12695ff8010abf234 100644 (file)
@@ -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)
index dedc5fd2552aaa42aa7ab7db2165aa09a29c040b..9f7cdae344eff835a7e4c2ed4dfe815e8c575918 100644 (file)
@@ -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);
index f687182320d36279210a9aae46ae0a1f8d9df1cf..b88b80aca68529b916fe88fa234d85f7162f5d6d 100644 (file)
@@ -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;
 
index f057ffe33ffc92086814a517305b3b7404b42659..db29b5df0402f131b8302a9be3f2dfe51821da6f 100644 (file)
@@ -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
 };
 
 /**
index b4f927596f84268cd2ccc37ba3cb905d7597a9cb..cb5ff180a02e9749d4323deac9b85aa72164f468 100644 (file)
@@ -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
index 61d586930a772af8666979725ef4e96bbe58c1f2..36febb3af87268e471a8131e88ad04bc29149273 100644 (file)
@@ -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";
        }
index 6b50997c4675bbf279a477ec8ce820b862b7500f..c871ae1ba391d18cbecbd18af097b6220d9d088f 100644 (file)
@@ -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)
 
index 82b72cdfb696f6ba738c8b33e8e0167f14650958..cdf52983351ffa3b3d5fe9e602a9f137ca34b5f7 100644 (file)
@@ -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);
index 47e9b7869cc06a6bc272ad3931411045f8d62270..069e0267fc552193bea817d39559dcfc884f6925 100644 (file)
@@ -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;
index 3d5aac6b6e6d1b1fbd6ad1092881ac2629646e66..5e4872e90bb34188002975c88363ecd4aa621bb8 100644 (file)
@@ -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;
index d7d7963992fbe2114b66a232da6841fcc8621480..bcd595105e994e3de2f251a0106b7a8019501290 100644 (file)
@@ -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;
index fec95449c04fe7481f0cb0ebcce267fc4f637b00..bdf389b173a059f8e1abef9eb586cdf6d1b28bc3 100644 (file)
@@ -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;
index 56d564cd0565cbc40d37196efac58f72cc3bfbb5..16268d564458a7b2340a024aa75b717ba7859665 100644 (file)
@@ -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) {
index 19b10693969df146a67d35c461cdc8ad9c7f76dd..3798f5a63f09e94eba6f8995046fb2c217ff904a 100644 (file)
@@ -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)
index c970745cf4686cfaa2ee804287c8e99ec2a8cc24..be2102971aad6a64bcc085c217769271801c2f2c 100644 (file)
@@ -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;
index 6f6c1ed67f65f14735dabd0d99c84feced966fb1..4dcba598a6c646e54d58422b529ad5389cf532cb 100644 (file)
@@ -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)
index 5ee94cd76c002a6320903e702d374ba384ec2dbc..5668e1a1b06ee6aaadddd457342776f012cbd20f 100644 (file)
@@ -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))
index 6f44bf8a784ad081e41cb543d347c76810153de9..423bd5c5a2d7d4747191fa6239242f9da56cd2bb 100644 (file)
@@ -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");