1 /* 2 * WPA Supplicant - RSN PMKSA cache 3 * Copyright (c) 2004-2009, 2011-2015, Jouni Malinen <j@w1.fi> 4 * 5 * This software may be distributed under the terms of the BSD license. 6 * See README for more details. 7 */ 8 9 #include "includes.h" 10 11 #include "common.h" 12 #include "eloop.h" 13 #include "eapol_supp/eapol_supp_sm.h" 14 #include "wpa.h" 15 #include "wpa_i.h" 16 #include "pmksa_cache.h" 17 18 #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA) 19 20 static const int pmksa_cache_max_entries = 32; 21 22 struct rsn_pmksa_cache { 23 struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */ 24 int pmksa_count; /* number of entries in PMKSA cache */ 25 struct wpa_sm *sm; /* TODO: get rid of this reference(?) */ 26 27 void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx, 28 enum pmksa_free_reason reason); 29 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry, 30 void *ctx); 31 void (*notify_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx); 32 void *ctx; 33 }; 34 35 36 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); 37 38 39 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) 40 { 41 bin_clear_free(entry, sizeof(*entry)); 42 } 43 44 45 static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, 46 struct rsn_pmksa_cache_entry *entry, 47 enum pmksa_free_reason reason) 48 { 49 if (pmksa->sm) 50 wpa_sm_remove_pmkid(pmksa->sm, entry->network_ctx, entry->aa, 51 entry->pmkid, 52 entry->fils_cache_id_set ? 53 entry->fils_cache_id : NULL); 54 pmksa->pmksa_count--; 55 if (pmksa->free_cb) 56 pmksa->free_cb(entry, pmksa->ctx, reason); 57 _pmksa_cache_free_entry(entry); 58 } 59 60 61 void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa, 62 struct rsn_pmksa_cache_entry *entry) 63 { 64 struct rsn_pmksa_cache_entry *e; 65 66 e = pmksa->pmksa; 67 while (e) { 68 if (e == entry) { 69 pmksa->pmksa = entry->next; 70 break; 71 } 72 if (e->next == entry) { 73 e->next = entry->next; 74 break; 75 } 76 } 77 78 if (!e) { 79 wpa_printf(MSG_DEBUG, 80 "RSN: Could not remove PMKSA cache entry %p since it is not in the list", 81 entry); 82 return; 83 } 84 85 pmksa_cache_free_entry(pmksa, entry, PMKSA_FREE); 86 } 87 88 89 static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) 90 { 91 struct rsn_pmksa_cache *pmksa = eloop_ctx; 92 struct os_reltime now; 93 struct rsn_pmksa_cache_entry *prev = NULL, *tmp; 94 struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; 95 96 os_get_reltime(&now); 97 while (entry && entry->expiration <= now.sec) { 98 if (wpa_key_mgmt_sae(entry->akmp) && pmksa->is_current_cb && 99 pmksa->is_current_cb(entry, pmksa->ctx)) { 100 /* Do not expire the currently used PMKSA entry for SAE 101 * since there is no convenient mechanism for 102 * reauthenticating during an association with SAE. The 103 * expired entry will be removed after this association 104 * has been lost. */ 105 wpa_printf(MSG_DEBUG, 106 "RSN: postpone PMKSA cache entry expiration for SAE with " 107 MACSTR, MAC2STR(entry->aa)); 108 prev = entry; 109 entry = entry->next; 110 continue; 111 } 112 113 wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " 114 MACSTR, MAC2STR(entry->aa)); 115 if (prev) 116 prev->next = entry->next; 117 else 118 pmksa->pmksa = entry->next; 119 tmp = entry; 120 entry = entry->next; 121 pmksa_cache_free_entry(pmksa, tmp, PMKSA_EXPIRE); 122 } 123 124 pmksa_cache_set_expiration(pmksa); 125 } 126 127 128 static void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx) 129 { 130 struct rsn_pmksa_cache *pmksa = eloop_ctx; 131 132 if (!pmksa->sm) 133 return; 134 135 if (pmksa->sm->driver_bss_selection) { 136 struct rsn_pmksa_cache_entry *entry; 137 138 entry = pmksa->sm->cur_pmksa ? 139 pmksa->sm->cur_pmksa : 140 pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 141 NULL, 0); 142 if (entry && wpa_key_mgmt_sae(entry->akmp)) { 143 wpa_printf(MSG_DEBUG, 144 "RSN: remove reauth threshold passed PMKSA from the driver for SAE"); 145 entry->sae_reauth_scheduled = true; 146 wpa_sm_remove_pmkid(pmksa->sm, entry->network_ctx, 147 entry->aa, entry->pmkid, NULL); 148 return; 149 } 150 } 151 152 pmksa->sm->cur_pmksa = NULL; 153 eapol_sm_request_reauth(pmksa->sm->eapol); 154 } 155 156 157 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) 158 { 159 int sec; 160 struct rsn_pmksa_cache_entry *entry; 161 struct os_reltime now; 162 163 eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); 164 eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL); 165 if (pmksa->pmksa == NULL) 166 return; 167 os_get_reltime(&now); 168 sec = pmksa->pmksa->expiration - now.sec; 169 if (sec < 0) { 170 sec = 0; 171 if (wpa_key_mgmt_sae(pmksa->pmksa->akmp) && 172 pmksa->is_current_cb && 173 pmksa->is_current_cb(pmksa->pmksa, pmksa->ctx)) { 174 /* Do not continue polling for the current PMKSA entry 175 * from SAE to expire every second. Use the expiration 176 * time to the following entry, if any, and wait at 177 * maximum 10 minutes to check again. 178 */ 179 entry = pmksa->pmksa->next; 180 if (entry) { 181 sec = entry->expiration - now.sec; 182 if (sec < 0) 183 sec = 0; 184 else if (sec > 600) 185 sec = 600; 186 } else { 187 sec = 600; 188 } 189 } 190 } 191 eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); 192 193 if (!pmksa->sm) 194 return; 195 196 entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa : 197 pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, NULL, 0); 198 if (entry && 199 (!wpa_key_mgmt_sae(entry->akmp) || 200 (pmksa->sm->driver_bss_selection && 201 !entry->sae_reauth_scheduled))) { 202 sec = pmksa->pmksa->reauth_time - now.sec; 203 if (sec < 0) 204 sec = 0; 205 eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa, 206 NULL); 207 } 208 } 209 210 211 /** 212 * pmksa_cache_add - Add a PMKSA cache entry 213 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 214 * @pmk: The new pairwise master key 215 * @pmk_len: PMK length in bytes, usually PMK_LEN (32) 216 * @pmkid: Calculated PMKID 217 * @kck: Key confirmation key or %NULL if not yet derived 218 * @kck_len: KCK length in bytes 219 * @aa: Authenticator address 220 * @spa: Supplicant address 221 * @network_ctx: Network configuration context for this PMK 222 * @akmp: WPA_KEY_MGMT_* used in key derivation 223 * @cache_id: Pointer to FILS Cache Identifier or %NULL if not advertised 224 * Returns: Pointer to the added PMKSA cache entry or %NULL on error 225 * 226 * This function create a PMKSA entry for a new PMK and adds it to the PMKSA 227 * cache. If an old entry is already in the cache for the same Authenticator, 228 * this entry will be replaced with the new entry. PMKID will be calculated 229 * based on the PMK and the driver interface is notified of the new PMKID. 230 */ 231 struct rsn_pmksa_cache_entry * 232 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, 233 const u8 *pmkid, const u8 *kck, size_t kck_len, 234 const u8 *aa, const u8 *spa, void *network_ctx, int akmp, 235 const u8 *cache_id) 236 { 237 struct rsn_pmksa_cache_entry *entry; 238 struct os_reltime now; 239 unsigned int pmk_lifetime = 43200; 240 unsigned int pmk_reauth_threshold = 70; 241 242 if (pmk_len > PMK_LEN_MAX) 243 return NULL; 244 245 if (kck_len > WPA_KCK_MAX_LEN) 246 return NULL; 247 248 if (wpa_key_mgmt_suite_b(akmp) && !kck) 249 return NULL; 250 251 entry = os_zalloc(sizeof(*entry)); 252 if (entry == NULL) 253 return NULL; 254 os_memcpy(entry->pmk, pmk, pmk_len); 255 entry->pmk_len = pmk_len; 256 if (kck_len > 0) 257 os_memcpy(entry->kck, kck, kck_len); 258 entry->kck_len = kck_len; 259 if (pmkid) 260 os_memcpy(entry->pmkid, pmkid, PMKID_LEN); 261 else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) 262 rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); 263 else if (wpa_key_mgmt_suite_b(akmp)) 264 rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); 265 else 266 rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp); 267 os_get_reltime(&now); 268 if (pmksa->sm) { 269 pmk_lifetime = pmksa->sm->dot11RSNAConfigPMKLifetime; 270 pmk_reauth_threshold = 271 pmksa->sm->dot11RSNAConfigPMKReauthThreshold; 272 } 273 entry->expiration = now.sec + pmk_lifetime; 274 entry->reauth_time = now.sec + 275 pmk_lifetime * pmk_reauth_threshold / 100; 276 entry->akmp = akmp; 277 if (cache_id) { 278 entry->fils_cache_id_set = 1; 279 os_memcpy(entry->fils_cache_id, cache_id, FILS_CACHE_ID_LEN); 280 } 281 os_memcpy(entry->aa, aa, ETH_ALEN); 282 os_memcpy(entry->spa, spa, ETH_ALEN); 283 entry->network_ctx = network_ctx; 284 285 return pmksa_cache_add_entry(pmksa, entry); 286 } 287 288 289 struct rsn_pmksa_cache_entry * 290 pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, 291 struct rsn_pmksa_cache_entry *entry) 292 { 293 struct rsn_pmksa_cache_entry *pos, *prev; 294 295 /* Replace an old entry for the same Authenticator (if found) with the 296 * new entry */ 297 pos = pmksa->pmksa; 298 prev = NULL; 299 while (pos) { 300 if (ether_addr_equal(entry->aa, pos->aa) && 301 ether_addr_equal(entry->spa, pos->spa)) { 302 if (pos->pmk_len == entry->pmk_len && 303 os_memcmp_const(pos->pmk, entry->pmk, 304 entry->pmk_len) == 0 && 305 os_memcmp_const(pos->pmkid, entry->pmkid, 306 PMKID_LEN) == 0) { 307 wpa_printf(MSG_DEBUG, "WPA: reusing previous " 308 "PMKSA entry"); 309 os_free(entry); 310 return pos; 311 } 312 if (prev == NULL) 313 pmksa->pmksa = pos->next; 314 else 315 prev->next = pos->next; 316 317 /* 318 * If OKC is used, there may be other PMKSA cache 319 * entries based on the same PMK. These needs to be 320 * flushed so that a new entry can be created based on 321 * the new PMK. Only clear other entries if they have a 322 * matching PMK and this PMK has been used successfully 323 * with the current AP, i.e., if opportunistic flag has 324 * been cleared in wpa_supplicant_key_neg_complete(). 325 */ 326 wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for " 327 "the current AP and any PMKSA cache entry " 328 "that was based on the old PMK"); 329 if (!pos->opportunistic) 330 pmksa_cache_flush(pmksa, entry->network_ctx, 331 pos->pmk, pos->pmk_len, 332 false); 333 pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE); 334 break; 335 } 336 prev = pos; 337 pos = pos->next; 338 } 339 340 if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { 341 /* Remove the oldest entry to make room for the new entry */ 342 pos = pmksa->pmksa; 343 344 if (pmksa->sm && pos == pmksa->sm->cur_pmksa) { 345 /* 346 * Never remove the current PMKSA cache entry, since 347 * it's in use, and removing it triggers a needless 348 * deauthentication. 349 */ 350 pos = pos->next; 351 pmksa->pmksa->next = pos ? pos->next : NULL; 352 } else 353 pmksa->pmksa = pos->next; 354 355 if (pos) { 356 wpa_printf(MSG_DEBUG, "RSN: removed the oldest idle " 357 "PMKSA cache entry (for " MACSTR ") to " 358 "make room for new one", 359 MAC2STR(pos->aa)); 360 pmksa_cache_free_entry(pmksa, pos, PMKSA_FREE); 361 } 362 } 363 364 /* Add the new entry; order by expiration time */ 365 pos = pmksa->pmksa; 366 prev = NULL; 367 while (pos) { 368 if (pos->expiration > entry->expiration) 369 break; 370 prev = pos; 371 pos = pos->next; 372 } 373 if (prev == NULL) { 374 entry->next = pmksa->pmksa; 375 pmksa->pmksa = entry; 376 pmksa_cache_set_expiration(pmksa); 377 } else { 378 entry->next = prev->next; 379 prev->next = entry; 380 } 381 pmksa->pmksa_count++; 382 wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR 383 " spa=" MACSTR " network_ctx=%p akmp=0x%x", 384 MAC2STR(entry->aa), MAC2STR(entry->spa), 385 entry->network_ctx, entry->akmp); 386 387 if (!pmksa->sm) 388 return entry; 389 390 if (pmksa->notify_cb) 391 pmksa->notify_cb(entry, pmksa->ctx); 392 393 wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, entry->pmkid, 394 entry->fils_cache_id_set ? entry->fils_cache_id : NULL, 395 entry->pmk, entry->pmk_len, 396 pmksa->sm->dot11RSNAConfigPMKLifetime, 397 pmksa->sm->dot11RSNAConfigPMKReauthThreshold, 398 entry->akmp); 399 400 return entry; 401 } 402 403 404 /** 405 * pmksa_cache_flush - Flush PMKSA cache entries for a specific network 406 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 407 * @network_ctx: Network configuration context or %NULL to flush all entries 408 * @pmk: PMK to match for or %NULL to match all PMKs 409 * @pmk_len: PMK length 410 * @external_only: Flush only PMKSA cache entries configured by external 411 * applications 412 */ 413 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, 414 const u8 *pmk, size_t pmk_len, bool external_only) 415 { 416 struct rsn_pmksa_cache_entry *entry, *prev = NULL, *tmp; 417 int removed = 0; 418 419 entry = pmksa->pmksa; 420 while (entry) { 421 if ((entry->network_ctx == network_ctx || 422 network_ctx == NULL) && 423 (pmk == NULL || 424 (pmk_len == entry->pmk_len && 425 os_memcmp(pmk, entry->pmk, pmk_len) == 0)) && 426 (!external_only || entry->external)) { 427 wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry " 428 "for " MACSTR, MAC2STR(entry->aa)); 429 if (prev) 430 prev->next = entry->next; 431 else 432 pmksa->pmksa = entry->next; 433 tmp = entry; 434 entry = entry->next; 435 pmksa_cache_free_entry(pmksa, tmp, PMKSA_FREE); 436 removed++; 437 } else { 438 prev = entry; 439 entry = entry->next; 440 } 441 } 442 if (removed) 443 pmksa_cache_set_expiration(pmksa); 444 } 445 446 447 /** 448 * pmksa_cache_deinit - Free all entries in PMKSA cache 449 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 450 */ 451 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) 452 { 453 struct rsn_pmksa_cache_entry *entry, *prev; 454 455 if (pmksa == NULL) 456 return; 457 458 entry = pmksa->pmksa; 459 pmksa->pmksa = NULL; 460 while (entry) { 461 prev = entry; 462 entry = entry->next; 463 os_free(prev); 464 } 465 pmksa_cache_set_expiration(pmksa); 466 os_free(pmksa); 467 } 468 469 470 /** 471 * pmksa_cache_get - Fetch a PMKSA cache entry 472 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 473 * @aa: Authenticator address or %NULL to match any 474 * @pmkid: PMKID or %NULL to match any 475 * @network_ctx: Network context or %NULL to match any 476 * @akmp: Specific AKMP to search for or 0 for any 477 * Returns: Pointer to PMKSA cache entry or %NULL if no match was found 478 */ 479 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, 480 const u8 *aa, const u8 *spa, 481 const u8 *pmkid, 482 const void *network_ctx, 483 int akmp) 484 { 485 struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; 486 while (entry) { 487 if ((aa == NULL || ether_addr_equal(entry->aa, aa)) && 488 (!spa || ether_addr_equal(entry->spa, spa)) && 489 (pmkid == NULL || 490 os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) && 491 (!akmp || akmp == entry->akmp) && 492 (network_ctx == NULL || network_ctx == entry->network_ctx)) 493 return entry; 494 entry = entry->next; 495 } 496 return NULL; 497 } 498 499 500 static struct rsn_pmksa_cache_entry * 501 pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa, 502 const struct rsn_pmksa_cache_entry *old_entry, 503 const u8 *aa) 504 { 505 struct rsn_pmksa_cache_entry *new_entry; 506 os_time_t old_expiration = old_entry->expiration; 507 os_time_t old_reauth_time = old_entry->reauth_time; 508 const u8 *pmkid = NULL; 509 510 if (!pmksa->sm) 511 return NULL; 512 513 if (wpa_key_mgmt_sae(old_entry->akmp) || 514 wpa_key_mgmt_fils(old_entry->akmp)) 515 pmkid = old_entry->pmkid; 516 new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len, 517 pmkid, old_entry->kck, old_entry->kck_len, 518 aa, pmksa->sm->own_addr, 519 old_entry->network_ctx, old_entry->akmp, 520 old_entry->fils_cache_id_set ? 521 old_entry->fils_cache_id : NULL); 522 if (new_entry == NULL) 523 return NULL; 524 525 /* TODO: reorder entries based on expiration time? */ 526 new_entry->expiration = old_expiration; 527 new_entry->reauth_time = old_reauth_time; 528 new_entry->opportunistic = 1; 529 530 return new_entry; 531 } 532 533 534 /** 535 * pmksa_cache_get_opportunistic - Try to get an opportunistic PMKSA entry 536 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 537 * @network_ctx: Network configuration context 538 * @aa: Authenticator address for the new AP 539 * @akmp: Specific AKMP to search for or 0 for any 540 * Returns: Pointer to a new PMKSA cache entry or %NULL if not available 541 * 542 * Try to create a new PMKSA cache entry opportunistically by guessing that the 543 * new AP is sharing the same PMK as another AP that has the same SSID and has 544 * already an entry in PMKSA cache. 545 */ 546 struct rsn_pmksa_cache_entry * 547 pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx, 548 const u8 *aa, int akmp) 549 { 550 struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; 551 552 wpa_printf(MSG_DEBUG, "RSN: Consider " MACSTR " for OKC", MAC2STR(aa)); 553 if (network_ctx == NULL) 554 return NULL; 555 while (entry) { 556 if (entry->network_ctx == network_ctx && 557 (!akmp || entry->akmp == akmp)) { 558 struct os_reltime now; 559 560 if (wpa_key_mgmt_sae(entry->akmp) && 561 os_get_reltime(&now) == 0 && 562 entry->reauth_time < now.sec) { 563 wpa_printf(MSG_DEBUG, 564 "RSN: Do not clone PMKSA cache entry for " 565 MACSTR 566 " since its reauth threshold has passed", 567 MAC2STR(entry->aa)); 568 entry = entry->next; 569 continue; 570 } 571 572 entry = pmksa_cache_clone_entry(pmksa, entry, aa); 573 if (entry) { 574 wpa_printf(MSG_DEBUG, "RSN: added " 575 "opportunistic PMKSA cache entry " 576 "for " MACSTR, MAC2STR(aa)); 577 } 578 return entry; 579 } 580 entry = entry->next; 581 } 582 return NULL; 583 } 584 585 586 static struct rsn_pmksa_cache_entry * 587 pmksa_cache_get_fils_cache_id(struct rsn_pmksa_cache *pmksa, 588 const void *network_ctx, const u8 *cache_id) 589 { 590 struct rsn_pmksa_cache_entry *entry; 591 592 for (entry = pmksa->pmksa; entry; entry = entry->next) { 593 if (network_ctx == entry->network_ctx && 594 entry->fils_cache_id_set && 595 os_memcmp(cache_id, entry->fils_cache_id, 596 FILS_CACHE_ID_LEN) == 0) 597 return entry; 598 } 599 600 return NULL; 601 } 602 603 604 /** 605 * pmksa_cache_get_current - Get the current used PMKSA entry 606 * @sm: Pointer to WPA state machine data from wpa_sm_init() 607 * Returns: Pointer to the current PMKSA cache entry or %NULL if not available 608 */ 609 struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm) 610 { 611 if (sm == NULL) 612 return NULL; 613 return sm->cur_pmksa; 614 } 615 616 617 /** 618 * pmksa_cache_clear_current - Clear the current PMKSA entry selection 619 * @sm: Pointer to WPA state machine data from wpa_sm_init() 620 */ 621 void pmksa_cache_clear_current(struct wpa_sm *sm) 622 { 623 if (sm == NULL) 624 return; 625 if (sm->cur_pmksa) 626 wpa_printf(MSG_DEBUG, 627 "RSN: Clear current PMKSA entry selection"); 628 sm->cur_pmksa = NULL; 629 } 630 631 632 /** 633 * pmksa_cache_set_current - Set the current PMKSA entry selection 634 * @sm: Pointer to WPA state machine data from wpa_sm_init() 635 * @pmkid: PMKID for selecting PMKSA or %NULL if not used 636 * @bssid: BSSID for PMKSA or %NULL if not used 637 * @network_ctx: Network configuration context 638 * @try_opportunistic: Whether to allow opportunistic PMKSA caching 639 * @fils_cache_id: Pointer to FILS Cache Identifier or %NULL if not used 640 * @associated: Whether the device is associated 641 * Returns: 0 if PMKSA was found or -1 if no matching entry was found 642 */ 643 int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, 644 const u8 *bssid, void *network_ctx, 645 int try_opportunistic, const u8 *fils_cache_id, 646 int akmp, bool associated) 647 { 648 struct rsn_pmksa_cache *pmksa = sm->pmksa; 649 wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p " 650 "try_opportunistic=%d akmp=0x%x", 651 network_ctx, try_opportunistic, akmp); 652 if (pmkid) 653 wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID", 654 pmkid, PMKID_LEN); 655 if (bssid) 656 wpa_printf(MSG_DEBUG, "RSN: Search for BSSID " MACSTR, 657 MAC2STR(bssid)); 658 if (fils_cache_id) 659 wpa_printf(MSG_DEBUG, 660 "RSN: Search for FILS Cache Identifier %02x%02x", 661 fils_cache_id[0], fils_cache_id[1]); 662 663 sm->cur_pmksa = NULL; 664 if (pmkid) 665 sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, sm->own_addr, 666 pmkid, network_ctx, akmp); 667 if (sm->cur_pmksa == NULL && bssid) 668 sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, sm->own_addr, 669 NULL, network_ctx, akmp); 670 if (sm->cur_pmksa == NULL && try_opportunistic && bssid) 671 sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa, 672 network_ctx, 673 bssid, akmp); 674 if (sm->cur_pmksa == NULL && fils_cache_id) 675 sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa, 676 network_ctx, 677 fils_cache_id); 678 if (sm->cur_pmksa) { 679 struct os_reltime now; 680 681 if (wpa_key_mgmt_sae(sm->cur_pmksa->akmp) && 682 os_get_reltime(&now) == 0 && 683 sm->cur_pmksa->reauth_time < now.sec) { 684 /* Driver-based roaming might have used a PMKSA entry 685 * that is already past the reauthentication threshold. 686 * Remove the related PMKID from the driver to avoid 687 * further uses for this PMKSA, but allow the 688 * association to continue since the PMKSA has not yet 689 * expired. */ 690 wpa_sm_remove_pmkid(sm, sm->cur_pmksa->network_ctx, 691 sm->cur_pmksa->aa, 692 sm->cur_pmksa->pmkid, NULL); 693 if (associated) { 694 wpa_printf(MSG_DEBUG, 695 "RSN: Associated with " MACSTR 696 " using reauth threshold passed PMKSA cache entry", 697 MAC2STR(sm->cur_pmksa->aa)); 698 } else { 699 wpa_printf(MSG_DEBUG, 700 "RSN: Do not allow PMKSA cache entry for " 701 MACSTR 702 " to be used for SAE since its reauth threshold has passed", 703 MAC2STR(sm->cur_pmksa->aa)); 704 sm->cur_pmksa = NULL; 705 return -1; 706 } 707 } 708 709 wpa_hexdump(MSG_DEBUG, "RSN: PMKSA cache entry found - PMKID", 710 sm->cur_pmksa->pmkid, PMKID_LEN); 711 return 0; 712 } 713 wpa_printf(MSG_DEBUG, "RSN: No PMKSA cache entry found"); 714 return -1; 715 } 716 717 718 /** 719 * pmksa_cache_list - Dump text list of entries in PMKSA cache 720 * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() 721 * @buf: Buffer for the list 722 * @len: Length of the buffer 723 * Returns: number of bytes written to buffer 724 * 725 * This function is used to generate a text format representation of the 726 * current PMKSA cache contents for the ctrl_iface PMKSA command. 727 */ 728 int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) 729 { 730 int i, ret; 731 char *pos = buf; 732 struct rsn_pmksa_cache_entry *entry; 733 struct os_reltime now; 734 int cache_id_used = 0; 735 736 for (entry = pmksa->pmksa; entry; entry = entry->next) { 737 if (entry->fils_cache_id_set) { 738 cache_id_used = 1; 739 break; 740 } 741 } 742 743 os_get_reltime(&now); 744 ret = os_snprintf(pos, buf + len - pos, 745 "Index / AA / PMKID / expiration (in seconds) / " 746 "opportunistic%s\n", 747 cache_id_used ? " / FILS Cache Identifier" : ""); 748 if (os_snprintf_error(buf + len - pos, ret)) 749 return pos - buf; 750 pos += ret; 751 i = 0; 752 entry = pmksa->pmksa; 753 while (entry) { 754 i++; 755 ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", 756 i, MAC2STR(entry->aa)); 757 if (os_snprintf_error(buf + len - pos, ret)) 758 return pos - buf; 759 pos += ret; 760 pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, 761 PMKID_LEN); 762 ret = os_snprintf(pos, buf + len - pos, " %d %d", 763 (int) (entry->expiration - now.sec), 764 entry->opportunistic); 765 if (os_snprintf_error(buf + len - pos, ret)) 766 return pos - buf; 767 pos += ret; 768 if (entry->fils_cache_id_set) { 769 ret = os_snprintf(pos, buf + len - pos, " %02x%02x", 770 entry->fils_cache_id[0], 771 entry->fils_cache_id[1]); 772 if (os_snprintf_error(buf + len - pos, ret)) 773 return pos - buf; 774 pos += ret; 775 } 776 ret = os_snprintf(pos, buf + len - pos, "\n"); 777 if (os_snprintf_error(buf + len - pos, ret)) 778 return pos - buf; 779 pos += ret; 780 entry = entry->next; 781 } 782 return pos - buf; 783 } 784 785 786 struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa) 787 { 788 return pmksa->pmksa; 789 } 790 791 792 /** 793 * pmksa_cache_init - Initialize PMKSA cache 794 * @free_cb: Callback function to be called when a PMKSA cache entry is freed 795 * @ctx: Context pointer for free_cb function 796 * @sm: Pointer to WPA state machine data from wpa_sm_init() 797 * Returns: Pointer to PMKSA cache data or %NULL on failure 798 */ 799 struct rsn_pmksa_cache * 800 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, 801 void *ctx, enum pmksa_free_reason reason), 802 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry, 803 void *ctx), 804 void (*notify_cb)(struct rsn_pmksa_cache_entry *entry, 805 void *ctx), 806 void *ctx, struct wpa_sm *sm) 807 { 808 struct rsn_pmksa_cache *pmksa; 809 810 pmksa = os_zalloc(sizeof(*pmksa)); 811 if (pmksa) { 812 pmksa->free_cb = free_cb; 813 pmksa->is_current_cb = is_current_cb; 814 pmksa->notify_cb = notify_cb; 815 pmksa->ctx = ctx; 816 pmksa->sm = sm; 817 } 818 819 return pmksa; 820 } 821 822 823 void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa) 824 { 825 struct rsn_pmksa_cache_entry *entry; 826 struct os_reltime now; 827 828 if (!pmksa || !pmksa->pmksa) 829 return; 830 831 os_get_reltime(&now); 832 for (entry = pmksa->pmksa; entry; entry = entry->next) { 833 u32 life_time; 834 u8 reauth_threshold; 835 836 if (entry->expiration - now.sec < 1 || 837 entry->reauth_time - now.sec < 1) 838 continue; 839 840 life_time = entry->expiration - now.sec; 841 reauth_threshold = (entry->reauth_time - now.sec) * 100 / 842 life_time; 843 if (!reauth_threshold) 844 continue; 845 846 wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa, 847 entry->pmkid, 848 entry->fils_cache_id_set ? 849 entry->fils_cache_id : NULL, 850 entry->pmk, entry->pmk_len, life_time, 851 reauth_threshold, entry->akmp); 852 } 853 } 854 855 #else /* IEEE8021X_EAPOL */ 856 857 struct rsn_pmksa_cache * 858 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, 859 void *ctx, enum pmksa_free_reason reason), 860 bool (*is_current_cb)(struct rsn_pmksa_cache_entry *entry, 861 void *ctx), 862 void (*notify_cb)(struct rsn_pmksa_cache_entry *entry, 863 void *ctx), 864 void *ctx, struct wpa_sm *sm) 865 { 866 return (void *) -1; 867 } 868 869 870 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) 871 { 872 } 873 874 875 struct rsn_pmksa_cache_entry * 876 pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, 877 const u8 *pmkid, const void *network_ctx, int akmp) 878 { 879 return NULL; 880 } 881 882 883 struct rsn_pmksa_cache_entry * 884 pmksa_cache_get_current(struct wpa_sm *sm) 885 { 886 return NULL; 887 } 888 889 890 int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) 891 { 892 return -1; 893 } 894 895 896 struct rsn_pmksa_cache_entry * 897 pmksa_cache_head(struct rsn_pmksa_cache *pmksa) 898 { 899 return NULL; 900 } 901 902 903 struct rsn_pmksa_cache_entry * 904 pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa, 905 struct rsn_pmksa_cache_entry *entry) 906 { 907 return NULL; 908 } 909 910 911 struct rsn_pmksa_cache_entry * 912 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, 913 const u8 *pmkid, const u8 *kck, size_t kck_len, 914 const u8 *aa, const u8 *spa, void *network_ctx, int akmp, 915 const u8 *cache_id) 916 { 917 return NULL; 918 } 919 920 921 void pmksa_cache_clear_current(struct wpa_sm *sm) 922 { 923 } 924 925 926 int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, const u8 *bssid, 927 void *network_ctx, int try_opportunistic, 928 const u8 *fils_cache_id, int akmp, bool associated) 929 { 930 return -1; 931 } 932 933 934 void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, 935 const u8 *pmk, size_t pmk_len, bool external_only) 936 { 937 } 938 939 940 void pmksa_cache_remove(struct rsn_pmksa_cache *pmksa, 941 struct rsn_pmksa_cache_entry *entry) 942 { 943 } 944 945 946 void pmksa_cache_reconfig(struct rsn_pmksa_cache *pmksa) 947 { 948 } 949 950 #endif /* IEEE8021X_EAPOL */ 951