Mix in more data to GTK/IGTK derivation
The example GMK-to-GTK derivation described in the IEEE 802.11 standard is marked informative and there is no protocol reason for following it since this derivation is done only on the AP/Authenticator and does not need to match with the Supplicant. Mix in more data into the derivation process to get more separation from GMK.
This commit is contained in:
parent
783a082ccc
commit
5cb9d5c3d1
1 changed files with 32 additions and 19 deletions
|
@ -220,6 +220,8 @@ static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx)
|
||||||
"initialization.");
|
"initialization.");
|
||||||
} else {
|
} else {
|
||||||
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
|
wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd");
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "GMK",
|
||||||
|
wpa_auth->group->GMK, WPA_GMK_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wpa_auth->conf.wpa_gmk_rekey) {
|
if (wpa_auth->conf.wpa_gmk_rekey) {
|
||||||
|
@ -325,9 +327,12 @@ static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth,
|
||||||
os_free(group);
|
os_free(group);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN);
|
||||||
|
|
||||||
sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
|
sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf),
|
||||||
group->Counter, WPA_NONCE_LEN);
|
group->Counter, WPA_NONCE_LEN);
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "Key Counter",
|
||||||
|
group->Counter, WPA_NONCE_LEN);
|
||||||
|
|
||||||
group->GInit = TRUE;
|
group->GInit = TRUE;
|
||||||
wpa_group_sm_step(wpa_auth, group);
|
wpa_group_sm_step(wpa_auth, group);
|
||||||
|
@ -995,25 +1000,31 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void wpa_gmk_to_gtk(const u8 *gmk, const u8 *addr, const u8 *gnonce,
|
static void wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr,
|
||||||
u8 *gtk, size_t gtk_len)
|
const u8 *gnonce, u8 *gtk, size_t gtk_len)
|
||||||
{
|
{
|
||||||
u8 data[ETH_ALEN + WPA_NONCE_LEN];
|
u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16];
|
||||||
|
u8 *pos;
|
||||||
|
|
||||||
/* GTK = PRF-X(GMK, "Group key expansion", AA || GNonce) */
|
/* GTK = PRF-X(GMK, "Group key expansion",
|
||||||
|
* AA || GNonce || Time || random data)
|
||||||
|
* The example described in the IEEE 802.11 standard uses only AA and
|
||||||
|
* GNonce as inputs here. Add some more entropy since this derivation
|
||||||
|
* is done only at the Authenticator and as such, does not need to be
|
||||||
|
* exactly same.
|
||||||
|
*/
|
||||||
os_memcpy(data, addr, ETH_ALEN);
|
os_memcpy(data, addr, ETH_ALEN);
|
||||||
os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
|
os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN);
|
||||||
|
pos = data + ETH_ALEN + WPA_NONCE_LEN;
|
||||||
|
wpa_get_ntp_timestamp(pos);
|
||||||
|
pos += 8;
|
||||||
|
os_get_random(pos, 16);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
sha256_prf(gmk, WPA_GMK_LEN, "Group key expansion",
|
sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len);
|
||||||
data, sizeof(data), gtk, gtk_len);
|
|
||||||
#else /* CONFIG_IEEE80211W */
|
#else /* CONFIG_IEEE80211W */
|
||||||
sha1_prf(gmk, WPA_GMK_LEN, "Group key expansion",
|
sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len);
|
||||||
data, sizeof(data), gtk, gtk_len);
|
|
||||||
#endif /* CONFIG_IEEE80211W */
|
#endif /* CONFIG_IEEE80211W */
|
||||||
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "GMK", gmk, WPA_GMK_LEN);
|
|
||||||
wpa_hexdump_key(MSG_DEBUG, "GTK", gtk, gtk_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2094,20 +2105,22 @@ static int wpa_gtk_update(struct wpa_authenticator *wpa_auth,
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
/* FIX: is this the correct way of getting GNonce? */
|
|
||||||
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
|
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
|
||||||
inc_byte_array(group->Counter, WPA_NONCE_LEN);
|
inc_byte_array(group->Counter, WPA_NONCE_LEN);
|
||||||
wpa_gmk_to_gtk(group->GMK, wpa_auth->addr, group->GNonce,
|
wpa_gmk_to_gtk(group->GMK, "Group key expansion",
|
||||||
|
wpa_auth->addr, group->GNonce,
|
||||||
group->GTK[group->GN - 1], group->GTK_len);
|
group->GTK[group->GN - 1], group->GTK_len);
|
||||||
|
wpa_hexdump_key(MSG_DEBUG, "GTK",
|
||||||
|
group->GTK[group->GN - 1], group->GTK_len);
|
||||||
|
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) {
|
||||||
if (os_get_random(group->IGTK[group->GN_igtk - 4],
|
os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN);
|
||||||
WPA_IGTK_LEN) < 0) {
|
inc_byte_array(group->Counter, WPA_NONCE_LEN);
|
||||||
wpa_printf(MSG_INFO, "RSN: Failed to get new random "
|
wpa_gmk_to_gtk(group->GMK, "IGTK key expansion",
|
||||||
"IGTK");
|
wpa_auth->addr, group->GNonce,
|
||||||
ret = -1;
|
group->IGTK[group->GN_igtk - 4],
|
||||||
}
|
WPA_IGTK_LEN);
|
||||||
wpa_hexdump_key(MSG_DEBUG, "IGTK",
|
wpa_hexdump_key(MSG_DEBUG, "IGTK",
|
||||||
group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
|
group->IGTK[group->GN_igtk - 4], WPA_IGTK_LEN);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue