FILS: Add Association Response frame elements and encrypt them (AP)
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
78815f3dde
commit
e73ffa0925
3 changed files with 155 additions and 0 deletions
|
@ -2347,6 +2347,31 @@ static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta,
|
|||
|
||||
send_len += p - reply->u.assoc_resp.variable;
|
||||
|
||||
#ifdef CONFIG_FILS
|
||||
if ((sta->auth_alg == WLAN_AUTH_FILS_SK ||
|
||||
sta->auth_alg == WLAN_AUTH_FILS_SK_PFS ||
|
||||
sta->auth_alg == WLAN_AUTH_FILS_PK) &&
|
||||
status_code == WLAN_STATUS_SUCCESS) {
|
||||
struct ieee802_11_elems elems;
|
||||
|
||||
if (ieee802_11_parse_elems(ies, ies_len, &elems, 0) ==
|
||||
ParseFailed || !elems.fils_session)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
|
||||
/* FILS Session */
|
||||
*p++ = WLAN_EID_EXTENSION; /* Element ID */
|
||||
*p++ = 1 + FILS_SESSION_LEN; /* Length */
|
||||
*p++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */
|
||||
os_memcpy(p, elems.fils_session, FILS_SESSION_LEN);
|
||||
send_len += 2 + 1 + FILS_SESSION_LEN;
|
||||
|
||||
send_len = fils_encrypt_assoc(sta->wpa_sm, buf, send_len,
|
||||
sizeof(buf));
|
||||
if (send_len < 0)
|
||||
return WLAN_STATUS_UNSPECIFIED_FAILURE;
|
||||
}
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) {
|
||||
wpa_printf(MSG_INFO, "Failed to send assoc resp: %s",
|
||||
strerror(errno));
|
||||
|
|
|
@ -58,6 +58,7 @@ static void wpa_group_get(struct wpa_authenticator *wpa_auth,
|
|||
struct wpa_group *group);
|
||||
static void wpa_group_put(struct wpa_authenticator *wpa_auth,
|
||||
struct wpa_group *group);
|
||||
static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
|
||||
|
||||
static const u32 dot11RSNAConfigGroupUpdateCount = 4;
|
||||
static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
|
||||
|
@ -2255,6 +2256,133 @@ int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
|
|||
return left - AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
|
||||
int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
|
||||
size_t current_len, size_t max_len)
|
||||
{
|
||||
u8 *end = buf + max_len;
|
||||
u8 *pos = buf + current_len;
|
||||
struct ieee80211_mgmt *mgmt;
|
||||
struct wpabuf *plain;
|
||||
u8 *len, *tmp, *tmp2;
|
||||
u8 hdr[2];
|
||||
u8 *gtk, dummy_gtk[32];
|
||||
size_t gtk_len;
|
||||
struct wpa_group *gsm;
|
||||
const u8 *aad[5];
|
||||
size_t aad_len[5];
|
||||
|
||||
if (!sm || !sm->PTK_valid)
|
||||
return -1;
|
||||
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"FILS: Association Response frame before FILS processing",
|
||||
buf, current_len);
|
||||
|
||||
mgmt = (struct ieee80211_mgmt *) buf;
|
||||
|
||||
/* AES-SIV AAD vectors */
|
||||
|
||||
/* The AP's BSSID */
|
||||
aad[0] = mgmt->sa;
|
||||
aad_len[0] = ETH_ALEN;
|
||||
/* The STA's MAC address */
|
||||
aad[1] = mgmt->da;
|
||||
aad_len[1] = ETH_ALEN;
|
||||
/* The AP's nonce */
|
||||
aad[2] = sm->ANonce;
|
||||
aad_len[2] = FILS_NONCE_LEN;
|
||||
/* The STA's nonce */
|
||||
aad[3] = sm->SNonce;
|
||||
aad_len[3] = FILS_NONCE_LEN;
|
||||
/*
|
||||
* The (Re)Association Response frame from the Capability Information
|
||||
* field (the same offset in both Association and Reassociation
|
||||
* Response frames) to the FILS Session element (both inclusive).
|
||||
*/
|
||||
aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info;
|
||||
aad_len[4] = pos - aad[4];
|
||||
|
||||
/* The following elements will be encrypted with AES-SIV */
|
||||
|
||||
plain = wpabuf_alloc(1000);
|
||||
if (!plain)
|
||||
return -1;
|
||||
|
||||
/* TODO: FILS Public Key */
|
||||
|
||||
/* FILS Key Confirmation */
|
||||
wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
|
||||
wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */
|
||||
/* Element ID Extension */
|
||||
wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM);
|
||||
wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len);
|
||||
|
||||
/* TODO: FILS HLP Container */
|
||||
|
||||
/* TODO: FILS IP Address Assignment */
|
||||
|
||||
/* Key Delivery */
|
||||
gsm = sm->group;
|
||||
wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */
|
||||
len = wpabuf_put(plain, 1);
|
||||
wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY);
|
||||
wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN,
|
||||
wpabuf_put(plain, WPA_KEY_RSC_LEN));
|
||||
/* GTK KDE */
|
||||
gtk = gsm->GTK[gsm->GN - 1];
|
||||
gtk_len = gsm->GTK_len;
|
||||
if (sm->wpa_auth->conf.disable_gtk) {
|
||||
/*
|
||||
* Provide unique random GTK to each STA to prevent use
|
||||
* of GTK in the BSS.
|
||||
*/
|
||||
if (random_get_bytes(dummy_gtk, gtk_len) < 0) {
|
||||
wpabuf_free(plain);
|
||||
return -1;
|
||||
}
|
||||
gtk = dummy_gtk;
|
||||
}
|
||||
hdr[0] = gsm->GN & 0x03;
|
||||
hdr[1] = 0;
|
||||
tmp = wpabuf_put(plain, 0);
|
||||
tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2,
|
||||
gtk, gtk_len);
|
||||
wpabuf_put(plain, tmp2 - tmp);
|
||||
|
||||
/* IGTK KDE */
|
||||
tmp = wpabuf_put(plain, 0);
|
||||
tmp2 = ieee80211w_kde_add(sm, tmp);
|
||||
wpabuf_put(plain, tmp2 - tmp);
|
||||
|
||||
*len = (u8 *) wpabuf_put(plain, 0) - len - 1;
|
||||
|
||||
if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) {
|
||||
wpa_printf(MSG_DEBUG,
|
||||
"FILS: Not enough room for FILS elements");
|
||||
wpabuf_free(plain);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext",
|
||||
plain);
|
||||
|
||||
if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len,
|
||||
wpabuf_head(plain), wpabuf_len(plain),
|
||||
5, aad, aad_len, pos) < 0) {
|
||||
wpabuf_free(plain);
|
||||
return -1;
|
||||
}
|
||||
|
||||
wpa_hexdump(MSG_DEBUG,
|
||||
"FILS: Encrypted Association Response elements",
|
||||
pos, AES_BLOCK_SIZE + wpabuf_len(plain));
|
||||
current_len += wpabuf_len(plain) + AES_BLOCK_SIZE;
|
||||
wpabuf_free(plain);
|
||||
|
||||
return current_len;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_FILS */
|
||||
|
||||
|
||||
|
|
|
@ -353,5 +353,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
|
|||
int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session,
|
||||
const struct ieee80211_mgmt *mgmt, size_t frame_len,
|
||||
u8 *pos, size_t left);
|
||||
int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf,
|
||||
size_t current_len, size_t max_len);
|
||||
|
||||
#endif /* WPA_AUTH_H */
|
||||
|
|
Loading…
Reference in a new issue