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_wrap.h"
17 #include "crypto/random.h"
18 #include "ap_config.h"
19 #include "ieee802_11.h"
22 #include "wpa_auth_i.h"
25 #ifdef CONFIG_IEEE80211R_AP
27 static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine
*sm
,
28 const u8
*current_ap
, const u8
*sta_addr
,
29 u16 status
, const u8
*resp_ies
,
33 static int wpa_ft_rrb_send(struct wpa_authenticator
*wpa_auth
, const u8
*dst
,
34 const u8
*data
, size_t data_len
)
36 if (wpa_auth
->cb
->send_ether
== NULL
)
38 wpa_printf(MSG_DEBUG
, "FT: RRB send to " MACSTR
, MAC2STR(dst
));
39 return wpa_auth
->cb
->send_ether(wpa_auth
->cb_ctx
, dst
, ETH_P_RRB
,
44 static int wpa_ft_action_send(struct wpa_authenticator
*wpa_auth
,
45 const u8
*dst
, const u8
*data
, size_t data_len
)
47 if (wpa_auth
->cb
->send_ft_action
== NULL
)
49 return wpa_auth
->cb
->send_ft_action(wpa_auth
->cb_ctx
, dst
,
54 static const u8
* wpa_ft_get_psk(struct wpa_authenticator
*wpa_auth
,
55 const u8
*addr
, const u8
*p2p_dev_addr
,
58 if (wpa_auth
->cb
->get_psk
== NULL
)
60 return wpa_auth
->cb
->get_psk(wpa_auth
->cb_ctx
, addr
, p2p_dev_addr
,
65 static struct wpa_state_machine
*
66 wpa_ft_add_sta(struct wpa_authenticator
*wpa_auth
, const u8
*sta_addr
)
68 if (wpa_auth
->cb
->add_sta
== NULL
)
70 return wpa_auth
->cb
->add_sta(wpa_auth
->cb_ctx
, sta_addr
);
74 static int wpa_ft_add_tspec(struct wpa_authenticator
*wpa_auth
,
76 u8
*tspec_ie
, size_t tspec_ielen
)
78 if (wpa_auth
->cb
->add_tspec
== NULL
) {
79 wpa_printf(MSG_DEBUG
, "FT: add_tspec is not initialized");
82 return wpa_auth
->cb
->add_tspec(wpa_auth
->cb_ctx
, sta_addr
, tspec_ie
,
87 int wpa_write_mdie(struct wpa_auth_config
*conf
, u8
*buf
, size_t len
)
91 if (len
< 2 + sizeof(struct rsn_mdie
))
94 *pos
++ = WLAN_EID_MOBILITY_DOMAIN
;
95 *pos
++ = MOBILITY_DOMAIN_ID_LEN
+ 1;
96 os_memcpy(pos
, conf
->mobility_domain
, MOBILITY_DOMAIN_ID_LEN
);
97 pos
+= MOBILITY_DOMAIN_ID_LEN
;
100 capab
|= RSN_FT_CAPAB_FT_OVER_DS
;
107 int wpa_write_ftie(struct wpa_auth_config
*conf
, const u8
*r0kh_id
,
109 const u8
*anonce
, const u8
*snonce
,
110 u8
*buf
, size_t len
, const u8
*subelem
,
113 u8
*pos
= buf
, *ielen
;
114 struct rsn_ftie
*hdr
;
116 if (len
< 2 + sizeof(*hdr
) + 2 + FT_R1KH_ID_LEN
+ 2 + r0kh_id_len
+
120 *pos
++ = WLAN_EID_FAST_BSS_TRANSITION
;
123 hdr
= (struct rsn_ftie
*) pos
;
124 os_memset(hdr
, 0, sizeof(*hdr
));
126 WPA_PUT_LE16(hdr
->mic_control
, 0);
128 os_memcpy(hdr
->anonce
, anonce
, WPA_NONCE_LEN
);
130 os_memcpy(hdr
->snonce
, snonce
, WPA_NONCE_LEN
);
132 /* Optional Parameters */
133 *pos
++ = FTIE_SUBELEM_R1KH_ID
;
134 *pos
++ = FT_R1KH_ID_LEN
;
135 os_memcpy(pos
, conf
->r1_key_holder
, FT_R1KH_ID_LEN
);
136 pos
+= FT_R1KH_ID_LEN
;
139 *pos
++ = FTIE_SUBELEM_R0KH_ID
;
140 *pos
++ = r0kh_id_len
;
141 os_memcpy(pos
, r0kh_id
, r0kh_id_len
);
146 os_memcpy(pos
, subelem
, subelem_len
);
150 *ielen
= pos
- buf
- 2;
156 struct wpa_ft_pmk_r0_sa
{
157 struct wpa_ft_pmk_r0_sa
*next
;
159 u8 pmk_r0_name
[WPA_PMK_NAME_LEN
];
161 int pairwise
; /* Pairwise cipher suite, WPA_CIPHER_* */
162 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
166 struct wpa_ft_pmk_r1_sa
{
167 struct wpa_ft_pmk_r1_sa
*next
;
169 u8 pmk_r1_name
[WPA_PMK_NAME_LEN
];
171 int pairwise
; /* Pairwise cipher suite, WPA_CIPHER_* */
172 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
175 struct wpa_ft_pmk_cache
{
176 struct wpa_ft_pmk_r0_sa
*pmk_r0
;
177 struct wpa_ft_pmk_r1_sa
*pmk_r1
;
180 struct wpa_ft_pmk_cache
* wpa_ft_pmk_cache_init(void)
182 struct wpa_ft_pmk_cache
*cache
;
184 cache
= os_zalloc(sizeof(*cache
));
190 void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache
*cache
)
192 struct wpa_ft_pmk_r0_sa
*r0
, *r0prev
;
193 struct wpa_ft_pmk_r1_sa
*r1
, *r1prev
;
199 os_memset(r0prev
->pmk_r0
, 0, PMK_LEN
);
207 os_memset(r1prev
->pmk_r1
, 0, PMK_LEN
);
215 static int wpa_ft_store_pmk_r0(struct wpa_authenticator
*wpa_auth
,
216 const u8
*spa
, const u8
*pmk_r0
,
217 const u8
*pmk_r0_name
, int pairwise
)
219 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
220 struct wpa_ft_pmk_r0_sa
*r0
;
222 /* TODO: add expiration and limit on number of entries in cache */
224 r0
= os_zalloc(sizeof(*r0
));
228 os_memcpy(r0
->pmk_r0
, pmk_r0
, PMK_LEN
);
229 os_memcpy(r0
->pmk_r0_name
, pmk_r0_name
, WPA_PMK_NAME_LEN
);
230 os_memcpy(r0
->spa
, spa
, ETH_ALEN
);
231 r0
->pairwise
= pairwise
;
233 r0
->next
= cache
->pmk_r0
;
240 static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator
*wpa_auth
,
241 const u8
*spa
, const u8
*pmk_r0_name
,
242 u8
*pmk_r0
, int *pairwise
)
244 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
245 struct wpa_ft_pmk_r0_sa
*r0
;
249 if (os_memcmp(r0
->spa
, spa
, ETH_ALEN
) == 0 &&
250 os_memcmp_const(r0
->pmk_r0_name
, pmk_r0_name
,
251 WPA_PMK_NAME_LEN
) == 0) {
252 os_memcpy(pmk_r0
, r0
->pmk_r0
, PMK_LEN
);
254 *pairwise
= r0
->pairwise
;
265 static int wpa_ft_store_pmk_r1(struct wpa_authenticator
*wpa_auth
,
266 const u8
*spa
, const u8
*pmk_r1
,
267 const u8
*pmk_r1_name
, int pairwise
)
269 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
270 struct wpa_ft_pmk_r1_sa
*r1
;
272 /* TODO: add expiration and limit on number of entries in cache */
274 r1
= os_zalloc(sizeof(*r1
));
278 os_memcpy(r1
->pmk_r1
, pmk_r1
, PMK_LEN
);
279 os_memcpy(r1
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
);
280 os_memcpy(r1
->spa
, spa
, ETH_ALEN
);
281 r1
->pairwise
= pairwise
;
283 r1
->next
= cache
->pmk_r1
;
290 static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator
*wpa_auth
,
291 const u8
*spa
, const u8
*pmk_r1_name
,
292 u8
*pmk_r1
, int *pairwise
)
294 struct wpa_ft_pmk_cache
*cache
= wpa_auth
->ft_pmk_cache
;
295 struct wpa_ft_pmk_r1_sa
*r1
;
299 if (os_memcmp(r1
->spa
, spa
, ETH_ALEN
) == 0 &&
300 os_memcmp_const(r1
->pmk_r1_name
, pmk_r1_name
,
301 WPA_PMK_NAME_LEN
) == 0) {
302 os_memcpy(pmk_r1
, r1
->pmk_r1
, PMK_LEN
);
304 *pairwise
= r1
->pairwise
;
315 static int wpa_ft_pull_pmk_r1(struct wpa_state_machine
*sm
,
316 const u8
*ies
, size_t ies_len
,
317 const u8
*pmk_r0_name
)
319 struct ft_remote_r0kh
*r0kh
;
320 struct ft_r0kh_r1kh_pull_frame frame
, f
;
322 r0kh
= sm
->wpa_auth
->conf
.r0kh_list
;
324 if (r0kh
->id_len
== sm
->r0kh_id_len
&&
325 os_memcmp_const(r0kh
->id
, sm
->r0kh_id
, sm
->r0kh_id_len
) ==
331 wpa_hexdump(MSG_DEBUG
, "FT: Did not find R0KH-ID",
332 sm
->r0kh_id
, sm
->r0kh_id_len
);
336 wpa_printf(MSG_DEBUG
, "FT: Send PMK-R1 pull request to remote R0KH "
337 "address " MACSTR
, MAC2STR(r0kh
->addr
));
339 os_memset(&frame
, 0, sizeof(frame
));
340 frame
.frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
341 frame
.packet_type
= FT_PACKET_R0KH_R1KH_PULL
;
342 frame
.data_length
= host_to_le16(FT_R0KH_R1KH_PULL_DATA_LEN
);
343 os_memcpy(frame
.ap_address
, sm
->wpa_auth
->addr
, ETH_ALEN
);
345 /* aes_wrap() does not support inplace encryption, so use a temporary
346 * buffer for the data. */
347 if (random_get_bytes(f
.nonce
, FT_R0KH_R1KH_PULL_NONCE_LEN
)) {
348 wpa_printf(MSG_DEBUG
, "FT: Failed to get random data for "
352 os_memcpy(sm
->ft_pending_pull_nonce
, f
.nonce
,
353 FT_R0KH_R1KH_PULL_NONCE_LEN
);
354 os_memcpy(f
.pmk_r0_name
, pmk_r0_name
, WPA_PMK_NAME_LEN
);
355 os_memcpy(f
.r1kh_id
, sm
->wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
);
356 os_memcpy(f
.s1kh_id
, sm
->addr
, ETH_ALEN
);
357 os_memset(f
.pad
, 0, sizeof(f
.pad
));
359 if (aes_wrap(r0kh
->key
, sizeof(r0kh
->key
),
360 (FT_R0KH_R1KH_PULL_DATA_LEN
+ 7) / 8,
361 f
.nonce
, frame
.nonce
) < 0)
364 wpabuf_free(sm
->ft_pending_req_ies
);
365 sm
->ft_pending_req_ies
= wpabuf_alloc_copy(ies
, ies_len
);
366 if (sm
->ft_pending_req_ies
== NULL
)
369 wpa_ft_rrb_send(sm
->wpa_auth
, r0kh
->addr
, (u8
*) &frame
, sizeof(frame
));
375 int wpa_auth_derive_ptk_ft(struct wpa_state_machine
*sm
, const u8
*pmk
,
378 u8 pmk_r0
[PMK_LEN
], pmk_r0_name
[WPA_PMK_NAME_LEN
];
380 u8 ptk_name
[WPA_PMK_NAME_LEN
];
381 const u8
*mdid
= sm
->wpa_auth
->conf
.mobility_domain
;
382 const u8
*r0kh
= sm
->wpa_auth
->conf
.r0_key_holder
;
383 size_t r0kh_len
= sm
->wpa_auth
->conf
.r0_key_holder_len
;
384 const u8
*r1kh
= sm
->wpa_auth
->conf
.r1_key_holder
;
385 const u8
*ssid
= sm
->wpa_auth
->conf
.ssid
;
386 size_t ssid_len
= sm
->wpa_auth
->conf
.ssid_len
;
387 int psk_local
= sm
->wpa_auth
->conf
.ft_psk_generate_local
;
389 if (sm
->xxkey_len
== 0) {
390 wpa_printf(MSG_DEBUG
, "FT: XXKey not available for key "
395 if (wpa_derive_pmk_r0(sm
->xxkey
, sm
->xxkey_len
, ssid
, ssid_len
, mdid
,
396 r0kh
, r0kh_len
, sm
->addr
,
397 pmk_r0
, pmk_r0_name
) < 0)
399 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R0", pmk_r0
, PMK_LEN
);
400 wpa_hexdump(MSG_DEBUG
, "FT: PMKR0Name", pmk_r0_name
, WPA_PMK_NAME_LEN
);
401 if (!psk_local
|| !wpa_key_mgmt_ft_psk(sm
->wpa_key_mgmt
))
402 wpa_ft_store_pmk_r0(sm
->wpa_auth
, sm
->addr
, pmk_r0
, pmk_r0_name
,
405 if (wpa_derive_pmk_r1(pmk_r0
, pmk_r0_name
, r1kh
, sm
->addr
,
406 pmk_r1
, sm
->pmk_r1_name
) < 0)
408 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", pmk_r1
, PMK_LEN
);
409 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", sm
->pmk_r1_name
,
411 if (!psk_local
|| !wpa_key_mgmt_ft_psk(sm
->wpa_key_mgmt
))
412 wpa_ft_store_pmk_r1(sm
->wpa_auth
, sm
->addr
, pmk_r1
,
413 sm
->pmk_r1_name
, sm
->pairwise
);
415 return wpa_pmk_r1_to_ptk(pmk_r1
, sm
->SNonce
, sm
->ANonce
, sm
->addr
,
416 sm
->wpa_auth
->addr
, sm
->pmk_r1_name
,
417 ptk
, ptk_name
, sm
->wpa_key_mgmt
, sm
->pairwise
);
421 static inline int wpa_auth_get_seqnum(struct wpa_authenticator
*wpa_auth
,
422 const u8
*addr
, int idx
, u8
*seq
)
424 if (wpa_auth
->cb
->get_seqnum
== NULL
)
426 return wpa_auth
->cb
->get_seqnum(wpa_auth
->cb_ctx
, addr
, idx
, seq
);
430 static u8
* wpa_ft_gtk_subelem(struct wpa_state_machine
*sm
, size_t *len
)
433 struct wpa_group
*gsm
= sm
->group
;
434 size_t subelem_len
, pad_len
;
439 key_len
= gsm
->GTK_len
;
440 if (key_len
> sizeof(keybuf
))
444 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less
447 pad_len
= key_len
% 8;
449 pad_len
= 8 - pad_len
;
450 if (key_len
+ pad_len
< 16)
452 if (pad_len
&& key_len
< sizeof(keybuf
)) {
453 os_memcpy(keybuf
, gsm
->GTK
[gsm
->GN
- 1], key_len
);
454 os_memset(keybuf
+ key_len
, 0, pad_len
);
455 keybuf
[key_len
] = 0xdd;
459 key
= gsm
->GTK
[gsm
->GN
- 1];
462 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
465 subelem_len
= 13 + key_len
+ 8;
466 subelem
= os_zalloc(subelem_len
);
470 subelem
[0] = FTIE_SUBELEM_GTK
;
471 subelem
[1] = 11 + key_len
+ 8;
472 /* Key ID in B0-B1 of Key Info */
473 WPA_PUT_LE16(&subelem
[2], gsm
->GN
& 0x03);
474 subelem
[4] = gsm
->GTK_len
;
475 wpa_auth_get_seqnum(sm
->wpa_auth
, NULL
, gsm
->GN
, subelem
+ 5);
476 if (aes_wrap(sm
->PTK
.kek
, sm
->PTK
.kek_len
, key_len
/ 8, key
,
487 #ifdef CONFIG_IEEE80211W
488 static u8
* wpa_ft_igtk_subelem(struct wpa_state_machine
*sm
, size_t *len
)
491 struct wpa_group
*gsm
= sm
->group
;
494 /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
496 subelem_len
= 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN
+ 8;
497 subelem
= os_zalloc(subelem_len
);
502 *pos
++ = FTIE_SUBELEM_IGTK
;
503 *pos
++ = subelem_len
- 2;
504 WPA_PUT_LE16(pos
, gsm
->GN_igtk
);
506 wpa_auth_get_seqnum(sm
->wpa_auth
, NULL
, gsm
->GN_igtk
, pos
);
508 *pos
++ = WPA_IGTK_LEN
;
509 if (aes_wrap(sm
->PTK
.kek
, sm
->PTK
.kek_len
, WPA_IGTK_LEN
/ 8,
510 gsm
->IGTK
[gsm
->GN_igtk
- 4], pos
)) {
518 #endif /* CONFIG_IEEE80211W */
521 static u8
* wpa_ft_process_rdie(struct wpa_state_machine
*sm
,
522 u8
*pos
, u8
*end
, u8 id
, u8 descr_count
,
523 const u8
*ies
, size_t ies_len
)
525 struct ieee802_11_elems parse
;
526 struct rsn_rdie
*rdie
;
528 wpa_printf(MSG_DEBUG
, "FT: Resource Request: id=%d descr_count=%d",
530 wpa_hexdump(MSG_MSGDUMP
, "FT: Resource descriptor IE(s)",
533 if (end
- pos
< (int) sizeof(*rdie
)) {
534 wpa_printf(MSG_ERROR
, "FT: Not enough room for response RDIE");
538 *pos
++ = WLAN_EID_RIC_DATA
;
539 *pos
++ = sizeof(*rdie
);
540 rdie
= (struct rsn_rdie
*) pos
;
542 rdie
->descr_count
= 0;
543 rdie
->status_code
= host_to_le16(WLAN_STATUS_SUCCESS
);
544 pos
+= sizeof(*rdie
);
546 if (ieee802_11_parse_elems((u8
*) ies
, ies_len
, &parse
, 1) ==
548 wpa_printf(MSG_DEBUG
, "FT: Failed to parse request IEs");
550 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
554 if (parse
.wmm_tspec
) {
555 struct wmm_tspec_element
*tspec
;
557 if (parse
.wmm_tspec_len
+ 2 < (int) sizeof(*tspec
)) {
558 wpa_printf(MSG_DEBUG
, "FT: Too short WMM TSPEC IE "
559 "(%d)", (int) parse
.wmm_tspec_len
);
561 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
564 if (end
- pos
< (int) sizeof(*tspec
)) {
565 wpa_printf(MSG_ERROR
, "FT: Not enough room for "
568 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
571 tspec
= (struct wmm_tspec_element
*) pos
;
572 os_memcpy(tspec
, parse
.wmm_tspec
- 2, sizeof(*tspec
));
576 if (parse
.wmm_tspec
&& sm
->wpa_auth
->conf
.ap_mlme
) {
579 res
= wmm_process_tspec((struct wmm_tspec_element
*) pos
);
580 wpa_printf(MSG_DEBUG
, "FT: ADDTS processing result: %d", res
);
581 if (res
== WMM_ADDTS_STATUS_INVALID_PARAMETERS
)
583 host_to_le16(WLAN_STATUS_INVALID_PARAMETERS
);
584 else if (res
== WMM_ADDTS_STATUS_REFUSED
)
586 host_to_le16(WLAN_STATUS_REQUEST_DECLINED
);
588 /* TSPEC accepted; include updated TSPEC in response */
589 rdie
->descr_count
= 1;
590 pos
+= sizeof(struct wmm_tspec_element
);
594 #endif /* NEED_AP_MLME */
596 if (parse
.wmm_tspec
&& !sm
->wpa_auth
->conf
.ap_mlme
) {
599 res
= wpa_ft_add_tspec(sm
->wpa_auth
, sm
->addr
, pos
,
600 sizeof(struct wmm_tspec_element
));
603 rdie
->status_code
= host_to_le16(res
);
605 /* TSPEC accepted; include updated TSPEC in
607 rdie
->descr_count
= 1;
608 pos
+= sizeof(struct wmm_tspec_element
);
614 wpa_printf(MSG_DEBUG
, "FT: No supported resource requested");
615 rdie
->status_code
= host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE
);
620 static u8
* wpa_ft_process_ric(struct wpa_state_machine
*sm
, u8
*pos
, u8
*end
,
621 const u8
*ric
, size_t ric_len
)
623 const u8
*rpos
, *start
;
624 const struct rsn_rdie
*rdie
;
626 wpa_hexdump(MSG_MSGDUMP
, "FT: RIC Request", ric
, ric_len
);
629 while (rpos
+ sizeof(*rdie
) < ric
+ ric_len
) {
630 if (rpos
[0] != WLAN_EID_RIC_DATA
|| rpos
[1] < sizeof(*rdie
) ||
631 rpos
+ 2 + rpos
[1] > ric
+ ric_len
)
633 rdie
= (const struct rsn_rdie
*) (rpos
+ 2);
637 while (rpos
+ 2 <= ric
+ ric_len
&&
638 rpos
+ 2 + rpos
[1] <= ric
+ ric_len
) {
639 if (rpos
[0] == WLAN_EID_RIC_DATA
)
643 pos
= wpa_ft_process_rdie(sm
, pos
, end
, rdie
->id
,
645 start
, rpos
- start
);
652 u8
* wpa_sm_write_assoc_resp_ies(struct wpa_state_machine
*sm
, u8
*pos
,
653 size_t max_len
, int auth_alg
,
654 const u8
*req_ies
, size_t req_ies_len
)
656 u8
*end
, *mdie
, *ftie
, *rsnie
= NULL
, *r0kh_id
, *subelem
= NULL
;
657 size_t mdie_len
, ftie_len
, rsnie_len
= 0, r0kh_id_len
, subelem_len
= 0;
659 struct wpa_auth_config
*conf
;
660 struct rsn_ftie
*_ftie
;
661 struct wpa_ft_ies parse
;
668 conf
= &sm
->wpa_auth
->conf
;
670 if (!wpa_key_mgmt_ft(sm
->wpa_key_mgmt
))
675 if (auth_alg
== WLAN_AUTH_FT
) {
677 * RSN (only present if this is a Reassociation Response and
678 * part of a fast BSS transition)
680 res
= wpa_write_rsn_ie(conf
, pos
, end
- pos
, sm
->pmk_r1_name
);
688 /* Mobility Domain Information */
689 res
= wpa_write_mdie(conf
, pos
, end
- pos
);
696 /* Fast BSS Transition Information */
697 if (auth_alg
== WLAN_AUTH_FT
) {
698 subelem
= wpa_ft_gtk_subelem(sm
, &subelem_len
);
699 r0kh_id
= sm
->r0kh_id
;
700 r0kh_id_len
= sm
->r0kh_id_len
;
703 #ifdef CONFIG_IEEE80211W
704 if (sm
->mgmt_frame_prot
) {
708 igtk
= wpa_ft_igtk_subelem(sm
, &igtk_len
);
713 nbuf
= os_realloc(subelem
, subelem_len
+ igtk_len
);
720 os_memcpy(subelem
+ subelem_len
, igtk
, igtk_len
);
721 subelem_len
+= igtk_len
;
724 #endif /* CONFIG_IEEE80211W */
726 r0kh_id
= conf
->r0_key_holder
;
727 r0kh_id_len
= conf
->r0_key_holder_len
;
731 res
= wpa_write_ftie(conf
, r0kh_id
, r0kh_id_len
, anonce
, snonce
, pos
,
732 end
- pos
, subelem
, subelem_len
);
740 _ftie
= (struct rsn_ftie
*) (ftie
+ 2);
741 if (auth_alg
== WLAN_AUTH_FT
)
742 _ftie
->mic_control
[1] = 3; /* Information element count */
745 if (wpa_ft_parse_ies(req_ies
, req_ies_len
, &parse
) == 0 && parse
.ric
) {
746 pos
= wpa_ft_process_ric(sm
, pos
, end
, parse
.ric
,
748 if (auth_alg
== WLAN_AUTH_FT
)
749 _ftie
->mic_control
[1] +=
750 ieee802_11_ie_count(ric_start
,
753 if (ric_start
== pos
)
756 if (auth_alg
== WLAN_AUTH_FT
&&
757 wpa_ft_mic(sm
->PTK
.kck
, sm
->PTK
.kck_len
, sm
->addr
,
758 sm
->wpa_auth
->addr
, 6,
759 mdie
, mdie_len
, ftie
, ftie_len
,
761 ric_start
, ric_start
? pos
- ric_start
: 0,
763 wpa_printf(MSG_DEBUG
, "FT: Failed to calculate MIC");
765 os_free(sm
->assoc_resp_ftie
);
766 sm
->assoc_resp_ftie
= os_malloc(ftie_len
);
767 if (sm
->assoc_resp_ftie
)
768 os_memcpy(sm
->assoc_resp_ftie
, ftie
, ftie_len
);
774 static inline int wpa_auth_set_key(struct wpa_authenticator
*wpa_auth
,
776 enum wpa_alg alg
, const u8
*addr
, int idx
,
777 u8
*key
, size_t key_len
)
779 if (wpa_auth
->cb
->set_key
== NULL
)
781 return wpa_auth
->cb
->set_key(wpa_auth
->cb_ctx
, vlan_id
, alg
, addr
, idx
,
786 void wpa_ft_install_ptk(struct wpa_state_machine
*sm
)
791 /* MLME-SETKEYS.request(PTK) */
792 alg
= wpa_cipher_to_alg(sm
->pairwise
);
793 klen
= wpa_cipher_key_len(sm
->pairwise
);
794 if (!wpa_cipher_valid_pairwise(sm
->pairwise
)) {
795 wpa_printf(MSG_DEBUG
, "FT: Unknown pairwise alg 0x%x - skip "
796 "PTK configuration", sm
->pairwise
);
800 /* FIX: add STA entry to kernel/driver here? The set_key will fail
801 * most likely without this.. At the moment, STA entry is added only
802 * after association has been completed. This function will be called
803 * again after association to get the PTK configured, but that could be
804 * optimized by adding the STA entry earlier.
806 if (wpa_auth_set_key(sm
->wpa_auth
, 0, alg
, sm
->addr
, 0,
810 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
811 sm
->pairwise_set
= TRUE
;
815 /* Derive PMK-R1 from PSK, check all available PSK */
816 static int wpa_ft_psk_pmk_r1(struct wpa_state_machine
*sm
,
817 const u8
*req_pmk_r1_name
,
818 u8
*out_pmk_r1
, int *out_pairwise
)
820 const u8
*pmk
= NULL
;
821 u8 pmk_r0
[PMK_LEN
], pmk_r0_name
[WPA_PMK_NAME_LEN
];
822 u8 pmk_r1
[PMK_LEN
], pmk_r1_name
[WPA_PMK_NAME_LEN
];
823 struct wpa_authenticator
*wpa_auth
= sm
->wpa_auth
;
824 const u8
*mdid
= wpa_auth
->conf
.mobility_domain
;
825 const u8
*r0kh
= sm
->r0kh_id
;
826 size_t r0kh_len
= sm
->r0kh_id_len
;
827 const u8
*r1kh
= wpa_auth
->conf
.r1_key_holder
;
828 const u8
*ssid
= wpa_auth
->conf
.ssid
;
829 size_t ssid_len
= wpa_auth
->conf
.ssid_len
;
832 pairwise
= sm
->pairwise
;
835 pmk
= wpa_ft_get_psk(wpa_auth
, sm
->addr
, sm
->p2p_dev_addr
,
840 if (wpa_derive_pmk_r0(pmk
, PMK_LEN
, ssid
, ssid_len
, mdid
, r0kh
,
842 pmk_r0
, pmk_r0_name
) < 0 ||
843 wpa_derive_pmk_r1(pmk_r0
, pmk_r0_name
, r1kh
, sm
->addr
,
844 pmk_r1
, pmk_r1_name
) < 0 ||
845 os_memcmp_const(pmk_r1_name
, req_pmk_r1_name
,
846 WPA_PMK_NAME_LEN
) != 0)
849 /* We found a PSK that matches the requested pmk_r1_name */
850 wpa_printf(MSG_DEBUG
,
851 "FT: Found PSK to generate PMK-R1 locally");
852 os_memcpy(out_pmk_r1
, pmk_r1
, PMK_LEN
);
854 *out_pairwise
= pairwise
;
858 wpa_printf(MSG_DEBUG
,
859 "FT: Did not find PSK to generate PMK-R1 locally");
864 /* Detect the configuration the station asked for.
865 * Required to detect FT-PSK and pairwise cipher.
867 static int wpa_ft_set_key_mgmt(struct wpa_state_machine
*sm
,
868 struct wpa_ft_ies
*parse
)
870 int key_mgmt
, ciphers
;
872 if (sm
->wpa_key_mgmt
)
875 key_mgmt
= parse
->key_mgmt
& sm
->wpa_auth
->conf
.wpa_key_mgmt
;
877 wpa_printf(MSG_DEBUG
, "FT: Invalid key mgmt (0x%x) from "
878 MACSTR
, parse
->key_mgmt
, MAC2STR(sm
->addr
));
881 if (key_mgmt
& WPA_KEY_MGMT_FT_IEEE8021X
)
882 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_IEEE8021X
;
883 else if (key_mgmt
& WPA_KEY_MGMT_FT_PSK
)
884 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_PSK
;
886 else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA256
)
887 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_FILS_SHA256
;
888 else if (key_mgmt
& WPA_KEY_MGMT_FT_FILS_SHA384
)
889 sm
->wpa_key_mgmt
= WPA_KEY_MGMT_FT_FILS_SHA384
;
890 #endif /* CONFIG_FILS */
891 ciphers
= parse
->pairwise_cipher
& sm
->wpa_auth
->conf
.rsn_pairwise
;
893 wpa_printf(MSG_DEBUG
, "FT: Invalid pairwise cipher (0x%x) from "
895 parse
->pairwise_cipher
, MAC2STR(sm
->addr
));
898 sm
->pairwise
= wpa_pick_pairwise_cipher(ciphers
, 0);
904 static int wpa_ft_process_auth_req(struct wpa_state_machine
*sm
,
905 const u8
*ies
, size_t ies_len
,
906 u8
**resp_ies
, size_t *resp_ies_len
)
908 struct rsn_mdie
*mdie
;
909 struct rsn_ftie
*ftie
;
910 u8 pmk_r1
[PMK_LEN
], pmk_r1_name
[WPA_PMK_NAME_LEN
];
911 u8 ptk_name
[WPA_PMK_NAME_LEN
];
912 struct wpa_auth_config
*conf
;
913 struct wpa_ft_ies parse
;
922 sm
->pmk_r1_name_valid
= 0;
923 conf
= &sm
->wpa_auth
->conf
;
925 wpa_hexdump(MSG_DEBUG
, "FT: Received authentication frame IEs",
928 if (wpa_ft_parse_ies(ies
, ies_len
, &parse
) < 0) {
929 wpa_printf(MSG_DEBUG
, "FT: Failed to parse FT IEs");
930 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
933 mdie
= (struct rsn_mdie
*) parse
.mdie
;
934 if (mdie
== NULL
|| parse
.mdie_len
< sizeof(*mdie
) ||
935 os_memcmp(mdie
->mobility_domain
,
936 sm
->wpa_auth
->conf
.mobility_domain
,
937 MOBILITY_DOMAIN_ID_LEN
) != 0) {
938 wpa_printf(MSG_DEBUG
, "FT: Invalid MDIE");
939 return WLAN_STATUS_INVALID_MDIE
;
942 ftie
= (struct rsn_ftie
*) parse
.ftie
;
943 if (ftie
== NULL
|| parse
.ftie_len
< sizeof(*ftie
)) {
944 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE");
945 return WLAN_STATUS_INVALID_FTIE
;
948 os_memcpy(sm
->SNonce
, ftie
->snonce
, WPA_NONCE_LEN
);
950 if (parse
.r0kh_id
== NULL
) {
951 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE - no R0KH-ID");
952 return WLAN_STATUS_INVALID_FTIE
;
955 wpa_hexdump(MSG_DEBUG
, "FT: STA R0KH-ID",
956 parse
.r0kh_id
, parse
.r0kh_id_len
);
957 os_memcpy(sm
->r0kh_id
, parse
.r0kh_id
, parse
.r0kh_id_len
);
958 sm
->r0kh_id_len
= parse
.r0kh_id_len
;
960 if (parse
.rsn_pmkid
== NULL
) {
961 wpa_printf(MSG_DEBUG
, "FT: No PMKID in RSNIE");
962 return WLAN_STATUS_INVALID_PMKID
;
965 if (wpa_ft_set_key_mgmt(sm
, &parse
) < 0)
966 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
968 wpa_hexdump(MSG_DEBUG
, "FT: Requested PMKR0Name",
969 parse
.rsn_pmkid
, WPA_PMK_NAME_LEN
);
970 if (wpa_derive_pmk_r1_name(parse
.rsn_pmkid
,
971 sm
->wpa_auth
->conf
.r1_key_holder
, sm
->addr
,
973 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
974 wpa_hexdump(MSG_DEBUG
, "FT: Derived requested PMKR1Name",
975 pmk_r1_name
, WPA_PMK_NAME_LEN
);
977 if (conf
->ft_psk_generate_local
&&
978 wpa_key_mgmt_ft_psk(sm
->wpa_key_mgmt
)) {
979 if (wpa_ft_psk_pmk_r1(sm
, pmk_r1_name
, pmk_r1
, &pairwise
) < 0)
980 return WLAN_STATUS_INVALID_PMKID
;
981 } else if (wpa_ft_fetch_pmk_r1(sm
->wpa_auth
, sm
->addr
, pmk_r1_name
,
982 pmk_r1
, &pairwise
) < 0) {
983 if (wpa_ft_pull_pmk_r1(sm
, ies
, ies_len
, parse
.rsn_pmkid
) < 0) {
984 wpa_printf(MSG_DEBUG
, "FT: Did not have matching "
985 "PMK-R1 and unknown R0KH-ID");
986 return WLAN_STATUS_INVALID_PMKID
;
989 return -1; /* Status pending */
992 wpa_hexdump_key(MSG_DEBUG
, "FT: Selected PMK-R1", pmk_r1
, PMK_LEN
);
993 sm
->pmk_r1_name_valid
= 1;
994 os_memcpy(sm
->pmk_r1_name
, pmk_r1_name
, WPA_PMK_NAME_LEN
);
996 if (random_get_bytes(sm
->ANonce
, WPA_NONCE_LEN
)) {
997 wpa_printf(MSG_DEBUG
, "FT: Failed to get random data for "
999 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1002 wpa_hexdump(MSG_DEBUG
, "FT: Received SNonce",
1003 sm
->SNonce
, WPA_NONCE_LEN
);
1004 wpa_hexdump(MSG_DEBUG
, "FT: Generated ANonce",
1005 sm
->ANonce
, WPA_NONCE_LEN
);
1007 if (wpa_pmk_r1_to_ptk(pmk_r1
, sm
->SNonce
, sm
->ANonce
, sm
->addr
,
1008 sm
->wpa_auth
->addr
, pmk_r1_name
,
1009 &sm
->PTK
, ptk_name
, sm
->wpa_key_mgmt
,
1011 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1013 sm
->pairwise
= pairwise
;
1014 sm
->PTK_valid
= TRUE
;
1015 wpa_ft_install_ptk(sm
);
1017 buflen
= 2 + sizeof(struct rsn_mdie
) + 2 + sizeof(struct rsn_ftie
) +
1018 2 + FT_R1KH_ID_LEN
+ 200;
1019 *resp_ies
= os_zalloc(buflen
);
1020 if (*resp_ies
== NULL
)
1024 end
= *resp_ies
+ buflen
;
1026 ret
= wpa_write_rsn_ie(conf
, pos
, end
- pos
, parse
.rsn_pmkid
);
1031 ret
= wpa_write_mdie(conf
, pos
, end
- pos
);
1036 ret
= wpa_write_ftie(conf
, parse
.r0kh_id
, parse
.r0kh_id_len
,
1037 sm
->ANonce
, sm
->SNonce
, pos
, end
- pos
, NULL
, 0);
1042 *resp_ies_len
= pos
- *resp_ies
;
1044 return WLAN_STATUS_SUCCESS
;
1048 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1052 void wpa_ft_process_auth(struct wpa_state_machine
*sm
, const u8
*bssid
,
1053 u16 auth_transaction
, const u8
*ies
, size_t ies_len
,
1054 void (*cb
)(void *ctx
, const u8
*dst
, const u8
*bssid
,
1055 u16 auth_transaction
, u16 status
,
1056 const u8
*ies
, size_t ies_len
),
1061 size_t resp_ies_len
;
1065 wpa_printf(MSG_DEBUG
, "FT: Received authentication frame, but "
1066 "WPA SM not available");
1070 wpa_printf(MSG_DEBUG
, "FT: Received authentication frame: STA=" MACSTR
1071 " BSSID=" MACSTR
" transaction=%d",
1072 MAC2STR(sm
->addr
), MAC2STR(bssid
), auth_transaction
);
1073 sm
->ft_pending_cb
= cb
;
1074 sm
->ft_pending_cb_ctx
= ctx
;
1075 sm
->ft_pending_auth_transaction
= auth_transaction
;
1076 res
= wpa_ft_process_auth_req(sm
, ies
, ies_len
, &resp_ies
,
1079 wpa_printf(MSG_DEBUG
, "FT: Callback postponed until response is available");
1084 wpa_printf(MSG_DEBUG
, "FT: FT authentication response: dst=" MACSTR
1085 " auth_transaction=%d status=%d",
1086 MAC2STR(sm
->addr
), auth_transaction
+ 1, status
);
1087 wpa_hexdump(MSG_DEBUG
, "FT: Response IEs", resp_ies
, resp_ies_len
);
1088 cb(ctx
, sm
->addr
, bssid
, auth_transaction
+ 1, status
,
1089 resp_ies
, resp_ies_len
);
1094 u16
wpa_ft_validate_reassoc(struct wpa_state_machine
*sm
, const u8
*ies
,
1097 struct wpa_ft_ies parse
;
1098 struct rsn_mdie
*mdie
;
1099 struct rsn_ftie
*ftie
;
1100 u8 mic
[WPA_EAPOL_KEY_MIC_MAX_LEN
];
1101 size_t mic_len
= 16;
1105 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1107 wpa_hexdump(MSG_DEBUG
, "FT: Reassoc Req IEs", ies
, ies_len
);
1109 if (wpa_ft_parse_ies(ies
, ies_len
, &parse
) < 0) {
1110 wpa_printf(MSG_DEBUG
, "FT: Failed to parse FT IEs");
1111 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1114 if (parse
.rsn
== NULL
) {
1115 wpa_printf(MSG_DEBUG
, "FT: No RSNIE in Reassoc Req");
1116 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1119 if (parse
.rsn_pmkid
== NULL
) {
1120 wpa_printf(MSG_DEBUG
, "FT: No PMKID in RSNIE");
1121 return WLAN_STATUS_INVALID_PMKID
;
1124 if (os_memcmp_const(parse
.rsn_pmkid
, sm
->pmk_r1_name
, WPA_PMK_NAME_LEN
)
1126 wpa_printf(MSG_DEBUG
, "FT: PMKID in Reassoc Req did not match "
1127 "with the PMKR1Name derived from auth request");
1128 return WLAN_STATUS_INVALID_PMKID
;
1131 mdie
= (struct rsn_mdie
*) parse
.mdie
;
1132 if (mdie
== NULL
|| parse
.mdie_len
< sizeof(*mdie
) ||
1133 os_memcmp(mdie
->mobility_domain
,
1134 sm
->wpa_auth
->conf
.mobility_domain
,
1135 MOBILITY_DOMAIN_ID_LEN
) != 0) {
1136 wpa_printf(MSG_DEBUG
, "FT: Invalid MDIE");
1137 return WLAN_STATUS_INVALID_MDIE
;
1140 ftie
= (struct rsn_ftie
*) parse
.ftie
;
1141 if (ftie
== NULL
|| parse
.ftie_len
< sizeof(*ftie
)) {
1142 wpa_printf(MSG_DEBUG
, "FT: Invalid FTIE");
1143 return WLAN_STATUS_INVALID_FTIE
;
1146 if (os_memcmp(ftie
->snonce
, sm
->SNonce
, WPA_NONCE_LEN
) != 0) {
1147 wpa_printf(MSG_DEBUG
, "FT: SNonce mismatch in FTIE");
1148 wpa_hexdump(MSG_DEBUG
, "FT: Received SNonce",
1149 ftie
->snonce
, WPA_NONCE_LEN
);
1150 wpa_hexdump(MSG_DEBUG
, "FT: Expected SNonce",
1151 sm
->SNonce
, WPA_NONCE_LEN
);
1152 return WLAN_STATUS_INVALID_FTIE
;
1155 if (os_memcmp(ftie
->anonce
, sm
->ANonce
, WPA_NONCE_LEN
) != 0) {
1156 wpa_printf(MSG_DEBUG
, "FT: ANonce mismatch in FTIE");
1157 wpa_hexdump(MSG_DEBUG
, "FT: Received ANonce",
1158 ftie
->anonce
, WPA_NONCE_LEN
);
1159 wpa_hexdump(MSG_DEBUG
, "FT: Expected ANonce",
1160 sm
->ANonce
, WPA_NONCE_LEN
);
1161 return WLAN_STATUS_INVALID_FTIE
;
1165 if (parse
.r0kh_id
== NULL
) {
1166 wpa_printf(MSG_DEBUG
, "FT: No R0KH-ID subelem in FTIE");
1167 return WLAN_STATUS_INVALID_FTIE
;
1170 if (parse
.r0kh_id_len
!= sm
->r0kh_id_len
||
1171 os_memcmp_const(parse
.r0kh_id
, sm
->r0kh_id
, parse
.r0kh_id_len
) != 0)
1173 wpa_printf(MSG_DEBUG
, "FT: R0KH-ID in FTIE did not match with "
1174 "the current R0KH-ID");
1175 wpa_hexdump(MSG_DEBUG
, "FT: R0KH-ID in FTIE",
1176 parse
.r0kh_id
, parse
.r0kh_id_len
);
1177 wpa_hexdump(MSG_DEBUG
, "FT: The current R0KH-ID",
1178 sm
->r0kh_id
, sm
->r0kh_id_len
);
1179 return WLAN_STATUS_INVALID_FTIE
;
1182 if (parse
.r1kh_id
== NULL
) {
1183 wpa_printf(MSG_DEBUG
, "FT: No R1KH-ID subelem in FTIE");
1184 return WLAN_STATUS_INVALID_FTIE
;
1187 if (os_memcmp_const(parse
.r1kh_id
, sm
->wpa_auth
->conf
.r1_key_holder
,
1188 FT_R1KH_ID_LEN
) != 0) {
1189 wpa_printf(MSG_DEBUG
, "FT: Unknown R1KH-ID used in "
1191 wpa_hexdump(MSG_DEBUG
, "FT: R1KH-ID in FTIE",
1192 parse
.r1kh_id
, FT_R1KH_ID_LEN
);
1193 wpa_hexdump(MSG_DEBUG
, "FT: Expected R1KH-ID",
1194 sm
->wpa_auth
->conf
.r1_key_holder
, FT_R1KH_ID_LEN
);
1195 return WLAN_STATUS_INVALID_FTIE
;
1198 if (parse
.rsn_pmkid
== NULL
||
1199 os_memcmp_const(parse
.rsn_pmkid
, sm
->pmk_r1_name
, WPA_PMK_NAME_LEN
))
1201 wpa_printf(MSG_DEBUG
, "FT: No matching PMKR1Name (PMKID) in "
1202 "RSNIE (pmkid=%d)", !!parse
.rsn_pmkid
);
1203 return WLAN_STATUS_INVALID_PMKID
;
1208 count
+= ieee802_11_ie_count(parse
.ric
, parse
.ric_len
);
1209 if (ftie
->mic_control
[1] != count
) {
1210 wpa_printf(MSG_DEBUG
, "FT: Unexpected IE count in MIC "
1211 "Control: received %u expected %u",
1212 ftie
->mic_control
[1], count
);
1213 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1216 if (wpa_ft_mic(sm
->PTK
.kck
, sm
->PTK
.kck_len
, sm
->addr
,
1217 sm
->wpa_auth
->addr
, 5,
1218 parse
.mdie
- 2, parse
.mdie_len
+ 2,
1219 parse
.ftie
- 2, parse
.ftie_len
+ 2,
1220 parse
.rsn
- 2, parse
.rsn_len
+ 2,
1221 parse
.ric
, parse
.ric_len
,
1223 wpa_printf(MSG_DEBUG
, "FT: Failed to calculate MIC");
1224 return WLAN_STATUS_UNSPECIFIED_FAILURE
;
1227 if (os_memcmp_const(mic
, ftie
->mic
, mic_len
) != 0) {
1228 wpa_printf(MSG_DEBUG
, "FT: Invalid MIC in FTIE");
1229 wpa_printf(MSG_DEBUG
, "FT: addr=" MACSTR
" auth_addr=" MACSTR
,
1230 MAC2STR(sm
->addr
), MAC2STR(sm
->wpa_auth
->addr
));
1231 wpa_hexdump(MSG_MSGDUMP
, "FT: Received MIC",
1232 ftie
->mic
, mic_len
);
1233 wpa_hexdump(MSG_MSGDUMP
, "FT: Calculated MIC", mic
, mic_len
);
1234 wpa_hexdump(MSG_MSGDUMP
, "FT: MDIE",
1235 parse
.mdie
- 2, parse
.mdie_len
+ 2);
1236 wpa_hexdump(MSG_MSGDUMP
, "FT: FTIE",
1237 parse
.ftie
- 2, parse
.ftie_len
+ 2);
1238 wpa_hexdump(MSG_MSGDUMP
, "FT: RSN",
1239 parse
.rsn
- 2, parse
.rsn_len
+ 2);
1240 return WLAN_STATUS_INVALID_FTIE
;
1243 return WLAN_STATUS_SUCCESS
;
1247 int wpa_ft_action_rx(struct wpa_state_machine
*sm
, const u8
*data
, size_t len
)
1249 const u8
*sta_addr
, *target_ap
;
1253 struct ft_rrb_frame
*frame
;
1259 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1260 * FT Request action frame body[variable]
1264 wpa_printf(MSG_DEBUG
, "FT: Too short FT Action frame "
1265 "(len=%lu)", (unsigned long) len
);
1270 sta_addr
= data
+ 2;
1271 target_ap
= data
+ 8;
1275 wpa_printf(MSG_DEBUG
, "FT: Received FT Action frame (STA=" MACSTR
1276 " Target AP=" MACSTR
" Action=%d)",
1277 MAC2STR(sta_addr
), MAC2STR(target_ap
), action
);
1279 if (os_memcmp(sta_addr
, sm
->addr
, ETH_ALEN
) != 0) {
1280 wpa_printf(MSG_DEBUG
, "FT: Mismatch in FT Action STA address: "
1281 "STA=" MACSTR
" STA-Address=" MACSTR
,
1282 MAC2STR(sm
->addr
), MAC2STR(sta_addr
));
1287 * Do some sanity checking on the target AP address (not own and not
1288 * broadcast. This could be extended to filter based on a list of known
1289 * APs in the MD (if such a list were configured).
1291 if ((target_ap
[0] & 0x01) ||
1292 os_memcmp(target_ap
, sm
->wpa_auth
->addr
, ETH_ALEN
) == 0) {
1293 wpa_printf(MSG_DEBUG
, "FT: Invalid Target AP in FT Action "
1298 wpa_hexdump(MSG_MSGDUMP
, "FT: Action frame body", ies
, ies_len
);
1300 if (!sm
->wpa_auth
->conf
.ft_over_ds
) {
1301 wpa_printf(MSG_DEBUG
, "FT: Over-DS option disabled - reject");
1305 /* RRB - Forward action frame to the target AP */
1306 frame
= os_malloc(sizeof(*frame
) + len
);
1309 frame
->frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1310 frame
->packet_type
= FT_PACKET_REQUEST
;
1311 frame
->action_length
= host_to_le16(len
);
1312 os_memcpy(frame
->ap_address
, sm
->wpa_auth
->addr
, ETH_ALEN
);
1313 os_memcpy(frame
+ 1, data
, len
);
1315 wpa_ft_rrb_send(sm
->wpa_auth
, target_ap
, (u8
*) frame
,
1316 sizeof(*frame
) + len
);
1323 static void wpa_ft_rrb_rx_request_cb(void *ctx
, const u8
*dst
, const u8
*bssid
,
1324 u16 auth_transaction
, u16 resp
,
1325 const u8
*ies
, size_t ies_len
)
1327 struct wpa_state_machine
*sm
= ctx
;
1328 wpa_printf(MSG_DEBUG
, "FT: Over-the-DS RX request cb for " MACSTR
,
1330 wpa_ft_send_rrb_auth_resp(sm
, sm
->ft_pending_current_ap
, sm
->addr
,
1331 WLAN_STATUS_SUCCESS
, ies
, ies_len
);
1335 static int wpa_ft_rrb_rx_request(struct wpa_authenticator
*wpa_auth
,
1336 const u8
*current_ap
, const u8
*sta_addr
,
1337 const u8
*body
, size_t len
)
1339 struct wpa_state_machine
*sm
;
1342 size_t resp_ies_len
;
1345 sm
= wpa_ft_add_sta(wpa_auth
, sta_addr
);
1347 wpa_printf(MSG_DEBUG
, "FT: Failed to add new STA based on "
1352 wpa_hexdump(MSG_MSGDUMP
, "FT: RRB Request Frame body", body
, len
);
1354 sm
->ft_pending_cb
= wpa_ft_rrb_rx_request_cb
;
1355 sm
->ft_pending_cb_ctx
= sm
;
1356 os_memcpy(sm
->ft_pending_current_ap
, current_ap
, ETH_ALEN
);
1357 res
= wpa_ft_process_auth_req(sm
, body
, len
, &resp_ies
,
1360 wpa_printf(MSG_DEBUG
, "FT: No immediate response available - wait for pull response");
1365 res
= wpa_ft_send_rrb_auth_resp(sm
, current_ap
, sta_addr
, status
,
1366 resp_ies
, resp_ies_len
);
1372 static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine
*sm
,
1373 const u8
*current_ap
, const u8
*sta_addr
,
1374 u16 status
, const u8
*resp_ies
,
1375 size_t resp_ies_len
)
1377 struct wpa_authenticator
*wpa_auth
= sm
->wpa_auth
;
1379 struct ft_rrb_frame
*frame
;
1382 wpa_printf(MSG_DEBUG
, "FT: RRB authentication response: STA=" MACSTR
1383 " CurrentAP=" MACSTR
" status=%d",
1384 MAC2STR(sm
->addr
), MAC2STR(current_ap
), status
);
1385 wpa_hexdump(MSG_DEBUG
, "FT: Response IEs", resp_ies
, resp_ies_len
);
1387 /* RRB - Forward action frame response to the Current AP */
1390 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1391 * Status_Code[2] FT Request action frame body[variable]
1393 rlen
= 2 + 2 * ETH_ALEN
+ 2 + resp_ies_len
;
1395 frame
= os_malloc(sizeof(*frame
) + rlen
);
1398 frame
->frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1399 frame
->packet_type
= FT_PACKET_RESPONSE
;
1400 frame
->action_length
= host_to_le16(rlen
);
1401 os_memcpy(frame
->ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1402 pos
= (u8
*) (frame
+ 1);
1403 *pos
++ = WLAN_ACTION_FT
;
1404 *pos
++ = 2; /* Action: Response */
1405 os_memcpy(pos
, sta_addr
, ETH_ALEN
);
1407 os_memcpy(pos
, wpa_auth
->addr
, ETH_ALEN
);
1409 WPA_PUT_LE16(pos
, status
);
1412 os_memcpy(pos
, resp_ies
, resp_ies_len
);
1414 wpa_ft_rrb_send(wpa_auth
, current_ap
, (u8
*) frame
,
1415 sizeof(*frame
) + rlen
);
1422 static int wpa_ft_rrb_rx_pull(struct wpa_authenticator
*wpa_auth
,
1424 const u8
*data
, size_t data_len
)
1426 struct ft_r0kh_r1kh_pull_frame f
;
1429 struct ft_remote_r1kh
*r1kh
;
1430 struct ft_r0kh_r1kh_resp_frame resp
, r
;
1434 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 pull");
1436 if (data_len
< sizeof(f
))
1439 r1kh
= wpa_auth
->conf
.r1kh_list
;
1441 if (os_memcmp(r1kh
->addr
, src_addr
, ETH_ALEN
) == 0)
1446 wpa_printf(MSG_DEBUG
, "FT: No matching R1KH address found for "
1447 "PMK-R1 pull source address " MACSTR
,
1452 crypt
= data
+ offsetof(struct ft_r0kh_r1kh_pull_frame
, nonce
);
1453 os_memset(&f
, 0, sizeof(f
));
1454 plain
= ((u8
*) &f
) + offsetof(struct ft_r0kh_r1kh_pull_frame
, nonce
);
1455 /* aes_unwrap() does not support inplace decryption, so use a temporary
1456 * buffer for the data. */
1457 if (aes_unwrap(r1kh
->key
, sizeof(r1kh
->key
),
1458 (FT_R0KH_R1KH_PULL_DATA_LEN
+ 7) / 8,
1459 crypt
, plain
) < 0) {
1460 wpa_printf(MSG_DEBUG
, "FT: Failed to decrypt PMK-R1 pull "
1461 "request from " MACSTR
, MAC2STR(src_addr
));
1465 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - nonce",
1466 f
.nonce
, sizeof(f
.nonce
));
1467 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - PMKR0Name",
1468 f
.pmk_r0_name
, WPA_PMK_NAME_LEN
);
1469 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
" S1KH-ID="
1470 MACSTR
, MAC2STR(f
.r1kh_id
), MAC2STR(f
.s1kh_id
));
1472 os_memset(&resp
, 0, sizeof(resp
));
1473 resp
.frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1474 resp
.packet_type
= FT_PACKET_R0KH_R1KH_RESP
;
1475 resp
.data_length
= host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN
);
1476 os_memcpy(resp
.ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1478 /* aes_wrap() does not support inplace encryption, so use a temporary
1479 * buffer for the data. */
1480 os_memcpy(r
.nonce
, f
.nonce
, sizeof(f
.nonce
));
1481 os_memcpy(r
.r1kh_id
, f
.r1kh_id
, FT_R1KH_ID_LEN
);
1482 os_memcpy(r
.s1kh_id
, f
.s1kh_id
, ETH_ALEN
);
1483 if (wpa_ft_fetch_pmk_r0(wpa_auth
, f
.s1kh_id
, f
.pmk_r0_name
, pmk_r0
,
1485 wpa_printf(MSG_DEBUG
, "FT: No matching PMKR0Name found for "
1490 if (wpa_derive_pmk_r1(pmk_r0
, f
.pmk_r0_name
, f
.r1kh_id
, f
.s1kh_id
,
1491 r
.pmk_r1
, r
.pmk_r1_name
) < 0) {
1492 os_memset(pmk_r0
, 0, PMK_LEN
);
1495 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", r
.pmk_r1
, PMK_LEN
);
1496 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", r
.pmk_r1_name
,
1498 r
.pairwise
= host_to_le16(pairwise
);
1499 os_memset(r
.pad
, 0, sizeof(r
.pad
));
1501 if (aes_wrap(r1kh
->key
, sizeof(r1kh
->key
),
1502 (FT_R0KH_R1KH_RESP_DATA_LEN
+ 7) / 8,
1503 r
.nonce
, resp
.nonce
) < 0) {
1504 os_memset(pmk_r0
, 0, PMK_LEN
);
1508 os_memset(pmk_r0
, 0, PMK_LEN
);
1510 wpa_ft_rrb_send(wpa_auth
, src_addr
, (u8
*) &resp
, sizeof(resp
));
1516 static void ft_pull_resp_cb_finish(void *eloop_ctx
, void *timeout_ctx
)
1518 struct wpa_state_machine
*sm
= eloop_ctx
;
1521 size_t resp_ies_len
;
1524 res
= wpa_ft_process_auth_req(sm
, wpabuf_head(sm
->ft_pending_req_ies
),
1525 wpabuf_len(sm
->ft_pending_req_ies
),
1526 &resp_ies
, &resp_ies_len
);
1527 wpabuf_free(sm
->ft_pending_req_ies
);
1528 sm
->ft_pending_req_ies
= NULL
;
1530 res
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
1532 wpa_printf(MSG_DEBUG
, "FT: Postponed auth callback result for " MACSTR
1533 " - status %u", MAC2STR(sm
->addr
), status
);
1535 sm
->ft_pending_cb(sm
->ft_pending_cb_ctx
, sm
->addr
, sm
->wpa_auth
->addr
,
1536 sm
->ft_pending_auth_transaction
+ 1, status
,
1537 resp_ies
, resp_ies_len
);
1542 static int ft_pull_resp_cb(struct wpa_state_machine
*sm
, void *ctx
)
1544 struct ft_r0kh_r1kh_resp_frame
*frame
= ctx
;
1546 if (os_memcmp(frame
->s1kh_id
, sm
->addr
, ETH_ALEN
) != 0 ||
1547 os_memcmp(frame
->nonce
, sm
->ft_pending_pull_nonce
,
1548 FT_R0KH_R1KH_PULL_NONCE_LEN
) != 0 ||
1549 sm
->ft_pending_cb
== NULL
|| sm
->ft_pending_req_ies
== NULL
)
1552 wpa_printf(MSG_DEBUG
, "FT: Response to a pending pull request for "
1553 MACSTR
" - process from timeout", MAC2STR(sm
->addr
));
1554 eloop_register_timeout(0, 0, ft_pull_resp_cb_finish
, sm
, NULL
);
1559 static int wpa_ft_rrb_rx_resp(struct wpa_authenticator
*wpa_auth
,
1561 const u8
*data
, size_t data_len
)
1563 struct ft_r0kh_r1kh_resp_frame f
;
1566 struct ft_remote_r0kh
*r0kh
;
1569 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 pull response");
1571 if (data_len
< sizeof(f
))
1574 r0kh
= wpa_auth
->conf
.r0kh_list
;
1576 if (os_memcmp(r0kh
->addr
, src_addr
, ETH_ALEN
) == 0)
1581 wpa_printf(MSG_DEBUG
, "FT: No matching R0KH address found for "
1582 "PMK-R0 pull response source address " MACSTR
,
1587 crypt
= data
+ offsetof(struct ft_r0kh_r1kh_resp_frame
, nonce
);
1588 os_memset(&f
, 0, sizeof(f
));
1589 plain
= ((u8
*) &f
) + offsetof(struct ft_r0kh_r1kh_resp_frame
, nonce
);
1590 /* aes_unwrap() does not support inplace decryption, so use a temporary
1591 * buffer for the data. */
1592 if (aes_unwrap(r0kh
->key
, sizeof(r0kh
->key
),
1593 (FT_R0KH_R1KH_RESP_DATA_LEN
+ 7) / 8,
1594 crypt
, plain
) < 0) {
1595 wpa_printf(MSG_DEBUG
, "FT: Failed to decrypt PMK-R1 pull "
1596 "response from " MACSTR
, MAC2STR(src_addr
));
1600 if (os_memcmp_const(f
.r1kh_id
, wpa_auth
->conf
.r1_key_holder
,
1601 FT_R1KH_ID_LEN
) != 0) {
1602 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 pull response did not use a "
1603 "matching R1KH-ID");
1607 pairwise
= le_to_host16(f
.pairwise
);
1608 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - nonce",
1609 f
.nonce
, sizeof(f
.nonce
));
1610 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 pull - R1KH-ID=" MACSTR
" S1KH-ID="
1611 MACSTR
" pairwise=0x%x",
1612 MAC2STR(f
.r1kh_id
), MAC2STR(f
.s1kh_id
), pairwise
);
1613 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1 pull - PMK-R1",
1615 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 pull - PMKR1Name",
1616 f
.pmk_r1_name
, WPA_PMK_NAME_LEN
);
1618 res
= wpa_ft_store_pmk_r1(wpa_auth
, f
.s1kh_id
, f
.pmk_r1
, f
.pmk_r1_name
,
1620 wpa_printf(MSG_DEBUG
, "FT: Look for pending pull request");
1621 wpa_auth_for_each_sta(wpa_auth
, ft_pull_resp_cb
, &f
);
1622 os_memset(f
.pmk_r1
, 0, PMK_LEN
);
1624 return res
? 0 : -1;
1628 static int wpa_ft_rrb_rx_push(struct wpa_authenticator
*wpa_auth
,
1630 const u8
*data
, size_t data_len
)
1632 struct ft_r0kh_r1kh_push_frame f
;
1635 struct ft_remote_r0kh
*r0kh
;
1640 wpa_printf(MSG_DEBUG
, "FT: Received PMK-R1 push");
1642 if (data_len
< sizeof(f
))
1645 r0kh
= wpa_auth
->conf
.r0kh_list
;
1647 if (os_memcmp(r0kh
->addr
, src_addr
, ETH_ALEN
) == 0)
1652 wpa_printf(MSG_DEBUG
, "FT: No matching R0KH address found for "
1653 "PMK-R0 push source address " MACSTR
,
1658 crypt
= data
+ offsetof(struct ft_r0kh_r1kh_push_frame
, timestamp
);
1659 os_memset(&f
, 0, sizeof(f
));
1660 plain
= ((u8
*) &f
) + offsetof(struct ft_r0kh_r1kh_push_frame
,
1662 /* aes_unwrap() does not support inplace decryption, so use a temporary
1663 * buffer for the data. */
1664 if (aes_unwrap(r0kh
->key
, sizeof(r0kh
->key
),
1665 (FT_R0KH_R1KH_PUSH_DATA_LEN
+ 7) / 8,
1666 crypt
, plain
) < 0) {
1667 wpa_printf(MSG_DEBUG
, "FT: Failed to decrypt PMK-R1 push from "
1668 MACSTR
, MAC2STR(src_addr
));
1673 tsend
= WPA_GET_LE32(f
.timestamp
);
1674 if ((now
.sec
> tsend
&& now
.sec
- tsend
> 60) ||
1675 (now
.sec
< tsend
&& tsend
- now
.sec
> 60)) {
1676 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 push did not have a valid "
1677 "timestamp: sender time %d own time %d\n",
1678 (int) tsend
, (int) now
.sec
);
1682 if (os_memcmp_const(f
.r1kh_id
, wpa_auth
->conf
.r1_key_holder
,
1683 FT_R1KH_ID_LEN
) != 0) {
1684 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 push did not use a matching "
1685 "R1KH-ID (received " MACSTR
" own " MACSTR
")",
1687 MAC2STR(wpa_auth
->conf
.r1_key_holder
));
1691 pairwise
= le_to_host16(f
.pairwise
);
1692 wpa_printf(MSG_DEBUG
, "FT: PMK-R1 push - R1KH-ID=" MACSTR
" S1KH-ID="
1693 MACSTR
" pairwise=0x%x",
1694 MAC2STR(f
.r1kh_id
), MAC2STR(f
.s1kh_id
), pairwise
);
1695 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1 push - PMK-R1",
1697 wpa_hexdump(MSG_DEBUG
, "FT: PMK-R1 push - PMKR1Name",
1698 f
.pmk_r1_name
, WPA_PMK_NAME_LEN
);
1700 wpa_ft_store_pmk_r1(wpa_auth
, f
.s1kh_id
, f
.pmk_r1
, f
.pmk_r1_name
,
1702 os_memset(f
.pmk_r1
, 0, PMK_LEN
);
1708 int wpa_ft_rrb_rx(struct wpa_authenticator
*wpa_auth
, const u8
*src_addr
,
1709 const u8
*data
, size_t data_len
)
1711 struct ft_rrb_frame
*frame
;
1713 const u8
*pos
, *end
, *start
;
1715 const u8
*sta_addr
, *target_ap_addr
;
1717 wpa_printf(MSG_DEBUG
, "FT: RRB received frame from remote AP " MACSTR
,
1720 if (data_len
< sizeof(*frame
)) {
1721 wpa_printf(MSG_DEBUG
, "FT: Too short RRB frame (data_len=%lu)",
1722 (unsigned long) data_len
);
1727 frame
= (struct ft_rrb_frame
*) pos
;
1728 pos
+= sizeof(*frame
);
1730 alen
= le_to_host16(frame
->action_length
);
1731 wpa_printf(MSG_DEBUG
, "FT: RRB frame - frame_type=%d packet_type=%d "
1732 "action_length=%d ap_address=" MACSTR
,
1733 frame
->frame_type
, frame
->packet_type
, alen
,
1734 MAC2STR(frame
->ap_address
));
1736 if (frame
->frame_type
!= RSN_REMOTE_FRAME_TYPE_FT_RRB
) {
1737 /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */
1738 wpa_printf(MSG_DEBUG
, "FT: RRB discarded frame with "
1739 "unrecognized type %d", frame
->frame_type
);
1743 if (alen
> data_len
- sizeof(*frame
)) {
1744 wpa_printf(MSG_DEBUG
, "FT: RRB frame too short for action "
1749 if (frame
->packet_type
== FT_PACKET_R0KH_R1KH_PULL
)
1750 return wpa_ft_rrb_rx_pull(wpa_auth
, src_addr
, data
, data_len
);
1751 if (frame
->packet_type
== FT_PACKET_R0KH_R1KH_RESP
)
1752 return wpa_ft_rrb_rx_resp(wpa_auth
, src_addr
, data
, data_len
);
1753 if (frame
->packet_type
== FT_PACKET_R0KH_R1KH_PUSH
)
1754 return wpa_ft_rrb_rx_push(wpa_auth
, src_addr
, data
, data_len
);
1756 wpa_hexdump(MSG_MSGDUMP
, "FT: RRB - FT Action frame", pos
, alen
);
1758 if (alen
< 1 + 1 + 2 * ETH_ALEN
) {
1759 wpa_printf(MSG_DEBUG
, "FT: Too short RRB frame (not enough "
1760 "room for Action Frame body); alen=%lu",
1761 (unsigned long) alen
);
1767 if (*pos
!= WLAN_ACTION_FT
) {
1768 wpa_printf(MSG_DEBUG
, "FT: Unexpected Action frame category "
1777 target_ap_addr
= pos
;
1779 wpa_printf(MSG_DEBUG
, "FT: RRB Action Frame: action=%d sta_addr="
1780 MACSTR
" target_ap_addr=" MACSTR
,
1781 action
, MAC2STR(sta_addr
), MAC2STR(target_ap_addr
));
1783 if (frame
->packet_type
== FT_PACKET_REQUEST
) {
1784 wpa_printf(MSG_DEBUG
, "FT: FT Packet Type - Request");
1787 wpa_printf(MSG_DEBUG
, "FT: Unexpected Action %d in "
1788 "RRB Request", action
);
1792 if (os_memcmp(target_ap_addr
, wpa_auth
->addr
, ETH_ALEN
) != 0) {
1793 wpa_printf(MSG_DEBUG
, "FT: Target AP address in the "
1794 "RRB Request does not match with own "
1799 if (wpa_ft_rrb_rx_request(wpa_auth
, frame
->ap_address
,
1800 sta_addr
, pos
, end
- pos
) < 0)
1802 } else if (frame
->packet_type
== FT_PACKET_RESPONSE
) {
1805 if (end
- pos
< 2) {
1806 wpa_printf(MSG_DEBUG
, "FT: Not enough room for status "
1807 "code in RRB Response");
1810 status_code
= WPA_GET_LE16(pos
);
1813 wpa_printf(MSG_DEBUG
, "FT: FT Packet Type - Response "
1814 "(status_code=%d)", status_code
);
1816 if (wpa_ft_action_send(wpa_auth
, sta_addr
, start
, alen
) < 0)
1819 wpa_printf(MSG_DEBUG
, "FT: RRB discarded frame with unknown "
1820 "packet_type %d", frame
->packet_type
);
1825 wpa_hexdump(MSG_DEBUG
, "FT: Ignore extra data in end",
1833 static int wpa_ft_generate_pmk_r1(struct wpa_authenticator
*wpa_auth
,
1834 struct wpa_ft_pmk_r0_sa
*pmk_r0
,
1835 struct ft_remote_r1kh
*r1kh
,
1836 const u8
*s1kh_id
, int pairwise
)
1838 struct ft_r0kh_r1kh_push_frame frame
, f
;
1843 os_memset(&frame
, 0, sizeof(frame
));
1844 frame
.frame_type
= RSN_REMOTE_FRAME_TYPE_FT_RRB
;
1845 frame
.packet_type
= FT_PACKET_R0KH_R1KH_PUSH
;
1846 frame
.data_length
= host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN
);
1847 os_memcpy(frame
.ap_address
, wpa_auth
->addr
, ETH_ALEN
);
1849 /* aes_wrap() does not support inplace encryption, so use a temporary
1850 * buffer for the data. */
1851 os_memcpy(f
.r1kh_id
, r1kh
->id
, FT_R1KH_ID_LEN
);
1852 os_memcpy(f
.s1kh_id
, s1kh_id
, ETH_ALEN
);
1853 os_memcpy(f
.pmk_r0_name
, pmk_r0
->pmk_r0_name
, WPA_PMK_NAME_LEN
);
1854 if (wpa_derive_pmk_r1(pmk_r0
->pmk_r0
, pmk_r0
->pmk_r0_name
, r1kh
->id
,
1855 s1kh_id
, f
.pmk_r1
, f
.pmk_r1_name
) < 0)
1857 wpa_printf(MSG_DEBUG
, "FT: R1KH-ID " MACSTR
, MAC2STR(r1kh
->id
));
1858 wpa_hexdump_key(MSG_DEBUG
, "FT: PMK-R1", f
.pmk_r1
, PMK_LEN
);
1859 wpa_hexdump(MSG_DEBUG
, "FT: PMKR1Name", f
.pmk_r1_name
,
1862 WPA_PUT_LE32(f
.timestamp
, now
.sec
);
1863 f
.pairwise
= host_to_le16(pairwise
);
1864 os_memset(f
.pad
, 0, sizeof(f
.pad
));
1865 plain
= ((const u8
*) &f
) + offsetof(struct ft_r0kh_r1kh_push_frame
,
1867 crypt
= ((u8
*) &frame
) + offsetof(struct ft_r0kh_r1kh_push_frame
,
1869 if (aes_wrap(r1kh
->key
, sizeof(r1kh
->key
),
1870 (FT_R0KH_R1KH_PUSH_DATA_LEN
+ 7) / 8,
1874 wpa_ft_rrb_send(wpa_auth
, r1kh
->addr
, (u8
*) &frame
, sizeof(frame
));
1879 void wpa_ft_push_pmk_r1(struct wpa_authenticator
*wpa_auth
, const u8
*addr
)
1881 struct wpa_ft_pmk_r0_sa
*r0
;
1882 struct ft_remote_r1kh
*r1kh
;
1884 if (!wpa_auth
->conf
.pmk_r1_push
)
1887 r0
= wpa_auth
->ft_pmk_cache
->pmk_r0
;
1889 if (os_memcmp(r0
->spa
, addr
, ETH_ALEN
) == 0)
1894 if (r0
== NULL
|| r0
->pmk_r1_pushed
)
1896 r0
->pmk_r1_pushed
= 1;
1898 wpa_printf(MSG_DEBUG
, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
1899 "for STA " MACSTR
, MAC2STR(addr
));
1901 r1kh
= wpa_auth
->conf
.r1kh_list
;
1903 wpa_ft_generate_pmk_r1(wpa_auth
, r0
, r1kh
, addr
, r0
->pairwise
);
1908 #endif /* CONFIG_IEEE80211R_AP */