From 835822d404c507d1bad223d87eae24d0ff634918 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sun, 16 Dec 2012 19:46:10 +0200 Subject: [PATCH] WNM: Fix GTK/IGTK encoding in WNM-Sleep Mode Exit frame These subelements do not use AES key wrap (MFP is used instead). Signed-hostap: Jouni Malinen --- src/ap/wpa_auth.c | 112 ++++++++++++++-------------------------------- 1 file changed, 33 insertions(+), 79 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 0dc3f58a5..2c70149a1 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -2444,108 +2444,62 @@ void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) { - u8 *subelem; struct wpa_group *gsm = sm->group; - size_t subelem_len, pad_len; - const u8 *key; - size_t key_len; - u8 keybuf[32]; - - /* GTK subslement */ - key_len = gsm->GTK_len; - if (key_len > sizeof(keybuf)) - return 0; - - /* - * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less - * than 16 bytes. - */ - pad_len = key_len % 8; - if (pad_len) - pad_len = 8 - pad_len; - if (key_len + pad_len < 16) - pad_len += 8; - if (pad_len) { - os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len); - os_memset(keybuf + key_len, 0, pad_len); - keybuf[key_len] = 0xdd; - key_len += pad_len; - key = keybuf; - } else - key = gsm->GTK[gsm->GN - 1]; + u8 *start = pos; /* + * GTK subelement: * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | - * Key[5..32] | 8 padding. + * Key[5..32] */ - subelem_len = 13 + key_len + 8; - subelem = os_zalloc(subelem_len); - if (subelem == NULL) - return 0; - - subelem[0] = WNM_SLEEP_SUBELEM_GTK; - subelem[1] = 11 + key_len + 8; + *pos++ = WNM_SLEEP_SUBELEM_GTK; + *pos++ = 11 + gsm->GTK_len; /* Key ID in B0-B1 of Key Info */ - WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03); - subelem[4] = gsm->GTK_len; - if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5) != 0) - { - os_free(subelem); + WPA_PUT_LE16(pos, gsm->GN & 0x03); + pos += 2; + *pos++ = gsm->GTK_len; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) return 0; - } - if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) { - os_free(subelem); - return 0; - } + pos += 8; + os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); + pos += gsm->GTK_len; - os_memcpy(pos, subelem, subelem_len); - - wpa_hexdump_key(MSG_DEBUG, "Plaintext GTK", + wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN); + wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", gsm->GTK[gsm->GN - 1], gsm->GTK_len); - os_free(subelem); - return subelem_len; + return pos - start; } #ifdef CONFIG_IEEE80211W int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) { - u8 *subelem, *ptr; struct wpa_group *gsm = sm->group; - size_t subelem_len; + u8 *start = pos; - /* IGTK subelement - * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | - * Key[16] | 8 padding */ - subelem_len = 1 + 1 + 2 + 6 + WPA_IGTK_LEN + 8; - subelem = os_zalloc(subelem_len); - if (subelem == NULL) + /* + * 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; + 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; - ptr = subelem; - *ptr++ = WNM_SLEEP_SUBELEM_IGTK; - *ptr++ = subelem_len - 2; - WPA_PUT_LE16(ptr, gsm->GN_igtk); - ptr += 2; - if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, ptr) != 0) { - os_free(subelem); - return 0; - } - ptr += 6; - if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8, - gsm->IGTK[gsm->GN_igtk - 4], ptr)) { - os_free(subelem); - return -1; - } + os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN); + pos += WPA_IGTK_LEN; - os_memcpy(pos, subelem, subelem_len); - - wpa_hexdump_key(MSG_DEBUG, "Plaintext IGTK", + 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); - os_free(subelem); - return subelem_len; + return pos - start; } #endif /* CONFIG_IEEE80211W */ #endif /* CONFIG_WNM */