aboutsummaryrefslogtreecommitdiffstats
path: root/src/ap
diff options
context:
space:
mode:
authorJouni Malinen <jouni@qca.qualcomm.com>2014-03-12 18:26:37 (GMT)
committerJouni Malinen <j@w1.fi>2014-03-14 19:58:45 (GMT)
commit8dd9f9cdde4b865a7b611a2ed5b97a849ac945bc (patch)
tree53e6b696818bcc42effcc472c4ae31668ee83ac8 /src/ap
parent67d39cfb3245c8e3adb91e82482ff69d7f1b25c6 (diff)
downloadhostap-8dd9f9cdde4b865a7b611a2ed5b97a849ac945bc.zip
hostap-8dd9f9cdde4b865a7b611a2ed5b97a849ac945bc.tar.gz
hostap-8dd9f9cdde4b865a7b611a2ed5b97a849ac945bc.tar.bz2
Allow management group cipher to be configured
This allows hostapd to set a different management group cipher than the previously hardcoded default BIP (AES-128-CMAC). The new configuration file parameter group_mgmt_cipher can be set to BIP-GMAC-128, BIP-GMAC-256, or BIP-CMAC-256 to select one of the ciphers defined in IEEE Std 802.11ac-2013. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Diffstat (limited to 'src/ap')
-rw-r--r--src/ap/ap_config.c1
-rw-r--r--src/ap/ap_config.h1
-rw-r--r--src/ap/wpa_auth.c47
-rw-r--r--src/ap/wpa_auth.h1
-rw-r--r--src/ap/wpa_auth_glue.c1
-rw-r--r--src/ap/wpa_auth_i.h2
-rw-r--r--src/ap/wpa_auth_ie.c23
7 files changed, 56 insertions, 20 deletions
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 3ca85a0..c17b016 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -73,6 +73,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
#ifdef CONFIG_IEEE80211W
bss->assoc_sa_query_max_timeout = 1000;
bss->assoc_sa_query_retry_timeout = 201;
+ bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
#endif /* CONFIG_IEEE80211W */
#ifdef EAP_SERVER_FAST
/* both anonymous and authenticated provisioning */
diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
index aa3a51a..25eb490 100644
--- a/src/ap/ap_config.h
+++ b/src/ap/ap_config.h
@@ -254,6 +254,7 @@ struct hostapd_bss_config {
int wpa_key_mgmt;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
+ int group_mgmt_cipher;
/* dot11AssociationSAQueryMaximumTimeout (in TUs) */
unsigned int assoc_sa_query_max_timeout;
/* dot11AssociationSAQueryRetryTimeout (in TUs) */
diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
index 7d89edf..4d19bb0 100644
--- a/src/ap/wpa_auth.c
+++ b/src/ap/wpa_auth.c
@@ -1918,7 +1918,9 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2)
static int ieee80211w_kde_len(struct wpa_state_machine *sm)
{
if (sm->mgmt_frame_prot) {
- return 2 + RSN_SELECTOR_LEN + sizeof(struct wpa_igtk_kde);
+ size_t len;
+ len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
+ return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len;
}
return 0;
@@ -1930,6 +1932,7 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
struct wpa_igtk_kde igtk;
struct wpa_group *gsm = sm->group;
u8 rsc[WPA_KEY_RSC_LEN];
+ size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
if (!sm->mgmt_frame_prot)
return pos;
@@ -1941,17 +1944,18 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos)
os_memset(igtk.pn, 0, sizeof(igtk.pn));
else
os_memcpy(igtk.pn, rsc, sizeof(igtk.pn));
- os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
+ os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len);
if (sm->wpa_auth->conf.disable_gtk) {
/*
* Provide unique random IGTK to each STA to prevent use of
* IGTK in the BSS.
*/
- if (random_get_bytes(igtk.igtk, WPA_IGTK_LEN) < 0)
+ if (random_get_bytes(igtk.igtk, len) < 0)
return pos;
}
pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK,
- (const u8 *) &igtk, sizeof(igtk), NULL, 0);
+ (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len,
+ NULL, 0);
return pos;
}
@@ -2457,15 +2461,16 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
#ifdef CONFIG_IEEE80211W
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ size_t len;
+ len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
inc_byte_array(group->Counter, WPA_NONCE_LEN);
if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
wpa_auth->addr, group->GNonce,
- group->IGTK[group->GN_igtk - 4],
- WPA_IGTK_LEN) < 0)
+ group->IGTK[group->GN_igtk - 4], len) < 0)
ret = -1;
wpa_hexdump_key(MSG_DEBUG, "IGTK",
- group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
+ group->IGTK[group->GN_igtk - 4], len);
}
#endif /* CONFIG_IEEE80211W */
@@ -2582,26 +2587,27 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos)
{
struct wpa_group *gsm = sm->group;
u8 *start = pos;
+ size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher);
/*
* IGTK subelement:
* Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16]
*/
*pos++ = WNM_SLEEP_SUBELEM_IGTK;
- *pos++ = 2 + 6 + WPA_IGTK_LEN;
+ *pos++ = 2 + 6 + len;
WPA_PUT_LE16(pos, gsm->GN_igtk);
pos += 2;
if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0)
return 0;
pos += 6;
- os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
- pos += WPA_IGTK_LEN;
+ os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len);
+ pos += len;
wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit",
gsm->GN_igtk);
wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit",
- gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
+ gsm->IGTK[gsm->GN_igtk - 4], len);
return pos - start;
}
@@ -2656,12 +2662,19 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth,
ret = -1;
#ifdef CONFIG_IEEE80211W
- if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION &&
- wpa_auth_set_key(wpa_auth, group->vlan_id, WPA_ALG_IGTK,
- broadcast_ether_addr, group->GN_igtk,
- group->IGTK[group->GN_igtk - 4],
- WPA_IGTK_LEN) < 0)
- ret = -1;
+ if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
+ enum wpa_alg alg;
+ size_t len;
+
+ alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher);
+ len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher);
+
+ if (ret == 0 &&
+ wpa_auth_set_key(wpa_auth, group->vlan_id, alg,
+ broadcast_ether_addr, group->GN_igtk,
+ group->IGTK[group->GN_igtk - 4], len) < 0)
+ ret = -1;
+ }
#endif /* CONFIG_IEEE80211W */
return ret;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index d99db69..3ab3e3d 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -142,6 +142,7 @@ struct wpa_auth_config {
int tx_status;
#ifdef CONFIG_IEEE80211W
enum mfp_options ieee80211w;
+ int group_mgmt_cipher;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
#define SSID_LEN 32
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index da5fea7..6ee9a4f 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -49,6 +49,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
wconf->okc = conf->okc;
#ifdef CONFIG_IEEE80211W
wconf->ieee80211w = conf->ieee80211w;
+ wconf->group_mgmt_cipher = conf->group_mgmt_cipher;
#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
wconf->ssid_len = conf->ssid.ssid_len;
diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
index fcd5878..2e1bdcf 100644
--- a/src/ap/wpa_auth_i.h
+++ b/src/ap/wpa_auth_i.h
@@ -154,7 +154,7 @@ struct wpa_group {
Boolean first_sta_seen;
Boolean reject_4way_hs_for_entropy;
#ifdef CONFIG_IEEE80211W
- u8 IGTK[2][WPA_IGTK_LEN];
+ u8 IGTK[2][WPA_IGTK_MAX_LEN];
int GN_igtk, GM_igtk;
#endif /* CONFIG_IEEE80211W */
};
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 7a49751..e957c6e 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -261,7 +261,25 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len,
}
/* Management Group Cipher Suite */
- RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+ switch (conf->group_mgmt_cipher) {
+ case WPA_CIPHER_AES_128_CMAC:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC);
+ break;
+ case WPA_CIPHER_BIP_GMAC_128:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128);
+ break;
+ case WPA_CIPHER_BIP_GMAC_256:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256);
+ break;
+ case WPA_CIPHER_BIP_CMAC_256:
+ RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG,
+ "Invalid group management cipher (0x%x)",
+ conf->group_mgmt_cipher);
+ return -1;
+ }
pos += RSN_SELECTOR_LEN;
}
#endif /* CONFIG_IEEE80211W */
@@ -586,7 +604,8 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
return WPA_MGMT_FRAME_PROTECTION_VIOLATION;
}
- if (data.mgmt_group_cipher != WPA_CIPHER_AES_128_CMAC) {
+ if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher)
+ {
wpa_printf(MSG_DEBUG, "Unsupported management group "
"cipher %d", data.mgmt_group_cipher);
return WPA_INVALID_MGMT_GROUP_CIPHER;