|
@@ -117,6 +117,7 @@ static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
|
|
|
* @spa: Supplicant address
|
|
|
* @network_ctx: Network configuration context for this PMK
|
|
|
* @akmp: WPA_KEY_MGMT_* used in key derivation
|
|
|
+ * @cache_id: Pointer to FILS Cache Identifier or %NULL if not advertised
|
|
|
* Returns: Pointer to the added PMKSA cache entry or %NULL on error
|
|
|
*
|
|
|
* This function create a PMKSA entry for a new PMK and adds it to the PMKSA
|
|
@@ -127,7 +128,8 @@ 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 *pmkid, const u8 *kck, size_t kck_len,
|
|
|
- const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
|
|
|
+ const u8 *aa, const u8 *spa, void *network_ctx, int akmp,
|
|
|
+ const u8 *cache_id)
|
|
|
{
|
|
|
struct rsn_pmksa_cache_entry *entry;
|
|
|
struct os_reltime now;
|
|
@@ -157,6 +159,10 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|
|
entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime *
|
|
|
pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100;
|
|
|
entry->akmp = akmp;
|
|
|
+ if (cache_id) {
|
|
|
+ entry->fils_cache_id_set = 1;
|
|
|
+ os_memcpy(entry->fils_cache_id, cache_id, FILS_CACHE_ID_LEN);
|
|
|
+ }
|
|
|
os_memcpy(entry->aa, aa, ETH_ALEN);
|
|
|
entry->network_ctx = network_ctx;
|
|
|
|
|
@@ -362,7 +368,9 @@ pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
|
|
|
new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
|
|
|
NULL, NULL, 0,
|
|
|
aa, pmksa->sm->own_addr,
|
|
|
- old_entry->network_ctx, old_entry->akmp);
|
|
|
+ old_entry->network_ctx, old_entry->akmp,
|
|
|
+ old_entry->fils_cache_id_set ?
|
|
|
+ old_entry->fils_cache_id : NULL);
|
|
|
if (new_entry == NULL)
|
|
|
return NULL;
|
|
|
|
|
@@ -410,6 +418,24 @@ pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
|
|
|
}
|
|
|
|
|
|
|
|
|
+static struct rsn_pmksa_cache_entry *
|
|
|
+pmksa_cache_get_fils_cache_id(struct rsn_pmksa_cache *pmksa,
|
|
|
+ const void *network_ctx, const u8 *cache_id)
|
|
|
+{
|
|
|
+ struct rsn_pmksa_cache_entry *entry;
|
|
|
+
|
|
|
+ for (entry = pmksa->pmksa; entry; entry = entry->next) {
|
|
|
+ if (network_ctx == entry->network_ctx &&
|
|
|
+ entry->fils_cache_id_set &&
|
|
|
+ os_memcmp(cache_id, entry->fils_cache_id,
|
|
|
+ FILS_CACHE_ID_LEN) == 0)
|
|
|
+ return entry;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/**
|
|
|
* pmksa_cache_get_current - Get the current used PMKSA entry
|
|
|
* @sm: Pointer to WPA state machine data from wpa_sm_init()
|
|
@@ -442,11 +468,12 @@ void pmksa_cache_clear_current(struct wpa_sm *sm)
|
|
|
* @bssid: BSSID for PMKSA or %NULL if not used
|
|
|
* @network_ctx: Network configuration context
|
|
|
* @try_opportunistic: Whether to allow opportunistic PMKSA caching
|
|
|
+ * @fils_cache_id: Pointer to FILS Cache Identifier or %NULL if not used
|
|
|
* 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)
|
|
|
+ int try_opportunistic, const u8 *fils_cache_id)
|
|
|
{
|
|
|
struct rsn_pmksa_cache *pmksa = sm->pmksa;
|
|
|
wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
|
|
@@ -457,6 +484,10 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
|
|
|
if (bssid)
|
|
|
wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR,
|
|
|
MAC2STR(bssid));
|
|
|
+ if (fils_cache_id)
|
|
|
+ wpa_printf(MSG_DEBUG,
|
|
|
+ "RSN: Search for FILS Cache Identifier %02x%02x",
|
|
|
+ fils_cache_id[0], fils_cache_id[1]);
|
|
|
|
|
|
sm->cur_pmksa = NULL;
|
|
|
if (pmkid)
|
|
@@ -469,6 +500,10 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
|
|
|
sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
|
|
|
network_ctx,
|
|
|
bssid);
|
|
|
+ if (sm->cur_pmksa == NULL && fils_cache_id)
|
|
|
+ sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa,
|
|
|
+ network_ctx,
|
|
|
+ fils_cache_id);
|
|
|
if (sm->cur_pmksa) {
|
|
|
wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID",
|
|
|
sm->cur_pmksa->pmkid, PMKID_LEN);
|
|
@@ -495,11 +530,20 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
|
|
|
char *pos = buf;
|
|
|
struct rsn_pmksa_cache_entry *entry;
|
|
|
struct os_reltime now;
|
|
|
+ int cache_id_used = 0;
|
|
|
+
|
|
|
+ for (entry = pmksa->pmksa; entry; entry = entry->next) {
|
|
|
+ if (entry->fils_cache_id_set) {
|
|
|
+ cache_id_used = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
os_get_reltime(&now);
|
|
|
ret = os_snprintf(pos, buf + len - pos,
|
|
|
"Index / AA / PMKID / expiration (in seconds) / "
|
|
|
- "opportunistic\n");
|
|
|
+ "opportunistic%s\n",
|
|
|
+ cache_id_used ? " / FILS Cache Identifier" : "");
|
|
|
if (os_snprintf_error(buf + len - pos, ret))
|
|
|
return pos - buf;
|
|
|
pos += ret;
|
|
@@ -514,12 +558,24 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
|
|
|
pos += ret;
|
|
|
pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
|
|
|
PMKID_LEN);
|
|
|
- ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
|
|
|
+ ret = os_snprintf(pos, buf + len - pos, " %d %d",
|
|
|
(int) (entry->expiration - now.sec),
|
|
|
entry->opportunistic);
|
|
|
if (os_snprintf_error(buf + len - pos, ret))
|
|
|
return pos - buf;
|
|
|
pos += ret;
|
|
|
+ if (entry->fils_cache_id_set) {
|
|
|
+ ret = os_snprintf(pos, buf + len - pos, " %02x%02x",
|
|
|
+ entry->fils_cache_id[0],
|
|
|
+ entry->fils_cache_id[1]);
|
|
|
+ if (os_snprintf_error(buf + len - pos, ret))
|
|
|
+ return pos - buf;
|
|
|
+ pos += ret;
|
|
|
+ }
|
|
|
+ ret = os_snprintf(pos, buf + len - pos, "\n");
|
|
|
+ if (os_snprintf_error(buf + len - pos, ret))
|
|
|
+ return pos - buf;
|
|
|
+ pos += ret;
|
|
|
entry = entry->next;
|
|
|
}
|
|
|
return pos - buf;
|