pmksa_cache.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  1. /*
  2. * WPA Supplicant - RSN PMKSA cache
  3. * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "wpa.h"
  17. #include "eloop.h"
  18. #include "sha1.h"
  19. #include "sha256.h"
  20. #include "wpa_i.h"
  21. #include "eapol_supp/eapol_supp_sm.h"
  22. #include "pmksa_cache.h"
  23. #if defined(IEEE8021X_EAPOL) && !defined(CONFIG_NO_WPA2)
  24. static const int pmksa_cache_max_entries = 32;
  25. struct rsn_pmksa_cache {
  26. struct rsn_pmksa_cache_entry *pmksa; /* PMKSA cache */
  27. int pmksa_count; /* number of entries in PMKSA cache */
  28. struct wpa_sm *sm; /* TODO: get rid of this reference(?) */
  29. void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx,
  30. int replace);
  31. void *ctx;
  32. };
  33. /**
  34. * rsn_pmkid - Calculate PMK identifier
  35. * @pmk: Pairwise master key
  36. * @pmk_len: Length of pmk in bytes
  37. * @aa: Authenticator address
  38. * @spa: Supplicant address
  39. * @use_sha256: Whether to use SHA256-based KDF
  40. *
  41. * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
  42. * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
  43. */
  44. static void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa,
  45. const u8 *spa, u8 *pmkid, int use_sha256)
  46. {
  47. char *title = "PMK Name";
  48. const u8 *addr[3];
  49. const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
  50. unsigned char hash[SHA256_MAC_LEN];
  51. addr[0] = (u8 *) title;
  52. addr[1] = aa;
  53. addr[2] = spa;
  54. #ifdef CONFIG_IEEE80211W
  55. if (use_sha256)
  56. hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
  57. else
  58. #endif /* CONFIG_IEEE80211W */
  59. hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
  60. os_memcpy(pmkid, hash, PMKID_LEN);
  61. }
  62. static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
  63. static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
  64. {
  65. os_free(entry);
  66. }
  67. static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
  68. struct rsn_pmksa_cache_entry *entry,
  69. int replace)
  70. {
  71. pmksa->pmksa_count--;
  72. pmksa->free_cb(entry, pmksa->ctx, replace);
  73. _pmksa_cache_free_entry(entry);
  74. }
  75. static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
  76. {
  77. struct rsn_pmksa_cache *pmksa = eloop_ctx;
  78. struct os_time now;
  79. os_get_time(&now);
  80. while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
  81. struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
  82. pmksa->pmksa = entry->next;
  83. wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
  84. MACSTR, MAC2STR(entry->aa));
  85. pmksa_cache_free_entry(pmksa, entry, 0);
  86. }
  87. pmksa_cache_set_expiration(pmksa);
  88. }
  89. static void pmksa_cache_reauth(void *eloop_ctx, void *timeout_ctx)
  90. {
  91. struct rsn_pmksa_cache *pmksa = eloop_ctx;
  92. pmksa->sm->cur_pmksa = NULL;
  93. eapol_sm_request_reauth(pmksa->sm->eapol);
  94. }
  95. static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
  96. {
  97. int sec;
  98. struct rsn_pmksa_cache_entry *entry;
  99. struct os_time now;
  100. eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
  101. eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL);
  102. if (pmksa->pmksa == NULL)
  103. return;
  104. os_get_time(&now);
  105. sec = pmksa->pmksa->expiration - now.sec;
  106. if (sec < 0)
  107. sec = 0;
  108. eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
  109. entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
  110. pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL);
  111. if (entry) {
  112. sec = pmksa->pmksa->reauth_time - now.sec;
  113. if (sec < 0)
  114. sec = 0;
  115. eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa,
  116. NULL);
  117. }
  118. }
  119. /**
  120. * pmksa_cache_add - Add a PMKSA cache entry
  121. * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  122. * @pmk: The new pairwise master key
  123. * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
  124. * @aa: Authenticator address
  125. * @spa: Supplicant address
  126. * @network_ctx: Network configuration context for this PMK
  127. * @akmp: WPA_KEY_MGMT_* used in key derivation
  128. * Returns: Pointer to the added PMKSA cache entry or %NULL on error
  129. *
  130. * This function create a PMKSA entry for a new PMK and adds it to the PMKSA
  131. * cache. If an old entry is already in the cache for the same Authenticator,
  132. * this entry will be replaced with the new entry. PMKID will be calculated
  133. * based on the PMK and the driver interface is notified of the new PMKID.
  134. */
  135. struct rsn_pmksa_cache_entry *
  136. pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
  137. const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
  138. {
  139. struct rsn_pmksa_cache_entry *entry, *pos, *prev;
  140. struct os_time now;
  141. if (pmk_len > PMK_LEN)
  142. return NULL;
  143. entry = os_zalloc(sizeof(*entry));
  144. if (entry == NULL)
  145. return NULL;
  146. os_memcpy(entry->pmk, pmk, pmk_len);
  147. entry->pmk_len = pmk_len;
  148. rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
  149. wpa_key_mgmt_sha256(akmp));
  150. os_get_time(&now);
  151. entry->expiration = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime;
  152. entry->reauth_time = now.sec + pmksa->sm->dot11RSNAConfigPMKLifetime *
  153. pmksa->sm->dot11RSNAConfigPMKReauthThreshold / 100;
  154. entry->akmp = akmp;
  155. os_memcpy(entry->aa, aa, ETH_ALEN);
  156. entry->network_ctx = network_ctx;
  157. /* Replace an old entry for the same Authenticator (if found) with the
  158. * new entry */
  159. pos = pmksa->pmksa;
  160. prev = NULL;
  161. while (pos) {
  162. if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) {
  163. if (pos->pmk_len == pmk_len &&
  164. os_memcmp(pos->pmk, pmk, pmk_len) == 0 &&
  165. os_memcmp(pos->pmkid, entry->pmkid, PMKID_LEN) ==
  166. 0) {
  167. wpa_printf(MSG_DEBUG, "WPA: reusing previous "
  168. "PMKSA entry");
  169. os_free(entry);
  170. return pos;
  171. }
  172. if (prev == NULL)
  173. pmksa->pmksa = pos->next;
  174. else
  175. prev->next = pos->next;
  176. if (pos == pmksa->sm->cur_pmksa) {
  177. /* We are about to replace the current PMKSA
  178. * cache entry. This happens when the PMKSA
  179. * caching attempt fails, so we don't want to
  180. * force pmksa_cache_free_entry() to disconnect
  181. * at this point. Let's just make sure the old
  182. * PMKSA cache entry will not be used in the
  183. * future.
  184. */
  185. wpa_printf(MSG_DEBUG, "RSN: replacing current "
  186. "PMKSA entry");
  187. pmksa->sm->cur_pmksa = NULL;
  188. }
  189. wpa_printf(MSG_DEBUG, "RSN: Replace PMKSA entry for "
  190. "the current AP");
  191. pmksa_cache_free_entry(pmksa, pos, 1);
  192. break;
  193. }
  194. prev = pos;
  195. pos = pos->next;
  196. }
  197. if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
  198. /* Remove the oldest entry to make room for the new entry */
  199. pos = pmksa->pmksa;
  200. pmksa->pmksa = pos->next;
  201. wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache "
  202. "entry (for " MACSTR ") to make room for new one",
  203. MAC2STR(pos->aa));
  204. wpa_sm_remove_pmkid(pmksa->sm, pos->aa, pos->pmkid);
  205. pmksa_cache_free_entry(pmksa, pos, 0);
  206. }
  207. /* Add the new entry; order by expiration time */
  208. pos = pmksa->pmksa;
  209. prev = NULL;
  210. while (pos) {
  211. if (pos->expiration > entry->expiration)
  212. break;
  213. prev = pos;
  214. pos = pos->next;
  215. }
  216. if (prev == NULL) {
  217. entry->next = pmksa->pmksa;
  218. pmksa->pmksa = entry;
  219. pmksa_cache_set_expiration(pmksa);
  220. } else {
  221. entry->next = prev->next;
  222. prev->next = entry;
  223. }
  224. pmksa->pmksa_count++;
  225. wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
  226. MAC2STR(entry->aa));
  227. wpa_sm_add_pmkid(pmksa->sm, entry->aa, entry->pmkid);
  228. return entry;
  229. }
  230. /**
  231. * pmksa_cache_deinit - Free all entries in PMKSA cache
  232. * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  233. */
  234. void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
  235. {
  236. struct rsn_pmksa_cache_entry *entry, *prev;
  237. if (pmksa == NULL)
  238. return;
  239. entry = pmksa->pmksa;
  240. pmksa->pmksa = NULL;
  241. while (entry) {
  242. prev = entry;
  243. entry = entry->next;
  244. os_free(prev);
  245. }
  246. pmksa_cache_set_expiration(pmksa);
  247. os_free(pmksa);
  248. }
  249. /**
  250. * pmksa_cache_get - Fetch a PMKSA cache entry
  251. * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  252. * @aa: Authenticator address or %NULL to match any
  253. * @pmkid: PMKID or %NULL to match any
  254. * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
  255. */
  256. struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
  257. const u8 *aa, const u8 *pmkid)
  258. {
  259. struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
  260. while (entry) {
  261. if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
  262. (pmkid == NULL ||
  263. os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
  264. return entry;
  265. entry = entry->next;
  266. }
  267. return NULL;
  268. }
  269. /**
  270. * pmksa_cache_notify_reconfig - Reconfiguration notification for PMKSA cache
  271. * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  272. *
  273. * Clear references to old data structures when wpa_supplicant is reconfigured.
  274. */
  275. void pmksa_cache_notify_reconfig(struct rsn_pmksa_cache *pmksa)
  276. {
  277. struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
  278. while (entry) {
  279. entry->network_ctx = NULL;
  280. entry = entry->next;
  281. }
  282. }
  283. static struct rsn_pmksa_cache_entry *
  284. pmksa_cache_clone_entry(struct rsn_pmksa_cache *pmksa,
  285. const struct rsn_pmksa_cache_entry *old_entry,
  286. const u8 *aa)
  287. {
  288. struct rsn_pmksa_cache_entry *new_entry;
  289. new_entry = pmksa_cache_add(pmksa, old_entry->pmk, old_entry->pmk_len,
  290. aa, pmksa->sm->own_addr,
  291. old_entry->network_ctx, old_entry->akmp);
  292. if (new_entry == NULL)
  293. return NULL;
  294. /* TODO: reorder entries based on expiration time? */
  295. new_entry->expiration = old_entry->expiration;
  296. new_entry->opportunistic = 1;
  297. return new_entry;
  298. }
  299. /**
  300. * pmksa_cache_get_opportunistic - Try to get an opportunistic PMKSA entry
  301. * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
  302. * @network_ctx: Network configuration context
  303. * @aa: Authenticator address for the new AP
  304. * Returns: Pointer to a new PMKSA cache entry or %NULL if not available
  305. *
  306. * Try to create a new PMKSA cache entry opportunistically by guessing that the
  307. * new AP is sharing the same PMK as another AP that has the same SSID and has
  308. * already an entry in PMKSA cache.
  309. */
  310. struct rsn_pmksa_cache_entry *
  311. pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
  312. const u8 *aa)
  313. {
  314. struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
  315. if (network_ctx == NULL)
  316. return NULL;
  317. while (entry) {
  318. if (entry->network_ctx == network_ctx) {
  319. entry = pmksa_cache_clone_entry(pmksa, entry, aa);
  320. if (entry) {
  321. wpa_printf(MSG_DEBUG, "RSN: added "
  322. "opportunistic PMKSA cache entry "
  323. "for " MACSTR, MAC2STR(aa));
  324. }
  325. return entry;
  326. }
  327. entry = entry->next;
  328. }
  329. return NULL;
  330. }
  331. /**
  332. * pmksa_cache_get_current - Get the current used PMKSA entry
  333. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  334. * Returns: Pointer to the current PMKSA cache entry or %NULL if not available
  335. */
  336. struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm)
  337. {
  338. if (sm == NULL)
  339. return NULL;
  340. return sm->cur_pmksa;
  341. }
  342. /**
  343. * pmksa_cache_clear_current - Clear the current PMKSA entry selection
  344. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  345. */
  346. void pmksa_cache_clear_current(struct wpa_sm *sm)
  347. {
  348. if (sm == NULL)
  349. return;
  350. sm->cur_pmksa = NULL;
  351. }
  352. /**
  353. * pmksa_cache_set_current - Set the current PMKSA entry selection
  354. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  355. * @pmkid: PMKID for selecting PMKSA or %NULL if not used
  356. * @bssid: BSSID for PMKSA or %NULL if not used
  357. * @network_ctx: Network configuration context
  358. * @try_opportunistic: Whether to allow opportunistic PMKSA caching
  359. * Returns: 0 if PMKSA was found or -1 if no matching entry was found
  360. */
  361. int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
  362. const u8 *bssid, void *network_ctx,
  363. int try_opportunistic)
  364. {
  365. struct rsn_pmksa_cache *pmksa = sm->pmksa;
  366. sm->cur_pmksa = NULL;
  367. if (pmkid)
  368. sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid);
  369. if (sm->cur_pmksa == NULL && bssid)
  370. sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL);
  371. if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
  372. sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
  373. network_ctx,
  374. bssid);
  375. if (sm->cur_pmksa) {
  376. wpa_hexdump(MSG_DEBUG, "RSN: PMKID",
  377. sm->cur_pmksa->pmkid, PMKID_LEN);
  378. return 0;
  379. }
  380. return -1;
  381. }
  382. /**
  383. * pmksa_cache_list - Dump text list of entries in PMKSA cache
  384. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  385. * @buf: Buffer for the list
  386. * @len: Length of the buffer
  387. * Returns: number of bytes written to buffer
  388. *
  389. * This function is used to generate a text format representation of the
  390. * current PMKSA cache contents for the ctrl_iface PMKSA command.
  391. */
  392. int pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
  393. {
  394. int i, ret;
  395. char *pos = buf;
  396. struct rsn_pmksa_cache_entry *entry;
  397. struct os_time now;
  398. os_get_time(&now);
  399. ret = os_snprintf(pos, buf + len - pos,
  400. "Index / AA / PMKID / expiration (in seconds) / "
  401. "opportunistic\n");
  402. if (ret < 0 || ret >= buf + len - pos)
  403. return pos - buf;
  404. pos += ret;
  405. i = 0;
  406. entry = sm->pmksa->pmksa;
  407. while (entry) {
  408. i++;
  409. ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ",
  410. i, MAC2STR(entry->aa));
  411. if (ret < 0 || ret >= buf + len - pos)
  412. return pos - buf;
  413. pos += ret;
  414. pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid,
  415. PMKID_LEN);
  416. ret = os_snprintf(pos, buf + len - pos, " %d %d\n",
  417. (int) (entry->expiration - now.sec),
  418. entry->opportunistic);
  419. if (ret < 0 || ret >= buf + len - pos)
  420. return pos - buf;
  421. pos += ret;
  422. entry = entry->next;
  423. }
  424. return pos - buf;
  425. }
  426. /**
  427. * pmksa_cache_init - Initialize PMKSA cache
  428. * @free_cb: Callback function to be called when a PMKSA cache entry is freed
  429. * @ctx: Context pointer for free_cb function
  430. * @sm: Pointer to WPA state machine data from wpa_sm_init()
  431. * Returns: Pointer to PMKSA cache data or %NULL on failure
  432. */
  433. struct rsn_pmksa_cache *
  434. pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
  435. void *ctx, int replace),
  436. void *ctx, struct wpa_sm *sm)
  437. {
  438. struct rsn_pmksa_cache *pmksa;
  439. pmksa = os_zalloc(sizeof(*pmksa));
  440. if (pmksa) {
  441. pmksa->free_cb = free_cb;
  442. pmksa->ctx = ctx;
  443. pmksa->sm = sm;
  444. }
  445. return pmksa;
  446. }
  447. #endif /* IEEE8021X_EAPOL and !CONFIG_NO_WPA2 */