Merge branch 'vendor/MDOCML'
[dragonfly.git] / contrib / hostapd / hostapd / pmksa_cache.c
1 /*
2  * hostapd - PMKSA cache for IEEE 802.11i RSN
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
15 #include "includes.h"
16
17 #include "common.h"
18 #include "ap.h"
19 #include "config.h"
20 #include "common.h"
21 #include "eloop.h"
22 #include "sha1.h"
23 #include "sha256.h"
24 #include "ieee802_1x.h"
25 #include "eapol_sm.h"
26 #include "pmksa_cache.h"
27
28
29 static const int pmksa_cache_max_entries = 1024;
30 static const int dot11RSNAConfigPMKLifetime = 43200;
31
32 struct rsn_pmksa_cache {
33 #define PMKID_HASH_SIZE 128
34 #define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & 0x7f)
35         struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE];
36         struct rsn_pmksa_cache_entry *pmksa;
37         int pmksa_count;
38
39         void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx);
40         void *ctx;
41 };
42
43
44 /**
45  * rsn_pmkid - Calculate PMK identifier
46  * @pmk: Pairwise master key
47  * @pmk_len: Length of pmk in bytes
48  * @aa: Authenticator address
49  * @spa: Supplicant address
50  * @pmkid: Buffer for PMKID
51  * @use_sha256: Whether to use SHA256-based KDF
52  *
53  * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy
54  * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA)
55  */
56 void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa,
57                u8 *pmkid, int use_sha256)
58 {
59         char *title = "PMK Name";
60         const u8 *addr[3];
61         const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN };
62         unsigned char hash[SHA256_MAC_LEN];
63
64         addr[0] = (u8 *) title;
65         addr[1] = aa;
66         addr[2] = spa;
67
68 #ifdef CONFIG_IEEE80211W
69         if (use_sha256)
70                 hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash);
71         else
72 #endif /* CONFIG_IEEE80211W */
73                 hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash);
74         os_memcpy(pmkid, hash, PMKID_LEN);
75 }
76
77
78 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa);
79
80
81 static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry)
82 {
83         if (entry == NULL)
84                 return;
85         os_free(entry->identity);
86         ieee802_1x_free_radius_class(&entry->radius_class);
87         os_free(entry);
88 }
89
90
91 static void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa,
92                                    struct rsn_pmksa_cache_entry *entry)
93 {
94         struct rsn_pmksa_cache_entry *pos, *prev;
95
96         pmksa->pmksa_count--;
97         pmksa->free_cb(entry, pmksa->ctx);
98         pos = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
99         prev = NULL;
100         while (pos) {
101                 if (pos == entry) {
102                         if (prev != NULL) {
103                                 prev->hnext = pos->hnext;
104                         } else {
105                                 pmksa->pmkid[PMKID_HASH(entry->pmkid)] =
106                                         pos->hnext;
107                         }
108                         break;
109                 }
110                 prev = pos;
111                 pos = pos->hnext;
112         }
113
114         pos = pmksa->pmksa;
115         prev = NULL;
116         while (pos) {
117                 if (pos == entry) {
118                         if (prev != NULL)
119                                 prev->next = pos->next;
120                         else
121                                 pmksa->pmksa = pos->next;
122                         break;
123                 }
124                 prev = pos;
125                 pos = pos->next;
126         }
127         _pmksa_cache_free_entry(entry);
128 }
129
130
131 static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx)
132 {
133         struct rsn_pmksa_cache *pmksa = eloop_ctx;
134         struct os_time now;
135
136         os_get_time(&now);
137         while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) {
138                 struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
139                 pmksa->pmksa = entry->next;
140                 wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for "
141                            MACSTR, MAC2STR(entry->spa));
142                 pmksa_cache_free_entry(pmksa, entry);
143         }
144
145         pmksa_cache_set_expiration(pmksa);
146 }
147
148
149 static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa)
150 {
151         int sec;
152         struct os_time now;
153
154         eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
155         if (pmksa->pmksa == NULL)
156                 return;
157         os_get_time(&now);
158         sec = pmksa->pmksa->expiration - now.sec;
159         if (sec < 0)
160                 sec = 0;
161         eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
162 }
163
164
165 static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry,
166                                         struct eapol_state_machine *eapol)
167 {
168         if (eapol == NULL)
169                 return;
170
171         if (eapol->identity) {
172                 entry->identity = os_malloc(eapol->identity_len);
173                 if (entry->identity) {
174                         entry->identity_len = eapol->identity_len;
175                         os_memcpy(entry->identity, eapol->identity,
176                                   eapol->identity_len);
177                 }
178         }
179
180         ieee802_1x_copy_radius_class(&entry->radius_class,
181                                      &eapol->radius_class);
182
183         entry->eap_type_authsrv = eapol->eap_type_authsrv;
184         entry->vlan_id = eapol->sta->vlan_id;
185 }
186
187
188 void pmksa_cache_to_eapol_data(struct rsn_pmksa_cache_entry *entry,
189                                struct eapol_state_machine *eapol)
190 {
191         if (entry == NULL || eapol == NULL)
192                 return;
193
194         if (entry->identity) {
195                 os_free(eapol->identity);
196                 eapol->identity = os_malloc(entry->identity_len);
197                 if (eapol->identity) {
198                         eapol->identity_len = entry->identity_len;
199                         os_memcpy(eapol->identity, entry->identity,
200                                   entry->identity_len);
201                 }
202                 wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA",
203                                   eapol->identity, eapol->identity_len);
204         }
205
206         ieee802_1x_free_radius_class(&eapol->radius_class);
207         ieee802_1x_copy_radius_class(&eapol->radius_class,
208                                      &entry->radius_class);
209         if (eapol->radius_class.attr) {
210                 wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from "
211                            "PMKSA", (unsigned long) eapol->radius_class.count);
212         }
213
214         eapol->eap_type_authsrv = entry->eap_type_authsrv;
215         eapol->sta->vlan_id = entry->vlan_id;
216 }
217
218
219 static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa,
220                                    struct rsn_pmksa_cache_entry *entry)
221 {
222         struct rsn_pmksa_cache_entry *pos, *prev;
223
224         /* Add the new entry; order by expiration time */
225         pos = pmksa->pmksa;
226         prev = NULL;
227         while (pos) {
228                 if (pos->expiration > entry->expiration)
229                         break;
230                 prev = pos;
231                 pos = pos->next;
232         }
233         if (prev == NULL) {
234                 entry->next = pmksa->pmksa;
235                 pmksa->pmksa = entry;
236         } else {
237                 entry->next = prev->next;
238                 prev->next = entry;
239         }
240         entry->hnext = pmksa->pmkid[PMKID_HASH(entry->pmkid)];
241         pmksa->pmkid[PMKID_HASH(entry->pmkid)] = entry;
242
243         pmksa->pmksa_count++;
244         wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR,
245                    MAC2STR(entry->spa));
246         wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN);
247 }
248
249
250 /**
251  * pmksa_cache_add - Add a PMKSA cache entry
252  * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
253  * @pmk: The new pairwise master key
254  * @pmk_len: PMK length in bytes, usually PMK_LEN (32)
255  * @aa: Authenticator address
256  * @spa: Supplicant address
257  * @session_timeout: Session timeout
258  * @eapol: Pointer to EAPOL state machine data
259  * @akmp: WPA_KEY_MGMT_* used in key derivation
260  * Returns: Pointer to the added PMKSA cache entry or %NULL on error
261  *
262  * This function create a PMKSA entry for a new PMK and adds it to the PMKSA
263  * cache. If an old entry is already in the cache for the same Supplicant,
264  * this entry will be replaced with the new entry. PMKID will be calculated
265  * based on the PMK.
266  */
267 struct rsn_pmksa_cache_entry *
268 pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
269                 const u8 *aa, const u8 *spa, int session_timeout,
270                 struct eapol_state_machine *eapol, int akmp)
271 {
272         struct rsn_pmksa_cache_entry *entry, *pos;
273         struct os_time now;
274
275         if (pmk_len > PMK_LEN)
276                 return NULL;
277
278         entry = os_zalloc(sizeof(*entry));
279         if (entry == NULL)
280                 return NULL;
281         os_memcpy(entry->pmk, pmk, pmk_len);
282         entry->pmk_len = pmk_len;
283         rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid,
284                   wpa_key_mgmt_sha256(akmp));
285         os_get_time(&now);
286         entry->expiration = now.sec;
287         if (session_timeout > 0)
288                 entry->expiration += session_timeout;
289         else
290                 entry->expiration += dot11RSNAConfigPMKLifetime;
291         entry->akmp = akmp;
292         os_memcpy(entry->spa, spa, ETH_ALEN);
293         pmksa_cache_from_eapol_data(entry, eapol);
294
295         /* Replace an old entry for the same STA (if found) with the new entry
296          */
297         pos = pmksa_cache_get(pmksa, spa, NULL);
298         if (pos)
299                 pmksa_cache_free_entry(pmksa, pos);
300
301         if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) {
302                 /* Remove the oldest entry to make room for the new entry */
303                 wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache "
304                            "entry (for " MACSTR ") to make room for new one",
305                            MAC2STR(pmksa->pmksa->spa));
306                 pmksa_cache_free_entry(pmksa, pmksa->pmksa);
307         }
308
309         pmksa_cache_link_entry(pmksa, entry);
310
311         return entry;
312 }
313
314
315 struct rsn_pmksa_cache_entry *
316 pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa,
317                     const struct rsn_pmksa_cache_entry *old_entry,
318                     const u8 *aa, const u8 *pmkid)
319 {
320         struct rsn_pmksa_cache_entry *entry;
321
322         entry = os_zalloc(sizeof(*entry));
323         if (entry == NULL)
324                 return NULL;
325         os_memcpy(entry->pmkid, pmkid, PMKID_LEN);
326         os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len);
327         entry->pmk_len = old_entry->pmk_len;
328         entry->expiration = old_entry->expiration;
329         entry->akmp = old_entry->akmp;
330         os_memcpy(entry->spa, old_entry->spa, ETH_ALEN);
331         entry->opportunistic = 1;
332         if (old_entry->identity) {
333                 entry->identity = os_malloc(old_entry->identity_len);
334                 if (entry->identity) {
335                         entry->identity_len = old_entry->identity_len;
336                         os_memcpy(entry->identity, old_entry->identity,
337                                   old_entry->identity_len);
338                 }
339         }
340         ieee802_1x_copy_radius_class(&entry->radius_class,
341                                      &old_entry->radius_class);
342         entry->eap_type_authsrv = old_entry->eap_type_authsrv;
343         entry->vlan_id = old_entry->vlan_id;
344         entry->opportunistic = 1;
345
346         pmksa_cache_link_entry(pmksa, entry);
347
348         return entry;
349 }
350
351
352 /**
353  * pmksa_cache_deinit - Free all entries in PMKSA cache
354  * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
355  */
356 void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa)
357 {
358         struct rsn_pmksa_cache_entry *entry, *prev;
359         int i;
360
361         if (pmksa == NULL)
362                 return;
363
364         entry = pmksa->pmksa;
365         while (entry) {
366                 prev = entry;
367                 entry = entry->next;
368                 _pmksa_cache_free_entry(prev);
369         }
370         eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL);
371         for (i = 0; i < PMKID_HASH_SIZE; i++)
372                 pmksa->pmkid[i] = NULL;
373         os_free(pmksa);
374 }
375
376
377 /**
378  * pmksa_cache_get - Fetch a PMKSA cache entry
379  * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
380  * @spa: Supplicant address or %NULL to match any
381  * @pmkid: PMKID or %NULL to match any
382  * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
383  */
384 struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
385                                                const u8 *spa, const u8 *pmkid)
386 {
387         struct rsn_pmksa_cache_entry *entry;
388
389         if (pmkid)
390                 entry = pmksa->pmkid[PMKID_HASH(pmkid)];
391         else
392                 entry = pmksa->pmksa;
393         while (entry) {
394                 if ((spa == NULL ||
395                      os_memcmp(entry->spa, spa, ETH_ALEN) == 0) &&
396                     (pmkid == NULL ||
397                      os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0))
398                         return entry;
399                 entry = pmkid ? entry->hnext : entry->next;
400         }
401         return NULL;
402 }
403
404
405 /**
406  * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC
407  * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
408  * @aa: Authenticator address
409  * @spa: Supplicant address
410  * @pmkid: PMKID
411  * Returns: Pointer to PMKSA cache entry or %NULL if no match was found
412  *
413  * Use opportunistic key caching (OKC) to find a PMK for a supplicant.
414  */
415 struct rsn_pmksa_cache_entry * pmksa_cache_get_okc(
416         struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa,
417         const u8 *pmkid)
418 {
419         struct rsn_pmksa_cache_entry *entry;
420         u8 new_pmkid[PMKID_LEN];
421
422         entry = pmksa->pmksa;
423         while (entry) {
424                 if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0)
425                         continue;
426                 rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid,
427                           wpa_key_mgmt_sha256(entry->akmp));
428                 if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0)
429                         return entry;
430                 entry = entry->next;
431         }
432         return NULL;
433 }
434
435
436 /**
437  * pmksa_cache_init - Initialize PMKSA cache
438  * @free_cb: Callback function to be called when a PMKSA cache entry is freed
439  * @ctx: Context pointer for free_cb function
440  * Returns: Pointer to PMKSA cache data or %NULL on failure
441  */
442 struct rsn_pmksa_cache *
443 pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry,
444                                  void *ctx), void *ctx)
445 {
446         struct rsn_pmksa_cache *pmksa;
447
448         pmksa = os_zalloc(sizeof(*pmksa));
449         if (pmksa) {
450                 pmksa->free_cb = free_cb;
451                 pmksa->ctx = ctx;
452         }
453
454         return pmksa;
455 }