Add support for using GCMP cipher from IEEE 802.11ad

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>
This commit is contained in:
Jouni Malinen 2012-08-29 11:52:15 +03:00 committed by Jouni Malinen
parent e3e234fa35
commit eb7719ff22
20 changed files with 261 additions and 28 deletions

View 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;

View 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)

View 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)

View 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);

View 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;

View 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
};
/**

View 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

View 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";
}

View 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)

View 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);

View 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;

View 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;

View 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;

View 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;

View 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) {

View 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)

View 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;

View 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)

View 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))

View 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");