Browse Source

FILS: Implement FILS-FT derivation

This extends fils_pmk_to_ptk() to allow FILS-FT to be derived. The
callers do not yet use that capability; i.e., actual use will be added
in separate commits.

Signed-off-by: Jouni Malinen <j@w1.fi>
Jouni Malinen 7 years ago
parent
commit
215eaa748b
4 changed files with 28 additions and 7 deletions
  1. 1 1
      src/ap/wpa_auth.c
  2. 22 3
      src/common/wpa_common.c
  3. 3 1
      src/common/wpa_common.h
  4. 2 2
      src/rsn_supp/wpa.c

+ 1 - 1
src/ap/wpa_auth.c

@@ -2092,7 +2092,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
 
 	res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr,
 			      snonce, anonce, &sm->PTK, ick, &ick_len,
-			      sm->wpa_key_mgmt, sm->pairwise);
+			      sm->wpa_key_mgmt, sm->pairwise, NULL, NULL);
 	if (res < 0)
 		return res;
 	sm->PTK_valid = TRUE;

+ 22 - 3
src/common/wpa_common.c

@@ -339,10 +339,12 @@ int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
 
 int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 		    const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk,
-		    u8 *ick, size_t *ick_len, int akmp, int cipher)
+		    u8 *ick, size_t *ick_len, int akmp, int cipher,
+		    u8 *fils_ft, size_t *fils_ft_len)
 {
 	u8 data[2 * ETH_ALEN + 2 * FILS_NONCE_LEN];
-	u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN];
+	u8 tmp[FILS_ICK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN +
+	       FILS_FT_MAX_LEN];
 	size_t key_data_len;
 	const char *label = "FILS PTK Derivation";
 
@@ -372,6 +374,18 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 		return -1;
 	key_data_len = *ick_len + ptk->kek_len + ptk->tk_len;
 
+	if (fils_ft && fils_ft_len) {
+		if (akmp == WPA_KEY_MGMT_FT_FILS_SHA256) {
+			*fils_ft_len = 32;
+		} else if (akmp == WPA_KEY_MGMT_FT_FILS_SHA384) {
+			*fils_ft_len = 48;
+		} else {
+			*fils_ft_len = 0;
+			fils_ft = NULL;
+		}
+		key_data_len += *fils_ft_len;
+	}
+
 	if (wpa_key_mgmt_sha384(akmp)) {
 		wpa_printf(MSG_DEBUG, "FILS: PTK derivation using PRF(SHA384)");
 		if (sha384_prf(pmk, pmk_len, label, data, sizeof(data),
@@ -400,7 +414,12 @@ int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 	os_memcpy(ptk->tk, tmp + *ick_len + ptk->kek_len, ptk->tk_len);
 	wpa_hexdump_key(MSG_DEBUG, "FILS: TK", ptk->tk, ptk->tk_len);
 
-	/* TODO: FILS-FT */
+	if (fils_ft && fils_ft_len) {
+		os_memcpy(fils_ft, tmp + *ick_len + ptk->kek_len + ptk->tk_len,
+			  *fils_ft_len);
+		wpa_hexdump_key(MSG_DEBUG, "FILS: FILS-FT",
+				fils_ft, *fils_ft_len);
+	}
 
 	os_memset(tmp, 0, sizeof(tmp));
 	return 0;

+ 3 - 1
src/common/wpa_common.h

@@ -202,6 +202,7 @@ struct wpa_eapol_key {
 #define WPA_KEK_MAX_LEN 64
 #define WPA_TK_MAX_LEN 32
 #define FILS_ICK_MAX_LEN 48
+#define FILS_FT_MAX_LEN 48
 
 /**
  * struct wpa_ptk - WPA Pairwise Transient Key
@@ -346,7 +347,8 @@ int fils_pmkid_erp(int akmp, const u8 *reauth, size_t reauth_len,
 		   u8 *pmkid);
 int fils_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const u8 *spa, const u8 *aa,
 		    const u8 *snonce, const u8 *anonce, struct wpa_ptk *ptk,
-		    u8 *ick, size_t *ick_len, int akmp, int cipher);
+		    u8 *ick, size_t *ick_len, int akmp, int cipher,
+		    u8 *fils_ft, size_t *fils_ft_len);
 int fils_key_auth_sk(const u8 *ick, size_t ick_len, const u8 *snonce,
 		     const u8 *anonce, const u8 *sta_addr, const u8 *bssid,
 		     const u8 *g_sta, size_t g_sta_len,

+ 2 - 2
src/rsn_supp/wpa.c

@@ -3603,8 +3603,8 @@ int fils_process_auth(struct wpa_sm *sm, const u8 *bssid, const u8 *data,
 
 	if (fils_pmk_to_ptk(sm->pmk, sm->pmk_len, sm->own_addr, sm->bssid,
 			    sm->fils_nonce, sm->fils_anonce, &sm->ptk,
-			    ick, &ick_len, sm->key_mgmt, sm->pairwise_cipher) <
-	    0) {
+			    ick, &ick_len, sm->key_mgmt, sm->pairwise_cipher,
+			    NULL, NULL) < 0) {
 		wpa_printf(MSG_DEBUG, "FILS: Failed to derive PTK");
 		goto fail;
 	}