18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WPA Supplicant - RSN PMKSA cache 340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt * Copyright (c) 2004-2009, 2011-2015, Jouni Malinen <j@w1.fi> 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h" 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eloop.h" 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "eapol_supp/eapol_supp_sm.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wpa_i.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "pmksa_cache.h" 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 181d6bf427f4769edb60865a3999d01eeb8f8fcb19Dmitry Shmidt#if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA) 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic const int pmksa_cache_max_entries = 32; 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache { 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */ 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int pmksa_count; /* number of entries in PMKSA cache */ 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm; /* TODO: get rid of this reference(?) */ 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx, 28d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt enum pmksa_free_reason reason); 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx; 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 389ead16e203b81d44a2d84eadc2901ceeb7daf805Dmitry Shmidt bin_clear_free(entry, sizeof(*entry)); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry, 44d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt enum pmksa_free_reason reason) 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 46293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt wpa_sm_remove_pmkid(pmksa->sm, entry->network_ctx, entry->aa, 47d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->pmkid, 48d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->fils_cache_id_set ? entry->fils_cache_id : 49d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt NULL); 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa_count--; 51d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa->free_cb(entry, pmksa->ctx, reason); 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _pmksa_cache_free_entry(entry); 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa = eloop_ctx; 59fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa = entry->next; 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, MAC2STR(entry->aa)); 67d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_free_entry(pmksa, entry, PMKSA_EXPIRE); 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_set_expiration(pmksa); 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx) 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa = eloop_ctx; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->sm->cur_pmksa = NULL; 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eapol_sm_request_reauth(pmksa->sm->eapol); 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int sec; 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 86fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa->pmksa == NULL) 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 92fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = pmksa->pmksa->expiration - now.sec; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sec < 0) 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = 0; 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa : 99c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL); 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry) { 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = pmksa->pmksa->reauth_time - now.sec; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sec < 0) 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sec = 0; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa, 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL); 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_add - Add a PMKSA cache entry 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk: The new pairwise master key 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmk_len: PMK length in bytes, usually PMK_LEN (32) 11557c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt * @pmkid: Calculated PMKID 116fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @kck: Key confirmation key or %NULL if not yet derived 117fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt * @kck_len: KCK length in bytes 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @spa: Supplicant address 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @network_ctx: Network configuration context for this PMK 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @akmp: WPA_KEY_MGMT_* used in key derivation 122d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * @cache_id: Pointer to FILS Cache Identifier or %NULL if not advertised 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the added PMKSA cache entry or %NULL on error 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function create a PMKSA entry for a new PMK and adds it to the PMKSA 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * cache. If an old entry is already in the cache for the same Authenticator, 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * this entry will be replaced with the new entry. PMKID will be calculated 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * based on the PMK and the driver interface is notified of the new PMKID. 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, 13257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt const u8 *pmkid, const u8 *kck, size_t kck_len, 133d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt const u8 *aa, const u8 *spa, void *network_ctx, int akmp, 134d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt const u8 *cache_id) 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 136293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 137fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 139d80a401aed31d06f261efd19223cf55d1a2a8228Dmitry Shmidt if (pmk_len > PMK_LEN_MAX) 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 142fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (wpa_key_mgmt_suite_b(akmp) && !kck) 143fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt return NULL; 144fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = os_zalloc(sizeof(*entry)); 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry == NULL) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->pmk, pmk, pmk_len); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->pmk_len = pmk_len; 15057c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt if (pmkid) 15157c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt os_memcpy(entry->pmkid, pmkid, PMKID_LEN); 15257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 15340b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); 15440b07208ef4402da20a7f666835a62f6ec098e16Dmitry Shmidt else if (wpa_key_mgmt_suite_b(akmp)) 155fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); 156fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt else 157d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp); 158fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime * 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->akmp = akmp; 163d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (cache_id) { 164d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->fils_cache_id_set = 1; 165d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt os_memcpy(entry->fils_cache_id, cache_id, FILS_CACHE_ID_LEN); 166d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(entry->aa, aa, ETH_ALEN); 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->network_ctx = network_ctx; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 170293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt return pmksa_cache_add_entry(pmksa, entry); 171293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt} 172293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 173293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 174293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstruct rsn_pmksa_cache_entry * 175293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtpmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, 176293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt struct rsn_pmksa_cache_entry *entry) 177293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt{ 178293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt struct rsn_pmksa_cache_entry *pos, *prev; 179293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Replace an old entry for the same Authenticator (if found) with the 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * new entry */ 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pmksa->pmksa; 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 185293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (os_memcmp(entry->aa, pos->aa, ETH_ALEN) == 0) { 186293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt if (pos->pmk_len == entry->pmk_len && 187293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt os_memcmp_const(pos->pmk, entry->pmk, 188293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt entry->pmk_len) == 0 && 189c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt os_memcmp_const(pos->pmkid, entry->pmkid, 190c28170251eb54dbf64a9074a07fee377587425b2Dmitry Shmidt PMKID_LEN) == 0) { 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "WPA: reusing previous " 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "PMKSA entry"); 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(entry); 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa = pos->next; 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = pos->next; 2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* 2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * If OKC is used, there may be other PMKSA cache 2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * entries based on the same PMK. These needs to be 2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * flushed so that a new entry can be created based on 205f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt * the new PMK. Only clear other entries if they have a 206f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt * matching PMK and this PMK has been used successfully 207f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt * with the current AP, i.e., if opportunistic flag has 208f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt * been cleared in wpa_supplicant_key_neg_complete(). 2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 210f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " 211f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt "the current AP and any PMKSA cache entry " 212f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt "that was based on the old PMK"); 213f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if (!pos->opportunistic) 214293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt pmksa_cache_flush(pmksa, entry->network_ctx, 215293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt pos->pmk, pos->pmk_len); 216f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pos; 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pos->next; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Remove the oldest entry to make room for the new entry */ 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pmksa->pmksa; 22661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 22761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos == pmksa->sm->cur_pmksa) { 22861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt /* 22961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Never remove the current PMKSA cache entry, since 23061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * it's in use, and removing it triggers a needless 23161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * deauthentication. 23261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt */ 23361d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pos = pos->next; 23461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pmksa->pmksa->next = pos ? pos->next : NULL; 23561d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } else 23661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt pmksa->pmksa = pos->next; 23761d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt 23861d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt if (pos) { 23961d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: removed the oldest idle " 24061d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "PMKSA cache entry (for " MACSTR ") to " 24161d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt "make room for new one", 24261d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt MAC2STR(pos->aa)); 243d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_free_entry(pmksa, pos, PMKSA_FREE); 24461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt } 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Add the new entry; order by expiration time */ 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pmksa->pmksa; 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = NULL; 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (pos) { 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pos->expiration > entry->expiration) 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = pos; 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = pos->next; 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (prev == NULL) { 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next = pmksa->pmksa; 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa = entry; 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_set_expiration(pmksa); 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->next = prev->next; 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev->next = entry; 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa_count++; 265c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR 266293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt " network_ctx=%p", MAC2STR(entry->aa), entry->network_ctx); 267d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid, 268d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->fils_cache_id_set ? entry->fils_cache_id : NULL, 269d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->pmk, entry->pmk_len); 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return entry; 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 2761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * pmksa_cache_flush - Flush PMKSA cache entries for a specific network 2771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 2781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @network_ctx: Network configuration context or %NULL to flush all entries 279f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt * @pmk: PMK to match for or %NYLL to match all PMKs 280f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt * @pmk_len: PMK length 2811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 282f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidtvoid pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, 283f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt const u8 *pmk, size_t pmk_len) 2841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp; 2861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt int removed = 0; 2871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt entry = pmksa->pmksa; 2891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (entry) { 290f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt if ((entry->network_ctx == network_ctx || 291f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt network_ctx == NULL) && 292f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt (pmk == NULL || 293f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt (pmk_len == entry->pmk_len && 294f7e0a9905988e62e4f70fed8b795722abeab719bDmitry Shmidt os_memcmp(pmk, entry->pmk, pmk_len) == 0))) { 2951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry " 2961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "for " MACSTR, MAC2STR(entry->aa)); 2971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (prev) 2981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prev->next = entry->next; 2991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt else 3001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pmksa->pmksa = entry->next; 3011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt tmp = entry; 3021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt entry = entry->next; 303d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt pmksa_cache_free_entry(pmksa, tmp, PMKSA_FREE); 3041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt removed++; 3051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } else { 3061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt prev = entry; 3071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt entry = entry->next; 3081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 3101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (removed) 3111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt pmksa_cache_set_expiration(pmksa); 3121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 3131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_deinit - Free all entries in PMKSA cache 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry, *prev; 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa == NULL) 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = pmksa->pmksa; 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->pmksa = NULL; 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt prev = entry; 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(prev); 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa_cache_set_expiration(pmksa); 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(pmksa); 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_get - Fetch a PMKSA cache entry 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address or %NULL to match any 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmkid: PMKID or %NULL to match any 343c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * @network_ctx: Network context or %NULL to match any 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to PMKSA cache entry or %NULL if no match was found 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, 347c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const u8 *aa, const u8 *pmkid, 348c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt const void *network_ctx) 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) && 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (pmkid == NULL || 354c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) && 355c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt (network_ctx == NULL || network_ctx == entry->network_ctx)) 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return entry; 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic struct rsn_pmksa_cache_entry * 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct rsn_pmksa_cache_entry *old_entry, 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *aa) 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *new_entry; 369d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt os_time_t old_expiration = old_entry->expiration; 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, 37257c2d39d85825f38c5fdac9b73bb0088406ffc85Dmitry Shmidt NULL, NULL, 0, 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt aa, pmksa->sm->own_addr, 374d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt old_entry->network_ctx, old_entry->akmp, 375d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt old_entry->fils_cache_id_set ? 376d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt old_entry->fils_cache_id : NULL); 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (new_entry == NULL) 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: reorder entries based on expiration time? */ 381d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt new_entry->expiration = old_expiration; 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt new_entry->opportunistic = 1; 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return new_entry; 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_get_opportunistic - Try to get an opportunistic PMKSA entry 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @network_ctx: Network configuration context 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @aa: Authenticator address for the new AP 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to a new PMKSA cache entry or %NULL if not available 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Try to create a new PMKSA cache entry opportunistically by guessing that the 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * new AP is sharing the same PMK as another AP that has the same SSID and has 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * already an entry in PMKSA cache. 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *aa) 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Consider " MACSTR " for OKC", MAC2STR(aa)); 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (network_ctx == NULL) 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry->network_ctx == network_ctx) { 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = pmksa_cache_clone_entry(pmksa, entry, aa); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (entry) { 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: added " 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "opportunistic PMKSA cache entry " 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for " MACSTR, MAC2STR(aa)); 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return entry; 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 424d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtstatic struct rsn_pmksa_cache_entry * 425d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidtpmksa_cache_get_fils_cache_id(struct rsn_pmksa_cache *pmksa, 426d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt const void *network_ctx, const u8 *cache_id) 427d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt{ 428d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 429d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 430d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt for (entry = pmksa->pmksa; entry; entry = entry->next) { 431d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (network_ctx == entry->network_ctx && 432d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->fils_cache_id_set && 433d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt os_memcmp(cache_id, entry->fils_cache_id, 434d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt FILS_CACHE_ID_LEN) == 0) 435d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return entry; 436d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 437d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 438d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return NULL; 439d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt} 440d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 441d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_get_current - Get the current used PMKSA entry 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to the current PMKSA cache entry or %NULL if not available 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm) 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return NULL; 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->cur_pmksa; 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_clear_current - Clear the current PMKSA entry selection 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid pmksa_cache_clear_current(struct wpa_sm *sm) 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = NULL; 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_set_current - Set the current PMKSA entry selection 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmkid: PMKID for selecting PMKSA or %NULL if not used 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @bssid: BSSID for PMKSA or %NULL if not used 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @network_ctx: Network configuration context 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @try_opportunistic: Whether to allow opportunistic PMKSA caching 474d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt * @fils_cache_id: Pointer to FILS Cache Identifier or %NULL if not used 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 if PMKSA was found or -1 if no matching entry was found 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *bssid, void *network_ctx, 479d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int try_opportunistic, const u8 *fils_cache_id) 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa = sm->pmksa; 482c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p " 483c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt "try_opportunistic=%d", network_ctx, try_opportunistic); 484c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (pmkid) 485c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID", 486c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt pmkid, PMKID_LEN); 487c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt if (bssid) 488c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR, 489c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt MAC2STR(bssid)); 490d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (fils_cache_id) 491d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt wpa_printf(MSG_DEBUG, 492d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt "RSN: Search for FILS Cache Identifier %02x%02x", 493d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt fils_cache_id[0], fils_cache_id[1]); 494c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = NULL; 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmkid) 497c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid, 498c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt network_ctx); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa == NULL && bssid) 500c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL, 501c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt network_ctx); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa == NULL && try_opportunistic && bssid) 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa, 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt network_ctx, 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt bssid); 506d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (sm->cur_pmksa == NULL && fils_cache_id) 507d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa, 508d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt network_ctx, 509d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt fils_cache_id); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->cur_pmksa) { 511c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID", 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->cur_pmksa->pmkid, PMKID_LEN); 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 515c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt wpa_printf(MSG_DEBUG, "RSN: No PMKSA cache entry found"); 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_list - Dump text list of entries in PMKSA cache 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @buf: Buffer for the list 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @len: Length of the buffer 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: number of bytes written to buffer 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is used to generate a text format representation of the 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * current PMKSA cache contents for the ctrl_iface PMKSA command. 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, ret; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt char *pos = buf; 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache_entry *entry; 535fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt struct os_reltime now; 536d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt int cache_id_used = 0; 537d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt 538d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt for (entry = pmksa->pmksa; entry; entry = entry->next) { 539d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (entry->fils_cache_id_set) { 540d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt cache_id_used = 1; 541d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt break; 542d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 543d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 545fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt os_get_reltime(&now); 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, buf + len - pos, 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Index / AA / PMKID / expiration (in seconds) / " 548d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt "opportunistic%s\n", 549d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt cache_id_used ? " / FILS Cache Identifier" : ""); 550fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i = 0; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = pmksa->pmksa; 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (entry) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i++; 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt i, MAC2STR(entry->aa)); 559fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt PMKID_LEN); 564d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ret = os_snprintf(pos, buf + len - pos, " %d %d", 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (int) (entry->expiration - now.sec), 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry->opportunistic); 567fb45fd5cfed8bdccd0859c7fc05449fc187e2d06Dmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ret; 570d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (entry->fils_cache_id_set) { 571d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ret = os_snprintf(pos, buf + len - pos, " %02x%02x", 572d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->fils_cache_id[0], 573d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt entry->fils_cache_id[1]); 574d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 575d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return pos - buf; 576d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt pos += ret; 577d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt } 578d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt ret = os_snprintf(pos, buf + len - pos, "\n"); 579d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt if (os_snprintf_error(buf + len - pos, ret)) 580d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt return pos - buf; 581d2986c2e737a8441ff5a791b6b56c1c8322ef3c9Dmitry Shmidt pos += ret; 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt entry = entry->next; 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos - buf; 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 588293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidtstruct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa) 589293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt{ 590293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt return pmksa->pmksa; 591293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt} 592293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 593293335998d38c497293b1c41f7ad8342b507d458Dmitry Shmidt 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * pmksa_cache_init - Initialize PMKSA cache 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @free_cb: Callback function to be called when a PMKSA cache entry is freed 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ctx: Context pointer for free_cb function 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: Pointer to PMKSA cache data or %NULL on failure 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct rsn_pmksa_cache * 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtpmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, 603d5e4923d04122f81300fa68fb07d64ede28fd44dDmitry Shmidt void *ctx, enum pmksa_free_reason reason), 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt void *ctx, struct wpa_sm *sm) 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_pmksa_cache *pmksa; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa = os_zalloc(sizeof(*pmksa)); 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (pmksa) { 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->free_cb = free_cb; 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->ctx = ctx; 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pmksa->sm = sm; 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pmksa; 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 61834af306c42b7ccf956508e7cd23f0ba90606e360Dmitry Shmidt#endif /* IEEE8021X_EAPOL */ 619