Procházet zdrojové kódy

wifi: Add PMK caching feature for station WPA2-enterprise

4. Pmksa cache expiry after dot11RSNAConfigPMKLifetime timeout.
Hrudaynath Dhabe před 6 roky
rodič
revize
4d3356be52

+ 3 - 10
components/wpa_supplicant/src/esp_supplicant/esp_wpa2.c

@@ -697,16 +697,9 @@ static int wpa2_start_eapol_internal(void)
         return ESP_FAIL;
     }
     if (wpa_sta_is_cur_pmksa_set()) {
-        if (0) {
-            wpa_printf(MSG_DEBUG,
-                    "RSN: Timeout on waiting for the AP to initiate 4-way handshake \
-                    for PMKSA caching or EAP authentication \
-                    - try to force it to start EAP authentication");
-        } else {
-            wpa_printf(MSG_DEBUG,
-                    "RSN: PMKSA caching - do not send EAPOL-Start");
-            return -1;
-        }
+        wpa_printf(MSG_DEBUG,
+                "RSN: PMKSA caching - do not send EAPOL-Start");
+        return ESP_FAIL;
     }
 
     ret = esp_wifi_get_assoc_bssid_internal(bssid);

+ 0 - 6
components/wpa_supplicant/src/esp_supplicant/esp_wpa_main.c

@@ -109,14 +109,8 @@ void  wpa_neg_complete(void)
 bool  wpa_attach(void)
 {
     bool ret = true; 
-#ifndef IOT_SIP_MODE
     ret = wpa_sm_init(NULL, wpa_sendto_wrapper,
                  wpa_config_assoc_ie, wpa_install_key, wpa_get_key, wpa_deauthenticate, wpa_neg_complete);
-#else
-    u8 *payload = (u8 *)os_malloc(WPA_TX_MSG_BUFF_MAXLEN);
-    ret = wpa_sm_init(payload, wpa_sendto_wrapper,
-                 wpa_config_assoc_ie, wpa_install_key, wpa_get_key, wpa_deauthenticate, wpa_neg_complete);
-#endif
     if(ret) {   
         ret = (esp_wifi_register_tx_cb_internal(eapol_txcb, WIFI_TXCB_EAPOL_ID) == ESP_OK);
     }

+ 326 - 336
components/wpa_supplicant/src/rsn_supp/pmksa_cache.c

@@ -13,92 +13,75 @@
 #include "common/eapol_common.h"
 #include "common/ieee802_11_defs.h"
 #include "pmksa_cache.h"
+#include "esp_timer.h"
 
 #ifdef IEEE8021X_EAPOL
 
 static const int pmksa_cache_max_entries = 10;
+static const int dot11RSNAConfigPMKLifetime = 43200;
+static const int dot11RSNAConfigPMKReauthThreshold = 70;
 
 struct rsn_pmksa_cache {
-	struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */
-	int pmksa_count; /* number of entries in PMKSA cache */
-	struct wpa_sm *sm; /* TODO: get rid of this reference(?) */
-
-	void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx,
-			enum pmksa_free_reason reason);
-	void *ctx;
+    struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */
+    int pmksa_count; /* number of entries in PMKSA cache */
+    struct wpa_sm *sm; /* TODO: get rid of this reference(?) */
+    esp_timer_handle_t cache_timeout_timer;
+
+    void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx,
+            enum pmksa_free_reason reason);
+    void *ctx;
 };
 
 
-//static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
+static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
 
 
 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
 {
-	bin_clear_free(entry, sizeof(*entry));
+    wpa_bin_clear_free(entry, sizeof(*entry));
 }
 
 
 static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
-				   struct rsn_pmksa_cache_entry *entry,
-				   enum pmksa_free_reason reason)
+        struct rsn_pmksa_cache_entry *entry,
+        enum pmksa_free_reason reason)
 {
-	//wpa_sm_remove_pmkid(pmksa->sm, entry->aa, entry->pmkid);
-	pmksa->pmksa_count--;
-	pmksa->free_cb(entry, pmksa->ctx, reason);
-	_pmksa_cache_free_entry(entry);
+    pmksa->pmksa_count--;
+    pmksa->free_cb(entry, pmksa->ctx, reason);
+    _pmksa_cache_free_entry(entry);
 }
 
-#if 0
-static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
-{
-	struct rsn_pmksa_cache *pmksa = eloop_ctx;
-	struct os_reltime now;
-
-	os_get_reltime(&now);
-	while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
-		struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
-		pmksa->pmksa = entry->next;
-		wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
-			   MACSTR, MAC2STR(entry->aa));
-		pmksa_cache_free_entry(pmksa, entry, PMKSA_EXPIRE);
-	}
-
-	pmksa_cache_set_expiration(pmksa);
-}
 
-static void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx)
+static void pmksa_cache_expire(void *eloop_ctx)
 {
-	struct rsn_pmksa_cache *pmksa = eloop_ctx;
-	pmksa->sm->cur_pmksa = NULL;
-	eapol_sm_request_reauth(pmksa->sm->eapol);
+    struct rsn_pmksa_cache *pmksa = eloop_ctx;
+    int64_t now_sec = esp_timer_get_time() / 1e6;
+
+    while (pmksa->pmksa && pmksa->pmksa->expiration <= now_sec) {
+        struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
+        pmksa->pmksa = entry->next;
+        wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
+                MACSTR, MAC2STR(entry->aa));
+        pmksa_cache_free_entry(pmksa, entry, PMKSA_EXPIRE);
+    }
+
+    pmksa_cache_set_expiration(pmksa);
 }
 
 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
 {
-	int sec;
-	struct rsn_pmksa_cache_entry *entry;
-	struct os_reltime now;
-
-	eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL);
-	if (pmksa->pmksa == NULL)
-		return;
-	os_get_reltime(&now);
-	sec = pmksa->pmksa->expiration - now.sec;
-	if (sec < 0)
-		sec = 0;
-	eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
-
-	entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
-		pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL);
-	if (entry) {
-		sec = pmksa->pmksa->reauth_time - now.sec;
-		if (sec < 0)
-			sec = 0;
-		eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa,
-				       NULL);
-	}
+    int sec;
+    int64_t now_sec = esp_timer_get_time() / 1e6;
+
+    esp_timer_stop(pmksa->cache_timeout_timer);
+    if (pmksa->pmksa == NULL)
+        return;
+    sec = pmksa->pmksa->expiration - now_sec;
+    if (sec < 0)
+        sec = 0;
+
+    esp_timer_start_once(pmksa->cache_timeout_timer, (sec + 1) * 1e6);
 }
-#endif
 
 /**
  * pmksa_cache_add - Add a PMKSA cache entry
@@ -120,122 +103,120 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
  */
 struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-		const u8 *kck, size_t kck_len,
-		const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
+        const u8 *kck, size_t kck_len,
+        const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
 {
-	struct rsn_pmksa_cache_entry *entry, *pos, *prev;
-	//struct os_reltime now;
+    struct rsn_pmksa_cache_entry *entry, *pos, *prev;
+    int64_t now_sec = esp_timer_get_time() / 1e6;
 
-	if (pmk_len > PMK_LEN)
-		return NULL;
+    if (pmk_len > PMK_LEN)
+        return NULL;
 
-	if (wpa_key_mgmt_suite_b(akmp) && !kck)
-		return NULL;
+    if (wpa_key_mgmt_suite_b(akmp) && !kck)
+        return NULL;
 
-	entry = os_zalloc(sizeof(*entry));
-	if (entry == NULL)
-		return NULL;
-	os_memcpy(entry->pmk, pmk, pmk_len);
-	entry->pmk_len = pmk_len;
+    entry = os_zalloc(sizeof(*entry));
+    if (entry == NULL)
+        return NULL;
+    os_memcpy(entry->pmk, pmk, pmk_len);
+    entry->pmk_len = pmk_len;
     rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
-			  wpa_key_mgmt_sha256(akmp));
-	//os_get_reltime(&now);
-	//entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime;
-	/*entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime *
-		pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100;*/
-	entry->akmp = akmp;
-	os_memcpy(entry->aa, aa, ETH_ALEN);
-	entry->network_ctx = network_ctx;
-
-	/* Replace an old entry for the same Authenticator (if found) with the
-	 * new entry */
-	pos = pmksa->pmksa;
-	prev = NULL;
-	while (pos) {
-		if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) {
-			if (pos->pmk_len == pmk_len &&
-			    os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 &&
-			    os_memcmp_const(pos->pmkid, entry->pmkid,
-					    PMKID_LEN) == 0) {
-				wpa_printf(MSG_DEBUG, "WPA: reusing previous "
-					   "PMKSA entry");
-				os_free(entry);
-				return pos;
-			}
-			if (prev == NULL)
-				pmksa->pmksa = pos->next;
-			else
-				prev->next = pos->next;
-
-			/*
-			 * If OKC is used, there may be other PMKSA cache
-			 * entries based on the same PMK. These needs to be
-			 * flushed so that a new entry can be created based on
-			 * the new PMK. Only clear other entries if they have a
-			 * matching PMK and this PMK has been used successfully
-			 * with the current AP, i.e., if opportunistic flag has
-			 * been cleared in wpa_supplicant_key_neg_complete().
-			 */
-			wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
-				   "the current AP and any PMKSA cache entry "
-				   "that was based on the old PMK");
-			if (!pos->opportunistic)
-				pmksa_cache_flush(pmksa, network_ctx, pos->pmk,
-						  pos->pmk_len);
-			pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
-			break;
-		}
-		prev = pos;
-		pos = pos->next;
-	}
-
-	if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
-		/* Remove the oldest entry to make room for the new entry */
-		pos = pmksa->pmksa;
-
-		if (pos == pmksa->sm->cur_pmksa) {
-			/*
-			 * Never remove the current PMKSA cache entry, since
-			 * it's in use, and removing it triggers a needless
-			 * deauthentication.
-			 */
-			pos = pos->next;
-			pmksa->pmksa->next = pos ? pos->next : NULL;
-		} else
-			pmksa->pmksa = pos->next;
-
-		if (pos) {
-			wpa_printf(MSG_DEBUG, "RSN: removed the oldest idle "
-				   "PMKSA cache entry (for " MACSTR ") to "
-				   "make room for new one",
-				   MAC2STR(pos->aa));
-			pmksa_cache_free_entry(pmksa, pos, PMKSA_FREE);
-		}
-	}
-
-	/* Add the new entry; order by expiration time */
-	pos = pmksa->pmksa;
-	prev = NULL;
-	while (pos) {
-		if (pos->expiration > entry->expiration)
-			break;
-		prev = pos;
-		pos = pos->next;
-	}
-	if (prev == NULL) {
-		entry->next = pmksa->pmksa;
-		pmksa->pmksa = entry;
-		//pmksa_cache_set_expiration(pmksa);
-	} else {
-		entry->next = prev->next;
-		prev->next = entry;
-	}
-	pmksa->pmksa_count++;
-	wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR
-		   " network_ctx=%p", MAC2STR(entry->aa), network_ctx);
-	//wpa_sm_add_pmkid(pmksa->sm, entry->aa, entry->pmkid);
-
-	return entry;
+            wpa_key_mgmt_sha256(akmp));
+    entry->expiration = now_sec + dot11RSNAConfigPMKLifetime;
+    entry->reauth_time = now_sec + dot11RSNAConfigPMKLifetime *
+        dot11RSNAConfigPMKReauthThreshold / 100;
+    entry->akmp = akmp;
+    os_memcpy(entry->aa, aa, ETH_ALEN);
+    entry->network_ctx = network_ctx;
+
+    /* Replace an old entry for the same Authenticator (if found) with the
+     * new entry */
+    pos = pmksa->pmksa;
+    prev = NULL;
+    while (pos) {
+        if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) {
+            if (pos->pmk_len == pmk_len &&
+                    os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 &&
+                    os_memcmp_const(pos->pmkid, entry->pmkid,
+                        PMKID_LEN) == 0) {
+                wpa_printf(MSG_DEBUG, "WPA: reusing previous "
+                        "PMKSA entry");
+                os_free(entry);
+                return pos;
+            }
+            if (prev == NULL)
+                pmksa->pmksa = pos->next;
+            else
+                prev->next = pos->next;
+
+            /*
+             * If OKC is used, there may be other PMKSA cache
+             * entries based on the same PMK. These needs to be
+             * flushed so that a new entry can be created based on
+             * the new PMK. Only clear other entries if they have a
+             * matching PMK and this PMK has been used successfully
+             * with the current AP, i.e., if opportunistic flag has
+             * been cleared in wpa_supplicant_key_neg_complete().
+             */
+            wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
+                    "the current AP and any PMKSA cache entry "
+                    "that was based on the old PMK");
+            if (!pos->opportunistic)
+                pmksa_cache_flush(pmksa, network_ctx, pos->pmk,
+                        pos->pmk_len);
+            pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
+            break;
+        }
+        prev = pos;
+        pos = pos->next;
+    }
+
+    if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
+        /* Remove the oldest entry to make room for the new entry */
+        pos = pmksa->pmksa;
+
+        if (pos == pmksa->sm->cur_pmksa) {
+            /*
+             * Never remove the current PMKSA cache entry, since
+             * it's in use, and removing it triggers a needless
+             * deauthentication.
+             */
+            pos = pos->next;
+            pmksa->pmksa->next = pos ? pos->next : NULL;
+        } else
+            pmksa->pmksa = pos->next;
+
+        if (pos) {
+            wpa_printf(MSG_DEBUG, "RSN: removed the oldest idle "
+                    "PMKSA cache entry (for " MACSTR ") to "
+                    "make room for new one",
+                    MAC2STR(pos->aa));
+            pmksa_cache_free_entry(pmksa, pos, PMKSA_FREE);
+        }
+    }
+
+    /* Add the new entry; order by expiration time */
+    pos = pmksa->pmksa;
+    prev = NULL;
+    while (pos) {
+        if (pos->expiration > entry->expiration)
+            break;
+        prev = pos;
+        pos = pos->next;
+    }
+    if (prev == NULL) {
+        entry->next = pmksa->pmksa;
+        pmksa->pmksa = entry;
+        pmksa_cache_set_expiration(pmksa);
+    } else {
+        entry->next = prev->next;
+        prev->next = entry;
+    }
+    pmksa->pmksa_count++;
+    wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR
+            " network_ctx=%p", MAC2STR(entry->aa), network_ctx);
+
+    return entry;
 }
 
 
@@ -247,35 +228,35 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
  * @pmk_len: PMK length
  */
 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-		       const u8 *pmk, size_t pmk_len)
+        const u8 *pmk, size_t pmk_len)
 {
-	struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
-	int removed = 0;
-
-	entry = pmksa->pmksa;
-	while (entry) {
-		if ((entry->network_ctx == network_ctx ||
-		     network_ctx == NULL) &&
-		    (pmk == NULL ||
-		     (pmk_len == entry->pmk_len &&
-		      os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
-			wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
-				   "for " MACSTR, MAC2STR(entry->aa));
-			if (prev)
-				prev->next = entry->next;
-			else
-				pmksa->pmksa = entry->next;
-			tmp = entry;
-			entry = entry->next;
-			pmksa_cache_free_entry(pmksa, tmp, PMKSA_FREE);
-			removed++;
-		} else {
-			prev = entry;
-			entry = entry->next;
-		}
-	}
-	/*if (removed)
-		pmksa_cache_set_expiration(pmksa);*/
+    struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp;
+    int removed = 0;
+
+    entry = pmksa->pmksa;
+    while (entry) {
+        if ((entry->network_ctx == network_ctx ||
+                    network_ctx == NULL) &&
+                (pmk == NULL ||
+                 (pmk_len == entry->pmk_len &&
+                  os_memcmp(pmk, entry->pmk, pmk_len) == 0))) {
+            wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry "
+                    "for " MACSTR, MAC2STR(entry->aa));
+            if (prev)
+                prev->next = entry->next;
+            else
+                pmksa->pmksa = entry->next;
+            tmp = entry;
+            entry = entry->next;
+            pmksa_cache_free_entry(pmksa, tmp, PMKSA_FREE);
+            removed++;
+        } else {
+            prev = entry;
+            entry = entry->next;
+        }
+    }
+    /*if (removed)
+      pmksa_cache_set_expiration(pmksa);*/
 }
 
 
@@ -285,20 +266,21 @@ void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
  */
 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
 {
-	struct rsn_pmksa_cache_entry *entry, *prev;
-
-	if (pmksa == NULL)
-		return;
-
-	entry = pmksa->pmksa;
-	pmksa->pmksa = NULL;
-	while (entry) {
-		prev = entry;
-		entry = entry->next;
-		os_free(prev);
-	}
-	//pmksa_cache_set_expiration(pmksa);
-	os_free(pmksa);
+    struct rsn_pmksa_cache_entry *entry, *prev;
+
+    if (pmksa == NULL)
+        return;
+
+    entry = pmksa->pmksa;
+    pmksa->pmksa = NULL;
+    while (entry) {
+        prev = entry;
+        entry = entry->next;
+        os_free(prev);
+    }
+    pmksa_cache_set_expiration(pmksa);
+    os_free(pmksa);
+    esp_timer_stop(pmksa->cache_timeout_timer);
 }
 
 
@@ -311,41 +293,41 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
  * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
  */
 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
-					       const u8 *aa, const u8 *pmkid,
-					       const void *network_ctx)
+        const u8 *aa, const u8 *pmkid,
+        const void *network_ctx)
 {
-	struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
-	while (entry) {
-		if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
-		    (pmkid == NULL ||
-		     os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
-		    (network_ctx == NULL || network_ctx == entry->network_ctx))
-			return entry;
-		entry = entry->next;
-	}
-	return NULL;
+    struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
+    while (entry) {
+        if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
+                (pmkid == NULL ||
+                 os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
+                (network_ctx == NULL || network_ctx == entry->network_ctx))
+            return entry;
+        entry = entry->next;
+    }
+    return NULL;
 }
 
 
 static struct rsn_pmksa_cache_entry *
 pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
-			const struct rsn_pmksa_cache_entry *old_entry,
-			const u8 *aa)
+        const struct rsn_pmksa_cache_entry *old_entry,
+        const u8 *aa)
 {
-	struct rsn_pmksa_cache_entry *new_entry;
+    struct rsn_pmksa_cache_entry *new_entry;
 
-	new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
-				    NULL, 0,
-				    aa, pmksa->sm->own_addr,
-				    old_entry->network_ctx, old_entry->akmp);
-	if (new_entry == NULL)
-		return NULL;
+    new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
+            NULL, 0,
+            aa, pmksa->sm->own_addr,
+            old_entry->network_ctx, old_entry->akmp);
+    if (new_entry == NULL)
+        return NULL;
 
-	/* TODO: reorder entries based on expiration time? */
-	new_entry->expiration = old_entry->expiration;
-	new_entry->opportunistic = 1;
+    /* TODO: reorder entries based on expiration time? */
+    new_entry->expiration = old_entry->expiration;
+    new_entry->opportunistic = 1;
 
-	return new_entry;
+    return new_entry;
 }
 
 
@@ -362,26 +344,26 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
  */
 struct rsn_pmksa_cache_entry *
 pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-			      const u8 *aa)
+        const u8 *aa)
 {
-	struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
-
-	wpa_printf(MSG_DEBUG, "RSN: Consider " MACSTR " for OKC", MAC2STR(aa));
-	if (network_ctx == NULL)
-		return NULL;
-	while (entry) {
-		if (entry->network_ctx == network_ctx) {
-			entry = pmksa_cache_clone_entry(pmksa, entry, aa);
-			if (entry) {
-				wpa_printf(MSG_DEBUG, "RSN: added "
-					   "opportunistic PMKSA cache entry "
-					   "for " MACSTR, MAC2STR(aa));
-			}
-			return entry;
-		}
-		entry = entry->next;
-	}
-	return NULL;
+    struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
+
+    wpa_printf(MSG_DEBUG, "RSN: Consider " MACSTR " for OKC", MAC2STR(aa));
+    if (network_ctx == NULL)
+        return NULL;
+    while (entry) {
+        if (entry->network_ctx == network_ctx) {
+            entry = pmksa_cache_clone_entry(pmksa, entry, aa);
+            if (entry) {
+                wpa_printf(MSG_DEBUG, "RSN: added "
+                        "opportunistic PMKSA cache entry "
+                        "for " MACSTR, MAC2STR(aa));
+            }
+            return entry;
+        }
+        entry = entry->next;
+    }
+    return NULL;
 }
 
 
@@ -392,9 +374,9 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
  */
 struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm)
 {
-	if (sm == NULL)
-		return NULL;
-	return sm->cur_pmksa;
+    if (sm == NULL)
+        return NULL;
+    return sm->cur_pmksa;
 }
 
 
@@ -404,9 +386,9 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm)
  */
 void pmksa_cache_clear_current(struct wpa_sm *sm)
 {
-	if (sm == NULL)
-		return;
-	sm->cur_pmksa = NULL;
+    if (sm == NULL)
+        return;
+    sm->cur_pmksa = NULL;
 }
 
 
@@ -420,37 +402,37 @@ void pmksa_cache_clear_current(struct wpa_sm *sm)
  * Returns: 0 if PMKSA was found or -1 if no matching entry was found
  */
 int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
