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