|
@@ -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);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- if (aes_wrap(sm->PTK.kek, key_len / 8, key, subelem + 13)) {
|
|
|
- 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;
|
|
|
- }
|
|
|
-
|
|
|
- os_memcpy(pos, subelem, subelem_len);
|
|
|
+ pos += 8;
|
|
|
+ os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len);
|
|
|
+ pos += gsm->GTK_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;
|
|
|
-
|
|
|
- /* 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)
|
|
|
- return 0;
|
|
|
+ u8 *start = pos;
|
|
|
|
|
|
- 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);
|
|
|
+ /*
|
|
|
+ * 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;
|
|
|
- }
|
|
|
- ptr += 6;
|
|
|
- if (aes_wrap(sm->PTK.kek, WPA_IGTK_LEN / 8,
|
|
|
- gsm->IGTK[gsm->GN_igtk - 4], ptr)) {
|
|
|
- os_free(subelem);
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ pos += 6;
|
|
|
|
|
|
- os_memcpy(pos, subelem, subelem_len);
|
|
|
+ os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], WPA_IGTK_LEN);
|
|
|
+ pos += WPA_IGTK_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 */
|