-			    const u8 *bssid, void *network_ctx,
-			    int try_opportunistic)
+        const u8 *bssid, void *network_ctx,
+        int try_opportunistic)
 {
-	struct rsn_pmksa_cache *pmksa = sm->pmksa;
-	wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
-		   "try_opportunistic=%d", network_ctx, try_opportunistic);
-	if (pmkid)
-		wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
-			    pmkid, PMKID_LEN);
-	if (bssid)
-		wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR,
-			   MAC2STR(bssid));
-
-	sm->cur_pmksa = NULL;
-	if (pmkid)
-		sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
-						network_ctx);
-	if (sm->cur_pmksa == NULL && bssid)
-		sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
-						network_ctx);
-	if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
-		sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
-							      network_ctx,
-							      bssid);
-	if (sm->cur_pmksa) {
-		wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID",
-			    sm->cur_pmksa->pmkid, PMKID_LEN);
-		return 0;
-	}
-	wpa_printf(MSG_DEBUG, "RSN: No PMKSA cache entry found");
-	return -1;
+    struct rsn_pmksa_cache *pmksa = sm->pmksa;
+    wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
+            "try_opportunistic=%d", network_ctx, try_opportunistic);
+    if (pmkid)
+        wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
+                pmkid, PMKID_LEN);
+    if (bssid)
+        wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR,
+                MAC2STR(bssid));
+
+    sm->cur_pmksa = NULL;
+    if (pmkid)
+        sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
+                network_ctx);
+    if (sm->cur_pmksa == NULL && bssid)
+        sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
+                network_ctx);
+    if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
+        sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
+                network_ctx,
+                bssid);
+    if (sm->cur_pmksa) {
+        wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID",
+                sm->cur_pmksa->pmkid, PMKID_LEN);
+        return 0;
+    }
+    wpa_printf(MSG_DEBUG, "RSN: No PMKSA cache entry found");
+    return -1;
 }
 
 
@@ -466,38 +448,36 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
  */
 int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
 {
-	int i, ret;
-	char *pos = buf;
-	struct rsn_pmksa_cache_entry *entry;
-	//struct os_reltime now;
-
-	//os_get_reltime(&now);
-	ret = os_snprintf(pos, buf + len - pos,
-			  "Index / AA / PMKID / expiration (in seconds) / "
-			  "opportunistic\n");
-	if (os_snprintf_error(buf + len - pos, ret))
-		return pos - buf;
-	pos += ret;
-	i = 0;
-	entry = pmksa->pmksa;
-	while (entry) {
-		i++;
-		ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
-				  i, MAC2STR(entry->aa));
-		if (os_snprintf_error(buf + len - pos, ret))
-			return pos - buf;
-		pos += ret;
-		pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
-					PMKID_LEN);
-		ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
-				  (int) (entry->expiration),// - now.sec),
-				  entry->opportunistic);
-		if (os_snprintf_error(buf + len - pos, ret))
-			return pos - buf;
-		pos += ret;
-		entry = entry->next;
-	}
-	return pos - buf;
+    int i, ret;
+    char *pos = buf;
+    struct rsn_pmksa_cache_entry *entry;
+    int64_t now_sec = esp_timer_get_time() / 1e6;
+    ret = os_snprintf(pos, buf + len - pos,
+            "Index / AA / PMKID / expiration (in seconds) / "
+            "opportunistic\n");
+    if (os_snprintf_error(buf + len - pos, ret))
+        return pos - buf;
+    pos += ret;
+    i = 0;
+    entry = pmksa->pmksa;
+    while (entry) {
+        i++;
+        ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
+                i, MAC2STR(entry->aa));
+        if (os_snprintf_error(buf + len - pos, ret))
+            return pos - buf;
+        pos += ret;
+        pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
+                PMKID_LEN);
+        ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
+                (int) (entry->expiration - now_sec),
+                entry->opportunistic);
+        if (os_snprintf_error(buf + len - pos, ret))
+            return pos - buf;
+        pos += ret;
+        entry = entry->next;
+    }
+    return pos - buf;
 }
 
 
@@ -510,19 +490,29 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
  */
 struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
-				 void *ctx, enum pmksa_free_reason reason),
-		 void *ctx, struct wpa_sm *sm)
+            void *ctx, enum pmksa_free_reason reason),
+        void *ctx, struct wpa_sm *sm)
 {
-	struct rsn_pmksa_cache *pmksa;
-
-	pmksa = os_zalloc(sizeof(*pmksa));
-	if (pmksa) {
-		pmksa->free_cb = free_cb;
-		pmksa->ctx = ctx;
-		pmksa->sm = sm;
-	}
-
-	return pmksa;
+    struct rsn_pmksa_cache *pmksa;
+
+    pmksa = os_zalloc(sizeof(*pmksa));
+    if (pmksa) {
+        pmksa->free_cb = free_cb;
+        pmksa->ctx = ctx;
+        pmksa->sm = sm;
+        pmksa->pmksa_count = 0;
+        pmksa->pmksa = NULL;
+
+        esp_timer_create_args_t pmksa_cache_timeout_timer_create = {
+            .callback = &pmksa_cache_expire,
+            .arg = pmksa,
+            .dispatch_method = ESP_TIMER_TASK,
+            .name = "pmksa_timeout_timer"
+        };
+        esp_timer_create(&pmksa_cache_timeout_timer_create, &(pmksa->cache_timeout_timer));
+    }
+
+    return pmksa;
 }
 
 #endif /* IEEE8021X_EAPOL */

