2 * hostapd - IEEE 802.11r - Fast BSS Transition
3 * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
9 #include "utils/includes.h"
11 #include "utils/common.h"
12 #include "utils/eloop.h"
13 #include "utils/list.h"
14 #include "common/ieee802_11_defs.h"
15 #include "common/ieee802_11_common.h"
16 #include "crypto/aes.h"
17 #include "crypto/aes_siv.h"
18 #include "crypto/aes_wrap.h"
19 #include "crypto/random.h"
20 #include "ap_config.h"
21 #include "ieee802_11.h"
24 #include "wpa_auth_i.h"
27 #ifdef CONFIG_IEEE80211R_AP
29 static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine
*sm
,
30 const u8
*current_ap
, const u8
*sta_addr
,
31 u16 status
, const u8
*resp_ies
,
42 * wpa_ft_rrb_decrypt - Decrypt FT RRB message
43 * @key: AES-SIV key for AEAD
44 * @key_len: Length of key in octets
45 * @enc: Pointer to encrypted TLVs
46 * @enc_len: Length of encrypted TLVs in octets
47 * @auth: Pointer to authenticated TLVs
48 * @auth_len: Length of authenticated TLVs in octets
49 * @src_addr: MAC address of the frame sender
50 * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*)
51 * @plain: Pointer to return the pointer to the allocated plaintext buffer;
52 * needs to be freed by the caller if not NULL;
53 * will only be returned on success
54 * @plain_len: Pointer to return the length of the allocated plaintext buffer
56 * Returns: 0 on success, -1 on error
58 static int wpa_ft_rrb_decrypt(const u8
*key
, const size_t key_len
,
59 const u8
*enc
, const size_t enc_len
,
60 const u8
*auth
, const size_t auth_len
,
61 const u8
*src_addr
, u8 type
,
62 u8
**plain
, size_t *plain_size
)
64 const u8
*ad
[3] = { src_addr
, auth
, &type
};
65 size_t ad_len
[3] = { ETH_ALEN
, auth_len
, sizeof(type
) };
67 wpa_hexdump_key(MSG_DEBUG
, "FT(RRB): decrypt using key", key
, key_len
);
69 if (!key
) { /* skip decryption */
70 *plain
= os_memdup(enc
, enc_len
);
71 if (enc_len
> 0 && !*plain
)
74 *plain_size
= enc_len
;
82 if (enc_len
< AES_BLOCK_SIZE
)
85 *plain
= os_zalloc(enc_len
- AES_BLOCK_SIZE
);
89 if (aes_siv_decrypt(key
, key_len
, enc
, enc_len
, 3, ad
, ad_len
,
93 *plain_size
= enc_len
- AES_BLOCK_SIZE
;
94 wpa_hexdump_key(MSG_DEBUG
, "FT(RRB): decrypted TLVs",
102 wpa_printf(MSG_ERROR
, "FT(RRB): Failed to decrypt");
108 /* get first tlv record in packet matching type
109 * @data (decrypted) packet
110 * @return 0 on success else -1
112 static int wpa_ft_rrb_get_tlv(const u8
*plain
, size_t plain_len
,
113 u16 type
, size_t *tlv_len
, const u8
**tlv_data
)
115 const struct ft_rrb_tlv
*f
;
121 type16
= host_to_le16(type
);
123 while (left
>= sizeof(*f
)) {
124 f
= (const struct ft_rrb_tlv
*) plain
;
128 len
= le_to_host16(f
->len
);
131 wpa_printf(MSG_DEBUG
, "FT: RRB message truncated");
135 if (f
->type
== type16
) {
149 static void wpa_ft_rrb_dump(const u8
*plain
, const size_t plain_len
)
151 const struct ft_rrb_tlv
*f
;
157 wpa_printf(MSG_DEBUG
, "FT: RRB dump message");
158 while (left
>= sizeof(*f
)) {
159 f
= (const struct ft_rrb_tlv
*) plain
;
163 len
= le_to_host16(f
->len
);
165 wpa_printf(MSG_DEBUG
, "FT: RRB TLV type = %d, len = %zu",
166 le_to_host16(f
->type
), len
);
169 wpa_printf(MSG_DEBUG
,
170 "FT: RRB message truncated: left %zu bytes, need %zu",
175 wpa_hexdump(MSG_DEBUG
, "FT: RRB TLV data", plain
, len
);
182 wpa_hexdump(MSG_DEBUG
, "FT: RRB TLV padding", plain
, left
);
184 wpa_printf(MSG_DEBUG
, "FT: RRB dump message end");
188 static size_t wpa_ft_tlv_len(const struct tlv_list
*tlvs
)
196 for (i
= 0; tlvs
[i
].type
!= FT_RRB_LAST_EMPTY
; i
++) {
197 tlv_len
+= sizeof(struct ft_rrb_tlv
);
198 tlv_len
+= tlvs
[i
].len
;
205 static size_t wpa_ft_tlv_lin(const struct tlv_list
*tlvs
, u8
*start
,
210 struct ft_rrb_tlv
*hdr
;
218 for (i
= 0; tlvs
[i
].type
!= FT_RRB_LAST_EMPTY
; i
++) {
219 if (tlv_len
+ sizeof(*hdr
) > (size_t) (endpos
- start
))
221 tlv_len
+= sizeof(*hdr
);
222 hdr
= (struct ft_rrb_tlv
*) pos
;
223 hdr
->type
= host_to_le16(tlvs
[i
].type
);
224 hdr
->len
= host_to_le16(tlvs
[i
].len
);
225 pos
= start
+ tlv_len
;
227 if (tlv_len
+ tlvs
[i
].len
> (size_t) (endpos
- start
))
229 tlv_len
+= tlvs
[i
].len
;
230 os_memcpy(pos
, tlvs
[i
].data
, tlvs
[i
].len
);
231 pos
= start
+ tlv_len
;
238 static int wpa_ft_rrb_lin(const struct tlv_list
*tlvs1
,
239 const struct tlv_list
*tlvs2
,
240 u8
**plain
, size_t *plain_len
)
245 tlv_len
= wpa_ft_tlv_len(tlvs1
);
246 tlv_len
+= wpa_ft_tlv_len(tlvs2
);
248 *plain_len
= tlv_len
;
249 *plain
= os_zalloc(tlv_len
);
251 wpa_printf(MSG_ERROR
, "FT: Failed to allocate plaintext");
256 endpos
= *plain
+ tlv_len
;
257 pos
+= wpa_ft_tlv_lin(tlvs1
, pos
, endpos
);
258 pos
+= wpa_ft_tlv_lin(tlvs2
, pos
, endpos
);
262 wpa_printf(MSG_ERROR
, "FT: Length error building RRB");
276 static int wpa_ft_rrb_encrypt(const u8
*key
, const size_t key_len
,
277 const u8
*plain
, const size_t plain_len
,
278 const u8
*auth
, const size_t auth_len
,
279 const u8
*src_addr
, u8 type
, u8
*enc
)
281 const u8
*ad
[3] = { src_addr
, auth
, &type
};
282 size_t ad_len
[3] = { ETH_ALEN
, auth_len
, sizeof(type
) };
284 wpa_hexdump_key(MSG_DEBUG
, "FT(RRB): plaintext message",
286 wpa_hexdump_key(MSG_DEBUG
, "FT(RRB): encrypt using key", key
, key_len
);
289 /* encryption not needed, return plaintext as packet */
290 os_memcpy(enc
, plain
, plain_len
);
291 } else if (aes_siv_encrypt(key
, key_len
, plain
, plain_len
,
292 3, ad
, ad_len
, enc
) < 0) {
293 wpa_printf(MSG_ERROR
, "FT: Failed to encrypt RRB-OUI message");
302 * wpa_ft_rrb_build - Build and encrypt an FT RRB message
303 * @key: AES-SIV key for AEAD
304 * @key_len: Length of key in octets
305 * @tlvs_enc0: First set of to-be-encrypted TLVs
306 * @tlvs_enc1: Second set of to-be-encrypted TLVs
307 * @tlvs_auth: Set of to-be-authenticated TLVs
308 * @src_addr: MAC address of the frame sender
309 * @type: Vendor-specific subtype of the RRB frame (FT_PACKET_*)
310 * @packet Pointer to return the pointer to the allocated packet buffer;
311 * needs to be freed by the caller if not null;
312 * will only be returned on success
313 * @packet_len: Pointer to return the length of the allocated buffer in octets
314 * Returns: 0 on success, -1 on error
316 static int wpa_ft_rrb_build(const u8
*key
, const size_t key_len
,
317 const struct tlv_list
*tlvs_enc0
,
318 const struct tlv_list
*tlvs_enc1
,
319 const struct tlv_list
*tlvs_auth
,
320 const u8
*src_addr
, u8 type
,
321 u8
**packet
, size_t *packet_len
)
323 u8
*plain
= NULL
, *auth
= NULL
, *pos
;
324 size_t plain_len
= 0, auth_len
= 0;
327 if (wpa_ft_rrb_lin(tlvs_enc0
, tlvs_enc1
, &plain
, &plain_len
) < 0)
330 if (wpa_ft_rrb_lin(tlvs_auth
, NULL
, &auth
, &auth_len
) < 0)
333 *packet_len
= sizeof(u16
) + auth_len
+ plain_len
;
335 *packet_len
+= AES_BLOCK_SIZE
;
336 *packet
= os_zalloc(*packet_len
);
341 WPA_PUT_LE16(pos
, auth_len
);
343 os_memcpy(pos
, auth
, auth_len
);
345 if (wpa_ft_rrb_encrypt(key
, key_len
, plain
, plain_len
, auth
,
346 auth_len
, src_addr
, type
, pos
) < 0)
352 bin_clear_free(plain
, plain_len
);
356 wpa_printf(MSG_ERROR
, "FT: Failed to build RRB-OUI message");
366 #define RRB_GET_SRC(srcfield, type, field, txt, checklength) do { \
367 if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \
368 &f_##field##_len, &f_##field) < 0 || \
369 (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
370 wpa_printf(MSG_INFO, "FT: Missing required " #field \
371 " in %s from " MACSTR, txt, MAC2STR(src_addr)); \
372 wpa_ft_rrb_dump(srcfield, srcfield##_len); \
377 #define RRB_GET(type, field, txt, checklength) \
378 RRB_GET_SRC(plain, type, field, txt, checklength)
379 #define RRB_GET_AUTH(type, field, txt, checklength) \
380 RRB_GET_SRC(auth, type, field, txt, checklength)
382 #define RRB_GET_OPTIONAL_SRC(srcfield, type, field, txt, checklength) do { \
383 if (wpa_ft_rrb_get_tlv(srcfield, srcfield##_len, type, \
384 &f_##field##_len, &f_##field) < 0 || \
385 (checklength > 0 && ((size_t) checklength) != f_##field##_len)) { \
386 wpa_printf(MSG_DEBUG, "FT: Missing optional " #field \
387 " in %s from " MACSTR, txt, MAC2STR(src_addr)); \
388 f_##field##_len = 0; \
393 #define RRB_GET_OPTIONAL(type, field, txt, checklength) \
394 RRB_GET_OPTIONAL_SRC(plain, type, field, txt, checklength)
395 #define RRB_GET_OPTIONAL_AUTH(type, field, txt, checklength) \
396 RRB_GET_OPTIONAL_SRC(auth, type, field, txt, checklength)
398 static int wpa_ft_rrb_send(struct wpa_authenticator
*wpa_auth
, const u8
*dst
,
399 const u8
*data
, size_t data_len
)
401 if (wpa_auth
->cb
->send_ether
== NULL
)
403 wpa_printf(MSG_DEBUG
, "FT: RRB send to " MACSTR
, MAC2STR(dst
));
404 return wpa_auth
->cb
->send_ether(wpa_auth
->cb_ctx
, dst
, ETH_P_RRB
,
409 static int wpa_ft_rrb_oui_send(struct wpa_authenticator
*wpa_auth
,
410 const u8
*dst
, u8 oui_suffix
,
411 const u8
*data
, size_t data_len
)
413 if (!wpa_auth
->cb
->send_oui
)
415 wpa_printf(MSG_DEBUG
, "FT: RRB-OUI type %u send to " MACSTR
,
416 oui_suffix
, MAC2STR(dst
));
417 return wpa_auth
->cb
->send_oui(wpa_auth
->cb_ctx
, dst
, oui_suffix
, data
,
422 static int wpa_ft_action_send(struct wpa_authenticator
*wpa_auth
,
423 const u8
*dst
, const u8
*data
, size_t data_len
)
425 if (wpa_auth
->cb
->send_ft_action
== NULL
)
427 return wpa_auth
->cb
->send_ft_action(wpa_auth
->cb_ctx
, dst
,
432 static const u8
* wpa_ft_get_psk(struct wpa_authenticator
*wpa_auth
,
433 const u8
*addr
, const u8
*p2p_dev_addr
,
436 if (wpa_auth
->cb
->get_psk
== NULL
)
438 return wpa_auth
->cb
->get_psk(wpa_auth
->cb_ctx
, addr
, p2p_dev_addr
,
443 static struct wpa_state_machine
*
444 wpa_ft_add_sta(struct wpa_authenticator
*wpa_auth
, const u8
*sta_addr
)
446 if (wpa_auth
->cb
->add_sta
== NULL
)
448 return wpa_auth
->cb
->add_sta(wpa_auth
->cb_ctx
, sta_addr
);
452 static int wpa_ft_add_tspec(struct wpa_authenticator
*wpa_auth
,
454 u8
*tspec_ie
, size_t tspec_ielen
)
456 if (wpa_auth
->cb
->add_tspec
== NULL
) {
457 wpa_printf(MSG_DEBUG
, "FT: add_tspec is not initialized");
460 return wpa_auth
->cb
->add_tspec(wpa_auth
->cb_ctx
, sta_addr
, tspec_ie
,
465 int wpa_write_mdie(struct wpa_auth_config
*conf
, u8
*buf
, size_t len
)
469 if (len
< 2 + sizeof(struct rsn_mdie
))
472 *pos
++ = WLAN_EID_MOBILITY_DOMAIN
;
473 *pos
++ = MOBILITY_DOMAIN_ID_LEN
+ 1;
474 os_memcpy(pos
, conf
->mobility_domain
, MOBILITY_DOMAIN_ID_LEN
);
475 pos
+= MOBILITY_DOMAIN_ID_LEN
;
477 if (conf
->ft_over_ds
)
478 capab
|= RSN_FT_CAPAB_FT_OVER_DS
;
485 int wpa_write_ftie(struct wpa_auth_config
*conf
, const u8
*r0kh_id
,
487 const u8
*anonce
, const u8
*snonce
,
488 u8
*buf
, size_t len
, const u8
*subelem
,
491 u8
*pos
= buf
, *ielen
;
492 struct rsn_ftie
*hdr
;
494 if (len
< 2 + sizeof(*hdr
) + 2 + FT_R1KH_ID_LEN
+ 2 + r0kh_id_len
+
498 *pos
++ = WLAN_EID_FAST_BSS_TRANSITION
;
501 hdr
= (struct rsn_ftie
*) pos
;
502 os_memset(hdr
, 0, sizeof(*hdr
));
504 WPA_PUT_LE16(hdr
->mic_control
, 0);
506 os_memcpy(hdr
->anonce
, anonce
, WPA_NONCE_LEN
);
508 os_memcpy(hdr
->snonce
, snonce
, WPA_NONCE_LEN
);
510 /* Optional Parameters */
511 *pos
++ = FTIE_SUBELEM_R1KH_ID
;
512 *pos
++ = FT_R1KH_ID_LEN
;
513 os_memcpy(pos
, conf
->r1_key_holder
, FT_R1KH_ID_LEN
);
514 pos
+= FT_R1KH_ID_LEN
;
517 *pos
++ = FTIE_SUBELEM_R0KH_ID
;
518 *pos
++ = r0kh_id_len
;
519 os_memcpy(pos
, r0kh_id
, r0kh_id_len
);
524 os_memcpy(pos
, subelem
, subelem_len
);
528 *ielen
= pos
- buf
- 2;
534 struct wpa_ft_pmk_r0_sa
{
535 struct wpa_ft_pmk_r0_sa
*next
;
537 u8 pmk_r0_name
[WPA_PMK_NAME_LEN
];
539 int pairwise
; /* Pairwise cipher suite, WPA_CIPHER_* */
540 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
544 struct wpa_ft_pmk_r1_sa
{
545 struct wpa_ft_pmk_r1_sa
*next
;
547 u8 pmk_r1_name
[WPA_PMK_NAME_LEN
];
549 int pairwise
; /* Pairwise cipher suite, WPA_CIPHER_* */
550 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
553 struct wpa_ft_pmk_cache
{
554 struct wpa_ft_pmk_r0_sa
*pmk_r0
;
555 struct wpa_ft_pmk_r1_sa
*pmk_r1
;
558 struct wpa_ft_pmk_cache
* wpa_ft_pmk_cache_init(void)
560 struct wpa_ft_pmk_cache
*cache
;
562 cache
= os_zalloc(sizeof(*cache
));
568 void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache
*cache
)
570 struct wpa_ft_pmk_r0_sa
*r0
, *r0prev
;
571 struct wpa_ft_pmk_r1_sa
*r1
, *r1prev
;
577 os_memset(r0prev
->pmk_r0
, 0, PMK_LEN
);
585 os_memset(r1prev
->pmk_r1
, 0, PMK_LEN
);
593 static int wpa_ft_store_pmk_r0(struct wpa_authenticator
*wpa_auth
,
594 const u8
*spa
, const u8
*pmk_r0
,
595 const u8
*pmk_r0_name
, int pairwise
)
597 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
598 struct wpa_ft_pmk_r0_sa
*r0
;
600 /* TODO: add expiration and limit on number of entries in cache */
602 r0
= os_zalloc(sizeof(*r0
));
606 os_memcpy(r0
->pmk_r0
, pmk_r0
, PMK_LEN
);
607 os_memcpy(r0
->pmk_r0_name
, pmk_r0_name
, WPA_PMK_NAME_LEN
);
608 os_memcpy(r0
->spa
, spa
, ETH_ALEN
);
609 r0
->pairwise
= pairwise
;
611 r0
->next
= cache
->pmk_r0
;
618 static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator
*wpa_auth
,
619 const u8
*spa
, const u8
*pmk_r0_name
,
620 const struct wpa_ft_pmk_r0_sa
**r0_out
)
622 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
623 struct wpa_ft_pmk_r0_sa
*r0
;
627 if (os_memcmp(r0
->spa
, spa
, ETH_ALEN
) == 0 &&
628 os_memcmp_const(r0
->pmk_r0_name
, pmk_r0_name
,
629 WPA_PMK_NAME_LEN
) == 0) {
642 static int wpa_ft_store_pmk_r1(struct wpa_authenticator
*wpa_auth
,
643 const u8
*spa
, const u8
*pmk_r1
,
644 const u8
*pmk_r1_name
, int pairwise
)
646 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
647 struct wpa_ft_pmk_r1_sa
*r1
;
649 /* TODO: add expiration and limit on number of entries in cache */
651 r1
= os_zalloc(sizeof(*r1
));
655 os_memcpy(r1
->pmk_r1
, pmk_r1
, PMK_LEN
);
656 os_memcpy(r1
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
);
657 os_memcpy(r1
->spa
, spa
, ETH_ALEN
);
658 r1
->pairwise
= pairwise
;
660 r1
->next
= cache
->pmk_r1
;
667 static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator
*wpa_auth
,
668 const u8
*spa
, const u8
*pmk_r1_name
,
669 u8
*pmk_r1
, int *pairwise
)
671 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
672 struct wpa_ft_pmk_r1_sa
*r1
;
676 if (os_memcmp(r1
->spa
, spa
, ETH_ALEN
) == 0 &&
677 os_memcmp_const(r1
->pmk_r1_name
, pmk_r1_name
,
678 WPA_PMK_NAME_LEN
) == 0) {
679 os_memcpy(pmk_r1
, r1
->pmk_r1
, PMK_LEN
);
681 *pairwise
= r1
->pairwise
;
692 static void wpa_ft_rrb_lookup_r0kh(struct wpa_authenticator
*wpa_auth
,
693 const u8
*src_addr
, const u8
*f_r0kh_id
,
694 size_t f_r0kh_id_len
,
695 struct ft_remote_r0kh
**r0kh_out
)
697 struct ft_remote_r0kh
*r0kh
;
699 for (r0kh
= wpa_auth
->conf
.r0kh_list
; r0kh
; r0kh
= r0kh
->next
) {
700 if (src_addr
&& os_memcmp(r0kh
->addr
, src_addr
, ETH_ALEN
) != 0)
703 (r0kh
->id_len
!= f_r0kh_id_len
||
704 os_memcmp_const(f_r0kh_id
, r0kh
->id
, f_r0kh_id_len
) != 0))
710 wpa_printf(MSG_DEBUG
, "FT: No matching R0KH found");
716 static void wpa_ft_rrb_lookup_r1kh(struct wpa_authenticator
*wpa_auth
,
717 const u8
*src_addr
, const u8
*f_r1kh_id
,
718 struct ft_remote_r1kh
**r1kh_out
)
720 struct ft_remote_r1kh
*r1kh
;
722 for (r1kh
= wpa_auth
->conf
.r1kh_list
; r1kh
; r1kh
= r1kh
->next
) {
723 if (src_addr
&& os_memcmp(r1kh
->addr
, src_addr
, ETH_ALEN
) != 0)
726 os_memcmp_const(r1kh
->id
, f_r1kh_id
, FT_R1KH_ID_LEN
) != 0)
732 wpa_printf(MSG_DEBUG
, "FT: No matching R1KH found");
738 static int wpa_ft_rrb_check_r0kh(struct wpa_authenticator
*wpa_auth
,
739 const u8
*f_r0kh_id
, size_t f_r0kh_id_len
)
741 if (f_r0kh_id_len
!= wpa_auth
->conf
.r0_key_holder_len
||
742 os_memcmp_const(f_r0kh_id
, wpa_auth
->conf
.r0_key_holder
,
750 static int wpa_ft_rrb_check_r1kh(struct wpa_authenticator
*wpa_auth
,
753 if (os_memcmp_const(f_r1kh_id
, wpa_auth
->conf
.r1_key_holder
,
754 FT_R1KH_ID_LEN
) != 0)
761 static int wpa_ft_pull_pmk_r1(struct wpa_state_machine
*sm
,
762 const u8
*ies
, size_t ies_len
,
763 const u8
*pmk_r0_name
)
765 struct ft_remote_r0kh
*r0kh
;
768 size_t packet_len
, key_len
;
769 struct tlv_list req_enc
[] = {
770 { .type
= FT_RRB_PMK_R0_NAME
, .len
= WPA_PMK_NAME_LEN
,
771 .data
= pmk_r0_name
},
772 { .type
= FT_RRB_S1KH_ID
, .len
= ETH_ALEN
,
774 { .type
= FT_RRB_LAST_EMPTY
, .len
= 0, .data
= NULL
},
776 struct tlv_list req_auth
[] = {
777 { .type
= FT_RRB_NONCE
, .len
= FT_RRB_NONCE_LEN
,
778 .data
= sm
->ft_pending_pull_nonce
},
779 { .type
= FT_RRB_R0KH_ID
, .len
= sm
->r0kh_id_len
,
780 .data
= sm
->r0kh_id
},
781 { .type
= FT_RRB_R1KH_ID
, .len
= FT_R1KH_ID_LEN
,
782 .data
= sm
->wpa_auth
->conf
.r1_key_holder
},
783 { .type
= FT_RRB_LAST_EMPTY
, .len
= 0, .data
= NULL
},
786 wpa_ft_rrb_lookup_r0kh(sm
->wpa_auth
, NULL
, sm
->r0kh_id
, sm
->r0kh_id_len
,
789 wpa_hexdump(MSG_DEBUG
, "FT: Did not find R0KH-ID",
790 sm
->r0kh_id
, sm
->r0kh_id_len
);
794 key_len
= sizeof(r0kh
->key
);
796 wpa_printf(MSG_DEBUG
, "FT: Send PMK-R1 pull request to remote R0KH "
797 "address " MACSTR
, MAC2STR(r0kh
->addr
));
799 if (random_get_bytes(sm
->ft_pending_pull_nonce
, FT_RRB_NONCE_LEN
) < 0) {
800 wpa_printf(MSG_DEBUG
, "FT: Failed to get random data for "
805 if (wpa_ft_rrb_build(key
, key_len
, req_enc
, NULL
, req_auth
,
806 sm
->wpa_auth
->addr
, FT_PACKET_R0KH_R1KH_PULL
,
807 &packet
, &packet_len
) < 0)
810 wpabuf_free(sm
->ft_pending_req_ies
);
811 sm
->ft_pending_req_ies
= wpabuf_alloc_copy(ies
, ies_len
);
812 if (!sm
->ft_pending_req_ies
) {
817 wpa_ft_rrb_oui_send(sm
->wpa_auth
, r0kh
->addr
, FT_PACKET_R0KH_R1KH_PULL
,
826 int wpa_auth_derive_ptk_ft(struct wpa_state_machine
*sm
, const u8
*pmk
,
829 u8 pmk_r0
[PMK_LEN
], pmk_r0_name
[WPA_PMK_NAME_LEN
];
831 u8 ptk_name
[WPA_PMK_NAME_LEN
];
832 const u8
*mdid
= sm
->wpa_auth
->conf
.mobility_domain
;
833 const u8
*r0kh
= sm
->wpa_auth
->conf
.r0_key_holder
;
834 size_t r0kh_len
= sm
->wpa_auth
->conf
.r0_key_holder_len
;
835 const u8
*r1kh
= sm
->wpa_auth
->conf
.r1_key_holder
;
836 const u8
*ssid
= sm
->wpa_auth
->conf
.ssid
;
837 size_t ssid_len
= sm
->wpa_auth
->conf
.ssid_len
;
838 int psk_local
= sm
->wpa_auth
->conf
.ft_psk_generate_local
;
840 if (sm
->xxkey_len
== 0) {
841 wpa_printf(MSG_DEBUG
, "FT: XXKey not available for key "
846 if (wpa_derive_pmk_r0(sm
->xxkey
, sm
->xxkey_len
, ssid
, ssid_len
, mdid
,
847 r0kh
, r0kh_len
, sm
->addr
,
848 pmk_r0
, pmk_r0_name
) < 0)
850 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R0", pmk_r0
, PMK_LEN
);
851 wpa_hexdump(MSG_DEBUG
, "FT: PMKR0Name", pmk_r0_name
, WPA_PMK_NAME_LEN
);
852 if (!psk_local
|| !wpa_key_mgmt_ft_psk(sm
->wpa_key_mgmt
))
853 wpa_ft_store_pmk_r0(sm
->wpa_auth
, sm
->addr
, pmk_r0
, pmk_r0_name
,
856 if (wpa_derive_pmk_r1(pmk_r0
, pmk_r0_name
, r1kh
, sm
->addr
,
857 pmk_r1
, sm
->pmk_r1_name
) < 0)
859 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", pmk_r1
, PMK_LEN
);
860 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", sm
->pmk_r1_name
,
862 if (!psk_local
|| !wpa_key_mgmt_ft_psk(sm
->wpa_key_mgmt
))
863 wpa_ft_store_pmk_r1(sm
->wpa_auth
, sm
->addr
, pmk_r1
,
864 sm
->pmk_r1_name
, sm
->pairwise
);
866 return wpa_pmk_r1_to_ptk(pmk_r1
, sm
->SNonce
, sm
->ANonce
, sm
->addr
,
867 sm
->wpa_auth
->addr
, sm
->pmk_r1_name
,
868 ptk
, ptk_name
, sm
->wpa_key_mgmt
, sm
->pairwise
);
872 static inline int wpa_auth_get_seqnum(struct wpa_authenticator
*wpa_auth
,
873 const u8
*addr
, int idx
, u8
*seq
)
875 if (wpa_auth
->cb
->get_seqnum
== NULL
)
877 return wpa_auth
->cb
->get_seqnum(wpa_auth
->cb_ctx
, addr
, idx
, seq
);
881 static u8
* wpa_ft_gtk_subelem(struct wpa_state_machine
*sm
, size_t *len
)
884 struct wpa_group
*gsm
= sm
->group
;
885 size_t subelem_len
, pad_len
;
890 key_len
= gsm
->GTK_len
;
891 if (key_len
> sizeof(keybuf
))
895 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less
898 pad_len
= key_len
% 8;
900 pad_len
= 8 - pad_len
;
901 if (key_len
+ pad_len
< 16)
903 if (pad_len
&& key_len
< sizeof(keybuf
)) {
904 os_memcpy(keybuf
, gsm
->GTK
[gsm
->GN
- 1], key_len
);
905 os_memset(keybuf
+ key_len
, 0, pad_len
);
906 keybuf
[key_len
] = 0xdd;
910 key
= gsm
->GTK
[gsm
->GN
- 1];
913 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
916 subelem_len
= 13 + key_len
+ 8;
917 subelem
= os_zalloc(subelem_len
);
921 subelem
[0] = FTIE_SUBELEM_GTK
;
922 subelem
[1] = 11 + key_len
+ 8;
923 /* Key ID in B0-B1 of Key Info */
924 WPA_PUT_LE16(&subelem
[2], gsm
->GN
& 0x03);
925 subelem
[4] = gsm
->GTK_len
;
926 wpa_auth_get_seqnum(sm
->wpa_auth
, NULL
, gsm
->GN
, subelem
+ 5);
927 if (aes_wrap(sm
->PTK
.kek
, sm
->PTK
.kek_len
, key_len
/ 8, key
,
938 #ifdef CONFIG_IEEE80211W
939 static u8
* wpa_ft_igtk_subelem(struct wpa_state_machine
*sm
, size_t *len
)
942 struct wpa_group
*gsm
= sm
->group
;
945 /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
947 subelem_len
= 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN
+ 8;
948 subelem
= os_zalloc(subelem_len
);
953 *pos
++ = FTIE_SUBELEM_IGTK
;
954 *pos
++ = subelem_len
- 2;
955 WPA_PUT_LE16(pos
, gsm
->GN_igtk
);
957 wpa_auth_get_seqnum(sm
->wpa_auth
, NULL
, gsm
->GN_igtk
, pos
);
959 *pos
++ = WPA_IGTK_LEN
;
960 if (aes_wrap(sm
->PTK
.kek
, sm
->PTK
.kek_len
, WPA_IGTK_LEN
/ 8,
961 gsm
->IGTK
[gsm
->GN_igtk
- 4], pos
)) {
969 #endif /* CONFIG_IEEE80211W */
972 static u8
* wpa_ft_process_rdie(struct wpa_state_machine
*sm
,
973 u8
*pos
, u8
*end
, u8 id
, u8 descr_count
,
974 const u8
*ies
, size_t ies_len
)
976 struct ieee802_11_elems parse
;
977 struct rsn_rdie
*rdie
;
979 wpa_printf(MSG_DEBUG
, "FT: Resource Request: id=%d descr_count=%d",
981 wpa_hexdump(MSG_MSGDUMP
, "FT: Resource descriptor IE(s)",
984 if (end
- pos
< (int) sizeof(*rdie
)) {
985 wpa_printf(MSG_ERROR
, "FT: Not enough room for response RDIE");
989 *pos
++ = WLAN_EID_RIC_DATA
;
990 *pos
++ = sizeof(*rdie
);
991 rdie
= (struct rsn_rdie
*) pos
;
993 rdie
->descr_count
= 0;
994 rdie
->status_code
= host_to_le16(WLAN_STATUS_SUCCESS
);
995 pos
+= sizeof(*rdie
);
997 if (ieee802_11_parse_elems((u8
*) ies
, ies_len
, &parse
, 1) ==
999 wpa_printf(MSG_DEBUG
, "FT: Failed to parse request IEs");
1001 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
1005 if (parse
.wmm_tspec
) {
1006 struct wmm_tspec_element
*tspec
;
1008 if (parse
.wmm_tspec_len
+ 2 < (int) sizeof(*tspec
)) {
1009 wpa_printf(MSG_DEBUG
, "FT: Too short WMM TSPEC IE "
1010 "(%d)", (int) parse
.wmm_tspec_len
);
1012 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
1015 if (end
- pos
< (int) sizeof(*tspec
)) {
1016 wpa_printf(MSG_ERROR
, "FT: Not enough room for "
1019 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
1022 tspec
= (struct wmm_tspec_element
*) pos
;
1023 os_memcpy(tspec
, parse
.wmm_tspec
- 2, sizeof(*tspec
));
1027 if (parse
.wmm_tspec
&& sm
->wpa_auth
->conf
.ap_mlme
) {
1030 res
= wmm_process_tspec((struct wmm_tspec_element
*) pos
);
1031 wpa_printf(MSG_DEBUG
, "FT: ADDTS processing result: %d", res
);
1032 if (res
== WMM_ADDTS_STATUS_INVALID_PARAMETERS
)
1034 host_to_le16(WLAN_STATUS_INVALID_PARAMETERS
);
1035 else if (res
== WMM_ADDTS_STATUS_REFUSED
)
1037 host_to_le16(WLAN_STATUS_REQUEST_DECLINED
);
1039 /* TSPEC accepted; include updated TSPEC in response */
1040 rdie
->descr_count
= 1;
1041 pos
+= sizeof(struct wmm_tspec_element
);
1045 #endif /* NEED_AP_MLME */
1047 if (parse
.wmm_tspec
&& !sm
->wpa_auth
->conf
.ap_mlme
) {
1050 res
= wpa_ft_add_tspec(sm
->wpa_auth
, sm
->addr
, pos
,
1051 sizeof(struct wmm_tspec_element
));
1054 rdie
->status_code
= host_to_le16(res
);
1056 /* TSPEC accepted; include updated TSPEC in
1058 rdie
->descr_count
= 1;
1059 pos
+= sizeof(struct wmm_tspec_element
);
1065 wpa_printf(MSG_DEBUG
, "FT: No supported resource requested");
1066 rdie
->status_code
= host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
1071 static u8
* wpa_ft_process_ric(struct wpa_state_machine
*sm
, u8
*pos
, u8
*end
,
1072 const u8
*ric
, size_t ric_len
)
1074 const u8
*rpos
, *start
;
1075 const struct rsn_rdie
*rdie
;
1077 wpa_hexdump(MSG_MSGDUMP
, "FT: RIC Request", ric
, ric_len
);
1080 while (rpos
+ sizeof(*rdie
) < ric
+ ric_len
) {
1081 if (rpos
[0] != WLAN_EID_RIC_DATA
|| rpos
[1] < sizeof(*rdie
) ||
1082 rpos
+ 2 + rpos
[1] > ric
+ ric_len
)
1084 rdie
= (const struct rsn_rdie
*) (rpos
+ 2);
1085 rpos
+= 2 + rpos
[1];
1088 while (rpos
+ 2 <= ric
+ ric_len
&&
1089 rpos
+ 2 + rpos
[1] <= ric
+ ric_len
) {
1090 if (rpos
[0] == WLAN_EID_RIC_DATA
)
1092 rpos
+= 2 + rpos
[1];
1094 pos
= wpa_ft_process_rdie(sm
, pos
, end
, rdie
->id
,
1096 start
, rpos
- start
);
1103 u8
* wpa_sm_write_assoc_resp_ies(struct wpa_state_machine
*sm
, u8
*pos
,
1104 size_t max_len
, int auth_alg
,
1105 const u8
*req_ies
, size_t req_ies_len
)
1107 u8
*end
, *mdie
, *ftie
, *rsnie
= NULL
, *r0kh_id
, *subelem
= NULL
;
1108 size_t mdie_len
, ftie_len
, rsnie_len
= 0, r0kh_id_len
, subelem_len
= 0;
1110 struct wpa_auth_config
*conf
;
1111 struct rsn_ftie
*_ftie
;
1112 struct wpa_ft_ies parse
;
1114 u8
*anonce
, *snonce
;
1119 conf
= &sm
->wpa_auth
->conf
;
1121 if (!wpa_key_mgmt_ft(sm
->wpa_key_mgmt
))
1124 end
= pos
+ max_len
;
1126 if (auth_alg
== WLAN_AUTH_FT
) {
1128 * RSN (only present if this is a Reassociation Response and
1129 * part of a fast BSS transition)
1131 res
= wpa_write_rsn_ie(conf
, pos
, end
- pos
, sm
->pmk_r1_name
);
1139 /* Mobility Domain Information */
1140 res
= wpa_write_mdie(conf
, pos
, end
- pos
);
1147 /* Fast BSS Transition Information */
1148 if (auth_alg
== WLAN_AUTH_FT
) {
1149 subelem
= wpa_ft_gtk_subelem(sm
, &subelem_len
);
1150 r0kh_id
= sm
->r0kh_id
;
1151 r0kh_id_len
= sm
->r0kh_id_len
;
1152 anonce
= sm
->ANonce
;
1153 snonce
= sm
->SNonce
;
1154 #ifdef CONFIG_IEEE80211W
1155 if (sm
->mgmt_frame_prot
) {
1159 igtk
= wpa_ft_igtk_subelem(sm
, &igtk_len
);
1164 nbuf
= os_realloc(subelem
, subelem_len
+ igtk_len
);
1171 os_memcpy(subelem
+ subelem_len
, igtk
, igtk_len
);
1172 subelem_len
+= igtk_len
;
1175 #endif /* CONFIG_IEEE80211W */
1177 r0kh_id
= conf
->r0_key_holder
;
1178 r0kh_id_len
= conf
->r0_key_holder_len
;
1182 res
= wpa_write_ftie(conf
, r0kh_id
, r0kh_id_len
, anonce
, snonce
, pos
,
1183 end
- pos
, subelem
, subelem_len
);
1191 _ftie
= (struct rsn_ftie
*) (ftie
+ 2);
1192 if (auth_alg
== WLAN_AUTH_FT
)
1193 _ftie
->mic_control
[1] = 3; /* Information element count */
1196 if (wpa_ft_parse_ies(req_ies
, req_ies_len
, &parse
) == 0 && parse
.ric
) {
1197 pos
= wpa_ft_process_ric(sm
, pos
, end
, parse
.ric
,
1199 if (auth_alg
== WLAN_AUTH_FT
)
1200 _ftie
->mic_control
[1] +=
1201 ieee802_11_ie_count(ric_start
,
1204 if (ric_start
== pos
)
1207 if (auth_alg
== WLAN_AUTH_FT
&&
1208 wpa_ft_mic(sm
->PTK
.kck
, sm
->PTK
.kck_len
, sm
->addr
,
1209 sm
->wpa_auth
->addr
, 6,
1210 mdie
, mdie_len
, ftie
, ftie_len
,
1212 ric_start
, ric_start
? pos
- ric_start
: 0,
1214 wpa_printf(MSG_DEBUG
, "FT: Failed to calculate MIC");
1216 os_free(sm
->assoc_resp_ftie
);
1217 sm
->assoc_resp_ftie
= os_malloc(ftie_len
);
1218 if (sm
->assoc_resp_ftie
)
1219 os_memcpy(sm
->assoc_resp_ftie
, ftie
, ftie_len
);
1225 static inline int wpa_auth_set_key(struct wpa_authenticator
*wpa_auth
,
1227 enum wpa_alg alg
, const u8
*addr
, int idx
,
1228 u8
*key
, size_t key_len
)
1230 if (wpa_auth
->cb
->set_key
== NULL
)
1232 return wpa_auth
->cb
->set_key(wpa_auth
->cb_ctx
, vlan_id
, alg
, addr
, idx
,
1237 void wpa_ft_install_ptk(struct wpa_state_machine
*sm
)
1242 /* MLME-SETKEYS.request(PTK) */
1243 alg
= wpa_cipher_to_alg(sm
->pairwise
);
1244 klen
= wpa_cipher_key_len(sm
->pairwise
);
1245 if (!wpa_cipher_valid_pairwise(sm
->pairwise
)) {
1246 wpa_printf(MSG_DEBUG
, "FT: Unknown pairwise alg 0x%x - skip "
1247 "PTK configuration", sm
->pairwise
);
1251 /* FIX: add STA entry to kernel/driver here? The set_key will fail
1252 * most likely without this.. At the moment, STA entry is added only
1253 * after association has been completed. This function will be called
1254 * again after association to get the PTK configured, but that could be
1255 * optimized by adding the STA entry earlier.
1257 if (wpa_auth_set_key(sm
->wpa_auth
, 0, alg
, sm
->addr
, 0,
1261 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
1262 sm
->pairwise_set
= TRUE
;
1266 /* Derive PMK-R1 from PSK, check all available PSK */
1267 static int wpa_ft_psk_pmk_r1(struct wpa_state_machine
*sm
,
1268 const u8
*req_pmk_r1_name
,
1269 u8
*out_pmk_r1
, int *out_pairwise
)
1271 const u8
*pmk
= NULL
;
1272 u8 pmk_r0
[PMK_LEN
], pmk_r0_name
[WPA_PMK_NAME_LEN
];
1273 u8 pmk_r1
[PMK_LEN
], pmk_r1_name
[WPA_PMK_NAME_LEN
];
1274 struct wpa_authenticator
*wpa_auth
= sm
->wpa_auth
;
1275 const u8
*mdid
= wpa_auth
->conf
.mobility_domain
;
1276 const u8
*r0kh
= sm
->r0kh_id
;
1277 size_t r0kh_len
= sm
->r0kh_id_len
;
1278 const u8
*r1kh
= wpa_auth
->conf
.r1_key_holder
;
1279 const u8
*ssid
= wpa_auth
->conf
.ssid
;
1280 size_t ssid_len
= wpa_auth
->conf
.ssid_len
;
1283 pairwise
= sm
->pairwise
;
1286 pmk
= wpa_ft_get_psk(wpa_auth
, sm
->addr
, sm
->p2p_dev_addr
,
1291 if (wpa_derive_pmk_r0(pmk
, PMK_LEN
, ssid
, ssid_len
, mdid
, r0kh
,
1293 pmk_r0
, pmk_r0_name
) < 0 ||
1294 wpa_derive_pmk_r1(pmk_r0
, pmk_r0_name
, r1kh
, sm
->addr
,
1295 pmk_r1
, pmk_r1_name
) < 0 ||
1296 os_memcmp_const(pmk_r1_name
, req_pmk_r1_name
,
1297 WPA_PMK_NAME_LEN
) != 0)
1300 /* We found a PSK that matches the requested pmk_r1_name */
1301 wpa_printf(MSG_DEBUG
,
1302 "FT: Found PSK to generate PMK-R1 locally");
1303 os_memcpy(out_pmk_r1
, pmk_r1
, PMK_LEN
);
1305 *out_pairwise
= pairwise
;
1309 wpa_printf(MSG_DEBUG
,
1310 "FT: Did not find PSK to generate PMK-R1 locally");
1315 /* Detect the configuration the station asked for.
1316 * Required to detect FT-PSK and pairwise cipher.
1318 static int wpa_ft_set_key_mgmt(struct wpa_state_machine
*sm
,
1319 struct wpa_ft_ies
*parse
)
1321 int key_mgmt
, ciphers
;
1323 if (sm
->wpa_key_mgmt
)
1326 key_mgmt
= parse
->key_mgmt
& sm
->wpa_auth
->conf
.wpa_key_mgmt
;
1328 wpa_printf(MSG_DEBUG
, "FT: Invalid key mgmt (0x%x) from "
1329 MACSTR
, parse
->key_mgmt
, MAC2STR(sm
->addr
));
1332 if (key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
)
1333 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_IEEE8021X
;
1334 else if (key_mgmt
& WPA_KEY_MGMT_FT_PSK
)
1335 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_PSK
;
1337 else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA256
)
1338 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_FILS_SHA256
;
1339 else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA384
)
1340 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_FILS_SHA384
;
1341 #endif /* CONFIG_FILS */
1342 ciphers
= parse
->pairwise_cipher
& sm
->wpa_auth
->conf
.rsn_pairwise
;
1344 wpa_printf(MSG_DEBUG
, "FT: Invalid pairwise cipher (0x%x) from "
1346 parse
->pairwise_cipher
, MAC2STR(sm
->addr
));
1349 sm
->pairwise
= wpa_pick_pairwise_cipher(ciphers
, 0);
1355 static int wpa_ft_process_auth_req(struct wpa_state_machine
*sm
,
1356 const u8
*ies
, size_t ies_len
,
1357 u8
**resp_ies
, size_t *resp_ies_len
)
1359 struct rsn_mdie
*mdie
;
1360 struct rsn_ftie
*ftie
;
1361 u8 pmk_r1
[PMK_LEN
], pmk_r1_name
[WPA_PMK_NAME_LEN
];
1362 u8 ptk_name
[WPA_PMK_NAME_LEN
];
1363 struct wpa_auth_config
*conf
;
1364 struct wpa_ft_ies parse
;
1373 sm
->pmk_r1_name_valid
= 0;
1374 conf
= &sm
->wpa_auth
->conf
;
1376 wpa_hexdump(MSG_DEBUG
, "FT: Received authentication frame IEs",
1379 if (wpa_ft_parse_ies(ies
, ies_len
, &parse
) < 0) {
1380 wpa_printf(MSG_DEBUG
, "FT: Failed to parse FT IEs");
1381 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1384 mdie
= (struct rsn_mdie
*) parse
.mdie
;
1385 if (mdie
== NULL
|| parse
.mdie_len
< sizeof(*mdie
) ||
1386 os_memcmp(mdie
->mobility_domain
,
1387 sm
->wpa_auth
->conf
.mobility_domain
,
1388 MOBILITY_DOMAIN_ID_LEN
) != 0) {
1389 wpa_printf(MSG_DEBUG
, "FT: Invalid MDIE");
1390 return WLAN_STATUS_INVALID_MDIE
;
1393 ftie
= (struct rsn_ftie
*) parse
.ftie
;
1394 if (ftie
== NULL
|| parse
.ftie_len
< sizeof(*ftie
)) {
1395 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE");
1396 return WLAN_STATUS_INVALID_FTIE
;
1399 os_memcpy(sm
->SNonce
, ftie
->snonce
, WPA_NONCE_LEN
);
1401 if (parse
.r0kh_id
== NULL
) {
1402 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE - no R0KH-ID");
1403 return WLAN_STATUS_INVALID_FTIE
;
1406 wpa_hexdump(MSG_DEBUG
, "FT: STA R0KH-ID",
1407 parse
.r0kh_id
, parse
.r0kh_id_len
);
1408 os_memcpy(sm
->r0kh_id
, parse
.r0kh_id
, parse
.r0kh_id_len
);
1409 sm
->r0kh_id_len
= parse
.r0kh_id_len
;
1411 if (parse
.rsn_pmkid
== NULL
) {
1412 wpa_printf(MSG_DEBUG
, "FT: No PMKID in RSNIE");
1413 return WLAN_STATUS_INVALID_PMKID
;
1416 if (wpa_ft_set_key_mgmt(sm
, &parse
) < 0)
1417 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1419 wpa_hexdump(MSG_DEBUG
, "FT: Requested PMKR0Name",
1420 parse
.rsn_pmkid
, WPA_PMK_NAME_LEN
);
1421 if (wpa_derive_pmk_r1_name(parse
.rsn_pmkid
,
1422 sm
->wpa_auth
->conf
.r1_key_holder
, sm
->addr
,
1424 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1425 wpa_hexdump(MSG_DEBUG
, "FT: Derived requested PMKR1Name",
1426 pmk_r1_name
, WPA_PMK_NAME_LEN
);
1428 if (conf
->ft_psk_generate_local
&&
1429 wpa_key_mgmt_ft_psk(sm
->wpa_key_mgmt
)) {
1430 if (wpa_ft_psk_pmk_r1(sm
, pmk_r1_name
, pmk_r1
, &pairwise
) < 0)
1431 return WLAN_STATUS_INVALID_PMKID
;
1432 } else if (wpa_ft_fetch_pmk_r1(sm
->wpa_auth
, sm
->addr
, pmk_r1_name
,
1433 pmk_r1
, &pairwise
) < 0) {
1434 if (wpa_ft_pull_pmk_r1(sm
, ies
, ies_len
, parse
.rsn_pmkid
) < 0) {
1435 wpa_printf(MSG_DEBUG
, "FT: Did not have matching "
1436 "PMK-R1 and unknown R0KH-ID");
1437 return WLAN_STATUS_INVALID_PMKID
;
1440 return -1; /* Status pending */
1443 wpa_hexdump_key(MSG_DEBUG
, "FT: Selected PMK-R1", pmk_r1
, PMK_LEN
);
1444 sm
->pmk_r1_name_valid
= 1;
1445 os_memcpy(sm
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
);
1447 if (random_get_bytes(sm
->ANonce
, WPA_NONCE_LEN
)) {
1448 wpa_printf(MSG_DEBUG
, "FT: Failed to get random data for "
1450 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1453 wpa_hexdump(MSG_DEBUG
, "FT: Received SNonce",
1454 sm
->SNonce
, WPA_NONCE_LEN
);
1455 wpa_hexdump(MSG_DEBUG
, "FT: Generated ANonce",
1456 sm
->ANonce
, WPA_NONCE_LEN
);
1458 if (wpa_pmk_r1_to_ptk(pmk_r1
, sm
->SNonce
, sm
->ANonce
, sm
->addr
,
1459 sm
->wpa_auth
->addr
, pmk_r1_name
,
1460 &sm
->PTK
, ptk_name
, sm
->wpa_key_mgmt
,
1462 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1464 sm
->pairwise
= pairwise
;
1465 sm
->PTK_valid
= TRUE
;
1466 wpa_ft_install_ptk(sm
);
1468 buflen
= 2 + sizeof(struct rsn_mdie
) + 2 + sizeof(struct rsn_ftie
) +
1469 2 + FT_R1KH_ID_LEN
+ 200;
1470 *resp_ies
= os_zalloc(buflen
);
1471 if (*resp_ies
== NULL
)
1475 end
= *resp_ies
+ buflen
;
1477 ret
= wpa_write_rsn_ie(conf
, pos
, end
- pos
, parse
.rsn_pmkid
);
1482 ret
= wpa_write_mdie(conf
, pos
, end
- pos
);
1487 ret
= wpa_write_ftie(conf
, parse
.r0kh_id
, parse
.r0kh_id_len
,
1488 sm
->ANonce
, sm
->SNonce
, pos
, end
- pos
, NULL
, 0);
1493 *resp_ies_len
= pos
- *resp_ies
;
1495 return WLAN_STATUS_SUCCESS
;
1499 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1503 void wpa_ft_process_auth(struct wpa_state_machine
*sm
, const u8
*bssid
,
1504 u16 auth_transaction
, const u8
*ies
, size_t ies_len
,
1505 void (*cb
)(void *ctx
, const u8
*dst
, const u8
*bssid
,
1506 u16 auth_transaction
, u16 status
,
1507 const u8
*ies
, size_t ies_len
),
1512 size_t resp_ies_len
;
1516 wpa_printf(MSG_DEBUG
, "FT: Received authentication frame, but "
1517 "WPA SM not available");
1521 wpa_printf(MSG_DEBUG
, "FT: Received authentication frame: STA=" MACSTR
1522 " BSSID=" MACSTR
" transaction=%d",
1523 MAC2STR(sm
->addr
), MAC2STR(bssid
), auth_transaction
);
1524 sm
->ft_pending_cb
= cb
;
1525 sm
->ft_pending_cb_ctx
= ctx
;
1526 sm
->ft_pending_auth_transaction
= auth_transaction
;
1527 res
= wpa_ft_process_auth_req(sm
, ies
, ies_len
, &resp_ies
,
1530 wpa_printf(MSG_DEBUG
, "FT: Callback postponed until response is available");
1535 wpa_printf(MSG_DEBUG
, "FT: FT authentication response: dst=" MACSTR
1536 " auth_transaction=%d status=%d",
1537 MAC2STR(sm
->addr
), auth_transaction
+ 1, status
);
1538 wpa_hexdump(MSG_DEBUG
, "FT: Response IEs", resp_ies
, resp_ies_len
);
1539 cb(ctx
, sm
->addr
, bssid
, auth_transaction
+ 1, status
,
1540 resp_ies
, resp_ies_len
);
1545 u16
wpa_ft_validate_reassoc(struct wpa_state_machine
*sm
, const u8
*ies
,
1548 struct wpa_ft_ies parse
;
1549 struct rsn_mdie
*mdie
;
1550 struct rsn_ftie
*ftie
;
1551 u8 mic
[WPA_EAPOL_KEY_MIC_MAX_LEN
];
1552 size_t mic_len
= 16;
1556 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1558 wpa_hexdump(MSG_DEBUG
, "FT: Reassoc Req IEs", ies
, ies_len
);
1560 if (wpa_ft_parse_ies(ies
, ies_len
, &parse
) < 0) {
1561 wpa_printf(MSG_DEBUG
, "FT: Failed to parse FT IEs");
1562 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1565 if (parse
.rsn
== NULL
) {
1566 wpa_printf(MSG_DEBUG
, "FT: No RSNIE in Reassoc Req");
1567 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1570 if (parse
.rsn_pmkid
== NULL
) {
1571 wpa_printf(MSG_DEBUG
, "FT: No PMKID in RSNIE");
1572 return WLAN_STATUS_INVALID_PMKID
;
1575 if (os_memcmp_const(parse
.rsn_pmkid
, sm
->pmk_r1_name
, WPA_PMK_NAME_LEN
)
1577 wpa_printf(MSG_DEBUG
, "FT: PMKID in Reassoc Req did not match "
1578 "with the PMKR1Name derived from auth request");
1579 return WLAN_STATUS_INVALID_PMKID
;
1582 mdie
= (struct rsn_mdie
*) parse
.mdie
;
1583 if (mdie
== NULL
|| parse
.mdie_len
< sizeof(*mdie
) ||
1584 os_memcmp(mdie
->mobility_domain
,
1585 sm
->wpa_auth
->conf
.mobility_domain
,
1586 MOBILITY_DOMAIN_ID_LEN
) != 0) {
1587 wpa_printf(MSG_DEBUG
, "FT: Invalid MDIE");
1588 return WLAN_STATUS_INVALID_MDIE
;
1591 ftie
= (struct rsn_ftie
*) parse
.ftie
;
1592 if (ftie
== NULL
|| parse
.ftie_len
< sizeof(*ftie
)) {
1593 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE");
1594 return WLAN_STATUS_INVALID_FTIE
;
1597 if (os_memcmp(ftie
->snonce
, sm
->SNonce
, WPA_NONCE_LEN
) != 0) {
1598 wpa_printf(MSG_DEBUG
, "FT: SNonce mismatch in FTIE");
1599 wpa_hexdump(MSG_DEBUG
, "FT: Received SNonce",
1600 ftie
->snonce
, WPA_NONCE_LEN
);
1601 wpa_hexdump(MSG_DEBUG
, "FT: Expected SNonce",
1602 sm
->SNonce
, WPA_NONCE_LEN
);
1603 return WLAN_STATUS_INVALID_FTIE
;
1606 if (os_memcmp(ftie
->anonce
, sm
->ANonce
, WPA_NONCE_LEN
) != 0) {
1607 wpa_printf(MSG_DEBUG
, "FT: ANonce mismatch in FTIE");
1608 wpa_hexdump(MSG_DEBUG
, "FT: Received ANonce",
1609 ftie
->anonce
, WPA_NONCE_LEN
);
1610 wpa_hexdump(MSG_DEBUG
, "FT: Expected ANonce",
1611 sm
->ANonce
, WPA_NONCE_LEN
);
1612 return WLAN_STATUS_INVALID_FTIE
;
1616 if (parse
.r0kh_id
== NULL
) {
1617 wpa_printf(MSG_DEBUG
, "FT: No R0KH-ID subelem in FTIE");
1618 return WLAN_STATUS_INVALID_FTIE
;
1621 if (parse
.r0kh_id_len
!= sm
->r0kh_id_len
||
1622 os_memcmp_const(parse
.r0kh_id
, sm
->r0kh_id
, parse
.r0kh_id_len
) != 0)
1624 wpa_printf(MSG_DEBUG
, "FT: R0KH-ID in FTIE did not match with "
1625 "the current R0KH-ID");
1626 wpa_hexdump(MSG_DEBUG
, "FT: R0KH-ID in FTIE",
1627 parse
.r0kh_id
, parse
.r0kh_id_len
);
1628 wpa_hexdump(MSG_DEBUG
, "FT: The current R0KH-ID",
1629 sm
->r0kh_id
, sm
->r0kh_id_len
);
1630 return WLAN_STATUS_INVALID_FTIE
;
1633 if (parse
.r1kh_id
== NULL
) {
1634 wpa_printf(MSG_DEBUG
, "FT: No R1KH-ID subelem in FTIE");
1635 return WLAN_STATUS_INVALID_FTIE
;
1638 if (os_memcmp_const(parse
.r1kh_id
, sm
->wpa_auth
->conf
.r1_key_holder
,
1639 FT_R1KH_ID_LEN
) != 0) {
1640 wpa_printf(MSG_DEBUG
, "FT: Unknown R1KH-ID used in "
1642 wpa_hexdump(MSG_DEBUG
, "FT: R1KH-ID in FTIE",
1643 parse
.r1kh_id
, FT_R1KH_ID_LEN
);
1644 wpa_hexdump(MSG_DEBUG
, "FT: Expected R1KH-ID",
1645 sm
->wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
);
1646 return WLAN_STATUS_INVALID_FTIE
;
1649 if (parse
.rsn_pmkid
== NULL
||
1650 os_memcmp_const(parse
.rsn_pmkid
, sm
->pmk_r1_name
, WPA_PMK_NAME_LEN
))
1652 wpa_printf(MSG_DEBUG
, "FT: No matching PMKR1Name (PMKID) in "
1653 "RSNIE (pmkid=%d)", !!parse
.rsn_pmkid
);
1654 return WLAN_STATUS_INVALID_PMKID
;
1659 count
+= ieee802_11_ie_count(parse
.ric
, parse
.ric_len
);
1660 if (ftie
->mic_control
[1] != count
) {
1661 wpa_printf(MSG_DEBUG
, "FT: Unexpected IE count in MIC "
1662 "Control: received %u expected %u",
1663 ftie
->mic_control
[1], count
);
1664 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1667 if (wpa_ft_mic(sm
->PTK
.kck
, sm
->PTK
.kck_len
, sm
->addr
,
1668 sm
->wpa_auth
->addr
, 5,
1669 parse
.mdie
- 2, parse
.mdie_len
+ 2,
1670 parse
.ftie
- 2, parse
.ftie_len
+ 2,
1671 parse
.rsn
- 2, parse
.rsn_len
+ 2,
1672 parse
.ric
, parse
.ric_len
,
1674 wpa_printf(MSG_DEBUG
, "FT: Failed to calculate MIC");
1675 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1678 if (os_memcmp_const(mic
, ftie
->mic
, mic_len
) != 0) {
1679 wpa_printf(MSG_DEBUG
, "FT: Invalid MIC in FTIE");
1680 wpa_printf(MSG_DEBUG
, "FT: addr=" MACSTR
" auth_addr=" MACSTR
,
1681 MAC2STR(sm
->addr
), MAC2STR(sm
->wpa_auth
->addr
));
1682 wpa_hexdump(MSG_MSGDUMP
, "FT: Received MIC",
1683 ftie
->mic
, mic_len
);
1684 wpa_hexdump(MSG_MSGDUMP
, "FT: Calculated MIC", mic
, mic_len
);
1685 wpa_hexdump(MSG_MSGDUMP
, "FT: MDIE",
1686 parse
.mdie
- 2, parse
.mdie_len
+ 2);
1687 wpa_hexdump(MSG_MSGDUMP
, "FT: FTIE",
1688 parse
.ftie
- 2, parse
.ftie_len
+ 2);
1689 wpa_hexdump(MSG_MSGDUMP
, "FT: RSN",
1690 parse
.rsn
- 2, parse
.rsn_len
+ 2);
1691 return WLAN_STATUS_INVALID_FTIE
;
1694 return WLAN_STATUS_SUCCESS
;
1698 int wpa_ft_action_rx(struct wpa_state_machine
*sm
, const u8
*data
, size_t len
)
1700 const u8
*sta_addr
, *target_ap
;
1704 struct ft_rrb_frame
*frame
;
1710 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1711 * FT Request action frame body[variable]
1715 wpa_printf(MSG_DEBUG
, "FT: Too short FT Action frame "
1716 "(len=%lu)", (unsigned long) len
);
1721 sta_addr
= data
+ 2;
1722 target_ap
= data
+ 8;
1726 wpa_printf(MSG_DEBUG
, "FT: Received FT Action frame (STA=" MACSTR
1727 " Target AP=" MACSTR
" Action=%d)",
1728 MAC2STR(sta_addr
), MAC2STR(target_ap
), action
);
1730 if (os_memcmp(sta_addr
, sm
->addr
, ETH_ALEN
) != 0) {
1731 wpa_printf(MSG_DEBUG
, "FT: Mismatch in FT Action STA address: "
1732 "STA=" MACSTR
" STA-Address=" MACSTR
,
1733 MAC2STR(sm
->addr
), MAC2STR(sta_addr
));
1738 * Do some sanity checking on the target AP address (not own and not
1739 * broadcast. This could be extended to filter based on a list of known
1740 * APs in the MD (if such a list were configured).
1742 if ((target_ap
[0] & 0x01) ||
1743 os_memcmp(target_ap
, sm
->wpa_auth
->addr
, ETH_ALEN
) == 0) {
1744 wpa_printf(MSG_DEBUG
, "FT: Invalid Target AP in FT Action "
1749 wpa_hexdump(MSG_MSGDUMP
, "FT: Action frame body", ies
, ies_len
);
1751 if (!sm
->wpa_auth
->conf
.ft_over_ds
) {
1752 wpa_printf(MSG_DEBUG
, "FT: Over-DS option disabled - reject");
1756 /* RRB - Forward action frame to the target AP */
1757 frame
= os_malloc(sizeof(*frame
) + len
);
1760 frame
->frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1761 frame
->packet_type
= FT_PACKET_REQUEST
;
1762 frame
->action_length
= host_to_le16(len
);
1763 os_memcpy(frame
->ap_address
, sm
->wpa_auth
->addr
, ETH_ALEN
);
1764 os_memcpy(frame
+ 1, data
, len
);
1766 wpa_ft_rrb_send(sm
->wpa_auth
, target_ap
, (u8
*) frame
,
1767 sizeof(*frame
) + len
);
1774 static void wpa_ft_rrb_rx_request_cb(void *ctx
, const u8
*dst
, const u8
*bssid
,
1775 u16 auth_transaction
, u16 resp
,
1776 const u8
*ies
, size_t ies_len
)
1778 struct wpa_state_machine
*sm
= ctx
;
1779 wpa_printf(MSG_DEBUG
, "FT: Over-the-DS RX request cb for " MACSTR
,
1781 wpa_ft_send_rrb_auth_resp(sm
, sm
->ft_pending_current_ap
, sm
->addr
,
1782 WLAN_STATUS_SUCCESS
, ies
, ies_len
);
1786 static int wpa_ft_rrb_rx_request(struct wpa_authenticator
*wpa_auth
,
1787 const u8
*current_ap
, const u8
*sta_addr
,
1788 const u8
*body
, size_t len
)
1790 struct wpa_state_machine
*sm
;
1793 size_t resp_ies_len
;
1796 sm
= wpa_ft_add_sta(wpa_auth
, sta_addr
);
1798 wpa_printf(MSG_DEBUG
, "FT: Failed to add new STA based on "
1803 wpa_hexdump(MSG_MSGDUMP
, "FT: RRB Request Frame body", body
, len
);
1805 sm
->ft_pending_cb
= wpa_ft_rrb_rx_request_cb
;
1806 sm
->ft_pending_cb_ctx
= sm
;
1807 os_memcpy(sm
->ft_pending_current_ap
, current_ap
, ETH_ALEN
);
1808 res
= wpa_ft_process_auth_req(sm
, body
, len
, &resp_ies
,
1811 wpa_printf(MSG_DEBUG
, "FT: No immediate response available - wait for pull response");
1816 res
= wpa_ft_send_rrb_auth_resp(sm
, current_ap
, sta_addr
, status
,
1817 resp_ies
, resp_ies_len
);
1823 static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine
*sm
,
1824 const u8
*current_ap
, const u8
*sta_addr
,
1825 u16 status
, const u8
*resp_ies
,
1826 size_t resp_ies_len
)
1828 struct wpa_authenticator
*wpa_auth
= sm
->wpa_auth
;
1830 struct ft_rrb_frame
*frame
;
1833 wpa_printf(MSG_DEBUG
, "FT: RRB authentication response: STA=" MACSTR
1834 " CurrentAP=" MACSTR
" status=%d",
1835 MAC2STR(sm
->addr
), MAC2STR(current_ap
), status
);
1836 wpa_hexdump(MSG_DEBUG
, "FT: Response IEs", resp_ies
, resp_ies_len
);
1838 /* RRB - Forward action frame response to the Current AP */
1841 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1842 * Status_Code[2] FT Request action frame body[variable]
1844 rlen
= 2 + 2 * ETH_ALEN
+ 2 + resp_ies_len
;
1846 frame
= os_malloc(sizeof(*frame
) + rlen
);
1849 frame
->frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1850 frame
->packet_type
= FT_PACKET_RESPONSE
;
1851 frame
->action_length
= host_to_le16(rlen
);
1852 os_memcpy(frame
->ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1853 pos
= (u8
*) (frame
+ 1);
1854 *pos
++ = WLAN_ACTION_FT
;
1855 *pos
++ = 2; /* Action: Response */
1856 os_memcpy(pos
, sta_addr
, ETH_ALEN
);
1858 os_memcpy(pos
, wpa_auth
->addr
, ETH_ALEN
);
1860 WPA_PUT_LE16(pos
, status
);
1863 os_memcpy(pos
, resp_ies
, resp_ies_len
);
1865 wpa_ft_rrb_send(wpa_auth
, current_ap
, (u8
*) frame
,
1866 sizeof(*frame
) + rlen
);
1873 static int wpa_ft_rrb_build_r0(const u8
*key
, const size_t key_len
,
1874 const struct tlv_list
*tlvs
,
1875 const struct wpa_ft_pmk_r0_sa
*pmk_r0
,
1876 const u8
*r1kh_id
, const u8
*s1kh_id
,
1877 const struct tlv_list
*tlv_auth
,
1878 const u8
*src_addr
, u8 type
,
1879 u8
**packet
, size_t *packet_len
)
1882 u8 pmk_r1_name
[WPA_PMK_NAME_LEN
];
1883 u8 f_pairwise
[sizeof(le16
)];
1885 struct tlv_list sess_tlv
[] = {
1886 { .type
= FT_RRB_PMK_R1
, .len
= sizeof(pmk_r1
),
1888 { .type
= FT_RRB_PMK_R1_NAME
, .len
= sizeof(pmk_r1_name
),
1889 .data
= pmk_r1_name
},
1890 { .type
= FT_RRB_PAIRWISE
, .len
= sizeof(f_pairwise
),
1891 .data
= f_pairwise
},
1892 { .type
= FT_RRB_LAST_EMPTY
, .len
= 0, .data
= NULL
},
1895 if (wpa_derive_pmk_r1(pmk_r0
->pmk_r0
, pmk_r0
->pmk_r0_name
, r1kh_id
,
1896 s1kh_id
, pmk_r1
, pmk_r1_name
) < 0)
1898 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", pmk_r1
, PMK_LEN
);
1899 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", pmk_r1_name
, WPA_PMK_NAME_LEN
);
1900 WPA_PUT_LE16(f_pairwise
, pmk_r0
->pairwise
);
1902 ret
= wpa_ft_rrb_build(key
, key_len
, tlvs
, sess_tlv
, tlv_auth
,
1903 src_addr
, type
, packet
, packet_len
);
1905 os_memset(pmk_r1
, 0, sizeof(pmk_r1
));
1911 static int wpa_ft_rrb_rx_pull(struct wpa_authenticator
*wpa_auth
,
1913 const u8
*enc
, size_t enc_len
,
1914 const u8
*auth
, size_t auth_len
)
1916 const char *msgtype
= "pull request";
1917 u8
*plain
= NULL
, *packet
= NULL
;
1918 size_t plain_len
= 0, packet_len
= 0;
1919 struct ft_remote_r1kh
*r1kh
;
1922 const u8
*f_nonce
, *f_r0kh_id
, *f_r1kh_id
, *f_s1kh_id
, *f_pmk_r0_name
;
1923 size_t f_nonce_len
, f_r0kh_id_len
, f_r1kh_id_len
, f_s1kh_id_len
;
1924 size_t f_pmk_r0_name_len
;
1925 const struct wpa_ft_pmk_r0_sa
*r0
;
1927 struct tlv_list resp
[2];
1928 struct tlv_list resp_auth
[4];
1930 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 pull");
1932 RRB_GET_AUTH(FT_RRB_R0KH_ID
, r0kh_id
, msgtype
, -1);
1933 wpa_hexdump(MSG_DEBUG
, "FT: R0KH-ID", f_r0kh_id
, f_r0kh_id_len
);
1935 if (wpa_ft_rrb_check_r0kh(wpa_auth
, f_r0kh_id
, f_r0kh_id_len
)) {
1936 wpa_printf(MSG_DEBUG
, "FT: R0KH-ID mismatch");
1940 RRB_GET_AUTH(FT_RRB_R1KH_ID
, r1kh_id
, msgtype
, FT_R1KH_ID_LEN
);
1941 wpa_printf(MSG_DEBUG
, "FT: R1KH-ID=" MACSTR
, MAC2STR(f_r1kh_id
));
1943 wpa_ft_rrb_lookup_r1kh(wpa_auth
, src_addr
, f_r1kh_id
, &r1kh
);
1947 key_len
= sizeof(r1kh
->key
);
1949 RRB_GET_AUTH(FT_RRB_NONCE
, nonce
, "pull request", FT_RRB_NONCE_LEN
);
1950 wpa_hexdump(MSG_DEBUG
, "FT: nonce", f_nonce
, f_nonce_len
);
1952 if (wpa_ft_rrb_decrypt(key
, key_len
, enc
, enc_len
, auth
, auth_len
,
1953 src_addr
, FT_PACKET_R0KH_R1KH_PULL
,
1954 &plain
, &plain_len
) < 0)
1957 RRB_GET(FT_RRB_PMK_R0_NAME
, pmk_r0_name
, msgtype
, WPA_PMK_NAME_LEN
);
1958 wpa_hexdump(MSG_DEBUG
, "FT: PMKR0Name", f_pmk_r0_name
,
1961 RRB_GET(FT_RRB_S1KH_ID
, s1kh_id
, msgtype
, ETH_ALEN
);
1962 wpa_printf(MSG_DEBUG
, "FT: S1KH-ID=" MACSTR
, MAC2STR(f_s1kh_id
));
1964 resp
[0].type
= FT_RRB_S1KH_ID
;
1965 resp
[0].len
= f_s1kh_id_len
;
1966 resp
[0].data
= f_s1kh_id
;
1967 resp
[1].type
= FT_RRB_LAST_EMPTY
;
1969 resp
[1].data
= NULL
;
1971 resp_auth
[0].type
= FT_RRB_NONCE
;
1972 resp_auth
[0].len
= f_nonce_len
;
1973 resp_auth
[0].data
= f_nonce
;
1974 resp_auth
[1].type
= FT_RRB_R0KH_ID
;
1975 resp_auth
[1].len
= f_r0kh_id_len
;
1976 resp_auth
[1].data
= f_r0kh_id
;
1977 resp_auth
[2].type
= FT_RRB_R1KH_ID
;
1978 resp_auth
[2].len
= f_r1kh_id_len
;
1979 resp_auth
[2].data
= f_r1kh_id
;
1980 resp_auth
[3].type
= FT_RRB_LAST_EMPTY
;
1981 resp_auth
[3].len
= 0;
1982 resp_auth
[3].data
= NULL
;
1984 if (wpa_ft_fetch_pmk_r0(wpa_auth
, f_s1kh_id
, f_pmk_r0_name
, &r0
) < 0) {
1985 wpa_printf(MSG_DEBUG
, "FT: No matching PMK-R0-Name found");
1989 ret
= wpa_ft_rrb_build_r0(key
, key_len
, resp
, r0
, f_r1kh_id
, f_s1kh_id
,
1990 resp_auth
, wpa_auth
->addr
,
1991 FT_PACKET_R0KH_R1KH_RESP
,
1992 &packet
, &packet_len
);
1995 wpa_ft_rrb_oui_send(wpa_auth
, src_addr
,
1996 FT_PACKET_R0KH_R1KH_RESP
, packet
,
2007 /* @returns 0 on success
2010 static int wpa_ft_rrb_rx_r1(struct wpa_authenticator
*wpa_auth
,
2011 const u8
*src_addr
, u8 type
,
2012 const u8
*enc
, size_t enc_len
,
2013 const u8
*auth
, size_t auth_len
,
2014 const char *msgtype
, u8
*s1kh_id_out
)
2017 size_t plain_len
= 0;
2018 struct ft_remote_r0kh
*r0kh
;
2021 const u8
*f_r1kh_id
, *f_s1kh_id
, *f_r0kh_id
;
2022 const u8
*f_pmk_r1_name
, *f_pairwise
, *f_pmk_r1
;
2023 size_t f_r1kh_id_len
, f_s1kh_id_len
, f_r0kh_id_len
;
2024 size_t f_pmk_r1_name_len
, f_pairwise_len
, f_pmk_r1_len
;
2028 RRB_GET_AUTH(FT_RRB_R0KH_ID
, r0kh_id
, msgtype
, -1);
2029 wpa_hexdump(MSG_DEBUG
, "FT: R0KH-ID", f_r0kh_id
, f_r0kh_id_len
);
2031 RRB_GET_AUTH(FT_RRB_R1KH_ID
, r1kh_id
, msgtype
, FT_R1KH_ID_LEN
);
2032 wpa_printf(MSG_DEBUG
, "FT: R1KH-ID=" MACSTR
, MAC2STR(f_r1kh_id
));
2034 if (wpa_ft_rrb_check_r1kh(wpa_auth
, f_r1kh_id
)) {
2035 wpa_printf(MSG_DEBUG
, "FT: R1KH-ID mismatch");
2039 wpa_ft_rrb_lookup_r0kh(wpa_auth
, src_addr
, f_r0kh_id
, f_r0kh_id_len
,
2044 key_len
= sizeof(r0kh
->key
);
2046 if (wpa_ft_rrb_decrypt(key
, key_len
, enc
, enc_len
, auth
, auth_len
,
2047 src_addr
, type
, &plain
, &plain_len
) < 0)
2050 RRB_GET(FT_RRB_S1KH_ID
, s1kh_id
, msgtype
, ETH_ALEN
);
2051 wpa_printf(MSG_DEBUG
, "FT: S1KH-ID=" MACSTR
, MAC2STR(f_s1kh_id
));
2054 os_memcpy(s1kh_id_out
, f_s1kh_id
, ETH_ALEN
);
2056 RRB_GET(FT_RRB_PAIRWISE
, pairwise
, msgtype
, sizeof(le16
));
2057 wpa_hexdump(MSG_DEBUG
, "FT: pairwise", f_pairwise
, f_pairwise_len
);
2059 RRB_GET(FT_RRB_PMK_R1_NAME
, pmk_r1_name
, msgtype
, WPA_PMK_NAME_LEN
);
2060 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name",
2061 f_pmk_r1_name
, WPA_PMK_NAME_LEN
);
2063 RRB_GET(FT_RRB_PMK_R1
, pmk_r1
, msgtype
, PMK_LEN
);
2064 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", f_pmk_r1
, PMK_LEN
);
2066 pairwise
= WPA_GET_LE16(f_pairwise
);
2068 if (wpa_ft_store_pmk_r1(wpa_auth
, f_s1kh_id
, f_pmk_r1
, f_pmk_r1_name
,
2075 os_memset(plain
, 0, plain_len
);
2084 static void ft_finish_pull(struct wpa_state_machine
*sm
)
2088 size_t resp_ies_len
;
2091 res
= wpa_ft_process_auth_req(sm
, wpabuf_head(sm
->ft_pending_req_ies
),
2092 wpabuf_len(sm
->ft_pending_req_ies
),
2093 &resp_ies
, &resp_ies_len
);
2094 wpabuf_free(sm
->ft_pending_req_ies
);
2095 sm
->ft_pending_req_ies
= NULL
;
2097 res
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
2099 wpa_printf(MSG_DEBUG
, "FT: Postponed auth callback result for " MACSTR
2100 " - status %u", MAC2STR(sm
->addr
), status
);
2102 sm
->ft_pending_cb(sm
->ft_pending_cb_ctx
, sm
->addr
, sm
->wpa_auth
->addr
,
2103 sm
->ft_pending_auth_transaction
+ 1, status
,
2104 resp_ies
, resp_ies_len
);
2109 struct ft_get_sta_ctx
{
2112 struct wpa_state_machine
*sm
;
2116 static int ft_get_sta_cb(struct wpa_state_machine
*sm
, void *ctx
)
2118 struct ft_get_sta_ctx
*info
= ctx
;
2120 if ((info
->s1kh_id
&&
2121 os_memcmp(info
->s1kh_id
, sm
->addr
, ETH_ALEN
) != 0) ||
2122 os_memcmp(info
->nonce
, sm
->ft_pending_pull_nonce
,
2123 FT_RRB_NONCE_LEN
) != 0 ||
2124 sm
->ft_pending_cb
== NULL
|| sm
->ft_pending_req_ies
== NULL
)
2133 static int wpa_ft_rrb_rx_resp(struct wpa_authenticator
*wpa_auth
,
2135 const u8
*enc
, size_t enc_len
,
2136 const u8
*auth
, size_t auth_len
)
2138 const char *msgtype
= "pull response";
2140 struct ft_get_sta_ctx ctx
;
2141 u8 s1kh_id
[ETH_ALEN
];
2145 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 pull response");
2147 RRB_GET_AUTH(FT_RRB_NONCE
, nonce
, msgtype
, FT_RRB_NONCE_LEN
);
2148 wpa_hexdump(MSG_DEBUG
, "FT: nonce", f_nonce
, f_nonce_len
);
2150 os_memset(&ctx
, 0, sizeof(ctx
));
2151 ctx
.nonce
= f_nonce
;
2152 if (!wpa_auth_for_each_sta(wpa_auth
, ft_get_sta_cb
, &ctx
)) {
2153 /* nonce not found */
2154 wpa_printf(MSG_DEBUG
, "FT: Invalid nonce");
2158 ret
= wpa_ft_rrb_rx_r1(wpa_auth
, src_addr
, FT_PACKET_R0KH_R1KH_RESP
,
2159 enc
, enc_len
, auth
, auth_len
, msgtype
, s1kh_id
);
2163 ctx
.s1kh_id
= s1kh_id
;
2164 if (wpa_auth_for_each_sta(wpa_auth
, ft_get_sta_cb
, &ctx
)) {
2165 wpa_printf(MSG_DEBUG
,
2166 "FT: Response to a pending pull request for " MACSTR
,
2167 MAC2STR(ctx
.sm
->addr
));
2168 ft_finish_pull(ctx
.sm
);
2176 static int wpa_ft_rrb_rx_push(struct wpa_authenticator
*wpa_auth
,
2178 const u8
*enc
, size_t enc_len
,
2179 const u8
*auth
, size_t auth_len
)
2181 const char *msgtype
= "push";
2183 struct os_time tsend
;
2184 const u8
*f_timestamp
;
2185 size_t f_timestamp_len
;
2187 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 push");
2189 RRB_GET_AUTH(FT_RRB_TIMESTAMP
, timestamp
, msgtype
, sizeof(le32
));
2190 tsend
.sec
= WPA_GET_LE32(f_timestamp
);
2191 wpa_printf(MSG_DEBUG
, "FT: timestamp=%ld", tsend
.sec
);
2193 if ((now
.sec
> tsend
.sec
&& now
.sec
- tsend
.sec
> 60) ||
2194 (now
.sec
< tsend
.sec
&& tsend
.sec
- now
.sec
> 60)) {
2195 wpa_printf(MSG_DEBUG
,
2196 "FT(RRB): push did not have a valid timestamp: sender time %ld own time %ld",
2197 tsend
.sec
, now
.sec
);
2201 if (wpa_ft_rrb_rx_r1(wpa_auth
, src_addr
, FT_PACKET_R0KH_R1KH_PUSH
,
2202 enc
, enc_len
, auth
, auth_len
, msgtype
, NULL
) < 0)
2211 int wpa_ft_rrb_rx(struct wpa_authenticator
*wpa_auth
, const u8
*src_addr
,
2212 const u8
*data
, size_t data_len
)
2214 struct ft_rrb_frame
*frame
;
2216 const u8
*pos
, *end
, *start
;
2218 const u8
*sta_addr
, *target_ap_addr
;
2220 wpa_printf(MSG_DEBUG
, "FT: RRB received frame from remote AP " MACSTR
,
2223 if (data_len
< sizeof(*frame
)) {
2224 wpa_printf(MSG_DEBUG
, "FT: Too short RRB frame (data_len=%lu)",
2225 (unsigned long) data_len
);
2230 frame
= (struct ft_rrb_frame
*) pos
;
2231 pos
+= sizeof(*frame
);
2233 alen
= le_to_host16(frame
->action_length
);
2234 wpa_printf(MSG_DEBUG
, "FT: RRB frame - frame_type=%d packet_type=%d "
2235 "action_length=%d ap_address=" MACSTR
,
2236 frame
->frame_type
, frame
->packet_type
, alen
,
2237 MAC2STR(frame
->ap_address
));
2239 if (frame
->frame_type
!= RSN_REMOTE_FRAME_TYPE_FT_RRB
) {
2240 /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */
2241 wpa_printf(MSG_DEBUG
, "FT: RRB discarded frame with "
2242 "unrecognized type %d", frame
->frame_type
);
2246 if (alen
> data_len
- sizeof(*frame
)) {
2247 wpa_printf(MSG_DEBUG
, "FT: RRB frame too short for action "
2252 wpa_hexdump(MSG_MSGDUMP
, "FT: RRB - FT Action frame", pos
, alen
);
2254 if (alen
< 1 + 1 + 2 * ETH_ALEN
) {
2255 wpa_printf(MSG_DEBUG
, "FT: Too short RRB frame (not enough "
2256 "room for Action Frame body); alen=%lu",
2257 (unsigned long) alen
);
2263 if (*pos
!= WLAN_ACTION_FT
) {
2264 wpa_printf(MSG_DEBUG
, "FT: Unexpected Action frame category "
2273 target_ap_addr
= pos
;
2275 wpa_printf(MSG_DEBUG
, "FT: RRB Action Frame: action=%d sta_addr="
2276 MACSTR
" target_ap_addr=" MACSTR
,
2277 action
, MAC2STR(sta_addr
), MAC2STR(target_ap_addr
));
2279 if (frame
->packet_type
== FT_PACKET_REQUEST
) {
2280 wpa_printf(MSG_DEBUG
, "FT: FT Packet Type - Request");
2283 wpa_printf(MSG_DEBUG
, "FT: Unexpected Action %d in "
2284 "RRB Request", action
);
2288 if (os_memcmp(target_ap_addr
, wpa_auth
->addr
, ETH_ALEN
) != 0) {
2289 wpa_printf(MSG_DEBUG
, "FT: Target AP address in the "
2290 "RRB Request does not match with own "
2295 if (wpa_ft_rrb_rx_request(wpa_auth
, frame
->ap_address
,
2296 sta_addr
, pos
, end
- pos
) < 0)
2298 } else if (frame
->packet_type
== FT_PACKET_RESPONSE
) {
2301 if (end
- pos
< 2) {
2302 wpa_printf(MSG_DEBUG
, "FT: Not enough room for status "
2303 "code in RRB Response");
2306 status_code
= WPA_GET_LE16(pos
);
2309 wpa_printf(MSG_DEBUG
, "FT: FT Packet Type - Response "
2310 "(status_code=%d)", status_code
);
2312 if (wpa_ft_action_send(wpa_auth
, sta_addr
, start
, alen
) < 0)
2315 wpa_printf(MSG_DEBUG
, "FT: RRB discarded frame with unknown "
2316 "packet_type %d", frame
->packet_type
);
2321 wpa_hexdump(MSG_DEBUG
, "FT: Ignore extra data in end",
2329 void wpa_ft_rrb_oui_rx(struct wpa_authenticator
*wpa_auth
, const u8
*src_addr
,
2330 const u8
*dst_addr
, u8 oui_suffix
, const u8
*data
,
2333 const u8
*auth
, *enc
;
2336 wpa_printf(MSG_DEBUG
, "FT: RRB-OUI received frame from remote AP "
2337 MACSTR
, MAC2STR(src_addr
));
2338 wpa_printf(MSG_DEBUG
, "FT: RRB-OUI frame - oui_suffix=%d", oui_suffix
);
2340 if (is_multicast_ether_addr(src_addr
)) {
2341 wpa_printf(MSG_DEBUG
,
2342 "FT: RRB-OUI received frame from multicast address "
2343 MACSTR
, MAC2STR(src_addr
));
2347 if (is_multicast_ether_addr(dst_addr
)) {
2348 wpa_printf(MSG_DEBUG
,
2349 "FT: RRB-OUI received frame from remote AP " MACSTR
2350 " to multicast address " MACSTR
,
2351 MAC2STR(src_addr
), MAC2STR(dst_addr
));
2355 if (data_len
< sizeof(u16
)) {
2356 wpa_printf(MSG_DEBUG
, "FT: RRB-OUI frame too short");
2360 alen
= WPA_GET_LE16(data
);
2361 if (data_len
< sizeof(u16
) + alen
) {
2362 wpa_printf(MSG_DEBUG
, "FT: RRB-OUI frame too short");
2366 auth
= data
+ sizeof(u16
);
2367 enc
= data
+ sizeof(u16
) + alen
;
2368 elen
= data_len
- sizeof(u16
) - alen
;
2370 switch (oui_suffix
) {
2371 case FT_PACKET_R0KH_R1KH_PULL
:
2372 wpa_ft_rrb_rx_pull(wpa_auth
, src_addr
, enc
, elen
, auth
, alen
);
2374 case FT_PACKET_R0KH_R1KH_RESP
:
2375 wpa_ft_rrb_rx_resp(wpa_auth
, src_addr
, enc
, elen
, auth
, alen
);
2377 case FT_PACKET_R0KH_R1KH_PUSH
:
2378 wpa_ft_rrb_rx_push(wpa_auth
, src_addr
, enc
, elen
, auth
, alen
);
2384 static int wpa_ft_generate_pmk_r1(struct wpa_authenticator
*wpa_auth
,
2385 struct wpa_ft_pmk_r0_sa
*pmk_r0
,
2386 struct ft_remote_r1kh
*r1kh
,
2392 u8 f_timestamp
[sizeof(le32
)];
2393 struct tlv_list push
[] = {
2394 { .type
= FT_RRB_S1KH_ID
, .len
= ETH_ALEN
,
2396 { .type
= FT_RRB_PMK_R0_NAME
, .len
= WPA_PMK_NAME_LEN
,
2397 .data
= pmk_r0
->pmk_r0_name
},
2398 { .type
= FT_RRB_LAST_EMPTY
, .len
= 0, .data
= NULL
},
2400 struct tlv_list push_auth
[] = {
2401 { .type
= FT_RRB_TIMESTAMP
, .len
= sizeof(f_timestamp
),
2402 .data
= f_timestamp
},
2403 { .type
= FT_RRB_R0KH_ID
,
2404 .len
= wpa_auth
->conf
.r0_key_holder_len
,
2405 .data
= wpa_auth
->conf
.r0_key_holder
},
2406 { .type
= FT_RRB_R1KH_ID
, .len
= FT_R1KH_ID_LEN
,
2408 { .type
= FT_RRB_LAST_EMPTY
, .len
= 0, .data
= NULL
},
2412 WPA_PUT_LE32(f_timestamp
, now
.sec
);
2414 if (wpa_ft_rrb_build_r0(r1kh
->key
, sizeof(r1kh
->key
), push
, pmk_r0
,
2415 r1kh
->id
, s1kh_id
, push_auth
, wpa_auth
->addr
,
2416 FT_PACKET_R0KH_R1KH_PUSH
,
2417 &packet
, &packet_len
) < 0)
2420 wpa_ft_rrb_oui_send(wpa_auth
, r1kh
->addr
, FT_PACKET_R0KH_R1KH_PUSH
,
2421 packet
, packet_len
);
2428 void wpa_ft_push_pmk_r1(struct wpa_authenticator
*wpa_auth
, const u8
*addr
)
2430 struct wpa_ft_pmk_r0_sa
*r0
;
2431 struct ft_remote_r1kh
*r1kh
;
2433 if (!wpa_auth
->conf
.pmk_r1_push
)
2436 r0
= wpa_auth
->ft_pmk_cache
->pmk_r0
;
2438 if (os_memcmp(r0
->spa
, addr
, ETH_ALEN
) == 0)
2443 if (r0
== NULL
|| r0
->pmk_r1_pushed
)
2445 r0
->pmk_r1_pushed
= 1;
2447 wpa_printf(MSG_DEBUG
, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
2448 "for STA " MACSTR
, MAC2STR(addr
));
2450 r1kh
= wpa_auth
->conf
.r1kh_list
;
2452 wpa_ft_generate_pmk_r1(wpa_auth
, r0
, r1kh
, addr
);
2457 #endif /* CONFIG_IEEE80211R_AP */