]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/ap/wpa_auth_ft.c
FT: Connection settings for SHA384-based AKM
[thirdparty/hostap.git] / src / ap / wpa_auth_ft.c
CommitLineData
6fc6879b
JM
1/*
2 * hostapd - IEEE 802.11r - Fast BSS Transition
c22bb5bb 3 * Copyright (c) 2004-2018, Jouni Malinen <j@w1.fi>
6fc6879b 4 *
0f3d578e
JM
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
6fc6879b
JM
7 */
8
6226e38d 9#include "utils/includes.h"
6fc6879b 10
6226e38d 11#include "utils/common.h"
692ec305 12#include "utils/eloop.h"
76967603 13#include "utils/list.h"
81f4f619
JM
14#include "common/ieee802_11_defs.h"
15#include "common/ieee802_11_common.h"
245fc96e
MB
16#include "crypto/aes.h"
17#include "crypto/aes_siv.h"
03da66bd 18#include "crypto/aes_wrap.h"
a3e18dbb 19#include "crypto/sha384.h"
3642c431 20#include "crypto/random.h"
6226e38d 21#include "ap_config.h"
6fc6879b 22#include "ieee802_11.h"
1057d78e 23#include "wmm.h"
6226e38d 24#include "wpa_auth.h"
6fc6879b 25#include "wpa_auth_i.h"
6fc6879b
JM
26
27
4ec1fd8e 28#ifdef CONFIG_IEEE80211R_AP
6fc6879b 29
eefe8630
MB
30const unsigned int ftRRBseqTimeout = 10;
31const unsigned int ftRRBmaxQueueLen = 100;
32
33
692ec305
JM
34static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
35 const u8 *current_ap, const u8 *sta_addr,
36 u16 status, const u8 *resp_ies,
37 size_t resp_ies_len);
3a46cf93
MB
38static void ft_finish_pull(struct wpa_state_machine *sm);
39static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx);
eefe8630 40static void wpa_ft_rrb_seq_timeout(void *eloop_ctx, void *timeout_ctx);
692ec305 41
245fc96e
MB
42struct tlv_list {
43 u16 type;
44 size_t len;
45 const u8 *data;
46};
47
48
49/**
50 * wpa_ft_rrb_decrypt - Decrypt FT RRB message
51 * @key: AES-SIV key for AEAD
52 * @key_len: Length of key in octets
53 * @enc: Pointer to encrypted TLVs
54 * @enc_len: Length of encrypted TLVs in octets
55 * @auth: Pointer to authenticated TLVs
56 * @auth_len: Length of authenticated TLVs in octets
57 * @src_addr: MAC address of the frame sender
58 * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*)
59 * @plain: Pointer to return the pointer to the allocated plaintext buffer;
60 * needs to be freed by the caller if not NULL;
61 * will only be returned on success
62 * @plain_len: Pointer to return the length of the allocated plaintext buffer
63 * in octets
64 * Returns: 0 on success, -1 on error
65 */
66static int wpa_ft_rrb_decrypt(const u8 *key, const size_t key_len,
67 const u8 *enc, const size_t enc_len,
68 const u8 *auth, const size_t auth_len,
69 const u8 *src_addr, u8 type,
70 u8 **plain, size_t *plain_size)
71{
72 const u8 *ad[3] = { src_addr, auth, &type };
73 size_t ad_len[3] = { ETH_ALEN, auth_len, sizeof(type) };
74
75 wpa_hexdump_key(MSG_DEBUG, "FT(RRB): decrypt using key", key, key_len);
76
77 if (!key) { /* skip decryption */
78 *plain = os_memdup(enc, enc_len);
79 if (enc_len > 0 && !*plain)
80 goto err;
81
82 *plain_size = enc_len;
83
84 return 0;
85 }
86
87 *plain = NULL;
88
89 /* SIV overhead */
90 if (enc_len < AES_BLOCK_SIZE)
91 goto err;
92
93 *plain = os_zalloc(enc_len - AES_BLOCK_SIZE);
94 if (!*plain)
95 goto err;
96
97 if (aes_siv_decrypt(key, key_len, enc, enc_len, 3, ad, ad_len,
98 *plain) < 0)
99 goto err;
100
101 *plain_size = enc_len - AES_BLOCK_SIZE;
102 wpa_hexdump_key(MSG_DEBUG, "FT(RRB): decrypted TLVs",
103 *plain, *plain_size);
104 return 0;
105err:
106 os_free(*plain);
107 *plain = NULL;
108 *plain_size = 0;
109
110 wpa_printf(MSG_ERROR, "FT(RRB): Failed to decrypt");
111
112 return -1;
113}
114
115
116/* get first tlv record in packet matching type
117 * @data (decrypted) packet
118 * @return 0 on success else -1
119 */
120static int wpa_ft_rrb_get_tlv(const u8 *plain, size_t plain_len,
121 u16 type, size_t *tlv_len, const u8 **tlv_data)
122{
123 const struct ft_rrb_tlv *f;
124 size_t left;
125 le16 type16;
126 size_t len;
127
128 left = plain_len;
129 type16 = host_to_le16(type);
130
131 while (left >= sizeof(*f)) {
132 f = (const struct ft_rrb_tlv *) plain;
133
134 left -= sizeof(*f);
135 plain += sizeof(*f);
136 len = le_to_host16(f->len);
137
138 if (left < len) {
139 wpa_printf(MSG_DEBUG, "FT: RRB message truncated");
140 break;
141 }
142
143 if (f->type == type16) {
144 *tlv_len = len;
145 *tlv_data = plain;
146 return 0;
147 }
148
149 left -= len;
150 plain += len;
151 }
152
153 return -1;
154}
155
156
157static void wpa_ft_rrb_dump(const u8 *plain, const size_t plain_len)
158{
159 const struct ft_rrb_tlv *f;
160 size_t left;
161 size_t len;
162
163 left = plain_len;
164
165 wpa_printf(MSG_DEBUG, "FT: RRB dump message");
166 while (left >= sizeof(*f)) {
167 f = (const struct ft_rrb_tlv *) plain;
168
169 left -= sizeof(*f);
170 plain += sizeof(*f);
171 len = le_to_host16(f->len);
172
173 wpa_printf(MSG_DEBUG, "FT: RRB TLV type = %d, len = %zu",
174 le_to_host16(f->type), len);
175
176 if (left < len) {
177 wpa_printf(MSG_DEBUG,
178 "FT: RRB message truncated: left %zu bytes, need %zu",
179 left, len);
180 break;
181 }
182
183 wpa_hexdump(MSG_DEBUG, "FT: RRB TLV data", plain, len);
184
185 left -= len;
186 plain += len;
187 }
188
189 if (left > 0)
190 wpa_hexdump(MSG_DEBUG, "FT: RRB TLV padding", plain, left);
191
192 wpa_printf(MSG_DEBUG, "FT: RRB dump message end");
193}
194
195
17010c38
MB
196static int cmp_int(const void *a, const void *b)
197{
198 int x, y;
199
200 x = *((int *) a);
201 y = *((int *) b);
202 return x - y;
203}
204
205
206static int wpa_ft_rrb_get_tlv_vlan(const u8 *plain, const size_t plain_len,
207 struct vlan_description *vlan)
208{
209 struct ft_rrb_tlv *f;
210 size_t left;
211 size_t len;
212 int taggedidx;
213 int vlan_id;
214 int type;
215
216 left = plain_len;
217 taggedidx = 0;
218 os_memset(vlan, 0, sizeof(*vlan));
219
220 while (left >= sizeof(*f)) {
221 f = (struct ft_rrb_tlv *) plain;
222
223 left -= sizeof(*f);
224 plain += sizeof(*f);
225
226 len = le_to_host16(f->len);
227 type = le_to_host16(f->type);
228
229 if (left < len) {
230 wpa_printf(MSG_DEBUG, "FT: RRB message truncated");
231 return -1;
232 }
233
234 if (type != FT_RRB_VLAN_UNTAGGED && type != FT_RRB_VLAN_TAGGED)
235 goto skip;
236
237 if (type == FT_RRB_VLAN_UNTAGGED && len != sizeof(le16)) {
238 wpa_printf(MSG_DEBUG,
239 "FT: RRB VLAN_UNTAGGED invalid length");
240 return -1;
241 }
242
243 if (type == FT_RRB_VLAN_TAGGED && len % sizeof(le16) != 0) {
244 wpa_printf(MSG_DEBUG,
245 "FT: RRB VLAN_TAGGED invalid length");
246 return -1;
247 }
248
249 while (len >= sizeof(le16)) {
250 vlan_id = WPA_GET_LE16(plain);
251 plain += sizeof(le16);
252 left -= sizeof(le16);
253 len -= sizeof(le16);
254
255 if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) {
256 wpa_printf(MSG_DEBUG,
257 "FT: RRB VLAN ID invalid %d",
258 vlan_id);
259 continue;
260 }
261
262 if (type == FT_RRB_VLAN_UNTAGGED)
263 vlan->untagged = vlan_id;
264
265 if (type == FT_RRB_VLAN_TAGGED &&
266 taggedidx < MAX_NUM_TAGGED_VLAN) {
267 vlan->tagged[taggedidx] = vlan_id;
268 taggedidx++;
269 } else if (type == FT_RRB_VLAN_TAGGED) {
270 wpa_printf(MSG_DEBUG, "FT: RRB too many VLANs");
271 }
272 }
273
274 skip:
275 left -= len;
276 plain += len;
277 }
278
279 if (taggedidx)
280 qsort(vlan->tagged, taggedidx, sizeof(int), cmp_int);
281
282 vlan->notempty = vlan->untagged || vlan->tagged[0];
283
284 return 0;
285}
286
287
245fc96e
MB
288static size_t wpa_ft_tlv_len(const struct tlv_list *tlvs)
289{
290 size_t tlv_len = 0;
291 int i;
292
293 if (!tlvs)
294 return 0;
295
296 for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) {
297 tlv_len += sizeof(struct ft_rrb_tlv);
298 tlv_len += tlvs[i].len;
299 }
300
301 return tlv_len;
302}
303
304
305static size_t wpa_ft_tlv_lin(const struct tlv_list *tlvs, u8 *start,
306 u8 *endpos)
307{
308 int i;
309 size_t tlv_len;
310 struct ft_rrb_tlv *hdr;
311 u8 *pos;
312
313 if (!tlvs)
314 return 0;
315
316 tlv_len = 0;
317 pos = start;
318 for (i = 0; tlvs[i].type != FT_RRB_LAST_EMPTY; i++) {
319 if (tlv_len + sizeof(*hdr) > (size_t) (endpos - start))
320 return tlv_len;
321 tlv_len += sizeof(*hdr);
322 hdr = (struct ft_rrb_tlv *) pos;
323 hdr->type = host_to_le16(tlvs[i].type);
324 hdr->len = host_to_le16(tlvs[i].len);
325 pos = start + tlv_len;
326
327 if (tlv_len + tlvs[i].len > (size_t) (endpos - start))
328 return tlv_len;
069b4e30
MB
329 if (tlvs[i].len == 0)
330 continue;
245fc96e
MB
331 tlv_len += tlvs[i].len;
332 os_memcpy(pos, tlvs[i].data, tlvs[i].len);
333 pos = start + tlv_len;
334 }
335
336 return tlv_len;
337}
338
339
17010c38
MB
340static size_t wpa_ft_vlan_len(const struct vlan_description *vlan)
341{
342 size_t tlv_len = 0;
343 int i;
344
345 if (!vlan || !vlan->notempty)
346 return 0;
347
348 if (vlan->untagged) {
349 tlv_len += sizeof(struct ft_rrb_tlv);
350 tlv_len += sizeof(le16);
351 }
352 if (vlan->tagged[0])
353 tlv_len += sizeof(struct ft_rrb_tlv);
354 for (i = 0; i < MAX_NUM_TAGGED_VLAN && vlan->tagged[i]; i++)
355 tlv_len += sizeof(le16);
356
357 return tlv_len;
358}
359
360
361static size_t wpa_ft_vlan_lin(const struct vlan_description *vlan,
362 u8 *start, u8 *endpos)
363{
364 size_t tlv_len;
365 int i, len;
366 struct ft_rrb_tlv *hdr;
367 u8 *pos = start;
368
369 if (!vlan || !vlan->notempty)
370 return 0;
371
372 tlv_len = 0;
373 if (vlan->untagged) {
374 tlv_len += sizeof(*hdr);
375 if (start + tlv_len > endpos)
376 return tlv_len;
377 hdr = (struct ft_rrb_tlv *) pos;
378 hdr->type = host_to_le16(FT_RRB_VLAN_UNTAGGED);
379 hdr->len = host_to_le16(sizeof(le16));
380 pos = start + tlv_len;
381
382 tlv_len += sizeof(le16);
383 if (start + tlv_len > endpos)
384 return tlv_len;
385 WPA_PUT_LE16(pos, vlan->untagged);
386 pos = start + tlv_len;
387 }
388
389 if (!vlan->tagged[0])
390 return tlv_len;
391
392 tlv_len += sizeof(*hdr);
393 if (start + tlv_len > endpos)
394 return tlv_len;
395 hdr = (struct ft_rrb_tlv *) pos;
396 hdr->type = host_to_le16(FT_RRB_VLAN_TAGGED);
397 len = 0; /* len is computed below */
398 pos = start + tlv_len;
399
400 for (i = 0; i < MAX_NUM_TAGGED_VLAN && vlan->tagged[i]; i++) {
401 tlv_len += sizeof(le16);
402 if (start + tlv_len > endpos)
403 break;
404 len += sizeof(le16);
405 WPA_PUT_LE16(pos, vlan->tagged[i]);
406 pos = start + tlv_len;
407 }
408
409 hdr->len = host_to_le16(len);
410
411 return tlv_len;
412}
413
414
245fc96e
MB
415static int wpa_ft_rrb_lin(const struct tlv_list *tlvs1,
416 const struct tlv_list *tlvs2,
17010c38 417 const struct vlan_description *vlan,
245fc96e
MB
418 u8 **plain, size_t *plain_len)
419{
420 u8 *pos, *endpos;
421 size_t tlv_len;
422
423 tlv_len = wpa_ft_tlv_len(tlvs1);
424 tlv_len += wpa_ft_tlv_len(tlvs2);
17010c38 425 tlv_len += wpa_ft_vlan_len(vlan);
245fc96e
MB
426
427 *plain_len = tlv_len;
428 *plain = os_zalloc(tlv_len);
429 if (!*plain) {
430 wpa_printf(MSG_ERROR, "FT: Failed to allocate plaintext");
431 goto err;
432 }
433
434 pos = *plain;
435 endpos = *plain + tlv_len;
436 pos += wpa_ft_tlv_lin(tlvs1, pos, endpos);
437 pos += wpa_ft_tlv_lin(tlvs2, pos, endpos);
17010c38 438 pos += wpa_ft_vlan_lin(vlan, pos, endpos);
245fc96e
MB
439
440 /* sanity check */
441 if (pos != endpos) {
442 wpa_printf(MSG_ERROR, "FT: Length error building RRB");
443 goto err;
444 }
445
446 return 0;
447
448err:
449 os_free(*plain);
450 *plain = NULL;
451 *plain_len = 0;
452 return -1;
453}
454
455
456static int wpa_ft_rrb_encrypt(const u8 *key, const size_t key_len,
457 const u8 *plain, const size_t plain_len,
458 const u8 *auth, const size_t auth_len,
459 const u8 *src_addr, u8 type, u8 *enc)
460{
461 const u8 *ad[3] = { src_addr, auth, &type };
462 size_t ad_len[3] = { ETH_ALEN, auth_len, sizeof(type) };
463
464 wpa_hexdump_key(MSG_DEBUG, "FT(RRB): plaintext message",
465 plain, plain_len);
466 wpa_hexdump_key(MSG_DEBUG, "FT(RRB): encrypt using key", key, key_len);
467
468 if (!key) {
469 /* encryption not needed, return plaintext as packet */
470 os_memcpy(enc, plain, plain_len);
471 } else if (aes_siv_encrypt(key, key_len, plain, plain_len,
472 3, ad, ad_len, enc) < 0) {
473 wpa_printf(MSG_ERROR, "FT: Failed to encrypt RRB-OUI message");
474 return -1;
475 }
476
477 return 0;
478}
479
480
481/**
482 * wpa_ft_rrb_build - Build and encrypt an FT RRB message
483 * @key: AES-SIV key for AEAD
484 * @key_len: Length of key in octets
485 * @tlvs_enc0: First set of to-be-encrypted TLVs
486 * @tlvs_enc1: Second set of to-be-encrypted TLVs
487 * @tlvs_auth: Set of to-be-authenticated TLVs
488 * @src_addr: MAC address of the frame sender
489 * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*)
490 * @packet Pointer to return the pointer to the allocated packet buffer;
491 * needs to be freed by the caller if not null;
492 * will only be returned on success
493 * @packet_len: Pointer to return the length of the allocated buffer in octets
494 * Returns: 0 on success, -1 on error
495 */
496static int wpa_ft_rrb_build(const u8 *key, const size_t key_len,
497 const struct tlv_list *tlvs_enc0,
498 const struct tlv_list *tlvs_enc1,
499 const struct tlv_list *tlvs_auth,
17010c38 500 const struct vlan_description *vlan,
245fc96e
MB
501 const u8 *src_addr, u8 type,
502 u8 **packet, size_t *packet_len)
503{
504 u8 *plain = NULL, *auth = NULL, *pos;
505 size_t plain_len = 0, auth_len = 0;
506 int ret = -1;
507
17010c38 508 if (wpa_ft_rrb_lin(tlvs_enc0, tlvs_enc1, vlan, &plain, &plain_len) < 0)
245fc96e
MB
509 goto out;
510
17010c38 511 if (wpa_ft_rrb_lin(tlvs_auth, NULL, NULL, &auth, &auth_len) < 0)
245fc96e
MB
512 goto out;
513
514 *packet_len = sizeof(u16) + auth_len + plain_len;
515 if (key)
516 *packet_len += AES_BLOCK_SIZE;
517 *packet = os_zalloc(*packet_len);
518 if (!*packet)
519 goto out;
520
521 pos = *packet;
522 WPA_PUT_LE16(pos, auth_len);
523 pos += 2;
524 os_memcpy(pos, auth, auth_len);
525 pos += auth_len;
526 if (wpa_ft_rrb_encrypt(key, key_len, plain, plain_len, auth,
527 auth_len, src_addr, type, pos) < 0)
528 goto out;
529
530 ret = 0;
531
532out:
533 bin_clear_free(plain, plain_len);
534 os_free(auth);
535
536 if (ret) {
537 wpa_printf(MSG_ERROR, "FT: Failed to build RRB-OUI message");
538 os_free(*packet);
539 *packet = NULL;
540 *packet_len = 0;
541 }
542
543 return ret;
544}
545
546
547#define RRB_GET_SRC(srcfield, type, field, txt, checklength) do { \
548 if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \
549 &f_##field##_len, &f_##field) < 0 || \
550 (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
551 wpa_printf(MSG_INFO, "FT: Missing required " #field \
552 " in %s from " MACSTR, txt, MAC2STR(src_addr)); \
553 wpa_ft_rrb_dump(srcfield, srcfield##_len); \
554 goto out; \
555 } \
556} while (0)
557
558#define RRB_GET(type, field, txt, checklength) \
559 RRB_GET_SRC(plain, type, field, txt, checklength)
560#define RRB_GET_AUTH(type, field, txt, checklength) \
561 RRB_GET_SRC(auth, type, field, txt, checklength)
562
563#define RRB_GET_OPTIONAL_SRC(srcfield, type, field, txt, checklength) do { \
564 if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \
565 &f_##field##_len, &f_##field) < 0 || \
566 (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
567 wpa_printf(MSG_DEBUG, "FT: Missing optional " #field \
568 " in %s from " MACSTR, txt, MAC2STR(src_addr)); \
569 f_##field##_len = 0; \
570 f_##field = NULL; \
571 } \
572} while (0)
573
574#define RRB_GET_OPTIONAL(type, field, txt, checklength) \
575 RRB_GET_OPTIONAL_SRC(plain, type, field, txt, checklength)
576#define RRB_GET_OPTIONAL_AUTH(type, field, txt, checklength) \
577 RRB_GET_OPTIONAL_SRC(auth, type, field, txt, checklength)
692ec305 578
6fc6879b
JM
579static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
580 const u8 *data, size_t data_len)
581{
cef8fac0 582 if (wpa_auth->cb->send_ether == NULL)
6fc6879b 583 return -1;
67ccef7e 584 wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst));
cef8fac0
JB
585 return wpa_auth->cb->send_ether(wpa_auth->cb_ctx, dst, ETH_P_RRB,
586 data, data_len);
6fc6879b
JM
587}
588
589
50bd8e0a
MB
590static int wpa_ft_rrb_oui_send(struct wpa_authenticator *wpa_auth,
591 const u8 *dst, u8 oui_suffix,
592 const u8 *data, size_t data_len)
593{
594 if (!wpa_auth->cb->send_oui)
595 return -1;
596 wpa_printf(MSG_DEBUG, "FT: RRB-OUI type %u send to " MACSTR,
597 oui_suffix, MAC2STR(dst));
598 return wpa_auth->cb->send_oui(wpa_auth->cb_ctx, dst, oui_suffix, data,
599 data_len);
600}
601
602
6fc6879b
JM
603static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth,
604 const u8 *dst, const u8 *data, size_t data_len)
605{
cef8fac0 606 if (wpa_auth->cb->send_ft_action == NULL)
6fc6879b 607 return -1;
cef8fac0
JB
608 return wpa_auth->cb->send_ft_action(wpa_auth->cb_ctx, dst,
609 data, data_len);
6fc6879b
JM
610}
611
612
96590564
MB
613static const u8 * wpa_ft_get_psk(struct wpa_authenticator *wpa_auth,
614 const u8 *addr, const u8 *p2p_dev_addr,
615 const u8 *prev_psk)
616{
cef8fac0 617 if (wpa_auth->cb->get_psk == NULL)
96590564 618 return NULL;
cef8fac0 619 return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
7a12edd1 620 prev_psk, NULL);
96590564
MB
621}
622
623
6fc6879b
JM
624static struct wpa_state_machine *
625wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
626{
cef8fac0 627 if (wpa_auth->cb->add_sta == NULL)
6fc6879b 628 return NULL;
cef8fac0 629 return wpa_auth->cb->add_sta(wpa_auth->cb_ctx, sta_addr);
6fc6879b
JM
630}
631
632
17010c38
MB
633static int wpa_ft_set_vlan(struct wpa_authenticator *wpa_auth,
634 const u8 *sta_addr, struct vlan_description *vlan)
635{
636 if (!wpa_auth->cb->set_vlan)
637 return -1;
638 return wpa_auth->cb->set_vlan(wpa_auth->cb_ctx, sta_addr, vlan);
639}
640
641
642static int wpa_ft_get_vlan(struct wpa_authenticator *wpa_auth,
643 const u8 *sta_addr, struct vlan_description *vlan)
644{
645 if (!wpa_auth->cb->get_vlan)
646 return -1;
647 return wpa_auth->cb->get_vlan(wpa_auth->cb_ctx, sta_addr, vlan);
648}
649
650
069b4e30
MB
651static int
652wpa_ft_set_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
653 const u8 *identity, size_t identity_len)
654{
655 if (!wpa_auth->cb->set_identity)
656 return -1;
657 return wpa_auth->cb->set_identity(wpa_auth->cb_ctx, sta_addr, identity,
658 identity_len);
659}
660
661
662static size_t
663wpa_ft_get_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
664 const u8 **buf)
665{
666 *buf = NULL;
667 if (!wpa_auth->cb->get_identity)
668 return 0;
669 return wpa_auth->cb->get_identity(wpa_auth->cb_ctx, sta_addr, buf);
670}
671
672
673static int
674wpa_ft_set_radius_cui(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
675 const u8 *radius_cui, size_t radius_cui_len)
676{
677 if (!wpa_auth->cb->set_radius_cui)
678 return -1;
679 return wpa_auth->cb->set_radius_cui(wpa_auth->cb_ctx, sta_addr,
680 radius_cui, radius_cui_len);
681}
682
683
684static size_t
685wpa_ft_get_radius_cui(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
686 const u8 **buf)
687{
688 *buf = NULL;
689 if (!wpa_auth->cb->get_radius_cui)
690 return 0;
691 return wpa_auth->cb->get_radius_cui(wpa_auth->cb_ctx, sta_addr, buf);
692}
693
694
a6509e85
MB
695static void
696wpa_ft_set_session_timeout(struct wpa_authenticator *wpa_auth,
697 const u8 *sta_addr, int session_timeout)
698{
699 if (!wpa_auth->cb->set_session_timeout)
700 return;
701 wpa_auth->cb->set_session_timeout(wpa_auth->cb_ctx, sta_addr,
702 session_timeout);
703}
704
705
706static int
707wpa_ft_get_session_timeout(struct wpa_authenticator *wpa_auth,
708 const u8 *sta_addr)
709{
710 if (!wpa_auth->cb->get_session_timeout)
711 return 0;
712 return wpa_auth->cb->get_session_timeout(wpa_auth->cb_ctx, sta_addr);
713}
714
715
88b32a99
SP
716static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
717 const u8 *sta_addr,
718 u8 *tspec_ie, size_t tspec_ielen)
719{
cef8fac0 720 if (wpa_auth->cb->add_tspec == NULL) {
006309b5 721 wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
88b32a99
SP
722 return -1;
723 }
cef8fac0
JB
724 return wpa_auth->cb->add_tspec(wpa_auth->cb_ctx, sta_addr, tspec_ie,
725 tspec_ielen);
88b32a99
SP
726}
727
728
6fc6879b
JM
729int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
730{
731 u8 *pos = buf;
732 u8 capab;
733 if (len < 2 + sizeof(struct rsn_mdie))
734 return -1;
735
736 *pos++ = WLAN_EID_MOBILITY_DOMAIN;
737 *pos++ = MOBILITY_DOMAIN_ID_LEN + 1;
738 os_memcpy(pos, conf->mobility_domain, MOBILITY_DOMAIN_ID_LEN);
739 pos += MOBILITY_DOMAIN_ID_LEN;
d7956add
SP
740 capab = 0;
741 if (conf->ft_over_ds)
742 capab |= RSN_FT_CAPAB_FT_OVER_DS;
6fc6879b
JM
743 *pos++ = capab;
744
745 return pos - buf;
746}
747
748
86dfabb8
JM
749int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
750 size_t r0kh_id_len,
751 const u8 *anonce, const u8 *snonce,
752 u8 *buf, size_t len, const u8 *subelem,
753 size_t subelem_len)
6fc6879b
JM
754{
755 u8 *pos = buf, *ielen;
756 struct rsn_ftie *hdr;
757
758 if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len +
759 subelem_len)
760 return -1;
761
762 *pos++ = WLAN_EID_FAST_BSS_TRANSITION;
763 ielen = pos++;
764
765 hdr = (struct rsn_ftie *) pos;
766 os_memset(hdr, 0, sizeof(*hdr));
767 pos += sizeof(*hdr);
768 WPA_PUT_LE16(hdr->mic_control, 0);
769 if (anonce)
770 os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
771 if (snonce)
772 os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN);
773
774 /* Optional Parameters */
775 *pos++ = FTIE_SUBELEM_R1KH_ID;
776 *pos++ = FT_R1KH_ID_LEN;
777 os_memcpy(pos, conf->r1_key_holder, FT_R1KH_ID_LEN);
778 pos += FT_R1KH_ID_LEN;
779
780 if (r0kh_id) {
781 *pos++ = FTIE_SUBELEM_R0KH_ID;
782 *pos++ = r0kh_id_len;
783 os_memcpy(pos, r0kh_id, r0kh_id_len);
784 pos += r0kh_id_len;
785 }
786
787 if (subelem) {
788 os_memcpy(pos, subelem, subelem_len);
789 pos += subelem_len;
790 }
791
792 *ielen = pos - buf - 2;
793
794 return pos - buf;
795}
796
797
eefe8630
MB
798/* A packet to be handled after seq response */
799struct ft_remote_item {
800 struct dl_list list;
801
802 u8 nonce[FT_RRB_NONCE_LEN];
803 struct os_reltime nonce_ts;
804
805 u8 src_addr[ETH_ALEN];
806 u8 *enc;
807 size_t enc_len;
808 u8 *auth;
809 size_t auth_len;
810 int (*cb)(struct wpa_authenticator *wpa_auth,
811 const u8 *src_addr,
812 const u8 *enc, size_t enc_len,
813 const u8 *auth, size_t auth_len,
814 int no_defer);
815};
816
817
818static void wpa_ft_rrb_seq_free(struct ft_remote_item *item)
819{
820 eloop_cancel_timeout(wpa_ft_rrb_seq_timeout, ELOOP_ALL_CTX, item);
821 dl_list_del(&item->list);
822 bin_clear_free(item->enc, item->enc_len);
823 os_free(item->auth);
824 os_free(item);
825}
826
827
828static void wpa_ft_rrb_seq_flush(struct wpa_authenticator *wpa_auth,
829 struct ft_remote_seq *rkh_seq, int cb)
830{
831 struct ft_remote_item *item, *n;
832
833 dl_list_for_each_safe(item, n, &rkh_seq->rx.queue,
834 struct ft_remote_item, list) {
835 if (cb && item->cb)
836 item->cb(wpa_auth, item->src_addr, item->enc,
837 item->enc_len, item->auth, item->auth_len, 1);
838 wpa_ft_rrb_seq_free(item);
839 }
840}
841
842
843static void wpa_ft_rrb_seq_timeout(void *eloop_ctx, void *timeout_ctx)
844{
845 struct ft_remote_item *item = timeout_ctx;
846
847 wpa_ft_rrb_seq_free(item);
848}
849
850
851static int
852wpa_ft_rrb_seq_req(struct wpa_authenticator *wpa_auth,
853 struct ft_remote_seq *rkh_seq, const u8 *src_addr,
854 const u8 *f_r0kh_id, size_t f_r0kh_id_len,
855 const u8 *f_r1kh_id, const u8 *key, size_t key_len,
856 const u8 *enc, size_t enc_len,
857 const u8 *auth, size_t auth_len,
858 int (*cb)(struct wpa_authenticator *wpa_auth,
859 const u8 *src_addr,
860 const u8 *enc, size_t enc_len,
861 const u8 *auth, size_t auth_len,
862 int no_defer))
863{
864 struct ft_remote_item *item = NULL;
865 u8 *packet = NULL;
866 size_t packet_len;
867 struct tlv_list seq_req_auth[] = {
868 { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN,
869 .data = NULL /* to be filled: item->nonce */ },
870 { .type = FT_RRB_R0KH_ID, .len = f_r0kh_id_len,
871 .data = f_r0kh_id },
872 { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
873 .data = f_r1kh_id },
874 { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
875 };
876
877 if (dl_list_len(&rkh_seq->rx.queue) >= ftRRBmaxQueueLen) {
878 wpa_printf(MSG_DEBUG, "FT: Sequence number queue too long");
879 goto err;
880 }
881
882 item = os_zalloc(sizeof(*item));
883 if (!item)
884 goto err;
885
886 os_memcpy(item->src_addr, src_addr, ETH_ALEN);
887 item->cb = cb;
888
889 if (random_get_bytes(item->nonce, FT_RRB_NONCE_LEN) < 0) {
890 wpa_printf(MSG_DEBUG, "FT: Seq num nonce: out of random bytes");
891 goto err;
892 }
893
894 if (os_get_reltime(&item->nonce_ts) < 0)
895 goto err;
896
897 if (enc && enc_len > 0) {
898 item->enc = os_memdup(enc, enc_len);
899 item->enc_len = enc_len;
900 if (!item->enc)
901 goto err;
902 }
903
904 if (auth && auth_len > 0) {
905 item->auth = os_memdup(auth, auth_len);
906 item->auth_len = auth_len;
907 if (!item->auth)
908 goto err;
909 }
910
911 eloop_register_timeout(ftRRBseqTimeout, 0, wpa_ft_rrb_seq_timeout,
912 wpa_auth, item);
913
914 seq_req_auth[0].data = item->nonce;
915
17010c38 916 if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_req_auth, NULL,
eefe8630
MB
917 wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
918 &packet, &packet_len) < 0) {
919 item = NULL; /* some other seq resp might still accept this */
920 goto err;
921 }
922
923 dl_list_add(&rkh_seq->rx.queue, &item->list);
924
925 wpa_ft_rrb_oui_send(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
926 packet, packet_len);
927
928 os_free(packet);
929
930 return 0;
931err:
932 wpa_printf(MSG_DEBUG, "FT: Failed to send sequence number request");
933 if (item) {
934 os_free(item->auth);
935 bin_clear_free(item->enc, item->enc_len);
936 os_free(item);
937 }
938
939 return -1;
940}
941
942
943#define FT_RRB_SEQ_OK 0
944#define FT_RRB_SEQ_DROP 1
945#define FT_RRB_SEQ_DEFER 2
946
947static int
948wpa_ft_rrb_seq_chk(struct ft_remote_seq *rkh_seq, const u8 *src_addr,
949 const u8 *enc, size_t enc_len,
950 const u8 *auth, size_t auth_len,
951 const char *msgtype, int no_defer)
952{
953 const u8 *f_seq;
954 size_t f_seq_len;
955 const struct ft_rrb_seq *msg_both;
956 u32 msg_seq, msg_off, rkh_off;
957 struct os_reltime now;
958 unsigned int i;
959
960 RRB_GET_AUTH(FT_RRB_SEQ, seq, msgtype, sizeof(*msg_both));
961 wpa_hexdump(MSG_DEBUG, "FT: sequence number", f_seq, f_seq_len);
962 msg_both = (const struct ft_rrb_seq *) f_seq;
963
964 if (rkh_seq->rx.num_last == 0) {
965 /* first packet from remote */
966 goto defer;
967 }
968
969 if (le_to_host32(msg_both->dom) != rkh_seq->rx.dom) {
970 /* remote might have rebooted */
971 goto defer;
972 }
973
974 if (os_get_reltime(&now) == 0) {
975 u32 msg_ts_now_remote, msg_ts_off;
976 struct os_reltime now_remote;
977
978 os_reltime_sub(&now, &rkh_seq->rx.time_offset, &now_remote);
979 msg_ts_now_remote = now_remote.sec;
980 msg_ts_off = le_to_host32(msg_both->ts) -
981 (msg_ts_now_remote - ftRRBseqTimeout);
982 if (msg_ts_off > 2 * ftRRBseqTimeout)
983 goto defer;
984 }
985
986 msg_seq = le_to_host32(msg_both->seq);
987 rkh_off = rkh_seq->rx.last[rkh_seq->rx.offsetidx];
988 msg_off = msg_seq - rkh_off;
989 if (msg_off > 0xC0000000)
990 goto out; /* too old message, drop it */
991
992 if (msg_off <= 0x40000000) {
993 for (i = 0; i < rkh_seq->rx.num_last; i++) {
994 if (rkh_seq->rx.last[i] == msg_seq)
995 goto out; /* duplicate message, drop it */
996 }
997
998 return FT_RRB_SEQ_OK;
999 }
1000
1001defer:
1002 if (no_defer)
1003 goto out;
1004
1005 wpa_printf(MSG_DEBUG, "FT: Possibly invalid sequence number in %s from "
1006 MACSTR, msgtype, MAC2STR(src_addr));
1007
1008 return FT_RRB_SEQ_DEFER;
1009out:
1010 wpa_printf(MSG_DEBUG, "FT: Invalid sequence number in %s from " MACSTR,
1011 msgtype, MAC2STR(src_addr));
1012
1013 return FT_RRB_SEQ_DROP;
1014}
1015
1016
1017static void
1018wpa_ft_rrb_seq_accept(struct wpa_authenticator *wpa_auth,
1019 struct ft_remote_seq *rkh_seq, const u8 *src_addr,
1020 const u8 *auth, size_t auth_len,
1021 const char *msgtype)
1022{
1023 const u8 *f_seq;
1024 size_t f_seq_len;
1025 const struct ft_rrb_seq *msg_both;
1026 u32 msg_seq, msg_off, min_off, rkh_off;
1027 int minidx = 0;
1028 unsigned int i;
1029
1030 RRB_GET_AUTH(FT_RRB_SEQ, seq, msgtype, sizeof(*msg_both));
1031 msg_both = (const struct ft_rrb_seq *) f_seq;
1032
1033 msg_seq = le_to_host32(msg_both->seq);
1034
1035 if (rkh_seq->rx.num_last < FT_REMOTE_SEQ_BACKLOG) {
1036 rkh_seq->rx.last[rkh_seq->rx.num_last] = msg_seq;
1037 rkh_seq->rx.num_last++;
1038 return;
1039 }
1040
1041 rkh_off = rkh_seq->rx.last[rkh_seq->rx.offsetidx];
1042 for (i = 0; i < rkh_seq->rx.num_last; i++) {
1043 msg_off = rkh_seq->rx.last[i] - rkh_off;
1044 min_off = rkh_seq->rx.last[minidx] - rkh_off;
1045 if (msg_off < min_off && i != rkh_seq->rx.offsetidx)
1046 minidx = i;
1047 }
1048 rkh_seq->rx.last[rkh_seq->rx.offsetidx] = msg_seq;
1049 rkh_seq->rx.offsetidx = minidx;
1050
1051 return;
1052out:
1053 /* RRB_GET_AUTH should never fail here as
1054 * wpa_ft_rrb_seq_chk() verified FT_RRB_SEQ presence. */
1055 wpa_printf(MSG_ERROR, "FT: %s() failed", __func__);
1056}
1057
1058
1059static int wpa_ft_new_seq(struct ft_remote_seq *rkh_seq,
1060 struct ft_rrb_seq *f_seq)
1061{
1062 struct os_reltime now;
1063
1064 if (os_get_reltime(&now) < 0)
1065 return -1;
1066
1067 if (!rkh_seq->tx.dom) {
1068 if (random_get_bytes((u8 *) &rkh_seq->tx.seq,
1069 sizeof(rkh_seq->tx.seq))) {
1070 wpa_printf(MSG_ERROR,
1071 "FT: Failed to get random data for sequence number initialization");
1072 rkh_seq->tx.seq = now.usec;
1073 }
1074 if (random_get_bytes((u8 *) &rkh_seq->tx.dom,
1075 sizeof(rkh_seq->tx.dom))) {
1076 wpa_printf(MSG_ERROR,
1077 "FT: Failed to get random data for sequence number initialization");
1078 rkh_seq->tx.dom = now.usec;
1079 }
1080 rkh_seq->tx.dom |= 1;
1081 }
1082
1083 f_seq->dom = host_to_le32(rkh_seq->tx.dom);
1084 f_seq->seq = host_to_le32(rkh_seq->tx.seq);
1085 f_seq->ts = host_to_le32(now.sec);
1086
1087 rkh_seq->tx.seq++;
1088
1089 return 0;
1090}
1091
1092
6fc6879b 1093struct wpa_ft_pmk_r0_sa {
09211c98 1094 struct dl_list list;
a3e18dbb
JM
1095 u8 pmk_r0[PMK_LEN_MAX];
1096 size_t pmk_r0_len;
6fc6879b
JM
1097 u8 pmk_r0_name[WPA_PMK_NAME_LEN];
1098 u8 spa[ETH_ALEN];
1b484d60 1099 int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
17010c38 1100 struct vlan_description *vlan;
3a3e2832 1101 os_time_t expiration; /* 0 for no expiration */
069b4e30
MB
1102 u8 *identity;
1103 size_t identity_len;
1104 u8 *radius_cui;
1105 size_t radius_cui_len;
a6509e85
MB
1106 os_time_t session_timeout; /* 0 for no expiration */
1107 /* TODO: radius_class, EAP type */
6fc6879b
JM
1108 int pmk_r1_pushed;
1109};
1110
1111struct wpa_ft_pmk_r1_sa {
09211c98 1112 struct dl_list list;
a3e18dbb
JM
1113 u8 pmk_r1[PMK_LEN_MAX];
1114 size_t pmk_r1_len;
6fc6879b
JM
1115 u8 pmk_r1_name[WPA_PMK_NAME_LEN];
1116 u8 spa[ETH_ALEN];
1b484d60 1117 int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
17010c38 1118 struct vlan_description *vlan;
069b4e30
MB
1119 u8 *identity;
1120 size_t identity_len;
1121 u8 *radius_cui;
1122 size_t radius_cui_len;
a6509e85
MB
1123 os_time_t session_timeout; /* 0 for no expiration */
1124 /* TODO: radius_class, EAP type */
6fc6879b
JM
1125};
1126
1127struct wpa_ft_pmk_cache {
09211c98
MB
1128 struct dl_list pmk_r0; /* struct wpa_ft_pmk_r0_sa */
1129 struct dl_list pmk_r1; /* struct wpa_ft_pmk_r1_sa */
6fc6879b
JM
1130};
1131
09211c98 1132
3a3e2832
MB
1133static void wpa_ft_expire_pmk_r0(void *eloop_ctx, void *timeout_ctx);
1134static void wpa_ft_expire_pmk_r1(void *eloop_ctx, void *timeout_ctx);
1135
1136
09211c98
MB
1137static void wpa_ft_free_pmk_r0(struct wpa_ft_pmk_r0_sa *r0)
1138{
1139 if (!r0)
1140 return;
1141
1142 dl_list_del(&r0->list);
3a3e2832 1143 eloop_cancel_timeout(wpa_ft_expire_pmk_r0, r0, NULL);
09211c98 1144
a3e18dbb 1145 os_memset(r0->pmk_r0, 0, PMK_LEN_MAX);
17010c38 1146 os_free(r0->vlan);
069b4e30
MB
1147 os_free(r0->identity);
1148 os_free(r0->radius_cui);
09211c98
MB
1149 os_free(r0);
1150}
1151
1152
3a3e2832
MB
1153static void wpa_ft_expire_pmk_r0(void *eloop_ctx, void *timeout_ctx)
1154{
1155 struct wpa_ft_pmk_r0_sa *r0 = eloop_ctx;
1156 struct os_reltime now;
1157 int expires_in;
a6509e85 1158 int session_timeout;
3a3e2832
MB
1159
1160 os_get_reltime(&now);
1161
1162 if (!r0)
1163 return;
1164
1165 expires_in = r0->expiration - now.sec;
a6509e85
MB
1166 session_timeout = r0->session_timeout - now.sec;
1167 /* conditions to remove from cache:
1168 * a) r0->expiration is set and hit
1169 * -or-
1170 * b) r0->session_timeout is set and hit
1171 */
1172 if ((!r0->expiration || expires_in > 0) &&
1173 (!r0->session_timeout || session_timeout > 0)) {
3a3e2832 1174 wpa_printf(MSG_ERROR,
a6509e85
MB
1175 "FT: %s() called for non-expired entry %p",
1176 __func__, r0);
3a3e2832 1177 eloop_cancel_timeout(wpa_ft_expire_pmk_r0, r0, NULL);
a6509e85
MB
1178 if (r0->expiration && expires_in > 0)
1179 eloop_register_timeout(expires_in + 1, 0,
1180 wpa_ft_expire_pmk_r0, r0, NULL);
1181 if (r0->session_timeout && session_timeout > 0)
1182 eloop_register_timeout(session_timeout + 1, 0,
1183 wpa_ft_expire_pmk_r0, r0, NULL);
3a3e2832
MB
1184 return;
1185 }
1186
1187 wpa_ft_free_pmk_r0(r0);
1188}
1189
1190
09211c98
MB
1191static void wpa_ft_free_pmk_r1(struct wpa_ft_pmk_r1_sa *r1)
1192{
1193 if (!r1)
1194 return;
1195
1196 dl_list_del(&r1->list);
3a3e2832 1197 eloop_cancel_timeout(wpa_ft_expire_pmk_r1, r1, NULL);
09211c98 1198
a3e18dbb 1199 os_memset(r1->pmk_r1, 0, PMK_LEN_MAX);
17010c38 1200 os_free(r1->vlan);
069b4e30
MB
1201 os_free(r1->identity);
1202 os_free(r1->radius_cui);
09211c98
MB
1203 os_free(r1);
1204}
1205
1206
3a3e2832
MB
1207static void wpa_ft_expire_pmk_r1(void *eloop_ctx, void *timeout_ctx)
1208{
1209 struct wpa_ft_pmk_r1_sa *r1 = eloop_ctx;
1210
1211 wpa_ft_free_pmk_r1(r1);
1212}
1213
1214
6fc6879b
JM
1215struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void)
1216{
1217 struct wpa_ft_pmk_cache *cache;
1218
1219 cache = os_zalloc(sizeof(*cache));
09211c98
MB
1220 if (cache) {
1221 dl_list_init(&cache->pmk_r0);
1222 dl_list_init(&cache->pmk_r1);
1223 }
6fc6879b
JM
1224
1225 return cache;
1226}
1227
1228
1229void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache)
1230{
1231 struct wpa_ft_pmk_r0_sa *r0, *r0prev;
1232 struct wpa_ft_pmk_r1_sa *r1, *r1prev;
1233
09211c98
MB
1234 dl_list_for_each_safe(r0, r0prev, &cache->pmk_r0,
1235 struct wpa_ft_pmk_r0_sa, list)
1236 wpa_ft_free_pmk_r0(r0);
6fc6879b 1237
09211c98
MB
1238 dl_list_for_each_safe(r1, r1prev, &cache->pmk_r1,
1239 struct wpa_ft_pmk_r1_sa, list)
1240 wpa_ft_free_pmk_r1(r1);
6fc6879b
JM
1241
1242 os_free(cache);
1243}
1244
1245
89dea17e
MB
1246static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
1247 const u8 *spa, const u8 *pmk_r0,
a3e18dbb 1248 size_t pmk_r0_len,
3a3e2832 1249 const u8 *pmk_r0_name, int pairwise,
17010c38 1250 const struct vlan_description *vlan,
a6509e85 1251 int expires_in, int session_timeout,
069b4e30
MB
1252 const u8 *identity, size_t identity_len,
1253 const u8 *radius_cui, size_t radius_cui_len)
6fc6879b
JM
1254{
1255 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
1256 struct wpa_ft_pmk_r0_sa *r0;
3a3e2832 1257 struct os_reltime now;
6fc6879b 1258
3a3e2832
MB
1259 /* TODO: add limit on number of entries in cache */
1260 os_get_reltime(&now);
6fc6879b
JM
1261
1262 r0 = os_zalloc(sizeof(*r0));
1263 if (r0 == NULL)
1264 return -1;
1265
a3e18dbb
JM
1266 os_memcpy(r0->pmk_r0, pmk_r0, pmk_r0_len);
1267 r0->pmk_r0_len = pmk_r0_len;
6fc6879b
JM
1268 os_memcpy(r0->pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
1269 os_memcpy(r0->spa, spa, ETH_ALEN);
1b484d60 1270 r0->pairwise = pairwise;
3a3e2832
MB
1271 if (expires_in > 0)
1272 r0->expiration = now.sec + expires_in;
17010c38
MB
1273 if (vlan && vlan->notempty) {
1274 r0->vlan = os_zalloc(sizeof(*vlan));
1275 if (!r0->vlan) {
1276 bin_clear_free(r0, sizeof(*r0));
1277 return -1;
1278 }
1279 *r0->vlan = *vlan;
1280 }
069b4e30
MB
1281 if (identity) {
1282 r0->identity = os_malloc(identity_len);
1283 if (r0->identity) {
1284 os_memcpy(r0->identity, identity, identity_len);
1285 r0->identity_len = identity_len;
1286 }
1287 }
1288 if (radius_cui) {
1289 r0->radius_cui = os_malloc(radius_cui_len);
1290 if (r0->radius_cui) {
1291 os_memcpy(r0->radius_cui, radius_cui, radius_cui_len);
1292 r0->radius_cui_len = radius_cui_len;
1293 }
1294 }
a6509e85
MB
1295 if (session_timeout > 0)
1296 r0->session_timeout = now.sec + session_timeout;
6fc6879b 1297
09211c98 1298 dl_list_add(&cache->pmk_r0, &r0->list);
3a3e2832
MB
1299 if (expires_in > 0)
1300 eloop_register_timeout(expires_in + 1, 0, wpa_ft_expire_pmk_r0,
1301 r0, NULL);
a6509e85
MB
1302 if (session_timeout > 0)
1303 eloop_register_timeout(session_timeout + 1, 0,
1304 wpa_ft_expire_pmk_r0, r0, NULL);
6fc6879b
JM
1305
1306 return 0;
1307}
1308
1309
1310static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
1311 const u8 *spa, const u8 *pmk_r0_name,
245fc96e 1312 const struct wpa_ft_pmk_r0_sa **r0_out)
6fc6879b
JM
1313{
1314 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
1315 struct wpa_ft_pmk_r0_sa *r0;
3a3e2832 1316 struct os_reltime now;
6fc6879b 1317
3a3e2832 1318 os_get_reltime(&now);
09211c98 1319 dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) {
6fc6879b 1320 if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
870834a1
JM
1321 os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
1322 WPA_PMK_NAME_LEN) == 0) {
245fc96e 1323 *r0_out = r0;
6fc6879b
JM
1324 return 0;
1325 }
6fc6879b
JM
1326 }
1327
245fc96e 1328 *r0_out = NULL;
6fc6879b
JM
1329 return -1;
1330}
1331
1332
1333static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
1334 const u8 *spa, const u8 *pmk_r1,
a3e18dbb 1335 size_t pmk_r1_len,
3a3e2832 1336 const u8 *pmk_r1_name, int pairwise,
17010c38 1337 const struct vlan_description *vlan,
a6509e85 1338 int expires_in, int session_timeout,
069b4e30
MB
1339 const u8 *identity, size_t identity_len,
1340 const u8 *radius_cui, size_t radius_cui_len)
6fc6879b
JM
1341{
1342 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
3a3e2832 1343 int max_expires_in = wpa_auth->conf.r1_max_key_lifetime;
6fc6879b 1344 struct wpa_ft_pmk_r1_sa *r1;
a6509e85 1345 struct os_reltime now;
6fc6879b 1346
3a3e2832 1347 /* TODO: limit on number of entries in cache */
a6509e85 1348 os_get_reltime(&now);
3a3e2832
MB
1349
1350 if (max_expires_in && (max_expires_in < expires_in || expires_in == 0))
1351 expires_in = max_expires_in;
6fc6879b
JM
1352
1353 r1 = os_zalloc(sizeof(*r1));
1354 if (r1 == NULL)
1355 return -1;
1356
a3e18dbb
JM
1357 os_memcpy(r1->pmk_r1, pmk_r1, pmk_r1_len);
1358 r1->pmk_r1_len = pmk_r1_len;
6fc6879b
JM
1359 os_memcpy(r1->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
1360 os_memcpy(r1->spa, spa, ETH_ALEN);
1b484d60 1361 r1->pairwise = pairwise;
17010c38
MB
1362 if (vlan && vlan->notempty) {
1363 r1->vlan = os_zalloc(sizeof(*vlan));
1364 if (!r1->vlan) {
1365 bin_clear_free(r1, sizeof(*r1));
1366 return -1;
1367 }
1368 *r1->vlan = *vlan;
1369 }
069b4e30
MB
1370 if (identity) {
1371 r1->identity = os_malloc(identity_len);
1372 if (r1->identity) {
1373 os_memcpy(r1->identity, identity, identity_len);
1374 r1->identity_len = identity_len;
1375 }
1376 }
1377 if (radius_cui) {
1378 r1->radius_cui = os_malloc(radius_cui_len);
1379 if (r1->radius_cui) {
1380 os_memcpy(r1->radius_cui, radius_cui, radius_cui_len);
1381 r1->radius_cui_len = radius_cui_len;
1382 }
1383 }
a6509e85
MB
1384 if (session_timeout > 0)
1385 r1->session_timeout = now.sec + session_timeout;
6fc6879b 1386
09211c98 1387 dl_list_add(&cache->pmk_r1, &r1->list);
6fc6879b 1388
3a3e2832
MB
1389 if (expires_in > 0)
1390 eloop_register_timeout(expires_in + 1, 0, wpa_ft_expire_pmk_r1,
1391 r1, NULL);
a6509e85
MB
1392 if (session_timeout > 0)
1393 eloop_register_timeout(session_timeout + 1, 0,
1394 wpa_ft_expire_pmk_r1, r1, NULL);
3a3e2832 1395
6fc6879b
JM
1396 return 0;
1397}
1398
1399
1400static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
1401 const u8 *spa, const u8 *pmk_r1_name,
a3e18dbb 1402 u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise,
069b4e30
MB
1403 struct vlan_description *vlan,
1404 const u8 **identity, size_t *identity_len,
a6509e85
MB
1405 const u8 **radius_cui, size_t *radius_cui_len,
1406 int *session_timeout)
6fc6879b
JM
1407{
1408 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
1409 struct wpa_ft_pmk_r1_sa *r1;
a6509e85
MB
1410 struct os_reltime now;
1411
1412 os_get_reltime(&now);
6fc6879b 1413
09211c98 1414 dl_list_for_each(r1, &cache->pmk_r1, struct wpa_ft_pmk_r1_sa, list) {
6fc6879b 1415 if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&
870834a1
JM
1416 os_memcmp_const(r1->pmk_r1_name, pmk_r1_name,
1417 WPA_PMK_NAME_LEN) == 0) {
a3e18dbb
JM
1418 os_memcpy(pmk_r1, r1->pmk_r1, r1->pmk_r1_len);
1419 *pmk_r1_len = r1->pmk_r1_len;
1b484d60
JM
1420 if (pairwise)
1421 *pairwise = r1->pairwise;
17010c38
MB
1422 if (vlan && r1->vlan)
1423 *vlan = *r1->vlan;
1424 if (vlan && !r1->vlan)
1425 os_memset(vlan, 0, sizeof(*vlan));
069b4e30
MB
1426 if (identity && identity_len) {
1427 *identity = r1->identity;
1428 *identity_len = r1->identity_len;
1429 }
1430 if (radius_cui && radius_cui_len) {
1431 *radius_cui = r1->radius_cui;
1432 *radius_cui_len = r1->radius_cui_len;
1433 }
a6509e85
MB
1434 if (session_timeout && r1->session_timeout > now.sec)
1435 *session_timeout = r1->session_timeout -
1436 now.sec;
1437 else if (session_timeout && r1->session_timeout)
1438 *session_timeout = 1;
1439 else
1440 *session_timeout = 0;
6fc6879b
JM
1441 return 0;
1442 }
6fc6879b
JM
1443 }
1444
1445 return -1;
1446}
1447
1448
eefe8630
MB
1449static int wpa_ft_rrb_init_r0kh_seq(struct ft_remote_r0kh *r0kh)
1450{
1451 if (r0kh->seq)
1452 return 0;
1453
1454 r0kh->seq = os_zalloc(sizeof(*r0kh->seq));
1455 if (!r0kh->seq) {
1456 wpa_printf(MSG_DEBUG, "FT: Failed to allocate r0kh->seq");
1457 return -1;
1458 }
1459
1460 dl_list_init(&r0kh->seq->rx.queue);
1461
1462 return 0;
1463}
1464
1465
245fc96e 1466static void wpa_ft_rrb_lookup_r0kh(struct wpa_authenticator *wpa_auth,
eefe8630 1467 const u8 *f_r0kh_id, size_t f_r0kh_id_len,
3a46cf93
MB
1468 struct ft_remote_r0kh **r0kh_out,
1469 struct ft_remote_r0kh **r0kh_wildcard)
245fc96e
MB
1470{
1471 struct ft_remote_r0kh *r0kh;
1472
3a46cf93 1473 *r0kh_wildcard = NULL;
eefe8630
MB
1474 *r0kh_out = NULL;
1475
3a46cf93
MB
1476 if (wpa_auth->conf.r0kh_list)
1477 r0kh = *wpa_auth->conf.r0kh_list;
1478 else
1479 r0kh = NULL;
1480 for (; r0kh; r0kh = r0kh->next) {
1481 if (r0kh->id_len == 1 && r0kh->id[0] == '*')
1482 *r0kh_wildcard = r0kh;
eefe8630 1483 if (f_r0kh_id && r0kh->id_len == f_r0kh_id_len &&
3a46cf93 1484 os_memcmp_const(f_r0kh_id, r0kh->id, f_r0kh_id_len) == 0)
eefe8630 1485 *r0kh_out = r0kh;
245fc96e
MB
1486 }
1487
3a46cf93 1488 if (!*r0kh_out && !*r0kh_wildcard)
245fc96e
MB
1489 wpa_printf(MSG_DEBUG, "FT: No matching R0KH found");
1490
eefe8630
MB
1491 if (*r0kh_out && wpa_ft_rrb_init_r0kh_seq(*r0kh_out) < 0)
1492 *r0kh_out = NULL;
1493}
1494
1495
1496static int wpa_ft_rrb_init_r1kh_seq(struct ft_remote_r1kh *r1kh)
1497{
1498 if (r1kh->seq)
1499 return 0;
1500
1501 r1kh->seq = os_zalloc(sizeof(*r1kh->seq));
1502 if (!r1kh->seq) {
1503 wpa_printf(MSG_DEBUG, "FT: Failed to allocate r1kh->seq");
1504 return -1;
1505 }
1506
1507 dl_list_init(&r1kh->seq->rx.queue);
1508
1509 return 0;
245fc96e
MB
1510}
1511
1512
1513static void wpa_ft_rrb_lookup_r1kh(struct wpa_authenticator *wpa_auth,
eefe8630 1514 const u8 *f_r1kh_id,
3a46cf93
MB
1515 struct ft_remote_r1kh **r1kh_out,
1516 struct ft_remote_r1kh **r1kh_wildcard)
245fc96e
MB
1517{
1518 struct ft_remote_r1kh *r1kh;
1519
3a46cf93 1520 *r1kh_wildcard = NULL;
eefe8630
MB
1521 *r1kh_out = NULL;
1522
3a46cf93
MB
1523 if (wpa_auth->conf.r1kh_list)
1524 r1kh = *wpa_auth->conf.r1kh_list;
1525 else
1526 r1kh = NULL;
1527 for (; r1kh; r1kh = r1kh->next) {
1528 if (is_zero_ether_addr(r1kh->addr) &&
1529 is_zero_ether_addr(r1kh->id))
1530 *r1kh_wildcard = r1kh;
245fc96e 1531 if (f_r1kh_id &&
3a46cf93 1532 os_memcmp_const(r1kh->id, f_r1kh_id, FT_R1KH_ID_LEN) == 0)
eefe8630 1533 *r1kh_out = r1kh;
245fc96e
MB
1534 }
1535
3a46cf93 1536 if (!*r1kh_out && !*r1kh_wildcard)
245fc96e
MB
1537 wpa_printf(MSG_DEBUG, "FT: No matching R1KH found");
1538
eefe8630
MB
1539 if (*r1kh_out && wpa_ft_rrb_init_r1kh_seq(*r1kh_out) < 0)
1540 *r1kh_out = NULL;
245fc96e
MB
1541}
1542
1543
1544static int wpa_ft_rrb_check_r0kh(struct wpa_authenticator *wpa_auth,
1545 const u8 *f_r0kh_id, size_t f_r0kh_id_len)
1546{
1547 if (f_r0kh_id_len != wpa_auth->conf.r0_key_holder_len ||
1548 os_memcmp_const(f_r0kh_id, wpa_auth->conf.r0_key_holder,
1549 f_r0kh_id_len) != 0)
1550 return -1;
1551
1552 return 0;
1553}
1554
1555
1556static int wpa_ft_rrb_check_r1kh(struct wpa_authenticator *wpa_auth,
1557 const u8 *f_r1kh_id)
1558{
1559 if (os_memcmp_const(f_r1kh_id, wpa_auth->conf.r1_key_holder,
1560 FT_R1KH_ID_LEN) != 0)
1561 return -1;
1562
1563 return 0;
1564}
1565
1566
3a46cf93
MB
1567static void wpa_ft_rrb_del_r0kh(void *eloop_ctx, void *timeout_ctx)
1568{
1569 struct wpa_authenticator *wpa_auth = eloop_ctx;
1570 struct ft_remote_r0kh *r0kh, *prev = NULL;
1571
1572 if (!wpa_auth->conf.r0kh_list)
1573 return;
1574
1575 for (r0kh = *wpa_auth->conf.r0kh_list; r0kh; r0kh = r0kh->next) {
1576 if (r0kh == timeout_ctx)
1577 break;
1578 prev = r0kh;
1579 }
1580 if (!r0kh)
1581 return;
1582 if (prev)
1583 prev->next = r0kh->next;
1584 else
1585 *wpa_auth->conf.r0kh_list = r0kh->next;
1586 if (r0kh->seq)
1587 wpa_ft_rrb_seq_flush(wpa_auth, r0kh->seq, 0);
1588 os_free(r0kh->seq);
1589 os_free(r0kh);
1590}
1591
1592
1593static void wpa_ft_rrb_r0kh_replenish(struct wpa_authenticator *wpa_auth,
1594 struct ft_remote_r0kh *r0kh, int timeout)
1595{
1596 if (timeout > 0)
1597 eloop_replenish_timeout(timeout, 0, wpa_ft_rrb_del_r0kh,
1598 wpa_auth, r0kh);
1599}
1600
1601
1602static void wpa_ft_rrb_r0kh_timeout(struct wpa_authenticator *wpa_auth,
1603 struct ft_remote_r0kh *r0kh, int timeout)
1604{
1605 eloop_cancel_timeout(wpa_ft_rrb_del_r0kh, wpa_auth, r0kh);
1606
1607 if (timeout > 0)
1608 eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r0kh,
1609 wpa_auth, r0kh);
1610}
1611
1612
1613static struct ft_remote_r0kh *
1614wpa_ft_rrb_add_r0kh(struct wpa_authenticator *wpa_auth,
1615 struct ft_remote_r0kh *r0kh_wildcard,
1616 const u8 *src_addr, const u8 *r0kh_id, size_t id_len,
1617 int timeout)
1618{
1619 struct ft_remote_r0kh *r0kh;
1620
1621 if (!wpa_auth->conf.r0kh_list)
1622 return NULL;
1623
1624 r0kh = os_zalloc(sizeof(*r0kh));
1625 if (!r0kh)
1626 return NULL;
1627
1628 if (src_addr)
1629 os_memcpy(r0kh->addr, src_addr, sizeof(r0kh->addr));
1630
1631 if (id_len > FT_R0KH_ID_MAX_LEN)
1632 id_len = FT_R0KH_ID_MAX_LEN;
1633 os_memcpy(r0kh->id, r0kh_id, id_len);
1634 r0kh->id_len = id_len;
1635
1636 os_memcpy(r0kh->key, r0kh_wildcard->key, sizeof(r0kh->key));
1637
1638 r0kh->next = *wpa_auth->conf.r0kh_list;
1639 *wpa_auth->conf.r0kh_list = r0kh;
1640
1641 if (timeout > 0)
1642 eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r0kh,
1643 wpa_auth, r0kh);
1644
1645 if (wpa_ft_rrb_init_r0kh_seq(r0kh) < 0)
1646 return NULL;
1647
1648 return r0kh;
1649}
1650
1651
1652static void wpa_ft_rrb_del_r1kh(void *eloop_ctx, void *timeout_ctx)
1653{
1654 struct wpa_authenticator *wpa_auth = eloop_ctx;
1655 struct ft_remote_r1kh *r1kh, *prev = NULL;
1656
1657 if (!wpa_auth->conf.r1kh_list)
1658 return;
1659
1660 for (r1kh = *wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) {
1661 if (r1kh == timeout_ctx)
1662 break;
1663 prev = r1kh;
1664 }
1665 if (!r1kh)
1666 return;
1667 if (prev)
1668 prev->next = r1kh->next;
1669 else
1670 *wpa_auth->conf.r1kh_list = r1kh->next;
1671 if (r1kh->seq)
1672 wpa_ft_rrb_seq_flush(wpa_auth, r1kh->seq, 0);
1673 os_free(r1kh->seq);
1674 os_free(r1kh);
1675}
1676
1677
1678static void wpa_ft_rrb_r1kh_replenish(struct wpa_authenticator *wpa_auth,
1679 struct ft_remote_r1kh *r1kh, int timeout)
1680{
1681 if (timeout > 0)
1682 eloop_replenish_timeout(timeout, 0, wpa_ft_rrb_del_r1kh,
1683 wpa_auth, r1kh);
1684}
1685
1686
1687static struct ft_remote_r1kh *
1688wpa_ft_rrb_add_r1kh(struct wpa_authenticator *wpa_auth,
1689 struct ft_remote_r1kh *r1kh_wildcard,
1690 const u8 *src_addr, const u8 *r1kh_id, int timeout)
1691{
1692 struct ft_remote_r1kh *r1kh;
1693
1694 if (!wpa_auth->conf.r1kh_list)
1695 return NULL;
1696
1697 r1kh = os_zalloc(sizeof(*r1kh));
1698 if (!r1kh)
1699 return NULL;
1700
1701 os_memcpy(r1kh->addr, src_addr, sizeof(r1kh->addr));
1702 os_memcpy(r1kh->id, r1kh_id, sizeof(r1kh->id));
1703 os_memcpy(r1kh->key, r1kh_wildcard->key, sizeof(r1kh->key));
1704 r1kh->next = *wpa_auth->conf.r1kh_list;
1705 *wpa_auth->conf.r1kh_list = r1kh;
1706
1707 if (timeout > 0)
1708 eloop_register_timeout(timeout, 0, wpa_ft_rrb_del_r1kh,
1709 wpa_auth, r1kh);
1710
1711 if (wpa_ft_rrb_init_r1kh_seq(r1kh) < 0)
1712 return NULL;
1713
1714 return r1kh;
1715}
1716
1717
1718void wpa_ft_sta_deinit(struct wpa_state_machine *sm)
1719{
1720 eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
1721}
1722
1723
eefe8630
MB
1724static void wpa_ft_deinit_seq(struct wpa_authenticator *wpa_auth)
1725{
1726 struct ft_remote_r0kh *r0kh;
1727 struct ft_remote_r1kh *r1kh;
1728
1729 eloop_cancel_timeout(wpa_ft_rrb_seq_timeout, wpa_auth, ELOOP_ALL_CTX);
1730
3a46cf93
MB
1731 if (wpa_auth->conf.r0kh_list)
1732 r0kh = *wpa_auth->conf.r0kh_list;
1733 else
1734 r0kh = NULL;
1735 for (; r0kh; r0kh = r0kh->next) {
eefe8630
MB
1736 if (!r0kh->seq)
1737 continue;
1738 wpa_ft_rrb_seq_flush(wpa_auth, r0kh->seq, 0);
1739 os_free(r0kh->seq);
1740 r0kh->seq = NULL;
1741 }
1742
3a46cf93
MB
1743 if (wpa_auth->conf.r1kh_list)
1744 r1kh = *wpa_auth->conf.r1kh_list;
1745 else
1746 r1kh = NULL;
1747 for (; r1kh; r1kh = r1kh->next) {
eefe8630
MB
1748 if (!r1kh->seq)
1749 continue;
1750 wpa_ft_rrb_seq_flush(wpa_auth, r1kh->seq, 0);
1751 os_free(r1kh->seq);
1752 r1kh->seq = NULL;
1753 }
1754}
1755
1756
3a46cf93
MB
1757static void wpa_ft_deinit_rkh_tmp(struct wpa_authenticator *wpa_auth)
1758{
1759 struct ft_remote_r0kh *r0kh, *r0kh_next, *r0kh_prev = NULL;
1760 struct ft_remote_r1kh *r1kh, *r1kh_next, *r1kh_prev = NULL;
1761
1762 if (wpa_auth->conf.r0kh_list)
1763 r0kh = *wpa_auth->conf.r0kh_list;
1764 else
1765 r0kh = NULL;
1766 while (r0kh) {
1767 r0kh_next = r0kh->next;
1768 if (eloop_cancel_timeout(wpa_ft_rrb_del_r0kh, wpa_auth,
1769 r0kh) > 0) {
1770 if (r0kh_prev)
1771 r0kh_prev->next = r0kh_next;
1772 else
1773 *wpa_auth->conf.r0kh_list = r0kh_next;
1774 os_free(r0kh);
1775 } else {
1776 r0kh_prev = r0kh;
1777 }
1778 r0kh = r0kh_next;
1779 }
1780
1781 if (wpa_auth->conf.r1kh_list)
1782 r1kh = *wpa_auth->conf.r1kh_list;
1783 else
1784 r1kh = NULL;
1785 while (r1kh) {
1786 r1kh_next = r1kh->next;
1787 if (eloop_cancel_timeout(wpa_ft_rrb_del_r1kh, wpa_auth,
1788 r1kh) > 0) {
1789 if (r1kh_prev)
1790 r1kh_prev->next = r1kh_next;
1791 else
1792 *wpa_auth->conf.r1kh_list = r1kh_next;
1793 os_free(r1kh);
1794 } else {
1795 r1kh_prev = r1kh;
1796 }
1797 r1kh = r1kh_next;
1798 }
1799}
1800
1801
eefe8630
MB
1802void wpa_ft_deinit(struct wpa_authenticator *wpa_auth)
1803{
1804 wpa_ft_deinit_seq(wpa_auth);
3a46cf93
MB
1805 wpa_ft_deinit_rkh_tmp(wpa_auth);
1806}
1807
1808
1809static void wpa_ft_block_r0kh(struct wpa_authenticator *wpa_auth,
1810 const u8 *f_r0kh_id, size_t f_r0kh_id_len)
1811{
1812 struct ft_remote_r0kh *r0kh, *r0kh_wildcard;
1813
1814 if (!wpa_auth->conf.rkh_neg_timeout)
1815 return;
1816
1817 wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len,
1818 &r0kh, &r0kh_wildcard);
1819
1820 if (!r0kh_wildcard) {
1821 /* r0kh removed after neg_timeout and might need re-adding */
1822 return;
1823 }
1824
1825 wpa_hexdump(MSG_DEBUG, "FT: Blacklist R0KH-ID",
1826 f_r0kh_id, f_r0kh_id_len);
1827
1828 if (r0kh) {
1829 wpa_ft_rrb_r0kh_timeout(wpa_auth, r0kh,
1830 wpa_auth->conf.rkh_neg_timeout);
1831 os_memset(r0kh->addr, 0, ETH_ALEN);
1832 } else
1833 wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, NULL, f_r0kh_id,
1834 f_r0kh_id_len,
1835 wpa_auth->conf.rkh_neg_timeout);
1836}
1837
1838
1839static void wpa_ft_expire_pull(void *eloop_ctx, void *timeout_ctx)
1840{
1841 struct wpa_state_machine *sm = eloop_ctx;
1842
1843 wpa_printf(MSG_DEBUG, "FT: Timeout pending pull request for " MACSTR,
1844 MAC2STR(sm->addr));
1845 if (sm->ft_pending_pull_left_retries <= 0)
1846 wpa_ft_block_r0kh(sm->wpa_auth, sm->r0kh_id, sm->r0kh_id_len);
1847
1848 /* cancel multiple timeouts */
1849 eloop_cancel_timeout(wpa_ft_expire_pull, sm, NULL);
1850 ft_finish_pull(sm);
eefe8630
MB
1851}
1852
1853
692ec305
JM
1854static int wpa_ft_pull_pmk_r1(struct wpa_state_machine *sm,
1855 const u8 *ies, size_t ies_len,
1856 const u8 *pmk_r0_name)
6fc6879b 1857{
3a46cf93 1858 struct ft_remote_r0kh *r0kh, *r0kh_wildcard;
245fc96e 1859 u8 *packet = NULL;
eefe8630 1860 const u8 *key, *f_r1kh_id = sm->wpa_auth->conf.r1_key_holder;
245fc96e 1861 size_t packet_len, key_len;
eefe8630 1862 struct ft_rrb_seq f_seq;
3a46cf93
MB
1863 int tsecs, tusecs, first;
1864 struct wpabuf *ft_pending_req_ies;
1865 int r0kh_timeout;
245fc96e
MB
1866 struct tlv_list req_enc[] = {
1867 { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN,
1868 .data = pmk_r0_name },
1869 { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN,
1870 .data = sm->addr },
1871 { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
1872 };
1873 struct tlv_list req_auth[] = {
1874 { .type = FT_RRB_NONCE, .len = FT_RRB_NONCE_LEN,
1875 .data = sm->ft_pending_pull_nonce },
eefe8630
MB
1876 { .type = FT_RRB_SEQ, .len = sizeof(f_seq),
1877 .data = (u8 *) &f_seq },
245fc96e
MB
1878 { .type = FT_RRB_R0KH_ID, .len = sm->r0kh_id_len,
1879 .data = sm->r0kh_id },
1880 { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
eefe8630 1881 .data = f_r1kh_id },
245fc96e
MB
1882 { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
1883 };
1884
3a46cf93
MB
1885 if (sm->ft_pending_pull_left_retries <= 0)
1886 return -1;
1887 first = sm->ft_pending_pull_left_retries ==
1888 sm->wpa_auth->conf.rkh_pull_retries;
1889 sm->ft_pending_pull_left_retries--;
1890
eefe8630 1891 wpa_ft_rrb_lookup_r0kh(sm->wpa_auth, sm->r0kh_id, sm->r0kh_id_len,
3a46cf93
MB
1892 &r0kh, &r0kh_wildcard);
1893
1894 /* Keep r0kh sufficiently long in the list for seq num check */
1895 r0kh_timeout = sm->wpa_auth->conf.rkh_pull_timeout / 1000 +
1896 1 + ftRRBseqTimeout;
1897 if (r0kh) {
1898 wpa_ft_rrb_r0kh_replenish(sm->wpa_auth, r0kh, r0kh_timeout);
1899 } else if (r0kh_wildcard) {
1900 wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
1901 /* r0kh->addr: updated by SEQ_RESP and wpa_ft_expire_pull */
1902 r0kh = wpa_ft_rrb_add_r0kh(sm->wpa_auth, r0kh_wildcard,
1903 r0kh_wildcard->addr,
1904 sm->r0kh_id, sm->r0kh_id_len,
1905 r0kh_timeout);
1906 }
692ec305
JM
1907 if (r0kh == NULL) {
1908 wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
1909 sm->r0kh_id, sm->r0kh_id_len);
6fc6879b 1910 return -1;
692ec305 1911 }
3a46cf93
MB
1912 if (is_zero_ether_addr(r0kh->addr)) {
1913 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID is blacklisted",
1914 sm->r0kh_id, sm->r0kh_id_len);
1915 return -1;
1916 }
1dc0945c
JM
1917 if (os_memcmp(r0kh->addr, sm->wpa_auth->addr, ETH_ALEN) == 0) {
1918 wpa_printf(MSG_DEBUG,
1919 "FT: R0KH-ID points to self - no matching key available");
1920 return -1;
1921 }
eefe8630 1922
245fc96e
MB
1923 key = r0kh->key;
1924 key_len = sizeof(r0kh->key);
6fc6879b
JM
1925
1926 wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
1927 "address " MACSTR, MAC2STR(r0kh->addr));
1928
eefe8630
MB
1929 if (r0kh->seq->rx.num_last == 0) {
1930 /* A sequence request will be sent out anyway when pull
1931 * response is received. Send it out now to avoid one RTT. */
1932 wpa_ft_rrb_seq_req(sm->wpa_auth, r0kh->seq, r0kh->addr,
1933 r0kh->id, r0kh->id_len, f_r1kh_id, key,
1934 key_len, NULL, 0, NULL, 0, NULL);
1935 }
1936
3a46cf93
MB
1937 if (first &&
1938 random_get_bytes(sm->ft_pending_pull_nonce, FT_RRB_NONCE_LEN) < 0) {
6fc6879b
JM
1939 wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
1940 "nonce");
1941 return -1;
1942 }
6fc6879b 1943
eefe8630
MB
1944 if (wpa_ft_new_seq(r0kh->seq, &f_seq) < 0) {
1945 wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
1946 return -1;
1947 }
1948
17010c38 1949 if (wpa_ft_rrb_build(key, key_len, req_enc, NULL, req_auth, NULL,
245fc96e
MB
1950 sm->wpa_auth->addr, FT_PACKET_R0KH_R1KH_PULL,
1951 &packet, &packet_len) < 0)
6fc6879b
JM
1952 return -1;
1953
3a46cf93 1954 ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
692ec305 1955 wpabuf_free(sm->ft_pending_req_ies);
3a46cf93 1956 sm->ft_pending_req_ies = ft_pending_req_ies;
245fc96e
MB
1957 if (!sm->ft_pending_req_ies) {
1958 os_free(packet);
692ec305 1959 return -1;
245fc96e 1960 }
692ec305 1961
3a46cf93
MB
1962 tsecs = sm->wpa_auth->conf.rkh_pull_timeout / 1000;
1963 tusecs = (sm->wpa_auth->conf.rkh_pull_timeout % 1000) * 1000;
1964 eloop_register_timeout(tsecs, tusecs, wpa_ft_expire_pull, sm, NULL);
1965
50bd8e0a 1966 wpa_ft_rrb_oui_send(sm->wpa_auth, r0kh->addr, FT_PACKET_R0KH_R1KH_PULL,
245fc96e
MB
1967 packet, packet_len);
1968
1969 os_free(packet);
6fc6879b
JM
1970
1971 return 0;
1972}
1973
1974
89dea17e
MB
1975int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm,
1976 const u8 *pmk_r0, const u8 *pmk_r0_name)
1977{
3a3e2832 1978 int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
17010c38 1979 struct vlan_description vlan;
069b4e30
MB
1980 const u8 *identity, *radius_cui;
1981 size_t identity_len, radius_cui_len;
a6509e85 1982 int session_timeout;
994eac7e
JM
1983 size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ?
1984 SHA384_MAC_LEN : PMK_LEN;
17010c38
MB
1985
1986 if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
1987 wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
1988 MAC2STR(sm->addr));
1989 return -1;
1990 }
3a3e2832 1991
069b4e30
MB
1992 identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
1993 radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr,
1994 &radius_cui);
a6509e85 1995 session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr);
069b4e30 1996
a3e18dbb
JM
1997 return wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
1998 pmk_r0_name, sm->pairwise, &vlan, expires_in,
a6509e85
MB
1999 session_timeout, identity, identity_len,
2000 radius_cui, radius_cui_len);
89dea17e
MB
2001}
2002
2003
6fc6879b 2004int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
98cd3d1c 2005 struct wpa_ptk *ptk)
6fc6879b 2006{
a3e18dbb 2007 u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN];
994eac7e
JM
2008 size_t pmk_r0_len = wpa_key_mgmt_sha384(sm->wpa_key_mgmt) ?
2009 SHA384_MAC_LEN : PMK_LEN;
a3e18dbb
JM
2010 size_t pmk_r1_len = pmk_r0_len;
2011 u8 pmk_r1[PMK_LEN_MAX];
6fc6879b
JM
2012 u8 ptk_name[WPA_PMK_NAME_LEN];
2013 const u8 *mdid = sm->wpa_auth->conf.mobility_domain;
2014 const u8 *r0kh = sm->wpa_auth->conf.r0_key_holder;
2015 size_t r0kh_len = sm->wpa_auth->conf.r0_key_holder_len;
2016 const u8 *r1kh = sm->wpa_auth->conf.r1_key_holder;
2017 const u8 *ssid = sm->wpa_auth->conf.ssid;
2018 size_t ssid_len = sm->wpa_auth->conf.ssid_len;
96590564 2019 int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
3a3e2832 2020 int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
17010c38 2021 struct vlan_description vlan;
069b4e30
MB
2022 const u8 *identity, *radius_cui;
2023 size_t identity_len, radius_cui_len;
a6509e85 2024 int session_timeout;
6fc6879b 2025
6fc6879b
JM
2026 if (sm->xxkey_len == 0) {
2027 wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
2028 "derivation");
2029 return -1;
2030 }
2031
17010c38
MB
2032 if (wpa_ft_get_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
2033 wpa_printf(MSG_DEBUG, "FT: vlan not available for STA " MACSTR,
2034 MAC2STR(sm->addr));
2035 return -1;
2036 }
2037
069b4e30
MB
2038 identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
2039 radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr,
2040 &radius_cui);
a6509e85 2041 session_timeout = wpa_ft_get_session_timeout(sm->wpa_auth, sm->addr);
069b4e30 2042
364c064a
JM
2043 if (wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid,
2044 r0kh, r0kh_len, sm->addr,
994eac7e
JM
2045 pmk_r0, pmk_r0_name,
2046 wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) < 0)
364c064a 2047 return -1;
a3e18dbb 2048 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, pmk_r0_len);
6fc6879b 2049 wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
96590564 2050 if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
a3e18dbb
JM
2051 wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
2052 pmk_r0_name,
a6509e85
MB
2053 sm->pairwise, &vlan, expires_in,
2054 session_timeout, identity, identity_len,
2055 radius_cui, radius_cui_len);
6fc6879b 2056
a3e18dbb 2057 if (wpa_derive_pmk_r1(pmk_r0, pmk_r0_len, pmk_r0_name, r1kh, sm->addr,
364c064a
JM
2058 pmk_r1, sm->pmk_r1_name) < 0)
2059 return -1;
a3e18dbb 2060 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, pmk_r1_len);
26e23750
JM
2061 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
2062 WPA_PMK_NAME_LEN);
96590564 2063 if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
a3e18dbb 2064 wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, pmk_r1_len,
17010c38 2065 sm->pmk_r1_name, sm->pairwise, &vlan,
a6509e85
MB
2066 expires_in, session_timeout, identity,
2067 identity_len, radius_cui, radius_cui_len);
6fc6879b 2068
a3e18dbb
JM
2069 return wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
2070 sm->addr, sm->wpa_auth->addr, sm->pmk_r1_name,
98cd3d1c 2071 ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise);
6fc6879b
JM
2072}
2073
2074
2075static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
2076 const u8 *addr, int idx, u8 *seq)
2077{
cef8fac0 2078 if (wpa_auth->cb->get_seqnum == NULL)
6fc6879b 2079 return -1;
cef8fac0 2080 return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
6fc6879b
JM
2081}
2082
2083
2084static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
2085{
2086 u8 *subelem;
2087 struct wpa_group *gsm = sm->group;
2088 size_t subelem_len, pad_len;
2089 const u8 *key;
2090 size_t key_len;
2091 u8 keybuf[32];
2092
2093 key_len = gsm->GTK_len;
2094 if (key_len > sizeof(keybuf))
2095 return NULL;
2096
2097 /*
2098 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less
2099 * than 16 bytes.
2100 */
2101 pad_len = key_len % 8;
2102 if (pad_len)
2103 pad_len = 8 - pad_len;
2104 if (key_len + pad_len < 16)
2105 pad_len += 8;
5bfc46bb 2106 if (pad_len && key_len < sizeof(keybuf)) {
6fc6879b
JM
2107 os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);
2108 os_memset(keybuf + key_len, 0, pad_len);
2109 keybuf[key_len] = 0xdd;
2110 key_len += pad_len;
2111 key = keybuf;
2112 } else
2113 key = gsm->GTK[gsm->GN - 1];
2114
2115 /*
39eb4d08 2116 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
6fc6879b
JM
2117 * Key[5..32].
2118 */
39eb4d08 2119 subelem_len = 13 + key_len + 8;
6fc6879b
JM
2120 subelem = os_zalloc(subelem_len);
2121 if (subelem == NULL)
2122 return NULL;
2123
2124 subelem[0] = FTIE_SUBELEM_GTK;
39eb4d08
JM
2125 subelem[1] = 11 + key_len + 8;
2126 /* Key ID in B0-B1 of Key Info */
2127 WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
2128 subelem[4] = gsm->GTK_len;
2129 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
98cd3d1c
JM
2130 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, key_len / 8, key,
2131 subelem + 13)) {
6fc6879b
JM
2132 os_free(subelem);
2133 return NULL;
2134 }
2135
2136 *len = subelem_len;
2137 return subelem;
2138}
2139
2140
b27f13ed
JM
2141#ifdef CONFIG_IEEE80211W
2142static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
2143{
2144 u8 *subelem, *pos;
2145 struct wpa_group *gsm = sm->group;
2146 size_t subelem_len;
2147
ff89afb7
JM
2148 /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
2149 * Key[16+8] */
2150 subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8;
b27f13ed
JM
2151 subelem = os_zalloc(subelem_len);
2152 if (subelem == NULL)
2153 return NULL;
2154
2155 pos = subelem;
2156 *pos++ = FTIE_SUBELEM_IGTK;
2157 *pos++ = subelem_len - 2;
2158 WPA_PUT_LE16(pos, gsm->GN_igtk);
2159 pos += 2;
9008a3e4 2160 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
b27f13ed 2161 pos += 6;
ff89afb7 2162 *pos++ = WPA_IGTK_LEN;
98cd3d1c 2163 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, WPA_IGTK_LEN / 8,
b27f13ed
JM
2164 gsm->IGTK[gsm->GN_igtk - 4], pos)) {
2165 os_free(subelem);
2166 return NULL;
2167 }
2168
2169 *len = subelem_len;
2170 return subelem;
2171}
2172#endif /* CONFIG_IEEE80211W */
2173
2174
88b32a99
SP
2175static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
2176 u8 *pos, u8 *end, u8 id, u8 descr_count,
f238cf9f
JM
2177 const u8 *ies, size_t ies_len)
2178{
2179 struct ieee802_11_elems parse;
2180 struct rsn_rdie *rdie;
2181
2182 wpa_printf(MSG_DEBUG, "FT: Resource Request: id=%d descr_count=%d",
2183 id, descr_count);
2184 wpa_hexdump(MSG_MSGDUMP, "FT: Resource descriptor IE(s)",
2185 ies, ies_len);
2186
2187 if (end - pos < (int) sizeof(*rdie)) {
2188 wpa_printf(MSG_ERROR, "FT: Not enough room for response RDIE");
2189 return pos;
2190 }
2191
2192 *pos++ = WLAN_EID_RIC_DATA;
2193 *pos++ = sizeof(*rdie);
2194 rdie = (struct rsn_rdie *) pos;
2195 rdie->id = id;
2196 rdie->descr_count = 0;
2197 rdie->status_code = host_to_le16(WLAN_STATUS_SUCCESS);
2198 pos += sizeof(*rdie);
2199
2200 if (ieee802_11_parse_elems((u8 *) ies, ies_len, &parse, 1) ==
2201 ParseFailed) {
2202 wpa_printf(MSG_DEBUG, "FT: Failed to parse request IEs");
2203 rdie->status_code =
2204 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
2205 return pos;
2206 }
2207
25310368 2208 if (parse.wmm_tspec) {
f238cf9f 2209 struct wmm_tspec_element *tspec;
f238cf9f
JM
2210
2211 if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) {
2212 wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE "
2213 "(%d)", (int) parse.wmm_tspec_len);
2214 rdie->status_code =
2215 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
2216 return pos;
2217 }
2218 if (end - pos < (int) sizeof(*tspec)) {
2219 wpa_printf(MSG_ERROR, "FT: Not enough room for "
2220 "response TSPEC");
2221 rdie->status_code =
2222 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
2223 return pos;
2224 }
2225 tspec = (struct wmm_tspec_element *) pos;
2226 os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
25310368
JM
2227 }
2228
2229#ifdef NEED_AP_MLME
2230 if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
2231 int res;
2232
2233 res = wmm_process_tspec((struct wmm_tspec_element *) pos);
f238cf9f
JM
2234 wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res);
2235 if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS)
2236 rdie->status_code =
2237 host_to_le16(WLAN_STATUS_INVALID_PARAMETERS);
2238 else if (res == WMM_ADDTS_STATUS_REFUSED)
2239 rdie->status_code =
2240 host_to_le16(WLAN_STATUS_REQUEST_DECLINED);
2241 else {
2242 /* TSPEC accepted; include updated TSPEC in response */
2243 rdie->descr_count = 1;
25310368 2244 pos += sizeof(struct wmm_tspec_element);
f238cf9f
JM
2245 }
2246 return pos;
2247 }
fe6bdb77 2248#endif /* NEED_AP_MLME */
f238cf9f 2249
88b32a99 2250 if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
88b32a99
SP
2251 int res;
2252
88b32a99 2253 res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
25310368 2254 sizeof(struct wmm_tspec_element));
88b32a99
SP
2255 if (res >= 0) {
2256 if (res)
2257 rdie->status_code = host_to_le16(res);
2258 else {
2259 /* TSPEC accepted; include updated TSPEC in
2260 * response */
006309b5 2261 rdie->descr_count = 1;
25310368 2262 pos += sizeof(struct wmm_tspec_element);
88b32a99
SP
2263 }
2264 return pos;
2265 }
2266 }
2267
f238cf9f
JM
2268 wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
2269 rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
2270 return pos;
2271}
2272
2273
88b32a99
SP
2274static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
2275 const u8 *ric, size_t ric_len)
f238cf9f
JM
2276{
2277 const u8 *rpos, *start;
2278 const struct rsn_rdie *rdie;
2279
2280 wpa_hexdump(MSG_MSGDUMP, "FT: RIC Request", ric, ric_len);
2281
2282 rpos = ric;
2283 while (rpos + sizeof(*rdie) < ric + ric_len) {
2284 if (rpos[0] != WLAN_EID_RIC_DATA || rpos[1] < sizeof(*rdie) ||
2285 rpos + 2 + rpos[1] > ric + ric_len)
2286 break;
2287 rdie = (const struct rsn_rdie *) (rpos + 2);
2288 rpos += 2 + rpos[1];
2289 start = rpos;
2290
2291 while (rpos + 2 <= ric + ric_len &&
2292 rpos + 2 + rpos[1] <= ric + ric_len) {
2293 if (rpos[0] == WLAN_EID_RIC_DATA)
2294 break;
2295 rpos += 2 + rpos[1];
2296 }
88b32a99 2297 pos = wpa_ft_process_rdie(sm, pos, end, rdie->id,
f238cf9f
JM
2298 rdie->descr_count,
2299 start, rpos - start);
2300 }
2301
2302 return pos;
2303}
2304
2305
6fc6879b 2306u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
f238cf9f
JM
2307 size_t max_len, int auth_alg,
2308 const u8 *req_ies, size_t req_ies_len)
6fc6879b 2309{
738a1cb2
JM
2310 u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
2311 size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
6fc6879b
JM
2312 int res;
2313 struct wpa_auth_config *conf;
2314 struct rsn_ftie *_ftie;
f238cf9f
JM
2315 struct wpa_ft_ies parse;
2316 u8 *ric_start;
6e80516a 2317 u8 *anonce, *snonce;
2f373878
JM
2318 const u8 *kck;
2319 size_t kck_len;
6fc6879b
JM
2320
2321 if (sm == NULL)
2322 return pos;
2323
2324 conf = &sm->wpa_auth->conf;
2325
aa189ac9 2326 if (!wpa_key_mgmt_ft(sm->wpa_key_mgmt))
6fc6879b
JM
2327 return pos;
2328
2329 end = pos + max_len;
2330
738a1cb2
JM
2331 if (auth_alg == WLAN_AUTH_FT) {
2332 /*
2333 * RSN (only present if this is a Reassociation Response and
2334 * part of a fast BSS transition)
2335 */
2336 res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
2337 if (res < 0)
2338 return pos;
2339 rsnie = pos;
2340 rsnie_len = res;
2341 pos += res;
2342 }
6fc6879b
JM
2343
2344 /* Mobility Domain Information */
2345 res = wpa_write_mdie(conf, pos, end - pos);
2346 if (res < 0)
2347 return pos;
2348 mdie = pos;
2349 mdie_len = res;
2350 pos += res;
2351
2352 /* Fast BSS Transition Information */
2353 if (auth_alg == WLAN_AUTH_FT) {
2354 subelem = wpa_ft_gtk_subelem(sm, &subelem_len);
2355 r0kh_id = sm->r0kh_id;
2356 r0kh_id_len = sm->r0kh_id_len;
6e80516a
JM
2357 anonce = sm->ANonce;
2358 snonce = sm->SNonce;
b27f13ed
JM
2359#ifdef CONFIG_IEEE80211W
2360 if (sm->mgmt_frame_prot) {
2361 u8 *igtk;
2362 size_t igtk_len;
2363 u8 *nbuf;
2364 igtk = wpa_ft_igtk_subelem(sm, &igtk_len);
2365 if (igtk == NULL) {
2366 os_free(subelem);
2367 return pos;
2368 }
2369 nbuf = os_realloc(subelem, subelem_len + igtk_len);
2370 if (nbuf == NULL) {
2371 os_free(subelem);
2372 os_free(igtk);
2373 return pos;
2374 }
2375 subelem = nbuf;
2376 os_memcpy(subelem + subelem_len, igtk, igtk_len);
2377 subelem_len += igtk_len;
2378 os_free(igtk);
2379 }
2380#endif /* CONFIG_IEEE80211W */
6fc6879b
JM
2381 } else {
2382 r0kh_id = conf->r0_key_holder;
2383 r0kh_id_len = conf->r0_key_holder_len;
6e80516a
JM
2384 anonce = NULL;
2385 snonce = NULL;
6fc6879b 2386 }
6e80516a 2387 res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos,
6fc6879b
JM
2388 end - pos, subelem, subelem_len);
2389 os_free(subelem);
2390 if (res < 0)
2391 return pos;
2392 ftie = pos;
2393 ftie_len = res;
2394 pos += res;
2395
2396 _ftie = (struct rsn_ftie *) (ftie + 2);
1f6e69e0
JM
2397 if (auth_alg == WLAN_AUTH_FT)
2398 _ftie->mic_control[1] = 3; /* Information element count */
f238cf9f
JM
2399
2400 ric_start = pos;
2401 if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
88b32a99
SP
2402 pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
2403 parse.ric_len);
1f6e69e0
JM
2404 if (auth_alg == WLAN_AUTH_FT)
2405 _ftie->mic_control[1] +=
2406 ieee802_11_ie_count(ric_start,
2407 pos - ric_start);
f238cf9f
JM
2408 }
2409 if (ric_start == pos)
2410 ric_start = NULL;
2411
2f373878
JM
2412 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
2413 kck = sm->PTK.kck2;
2414 kck_len = sm->PTK.kck2_len;
2415 } else {
2416 kck = sm->PTK.kck;
2417 kck_len = sm->PTK.kck_len;
2418 }
1f6e69e0 2419 if (auth_alg == WLAN_AUTH_FT &&
2f373878 2420 wpa_ft_mic(kck, kck_len, sm->addr, sm->wpa_auth->addr, 6,
6fc6879b 2421 mdie, mdie_len, ftie, ftie_len,
f238cf9f
JM
2422 rsnie, rsnie_len,
2423 ric_start, ric_start ? pos - ric_start : 0,
2424 _ftie->mic) < 0)
6fc6879b
JM
2425 wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
2426
e44bd28c
JM
2427 os_free(sm->assoc_resp_ftie);
2428 sm->assoc_resp_ftie = os_malloc(ftie_len);
2429 if (sm->assoc_resp_ftie)
2430 os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
2431
6fc6879b
JM
2432 return pos;
2433}
2434
2435
6fc6879b
JM
2436static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
2437 int vlan_id,
71934751 2438 enum wpa_alg alg, const u8 *addr, int idx,
6fc6879b
JM
2439 u8 *key, size_t key_len)
2440{
cef8fac0 2441 if (wpa_auth->cb->set_key == NULL)
6fc6879b 2442 return -1;
cef8fac0
JB
2443 return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
2444 key, key_len);
6fc6879b
JM
2445}
2446
2447
0e84c254 2448void wpa_ft_install_ptk(struct wpa_state_machine *sm)
6fc6879b 2449{
71934751 2450 enum wpa_alg alg;
6fc6879b
JM
2451 int klen;
2452
2453 /* MLME-SETKEYS.request(PTK) */
c3550295
JM
2454 alg = wpa_cipher_to_alg(sm->pairwise);
2455 klen = wpa_cipher_key_len(sm->pairwise);
2456 if (!wpa_cipher_valid_pairwise(sm->pairwise)) {
0e84c254
JM
2457 wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
2458 "PTK configuration", sm->pairwise);
6fc6879b 2459 return;
0e84c254 2460 }
6fc6879b 2461
0e3bd7ac
MV
2462 if (sm->tk_already_set) {
2463 /* Must avoid TK reconfiguration to prevent clearing of TX/RX
2464 * PN in the driver */
2465 wpa_printf(MSG_DEBUG,
2466 "FT: Do not re-install same PTK to the driver");
2467 return;
2468 }
2469
6fc6879b
JM
2470 /* FIX: add STA entry to kernel/driver here? The set_key will fail
2471 * most likely without this.. At the moment, STA entry is added only
0e84c254
JM
2472 * after association has been completed. This function will be called
2473 * again after association to get the PTK configured, but that could be
2474 * optimized by adding the STA entry earlier.
6fc6879b
JM
2475 */
2476 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
98cd3d1c 2477 sm->PTK.tk, klen))
6fc6879b
JM
2478 return;
2479
2480 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
2481 sm->pairwise_set = TRUE;
0e3bd7ac 2482 sm->tk_already_set = TRUE;
6fc6879b
JM
2483}
2484
2485
96590564
MB
2486/* Derive PMK-R1 from PSK, check all available PSK */
2487static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm,
2488 const u8 *req_pmk_r1_name,
17010c38 2489 u8 *out_pmk_r1, int *out_pairwise,
069b4e30
MB
2490 struct vlan_description *out_vlan,
2491 const u8 **out_identity, size_t *out_identity_len,
2492 const u8 **out_radius_cui,
a6509e85
MB
2493 size_t *out_radius_cui_len,
2494 int *out_session_timeout)
96590564
MB
2495{
2496 const u8 *pmk = NULL;
2497 u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
2498 u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
2499 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
2500 const u8 *mdid = wpa_auth->conf.mobility_domain;
2501 const u8 *r0kh = sm->r0kh_id;
2502 size_t r0kh_len = sm->r0kh_id_len;
2503 const u8 *r1kh = wpa_auth->conf.r1_key_holder;
2504 const u8 *ssid = wpa_auth->conf.ssid;
2505 size_t ssid_len = wpa_auth->conf.ssid_len;
2506 int pairwise;
2507
2508 pairwise = sm->pairwise;
2509
2510 for (;;) {
2511 pmk = wpa_ft_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
2512 pmk);
2513 if (pmk == NULL)
2514 break;
2515
364c064a
JM
2516 if (wpa_derive_pmk_r0(pmk, PMK_LEN, ssid, ssid_len, mdid, r0kh,
2517 r0kh_len, sm->addr,
994eac7e 2518 pmk_r0, pmk_r0_name, 0) < 0 ||
a3e18dbb
JM
2519 wpa_derive_pmk_r1(pmk_r0, PMK_LEN, pmk_r0_name, r1kh,
2520 sm->addr, pmk_r1, pmk_r1_name) < 0 ||
364c064a 2521 os_memcmp_const(pmk_r1_name, req_pmk_r1_name,
96590564
MB
2522 WPA_PMK_NAME_LEN) != 0)
2523 continue;
2524
2525 /* We found a PSK that matches the requested pmk_r1_name */
2526 wpa_printf(MSG_DEBUG,
2527 "FT: Found PSK to generate PMK-R1 locally");
2528 os_memcpy(out_pmk_r1, pmk_r1, PMK_LEN);
2529 if (out_pairwise)
2530 *out_pairwise = pairwise;
17010c38
MB
2531 if (out_vlan &&
2532 wpa_ft_get_vlan(sm->wpa_auth, sm->addr, out_vlan) < 0) {
2533 wpa_printf(MSG_DEBUG, "FT: vlan not available for STA "
2534 MACSTR, MAC2STR(sm->addr));
2535 return -1;
2536 }
2537
069b4e30
MB
2538 if (out_identity && out_identity_len) {
2539 *out_identity_len = wpa_ft_get_identity(
2540 sm->wpa_auth, sm->addr, out_identity);
2541 }
2542
2543 if (out_radius_cui && out_radius_cui_len) {
2544 *out_radius_cui_len = wpa_ft_get_radius_cui(
2545 sm->wpa_auth, sm->addr, out_radius_cui);
2546 }
2547
a6509e85
MB
2548 if (out_session_timeout) {
2549 *out_session_timeout = wpa_ft_get_session_timeout(
2550 sm->wpa_auth, sm->addr);
2551 }
2552
96590564
MB
2553 return 0;
2554 }
2555
2556 wpa_printf(MSG_DEBUG,
2557 "FT: Did not find PSK to generate PMK-R1 locally");
2558 return -1;
2559}
2560
2561
2562/* Detect the configuration the station asked for.
2563 * Required to detect FT-PSK and pairwise cipher.
2564 */
2565static int wpa_ft_set_key_mgmt(struct wpa_state_machine *sm,
2566 struct wpa_ft_ies *parse)
2567{
2568 int key_mgmt, ciphers;
2569
2570 if (sm->wpa_key_mgmt)
2571 return 0;
2572
2573 key_mgmt = parse->key_mgmt & sm->wpa_auth->conf.wpa_key_mgmt;
2574 if (!key_mgmt) {
2575 wpa_printf(MSG_DEBUG, "FT: Invalid key mgmt (0x%x) from "
2576 MACSTR, parse->key_mgmt, MAC2STR(sm->addr));
2577 return -1;
2578 }
2579 if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
2580 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
c22bb5bb
JM
2581#ifdef CONFIG_SHA384
2582 else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384)
2583 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384;
2584#endif /* CONFIG_SHA384 */
96590564
MB
2585 else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
2586 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
5aa08153
JM
2587#ifdef CONFIG_FILS
2588 else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256)
2589 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256;
2590 else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384)
2591 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384;
2592#endif /* CONFIG_FILS */
96590564
MB
2593 ciphers = parse->pairwise_cipher & sm->wpa_auth->conf.rsn_pairwise;
2594 if (!ciphers) {
2595 wpa_printf(MSG_DEBUG, "FT: Invalid pairwise cipher (0x%x) from "
2596 MACSTR,
2597 parse->pairwise_cipher, MAC2STR(sm->addr));
2598 return -1;
2599 }
2600 sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
2601
2602 return 0;
2603}
2604
2605
4ddca814
JM
2606static int wpa_ft_local_derive_pmk_r1(struct wpa_authenticator *wpa_auth,
2607 struct wpa_state_machine *sm,
2608 const u8 *r0kh_id, size_t r0kh_id_len,
2609 const u8 *req_pmk_r0_name,
2610 const u8 *req_pmk_r1_name,
17010c38 2611 u8 *out_pmk_r1, int *out_pairwise,
069b4e30
MB
2612 struct vlan_description *vlan,
2613 const u8 **identity, size_t *identity_len,
2614 const u8 **radius_cui,
a6509e85
MB
2615 size_t *radius_cui_len,
2616 int *out_session_timeout)
4ddca814
JM
2617{
2618 struct wpa_auth_config *conf = &wpa_auth->conf;
2619 const struct wpa_ft_pmk_r0_sa *r0;
2620 u8 pmk_r1_name[WPA_PMK_NAME_LEN];
3a3e2832 2621 int expires_in = 0;
a6509e85
MB
2622 int session_timeout = 0;
2623 struct os_reltime now;
4ddca814
JM
2624
2625 if (conf->r0_key_holder_len != r0kh_id_len ||
2626 os_memcmp(conf->r0_key_holder, r0kh_id, conf->r0_key_holder_len) !=
2627 0)
2628 return -1; /* not our R0KH-ID */
2629
2630 wpa_printf(MSG_DEBUG, "FT: STA R0KH-ID matching local configuration");
2631 if (wpa_ft_fetch_pmk_r0(sm->wpa_auth, sm->addr, req_pmk_r0_name, &r0) <
2632 0)
2633 return -1; /* no matching PMKR0Name in local cache */
2634
2635 wpa_printf(MSG_DEBUG, "FT: Requested PMKR0Name found in local cache");
2636
a3e18dbb
JM
2637 if (wpa_derive_pmk_r1(r0->pmk_r0, r0->pmk_r0_len, r0->pmk_r0_name,
2638 conf->r1_key_holder,
4ddca814
JM
2639 sm->addr, out_pmk_r1, pmk_r1_name) < 0)
2640 return -1;
a3e18dbb 2641 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", out_pmk_r1, r0->pmk_r0_len);
4ddca814
JM
2642 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", pmk_r1_name, WPA_PMK_NAME_LEN);
2643
a6509e85
MB
2644 os_get_reltime(&now);
2645 if (r0->expiration)
3a3e2832 2646 expires_in = r0->expiration - now.sec;
a6509e85
MB
2647
2648 if (r0->session_timeout)
2649 session_timeout = r0->session_timeout - now.sec;
3a3e2832 2650
a3e18dbb
JM
2651 wpa_ft_store_pmk_r1(wpa_auth, sm->addr, out_pmk_r1, r0->pmk_r0_len,
2652 pmk_r1_name,
a6509e85 2653 sm->pairwise, r0->vlan, expires_in, session_timeout,
069b4e30
MB
2654 r0->identity, r0->identity_len,
2655 r0->radius_cui, r0->radius_cui_len);
4ddca814
JM
2656
2657 *out_pairwise = sm->pairwise;
17010c38
MB
2658 if (vlan) {
2659 if (r0->vlan)
2660 *vlan = *r0->vlan;
2661 else
2662 os_memset(vlan, 0, sizeof(*vlan));
2663 }
069b4e30
MB
2664
2665 if (identity && identity_len) {
2666 *identity = r0->identity;
2667 *identity_len = r0->identity_len;
2668 }
2669
2670 if (radius_cui && radius_cui_len) {
2671 *radius_cui = r0->radius_cui;
2672 *radius_cui_len = r0->radius_cui_len;
2673 }
2674
a6509e85
MB
2675 *out_session_timeout = session_timeout;
2676
4ddca814
JM
2677 return 0;
2678}
2679
2680
692ec305 2681static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
6fc6879b
JM
2682 const u8 *ies, size_t ies_len,
2683 u8 **resp_ies, size_t *resp_ies_len)
2684{
2685 struct rsn_mdie *mdie;
2686 struct rsn_ftie *ftie;
a3e18dbb 2687 u8 pmk_r1[PMK_LEN_MAX], pmk_r1_name[WPA_PMK_NAME_LEN];
6fc6879b
JM
2688 u8 ptk_name[WPA_PMK_NAME_LEN];
2689 struct wpa_auth_config *conf;
2690 struct wpa_ft_ies parse;
98cd3d1c 2691 size_t buflen;
6fc6879b
JM
2692 int ret;
2693 u8 *pos, *end;
a6509e85 2694 int pairwise, session_timeout = 0;
17010c38 2695 struct vlan_description vlan;
069b4e30
MB
2696 const u8 *identity, *radius_cui;
2697 size_t identity_len = 0, radius_cui_len = 0;
a3e18dbb
JM
2698 int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt);
2699 size_t pmk_r1_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN;
6fc6879b
JM
2700
2701 *resp_ies = NULL;
2702 *resp_ies_len = 0;
2703
2704 sm->pmk_r1_name_valid = 0;
2705 conf = &sm->wpa_auth->conf;
2706
2707 wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",
2708 ies, ies_len);
2709
2710 if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
2711 wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
2712 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2713 }
2714
2715 mdie = (struct rsn_mdie *) parse.mdie;
2716 if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
2717 os_memcmp(mdie->mobility_domain,
2718 sm->wpa_auth->conf.mobility_domain,
2719 MOBILITY_DOMAIN_ID_LEN) != 0) {
2720 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
2721 return WLAN_STATUS_INVALID_MDIE;
2722 }
2723
2724 ftie = (struct rsn_ftie *) parse.ftie;
2725 if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
2726 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
2727 return WLAN_STATUS_INVALID_FTIE;
2728 }
2729
2730 os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
2731
2732 if (parse.r0kh_id == NULL) {
2733 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID");
2734 return WLAN_STATUS_INVALID_FTIE;
2735 }
2736
2737 wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID",
2738 parse.r0kh_id, parse.r0kh_id_len);
2739 os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);
2740 sm->r0kh_id_len = parse.r0kh_id_len;
2741
2742 if (parse.rsn_pmkid == NULL) {
2743 wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE");
2744 return WLAN_STATUS_INVALID_PMKID;
2745 }
2746
96590564
MB
2747 if (wpa_ft_set_key_mgmt(sm, &parse) < 0)
2748 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2749
6fc6879b
JM
2750 wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name",
2751 parse.rsn_pmkid, WPA_PMK_NAME_LEN);
364c064a
JM
2752 if (wpa_derive_pmk_r1_name(parse.rsn_pmkid,
2753 sm->wpa_auth->conf.r1_key_holder, sm->addr,
2754 pmk_r1_name) < 0)
2755 return WLAN_STATUS_UNSPECIFIED_FAILURE;
6fc6879b
JM
2756 wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name",
2757 pmk_r1_name, WPA_PMK_NAME_LEN);
2758
96590564
MB
2759 if (conf->ft_psk_generate_local &&
2760 wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
17010c38 2761 if (wpa_ft_psk_pmk_r1(sm, pmk_r1_name, pmk_r1, &pairwise,
069b4e30 2762 &vlan, &identity, &identity_len,
a6509e85
MB
2763 &radius_cui, &radius_cui_len,
2764 &session_timeout) < 0)
96590564 2765 return WLAN_STATUS_INVALID_PMKID;
4ddca814
JM
2766 wpa_printf(MSG_DEBUG,
2767 "FT: Generated PMK-R1 for FT-PSK locally");
96590564 2768 } else if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name,
a3e18dbb
JM
2769 pmk_r1, &pmk_r1_len, &pairwise, &vlan,
2770 &identity, &identity_len, &radius_cui,
a6509e85 2771 &radius_cui_len, &session_timeout) < 0) {
4ddca814
JM
2772 wpa_printf(MSG_DEBUG,
2773 "FT: No PMK-R1 available in local cache for the requested PMKR1Name");
2774 if (wpa_ft_local_derive_pmk_r1(sm->wpa_auth, sm,
2775 parse.r0kh_id, parse.r0kh_id_len,
2776 parse.rsn_pmkid,
17010c38 2777 pmk_r1_name, pmk_r1, &pairwise,
069b4e30 2778 &vlan, &identity, &identity_len,
a6509e85
MB
2779 &radius_cui, &radius_cui_len,
2780 &session_timeout) == 0) {
4ddca814
JM
2781 wpa_printf(MSG_DEBUG,
2782 "FT: Generated PMK-R1 based on local PMK-R0");
2783 goto pmk_r1_derived;
2784 }
2785
692ec305 2786 if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) {
3a46cf93
MB
2787 wpa_printf(MSG_DEBUG,
2788 "FT: Did not have matching PMK-R1 and either unknown or blocked R0KH-ID or NAK from R0KH");
6fc6879b
JM
2789 return WLAN_STATUS_INVALID_PMKID;
2790 }
2791
692ec305 2792 return -1; /* Status pending */
4ddca814
JM
2793 } else {
2794 wpa_printf(MSG_DEBUG, "FT: Found PMKR1Name from local cache");
6fc6879b
JM
2795 }
2796
4ddca814 2797pmk_r1_derived:
a3e18dbb 2798 wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, pmk_r1_len);
6fc6879b
JM
2799 sm->pmk_r1_name_valid = 1;
2800 os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
2801
3642c431 2802 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
6fc6879b
JM
2803 wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
2804 "ANonce");
2805 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2806 }
2807
2808 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
2809 sm->SNonce, WPA_NONCE_LEN);
2810 wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
2811 sm->ANonce, WPA_NONCE_LEN);
2812
a3e18dbb
JM
2813 if (wpa_pmk_r1_to_ptk(pmk_r1, pmk_r1_len, sm->SNonce, sm->ANonce,
2814 sm->addr, sm->wpa_auth->addr, pmk_r1_name,
98cd3d1c
JM
2815 &sm->PTK, ptk_name, sm->wpa_key_mgmt,
2816 pairwise) < 0)
2817 return WLAN_STATUS_UNSPECIFIED_FAILURE;
6fc6879b 2818
0e84c254 2819 sm->pairwise = pairwise;
3d4d2348 2820 sm->PTK_valid = TRUE;
0e3bd7ac 2821 sm->tk_already_set = FALSE;
6fc6879b
JM
2822 wpa_ft_install_ptk(sm);
2823
17010c38
MB
2824 if (wpa_ft_set_vlan(sm->wpa_auth, sm->addr, &vlan) < 0) {
2825 wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN");
2826 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2827 }
069b4e30
MB
2828 if (wpa_ft_set_identity(sm->wpa_auth, sm->addr,
2829 identity, identity_len) < 0 ||
2830 wpa_ft_set_radius_cui(sm->wpa_auth, sm->addr,
2831 radius_cui, radius_cui_len) < 0) {
2832 wpa_printf(MSG_DEBUG, "FT: Failed to configure identity/CUI");
2833 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2834 }
a6509e85 2835 wpa_ft_set_session_timeout(sm->wpa_auth, sm->addr, session_timeout);
17010c38 2836
6fc6879b
JM
2837 buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
2838 2 + FT_R1KH_ID_LEN + 200;
2839 *resp_ies = os_zalloc(buflen);
a8e25dee
JM
2840 if (*resp_ies == NULL)
2841 goto fail;
6fc6879b
JM
2842
2843 pos = *resp_ies;
2844 end = *resp_ies + buflen;
2845
2846 ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid);
a8e25dee
JM
2847 if (ret < 0)
2848 goto fail;
6fc6879b
JM
2849 pos += ret;
2850
2851 ret = wpa_write_mdie(conf, pos, end - pos);
a8e25dee
JM
2852 if (ret < 0)
2853 goto fail;
6fc6879b
JM
2854 pos += ret;
2855
2856 ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len,
2857 sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0);
a8e25dee
JM
2858 if (ret < 0)
2859 goto fail;
6fc6879b
JM
2860 pos += ret;
2861
2862 *resp_ies_len = pos - *resp_ies;
2863
2864 return WLAN_STATUS_SUCCESS;
a8e25dee
JM
2865fail:
2866 os_free(*resp_ies);
2867 *resp_ies = NULL;
2868 return WLAN_STATUS_UNSPECIFIED_FAILURE;
6fc6879b
JM
2869}
2870
2871
2872void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
2873 u16 auth_transaction, const u8 *ies, size_t ies_len,
2874 void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
2875 u16 auth_transaction, u16 status,
2876 const u8 *ies, size_t ies_len),
2877 void *ctx)
2878{
2879 u16 status;
2880 u8 *resp_ies;
2881 size_t resp_ies_len;
692ec305 2882 int res;
6fc6879b
JM
2883
2884 if (sm == NULL) {
2885 wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but "
2886 "WPA SM not available");
2887 return;
2888 }
2889
2890 wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR
2891 " BSSID=" MACSTR " transaction=%d",
2892 MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);
692ec305
JM
2893 sm->ft_pending_cb = cb;
2894 sm->ft_pending_cb_ctx = ctx;
2895 sm->ft_pending_auth_transaction = auth_transaction;
3a46cf93 2896 sm->ft_pending_pull_left_retries = sm->wpa_auth->conf.rkh_pull_retries;
692ec305
JM
2897 res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
2898 &resp_ies_len);
2899 if (res < 0) {
2900 wpa_printf(MSG_DEBUG, "FT: Callback postponed until response is available");
2901 return;
2902 }
2903 status = res;
6fc6879b
JM
2904
2905 wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR
2906 " auth_transaction=%d status=%d",
2907 MAC2STR(sm->addr), auth_transaction + 1, status);
2908 wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);
2909 cb(ctx, sm->addr, bssid, auth_transaction + 1, status,
2910 resp_ies, resp_ies_len);
2911 os_free(resp_ies);
2912}
2913
2914
2915u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
2916 size_t ies_len)
2917{
2918 struct wpa_ft_ies parse;
2919 struct rsn_mdie *mdie;
2920 struct rsn_ftie *ftie;
98cd3d1c
JM
2921 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
2922 size_t mic_len = 16;
8aaf894d 2923 unsigned int count;
2f373878
JM
2924 const u8 *kck;
2925 size_t kck_len;
6fc6879b
JM
2926
2927 if (sm == NULL)
2928 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2929
2930 wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
2931
2932 if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
2933 wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
2934 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2935 }
2936
2937 if (parse.rsn == NULL) {
2938 wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req");
2939 return WLAN_STATUS_UNSPECIFIED_FAILURE;
2940 }
2941
2942 if (parse.rsn_pmkid == NULL) {
2943 wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE");
2944 return WLAN_STATUS_INVALID_PMKID;
2945 }
2946
870834a1
JM
2947 if (os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)
2948 != 0) {
6fc6879b
JM
2949 wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match "
2950 "with the PMKR1Name derived from auth request");
2951 return WLAN_STATUS_INVALID_PMKID;
2952 }
2953
2954 mdie = (struct rsn_mdie *) parse.mdie;
2955 if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
2956 os_memcmp(mdie->mobility_domain,
2957 sm->wpa_auth->conf.mobility_domain,
2958 MOBILITY_DOMAIN_ID_LEN) != 0) {
2959 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
2960 return WLAN_STATUS_INVALID_MDIE;
2961 }
2962
2963 ftie = (struct rsn_ftie *) parse.ftie;
2964 if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
2965 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
2966 return WLAN_STATUS_INVALID_FTIE;
2967 }
2968
0ae145cd
JM
2969 if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
2970 wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
2971 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
2972 ftie->snonce, WPA_NONCE_LEN);
2973 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
2974 sm->SNonce, WPA_NONCE_LEN);
0a63635e 2975 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
2976 }
2977
2978 if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
2979 wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
2980 wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
2981 ftie->anonce, WPA_NONCE_LEN);
2982 wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
2983 sm->ANonce, WPA_NONCE_LEN);
0a63635e 2984 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
2985 }
2986
2987
2988 if (parse.r0kh_id == NULL) {
2989 wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
0a63635e 2990 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
2991 }
2992
2993 if (parse.r0kh_id_len != sm->r0kh_id_len ||
870834a1
JM
2994 os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
2995 {
0ae145cd
JM
2996 wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
2997 "the current R0KH-ID");
2998 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
2999 parse.r0kh_id, parse.r0kh_id_len);
3000 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
3001 sm->r0kh_id, sm->r0kh_id_len);
0a63635e 3002 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
3003 }
3004
3005 if (parse.r1kh_id == NULL) {
3006 wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
0a63635e 3007 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
3008 }
3009
870834a1
JM
3010 if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
3011 FT_R1KH_ID_LEN) != 0) {
0ae145cd
JM
3012 wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
3013 "ReassocReq");
3014 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
3015 parse.r1kh_id, FT_R1KH_ID_LEN);
3016 wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
3017 sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
0a63635e 3018 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
3019 }
3020
3021 if (parse.rsn_pmkid == NULL ||
870834a1
JM
3022 os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
3023 {
0ae145cd
JM
3024 wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
3025 "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
0a63635e 3026 return WLAN_STATUS_INVALID_PMKID;
0ae145cd
JM
3027 }
3028
8aaf894d
JM
3029 count = 3;
3030 if (parse.ric)
c284b461 3031 count += ieee802_11_ie_count(parse.ric, parse.ric_len);
8aaf894d
JM
3032 if (ftie->mic_control[1] != count) {
3033 wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
3034 "Control: received %u expected %u",
3035 ftie->mic_control[1], count);
0a63635e 3036 return WLAN_STATUS_UNSPECIFIED_FAILURE;
8aaf894d
JM
3037 }
3038
2f373878
JM
3039 if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
3040 kck = sm->PTK.kck2;
3041 kck_len = sm->PTK.kck2_len;
3042 } else {
3043 kck = sm->PTK.kck;
3044 kck_len = sm->PTK.kck_len;
3045 }
3046 if (wpa_ft_mic(kck, kck_len, sm->addr, sm->wpa_auth->addr, 5,
6fc6879b
JM
3047 parse.mdie - 2, parse.mdie_len + 2,
3048 parse.ftie - 2, parse.ftie_len + 2,
babfbf15
JM
3049 parse.rsn - 2, parse.rsn_len + 2,
3050 parse.ric, parse.ric_len,
6fc6879b
JM
3051 mic) < 0) {
3052 wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
3053 return WLAN_STATUS_UNSPECIFIED_FAILURE;
3054 }
3055
98cd3d1c 3056 if (os_memcmp_const(mic, ftie->mic, mic_len) != 0) {
6fc6879b 3057 wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
88b32a99
SP
3058 wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
3059 MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
98cd3d1c
JM
3060 wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
3061 ftie->mic, mic_len);
3062 wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len);
88b32a99
SP
3063 wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
3064 parse.mdie - 2, parse.mdie_len + 2);
3065 wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
3066 parse.ftie - 2, parse.ftie_len + 2);
3067 wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
3068 parse.rsn - 2, parse.rsn_len + 2);
6fc6879b
JM
3069 return WLAN_STATUS_INVALID_FTIE;
3070 }
3071
3072 return WLAN_STATUS_SUCCESS;
3073}
3074
3075
3076int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len)
3077{
3078 const u8 *sta_addr, *target_ap;
3079 const u8 *ies;
3080 size_t ies_len;
3081 u8 action;
3082 struct ft_rrb_frame *frame;
3083
3084 if (sm == NULL)
3085 return -1;
3086
3087 /*
3088 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
3089 * FT Request action frame body[variable]
3090 */
3091
3092 if (len < 14) {
3093 wpa_printf(MSG_DEBUG, "FT: Too short FT Action frame "
3094 "(len=%lu)", (unsigned long) len);
3095 return -1;
3096 }
3097
3098 action = data[1];
3099 sta_addr = data + 2;
3100 target_ap = data + 8;
3101 ies = data + 14;
3102 ies_len = len - 14;
3103
3104 wpa_printf(MSG_DEBUG, "FT: Received FT Action frame (STA=" MACSTR
3105 " Target AP=" MACSTR " Action=%d)",
3106 MAC2STR(sta_addr), MAC2STR(target_ap), action);
3107
3108 if (os_memcmp(sta_addr, sm->addr, ETH_ALEN) != 0) {
3109 wpa_printf(MSG_DEBUG, "FT: Mismatch in FT Action STA address: "
3110 "STA=" MACSTR " STA-Address=" MACSTR,
3111 MAC2STR(sm->addr), MAC2STR(sta_addr));
3112 return -1;
3113 }
3114
3115 /*
3116 * Do some sanity checking on the target AP address (not own and not
3117 * broadcast. This could be extended to filter based on a list of known
3118 * APs in the MD (if such a list were configured).
3119 */
3120 if ((target_ap[0] & 0x01) ||
3121 os_memcmp(target_ap, sm->wpa_auth->addr, ETH_ALEN) == 0) {
3122 wpa_printf(MSG_DEBUG, "FT: Invalid Target AP in FT Action "
3123 "frame");
3124 return -1;
3125 }
3126
3127 wpa_hexdump(MSG_MSGDUMP, "FT: Action frame body", ies, ies_len);
3128
1940559e
JM
3129 if (!sm->wpa_auth->conf.ft_over_ds) {
3130 wpa_printf(MSG_DEBUG, "FT: Over-DS option disabled - reject");
3131 return -1;
3132 }
3133
6fc6879b
JM
3134 /* RRB - Forward action frame to the target AP */
3135 frame = os_malloc(sizeof(*frame) + len);
2c48211c
JM
3136 if (frame == NULL)
3137 return -1;
6fc6879b
JM
3138 frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
3139 frame->packet_type = FT_PACKET_REQUEST;
3140 frame->action_length = host_to_le16(len);
3141 os_memcpy(frame->ap_address, sm->wpa_auth->addr, ETH_ALEN);
3142 os_memcpy(frame + 1, data, len);
3143
3144 wpa_ft_rrb_send(sm->wpa_auth, target_ap, (u8 *) frame,
3145 sizeof(*frame) + len);
3146 os_free(frame);
3147
3148 return 0;
3149}
3150
3151
692ec305
JM
3152static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
3153 u16 auth_transaction, u16 resp,
3154 const u8 *ies, size_t ies_len)
3155{
3156 struct wpa_state_machine *sm = ctx;
3157 wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR,
3158 MAC2STR(sm->addr));
3159 wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr,
3160 WLAN_STATUS_SUCCESS, ies, ies_len);
3161}
3162
3163
6fc6879b
JM
3164static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
3165 const u8 *current_ap, const u8 *sta_addr,
3166 const u8 *body, size_t len)
3167{
3168 struct wpa_state_machine *sm;
3169 u16 status;
692ec305
JM
3170 u8 *resp_ies;
3171 size_t resp_ies_len;
3172 int res;
6fc6879b
JM
3173
3174 sm = wpa_ft_add_sta(wpa_auth, sta_addr);
3175 if (sm == NULL) {
3176 wpa_printf(MSG_DEBUG, "FT: Failed to add new STA based on "
3177 "RRB Request");
3178 return -1;
3179 }
3180
3181 wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len);
3182
692ec305
JM
3183 sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb;
3184 sm->ft_pending_cb_ctx = sm;
3185 os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN);
3a46cf93 3186 sm->ft_pending_pull_left_retries = sm->wpa_auth->conf.rkh_pull_retries;
692ec305
JM
3187 res = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
3188 &resp_ies_len);
3189 if (res < 0) {
3190 wpa_printf(MSG_DEBUG, "FT: No immediate response available - wait for pull response");
3191 return 0;
3192 }
3193 status = res;
3194
3195 res = wpa_ft_send_rrb_auth_resp(sm, current_ap, sta_addr, status,
3196 resp_ies, resp_ies_len);
3197 os_free(resp_ies);
3198 return res;
3199}
3200
3201
3202static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
3203 const u8 *current_ap, const u8 *sta_addr,
3204 u16 status, const u8 *resp_ies,
3205 size_t resp_ies_len)
3206{
3207 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
3208 size_t rlen;
3209 struct ft_rrb_frame *frame;
3210 u8 *pos;
6fc6879b
JM
3211
3212 wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR
3213 " CurrentAP=" MACSTR " status=%d",
3214 MAC2STR(sm->addr), MAC2STR(current_ap), status);
3215 wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);
3216
3217 /* RRB - Forward action frame response to the Current AP */
3218
3219 /*
3220 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
3221 * Status_Code[2] FT Request action frame body[variable]
3222 */
3223 rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len;
3224
3225 frame = os_malloc(sizeof(*frame) + rlen);
692ec305 3226 if (frame == NULL)
2c48211c 3227 return -1;
6fc6879b
JM
3228 frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
3229 frame->packet_type = FT_PACKET_RESPONSE;
3230 frame->action_length = host_to_le16(rlen);
3231 os_memcpy(frame->ap_address, wpa_auth->addr, ETH_ALEN);
3232 pos = (u8 *) (frame + 1);
3233 *pos++ = WLAN_ACTION_FT;
3234 *pos++ = 2; /* Action: Response */
3235 os_memcpy(pos, sta_addr, ETH_ALEN);
3236 pos += ETH_ALEN;
3237 os_memcpy(pos, wpa_auth->addr, ETH_ALEN);
3238 pos += ETH_ALEN;
3239 WPA_PUT_LE16(pos, status);
3240 pos += 2;
692ec305 3241 if (resp_ies)
6fc6879b 3242 os_memcpy(pos, resp_ies, resp_ies_len);
6fc6879b
JM
3243
3244 wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame,
3245 sizeof(*frame) + rlen);
3246 os_free(frame);
3247
3248 return 0;
3249}
3250
3251
245fc96e
MB
3252static int wpa_ft_rrb_build_r0(const u8 *key, const size_t key_len,
3253 const struct tlv_list *tlvs,
3254 const struct wpa_ft_pmk_r0_sa *pmk_r0,
3255 const u8 *r1kh_id, const u8 *s1kh_id,
3256 const struct tlv_list *tlv_auth,
3257 const u8 *src_addr, u8 type,
3258 u8 **packet, size_t *packet_len)
3259{
a3e18dbb
JM
3260 u8 pmk_r1[PMK_LEN_MAX];
3261 size_t pmk_r1_len = pmk_r0->pmk_r0_len;
245fc96e
MB
3262 u8 pmk_r1_name[WPA_PMK_NAME_LEN];
3263 u8 f_pairwise[sizeof(le16)];
3a3e2832 3264 u8 f_expires_in[sizeof(le16)];
a6509e85 3265 u8 f_session_timeout[sizeof(le32)];
3a3e2832 3266 int expires_in;
a6509e85 3267 int session_timeout;
3a3e2832 3268 struct os_reltime now;
245fc96e
MB
3269 int ret;
3270 struct tlv_list sess_tlv[] = {
a3e18dbb 3271 { .type = FT_RRB_PMK_R1, .len = pmk_r1_len,
245fc96e
MB
3272 .data = pmk_r1 },
3273 { .type = FT_RRB_PMK_R1_NAME, .len = sizeof(pmk_r1_name),
3274 .data = pmk_r1_name },
3275 { .type = FT_RRB_PAIRWISE, .len = sizeof(f_pairwise),
3276 .data = f_pairwise },
3a3e2832
MB
3277 { .type = FT_RRB_EXPIRES_IN, .len = sizeof(f_expires_in),
3278 .data = f_expires_in },
069b4e30
MB
3279 { .type = FT_RRB_IDENTITY, .len = pmk_r0->identity_len,
3280 .data = pmk_r0->identity },
3281 { .type = FT_RRB_RADIUS_CUI, .len = pmk_r0->radius_cui_len,
3282 .data = pmk_r0->radius_cui },
a6509e85
MB
3283 { .type = FT_RRB_SESSION_TIMEOUT,
3284 .len = sizeof(f_session_timeout),
3285 .data = f_session_timeout },
245fc96e
MB
3286 { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
3287 };
3288
a3e18dbb
JM
3289 if (wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_len,
3290 pmk_r0->pmk_r0_name, r1kh_id,
245fc96e
MB
3291 s1kh_id, pmk_r1, pmk_r1_name) < 0)
3292 return -1;
a3e18dbb
JM
3293 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 (for peer AP)",
3294 pmk_r1, pmk_r1_len);
3295 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name (for peer AP)",
3296 pmk_r1_name, WPA_PMK_NAME_LEN);
245fc96e
MB
3297 WPA_PUT_LE16(f_pairwise, pmk_r0->pairwise);
3298
3a3e2832
MB
3299 os_get_reltime(&now);
3300 if (pmk_r0->expiration > now.sec)
3301 expires_in = pmk_r0->expiration - now.sec;
3302 else if (pmk_r0->expiration)
3303 expires_in = 1;
3304 else
3305 expires_in = 0;
3306 WPA_PUT_LE16(f_expires_in, expires_in);
3307
a6509e85
MB
3308 if (pmk_r0->session_timeout > now.sec)
3309 session_timeout = pmk_r0->session_timeout - now.sec;
3310 else if (pmk_r0->session_timeout)
3311 session_timeout = 1;
3312 else
3313 session_timeout = 0;
3314 WPA_PUT_LE32(f_session_timeout, session_timeout);
3315
245fc96e 3316 ret = wpa_ft_rrb_build(key, key_len, tlvs, sess_tlv, tlv_auth,
17010c38
MB
3317 pmk_r0->vlan, src_addr, type,
3318 packet, packet_len);
245fc96e
MB
3319
3320 os_memset(pmk_r1, 0, sizeof(pmk_r1));
3321
3322 return ret;
3323}
3324
3325
6fc6879b
JM
3326static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
3327 const u8 *src_addr,
245fc96e 3328 const u8 *enc, size_t enc_len,
eefe8630
MB
3329 const u8 *auth, size_t auth_len,
3330 int no_defer)
6fc6879b 3331{
245fc96e
MB
3332 const char *msgtype = "pull request";
3333 u8 *plain = NULL, *packet = NULL;
3334 size_t plain_len = 0, packet_len = 0;
3a46cf93 3335 struct ft_remote_r1kh *r1kh, *r1kh_wildcard;
245fc96e
MB
3336 const u8 *key;
3337 size_t key_len;
eefe8630 3338 int seq_ret;
245fc96e
MB
3339 const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id, *f_s1kh_id, *f_pmk_r0_name;
3340 size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len, f_s1kh_id_len;
3341 size_t f_pmk_r0_name_len;
3342 const struct wpa_ft_pmk_r0_sa *r0;
3343 int ret;
3344 struct tlv_list resp[2];
eefe8630
MB
3345 struct tlv_list resp_auth[5];
3346 struct ft_rrb_seq f_seq;
6fc6879b
JM
3347
3348 wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull");
3349
245fc96e
MB
3350 RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1);
3351 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", f_r0kh_id, f_r0kh_id_len);
3352
3353 if (wpa_ft_rrb_check_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len)) {
3354 wpa_printf(MSG_DEBUG, "FT: R0KH-ID mismatch");
3355 goto out;
3356 }
3357
3358 RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN);
3359 wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR, MAC2STR(f_r1kh_id));
3360
3a46cf93
MB
3361 wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh, &r1kh_wildcard);
3362 if (r1kh) {
3363 key = r1kh->key;
3364 key_len = sizeof(r1kh->key);
3365 } else if (r1kh_wildcard) {
3366 wpa_printf(MSG_DEBUG, "FT: Using wildcard R1KH-ID");
3367 key = r1kh_wildcard->key;
3368 key_len = sizeof(r1kh_wildcard->key);
3369 } else {
245fc96e 3370 goto out;
3a46cf93 3371 }
245fc96e
MB
3372
3373 RRB_GET_AUTH(FT_RRB_NONCE, nonce, "pull request", FT_RRB_NONCE_LEN);
3374 wpa_hexdump(MSG_DEBUG, "FT: nonce", f_nonce, f_nonce_len);
3375
3a46cf93
MB
3376 seq_ret = FT_RRB_SEQ_DROP;
3377 if (r1kh)
3378 seq_ret = wpa_ft_rrb_seq_chk(r1kh->seq, src_addr, enc, enc_len,
3379 auth, auth_len, msgtype, no_defer);
3380 if (!no_defer && r1kh_wildcard &&
3381 (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) {
3382 /* wildcard: r1kh-id unknown or changed addr -> do a seq req */
3383 seq_ret = FT_RRB_SEQ_DEFER;
3384 }
3385
eefe8630
MB
3386 if (seq_ret == FT_RRB_SEQ_DROP)
3387 goto out;
3388
245fc96e
MB
3389 if (wpa_ft_rrb_decrypt(key, key_len, enc, enc_len, auth, auth_len,
3390 src_addr, FT_PACKET_R0KH_R1KH_PULL,
3391 &plain, &plain_len) < 0)
3392 goto out;
3393
3a46cf93
MB
3394 if (!r1kh)
3395 r1kh = wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard, src_addr,
3396 f_r1kh_id,
3397 wpa_auth->conf.rkh_pos_timeout);
3398 if (!r1kh)
3399 goto out;
3400
eefe8630
MB
3401 if (seq_ret == FT_RRB_SEQ_DEFER) {
3402 wpa_ft_rrb_seq_req(wpa_auth, r1kh->seq, src_addr, f_r0kh_id,
3403 f_r0kh_id_len, f_r1kh_id, key, key_len,
3404 enc, enc_len, auth, auth_len,
3405 &wpa_ft_rrb_rx_pull);
3406 goto out;
3407 }
3408
3409 wpa_ft_rrb_seq_accept(wpa_auth, r1kh->seq, src_addr, auth, auth_len,
3410 msgtype);
3a46cf93
MB
3411 wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh,
3412 wpa_auth->conf.rkh_pos_timeout);
eefe8630 3413
245fc96e
MB
3414 RRB_GET(FT_RRB_PMK_R0_NAME, pmk_r0_name, msgtype, WPA_PMK_NAME_LEN);
3415 wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", f_pmk_r0_name,
3416 f_pmk_r0_name_len);
3417
3418 RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN);
3419 wpa_printf(MSG_DEBUG, "FT: S1KH-ID=" MACSTR, MAC2STR(f_s1kh_id));
3420
eefe8630
MB
3421 if (wpa_ft_new_seq(r1kh->seq, &f_seq) < 0) {
3422 wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
3423 goto out;
3424 }
3425
245fc96e
MB
3426 resp[0].type = FT_RRB_S1KH_ID;
3427 resp[0].len = f_s1kh_id_len;
3428 resp[0].data = f_s1kh_id;
3429 resp[1].type = FT_RRB_LAST_EMPTY;
3430 resp[1].len = 0;
3431 resp[1].data = NULL;
3432
3433 resp_auth[0].type = FT_RRB_NONCE;
3434 resp_auth[0].len = f_nonce_len;
3435 resp_auth[0].data = f_nonce;
eefe8630
MB
3436 resp_auth[1].type = FT_RRB_SEQ;
3437 resp_auth[1].len = sizeof(f_seq);
3438 resp_auth[1].data = (u8 *) &f_seq;
3439 resp_auth[2].type = FT_RRB_R0KH_ID;
3440 resp_auth[2].len = f_r0kh_id_len;
3441 resp_auth[2].data = f_r0kh_id;
3442 resp_auth[3].type = FT_RRB_R1KH_ID;
3443 resp_auth[3].len = f_r1kh_id_len;
3444 resp_auth[3].data = f_r1kh_id;
3445 resp_auth[4].type = FT_RRB_LAST_EMPTY;
3446 resp_auth[4].len = 0;
3447 resp_auth[4].data = NULL;
245fc96e 3448
9fbe292f 3449 if (wpa_ft_fetch_pmk_r0(wpa_auth, f_s1kh_id, f_pmk_r0_name, &r0) < 0) {
245fc96e 3450 wpa_printf(MSG_DEBUG, "FT: No matching PMK-R0-Name found");
9fbe292f
MB
3451 ret = wpa_ft_rrb_build(key, key_len, resp, NULL, resp_auth,
3452 NULL, wpa_auth->addr,
3453 FT_PACKET_R0KH_R1KH_RESP,
3454 &packet, &packet_len);
3455 } else {
3456 ret = wpa_ft_rrb_build_r0(key, key_len, resp, r0, f_r1kh_id,
3457 f_s1kh_id, resp_auth, wpa_auth->addr,
3458 FT_PACKET_R0KH_R1KH_RESP,
3459 &packet, &packet_len);
3460 }
245fc96e
MB
3461
3462 if (!ret)
3463 wpa_ft_rrb_oui_send(wpa_auth, src_addr,
3464 FT_PACKET_R0KH_R1KH_RESP, packet,
3465 packet_len);
3466
3467out:
3468 os_free(plain);
3469 os_free(packet);
6fc6879b 3470
245fc96e
MB
3471 return 0;
3472}
6fc6879b 3473
6fc6879b 3474
245fc96e
MB
3475/* @returns 0 on success
3476 * -1 on error
3a46cf93 3477 * -2 if FR_RRB_PAIRWISE is missing
245fc96e
MB
3478 */
3479static int wpa_ft_rrb_rx_r1(struct wpa_authenticator *wpa_auth,
3480 const u8 *src_addr, u8 type,
3481 const u8 *enc, size_t enc_len,
3482 const u8 *auth, size_t auth_len,
eefe8630
MB
3483 const char *msgtype, u8 *s1kh_id_out,
3484 int (*cb)(struct wpa_authenticator *wpa_auth,
3485 const u8 *src_addr,
3486 const u8 *enc, size_t enc_len,
3487 const u8 *auth, size_t auth_len,
3488 int no_defer))
245fc96e
MB
3489{
3490 u8 *plain = NULL;
3491 size_t plain_len = 0;
3a46cf93 3492 struct ft_remote_r0kh *r0kh, *r0kh_wildcard;
245fc96e
MB
3493 const u8 *key;
3494 size_t key_len;
eefe8630 3495 int seq_ret;
245fc96e
MB
3496 const u8 *f_r1kh_id, *f_s1kh_id, *f_r0kh_id;
3497 const u8 *f_pmk_r1_name, *f_pairwise, *f_pmk_r1;
3a3e2832 3498 const u8 *f_expires_in;
245fc96e 3499 size_t f_r1kh_id_len, f_s1kh_id_len, f_r0kh_id_len;
069b4e30 3500 const u8 *f_identity, *f_radius_cui;
a6509e85 3501 const u8 *f_session_timeout;
245fc96e 3502 size_t f_pmk_r1_name_len, f_pairwise_len, f_pmk_r1_len;
3a3e2832 3503 size_t f_expires_in_len;
069b4e30 3504 size_t f_identity_len, f_radius_cui_len;
a6509e85 3505 size_t f_session_timeout_len;
245fc96e
MB
3506 int pairwise;
3507 int ret = -1;
3a3e2832 3508 int expires_in;
a6509e85 3509 int session_timeout;
17010c38 3510 struct vlan_description vlan;
6fc6879b 3511
245fc96e
MB
3512 RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1);
3513 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID", f_r0kh_id, f_r0kh_id_len);
6fc6879b 3514
245fc96e
MB
3515 RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, msgtype, FT_R1KH_ID_LEN);
3516 wpa_printf(MSG_DEBUG, "FT: R1KH-ID=" MACSTR, MAC2STR(f_r1kh_id));
3517
3518 if (wpa_ft_rrb_check_r1kh(wpa_auth, f_r1kh_id)) {
3519 wpa_printf(MSG_DEBUG, "FT: R1KH-ID mismatch");
3520 goto out;
6fc6879b
JM
3521 }
3522
3a46cf93
MB
3523 wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len, &r0kh,
3524 &r0kh_wildcard);
3525 if (r0kh) {
3526 key = r0kh->key;
3527 key_len = sizeof(r0kh->key);
3528 } else if (r0kh_wildcard) {
3529 wpa_printf(MSG_DEBUG, "FT: Using wildcard R0KH-ID");
3530 key = r0kh_wildcard->key;
3531 key_len = sizeof(r0kh_wildcard->key);
3532 } else {
245fc96e 3533 goto out;
3a46cf93
MB
3534 }
3535
3536 seq_ret = FT_RRB_SEQ_DROP;
3537 if (r0kh) {
3538 seq_ret = wpa_ft_rrb_seq_chk(r0kh->seq, src_addr, enc, enc_len,
3539 auth, auth_len, msgtype,
3540 cb ? 0 : 1);
3541 }
3542 if (cb && r0kh_wildcard &&
3543 (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) {
3544 /* wildcard: r0kh-id unknown or changed addr -> do a seq req */
3545 seq_ret = FT_RRB_SEQ_DEFER;
3546 }
6fc6879b 3547
eefe8630
MB
3548 if (seq_ret == FT_RRB_SEQ_DROP)
3549 goto out;
3550
245fc96e
MB
3551 if (wpa_ft_rrb_decrypt(key, key_len, enc, enc_len, auth, auth_len,
3552 src_addr, type, &plain, &plain_len) < 0)
3553 goto out;
3554
3a46cf93
MB
3555 if (!r0kh)
3556 r0kh = wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard, src_addr,
3557 f_r0kh_id, f_r0kh_id_len,
3558 wpa_auth->conf.rkh_pos_timeout);
3559 if (!r0kh)
3560 goto out;
3561
eefe8630
MB
3562 if (seq_ret == FT_RRB_SEQ_DEFER) {
3563 wpa_ft_rrb_seq_req(wpa_auth, r0kh->seq, src_addr, f_r0kh_id,
3564 f_r0kh_id_len, f_r1kh_id, key, key_len,
3565 enc, enc_len, auth, auth_len, cb);
3566 goto out;
3567 }
3568
3569 wpa_ft_rrb_seq_accept(wpa_auth, r0kh->seq, src_addr, auth, auth_len,
3570 msgtype);
3a46cf93
MB
3571 wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh,
3572 wpa_auth->conf.rkh_pos_timeout);
eefe8630 3573
245fc96e
MB
3574 RRB_GET(FT_RRB_S1KH_ID, s1kh_id, msgtype, ETH_ALEN);
3575 wpa_printf(MSG_DEBUG, "FT: S1KH-ID=" MACSTR, MAC2STR(f_s1kh_id));
3576
3577 if (s1kh_id_out)
3578 os_memcpy(s1kh_id_out, f_s1kh_id, ETH_ALEN);
3579
3a46cf93 3580 ret = -2;
245fc96e
MB
3581 RRB_GET(FT_RRB_PAIRWISE, pairwise, msgtype, sizeof(le16));
3582 wpa_hexdump(MSG_DEBUG, "FT: pairwise", f_pairwise, f_pairwise_len);
3583
3a46cf93 3584 ret = -1;
245fc96e
MB
3585 RRB_GET(FT_RRB_PMK_R1_NAME, pmk_r1_name, msgtype, WPA_PMK_NAME_LEN);
3586 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name",
3587 f_pmk_r1_name, WPA_PMK_NAME_LEN);
3588
3589 RRB_GET(FT_RRB_PMK_R1, pmk_r1, msgtype, PMK_LEN);
3590 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f_pmk_r1, PMK_LEN);
3591
3592 pairwise = WPA_GET_LE16(f_pairwise);
3593
3a3e2832
MB
3594 RRB_GET_OPTIONAL(FT_RRB_EXPIRES_IN, expires_in, msgtype,
3595 sizeof(le16));
3596 if (f_expires_in)
3597 expires_in = WPA_GET_LE16(f_expires_in);
3598 else
3599 expires_in = 0;
3600
3601 wpa_printf(MSG_DEBUG, "FT: PMK-R1 %s - expires_in=%d", msgtype,
3602 expires_in);
3603
17010c38
MB
3604 if (wpa_ft_rrb_get_tlv_vlan(plain, plain_len, &vlan) < 0) {
3605 wpa_printf(MSG_DEBUG, "FT: Cannot parse vlan");
3606 wpa_ft_rrb_dump(plain, plain_len);
3607 goto out;
3608 }
3609
3610 wpa_printf(MSG_DEBUG, "FT: vlan %d%s",
3611 le_to_host16(vlan.untagged), vlan.tagged[0] ? "+" : "");
3612
069b4e30
MB
3613 RRB_GET_OPTIONAL(FT_RRB_IDENTITY, identity, msgtype, -1);
3614 if (f_identity)
3615 wpa_hexdump_ascii(MSG_DEBUG, "FT: Identity", f_identity,
3616 f_identity_len);
3617
3618 RRB_GET_OPTIONAL(FT_RRB_RADIUS_CUI, radius_cui, msgtype, -1);
3619 if (f_radius_cui)
3620 wpa_hexdump_ascii(MSG_DEBUG, "FT: CUI", f_radius_cui,
3621 f_radius_cui_len);
3622
a6509e85
MB
3623 RRB_GET_OPTIONAL(FT_RRB_SESSION_TIMEOUT, session_timeout, msgtype,
3624 sizeof(le32));
3625 if (f_session_timeout)
3626 session_timeout = WPA_GET_LE32(f_session_timeout);
3627 else
3628 session_timeout = 0;
3629 wpa_printf(MSG_DEBUG, "FT: session_timeout %d", session_timeout);
3630
a3e18dbb
JM
3631 if (wpa_ft_store_pmk_r1(wpa_auth, f_s1kh_id, f_pmk_r1, PMK_LEN,
3632 f_pmk_r1_name,
a6509e85
MB
3633 pairwise, &vlan, expires_in, session_timeout,
3634 f_identity, f_identity_len, f_radius_cui,
069b4e30 3635 f_radius_cui_len) < 0)
245fc96e
MB
3636 goto out;
3637
3638 ret = 0;
3639out:
3640 if (plain) {
3641 os_memset(plain, 0, plain_len);
3642 os_free(plain);
3643 }
3644
3645 return ret;
6fc6879b 3646
6fc6879b
JM
3647}
3648
3649
245fc96e 3650static void ft_finish_pull(struct wpa_state_machine *sm)
692ec305 3651{
692ec305
JM
3652 int res;
3653 u8 *resp_ies;
3654 size_t resp_ies_len;
3655 u16 status;
3656
3a46cf93
MB
3657 if (!sm->ft_pending_cb || !sm->ft_pending_req_ies)
3658 return;
3659
692ec305
JM
3660 res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies),
3661 wpabuf_len(sm->ft_pending_req_ies),
3662 &resp_ies, &resp_ies_len);
3a46cf93
MB
3663 if (res < 0) {
3664 /* this loop is broken by ft_pending_pull_left_retries */
3665 wpa_printf(MSG_DEBUG,
3666 "FT: Callback postponed until response is available");
3667 return;
3668 }
692ec305
JM
3669 wpabuf_free(sm->ft_pending_req_ies);
3670 sm->ft_pending_req_ies = NULL;
692ec305
JM
3671 status = res;
3672 wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
3673 " - status %u", MAC2STR(sm->addr), status);
3674
3675 sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr,
3676 sm->ft_pending_auth_transaction + 1, status,
3677 resp_ies, resp_ies_len);
3678 os_free(resp_ies);
3679}
3680
3681
245fc96e
MB
3682struct ft_get_sta_ctx {
3683 const u8 *nonce;
3684 const u8 *s1kh_id;
3685 struct wpa_state_machine *sm;
3686};
3687
3688
3689static int ft_get_sta_cb(struct wpa_state_machine *sm, void *ctx)
692ec305 3690{
245fc96e 3691 struct ft_get_sta_ctx *info = ctx;
692ec305 3692
245fc96e
MB
3693 if ((info->s1kh_id &&
3694 os_memcmp(info->s1kh_id, sm->addr, ETH_ALEN) != 0) ||
3695 os_memcmp(info->nonce, sm->ft_pending_pull_nonce,
3696 FT_RRB_NONCE_LEN) != 0 ||
a8e25dee 3697 sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
692ec305
JM
3698 return 0;
3699
245fc96e
MB
3700 info->sm = sm;
3701
692ec305
JM
3702 return 1;
3703}
3704
3705
6fc6879b
JM
3706static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
3707 const u8 *src_addr,
245fc96e 3708 const u8 *enc, size_t enc_len,
eefe8630
MB
3709 const u8 *auth, size_t auth_len,
3710 int no_defer)
6fc6879b 3711{
245fc96e 3712 const char *msgtype = "pull response";
3a46cf93 3713 int nak, ret = -1;
245fc96e
MB
3714 struct ft_get_sta_ctx ctx;
3715 u8 s1kh_id[ETH_ALEN];
3716 const u8 *f_nonce;
3717 size_t f_nonce_len;
6fc6879b
JM
3718
3719 wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
3720
245fc96e
MB
3721 RRB_GET_AUTH(FT_RRB_NONCE, nonce, msgtype, FT_RRB_NONCE_LEN);
3722 wpa_hexdump(MSG_DEBUG, "FT: nonce", f_nonce, f_nonce_len);
6fc6879b 3723
245fc96e
MB
3724 os_memset(&ctx, 0, sizeof(ctx));
3725 ctx.nonce = f_nonce;
3726 if (!wpa_auth_for_each_sta(wpa_auth, ft_get_sta_cb, &ctx)) {
3727 /* nonce not found */
3728 wpa_printf(MSG_DEBUG, "FT: Invalid nonce");
6fc6879b
JM
3729 return -1;
3730 }
3731
245fc96e 3732 ret = wpa_ft_rrb_rx_r1(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_RESP,
eefe8630
MB
3733 enc, enc_len, auth, auth_len, msgtype, s1kh_id,
3734 no_defer ? NULL : &wpa_ft_rrb_rx_resp);
3a46cf93
MB
3735 if (ret == -2) {
3736 ret = 0;
3737 nak = 1;
3738 } else {
3739 nak = 0;
3740 }
245fc96e 3741 if (ret < 0)
6fc6879b 3742 return -1;
6fc6879b 3743
245fc96e
MB
3744 ctx.s1kh_id = s1kh_id;
3745 if (wpa_auth_for_each_sta(wpa_auth, ft_get_sta_cb, &ctx)) {
3746 wpa_printf(MSG_DEBUG,
3747 "FT: Response to a pending pull request for " MACSTR,
3748 MAC2STR(ctx.sm->addr));
3a46cf93
MB
3749 eloop_cancel_timeout(wpa_ft_expire_pull, ctx.sm, NULL);
3750 if (nak)
3751 ctx.sm->ft_pending_pull_left_retries = 0;
245fc96e 3752 ft_finish_pull(ctx.sm);
6fc6879b
JM
3753 }
3754
245fc96e
MB
3755out:
3756 return ret;
6fc6879b
JM
3757}
3758
3759
3760static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
3761 const u8 *src_addr,
245fc96e 3762 const u8 *enc, size_t enc_len,
eefe8630 3763 const u8 *auth, size_t auth_len, int no_defer)
6fc6879b 3764{
245fc96e 3765 const char *msgtype = "push";
6fc6879b
JM
3766
3767 wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push");
3768
eefe8630
MB
3769 if (wpa_ft_rrb_rx_r1(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_PUSH,
3770 enc, enc_len, auth, auth_len, msgtype, NULL,
3771 no_defer ? NULL : wpa_ft_rrb_rx_push) < 0)
6fc6879b 3772 return -1;
eefe8630
MB
3773
3774 return 0;
3775}
3776
3777
3778static int wpa_ft_rrb_rx_seq(struct wpa_authenticator *wpa_auth,
3779 const u8 *src_addr, int type,
3780 const u8 *enc, size_t enc_len,
3781 const u8 *auth, size_t auth_len,
3782 struct ft_remote_seq **rkh_seq,
3a46cf93
MB
3783 u8 **key, size_t *key_len,
3784 struct ft_remote_r0kh **r0kh_out,
3785 struct ft_remote_r1kh **r1kh_out,
3786 struct ft_remote_r0kh **r0kh_wildcard_out,
3787 struct ft_remote_r1kh **r1kh_wildcard_out)
eefe8630
MB
3788{
3789 struct ft_remote_r0kh *r0kh = NULL;
3790 struct ft_remote_r1kh *r1kh = NULL;
3791 const u8 *f_r0kh_id, *f_r1kh_id;
3792 size_t f_r0kh_id_len, f_r1kh_id_len;
3793 int to_r0kh, to_r1kh;
3794 u8 *plain = NULL;
3795 size_t plain_len = 0;
3a46cf93
MB
3796 struct ft_remote_r0kh *r0kh_wildcard;
3797 struct ft_remote_r1kh *r1kh_wildcard;
eefe8630
MB
3798
3799 RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, "seq", -1);
3800 RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, "seq", FT_R1KH_ID_LEN);
3801
3802 to_r0kh = !wpa_ft_rrb_check_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len);
3803 to_r1kh = !wpa_ft_rrb_check_r1kh(wpa_auth, f_r1kh_id);
3804
3805 if (to_r0kh && to_r1kh) {
3806 wpa_printf(MSG_DEBUG, "FT: seq - local R0KH-ID and R1KH-ID");
3807 goto out;
6fc6879b
JM
3808 }
3809
eefe8630
MB
3810 if (!to_r0kh && !to_r1kh) {
3811 wpa_printf(MSG_DEBUG, "FT: seq - remote R0KH-ID and R1KH-ID");
3812 goto out;
3813 }
3814
3815 if (!to_r0kh) {
3816 wpa_ft_rrb_lookup_r0kh(wpa_auth, f_r0kh_id, f_r0kh_id_len,
3a46cf93
MB
3817 &r0kh, &r0kh_wildcard);
3818 if (!r0kh_wildcard &&
3819 (!r0kh || os_memcmp(r0kh->addr, src_addr, ETH_ALEN) != 0)) {
eefe8630
MB
3820 wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
3821 f_r0kh_id, f_r0kh_id_len);
3822 goto out;
3823 }
3a46cf93
MB
3824 if (r0kh) {
3825 *key = r0kh->key;
3826 *key_len = sizeof(r0kh->key);
3827 } else {
3828 *key = r0kh_wildcard->key;
3829 *key_len = sizeof(r0kh_wildcard->key);
3830 }
eefe8630
MB
3831 }
3832
3833 if (!to_r1kh) {
3a46cf93
MB
3834 wpa_ft_rrb_lookup_r1kh(wpa_auth, f_r1kh_id, &r1kh,
3835 &r1kh_wildcard);
3836 if (!r1kh_wildcard &&
3837 (!r1kh || os_memcmp(r1kh->addr, src_addr, ETH_ALEN) != 0)) {
eefe8630
MB
3838 wpa_hexdump(MSG_DEBUG, "FT: Did not find R1KH-ID",
3839 f_r1kh_id, FT_R1KH_ID_LEN);
3840 goto out;
3841 }
3a46cf93
MB
3842 if (r1kh) {
3843 *key = r1kh->key;
3844 *key_len = sizeof(r1kh->key);
3845 } else {
3846 *key = r1kh_wildcard->key;
3847 *key_len = sizeof(r1kh_wildcard->key);
3848 }
eefe8630
MB
3849 }
3850
3851 if (wpa_ft_rrb_decrypt(*key, *key_len, enc, enc_len, auth, auth_len,
3852 src_addr, type, &plain, &plain_len) < 0)
3853 goto out;
3854
3855 os_free(plain);
3856
3a46cf93
MB
3857 if (!to_r0kh) {
3858 if (!r0kh)
3859 r0kh = wpa_ft_rrb_add_r0kh(wpa_auth, r0kh_wildcard,
3860 src_addr, f_r0kh_id,
3861 f_r0kh_id_len,
3862 ftRRBseqTimeout);
3863 if (!r0kh)
3864 goto out;
3865
3866 wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh, ftRRBseqTimeout);
3867 *rkh_seq = r0kh->seq;
3868 if (r0kh_out)
3869 *r0kh_out = r0kh;
3870 if (r0kh_wildcard_out)
3871 *r0kh_wildcard_out = r0kh_wildcard;
3872 }
3873
3874 if (!to_r1kh) {
3875 if (!r1kh)
3876 r1kh = wpa_ft_rrb_add_r1kh(wpa_auth, r1kh_wildcard,
3877 src_addr, f_r1kh_id,
3878 ftRRBseqTimeout);
3879 if (!r1kh)
3880 goto out;
3881
3882 wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh, ftRRBseqTimeout);
3883 *rkh_seq = r1kh->seq;
3884 if (r1kh_out)
3885 *r1kh_out = r1kh;
3886 if (r1kh_wildcard_out)
3887 *r1kh_wildcard_out = r1kh_wildcard;
3888 }
3889
eefe8630
MB
3890 return 0;
3891out:
3892 return -1;
3893}
3894
3895
3896static int wpa_ft_rrb_rx_seq_req(struct wpa_authenticator *wpa_auth,
3897 const u8 *src_addr,
3898 const u8 *enc, size_t enc_len,
3899 const u8 *auth, size_t auth_len,
3900 int no_defer)
3901{
3902 int ret = -1;
3903 struct ft_rrb_seq f_seq;
3904 const u8 *f_nonce, *f_r0kh_id, *f_r1kh_id;
3905 size_t f_nonce_len, f_r0kh_id_len, f_r1kh_id_len;
3a46cf93 3906 struct ft_remote_seq *rkh_seq = NULL;
eefe8630
MB
3907 u8 *packet = NULL, *key = NULL;
3908 size_t packet_len = 0, key_len = 0;
3909 struct tlv_list seq_resp_auth[5];
3910
3911 wpa_printf(MSG_DEBUG, "FT: Received sequence number request");
3912
3913 if (wpa_ft_rrb_rx_seq(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
3914 enc, enc_len, auth, auth_len, &rkh_seq, &key,
3a46cf93 3915 &key_len, NULL, NULL, NULL, NULL) < 0)
eefe8630
MB
3916 goto out;
3917
3918 RRB_GET_AUTH(FT_RRB_NONCE, nonce, "seq request", FT_RRB_NONCE_LEN);
3919 wpa_hexdump(MSG_DEBUG, "FT: seq request - nonce", f_nonce, f_nonce_len);
3920
3921 RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, "seq", -1);
3922 RRB_GET_AUTH(FT_RRB_R1KH_ID, r1kh_id, "seq", FT_R1KH_ID_LEN);
3923
3924 if (wpa_ft_new_seq(rkh_seq, &f_seq) < 0) {
3925 wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
3926 goto out;
3927 }
3928
3929 seq_resp_auth[0].type = FT_RRB_NONCE;
3930 seq_resp_auth[0].len = f_nonce_len;
3931 seq_resp_auth[0].data = f_nonce;
3932 seq_resp_auth[1].type = FT_RRB_SEQ;
3933 seq_resp_auth[1].len = sizeof(f_seq);
3934 seq_resp_auth[1].data = (u8 *) &f_seq;
3935 seq_resp_auth[2].type = FT_RRB_R0KH_ID;
3936 seq_resp_auth[2].len = f_r0kh_id_len;
3937 seq_resp_auth[2].data = f_r0kh_id;
3938 seq_resp_auth[3].type = FT_RRB_R1KH_ID;
3939 seq_resp_auth[3].len = FT_R1KH_ID_LEN;
3940 seq_resp_auth[3].data = f_r1kh_id;
3941 seq_resp_auth[4].type = FT_RRB_LAST_EMPTY;
3942 seq_resp_auth[4].len = 0;
3943 seq_resp_auth[4].data = NULL;
3944
17010c38 3945 if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_resp_auth, NULL,
eefe8630
MB
3946 wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_RESP,
3947 &packet, &packet_len) < 0)
3948 goto out;
3949
3950 wpa_ft_rrb_oui_send(wpa_auth, src_addr,
3951 FT_PACKET_R0KH_R1KH_SEQ_RESP, packet,
3952 packet_len);
3953
3954out:
3955 os_free(packet);
3956
3957 return ret;
3958}
3959
3960
3961static int wpa_ft_rrb_rx_seq_resp(struct wpa_authenticator *wpa_auth,
3962 const u8 *src_addr,
3963 const u8 *enc, size_t enc_len,
3964 const u8 *auth, size_t auth_len,
3965 int no_defer)
3966{
3967 u8 *key = NULL;
3968 size_t key_len = 0;
3a46cf93
MB
3969 struct ft_remote_r0kh *r0kh = NULL, *r0kh_wildcard = NULL;
3970 struct ft_remote_r1kh *r1kh = NULL, *r1kh_wildcard = NULL;
eefe8630
MB
3971 const u8 *f_nonce, *f_seq;
3972 size_t f_nonce_len, f_seq_len;
3973 struct ft_remote_seq *rkh_seq = NULL;
3974 struct ft_remote_item *item;
3975 struct os_reltime now, now_remote;
3976 int seq_ret, found;
3977 const struct ft_rrb_seq *msg_both;
3978 u32 msg_dom, msg_seq;
3979
3980 wpa_printf(MSG_DEBUG, "FT: Received sequence number response");
3981
3982 if (wpa_ft_rrb_rx_seq(wpa_auth, src_addr, FT_PACKET_R0KH_R1KH_SEQ_RESP,
3983 enc, enc_len, auth, auth_len, &rkh_seq, &key,
3a46cf93
MB
3984 &key_len, &r0kh, &r1kh, &r0kh_wildcard,
3985 &r1kh_wildcard) < 0)
eefe8630
MB
3986 goto out;
3987
3988 RRB_GET_AUTH(FT_RRB_NONCE, nonce, "seq response", FT_RRB_NONCE_LEN);
3989 wpa_hexdump(MSG_DEBUG, "FT: seq response - nonce", f_nonce,
3990 f_nonce_len);
3991
3992 found = 0;
3993 dl_list_for_each(item, &rkh_seq->rx.queue, struct ft_remote_item,
3994 list) {
3995 if (os_memcmp_const(f_nonce, item->nonce,
3996 FT_RRB_NONCE_LEN) != 0 ||
3997 os_get_reltime(&now) < 0 ||
3998 os_reltime_expired(&now, &item->nonce_ts, ftRRBseqTimeout))
3999 continue;
4000
4001 found = 1;
4002 break;
4003 }
4004 if (!found) {
4005 wpa_printf(MSG_DEBUG, "FT: seq response - bad nonce");
4006 goto out;
4007 }
4008
3a46cf93
MB
4009 if (r0kh) {
4010 wpa_ft_rrb_r0kh_replenish(wpa_auth, r0kh,
4011 wpa_auth->conf.rkh_pos_timeout);
4012 if (r0kh_wildcard)
4013 os_memcpy(r0kh->addr, src_addr, ETH_ALEN);
4014 }
4015
4016 if (r1kh) {
4017 wpa_ft_rrb_r1kh_replenish(wpa_auth, r1kh,
4018 wpa_auth->conf.rkh_pos_timeout);
4019 if (r1kh_wildcard)
4020 os_memcpy(r1kh->addr, src_addr, ETH_ALEN);
4021 }
4022
eefe8630
MB
4023 seq_ret = wpa_ft_rrb_seq_chk(rkh_seq, src_addr, enc, enc_len, auth,
4024 auth_len, "seq response", 1);
4025 if (seq_ret == FT_RRB_SEQ_OK) {
4026 wpa_printf(MSG_DEBUG, "FT: seq response - valid seq number");
4027 wpa_ft_rrb_seq_accept(wpa_auth, rkh_seq, src_addr, auth,
4028 auth_len, "seq response");
4029 } else {
4030 wpa_printf(MSG_DEBUG, "FT: seq response - reset seq number");
4031
4032 RRB_GET_AUTH(FT_RRB_SEQ, seq, "seq response",
4033 sizeof(*msg_both));
4034 msg_both = (const struct ft_rrb_seq *) f_seq;
4035
4036 msg_dom = le_to_host32(msg_both->dom);
4037 msg_seq = le_to_host32(msg_both->seq);
4038 now_remote.sec = le_to_host32(msg_both->ts);
4039 now_remote.usec = 0;
4040
4041 rkh_seq->rx.num_last = 2;
4042 rkh_seq->rx.dom = msg_dom;
4043 rkh_seq->rx.offsetidx = 0;
4044 /* Accept some older, possibly cached packets as well */
4045 rkh_seq->rx.last[0] = msg_seq - FT_REMOTE_SEQ_BACKLOG -
4046 dl_list_len(&rkh_seq->rx.queue);
4047 rkh_seq->rx.last[1] = msg_seq;
4048
4049 /* local time - offset = remote time
4050 * <=> local time - remote time = offset */
4051 os_reltime_sub(&now, &now_remote, &rkh_seq->rx.time_offset);
4052 }
4053
4054 wpa_ft_rrb_seq_flush(wpa_auth, rkh_seq, 1);
6fc6879b
JM
4055
4056 return 0;
245fc96e
MB
4057out:
4058 return -1;
6fc6879b
JM
4059}
4060
4061
4062int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
4063 const u8 *data, size_t data_len)
4064{
4065 struct ft_rrb_frame *frame;
4066 u16 alen;
4067 const u8 *pos, *end, *start;
4068 u8 action;
4069 const u8 *sta_addr, *target_ap_addr;
4070
4071 wpa_printf(MSG_DEBUG, "FT: RRB received frame from remote AP " MACSTR,
4072 MAC2STR(src_addr));
4073
4074 if (data_len < sizeof(*frame)) {
4075 wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (data_len=%lu)",
4076 (unsigned long) data_len);
4077 return -1;
4078 }
4079
4080 pos = data;
4081 frame = (struct ft_rrb_frame *) pos;
4082 pos += sizeof(*frame);
4083
4084 alen = le_to_host16(frame->action_length);
4085 wpa_printf(MSG_DEBUG, "FT: RRB frame - frame_type=%d packet_type=%d "
4086 "action_length=%d ap_address=" MACSTR,
4087 frame->frame_type, frame->packet_type, alen,
4088 MAC2STR(frame->ap_address));
4089
4090 if (frame->frame_type != RSN_REMOTE_FRAME_TYPE_FT_RRB) {
c1e033b0 4091 /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */
6fc6879b
JM
4092 wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with "
4093 "unrecognized type %d", frame->frame_type);
4094 return -1;
4095 }
4096
4097 if (alen > data_len - sizeof(*frame)) {
4098 wpa_printf(MSG_DEBUG, "FT: RRB frame too short for action "
4099 "frame");
4100 return -1;
4101 }
4102
6fc6879b
JM
4103 wpa_hexdump(MSG_MSGDUMP, "FT: RRB - FT Action frame", pos, alen);
4104
4105 if (alen < 1 + 1 + 2 * ETH_ALEN) {
4106 wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (not enough "
4107 "room for Action Frame body); alen=%lu",
4108 (unsigned long) alen);
4109 return -1;
4110 }
4111 start = pos;
4112 end = pos + alen;
4113
4114 if (*pos != WLAN_ACTION_FT) {
4115 wpa_printf(MSG_DEBUG, "FT: Unexpected Action frame category "
4116 "%d", *pos);
4117 return -1;
4118 }
4119
4120 pos++;
4121 action = *pos++;
4122 sta_addr = pos;
4123 pos += ETH_ALEN;
4124 target_ap_addr = pos;
4125 pos += ETH_ALEN;
4126 wpa_printf(MSG_DEBUG, "FT: RRB Action Frame: action=%d sta_addr="
4127 MACSTR " target_ap_addr=" MACSTR,
4128 action, MAC2STR(sta_addr), MAC2STR(target_ap_addr));
4129
4130 if (frame->packet_type == FT_PACKET_REQUEST) {
4131 wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Request");
4132
4133 if (action != 1) {
4134 wpa_printf(MSG_DEBUG, "FT: Unexpected Action %d in "
4135 "RRB Request", action);
4136 return -1;
4137 }
4138
4139 if (os_memcmp(target_ap_addr, wpa_auth->addr, ETH_ALEN) != 0) {
4140 wpa_printf(MSG_DEBUG, "FT: Target AP address in the "
4141 "RRB Request does not match with own "
4142 "address");
4143 return -1;
4144 }
4145
4146 if (wpa_ft_rrb_rx_request(wpa_auth, frame->ap_address,
4147 sta_addr, pos, end - pos) < 0)
4148 return -1;
4149 } else if (frame->packet_type == FT_PACKET_RESPONSE) {
4150 u16 status_code;
4151
4152 if (end - pos < 2) {
4153 wpa_printf(MSG_DEBUG, "FT: Not enough room for status "
4154 "code in RRB Response");
4155 return -1;
4156 }
4157 status_code = WPA_GET_LE16(pos);
4158 pos += 2;
4159
4160 wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response "
4161 "(status_code=%d)", status_code);
4162
4163 if (wpa_ft_action_send(wpa_auth, sta_addr, start, alen) < 0)
4164 return -1;
4165 } else {
4166 wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with unknown "
4167 "packet_type %d", frame->packet_type);
4168 return -1;
4169 }
4170
164a453f
JM
4171 if (end > pos) {
4172 wpa_hexdump(MSG_DEBUG, "FT: Ignore extra data in end",
4173 pos, end - pos);
4174 }
4175
6fc6879b
JM
4176 return 0;
4177}
4178
4179
50bd8e0a
MB
4180void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
4181 const u8 *dst_addr, u8 oui_suffix, const u8 *data,
4182 size_t data_len)
4183{
245fc96e
MB
4184 const u8 *auth, *enc;
4185 size_t alen, elen;
3a46cf93 4186 int no_defer = 0;
245fc96e 4187
50bd8e0a
MB
4188 wpa_printf(MSG_DEBUG, "FT: RRB-OUI received frame from remote AP "
4189 MACSTR, MAC2STR(src_addr));
4190 wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame - oui_suffix=%d", oui_suffix);
4191
4192 if (is_multicast_ether_addr(src_addr)) {
4193 wpa_printf(MSG_DEBUG,
4194 "FT: RRB-OUI received frame from multicast address "
4195 MACSTR, MAC2STR(src_addr));
4196 return;
4197 }
4198
4199 if (is_multicast_ether_addr(dst_addr)) {
4200 wpa_printf(MSG_DEBUG,
4201 "FT: RRB-OUI received frame from remote AP " MACSTR
4202 " to multicast address " MACSTR,
4203 MAC2STR(src_addr), MAC2STR(dst_addr));
3a46cf93 4204 no_defer = 1;
50bd8e0a
MB
4205 }
4206
245fc96e
MB
4207 if (data_len < sizeof(u16)) {
4208 wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short");
4209 return;
4210 }
4211
4212 alen = WPA_GET_LE16(data);
4213 if (data_len < sizeof(u16) + alen) {
4214 wpa_printf(MSG_DEBUG, "FT: RRB-OUI frame too short");
4215 return;
4216 }
4217
4218 auth = data + sizeof(u16);
4219 enc = data + sizeof(u16) + alen;
4220 elen = data_len - sizeof(u16) - alen;
4221
50bd8e0a
MB
4222 switch (oui_suffix) {
4223 case FT_PACKET_R0KH_R1KH_PULL:
eefe8630 4224 wpa_ft_rrb_rx_pull(wpa_auth, src_addr, enc, elen, auth, alen,
3a46cf93 4225 no_defer);
50bd8e0a
MB
4226 break;
4227 case FT_PACKET_R0KH_R1KH_RESP:
eefe8630 4228 wpa_ft_rrb_rx_resp(wpa_auth, src_addr, enc, elen, auth, alen,
3a46cf93 4229 no_defer);
50bd8e0a
MB
4230 break;
4231 case FT_PACKET_R0KH_R1KH_PUSH:
eefe8630 4232 wpa_ft_rrb_rx_push(wpa_auth, src_addr, enc, elen, auth, alen,
3a46cf93 4233 no_defer);
eefe8630
MB
4234 break;
4235 case FT_PACKET_R0KH_R1KH_SEQ_REQ:
4236 wpa_ft_rrb_rx_seq_req(wpa_auth, src_addr, enc, elen, auth, alen,
3a46cf93 4237 no_defer);
eefe8630
MB
4238 break;
4239 case FT_PACKET_R0KH_R1KH_SEQ_RESP:
4240 wpa_ft_rrb_rx_seq_resp(wpa_auth, src_addr, enc, elen, auth,
3a46cf93 4241 alen, no_defer);
50bd8e0a
MB
4242 break;
4243 }
4244}
4245
4246
364c064a
JM
4247static int wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
4248 struct wpa_ft_pmk_r0_sa *pmk_r0,
4249 struct ft_remote_r1kh *r1kh,
245fc96e 4250 const u8 *s1kh_id)
6fc6879b 4251{
245fc96e
MB
4252 u8 *packet;
4253 size_t packet_len;
eefe8630 4254 struct ft_rrb_seq f_seq;
245fc96e
MB
4255 struct tlv_list push[] = {
4256 { .type = FT_RRB_S1KH_ID, .len = ETH_ALEN,
4257 .data = s1kh_id },
4258 { .type = FT_RRB_PMK_R0_NAME, .len = WPA_PMK_NAME_LEN,
4259 .data = pmk_r0->pmk_r0_name },
4260 { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
4261 };
4262 struct tlv_list push_auth[] = {
eefe8630
MB
4263 { .type = FT_RRB_SEQ, .len = sizeof(f_seq),
4264 .data = (u8 *) &f_seq },
245fc96e
MB
4265 { .type = FT_RRB_R0KH_ID,
4266 .len = wpa_auth->conf.r0_key_holder_len,
4267 .data = wpa_auth->conf.r0_key_holder },
4268 { .type = FT_RRB_R1KH_ID, .len = FT_R1KH_ID_LEN,
4269 .data = r1kh->id },
4270 { .type = FT_RRB_LAST_EMPTY, .len = 0, .data = NULL },
4271 };
4272
eefe8630
MB
4273 if (wpa_ft_new_seq(r1kh->seq, &f_seq) < 0) {
4274 wpa_printf(MSG_DEBUG, "FT: Failed to get seq num");
4275 return -1;
4276 }
245fc96e
MB
4277
4278 if (wpa_ft_rrb_build_r0(r1kh->key, sizeof(r1kh->key), push, pmk_r0,
4279 r1kh->id, s1kh_id, push_auth, wpa_auth->addr,
4280 FT_PACKET_R0KH_R1KH_PUSH,
4281 &packet, &packet_len) < 0)
364c064a 4282 return -1;
6fc6879b 4283
50bd8e0a 4284 wpa_ft_rrb_oui_send(wpa_auth, r1kh->addr, FT_PACKET_R0KH_R1KH_PUSH,
245fc96e
MB
4285 packet, packet_len);
4286
4287 os_free(packet);
364c064a 4288 return 0;
6fc6879b
JM
4289}
4290
4291
4292void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
4293{
09211c98
MB
4294 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
4295 struct wpa_ft_pmk_r0_sa *r0, *r0found = NULL;
6fc6879b
JM
4296 struct ft_remote_r1kh *r1kh;
4297
4298 if (!wpa_auth->conf.pmk_r1_push)
4299 return;
3a46cf93
MB
4300 if (!wpa_auth->conf.r1kh_list)
4301 return;
6fc6879b 4302
09211c98
MB
4303 dl_list_for_each(r0, &cache->pmk_r0, struct wpa_ft_pmk_r0_sa, list) {
4304 if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0) {
4305 r0found = r0;
6fc6879b 4306 break;
09211c98 4307 }
6fc6879b
JM
4308 }
4309
09211c98 4310 r0 = r0found;
6fc6879b
JM
4311 if (r0 == NULL || r0->pmk_r1_pushed)
4312 return;
4313 r0->pmk_r1_pushed = 1;
4314
4315 wpa_printf(MSG_DEBUG, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
4316 "for STA " MACSTR, MAC2STR(addr));
4317
3a46cf93
MB
4318 for (r1kh = *wpa_auth->conf.r1kh_list; r1kh; r1kh = r1kh->next) {
4319 if (is_zero_ether_addr(r1kh->addr) ||
4320 is_zero_ether_addr(r1kh->id))
4321 continue;
eefe8630
MB
4322 if (wpa_ft_rrb_init_r1kh_seq(r1kh) < 0)
4323 continue;
245fc96e 4324 wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr);
6fc6879b
JM
4325 }
4326}
4327
4ec1fd8e 4328#endif /* CONFIG_IEEE80211R_AP */