+ 55 - 55
components/wpa_supplicant/src/rsn_supp/pmksa_cache.h

@@ -13,102 +13,102 @@
  * struct rsn_pmksa_cache_entry - PMKSA cache entry
  */
 struct rsn_pmksa_cache_entry {
-	struct rsn_pmksa_cache_entry *next;
-	u8 pmkid[PMKID_LEN];
-	u8 pmk[PMK_LEN];
-	size_t pmk_len;
-	os_time_t expiration;
-	int akmp; /* WPA_KEY_MGMT_* */
-	u8 aa[ETH_ALEN];
-
-	os_time_t reauth_time;
-
-	/**
-	 * network_ctx - Network configuration context
-	 *
-	 * This field is only used to match PMKSA cache entries to a specific
-	 * network configuration (e.g., a specific SSID and security policy).
-	 * This can be a pointer to the configuration entry, but PMKSA caching
-	 * code does not dereference the value and this could be any kind of
-	 * identifier.
-	 */
-	void *network_ctx;
-	int opportunistic;
+    struct rsn_pmksa_cache_entry *next;
+    u8 pmkid[PMKID_LEN];
+    u8 pmk[PMK_LEN];
+    size_t pmk_len;
+    os_time_t expiration;
+    int akmp; /* WPA_KEY_MGMT_* */
+    u8 aa[ETH_ALEN];
+
+    os_time_t reauth_time;
+
+    /**
+     * network_ctx - Network configuration context
+     *
+     * This field is only used to match PMKSA cache entries to a specific
+     * network configuration (e.g., a specific SSID and security policy).
+     * This can be a pointer to the configuration entry, but PMKSA caching
+     * code does not dereference the value and this could be any kind of
+     * identifier.
+     */
+    void *network_ctx;
+    int opportunistic;
 };
 
 struct rsn_pmksa_cache;
 
 enum pmksa_free_reason {
-	PMKSA_FREE,
-	PMKSA_REPLACE,
-	PMKSA_EXPIRE,
+    PMKSA_FREE,
+    PMKSA_REPLACE,
+    PMKSA_EXPIRE,
 };
 
 #ifdef IEEE8021X_EAPOL
 
 struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
-				 void *ctx, enum pmksa_free_reason reason),
-		 void *ctx, struct wpa_sm *sm);
+            void *ctx, enum pmksa_free_reason reason),
+        void *ctx, struct wpa_sm *sm);
 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa);
 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
-					       const u8 *aa, const u8 *pmkid,
-					       const void *network_ctx);
+        const u8 *aa, const u8 *pmkid,
+        const void *network_ctx);
 int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
 struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-		const u8 *kck, size_t kck_len,
-		const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
+        const u8 *kck, size_t kck_len,
+        const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
 struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
 void pmksa_cache_clear_current(struct wpa_sm *sm);
 int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
-			    const u8 *bssid, void *network_ctx,
-			    int try_opportunistic);
+        const u8 *bssid, void *network_ctx,
+        int try_opportunistic);
 struct rsn_pmksa_cache_entry *
 pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
-			      void *network_ctx, const u8 *aa);
+        void *network_ctx, const u8 *aa);
 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
-		       const u8 *pmk, size_t pmk_len);
+        const u8 *pmk, size_t pmk_len);
 
 #else /* IEEE8021X_EAPOL */
 
-static inline struct rsn_pmksa_cache *
+    static inline struct rsn_pmksa_cache *
 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
-				 void *ctx, enum pmksa_free_reason reason),
-		 void *ctx, struct wpa_sm *sm)
+            void *ctx, enum pmksa_free_reason reason),
+        void *ctx, struct wpa_sm *sm)
 {
-	return (void *) -1;
+    return (void *) -1;
 }
 
 static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
 {
 }
 
-static inline struct rsn_pmksa_cache_entry *
+    static inline struct rsn_pmksa_cache_entry *
 pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid,
-		const void *network_ctx)
+        const void *network_ctx)
 {
-	return NULL;
+    return NULL;
 }
 
-static inline struct rsn_pmksa_cache_entry *
+    static inline struct rsn_pmksa_cache_entry *
 pmksa_cache_get_current(struct wpa_sm *sm)
 {
-	return NULL;
+    return NULL;
 }
 
 static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf,
-				   size_t len)
+        size_t len)
 {
-	return -1;
+    return -1;
 }
 
-static inline struct rsn_pmksa_cache_entry *
+    static inline struct rsn_pmksa_cache_entry *
 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
