Browse Source

FILS: Add elements to FILS Association Request frame

Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
Jouni Malinen 9 years ago
parent
commit
86cd6928e0
4 changed files with 87 additions and 1 deletions
  1. 49 0
      src/rsn_supp/wpa.c
  2. 3 0
      src/rsn_supp/wpa.h
  3. 34 0
      wpa_supplicant/sme.c
  4. 1 1
      wpa_supplicant/wpa_supplicant_i.h

+ 49 - 0
src/rsn_supp/wpa.c

@@ -3422,4 +3422,53 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len)
 	return res;
 }
 
+
+struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
+				     size_t *kek_len, const u8 **snonce,
+				     const u8 **anonce)
+{
+	struct wpabuf *buf;
+
+	buf = wpabuf_alloc(1000);
+	if (!buf)
+		return NULL;
+
+	/* FILS Session */
+	wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+	wpabuf_put_u8(buf, 1 + FILS_SESSION_LEN); /* Length */
+	/* Element ID Extension */
+	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_SESSION);
+	wpabuf_put_data(buf, sm->fils_session, FILS_SESSION_LEN);
+
+	/* Everything after FILS Session element gets encrypted in the driver
+	 * with KEK. The buffer returned from here is the plaintext version. */
+
+	/* TODO: FILS Public Key */
+
+	/* FILS Key Confirm */
+	wpabuf_put_u8(buf, WLAN_EID_EXTENSION); /* Element ID */
+	wpabuf_put_u8(buf, 1 + sm->fils_key_auth_len); /* Length */
+	/* Element ID Extension */
+	wpabuf_put_u8(buf, WLAN_EID_EXT_FILS_KEY_CONFIRM);
+	wpabuf_put_data(buf, sm->fils_key_auth_sta, sm->fils_key_auth_len);
+
+	/* TODO: FILS HLP Container */
+
+	/* TODO: FILS IP Address Assignment */
+
+	wpa_hexdump_buf(MSG_DEBUG, "FILS: Association Request plaintext", buf);
+
+	*kek = sm->ptk.kek;
+	*kek_len = sm->ptk.kek_len;
+	wpa_hexdump_key(MSG_DEBUG, "FILS: KEK for AEAD", *kek, *kek_len);
+	*snonce = sm->fils_nonce;
+	wpa_hexdump(MSG_DEBUG, "FILS: SNonce for AEAD AAD",
+		    *snonce, FILS_NONCE_LEN);
+	*anonce = sm->fils_anonce;
+	wpa_hexdump(MSG_DEBUG, "FILS: ANonce for AEAD AAD",
+		    *anonce, FILS_NONCE_LEN);
+
+	return buf;
+}
+
 #endif /* CONFIG_FILS */

+ 3 - 0
src/rsn_supp/wpa.h

@@ -428,5 +428,8 @@ void wpa_sm_set_test_assoc_ie(struct wpa_sm *sm, struct wpabuf *buf);
 
 struct wpabuf * fils_build_auth(struct wpa_sm *sm);
 int fils_process_auth(struct wpa_sm *sm, const u8 *data, size_t len);
+struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek,
+				     size_t *kek_len, const u8 **snonce,
+				     const u8 **anonce);
 
 #endif /* WPA_H */

+ 34 - 0
wpa_supplicant/sme.c

@@ -986,6 +986,9 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
 {
 	struct wpa_driver_associate_params params;
 	struct ieee802_11_elems elems;
+#ifdef CONFIG_FILS
+	u8 nonces[2 * FILS_NONCE_LEN];
+#endif /* CONFIG_FILS */
 #ifdef CONFIG_HT_OVERRIDES
 	struct ieee80211_ht_capabilities htcaps;
 	struct ieee80211_ht_capabilities htcaps_mask;
@@ -996,6 +999,37 @@ void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode,
 #endif /* CONFIG_VHT_OVERRIDES */
 
 	os_memset(&params, 0, sizeof(params));
+
+#ifdef CONFIG_FILS
+	if (auth_type == WLAN_AUTH_FILS_SK) {
+		struct wpabuf *buf;
+		const u8 *snonce, *anonce;
+
+		buf = fils_build_assoc_req(wpa_s->wpa, &params.fils_kek,
+					   &params.fils_kek_len, &snonce,
+					   &anonce);
+		if (!buf)
+			return;
+		/* TODO: Make wpa_s->sme.assoc_req_ie use dynamic allocation */
+		if (wpa_s->sme.assoc_req_ie_len + wpabuf_len(buf) >
+		    sizeof(wpa_s->sme.assoc_req_ie)) {
+			wpa_printf(MSG_ERROR,
+				   "FILS: Not enough buffer room for own AssocReq elements");
+			wpabuf_free(buf);
+			return;
+		}
+		os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len,
+			  wpabuf_head(buf), wpabuf_len(buf));
+		wpa_s->sme.assoc_req_ie_len += wpabuf_len(buf);
+		wpabuf_free(buf);
+
+		os_memcpy(nonces, snonce, FILS_NONCE_LEN);
+		os_memcpy(nonces + FILS_NONCE_LEN, anonce, FILS_NONCE_LEN);
+		params.fils_nonces = nonces;
+		params.fils_nonces_len = sizeof(nonces);
+	}
+#endif /* CONFIG_FILS */
+
 	params.bssid = bssid;
 	params.ssid = wpa_s->sme.ssid;
 	params.ssid_len = wpa_s->sme.ssid_len;

+ 1 - 1
wpa_supplicant/wpa_supplicant_i.h

@@ -721,7 +721,7 @@ struct wpa_supplicant {
 		u8 ssid[SSID_MAX_LEN];
 		size_t ssid_len;
 		int freq;
-		u8 assoc_req_ie[200];
+		u8 assoc_req_ie[300];
 		size_t assoc_req_ie_len;
 		int mfp;
 		int ft_used;