2 * hostapd - IEEE 802.11r - Fast BSS Transition
3 * Copyright (c) 2004-2014, 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 "common/ieee802_11_defs.h"
14 #include "common/ieee802_11_common.h"
15 #include "crypto/aes_wrap.h"
16 #include "crypto/random.h"
17 #include "ap_config.h"
18 #include "ieee802_11.h"
21 #include "wpa_auth_i.h"
24 #ifdef CONFIG_IEEE80211R
26 static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine
*sm
,
27 const u8
*current_ap
, const u8
*sta_addr
,
28 u16 status
, const u8
*resp_ies
,
32 static int wpa_ft_rrb_send(struct wpa_authenticator
*wpa_auth
, const u8
*dst
,
33 const u8
*data
, size_t data_len
)
35 if (wpa_auth
->cb
.send_ether
== NULL
)
37 wpa_printf(MSG_DEBUG
, "FT: RRB send to " MACSTR
, MAC2STR(dst
));
38 return wpa_auth
->cb
.send_ether(wpa_auth
->cb
.ctx
, dst
, ETH_P_RRB
,
43 static int wpa_ft_action_send(struct wpa_authenticator
*wpa_auth
,
44 const u8
*dst
, const u8
*data
, size_t data_len
)
46 if (wpa_auth
->cb
.send_ft_action
== NULL
)
48 return wpa_auth
->cb
.send_ft_action(wpa_auth
->cb
.ctx
, dst
,
53 static struct wpa_state_machine
*
54 wpa_ft_add_sta(struct wpa_authenticator
*wpa_auth
, const u8
*sta_addr
)
56 if (wpa_auth
->cb
.add_sta
== NULL
)
58 return wpa_auth
->cb
.add_sta(wpa_auth
->cb
.ctx
, sta_addr
);
62 static int wpa_ft_add_tspec(struct wpa_authenticator
*wpa_auth
,
64 u8
*tspec_ie
, size_t tspec_ielen
)
66 if (wpa_auth
->cb
.add_tspec
== NULL
) {
67 wpa_printf(MSG_DEBUG
, "FT: add_tspec is not initialized");
70 return wpa_auth
->cb
.add_tspec(wpa_auth
->cb
.ctx
, sta_addr
, tspec_ie
,
75 int wpa_write_mdie(struct wpa_auth_config
*conf
, u8
*buf
, size_t len
)
79 if (len
< 2 + sizeof(struct rsn_mdie
))
82 *pos
++ = WLAN_EID_MOBILITY_DOMAIN
;
83 *pos
++ = MOBILITY_DOMAIN_ID_LEN
+ 1;
84 os_memcpy(pos
, conf
->mobility_domain
, MOBILITY_DOMAIN_ID_LEN
);
85 pos
+= MOBILITY_DOMAIN_ID_LEN
;
88 capab
|= RSN_FT_CAPAB_FT_OVER_DS
;
95 int wpa_write_ftie(struct wpa_auth_config
*conf
, const u8
*r0kh_id
,
97 const u8
*anonce
, const u8
*snonce
,
98 u8
*buf
, size_t len
, const u8
*subelem
,
101 u8
*pos
= buf
, *ielen
;
102 struct rsn_ftie
*hdr
;
104 if (len
< 2 + sizeof(*hdr
) + 2 + FT_R1KH_ID_LEN
+ 2 + r0kh_id_len
+
108 *pos
++ = WLAN_EID_FAST_BSS_TRANSITION
;
111 hdr
= (struct rsn_ftie
*) pos
;
112 os_memset(hdr
, 0, sizeof(*hdr
));
114 WPA_PUT_LE16(hdr
->mic_control
, 0);
116 os_memcpy(hdr
->anonce
, anonce
, WPA_NONCE_LEN
);
118 os_memcpy(hdr
->snonce
, snonce
, WPA_NONCE_LEN
);
120 /* Optional Parameters */
121 *pos
++ = FTIE_SUBELEM_R1KH_ID
;
122 *pos
++ = FT_R1KH_ID_LEN
;
123 os_memcpy(pos
, conf
->r1_key_holder
, FT_R1KH_ID_LEN
);
124 pos
+= FT_R1KH_ID_LEN
;
127 *pos
++ = FTIE_SUBELEM_R0KH_ID
;
128 *pos
++ = r0kh_id_len
;
129 os_memcpy(pos
, r0kh_id
, r0kh_id_len
);
134 os_memcpy(pos
, subelem
, subelem_len
);
138 *ielen
= pos
- buf
- 2;
144 struct wpa_ft_pmk_r0_sa
{
145 struct wpa_ft_pmk_r0_sa
*next
;
147 u8 pmk_r0_name
[WPA_PMK_NAME_LEN
];
149 int pairwise
; /* Pairwise cipher suite, WPA_CIPHER_* */
150 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
154 struct wpa_ft_pmk_r1_sa
{
155 struct wpa_ft_pmk_r1_sa
*next
;
157 u8 pmk_r1_name
[WPA_PMK_NAME_LEN
];
159 int pairwise
; /* Pairwise cipher suite, WPA_CIPHER_* */
160 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
163 struct wpa_ft_pmk_cache
{
164 struct wpa_ft_pmk_r0_sa
*pmk_r0
;
165 struct wpa_ft_pmk_r1_sa
*pmk_r1
;
168 struct wpa_ft_pmk_cache
* wpa_ft_pmk_cache_init(void)
170 struct wpa_ft_pmk_cache
*cache
;
172 cache
= os_zalloc(sizeof(*cache
));
178 void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache
*cache
)
180 struct wpa_ft_pmk_r0_sa
*r0
, *r0prev
;
181 struct wpa_ft_pmk_r1_sa
*r1
, *r1prev
;
187 os_memset(r0prev
->pmk_r0
, 0, PMK_LEN
);
195 os_memset(r1prev
->pmk_r1
, 0, PMK_LEN
);
203 static int wpa_ft_store_pmk_r0(struct wpa_authenticator
*wpa_auth
,
204 const u8
*spa
, const u8
*pmk_r0
,
205 const u8
*pmk_r0_name
, int pairwise
)
207 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
208 struct wpa_ft_pmk_r0_sa
*r0
;
210 /* TODO: add expiration and limit on number of entries in cache */
212 r0
= os_zalloc(sizeof(*r0
));
216 os_memcpy(r0
->pmk_r0
, pmk_r0
, PMK_LEN
);
217 os_memcpy(r0
->pmk_r0_name
, pmk_r0_name
, WPA_PMK_NAME_LEN
);
218 os_memcpy(r0
->spa
, spa
, ETH_ALEN
);
219 r0
->pairwise
= pairwise
;
221 r0
->next
= cache
->pmk_r0
;
228 static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator
*wpa_auth
,
229 const u8
*spa
, const u8
*pmk_r0_name
,
230 u8
*pmk_r0
, int *pairwise
)
232 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
233 struct wpa_ft_pmk_r0_sa
*r0
;
237 if (os_memcmp(r0
->spa
, spa
, ETH_ALEN
) == 0 &&
238 os_memcmp(r0
->pmk_r0_name
, pmk_r0_name
, WPA_PMK_NAME_LEN
)
240 os_memcpy(pmk_r0
, r0
->pmk_r0
, PMK_LEN
);
242 *pairwise
= r0
->pairwise
;
253 static int wpa_ft_store_pmk_r1(struct wpa_authenticator
*wpa_auth
,
254 const u8
*spa
, const u8
*pmk_r1
,
255 const u8
*pmk_r1_name
, int pairwise
)
257 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
258 struct wpa_ft_pmk_r1_sa
*r1
;
260 /* TODO: add expiration and limit on number of entries in cache */
262 r1
= os_zalloc(sizeof(*r1
));
266 os_memcpy(r1
->pmk_r1
, pmk_r1
, PMK_LEN
);
267 os_memcpy(r1
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
);
268 os_memcpy(r1
->spa
, spa
, ETH_ALEN
);
269 r1
->pairwise
= pairwise
;
271 r1
->next
= cache
->pmk_r1
;
278 static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator
*wpa_auth
,
279 const u8
*spa
, const u8
*pmk_r1_name
,
280 u8
*pmk_r1
, int *pairwise
)
282 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
283 struct wpa_ft_pmk_r1_sa
*r1
;
287 if (os_memcmp(r1
->spa
, spa
, ETH_ALEN
) == 0 &&
288 os_memcmp(r1
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
)
290 os_memcpy(pmk_r1
, r1
->pmk_r1
, PMK_LEN
);
292 *pairwise
= r1
->pairwise
;
303 static int wpa_ft_pull_pmk_r1(struct wpa_state_machine
*sm
,
304 const u8
*ies
, size_t ies_len
,
305 const u8
*pmk_r0_name
)
307 struct ft_remote_r0kh
*r0kh
;
308 struct ft_r0kh_r1kh_pull_frame frame
, f
;
310 r0kh
= sm
->wpa_auth
->conf
.r0kh_list
;
312 if (r0kh
->id_len
== sm
->r0kh_id_len
&&
313 os_memcmp(r0kh
->id
, sm
->r0kh_id
, sm
->r0kh_id_len
) == 0)
318 wpa_hexdump(MSG_DEBUG
, "FT: Did not find R0KH-ID",
319 sm
->r0kh_id
, sm
->r0kh_id_len
);
323 wpa_printf(MSG_DEBUG
, "FT: Send PMK-R1 pull request to remote R0KH "
324 "address " MACSTR
, MAC2STR(r0kh
->addr
));
326 os_memset(&frame
, 0, sizeof(frame
));
327 frame
.frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
328 frame
.packet_type
= FT_PACKET_R0KH_R1KH_PULL
;
329 frame
.data_length
= host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN
);
330 os_memcpy(frame
.ap_address
, sm
->wpa_auth
->addr
, ETH_ALEN
);
332 /* aes_wrap() does not support inplace encryption, so use a temporary
333 * buffer for the data. */
334 if (random_get_bytes(f
.nonce
, FT_R0KH_R1KH_PULL_NONCE_LEN
)) {
335 wpa_printf(MSG_DEBUG
, "FT: Failed to get random data for "
339 os_memcpy(sm
->ft_pending_pull_nonce
, f
.nonce
,
340 FT_R0KH_R1KH_PULL_NONCE_LEN
);
341 os_memcpy(f
.pmk_r0_name
, pmk_r0_name
, WPA_PMK_NAME_LEN
);
342 os_memcpy(f
.r1kh_id
, sm
->wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
);
343 os_memcpy(f
.s1kh_id
, sm
->addr
, ETH_ALEN
);
344 os_memset(f
.pad
, 0, sizeof(f
.pad
));
346 if (aes_wrap(r0kh
->key
, (FT_R0KH_R1KH_PULL_DATA_LEN
+ 7) / 8,
347 f
.nonce
, frame
.nonce
) < 0)
350 wpabuf_free(sm
->ft_pending_req_ies
);
351 sm
->ft_pending_req_ies
= wpabuf_alloc_copy(ies
, ies_len
);
352 if (sm
->ft_pending_req_ies
== NULL
)
355 wpa_ft_rrb_send(sm
->wpa_auth
, r0kh
->addr
, (u8
*) &frame
, sizeof(frame
));
361 int wpa_auth_derive_ptk_ft(struct wpa_state_machine
*sm
, const u8
*pmk
,
362 struct wpa_ptk
*ptk
, size_t ptk_len
)
364 u8 pmk_r0
[PMK_LEN
], pmk_r0_name
[WPA_PMK_NAME_LEN
];
366 u8 ptk_name
[WPA_PMK_NAME_LEN
];
367 const u8
*mdid
= sm
->wpa_auth
->conf
.mobility_domain
;
368 const u8
*r0kh
= sm
->wpa_auth
->conf
.r0_key_holder
;
369 size_t r0kh_len
= sm
->wpa_auth
->conf
.r0_key_holder_len
;
370 const u8
*r1kh
= sm
->wpa_auth
->conf
.r1_key_holder
;
371 const u8
*ssid
= sm
->wpa_auth
->conf
.ssid
;
372 size_t ssid_len
= sm
->wpa_auth
->conf
.ssid_len
;
375 if (sm
->xxkey_len
== 0) {
376 wpa_printf(MSG_DEBUG
, "FT: XXKey not available for key "
381 wpa_derive_pmk_r0(sm
->xxkey
, sm
->xxkey_len
, ssid
, ssid_len
, mdid
,
382 r0kh
, r0kh_len
, sm
->addr
, pmk_r0
, pmk_r0_name
);
383 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R0", pmk_r0
, PMK_LEN
);
384 wpa_hexdump(MSG_DEBUG
, "FT: PMKR0Name", pmk_r0_name
, WPA_PMK_NAME_LEN
);
385 wpa_ft_store_pmk_r0(sm
->wpa_auth
, sm
->addr
, pmk_r0
, pmk_r0_name
,
388 wpa_derive_pmk_r1(pmk_r0
, pmk_r0_name
, r1kh
, sm
->addr
,
389 pmk_r1
, sm
->pmk_r1_name
);
390 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", pmk_r1
, PMK_LEN
);
391 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", sm
->pmk_r1_name
,
393 wpa_ft_store_pmk_r1(sm
->wpa_auth
, sm
->addr
, pmk_r1
, sm
->pmk_r1_name
,
396 wpa_pmk_r1_to_ptk(pmk_r1
, sm
->SNonce
, sm
->ANonce
, sm
->addr
,
397 sm
->wpa_auth
->addr
, sm
->pmk_r1_name
,
398 (u8
*) ptk
, ptk_len
, ptk_name
);
399 wpa_hexdump_key(MSG_DEBUG
, "FT: PTK", (u8
*) ptk
, ptk_len
);
400 wpa_hexdump(MSG_DEBUG
, "FT: PTKName", ptk_name
, WPA_PMK_NAME_LEN
);
406 static inline int wpa_auth_get_seqnum(struct wpa_authenticator
*wpa_auth
,
407 const u8
*addr
, int idx
, u8
*seq
)
409 if (wpa_auth
->cb
.get_seqnum
== NULL
)
411 return wpa_auth
->cb
.get_seqnum(wpa_auth
->cb
.ctx
, addr
, idx
, seq
);
415 static u8
* wpa_ft_gtk_subelem(struct wpa_state_machine
*sm
, size_t *len
)
418 struct wpa_group
*gsm
= sm
->group
;
419 size_t subelem_len
, pad_len
;
424 key_len
= gsm
->GTK_len
;
425 if (key_len
> sizeof(keybuf
))
429 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less
432 pad_len
= key_len
% 8;
434 pad_len
= 8 - pad_len
;
435 if (key_len
+ pad_len
< 16)
437 if (pad_len
&& key_len
< sizeof(keybuf
)) {
438 os_memcpy(keybuf
, gsm
->GTK
[gsm
->GN
- 1], key_len
);
439 os_memset(keybuf
+ key_len
, 0, pad_len
);
440 keybuf
[key_len
] = 0xdd;
444 key
= gsm
->GTK
[gsm
->GN
- 1];
447 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
450 subelem_len
= 13 + key_len
+ 8;
451 subelem
= os_zalloc(subelem_len
);
455 subelem
[0] = FTIE_SUBELEM_GTK
;
456 subelem
[1] = 11 + key_len
+ 8;
457 /* Key ID in B0-B1 of Key Info */
458 WPA_PUT_LE16(&subelem
[2], gsm
->GN
& 0x03);
459 subelem
[4] = gsm
->GTK_len
;
460 wpa_auth_get_seqnum(sm
->wpa_auth
, NULL
, gsm
->GN
, subelem
+ 5);
461 if (aes_wrap(sm
->PTK
.kek
, key_len
/ 8, key
, subelem
+ 13)) {
471 #ifdef CONFIG_IEEE80211W
472 static u8
* wpa_ft_igtk_subelem(struct wpa_state_machine
*sm
, size_t *len
)
475 struct wpa_group
*gsm
= sm
->group
;
478 /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
480 subelem_len
= 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN
+ 8;
481 subelem
= os_zalloc(subelem_len
);
486 *pos
++ = FTIE_SUBELEM_IGTK
;
487 *pos
++ = subelem_len
- 2;
488 WPA_PUT_LE16(pos
, gsm
->GN_igtk
);
490 wpa_auth_get_seqnum(sm
->wpa_auth
, NULL
, gsm
->GN_igtk
, pos
);
492 *pos
++ = WPA_IGTK_LEN
;
493 if (aes_wrap(sm
->PTK
.kek
, WPA_IGTK_LEN
/ 8,
494 gsm
->IGTK
[gsm
->GN_igtk
- 4], pos
)) {
502 #endif /* CONFIG_IEEE80211W */
505 static u8
* wpa_ft_process_rdie(struct wpa_state_machine
*sm
,
506 u8
*pos
, u8
*end
, u8 id
, u8 descr_count
,
507 const u8
*ies
, size_t ies_len
)
509 struct ieee802_11_elems parse
;
510 struct rsn_rdie
*rdie
;
512 wpa_printf(MSG_DEBUG
, "FT: Resource Request: id=%d descr_count=%d",
514 wpa_hexdump(MSG_MSGDUMP
, "FT: Resource descriptor IE(s)",
517 if (end
- pos
< (int) sizeof(*rdie
)) {
518 wpa_printf(MSG_ERROR
, "FT: Not enough room for response RDIE");
522 *pos
++ = WLAN_EID_RIC_DATA
;
523 *pos
++ = sizeof(*rdie
);
524 rdie
= (struct rsn_rdie
*) pos
;
526 rdie
->descr_count
= 0;
527 rdie
->status_code
= host_to_le16(WLAN_STATUS_SUCCESS
);
528 pos
+= sizeof(*rdie
);
530 if (ieee802_11_parse_elems((u8
*) ies
, ies_len
, &parse
, 1) ==
532 wpa_printf(MSG_DEBUG
, "FT: Failed to parse request IEs");
534 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
539 if (parse
.wmm_tspec
&& sm
->wpa_auth
->conf
.ap_mlme
) {
540 struct wmm_tspec_element
*tspec
;
543 if (parse
.wmm_tspec_len
+ 2 < (int) sizeof(*tspec
)) {
544 wpa_printf(MSG_DEBUG
, "FT: Too short WMM TSPEC IE "
545 "(%d)", (int) parse
.wmm_tspec_len
);
547 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
550 if (end
- pos
< (int) sizeof(*tspec
)) {
551 wpa_printf(MSG_ERROR
, "FT: Not enough room for "
554 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
557 tspec
= (struct wmm_tspec_element
*) pos
;
558 os_memcpy(tspec
, parse
.wmm_tspec
- 2, sizeof(*tspec
));
559 res
= wmm_process_tspec(tspec
);
560 wpa_printf(MSG_DEBUG
, "FT: ADDTS processing result: %d", res
);
561 if (res
== WMM_ADDTS_STATUS_INVALID_PARAMETERS
)
563 host_to_le16(WLAN_STATUS_INVALID_PARAMETERS
);
564 else if (res
== WMM_ADDTS_STATUS_REFUSED
)
566 host_to_le16(WLAN_STATUS_REQUEST_DECLINED
);
568 /* TSPEC accepted; include updated TSPEC in response */
569 rdie
->descr_count
= 1;
570 pos
+= sizeof(*tspec
);
574 #endif /* NEED_AP_MLME */
576 if (parse
.wmm_tspec
&& !sm
->wpa_auth
->conf
.ap_mlme
) {
577 struct wmm_tspec_element
*tspec
;
580 tspec
= (struct wmm_tspec_element
*) pos
;
581 os_memcpy(tspec
, parse
.wmm_tspec
- 2, sizeof(*tspec
));
582 res
= wpa_ft_add_tspec(sm
->wpa_auth
, sm
->addr
, pos
,
586 rdie
->status_code
= host_to_le16(res
);
588 /* TSPEC accepted; include updated TSPEC in
590 rdie
->descr_count
= 1;
591 pos
+= sizeof(*tspec
);
597 wpa_printf(MSG_DEBUG
, "FT: No supported resource requested");
598 rdie
->status_code
= host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
603 static u8
* wpa_ft_process_ric(struct wpa_state_machine
*sm
, u8
*pos
, u8
*end
,
604 const u8
*ric
, size_t ric_len
)
606 const u8
*rpos
, *start
;
607 const struct rsn_rdie
*rdie
;
609 wpa_hexdump(MSG_MSGDUMP
, "FT: RIC Request", ric
, ric_len
);
612 while (rpos
+ sizeof(*rdie
) < ric
+ ric_len
) {
613 if (rpos
[0] != WLAN_EID_RIC_DATA
|| rpos
[1] < sizeof(*rdie
) ||
614 rpos
+ 2 + rpos
[1] > ric
+ ric_len
)
616 rdie
= (const struct rsn_rdie
*) (rpos
+ 2);
620 while (rpos
+ 2 <= ric
+ ric_len
&&
621 rpos
+ 2 + rpos
[1] <= ric
+ ric_len
) {
622 if (rpos
[0] == WLAN_EID_RIC_DATA
)
626 pos
= wpa_ft_process_rdie(sm
, pos
, end
, rdie
->id
,
628 start
, rpos
- start
);
635 u8
* wpa_sm_write_assoc_resp_ies(struct wpa_state_machine
*sm
, u8
*pos
,
636 size_t max_len
, int auth_alg
,
637 const u8
*req_ies
, size_t req_ies_len
)
639 u8
*end
, *mdie
, *ftie
, *rsnie
= NULL
, *r0kh_id
, *subelem
= NULL
;
640 size_t mdie_len
, ftie_len
, rsnie_len
= 0, r0kh_id_len
, subelem_len
= 0;
642 struct wpa_auth_config
*conf
;
643 struct rsn_ftie
*_ftie
;
644 struct wpa_ft_ies parse
;
651 conf
= &sm
->wpa_auth
->conf
;
653 if (!wpa_key_mgmt_ft(sm
->wpa_key_mgmt
))
658 if (auth_alg
== WLAN_AUTH_FT
) {
660 * RSN (only present if this is a Reassociation Response and
661 * part of a fast BSS transition)
663 res
= wpa_write_rsn_ie(conf
, pos
, end
- pos
, sm
->pmk_r1_name
);
671 /* Mobility Domain Information */
672 res
= wpa_write_mdie(conf
, pos
, end
- pos
);
679 /* Fast BSS Transition Information */
680 if (auth_alg
== WLAN_AUTH_FT
) {
681 subelem
= wpa_ft_gtk_subelem(sm
, &subelem_len
);
682 r0kh_id
= sm
->r0kh_id
;
683 r0kh_id_len
= sm
->r0kh_id_len
;
686 #ifdef CONFIG_IEEE80211W
687 if (sm
->mgmt_frame_prot
) {
691 igtk
= wpa_ft_igtk_subelem(sm
, &igtk_len
);
696 nbuf
= os_realloc(subelem
, subelem_len
+ igtk_len
);
703 os_memcpy(subelem
+ subelem_len
, igtk
, igtk_len
);
704 subelem_len
+= igtk_len
;
707 #endif /* CONFIG_IEEE80211W */
709 r0kh_id
= conf
->r0_key_holder
;
710 r0kh_id_len
= conf
->r0_key_holder_len
;
714 res
= wpa_write_ftie(conf
, r0kh_id
, r0kh_id_len
, anonce
, snonce
, pos
,
715 end
- pos
, subelem
, subelem_len
);
723 os_free(sm
->assoc_resp_ftie
);
724 sm
->assoc_resp_ftie
= os_malloc(ftie_len
);
725 if (sm
->assoc_resp_ftie
)
726 os_memcpy(sm
->assoc_resp_ftie
, ftie
, ftie_len
);
728 _ftie
= (struct rsn_ftie
*) (ftie
+ 2);
729 if (auth_alg
== WLAN_AUTH_FT
)
730 _ftie
->mic_control
[1] = 3; /* Information element count */
733 if (wpa_ft_parse_ies(req_ies
, req_ies_len
, &parse
) == 0 && parse
.ric
) {
734 pos
= wpa_ft_process_ric(sm
, pos
, end
, parse
.ric
,
736 if (auth_alg
== WLAN_AUTH_FT
)
737 _ftie
->mic_control
[1] +=
738 ieee802_11_ie_count(ric_start
,
741 if (ric_start
== pos
)
744 if (auth_alg
== WLAN_AUTH_FT
&&
745 wpa_ft_mic(sm
->PTK
.kck
, sm
->addr
, sm
->wpa_auth
->addr
, 6,
746 mdie
, mdie_len
, ftie
, ftie_len
,
748 ric_start
, ric_start
? pos
- ric_start
: 0,
750 wpa_printf(MSG_DEBUG
, "FT: Failed to calculate MIC");
756 static inline int wpa_auth_set_key(struct wpa_authenticator
*wpa_auth
,
758 enum wpa_alg alg
, const u8
*addr
, int idx
,
759 u8
*key
, size_t key_len
)
761 if (wpa_auth
->cb
.set_key
== NULL
)
763 return wpa_auth
->cb
.set_key(wpa_auth
->cb
.ctx
, vlan_id
, alg
, addr
, idx
,
768 void wpa_ft_install_ptk(struct wpa_state_machine
*sm
)
773 /* MLME-SETKEYS.request(PTK) */
774 alg
= wpa_cipher_to_alg(sm
->pairwise
);
775 klen
= wpa_cipher_key_len(sm
->pairwise
);
776 if (!wpa_cipher_valid_pairwise(sm
->pairwise
)) {
777 wpa_printf(MSG_DEBUG
, "FT: Unknown pairwise alg 0x%x - skip "
778 "PTK configuration", sm
->pairwise
);
782 /* FIX: add STA entry to kernel/driver here? The set_key will fail
783 * most likely without this.. At the moment, STA entry is added only
784 * after association has been completed. This function will be called
785 * again after association to get the PTK configured, but that could be
786 * optimized by adding the STA entry earlier.
788 if (wpa_auth_set_key(sm
->wpa_auth
, 0, alg
, sm
->addr
, 0,
792 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
793 sm
->pairwise_set
= TRUE
;
797 static int wpa_ft_process_auth_req(struct wpa_state_machine
*sm
,
798 const u8
*ies
, size_t ies_len
,
799 u8
**resp_ies
, size_t *resp_ies_len
)
801 struct rsn_mdie
*mdie
;
802 struct rsn_ftie
*ftie
;
803 u8 pmk_r1
[PMK_LEN
], pmk_r1_name
[WPA_PMK_NAME_LEN
];
804 u8 ptk_name
[WPA_PMK_NAME_LEN
];
805 struct wpa_auth_config
*conf
;
806 struct wpa_ft_ies parse
;
807 size_t buflen
, ptk_len
;
815 sm
->pmk_r1_name_valid
= 0;
816 conf
= &sm
->wpa_auth
->conf
;
818 wpa_hexdump(MSG_DEBUG
, "FT: Received authentication frame IEs",
821 if (wpa_ft_parse_ies(ies
, ies_len
, &parse
) < 0) {
822 wpa_printf(MSG_DEBUG
, "FT: Failed to parse FT IEs");
823 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
826 mdie
= (struct rsn_mdie
*) parse
.mdie
;
827 if (mdie
== NULL
|| parse
.mdie_len
< sizeof(*mdie
) ||
828 os_memcmp(mdie
->mobility_domain
,
829 sm
->wpa_auth
->conf
.mobility_domain
,
830 MOBILITY_DOMAIN_ID_LEN
) != 0) {
831 wpa_printf(MSG_DEBUG
, "FT: Invalid MDIE");
832 return WLAN_STATUS_INVALID_MDIE
;
835 ftie
= (struct rsn_ftie
*) parse
.ftie
;
836 if (ftie
== NULL
|| parse
.ftie_len
< sizeof(*ftie
)) {
837 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE");
838 return WLAN_STATUS_INVALID_FTIE
;
841 os_memcpy(sm
->SNonce
, ftie
->snonce
, WPA_NONCE_LEN
);
843 if (parse
.r0kh_id
== NULL
) {
844 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE - no R0KH-ID");
845 return WLAN_STATUS_INVALID_FTIE
;
848 wpa_hexdump(MSG_DEBUG
, "FT: STA R0KH-ID",
849 parse
.r0kh_id
, parse
.r0kh_id_len
);
850 os_memcpy(sm
->r0kh_id
, parse
.r0kh_id
, parse
.r0kh_id_len
);
851 sm
->r0kh_id_len
= parse
.r0kh_id_len
;
853 if (parse
.rsn_pmkid
== NULL
) {
854 wpa_printf(MSG_DEBUG
, "FT: No PMKID in RSNIE");
855 return WLAN_STATUS_INVALID_PMKID
;
858 wpa_hexdump(MSG_DEBUG
, "FT: Requested PMKR0Name",
859 parse
.rsn_pmkid
, WPA_PMK_NAME_LEN
);
860 wpa_derive_pmk_r1_name(parse
.rsn_pmkid
,
861 sm
->wpa_auth
->conf
.r1_key_holder
, sm
->addr
,
863 wpa_hexdump(MSG_DEBUG
, "FT: Derived requested PMKR1Name",
864 pmk_r1_name
, WPA_PMK_NAME_LEN
);
866 if (wpa_ft_fetch_pmk_r1(sm
->wpa_auth
, sm
->addr
, pmk_r1_name
, pmk_r1
,
868 if (wpa_ft_pull_pmk_r1(sm
, ies
, ies_len
, parse
.rsn_pmkid
) < 0) {
869 wpa_printf(MSG_DEBUG
, "FT: Did not have matching "
870 "PMK-R1 and unknown R0KH-ID");
871 return WLAN_STATUS_INVALID_PMKID
;
874 return -1; /* Status pending */
877 wpa_hexdump_key(MSG_DEBUG
, "FT: Selected PMK-R1", pmk_r1
, PMK_LEN
);
878 sm
->pmk_r1_name_valid
= 1;
879 os_memcpy(sm
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
);
881 if (random_get_bytes(sm
->ANonce
, WPA_NONCE_LEN
)) {
882 wpa_printf(MSG_DEBUG
, "FT: Failed to get random data for "
884 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
887 wpa_hexdump(MSG_DEBUG
, "FT: Received SNonce",
888 sm
->SNonce
, WPA_NONCE_LEN
);
889 wpa_hexdump(MSG_DEBUG
, "FT: Generated ANonce",
890 sm
->ANonce
, WPA_NONCE_LEN
);
892 ptk_len
= pairwise
== WPA_CIPHER_TKIP
? 64 : 48;
893 wpa_pmk_r1_to_ptk(pmk_r1
, sm
->SNonce
, sm
->ANonce
, sm
->addr
,
894 sm
->wpa_auth
->addr
, pmk_r1_name
,
895 (u8
*) &sm
->PTK
, ptk_len
, ptk_name
);
896 wpa_hexdump_key(MSG_DEBUG
, "FT: PTK",
897 (u8
*) &sm
->PTK
, ptk_len
);
898 wpa_hexdump(MSG_DEBUG
, "FT: PTKName", ptk_name
, WPA_PMK_NAME_LEN
);
900 sm
->pairwise
= pairwise
;
901 sm
->PTK_valid
= TRUE
;
902 wpa_ft_install_ptk(sm
);
904 buflen
= 2 + sizeof(struct rsn_mdie
) + 2 + sizeof(struct rsn_ftie
) +
905 2 + FT_R1KH_ID_LEN
+ 200;
906 *resp_ies
= os_zalloc(buflen
);
907 if (*resp_ies
== NULL
) {
908 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
912 end
= *resp_ies
+ buflen
;
914 ret
= wpa_write_rsn_ie(conf
, pos
, end
- pos
, parse
.rsn_pmkid
);
918 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
922 ret
= wpa_write_mdie(conf
, pos
, end
- pos
);
926 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
930 ret
= wpa_write_ftie(conf
, parse
.r0kh_id
, parse
.r0kh_id_len
,
931 sm
->ANonce
, sm
->SNonce
, pos
, end
- pos
, NULL
, 0);
935 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
939 *resp_ies_len
= pos
- *resp_ies
;
941 return WLAN_STATUS_SUCCESS
;
945 void wpa_ft_process_auth(struct wpa_state_machine
*sm
, const u8
*bssid
,
946 u16 auth_transaction
, const u8
*ies
, size_t ies_len
,
947 void (*cb
)(void *ctx
, const u8
*dst
, const u8
*bssid
,
948 u16 auth_transaction
, u16 status
,
949 const u8
*ies
, size_t ies_len
),
958 wpa_printf(MSG_DEBUG
, "FT: Received authentication frame, but "
959 "WPA SM not available");
963 wpa_printf(MSG_DEBUG
, "FT: Received authentication frame: STA=" MACSTR
964 " BSSID=" MACSTR
" transaction=%d",
965 MAC2STR(sm
->addr
), MAC2STR(bssid
), auth_transaction
);
966 sm
->ft_pending_cb
= cb
;
967 sm
->ft_pending_cb_ctx
= ctx
;
968 sm
->ft_pending_auth_transaction
= auth_transaction
;
969 res
= wpa_ft_process_auth_req(sm
, ies
, ies_len
, &resp_ies
,
972 wpa_printf(MSG_DEBUG
, "FT: Callback postponed until response is available");
977 wpa_printf(MSG_DEBUG
, "FT: FT authentication response: dst=" MACSTR
978 " auth_transaction=%d status=%d",
979 MAC2STR(sm
->addr
), auth_transaction
+ 1, status
);
980 wpa_hexdump(MSG_DEBUG
, "FT: Response IEs", resp_ies
, resp_ies_len
);
981 cb(ctx
, sm
->addr
, bssid
, auth_transaction
+ 1, status
,
982 resp_ies
, resp_ies_len
);
987 u16
wpa_ft_validate_reassoc(struct wpa_state_machine
*sm
, const u8
*ies
,
990 struct wpa_ft_ies parse
;
991 struct rsn_mdie
*mdie
;
992 struct rsn_ftie
*ftie
;
997 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
999 wpa_hexdump(MSG_DEBUG
, "FT: Reassoc Req IEs", ies
, ies_len
);
1001 if (wpa_ft_parse_ies(ies
, ies_len
, &parse
) < 0) {
1002 wpa_printf(MSG_DEBUG
, "FT: Failed to parse FT IEs");
1003 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1006 if (parse
.rsn
== NULL
) {
1007 wpa_printf(MSG_DEBUG
, "FT: No RSNIE in Reassoc Req");
1008 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1011 if (parse
.rsn_pmkid
== NULL
) {
1012 wpa_printf(MSG_DEBUG
, "FT: No PMKID in RSNIE");
1013 return WLAN_STATUS_INVALID_PMKID
;
1016 if (os_memcmp(parse
.rsn_pmkid
, sm
->pmk_r1_name
, WPA_PMK_NAME_LEN
) != 0)
1018 wpa_printf(MSG_DEBUG
, "FT: PMKID in Reassoc Req did not match "
1019 "with the PMKR1Name derived from auth request");
1020 return WLAN_STATUS_INVALID_PMKID
;
1023 mdie
= (struct rsn_mdie
*) parse
.mdie
;
1024 if (mdie
== NULL
|| parse
.mdie_len
< sizeof(*mdie
) ||
1025 os_memcmp(mdie
->mobility_domain
,
1026 sm
->wpa_auth
->conf
.mobility_domain
,
1027 MOBILITY_DOMAIN_ID_LEN
) != 0) {
1028 wpa_printf(MSG_DEBUG
, "FT: Invalid MDIE");
1029 return WLAN_STATUS_INVALID_MDIE
;
1032 ftie
= (struct rsn_ftie
*) parse
.ftie
;
1033 if (ftie
== NULL
|| parse
.ftie_len
< sizeof(*ftie
)) {
1034 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE");
1035 return WLAN_STATUS_INVALID_FTIE
;
1038 if (os_memcmp(ftie
->snonce
, sm
->SNonce
, WPA_NONCE_LEN
) != 0) {
1039 wpa_printf(MSG_DEBUG
, "FT: SNonce mismatch in FTIE");
1040 wpa_hexdump(MSG_DEBUG
, "FT: Received SNonce",
1041 ftie
->snonce
, WPA_NONCE_LEN
);
1042 wpa_hexdump(MSG_DEBUG
, "FT: Expected SNonce",
1043 sm
->SNonce
, WPA_NONCE_LEN
);
1047 if (os_memcmp(ftie
->anonce
, sm
->ANonce
, WPA_NONCE_LEN
) != 0) {
1048 wpa_printf(MSG_DEBUG
, "FT: ANonce mismatch in FTIE");
1049 wpa_hexdump(MSG_DEBUG
, "FT: Received ANonce",
1050 ftie
->anonce
, WPA_NONCE_LEN
);
1051 wpa_hexdump(MSG_DEBUG
, "FT: Expected ANonce",
1052 sm
->ANonce
, WPA_NONCE_LEN
);
1057 if (parse
.r0kh_id
== NULL
) {
1058 wpa_printf(MSG_DEBUG
, "FT: No R0KH-ID subelem in FTIE");
1062 if (parse
.r0kh_id_len
!= sm
->r0kh_id_len
||
1063 os_memcmp(parse
.r0kh_id
, sm
->r0kh_id
, parse
.r0kh_id_len
) != 0) {
1064 wpa_printf(MSG_DEBUG
, "FT: R0KH-ID in FTIE did not match with "
1065 "the current R0KH-ID");
1066 wpa_hexdump(MSG_DEBUG
, "FT: R0KH-ID in FTIE",
1067 parse
.r0kh_id
, parse
.r0kh_id_len
);
1068 wpa_hexdump(MSG_DEBUG
, "FT: The current R0KH-ID",
1069 sm
->r0kh_id
, sm
->r0kh_id_len
);
1073 if (parse
.r1kh_id
== NULL
) {
1074 wpa_printf(MSG_DEBUG
, "FT: No R1KH-ID subelem in FTIE");
1078 if (os_memcmp(parse
.r1kh_id
, sm
->wpa_auth
->conf
.r1_key_holder
,
1079 FT_R1KH_ID_LEN
) != 0) {
1080 wpa_printf(MSG_DEBUG
, "FT: Unknown R1KH-ID used in "
1082 wpa_hexdump(MSG_DEBUG
, "FT: R1KH-ID in FTIE",
1083 parse
.r1kh_id
, FT_R1KH_ID_LEN
);
1084 wpa_hexdump(MSG_DEBUG
, "FT: Expected R1KH-ID",
1085 sm
->wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
);
1089 if (parse
.rsn_pmkid
== NULL
||
1090 os_memcmp(parse
.rsn_pmkid
, sm
->pmk_r1_name
, WPA_PMK_NAME_LEN
)) {
1091 wpa_printf(MSG_DEBUG
, "FT: No matching PMKR1Name (PMKID) in "
1092 "RSNIE (pmkid=%d)", !!parse
.rsn_pmkid
);
1098 count
+= ieee802_11_ie_count(parse
.ric
, parse
.ric_len
);
1099 if (ftie
->mic_control
[1] != count
) {
1100 wpa_printf(MSG_DEBUG
, "FT: Unexpected IE count in MIC "
1101 "Control: received %u expected %u",
1102 ftie
->mic_control
[1], count
);
1106 if (wpa_ft_mic(sm
->PTK
.kck
, sm
->addr
, sm
->wpa_auth
->addr
, 5,
1107 parse
.mdie
- 2, parse
.mdie_len
+ 2,
1108 parse
.ftie
- 2, parse
.ftie_len
+ 2,
1109 parse
.rsn
- 2, parse
.rsn_len
+ 2,
1110 parse
.ric
, parse
.ric_len
,
1112 wpa_printf(MSG_DEBUG
, "FT: Failed to calculate MIC");
1113 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1116 if (os_memcmp(mic
, ftie
->mic
, 16) != 0) {
1117 wpa_printf(MSG_DEBUG
, "FT: Invalid MIC in FTIE");
1118 wpa_printf(MSG_DEBUG
, "FT: addr=" MACSTR
" auth_addr=" MACSTR
,
1119 MAC2STR(sm
->addr
), MAC2STR(sm
->wpa_auth
->addr
));
1120 wpa_hexdump(MSG_MSGDUMP
, "FT: Received MIC", ftie
->mic
, 16);
1121 wpa_hexdump(MSG_MSGDUMP
, "FT: Calculated MIC", mic
, 16);
1122 wpa_hexdump(MSG_MSGDUMP
, "FT: MDIE",
1123 parse
.mdie
- 2, parse
.mdie_len
+ 2);
1124 wpa_hexdump(MSG_MSGDUMP
, "FT: FTIE",
1125 parse
.ftie
- 2, parse
.ftie_len
+ 2);
1126 wpa_hexdump(MSG_MSGDUMP
, "FT: RSN",
1127 parse
.rsn
- 2, parse
.rsn_len
+ 2);
1128 return WLAN_STATUS_INVALID_FTIE
;
1131 return WLAN_STATUS_SUCCESS
;
1135 int wpa_ft_action_rx(struct wpa_state_machine
*sm
, const u8
*data
, size_t len
)
1137 const u8
*sta_addr
, *target_ap
;
1141 struct ft_rrb_frame
*frame
;
1147 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1148 * FT Request action frame body[variable]
1152 wpa_printf(MSG_DEBUG
, "FT: Too short FT Action frame "
1153 "(len=%lu)", (unsigned long) len
);
1158 sta_addr
= data
+ 2;
1159 target_ap
= data
+ 8;
1163 wpa_printf(MSG_DEBUG
, "FT: Received FT Action frame (STA=" MACSTR
1164 " Target AP=" MACSTR
" Action=%d)",
1165 MAC2STR(sta_addr
), MAC2STR(target_ap
), action
);
1167 if (os_memcmp(sta_addr
, sm
->addr
, ETH_ALEN
) != 0) {
1168 wpa_printf(MSG_DEBUG
, "FT: Mismatch in FT Action STA address: "
1169 "STA=" MACSTR
" STA-Address=" MACSTR
,
1170 MAC2STR(sm
->addr
), MAC2STR(sta_addr
));
1175 * Do some sanity checking on the target AP address (not own and not
1176 * broadcast. This could be extended to filter based on a list of known
1177 * APs in the MD (if such a list were configured).
1179 if ((target_ap
[0] & 0x01) ||
1180 os_memcmp(target_ap
, sm
->wpa_auth
->addr
, ETH_ALEN
) == 0) {
1181 wpa_printf(MSG_DEBUG
, "FT: Invalid Target AP in FT Action "
1186 wpa_hexdump(MSG_MSGDUMP
, "FT: Action frame body", ies
, ies_len
);
1188 /* RRB - Forward action frame to the target AP */
1189 frame
= os_malloc(sizeof(*frame
) + len
);
1192 frame
->frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1193 frame
->packet_type
= FT_PACKET_REQUEST
;
1194 frame
->action_length
= host_to_le16(len
);
1195 os_memcpy(frame
->ap_address
, sm
->wpa_auth
->addr
, ETH_ALEN
);
1196 os_memcpy(frame
+ 1, data
, len
);
1198 wpa_ft_rrb_send(sm
->wpa_auth
, target_ap
, (u8
*) frame
,
1199 sizeof(*frame
) + len
);
1206 static void wpa_ft_rrb_rx_request_cb(void *ctx
, const u8
*dst
, const u8
*bssid
,
1207 u16 auth_transaction
, u16 resp
,
1208 const u8
*ies
, size_t ies_len
)
1210 struct wpa_state_machine
*sm
= ctx
;
1211 wpa_printf(MSG_DEBUG
, "FT: Over-the-DS RX request cb for " MACSTR
,
1213 wpa_ft_send_rrb_auth_resp(sm
, sm
->ft_pending_current_ap
, sm
->addr
,
1214 WLAN_STATUS_SUCCESS
, ies
, ies_len
);
1218 static int wpa_ft_rrb_rx_request(struct wpa_authenticator
*wpa_auth
,
1219 const u8
*current_ap
, const u8
*sta_addr
,
1220 const u8
*body
, size_t len
)
1222 struct wpa_state_machine
*sm
;
1225 size_t resp_ies_len
;
1228 sm
= wpa_ft_add_sta(wpa_auth
, sta_addr
);
1230 wpa_printf(MSG_DEBUG
, "FT: Failed to add new STA based on "
1235 wpa_hexdump(MSG_MSGDUMP
, "FT: RRB Request Frame body", body
, len
);
1237 sm
->ft_pending_cb
= wpa_ft_rrb_rx_request_cb
;
1238 sm
->ft_pending_cb_ctx
= sm
;
1239 os_memcpy(sm
->ft_pending_current_ap
, current_ap
, ETH_ALEN
);
1240 res
= wpa_ft_process_auth_req(sm
, body
, len
, &resp_ies
,
1243 wpa_printf(MSG_DEBUG
, "FT: No immediate response available - wait for pull response");
1248 res
= wpa_ft_send_rrb_auth_resp(sm
, current_ap
, sta_addr
, status
,
1249 resp_ies
, resp_ies_len
);
1255 static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine
*sm
,
1256 const u8
*current_ap
, const u8
*sta_addr
,
1257 u16 status
, const u8
*resp_ies
,
1258 size_t resp_ies_len
)
1260 struct wpa_authenticator
*wpa_auth
= sm
->wpa_auth
;
1262 struct ft_rrb_frame
*frame
;
1265 wpa_printf(MSG_DEBUG
, "FT: RRB authentication response: STA=" MACSTR
1266 " CurrentAP=" MACSTR
" status=%d",
1267 MAC2STR(sm
->addr
), MAC2STR(current_ap
), status
);
1268 wpa_hexdump(MSG_DEBUG
, "FT: Response IEs", resp_ies
, resp_ies_len
);
1270 /* RRB - Forward action frame response to the Current AP */
1273 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1274 * Status_Code[2] FT Request action frame body[variable]
1276 rlen
= 2 + 2 * ETH_ALEN
+ 2 + resp_ies_len
;
1278 frame
= os_malloc(sizeof(*frame
) + rlen
);
1281 frame
->frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1282 frame
->packet_type
= FT_PACKET_RESPONSE
;
1283 frame
->action_length
= host_to_le16(rlen
);
1284 os_memcpy(frame
->ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1285 pos
= (u8
*) (frame
+ 1);
1286 *pos
++ = WLAN_ACTION_FT
;
1287 *pos
++ = 2; /* Action: Response */
1288 os_memcpy(pos
, sta_addr
, ETH_ALEN
);
1290 os_memcpy(pos
, wpa_auth
->addr
, ETH_ALEN
);
1292 WPA_PUT_LE16(pos
, status
);
1295 os_memcpy(pos
, resp_ies
, resp_ies_len
);
1297 wpa_ft_rrb_send(wpa_auth
, current_ap
, (u8
*) frame
,
1298 sizeof(*frame
) + rlen
);
1305 static int wpa_ft_rrb_rx_pull(struct wpa_authenticator
*wpa_auth
,
1307 const u8
*data
, size_t data_len
)
1309 struct ft_r0kh_r1kh_pull_frame
*frame
, f
;
1310 struct ft_remote_r1kh
*r1kh
;
1311 struct ft_r0kh_r1kh_resp_frame resp
, r
;
1315 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 pull");
1317 if (data_len
< sizeof(*frame
))
1320 r1kh
= wpa_auth
->conf
.r1kh_list
;
1322 if (os_memcmp(r1kh
->addr
, src_addr
, ETH_ALEN
) == 0)
1327 wpa_printf(MSG_DEBUG
, "FT: No matching R1KH address found for "
1328 "PMK-R1 pull source address " MACSTR
,
1333 frame
= (struct ft_r0kh_r1kh_pull_frame
*) data
;
1334 /* aes_unwrap() does not support inplace decryption, so use a temporary
1335 * buffer for the data. */
1336 if (aes_unwrap(r1kh
->key
, (FT_R0KH_R1KH_PULL_DATA_LEN
+ 7) / 8,
1337 frame
->nonce
, f
.nonce
) < 0) {
1338 wpa_printf(MSG_DEBUG
, "FT: Failed to decrypt PMK-R1 pull "
1339 "request from " MACSTR
, MAC2STR(src_addr
));
1343 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - nonce",
1344 f
.nonce
, sizeof(f
.nonce
));
1345 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - PMKR0Name",
1346 f
.pmk_r0_name
, WPA_PMK_NAME_LEN
);
1347 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
" S1KH-ID="
1348 MACSTR
, MAC2STR(f
.r1kh_id
), MAC2STR(f
.s1kh_id
));
1350 os_memset(&resp
, 0, sizeof(resp
));
1351 resp
.frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1352 resp
.packet_type
= FT_PACKET_R0KH_R1KH_RESP
;
1353 resp
.data_length
= host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN
);
1354 os_memcpy(resp
.ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1356 /* aes_wrap() does not support inplace encryption, so use a temporary
1357 * buffer for the data. */
1358 os_memcpy(r
.nonce
, f
.nonce
, sizeof(f
.nonce
));
1359 os_memcpy(r
.r1kh_id
, f
.r1kh_id
, FT_R1KH_ID_LEN
);
1360 os_memcpy(r
.s1kh_id
, f
.s1kh_id
, ETH_ALEN
);
1361 if (wpa_ft_fetch_pmk_r0(wpa_auth
, f
.s1kh_id
, f
.pmk_r0_name
, pmk_r0
,
1363 wpa_printf(MSG_DEBUG
, "FT: No matching PMKR0Name found for "
1368 wpa_derive_pmk_r1(pmk_r0
, f
.pmk_r0_name
, f
.r1kh_id
, f
.s1kh_id
,
1369 r
.pmk_r1
, r
.pmk_r1_name
);
1370 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", r
.pmk_r1
, PMK_LEN
);
1371 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", r
.pmk_r1_name
,
1373 r
.pairwise
= host_to_le16(pairwise
);
1374 os_memset(r
.pad
, 0, sizeof(r
.pad
));
1376 if (aes_wrap(r1kh
->key
, (FT_R0KH_R1KH_RESP_DATA_LEN
+ 7) / 8,
1377 r
.nonce
, resp
.nonce
) < 0) {
1378 os_memset(pmk_r0
, 0, PMK_LEN
);
1382 os_memset(pmk_r0
, 0, PMK_LEN
);
1384 wpa_ft_rrb_send(wpa_auth
, src_addr
, (u8
*) &resp
, sizeof(resp
));
1390 static void ft_pull_resp_cb_finish(void *eloop_ctx
, void *timeout_ctx
)
1392 struct wpa_state_machine
*sm
= eloop_ctx
;
1395 size_t resp_ies_len
;
1398 res
= wpa_ft_process_auth_req(sm
, wpabuf_head(sm
->ft_pending_req_ies
),
1399 wpabuf_len(sm
->ft_pending_req_ies
),
1400 &resp_ies
, &resp_ies_len
);
1401 wpabuf_free(sm
->ft_pending_req_ies
);
1402 sm
->ft_pending_req_ies
= NULL
;
1404 res
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
1406 wpa_printf(MSG_DEBUG
, "FT: Postponed auth callback result for " MACSTR
1407 " - status %u", MAC2STR(sm
->addr
), status
);
1409 sm
->ft_pending_cb(sm
->ft_pending_cb_ctx
, sm
->addr
, sm
->wpa_auth
->addr
,
1410 sm
->ft_pending_auth_transaction
+ 1, status
,
1411 resp_ies
, resp_ies_len
);
1416 static int ft_pull_resp_cb(struct wpa_state_machine
*sm
, void *ctx
)
1418 struct ft_r0kh_r1kh_resp_frame
*frame
= ctx
;
1420 if (os_memcmp(frame
->s1kh_id
, sm
->addr
, ETH_ALEN
) != 0)
1422 if (os_memcmp(frame
->nonce
, sm
->ft_pending_pull_nonce
,
1423 FT_R0KH_R1KH_PULL_NONCE_LEN
) != 0)
1425 if (sm
->ft_pending_cb
== NULL
|| sm
->ft_pending_req_ies
== NULL
)
1428 wpa_printf(MSG_DEBUG
, "FT: Response to a pending pull request for "
1429 MACSTR
" - process from timeout", MAC2STR(sm
->addr
));
1430 eloop_register_timeout(0, 0, ft_pull_resp_cb_finish
, sm
, NULL
);
1435 static int wpa_ft_rrb_rx_resp(struct wpa_authenticator
*wpa_auth
,
1437 const u8
*data
, size_t data_len
)
1439 struct ft_r0kh_r1kh_resp_frame
*frame
, f
;
1440 struct ft_remote_r0kh
*r0kh
;
1443 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 pull response");
1445 if (data_len
< sizeof(*frame
))
1448 r0kh
= wpa_auth
->conf
.r0kh_list
;
1450 if (os_memcmp(r0kh
->addr
, src_addr
, ETH_ALEN
) == 0)
1455 wpa_printf(MSG_DEBUG
, "FT: No matching R0KH address found for "
1456 "PMK-R0 pull response source address " MACSTR
,
1461 frame
= (struct ft_r0kh_r1kh_resp_frame
*) data
;
1462 /* aes_unwrap() does not support inplace decryption, so use a temporary
1463 * buffer for the data. */
1464 if (aes_unwrap(r0kh
->key
, (FT_R0KH_R1KH_RESP_DATA_LEN
+ 7) / 8,
1465 frame
->nonce
, f
.nonce
) < 0) {
1466 wpa_printf(MSG_DEBUG
, "FT: Failed to decrypt PMK-R1 pull "
1467 "response from " MACSTR
, MAC2STR(src_addr
));
1471 if (os_memcmp(f
.r1kh_id
, wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
)
1473 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 pull response did not use a "
1474 "matching R1KH-ID");
1478 pairwise
= le_to_host16(f
.pairwise
);
1479 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - nonce",
1480 f
.nonce
, sizeof(f
.nonce
));
1481 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
" S1KH-ID="
1482 MACSTR
" pairwise=0x%x",
1483 MAC2STR(f
.r1kh_id
), MAC2STR(f
.s1kh_id
), pairwise
);
1484 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1 pull - PMK-R1",
1486 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - PMKR1Name",
1487 f
.pmk_r1_name
, WPA_PMK_NAME_LEN
);
1489 res
= wpa_ft_store_pmk_r1(wpa_auth
, f
.s1kh_id
, f
.pmk_r1
, f
.pmk_r1_name
,
1491 wpa_printf(MSG_DEBUG
, "FT: Look for pending pull request");
1492 wpa_auth_for_each_sta(wpa_auth
, ft_pull_resp_cb
, &f
);
1493 os_memset(f
.pmk_r1
, 0, PMK_LEN
);
1495 return res
? 0 : -1;
1499 static int wpa_ft_rrb_rx_push(struct wpa_authenticator
*wpa_auth
,
1501 const u8
*data
, size_t data_len
)
1503 struct ft_r0kh_r1kh_push_frame
*frame
, f
;
1504 struct ft_remote_r0kh
*r0kh
;
1509 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 push");
1511 if (data_len
< sizeof(*frame
))
1514 r0kh
= wpa_auth
->conf
.r0kh_list
;
1516 if (os_memcmp(r0kh
->addr
, src_addr
, ETH_ALEN
) == 0)
1521 wpa_printf(MSG_DEBUG
, "FT: No matching R0KH address found for "
1522 "PMK-R0 push source address " MACSTR
,
1527 frame
= (struct ft_r0kh_r1kh_push_frame
*) data
;
1528 /* aes_unwrap() does not support inplace decryption, so use a temporary
1529 * buffer for the data. */
1530 if (aes_unwrap(r0kh
->key
, (FT_R0KH_R1KH_PUSH_DATA_LEN
+ 7) / 8,
1531 frame
->timestamp
, f
.timestamp
) < 0) {
1532 wpa_printf(MSG_DEBUG
, "FT: Failed to decrypt PMK-R1 push from "
1533 MACSTR
, MAC2STR(src_addr
));
1538 tsend
= WPA_GET_LE32(f
.timestamp
);
1539 if ((now
.sec
> tsend
&& now
.sec
- tsend
> 60) ||
1540 (now
.sec
< tsend
&& tsend
- now
.sec
> 60)) {
1541 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 push did not have a valid "
1542 "timestamp: sender time %d own time %d\n",
1543 (int) tsend
, (int) now
.sec
);
1547 if (os_memcmp(f
.r1kh_id
, wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
)
1549 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 push did not use a matching "
1550 "R1KH-ID (received " MACSTR
" own " MACSTR
")",
1552 MAC2STR(wpa_auth
->conf
.r1_key_holder
));
1556 pairwise
= le_to_host16(f
.pairwise
);
1557 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 push - R1KH-ID=" MACSTR
" S1KH-ID="
1558 MACSTR
" pairwise=0x%x",
1559 MAC2STR(f
.r1kh_id
), MAC2STR(f
.s1kh_id
), pairwise
);
1560 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1 push - PMK-R1",
1562 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 push - PMKR1Name",
1563 f
.pmk_r1_name
, WPA_PMK_NAME_LEN
);
1565 wpa_ft_store_pmk_r1(wpa_auth
, f
.s1kh_id
, f
.pmk_r1
, f
.pmk_r1_name
,
1567 os_memset(f
.pmk_r1
, 0, PMK_LEN
);
1573 int wpa_ft_rrb_rx(struct wpa_authenticator
*wpa_auth
, const u8
*src_addr
,
1574 const u8
*data
, size_t data_len
)
1576 struct ft_rrb_frame
*frame
;
1578 const u8
*pos
, *end
, *start
;
1580 const u8
*sta_addr
, *target_ap_addr
;
1582 wpa_printf(MSG_DEBUG
, "FT: RRB received frame from remote AP " MACSTR
,
1585 if (data_len
< sizeof(*frame
)) {
1586 wpa_printf(MSG_DEBUG
, "FT: Too short RRB frame (data_len=%lu)",
1587 (unsigned long) data_len
);
1592 frame
= (struct ft_rrb_frame
*) pos
;
1593 pos
+= sizeof(*frame
);
1595 alen
= le_to_host16(frame
->action_length
);
1596 wpa_printf(MSG_DEBUG
, "FT: RRB frame - frame_type=%d packet_type=%d "
1597 "action_length=%d ap_address=" MACSTR
,
1598 frame
->frame_type
, frame
->packet_type
, alen
,
1599 MAC2STR(frame
->ap_address
));
1601 if (frame
->frame_type
!= RSN_REMOTE_FRAME_TYPE_FT_RRB
) {
1602 /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */
1603 wpa_printf(MSG_DEBUG
, "FT: RRB discarded frame with "
1604 "unrecognized type %d", frame
->frame_type
);
1608 if (alen
> data_len
- sizeof(*frame
)) {
1609 wpa_printf(MSG_DEBUG
, "FT: RRB frame too short for action "
1614 if (frame
->packet_type
== FT_PACKET_R0KH_R1KH_PULL
)
1615 return wpa_ft_rrb_rx_pull(wpa_auth
, src_addr
, data
, data_len
);
1616 if (frame
->packet_type
== FT_PACKET_R0KH_R1KH_RESP
)
1617 return wpa_ft_rrb_rx_resp(wpa_auth
, src_addr
, data
, data_len
);
1618 if (frame
->packet_type
== FT_PACKET_R0KH_R1KH_PUSH
)
1619 return wpa_ft_rrb_rx_push(wpa_auth
, src_addr
, data
, data_len
);
1621 wpa_hexdump(MSG_MSGDUMP
, "FT: RRB - FT Action frame", pos
, alen
);
1623 if (alen
< 1 + 1 + 2 * ETH_ALEN
) {
1624 wpa_printf(MSG_DEBUG
, "FT: Too short RRB frame (not enough "
1625 "room for Action Frame body); alen=%lu",
1626 (unsigned long) alen
);
1632 if (*pos
!= WLAN_ACTION_FT
) {
1633 wpa_printf(MSG_DEBUG
, "FT: Unexpected Action frame category "
1642 target_ap_addr
= pos
;
1644 wpa_printf(MSG_DEBUG
, "FT: RRB Action Frame: action=%d sta_addr="
1645 MACSTR
" target_ap_addr=" MACSTR
,
1646 action
, MAC2STR(sta_addr
), MAC2STR(target_ap_addr
));
1648 if (frame
->packet_type
== FT_PACKET_REQUEST
) {
1649 wpa_printf(MSG_DEBUG
, "FT: FT Packet Type - Request");
1652 wpa_printf(MSG_DEBUG
, "FT: Unexpected Action %d in "
1653 "RRB Request", action
);
1657 if (os_memcmp(target_ap_addr
, wpa_auth
->addr
, ETH_ALEN
) != 0) {
1658 wpa_printf(MSG_DEBUG
, "FT: Target AP address in the "
1659 "RRB Request does not match with own "
1664 if (wpa_ft_rrb_rx_request(wpa_auth
, frame
->ap_address
,
1665 sta_addr
, pos
, end
- pos
) < 0)
1667 } else if (frame
->packet_type
== FT_PACKET_RESPONSE
) {
1670 if (end
- pos
< 2) {
1671 wpa_printf(MSG_DEBUG
, "FT: Not enough room for status "
1672 "code in RRB Response");
1675 status_code
= WPA_GET_LE16(pos
);
1678 wpa_printf(MSG_DEBUG
, "FT: FT Packet Type - Response "
1679 "(status_code=%d)", status_code
);
1681 if (wpa_ft_action_send(wpa_auth
, sta_addr
, start
, alen
) < 0)
1684 wpa_printf(MSG_DEBUG
, "FT: RRB discarded frame with unknown "
1685 "packet_type %d", frame
->packet_type
);
1693 static void wpa_ft_generate_pmk_r1(struct wpa_authenticator
*wpa_auth
,
1694 struct wpa_ft_pmk_r0_sa
*pmk_r0
,
1695 struct ft_remote_r1kh
*r1kh
,
1696 const u8
*s1kh_id
, int pairwise
)
1698 struct ft_r0kh_r1kh_push_frame frame
, f
;
1701 os_memset(&frame
, 0, sizeof(frame
));
1702 frame
.frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1703 frame
.packet_type
= FT_PACKET_R0KH_R1KH_PUSH
;
1704 frame
.data_length
= host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN
);
1705 os_memcpy(frame
.ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1707 /* aes_wrap() does not support inplace encryption, so use a temporary
1708 * buffer for the data. */
1709 os_memcpy(f
.r1kh_id
, r1kh
->id
, FT_R1KH_ID_LEN
);
1710 os_memcpy(f
.s1kh_id
, s1kh_id
, ETH_ALEN
);
1711 os_memcpy(f
.pmk_r0_name
, pmk_r0
->pmk_r0_name
, WPA_PMK_NAME_LEN
);
1712 wpa_derive_pmk_r1(pmk_r0
->pmk_r0
, pmk_r0
->pmk_r0_name
, r1kh
->id
,
1713 s1kh_id
, f
.pmk_r1
, f
.pmk_r1_name
);
1714 wpa_printf(MSG_DEBUG
, "FT: R1KH-ID " MACSTR
, MAC2STR(r1kh
->id
));
1715 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", f
.pmk_r1
, PMK_LEN
);
1716 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", f
.pmk_r1_name
,
1719 WPA_PUT_LE32(f
.timestamp
, now
.sec
);
1720 f
.pairwise
= host_to_le16(pairwise
);
1721 os_memset(f
.pad
, 0, sizeof(f
.pad
));
1722 if (aes_wrap(r1kh
->key
, (FT_R0KH_R1KH_PUSH_DATA_LEN
+ 7) / 8,
1723 f
.timestamp
, frame
.timestamp
) < 0)
1726 wpa_ft_rrb_send(wpa_auth
, r1kh
->addr
, (u8
*) &frame
, sizeof(frame
));
1730 void wpa_ft_push_pmk_r1(struct wpa_authenticator
*wpa_auth
, const u8
*addr
)
1732 struct wpa_ft_pmk_r0_sa
*r0
;
1733 struct ft_remote_r1kh
*r1kh
;
1735 if (!wpa_auth
->conf
.pmk_r1_push
)
1738 r0
= wpa_auth
->ft_pmk_cache
->pmk_r0
;
1740 if (os_memcmp(r0
->spa
, addr
, ETH_ALEN
) == 0)
1745 if (r0
== NULL
|| r0
->pmk_r1_pushed
)
1747 r0
->pmk_r1_pushed
= 1;
1749 wpa_printf(MSG_DEBUG
, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
1750 "for STA " MACSTR
, MAC2STR(addr
));
1752 r1kh
= wpa_auth
->conf
.r1kh_list
;
1754 wpa_ft_generate_pmk_r1(wpa_auth
, r0
, r1kh
, addr
, r0
->pairwise
);
1759 #endif /* CONFIG_IEEE80211R */