-		const u8 *kck, size_t kck_len,
-		const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
+        const u8 *kck, size_t kck_len,
+        const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
 {
-	return NULL;
+    return NULL;
 }
 
 static inline void pmksa_cache_clear_current(struct wpa_sm *sm)
@@ -116,16 +116,16 @@ static inline void pmksa_cache_clear_current(struct wpa_sm *sm)
 }
 
 static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
-					  const u8 *bssid,
-					  void *network_ctx,
-					  int try_opportunistic)
+        const u8 *bssid,
+        void *network_ctx,
+        int try_opportunistic)
 {
-	return -1;
+    return -1;
 }
 
 static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa,
-				     void *network_ctx,
-				     const u8 *pmk, size_t pmk_len)
+        void *network_ctx,
+        const u8 *pmk, size_t pmk_len)
 {
 }
 

+ 2 - 0
components/wpa_supplicant/src/rsn_supp/wpa.c

@@ -528,6 +528,8 @@ void   wpa_supplicant_process_1_of_4(struct wpa_sm *sm,
     if (res)
         goto failed;
 
+    pmksa_cache_set_current(sm, NULL, sm->bssid, 0, 0);
+
     if (sm->renew_snonce) {
         if (os_get_random(sm->snonce, WPA_NONCE_LEN)) {
          #ifdef DEBUG_PRINT            

+ 3 - 3
components/wpa_supplicant/src/utils/common.c

@@ -286,7 +286,7 @@ char * wpa_config_parse_string(const char *value, size_t *len)
 }
 
 
-int is_hex(const u8 *data, size_t len)
+int wpa_is_hex(const u8 *data, size_t len)
 {
 	size_t i;
 
@@ -298,7 +298,7 @@ int is_hex(const u8 *data, size_t len)
 }
 
 
-size_t merge_byte_arrays(u8 *res, size_t res_len,
+size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
 			 const u8 *src1, size_t src1_len,
 			 const u8 *src2, size_t src2_len)
 {
@@ -344,7 +344,7 @@ char * dup_binstr(const void *src, size_t len)
 
 	return res;
 }
-void bin_clear_free(void *bin, size_t len)
+void wpa_bin_clear_free(void *bin, size_t len)
 {
 	if (bin) {
 		os_memset(bin, 0, len);

+ 4 - 27
components/wpa_supplicant/include/utils/common.h → components/wpa_supplicant/src/utils/common.h

@@ -396,8 +396,8 @@ size_t printf_decode(u8 *buf, size_t maxlen, const char *str);
 const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len);
 
 char * wpa_config_parse_string(const char *value, size_t *len);
-int is_hex(const u8 *data, size_t len);
-size_t merge_byte_arrays(u8 *res, size_t res_len,
+int wpa_is_hex(const u8 *data, size_t len);
+size_t wpa_merge_byte_arrays(u8 *res, size_t res_len,
 			 const u8 *src1, size_t src1_len,
 			 const u8 *src2, size_t src2_len);
 char * dup_binstr(const void *src, size_t len);
@@ -420,7 +420,7 @@ static inline int is_multicast_ether_addr(const u8 *a)
 #define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff"
 
 
-#include "wpa_debug.h"
+#include "utils/wpa_debug.h"
 
 
 struct wpa_freq_range_list {
@@ -431,32 +431,9 @@ struct wpa_freq_range_list {
 	unsigned int num;
 };
 
-int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value);
-int freq_range_list_includes(const struct wpa_freq_range_list *list,
-			     unsigned int freq);
-char * freq_range_list_str(const struct wpa_freq_range_list *list);
-
-int int_array_len(const int *a);
-void int_array_concat(int **res, const int *a);
-void int_array_sort_unique(int *a);
-void int_array_add_unique(int **res, int a);
-
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
-void str_clear_free(char *str);
-void bin_clear_free(void *bin, size_t len);
-
-int random_mac_addr(u8 *addr);
-int random_mac_addr_keep_oui(u8 *addr);
-
-const char * cstr_token(const char *str, const char *delim, const char **last);
-char * str_token(char *str, const char *delim, char **context);
-size_t utf8_escape(const char *inp, size_t in_size,
-		   char *outp, size_t out_size);
-size_t utf8_unescape(const char *inp, size_t in_size,
-		     char *outp, size_t out_size);
-int is_ctrl_char(char c);
-
+void wpa_bin_clear_free(void *bin, size_t len);
 
 /*
  * gcc 4.4 ends up generating strict-aliasing warnings about some very common