]> git.ipfire.org Git - thirdparty/hostap.git/blame - src/ap/wpa_auth_ft.c
tests: Add TEST_FAIL() to OpenSSL aes_wrap() and aes_unwrap()
[thirdparty/hostap.git] / src / ap / wpa_auth_ft.c
CommitLineData
6fc6879b
JM
1/*
2 * hostapd - IEEE 802.11r - Fast BSS Transition
98cd3d1c 3 * Copyright (c) 2004-2015, Jouni Malinen <j@w1.fi>
6fc6879b 4 *
0f3d578e
JM
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
6fc6879b
JM
7 */
8
6226e38d 9#include "utils/includes.h"
6fc6879b 10
6226e38d 11#include "utils/common.h"
692ec305 12#include "utils/eloop.h"
76967603 13#include "utils/list.h"
81f4f619
JM
14#include "common/ieee802_11_defs.h"
15#include "common/ieee802_11_common.h"
03da66bd 16#include "crypto/aes_wrap.h"
3642c431 17#include "crypto/random.h"
6226e38d 18#include "ap_config.h"
6fc6879b 19#include "ieee802_11.h"
1057d78e 20#include "wmm.h"
6226e38d 21#include "wpa_auth.h"
6fc6879b 22#include "wpa_auth_i.h"
6fc6879b
JM
23
24
4ec1fd8e 25#ifdef CONFIG_IEEE80211R_AP
6fc6879b 26
692ec305
JM
27static 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,
30 size_t resp_ies_len);
31
32
6fc6879b
JM
33static int wpa_ft_rrb_send(struct wpa_authenticator *wpa_auth, const u8 *dst,
34 const u8 *data, size_t data_len)
35{
cef8fac0 36 if (wpa_auth->cb->send_ether == NULL)
6fc6879b 37 return -1;
67ccef7e 38 wpa_printf(MSG_DEBUG, "FT: RRB send to " MACSTR, MAC2STR(dst));
cef8fac0
JB
39 return wpa_auth->cb->send_ether(wpa_auth->cb_ctx, dst, ETH_P_RRB,
40 data, data_len);
6fc6879b
JM
41}
42
43
44static int wpa_ft_action_send(struct wpa_authenticator *wpa_auth,
45 const u8 *dst, const u8 *data, size_t data_len)
46{
cef8fac0 47 if (wpa_auth->cb->send_ft_action == NULL)
6fc6879b 48 return -1;
cef8fac0
JB
49 return wpa_auth->cb->send_ft_action(wpa_auth->cb_ctx, dst,
50 data, data_len);
6fc6879b
JM
51}
52
53
96590564
MB
54static const u8 * wpa_ft_get_psk(struct wpa_authenticator *wpa_auth,
55 const u8 *addr, const u8 *p2p_dev_addr,
56 const u8 *prev_psk)
57{
cef8fac0 58 if (wpa_auth->cb->get_psk == NULL)
96590564 59 return NULL;
cef8fac0
JB
60 return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr,
61 prev_psk);
96590564
MB
62}
63
64
6fc6879b
JM
65static struct wpa_state_machine *
66wpa_ft_add_sta(struct wpa_authenticator *wpa_auth, const u8 *sta_addr)
67{
cef8fac0 68 if (wpa_auth->cb->add_sta == NULL)
6fc6879b 69 return NULL;
cef8fac0 70 return wpa_auth->cb->add_sta(wpa_auth->cb_ctx, sta_addr);
6fc6879b
JM
71}
72
73
88b32a99
SP
74static int wpa_ft_add_tspec(struct wpa_authenticator *wpa_auth,
75 const u8 *sta_addr,
76 u8 *tspec_ie, size_t tspec_ielen)
77{
cef8fac0 78 if (wpa_auth->cb->add_tspec == NULL) {
006309b5 79 wpa_printf(MSG_DEBUG, "FT: add_tspec is not initialized");
88b32a99
SP
80 return -1;
81 }
cef8fac0
JB
82 return wpa_auth->cb->add_tspec(wpa_auth->cb_ctx, sta_addr, tspec_ie,
83 tspec_ielen);
88b32a99
SP
84}
85
86
6fc6879b
JM
87int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len)
88{
89 u8 *pos = buf;
90 u8 capab;
91 if (len < 2 + sizeof(struct rsn_mdie))
92 return -1;
93
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;
d7956add
SP
98 capab = 0;
99 if (conf->ft_over_ds)
100 capab |= RSN_FT_CAPAB_FT_OVER_DS;
6fc6879b
JM
101 *pos++ = capab;
102
103 return pos - buf;
104}
105
106
86dfabb8
JM
107int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id,
108 size_t r0kh_id_len,
109 const u8 *anonce, const u8 *snonce,
110 u8 *buf, size_t len, const u8 *subelem,
111 size_t subelem_len)
6fc6879b
JM
112{
113 u8 *pos = buf, *ielen;
114 struct rsn_ftie *hdr;
115
116 if (len < 2 + sizeof(*hdr) + 2 + FT_R1KH_ID_LEN + 2 + r0kh_id_len +
117 subelem_len)
118 return -1;
119
120 *pos++ = WLAN_EID_FAST_BSS_TRANSITION;
121 ielen = pos++;
122
123 hdr = (struct rsn_ftie *) pos;
124 os_memset(hdr, 0, sizeof(*hdr));
125 pos += sizeof(*hdr);
126 WPA_PUT_LE16(hdr->mic_control, 0);
127 if (anonce)
128 os_memcpy(hdr->anonce, anonce, WPA_NONCE_LEN);
129 if (snonce)
130 os_memcpy(hdr->snonce, snonce, WPA_NONCE_LEN);
131
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;
137
138 if (r0kh_id) {
139 *pos++ = FTIE_SUBELEM_R0KH_ID;
140 *pos++ = r0kh_id_len;
141 os_memcpy(pos, r0kh_id, r0kh_id_len);
142 pos += r0kh_id_len;
143 }
144
145 if (subelem) {
146 os_memcpy(pos, subelem, subelem_len);
147 pos += subelem_len;
148 }
149
150 *ielen = pos - buf - 2;
151
152 return pos - buf;
153}
154
155
156struct wpa_ft_pmk_r0_sa {
157 struct wpa_ft_pmk_r0_sa *next;
158 u8 pmk_r0[PMK_LEN];
159 u8 pmk_r0_name[WPA_PMK_NAME_LEN];
160 u8 spa[ETH_ALEN];
1b484d60 161 int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
6fc6879b
JM
162 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
163 int pmk_r1_pushed;
164};
165
166struct wpa_ft_pmk_r1_sa {
167 struct wpa_ft_pmk_r1_sa *next;
168 u8 pmk_r1[PMK_LEN];
169 u8 pmk_r1_name[WPA_PMK_NAME_LEN];
170 u8 spa[ETH_ALEN];
1b484d60 171 int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
6fc6879b
JM
172 /* TODO: expiration, identity, radius_class, EAP type, VLAN ID */
173};
174
175struct wpa_ft_pmk_cache {
176 struct wpa_ft_pmk_r0_sa *pmk_r0;
177 struct wpa_ft_pmk_r1_sa *pmk_r1;
178};
179
180struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void)
181{
182 struct wpa_ft_pmk_cache *cache;
183
184 cache = os_zalloc(sizeof(*cache));
185
186 return cache;
187}
188
189
190void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache)
191{
192 struct wpa_ft_pmk_r0_sa *r0, *r0prev;
193 struct wpa_ft_pmk_r1_sa *r1, *r1prev;
194
195 r0 = cache->pmk_r0;
196 while (r0) {
197 r0prev = r0;
198 r0 = r0->next;
199 os_memset(r0prev->pmk_r0, 0, PMK_LEN);
200 os_free(r0prev);
201 }
202
203 r1 = cache->pmk_r1;
204 while (r1) {
205 r1prev = r1;
206 r1 = r1->next;
207 os_memset(r1prev->pmk_r1, 0, PMK_LEN);
208 os_free(r1prev);
209 }
210
211 os_free(cache);
212}
213
214
215static int wpa_ft_store_pmk_r0(struct wpa_authenticator *wpa_auth,
216 const u8 *spa, const u8 *pmk_r0,
1b484d60 217 const u8 *pmk_r0_name, int pairwise)
6fc6879b
JM
218{
219 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
220 struct wpa_ft_pmk_r0_sa *r0;
221
222 /* TODO: add expiration and limit on number of entries in cache */
223
224 r0 = os_zalloc(sizeof(*r0));
225 if (r0 == NULL)
226 return -1;
227
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);
1b484d60 231 r0->pairwise = pairwise;
6fc6879b
JM
232
233 r0->next = cache->pmk_r0;
234 cache->pmk_r0 = r0;
235
236 return 0;
237}
238
239
240static int wpa_ft_fetch_pmk_r0(struct wpa_authenticator *wpa_auth,
241 const u8 *spa, const u8 *pmk_r0_name,
1b484d60 242 u8 *pmk_r0, int *pairwise)
6fc6879b
JM
243{
244 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
245 struct wpa_ft_pmk_r0_sa *r0;
246
247 r0 = cache->pmk_r0;
248 while (r0) {
249 if (os_memcmp(r0->spa, spa, ETH_ALEN) == 0 &&
870834a1
JM
250 os_memcmp_const(r0->pmk_r0_name, pmk_r0_name,
251 WPA_PMK_NAME_LEN) == 0) {
6fc6879b 252 os_memcpy(pmk_r0, r0->pmk_r0, PMK_LEN);
1b484d60
JM
253 if (pairwise)
254 *pairwise = r0->pairwise;
6fc6879b
JM
255 return 0;
256 }
257
258 r0 = r0->next;
259 }
260
261 return -1;
262}
263
264
265static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
266 const u8 *spa, const u8 *pmk_r1,
1b484d60 267 const u8 *pmk_r1_name, int pairwise)
6fc6879b
JM
268{
269 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
270 struct wpa_ft_pmk_r1_sa *r1;
271
272 /* TODO: add expiration and limit on number of entries in cache */
273
274 r1 = os_zalloc(sizeof(*r1));
275 if (r1 == NULL)
276 return -1;
277
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);
1b484d60 281 r1->pairwise = pairwise;
6fc6879b
JM
282
283 r1->next = cache->pmk_r1;
284 cache->pmk_r1 = r1;
285
286 return 0;
287}
288
289
290static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
291 const u8 *spa, const u8 *pmk_r1_name,
1b484d60 292 u8 *pmk_r1, int *pairwise)
6fc6879b
JM
293{
294 struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
295 struct wpa_ft_pmk_r1_sa *r1;
296
297 r1 = cache->pmk_r1;
298 while (r1) {
299 if (os_memcmp(r1->spa, spa, ETH_ALEN) == 0 &&
870834a1
JM
300 os_memcmp_const(r1->pmk_r1_name, pmk_r1_name,
301 WPA_PMK_NAME_LEN) == 0) {
6fc6879b 302 os_memcpy(pmk_r1, r1->pmk_r1, PMK_LEN);
1b484d60
JM
303 if (pairwise)
304 *pairwise = r1->pairwise;
6fc6879b
JM
305 return 0;
306 }
307
308 r1 = r1->next;
309 }
310
311 return -1;
312}
313
314
692ec305
JM
315static 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)
6fc6879b
JM
318{
319 struct ft_remote_r0kh *r0kh;
320 struct ft_r0kh_r1kh_pull_frame frame, f;
321
692ec305 322 r0kh = sm->wpa_auth->conf.r0kh_list;
6fc6879b 323 while (r0kh) {
692ec305 324 if (r0kh->id_len == sm->r0kh_id_len &&
870834a1
JM
325 os_memcmp_const(r0kh->id, sm->r0kh_id, sm->r0kh_id_len) ==
326 0)
6fc6879b
JM
327 break;
328 r0kh = r0kh->next;
329 }
692ec305
JM
330 if (r0kh == NULL) {
331 wpa_hexdump(MSG_DEBUG, "FT: Did not find R0KH-ID",
332 sm->r0kh_id, sm->r0kh_id_len);
6fc6879b 333 return -1;
692ec305 334 }
6fc6879b
JM
335
336 wpa_printf(MSG_DEBUG, "FT: Send PMK-R1 pull request to remote R0KH "
337 "address " MACSTR, MAC2STR(r0kh->addr));
338
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);
692ec305 343 os_memcpy(frame.ap_address, sm->wpa_auth->addr, ETH_ALEN);
6fc6879b
JM
344
345 /* aes_wrap() does not support inplace encryption, so use a temporary
346 * buffer for the data. */
692ec305 347 if (random_get_bytes(f.nonce, FT_R0KH_R1KH_PULL_NONCE_LEN)) {
6fc6879b
JM
348 wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
349 "nonce");
350 return -1;
351 }
692ec305
JM
352 os_memcpy(sm->ft_pending_pull_nonce, f.nonce,
353 FT_R0KH_R1KH_PULL_NONCE_LEN);
6fc6879b 354 os_memcpy(f.pmk_r0_name, pmk_r0_name, WPA_PMK_NAME_LEN);
692ec305
JM
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);
5bcd5c5a 357 os_memset(f.pad, 0, sizeof(f.pad));
6fc6879b 358
eefec1e4
JM
359 if (aes_wrap(r0kh->key, sizeof(r0kh->key),
360 (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
6fc6879b
JM
361 f.nonce, frame.nonce) < 0)
362 return -1;
363
692ec305
JM
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)
367 return -1;
368
369 wpa_ft_rrb_send(sm->wpa_auth, r0kh->addr, (u8 *) &frame, sizeof(frame));
6fc6879b
JM
370
371 return 0;
372}
373
374
375int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk,
98cd3d1c 376 struct wpa_ptk *ptk)
6fc6879b
JM
377{
378 u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
26e23750 379 u8 pmk_r1[PMK_LEN];
6fc6879b
JM
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;
96590564 387 int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
6fc6879b 388
6fc6879b
JM
389 if (sm->xxkey_len == 0) {
390 wpa_printf(MSG_DEBUG, "FT: XXKey not available for key "
391 "derivation");
392 return -1;
393 }
394
395 wpa_derive_pmk_r0(sm->xxkey, sm->xxkey_len, ssid, ssid_len, mdid,
396 r0kh, r0kh_len, sm->addr, pmk_r0, pmk_r0_name);
397 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R0", pmk_r0, PMK_LEN);
398 wpa_hexdump(MSG_DEBUG, "FT: PMKR0Name", pmk_r0_name, WPA_PMK_NAME_LEN);
96590564
MB
399 if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
400 wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_name,
401 sm->pairwise);
6fc6879b
JM
402
403 wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr,
26e23750 404 pmk_r1, sm->pmk_r1_name);
6fc6879b 405 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", pmk_r1, PMK_LEN);
26e23750
JM
406 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", sm->pmk_r1_name,
407 WPA_PMK_NAME_LEN);
96590564
MB
408 if (!psk_local || !wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt))
409 wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1,
410 sm->pmk_r1_name, sm->pairwise);
6fc6879b 411
98cd3d1c
JM
412 return wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
413 sm->wpa_auth->addr, sm->pmk_r1_name,
414 ptk, ptk_name, sm->wpa_key_mgmt, sm->pairwise);
6fc6879b
JM
415}
416
417
418static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth,
419 const u8 *addr, int idx, u8 *seq)
420{
cef8fac0 421 if (wpa_auth->cb->get_seqnum == NULL)
6fc6879b 422 return -1;
cef8fac0 423 return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq);
6fc6879b
JM
424}
425
426
427static u8 * wpa_ft_gtk_subelem(struct wpa_state_machine *sm, size_t *len)
428{
429 u8 *subelem;
430 struct wpa_group *gsm = sm->group;
431 size_t subelem_len, pad_len;
432 const u8 *key;
433 size_t key_len;
434 u8 keybuf[32];
435
436 key_len = gsm->GTK_len;
437 if (key_len > sizeof(keybuf))
438 return NULL;
439
440 /*
441 * Pad key for AES Key Wrap if it is not multiple of 8 bytes or is less
442 * than 16 bytes.
443 */
444 pad_len = key_len % 8;
445 if (pad_len)
446 pad_len = 8 - pad_len;
447 if (key_len + pad_len < 16)
448 pad_len += 8;
5bfc46bb 449 if (pad_len && key_len < sizeof(keybuf)) {
6fc6879b
JM
450 os_memcpy(keybuf, gsm->GTK[gsm->GN - 1], key_len);
451 os_memset(keybuf + key_len, 0, pad_len);
452 keybuf[key_len] = 0xdd;
453 key_len += pad_len;
454 key = keybuf;
455 } else
456 key = gsm->GTK[gsm->GN - 1];
457
458 /*
39eb4d08 459 * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] |
6fc6879b
JM
460 * Key[5..32].
461 */
39eb4d08 462 subelem_len = 13 + key_len + 8;
6fc6879b
JM
463 subelem = os_zalloc(subelem_len);
464 if (subelem == NULL)
465 return NULL;
466
467 subelem[0] = FTIE_SUBELEM_GTK;
39eb4d08
JM
468 subelem[1] = 11 + key_len + 8;
469 /* Key ID in B0-B1 of Key Info */
470 WPA_PUT_LE16(&subelem[2], gsm->GN & 0x03);
471 subelem[4] = gsm->GTK_len;
472 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, subelem + 5);
98cd3d1c
JM
473 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, key_len / 8, key,
474 subelem + 13)) {
6fc6879b
JM
475 os_free(subelem);
476 return NULL;
477 }
478
479 *len = subelem_len;
480 return subelem;
481}
482
483
b27f13ed
JM
484#ifdef CONFIG_IEEE80211W
485static u8 * wpa_ft_igtk_subelem(struct wpa_state_machine *sm, size_t *len)
486{
487 u8 *subelem, *pos;
488 struct wpa_group *gsm = sm->group;
489 size_t subelem_len;
490
ff89afb7
JM
491 /* Sub-elem ID[1] | Length[1] | KeyID[2] | IPN[6] | Key Length[1] |
492 * Key[16+8] */
493 subelem_len = 1 + 1 + 2 + 6 + 1 + WPA_IGTK_LEN + 8;
b27f13ed
JM
494 subelem = os_zalloc(subelem_len);
495 if (subelem == NULL)
496 return NULL;
497
498 pos = subelem;
499 *pos++ = FTIE_SUBELEM_IGTK;
500 *pos++ = subelem_len - 2;
501 WPA_PUT_LE16(pos, gsm->GN_igtk);
502 pos += 2;
9008a3e4 503 wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos);
b27f13ed 504 pos += 6;
ff89afb7 505 *pos++ = WPA_IGTK_LEN;
98cd3d1c 506 if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, WPA_IGTK_LEN / 8,
b27f13ed
JM
507 gsm->IGTK[gsm->GN_igtk - 4], pos)) {
508 os_free(subelem);
509 return NULL;
510 }
511
512 *len = subelem_len;
513 return subelem;
514}
515#endif /* CONFIG_IEEE80211W */
516
517
88b32a99
SP
518static u8 * wpa_ft_process_rdie(struct wpa_state_machine *sm,
519 u8 *pos, u8 *end, u8 id, u8 descr_count,
f238cf9f
JM
520 const u8 *ies, size_t ies_len)
521{
522 struct ieee802_11_elems parse;
523 struct rsn_rdie *rdie;
524
525 wpa_printf(MSG_DEBUG, "FT: Resource Request: id=%d descr_count=%d",
526 id, descr_count);
527 wpa_hexdump(MSG_MSGDUMP, "FT: Resource descriptor IE(s)",
528 ies, ies_len);
529
530 if (end - pos < (int) sizeof(*rdie)) {
531 wpa_printf(MSG_ERROR, "FT: Not enough room for response RDIE");
532 return pos;
533 }
534
535 *pos++ = WLAN_EID_RIC_DATA;
536 *pos++ = sizeof(*rdie);
537 rdie = (struct rsn_rdie *) pos;
538 rdie->id = id;
539 rdie->descr_count = 0;
540 rdie->status_code = host_to_le16(WLAN_STATUS_SUCCESS);
541 pos += sizeof(*rdie);
542
543 if (ieee802_11_parse_elems((u8 *) ies, ies_len, &parse, 1) ==
544 ParseFailed) {
545 wpa_printf(MSG_DEBUG, "FT: Failed to parse request IEs");
546 rdie->status_code =
547 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
548 return pos;
549 }
550
25310368 551 if (parse.wmm_tspec) {
f238cf9f 552 struct wmm_tspec_element *tspec;
f238cf9f
JM
553
554 if (parse.wmm_tspec_len + 2 < (int) sizeof(*tspec)) {
555 wpa_printf(MSG_DEBUG, "FT: Too short WMM TSPEC IE "
556 "(%d)", (int) parse.wmm_tspec_len);
557 rdie->status_code =
558 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
559 return pos;
560 }
561 if (end - pos < (int) sizeof(*tspec)) {
562 wpa_printf(MSG_ERROR, "FT: Not enough room for "
563 "response TSPEC");
564 rdie->status_code =
565 host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
566 return pos;
567 }
568 tspec = (struct wmm_tspec_element *) pos;
569 os_memcpy(tspec, parse.wmm_tspec - 2, sizeof(*tspec));
25310368
JM
570 }
571
572#ifdef NEED_AP_MLME
573 if (parse.wmm_tspec && sm->wpa_auth->conf.ap_mlme) {
574 int res;
575
576 res = wmm_process_tspec((struct wmm_tspec_element *) pos);
f238cf9f
JM
577 wpa_printf(MSG_DEBUG, "FT: ADDTS processing result: %d", res);
578 if (res == WMM_ADDTS_STATUS_INVALID_PARAMETERS)
579 rdie->status_code =
580 host_to_le16(WLAN_STATUS_INVALID_PARAMETERS);
581 else if (res == WMM_ADDTS_STATUS_REFUSED)
582 rdie->status_code =
583 host_to_le16(WLAN_STATUS_REQUEST_DECLINED);
584 else {
585 /* TSPEC accepted; include updated TSPEC in response */
586 rdie->descr_count = 1;
25310368 587 pos += sizeof(struct wmm_tspec_element);
f238cf9f
JM
588 }
589 return pos;
590 }
fe6bdb77 591#endif /* NEED_AP_MLME */
f238cf9f 592
88b32a99 593 if (parse.wmm_tspec && !sm->wpa_auth->conf.ap_mlme) {
88b32a99
SP
594 int res;
595
88b32a99 596 res = wpa_ft_add_tspec(sm->wpa_auth, sm->addr, pos,
25310368 597 sizeof(struct wmm_tspec_element));
88b32a99
SP
598 if (res >= 0) {
599 if (res)
600 rdie->status_code = host_to_le16(res);
601 else {
602 /* TSPEC accepted; include updated TSPEC in
603 * response */
006309b5 604 rdie->descr_count = 1;
25310368 605 pos += sizeof(struct wmm_tspec_element);
88b32a99
SP
606 }
607 return pos;
608 }
609 }
610
f238cf9f
JM
611 wpa_printf(MSG_DEBUG, "FT: No supported resource requested");
612 rdie->status_code = host_to_le16(WLAN_STATUS_UNSPECIFIED_FAILURE);
613 return pos;
614}
615
616
88b32a99
SP
617static u8 * wpa_ft_process_ric(struct wpa_state_machine *sm, u8 *pos, u8 *end,
618 const u8 *ric, size_t ric_len)
f238cf9f
JM
619{
620 const u8 *rpos, *start;
621 const struct rsn_rdie *rdie;
622
623 wpa_hexdump(MSG_MSGDUMP, "FT: RIC Request", ric, ric_len);
624
625 rpos = ric;
626 while (rpos + sizeof(*rdie) < ric + ric_len) {
627 if (rpos[0] != WLAN_EID_RIC_DATA || rpos[1] < sizeof(*rdie) ||
628 rpos + 2 + rpos[1] > ric + ric_len)
629 break;
630 rdie = (const struct rsn_rdie *) (rpos + 2);
631 rpos += 2 + rpos[1];
632 start = rpos;
633
634 while (rpos + 2 <= ric + ric_len &&
635 rpos + 2 + rpos[1] <= ric + ric_len) {
636 if (rpos[0] == WLAN_EID_RIC_DATA)
637 break;
638 rpos += 2 + rpos[1];
639 }
88b32a99 640 pos = wpa_ft_process_rdie(sm, pos, end, rdie->id,
f238cf9f
JM
641 rdie->descr_count,
642 start, rpos - start);
643 }
644
645 return pos;
646}
647
648
6fc6879b 649u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos,
f238cf9f
JM
650 size_t max_len, int auth_alg,
651 const u8 *req_ies, size_t req_ies_len)
6fc6879b 652{
738a1cb2
JM
653 u8 *end, *mdie, *ftie, *rsnie = NULL, *r0kh_id, *subelem = NULL;
654 size_t mdie_len, ftie_len, rsnie_len = 0, r0kh_id_len, subelem_len = 0;
6fc6879b
JM
655 int res;
656 struct wpa_auth_config *conf;
657 struct rsn_ftie *_ftie;
f238cf9f
JM
658 struct wpa_ft_ies parse;
659 u8 *ric_start;
6e80516a 660 u8 *anonce, *snonce;
6fc6879b
JM
661
662 if (sm == NULL)
663 return pos;
664
665 conf = &sm->wpa_auth->conf;
666
aa189ac9 667 if (!wpa_key_mgmt_ft(sm->wpa_key_mgmt))
6fc6879b
JM
668 return pos;
669
670 end = pos + max_len;
671
738a1cb2
JM
672 if (auth_alg == WLAN_AUTH_FT) {
673 /*
674 * RSN (only present if this is a Reassociation Response and
675 * part of a fast BSS transition)
676 */
677 res = wpa_write_rsn_ie(conf, pos, end - pos, sm->pmk_r1_name);
678 if (res < 0)
679 return pos;
680 rsnie = pos;
681 rsnie_len = res;
682 pos += res;
683 }
6fc6879b
JM
684
685 /* Mobility Domain Information */
686 res = wpa_write_mdie(conf, pos, end - pos);
687 if (res < 0)
688 return pos;
689 mdie = pos;
690 mdie_len = res;
691 pos += res;
692
693 /* Fast BSS Transition Information */
694 if (auth_alg == WLAN_AUTH_FT) {
695 subelem = wpa_ft_gtk_subelem(sm, &subelem_len);
696 r0kh_id = sm->r0kh_id;
697 r0kh_id_len = sm->r0kh_id_len;
6e80516a
JM
698 anonce = sm->ANonce;
699 snonce = sm->SNonce;
b27f13ed
JM
700#ifdef CONFIG_IEEE80211W
701 if (sm->mgmt_frame_prot) {
702 u8 *igtk;
703 size_t igtk_len;
704 u8 *nbuf;
705 igtk = wpa_ft_igtk_subelem(sm, &igtk_len);
706 if (igtk == NULL) {
707 os_free(subelem);
708 return pos;
709 }
710 nbuf = os_realloc(subelem, subelem_len + igtk_len);
711 if (nbuf == NULL) {
712 os_free(subelem);
713 os_free(igtk);
714 return pos;
715 }
716 subelem = nbuf;
717 os_memcpy(subelem + subelem_len, igtk, igtk_len);
718 subelem_len += igtk_len;
719 os_free(igtk);
720 }
721#endif /* CONFIG_IEEE80211W */
6fc6879b
JM
722 } else {
723 r0kh_id = conf->r0_key_holder;
724 r0kh_id_len = conf->r0_key_holder_len;
6e80516a
JM
725 anonce = NULL;
726 snonce = NULL;
6fc6879b 727 }
6e80516a 728 res = wpa_write_ftie(conf, r0kh_id, r0kh_id_len, anonce, snonce, pos,
6fc6879b
JM
729 end - pos, subelem, subelem_len);
730 os_free(subelem);
731 if (res < 0)
732 return pos;
733 ftie = pos;
734 ftie_len = res;
735 pos += res;
736
737 _ftie = (struct rsn_ftie *) (ftie + 2);
1f6e69e0
JM
738 if (auth_alg == WLAN_AUTH_FT)
739 _ftie->mic_control[1] = 3; /* Information element count */
f238cf9f
JM
740
741 ric_start = pos;
742 if (wpa_ft_parse_ies(req_ies, req_ies_len, &parse) == 0 && parse.ric) {
88b32a99
SP
743 pos = wpa_ft_process_ric(sm, pos, end, parse.ric,
744 parse.ric_len);
1f6e69e0
JM
745 if (auth_alg == WLAN_AUTH_FT)
746 _ftie->mic_control[1] +=
747 ieee802_11_ie_count(ric_start,
748 pos - ric_start);
f238cf9f
JM
749 }
750 if (ric_start == pos)
751 ric_start = NULL;
752
1f6e69e0 753 if (auth_alg == WLAN_AUTH_FT &&
98cd3d1c
JM
754 wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr,
755 sm->wpa_auth->addr, 6,
6fc6879b 756 mdie, mdie_len, ftie, ftie_len,
f238cf9f
JM
757 rsnie, rsnie_len,
758 ric_start, ric_start ? pos - ric_start : 0,
759 _ftie->mic) < 0)
6fc6879b
JM
760 wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
761
e44bd28c
JM
762 os_free(sm->assoc_resp_ftie);
763 sm->assoc_resp_ftie = os_malloc(ftie_len);
764 if (sm->assoc_resp_ftie)
765 os_memcpy(sm->assoc_resp_ftie, ftie, ftie_len);
766
6fc6879b
JM
767 return pos;
768}
769
770
6fc6879b
JM
771static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth,
772 int vlan_id,
71934751 773 enum wpa_alg alg, const u8 *addr, int idx,
6fc6879b
JM
774 u8 *key, size_t key_len)
775{
cef8fac0 776 if (wpa_auth->cb->set_key == NULL)
6fc6879b 777 return -1;
cef8fac0
JB
778 return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx,
779 key, key_len);
6fc6879b
JM
780}
781
782
0e84c254 783void wpa_ft_install_ptk(struct wpa_state_machine *sm)
6fc6879b 784{
71934751 785 enum wpa_alg alg;
6fc6879b
JM
786 int klen;
787
788 /* MLME-SETKEYS.request(PTK) */
c3550295
JM
789 alg = wpa_cipher_to_alg(sm->pairwise);
790 klen = wpa_cipher_key_len(sm->pairwise);
791 if (!wpa_cipher_valid_pairwise(sm->pairwise)) {
0e84c254
JM
792 wpa_printf(MSG_DEBUG, "FT: Unknown pairwise alg 0x%x - skip "
793 "PTK configuration", sm->pairwise);
6fc6879b 794 return;
0e84c254 795 }
6fc6879b
JM
796
797 /* FIX: add STA entry to kernel/driver here? The set_key will fail
798 * most likely without this.. At the moment, STA entry is added only
0e84c254
JM
799 * after association has been completed. This function will be called
800 * again after association to get the PTK configured, but that could be
801 * optimized by adding the STA entry earlier.
6fc6879b
JM
802 */
803 if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0,
98cd3d1c 804 sm->PTK.tk, klen))
6fc6879b
JM
805 return;
806
807 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
808 sm->pairwise_set = TRUE;
809}
810
811
96590564
MB
812/* Derive PMK-R1 from PSK, check all available PSK */
813static int wpa_ft_psk_pmk_r1(struct wpa_state_machine *sm,
814 const u8 *req_pmk_r1_name,
815 u8 *out_pmk_r1, int *out_pairwise)
816{
817 const u8 *pmk = NULL;
818 u8 pmk_r0[PMK_LEN], pmk_r0_name[WPA_PMK_NAME_LEN];
819 u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
820 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
821 const u8 *mdid = wpa_auth->conf.mobility_domain;
822 const u8 *r0kh = sm->r0kh_id;
823 size_t r0kh_len = sm->r0kh_id_len;
824 const u8 *r1kh = wpa_auth->conf.r1_key_holder;
825 const u8 *ssid = wpa_auth->conf.ssid;
826 size_t ssid_len = wpa_auth->conf.ssid_len;
827 int pairwise;
828
829 pairwise = sm->pairwise;
830
831 for (;;) {
832 pmk = wpa_ft_get_psk(wpa_auth, sm->addr, sm->p2p_dev_addr,
833 pmk);
834 if (pmk == NULL)
835 break;
836
837 wpa_derive_pmk_r0(pmk, PMK_LEN, ssid, ssid_len, mdid, r0kh,
838 r0kh_len, sm->addr, pmk_r0, pmk_r0_name);
839 wpa_derive_pmk_r1(pmk_r0, pmk_r0_name, r1kh, sm->addr,
840 pmk_r1, pmk_r1_name);
841
842 if (os_memcmp_const(pmk_r1_name, req_pmk_r1_name,
843 WPA_PMK_NAME_LEN) != 0)
844 continue;
845
846 /* We found a PSK that matches the requested pmk_r1_name */
847 wpa_printf(MSG_DEBUG,
848 "FT: Found PSK to generate PMK-R1 locally");
849 os_memcpy(out_pmk_r1, pmk_r1, PMK_LEN);
850 if (out_pairwise)
851 *out_pairwise = pairwise;
852 return 0;
853 }
854
855 wpa_printf(MSG_DEBUG,
856 "FT: Did not find PSK to generate PMK-R1 locally");
857 return -1;
858}
859
860
861/* Detect the configuration the station asked for.
862 * Required to detect FT-PSK and pairwise cipher.
863 */
864static int wpa_ft_set_key_mgmt(struct wpa_state_machine *sm,
865 struct wpa_ft_ies *parse)
866{
867 int key_mgmt, ciphers;
868
869 if (sm->wpa_key_mgmt)
870 return 0;
871
872 key_mgmt = parse->key_mgmt & sm->wpa_auth->conf.wpa_key_mgmt;
873 if (!key_mgmt) {
874 wpa_printf(MSG_DEBUG, "FT: Invalid key mgmt (0x%x) from "
875 MACSTR, parse->key_mgmt, MAC2STR(sm->addr));
876 return -1;
877 }
878 if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X)
879 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X;
880 else if (key_mgmt & WPA_KEY_MGMT_FT_PSK)
881 sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK;
882 ciphers = parse->pairwise_cipher & sm->wpa_auth->conf.rsn_pairwise;
883 if (!ciphers) {
884 wpa_printf(MSG_DEBUG, "FT: Invalid pairwise cipher (0x%x) from "
885 MACSTR,
886 parse->pairwise_cipher, MAC2STR(sm->addr));
887 return -1;
888 }
889 sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0);
890
891 return 0;
892}
893
894
692ec305 895static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
6fc6879b
JM
896 const u8 *ies, size_t ies_len,
897 u8 **resp_ies, size_t *resp_ies_len)
898{
899 struct rsn_mdie *mdie;
900 struct rsn_ftie *ftie;
901 u8 pmk_r1[PMK_LEN], pmk_r1_name[WPA_PMK_NAME_LEN];
902 u8 ptk_name[WPA_PMK_NAME_LEN];
903 struct wpa_auth_config *conf;
904 struct wpa_ft_ies parse;
98cd3d1c 905 size_t buflen;
6fc6879b
JM
906 int ret;
907 u8 *pos, *end;
1b484d60 908 int pairwise;
6fc6879b
JM
909
910 *resp_ies = NULL;
911 *resp_ies_len = 0;
912
913 sm->pmk_r1_name_valid = 0;
914 conf = &sm->wpa_auth->conf;
915
916 wpa_hexdump(MSG_DEBUG, "FT: Received authentication frame IEs",
917 ies, ies_len);
918
919 if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
920 wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
921 return WLAN_STATUS_UNSPECIFIED_FAILURE;
922 }
923
924 mdie = (struct rsn_mdie *) parse.mdie;
925 if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
926 os_memcmp(mdie->mobility_domain,
927 sm->wpa_auth->conf.mobility_domain,
928 MOBILITY_DOMAIN_ID_LEN) != 0) {
929 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
930 return WLAN_STATUS_INVALID_MDIE;
931 }
932
933 ftie = (struct rsn_ftie *) parse.ftie;
934 if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
935 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
936 return WLAN_STATUS_INVALID_FTIE;
937 }
938
939 os_memcpy(sm->SNonce, ftie->snonce, WPA_NONCE_LEN);
940
941 if (parse.r0kh_id == NULL) {
942 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE - no R0KH-ID");
943 return WLAN_STATUS_INVALID_FTIE;
944 }
945
946 wpa_hexdump(MSG_DEBUG, "FT: STA R0KH-ID",
947 parse.r0kh_id, parse.r0kh_id_len);
948 os_memcpy(sm->r0kh_id, parse.r0kh_id, parse.r0kh_id_len);
949 sm->r0kh_id_len = parse.r0kh_id_len;
950
951 if (parse.rsn_pmkid == NULL) {
952 wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE");
953 return WLAN_STATUS_INVALID_PMKID;
954 }
955
96590564
MB
956 if (wpa_ft_set_key_mgmt(sm, &parse) < 0)
957 return WLAN_STATUS_UNSPECIFIED_FAILURE;
958
6fc6879b
JM
959 wpa_hexdump(MSG_DEBUG, "FT: Requested PMKR0Name",
960 parse.rsn_pmkid, WPA_PMK_NAME_LEN);
961 wpa_derive_pmk_r1_name(parse.rsn_pmkid,
962 sm->wpa_auth->conf.r1_key_holder, sm->addr,
963 pmk_r1_name);
964 wpa_hexdump(MSG_DEBUG, "FT: Derived requested PMKR1Name",
965 pmk_r1_name, WPA_PMK_NAME_LEN);
966
96590564
MB
967 if (conf->ft_psk_generate_local &&
968 wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) {
969 if (wpa_ft_psk_pmk_r1(sm, pmk_r1_name, pmk_r1, &pairwise) < 0)
970 return WLAN_STATUS_INVALID_PMKID;
971 } else if (wpa_ft_fetch_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1_name,
972 pmk_r1, &pairwise) < 0) {
692ec305 973 if (wpa_ft_pull_pmk_r1(sm, ies, ies_len, parse.rsn_pmkid) < 0) {
6fc6879b
JM
974 wpa_printf(MSG_DEBUG, "FT: Did not have matching "
975 "PMK-R1 and unknown R0KH-ID");
976 return WLAN_STATUS_INVALID_PMKID;
977 }
978
692ec305 979 return -1; /* Status pending */
6fc6879b
JM
980 }
981
982 wpa_hexdump_key(MSG_DEBUG, "FT: Selected PMK-R1", pmk_r1, PMK_LEN);
983 sm->pmk_r1_name_valid = 1;
984 os_memcpy(sm->pmk_r1_name, pmk_r1_name, WPA_PMK_NAME_LEN);
985
3642c431 986 if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
6fc6879b
JM
987 wpa_printf(MSG_DEBUG, "FT: Failed to get random data for "
988 "ANonce");
989 return WLAN_STATUS_UNSPECIFIED_FAILURE;
990 }
991
992 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
993 sm->SNonce, WPA_NONCE_LEN);
994 wpa_hexdump(MSG_DEBUG, "FT: Generated ANonce",
995 sm->ANonce, WPA_NONCE_LEN);
996
98cd3d1c
JM
997 if (wpa_pmk_r1_to_ptk(pmk_r1, sm->SNonce, sm->ANonce, sm->addr,
998 sm->wpa_auth->addr, pmk_r1_name,
999 &sm->PTK, ptk_name, sm->wpa_key_mgmt,
1000 pairwise) < 0)
1001 return WLAN_STATUS_UNSPECIFIED_FAILURE;
6fc6879b 1002
0e84c254 1003 sm->pairwise = pairwise;
3d4d2348 1004 sm->PTK_valid = TRUE;
6fc6879b
JM
1005 wpa_ft_install_ptk(sm);
1006
1007 buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
1008 2 + FT_R1KH_ID_LEN + 200;
1009 *resp_ies = os_zalloc(buflen);
1010 if (*resp_ies == NULL) {
1011 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1012 }
1013
1014 pos = *resp_ies;
1015 end = *resp_ies + buflen;
1016
1017 ret = wpa_write_rsn_ie(conf, pos, end - pos, parse.rsn_pmkid);
1018 if (ret < 0) {
1019 os_free(*resp_ies);
1020 *resp_ies = NULL;
1021 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1022 }
1023 pos += ret;
1024
1025 ret = wpa_write_mdie(conf, pos, end - pos);
1026 if (ret < 0) {
1027 os_free(*resp_ies);
1028 *resp_ies = NULL;
1029 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1030 }
1031 pos += ret;
1032
1033 ret = wpa_write_ftie(conf, parse.r0kh_id, parse.r0kh_id_len,
1034 sm->ANonce, sm->SNonce, pos, end - pos, NULL, 0);
1035 if (ret < 0) {
1036 os_free(*resp_ies);
1037 *resp_ies = NULL;
1038 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1039 }
1040 pos += ret;
1041
1042 *resp_ies_len = pos - *resp_ies;
1043
1044 return WLAN_STATUS_SUCCESS;
1045}
1046
1047
1048void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid,
1049 u16 auth_transaction, const u8 *ies, size_t ies_len,
1050 void (*cb)(void *ctx, const u8 *dst, const u8 *bssid,
1051 u16 auth_transaction, u16 status,
1052 const u8 *ies, size_t ies_len),
1053 void *ctx)
1054{
1055 u16 status;
1056 u8 *resp_ies;
1057 size_t resp_ies_len;
692ec305 1058 int res;
6fc6879b
JM
1059
1060 if (sm == NULL) {
1061 wpa_printf(MSG_DEBUG, "FT: Received authentication frame, but "
1062 "WPA SM not available");
1063 return;
1064 }
1065
1066 wpa_printf(MSG_DEBUG, "FT: Received authentication frame: STA=" MACSTR
1067 " BSSID=" MACSTR " transaction=%d",
1068 MAC2STR(sm->addr), MAC2STR(bssid), auth_transaction);
692ec305
JM
1069 sm->ft_pending_cb = cb;
1070 sm->ft_pending_cb_ctx = ctx;
1071 sm->ft_pending_auth_transaction = auth_transaction;
1072 res = wpa_ft_process_auth_req(sm, ies, ies_len, &resp_ies,
1073 &resp_ies_len);
1074 if (res < 0) {
1075 wpa_printf(MSG_DEBUG, "FT: Callback postponed until response is available");
1076 return;
1077 }
1078 status = res;
6fc6879b
JM
1079
1080 wpa_printf(MSG_DEBUG, "FT: FT authentication response: dst=" MACSTR
1081 " auth_transaction=%d status=%d",
1082 MAC2STR(sm->addr), auth_transaction + 1, status);
1083 wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);
1084 cb(ctx, sm->addr, bssid, auth_transaction + 1, status,
1085 resp_ies, resp_ies_len);
1086 os_free(resp_ies);
1087}
1088
1089
1090u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies,
1091 size_t ies_len)
1092{
1093 struct wpa_ft_ies parse;
1094 struct rsn_mdie *mdie;
1095 struct rsn_ftie *ftie;
98cd3d1c
JM
1096 u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN];
1097 size_t mic_len = 16;
8aaf894d 1098 unsigned int count;
6fc6879b
JM
1099
1100 if (sm == NULL)
1101 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1102
1103 wpa_hexdump(MSG_DEBUG, "FT: Reassoc Req IEs", ies, ies_len);
1104
1105 if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
1106 wpa_printf(MSG_DEBUG, "FT: Failed to parse FT IEs");
1107 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1108 }
1109
1110 if (parse.rsn == NULL) {
1111 wpa_printf(MSG_DEBUG, "FT: No RSNIE in Reassoc Req");
1112 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1113 }
1114
1115 if (parse.rsn_pmkid == NULL) {
1116 wpa_printf(MSG_DEBUG, "FT: No PMKID in RSNIE");
1117 return WLAN_STATUS_INVALID_PMKID;
1118 }
1119
870834a1
JM
1120 if (os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN)
1121 != 0) {
6fc6879b
JM
1122 wpa_printf(MSG_DEBUG, "FT: PMKID in Reassoc Req did not match "
1123 "with the PMKR1Name derived from auth request");
1124 return WLAN_STATUS_INVALID_PMKID;
1125 }
1126
1127 mdie = (struct rsn_mdie *) parse.mdie;
1128 if (mdie == NULL || parse.mdie_len < sizeof(*mdie) ||
1129 os_memcmp(mdie->mobility_domain,
1130 sm->wpa_auth->conf.mobility_domain,
1131 MOBILITY_DOMAIN_ID_LEN) != 0) {
1132 wpa_printf(MSG_DEBUG, "FT: Invalid MDIE");
1133 return WLAN_STATUS_INVALID_MDIE;
1134 }
1135
1136 ftie = (struct rsn_ftie *) parse.ftie;
1137 if (ftie == NULL || parse.ftie_len < sizeof(*ftie)) {
1138 wpa_printf(MSG_DEBUG, "FT: Invalid FTIE");
1139 return WLAN_STATUS_INVALID_FTIE;
1140 }
1141
0ae145cd
JM
1142 if (os_memcmp(ftie->snonce, sm->SNonce, WPA_NONCE_LEN) != 0) {
1143 wpa_printf(MSG_DEBUG, "FT: SNonce mismatch in FTIE");
1144 wpa_hexdump(MSG_DEBUG, "FT: Received SNonce",
1145 ftie->snonce, WPA_NONCE_LEN);
1146 wpa_hexdump(MSG_DEBUG, "FT: Expected SNonce",
1147 sm->SNonce, WPA_NONCE_LEN);
0a63635e 1148 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
1149 }
1150
1151 if (os_memcmp(ftie->anonce, sm->ANonce, WPA_NONCE_LEN) != 0) {
1152 wpa_printf(MSG_DEBUG, "FT: ANonce mismatch in FTIE");
1153 wpa_hexdump(MSG_DEBUG, "FT: Received ANonce",
1154 ftie->anonce, WPA_NONCE_LEN);
1155 wpa_hexdump(MSG_DEBUG, "FT: Expected ANonce",
1156 sm->ANonce, WPA_NONCE_LEN);
0a63635e 1157 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
1158 }
1159
1160
1161 if (parse.r0kh_id == NULL) {
1162 wpa_printf(MSG_DEBUG, "FT: No R0KH-ID subelem in FTIE");
0a63635e 1163 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
1164 }
1165
1166 if (parse.r0kh_id_len != sm->r0kh_id_len ||
870834a1
JM
1167 os_memcmp_const(parse.r0kh_id, sm->r0kh_id, parse.r0kh_id_len) != 0)
1168 {
0ae145cd
JM
1169 wpa_printf(MSG_DEBUG, "FT: R0KH-ID in FTIE did not match with "
1170 "the current R0KH-ID");
1171 wpa_hexdump(MSG_DEBUG, "FT: R0KH-ID in FTIE",
1172 parse.r0kh_id, parse.r0kh_id_len);
1173 wpa_hexdump(MSG_DEBUG, "FT: The current R0KH-ID",
1174 sm->r0kh_id, sm->r0kh_id_len);
0a63635e 1175 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
1176 }
1177
1178 if (parse.r1kh_id == NULL) {
1179 wpa_printf(MSG_DEBUG, "FT: No R1KH-ID subelem in FTIE");
0a63635e 1180 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
1181 }
1182
870834a1
JM
1183 if (os_memcmp_const(parse.r1kh_id, sm->wpa_auth->conf.r1_key_holder,
1184 FT_R1KH_ID_LEN) != 0) {
0ae145cd
JM
1185 wpa_printf(MSG_DEBUG, "FT: Unknown R1KH-ID used in "
1186 "ReassocReq");
1187 wpa_hexdump(MSG_DEBUG, "FT: R1KH-ID in FTIE",
1188 parse.r1kh_id, FT_R1KH_ID_LEN);
1189 wpa_hexdump(MSG_DEBUG, "FT: Expected R1KH-ID",
1190 sm->wpa_auth->conf.r1_key_holder, FT_R1KH_ID_LEN);
0a63635e 1191 return WLAN_STATUS_INVALID_FTIE;
0ae145cd
JM
1192 }
1193
1194 if (parse.rsn_pmkid == NULL ||
870834a1
JM
1195 os_memcmp_const(parse.rsn_pmkid, sm->pmk_r1_name, WPA_PMK_NAME_LEN))
1196 {
0ae145cd
JM
1197 wpa_printf(MSG_DEBUG, "FT: No matching PMKR1Name (PMKID) in "
1198 "RSNIE (pmkid=%d)", !!parse.rsn_pmkid);
0a63635e 1199 return WLAN_STATUS_INVALID_PMKID;
0ae145cd
JM
1200 }
1201
8aaf894d
JM
1202 count = 3;
1203 if (parse.ric)
c284b461 1204 count += ieee802_11_ie_count(parse.ric, parse.ric_len);
8aaf894d
JM
1205 if (ftie->mic_control[1] != count) {
1206 wpa_printf(MSG_DEBUG, "FT: Unexpected IE count in MIC "
1207 "Control: received %u expected %u",
1208 ftie->mic_control[1], count);
0a63635e 1209 return WLAN_STATUS_UNSPECIFIED_FAILURE;
8aaf894d
JM
1210 }
1211
98cd3d1c
JM
1212 if (wpa_ft_mic(sm->PTK.kck, sm->PTK.kck_len, sm->addr,
1213 sm->wpa_auth->addr, 5,
6fc6879b
JM
1214 parse.mdie - 2, parse.mdie_len + 2,
1215 parse.ftie - 2, parse.ftie_len + 2,
babfbf15
JM
1216 parse.rsn - 2, parse.rsn_len + 2,
1217 parse.ric, parse.ric_len,
6fc6879b
JM
1218 mic) < 0) {
1219 wpa_printf(MSG_DEBUG, "FT: Failed to calculate MIC");
1220 return WLAN_STATUS_UNSPECIFIED_FAILURE;
1221 }
1222
98cd3d1c 1223 if (os_memcmp_const(mic, ftie->mic, mic_len) != 0) {
6fc6879b 1224 wpa_printf(MSG_DEBUG, "FT: Invalid MIC in FTIE");
88b32a99
SP
1225 wpa_printf(MSG_DEBUG, "FT: addr=" MACSTR " auth_addr=" MACSTR,
1226 MAC2STR(sm->addr), MAC2STR(sm->wpa_auth->addr));
98cd3d1c
JM
1227 wpa_hexdump(MSG_MSGDUMP, "FT: Received MIC",
1228 ftie->mic, mic_len);
1229 wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, mic_len);
88b32a99
SP
1230 wpa_hexdump(MSG_MSGDUMP, "FT: MDIE",
1231 parse.mdie - 2, parse.mdie_len + 2);
1232 wpa_hexdump(MSG_MSGDUMP, "FT: FTIE",
1233 parse.ftie - 2, parse.ftie_len + 2);
1234 wpa_hexdump(MSG_MSGDUMP, "FT: RSN",
1235 parse.rsn - 2, parse.rsn_len + 2);
6fc6879b
JM
1236 return WLAN_STATUS_INVALID_FTIE;
1237 }
1238
1239 return WLAN_STATUS_SUCCESS;
1240}
1241
1242
1243int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len)
1244{
1245 const u8 *sta_addr, *target_ap;
1246 const u8 *ies;
1247 size_t ies_len;
1248 u8 action;
1249 struct ft_rrb_frame *frame;
1250
1251 if (sm == NULL)
1252 return -1;
1253
1254 /*
1255 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1256 * FT Request action frame body[variable]
1257 */
1258
1259 if (len < 14) {
1260 wpa_printf(MSG_DEBUG, "FT: Too short FT Action frame "
1261 "(len=%lu)", (unsigned long) len);
1262 return -1;
1263 }
1264
1265 action = data[1];
1266 sta_addr = data + 2;
1267 target_ap = data + 8;
1268 ies = data + 14;
1269 ies_len = len - 14;
1270
1271 wpa_printf(MSG_DEBUG, "FT: Received FT Action frame (STA=" MACSTR
1272 " Target AP=" MACSTR " Action=%d)",
1273 MAC2STR(sta_addr), MAC2STR(target_ap), action);
1274
1275 if (os_memcmp(sta_addr, sm->addr, ETH_ALEN) != 0) {
1276 wpa_printf(MSG_DEBUG, "FT: Mismatch in FT Action STA address: "
1277 "STA=" MACSTR " STA-Address=" MACSTR,
1278 MAC2STR(sm->addr), MAC2STR(sta_addr));
1279 return -1;
1280 }
1281
1282 /*
1283 * Do some sanity checking on the target AP address (not own and not
1284 * broadcast. This could be extended to filter based on a list of known
1285 * APs in the MD (if such a list were configured).
1286 */
1287 if ((target_ap[0] & 0x01) ||
1288 os_memcmp(target_ap, sm->wpa_auth->addr, ETH_ALEN) == 0) {
1289 wpa_printf(MSG_DEBUG, "FT: Invalid Target AP in FT Action "
1290 "frame");
1291 return -1;
1292 }
1293
1294 wpa_hexdump(MSG_MSGDUMP, "FT: Action frame body", ies, ies_len);
1295
1940559e
JM
1296 if (!sm->wpa_auth->conf.ft_over_ds) {
1297 wpa_printf(MSG_DEBUG, "FT: Over-DS option disabled - reject");
1298 return -1;
1299 }
1300
6fc6879b
JM
1301 /* RRB - Forward action frame to the target AP */
1302 frame = os_malloc(sizeof(*frame) + len);
2c48211c
JM
1303 if (frame == NULL)
1304 return -1;
6fc6879b
JM
1305 frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
1306 frame->packet_type = FT_PACKET_REQUEST;
1307 frame->action_length = host_to_le16(len);
1308 os_memcpy(frame->ap_address, sm->wpa_auth->addr, ETH_ALEN);
1309 os_memcpy(frame + 1, data, len);
1310
1311 wpa_ft_rrb_send(sm->wpa_auth, target_ap, (u8 *) frame,
1312 sizeof(*frame) + len);
1313 os_free(frame);
1314
1315 return 0;
1316}
1317
1318
692ec305
JM
1319static void wpa_ft_rrb_rx_request_cb(void *ctx, const u8 *dst, const u8 *bssid,
1320 u16 auth_transaction, u16 resp,
1321 const u8 *ies, size_t ies_len)
1322{
1323 struct wpa_state_machine *sm = ctx;
1324 wpa_printf(MSG_DEBUG, "FT: Over-the-DS RX request cb for " MACSTR,
1325 MAC2STR(sm->addr));
1326 wpa_ft_send_rrb_auth_resp(sm, sm->ft_pending_current_ap, sm->addr,
1327 WLAN_STATUS_SUCCESS, ies, ies_len);
1328}
1329
1330
6fc6879b
JM
1331static int wpa_ft_rrb_rx_request(struct wpa_authenticator *wpa_auth,
1332 const u8 *current_ap, const u8 *sta_addr,
1333 const u8 *body, size_t len)
1334{
1335 struct wpa_state_machine *sm;
1336 u16 status;
692ec305
JM
1337 u8 *resp_ies;
1338 size_t resp_ies_len;
1339 int res;
6fc6879b
JM
1340
1341 sm = wpa_ft_add_sta(wpa_auth, sta_addr);
1342 if (sm == NULL) {
1343 wpa_printf(MSG_DEBUG, "FT: Failed to add new STA based on "
1344 "RRB Request");
1345 return -1;
1346 }
1347
1348 wpa_hexdump(MSG_MSGDUMP, "FT: RRB Request Frame body", body, len);
1349
692ec305
JM
1350 sm->ft_pending_cb = wpa_ft_rrb_rx_request_cb;
1351 sm->ft_pending_cb_ctx = sm;
1352 os_memcpy(sm->ft_pending_current_ap, current_ap, ETH_ALEN);
1353 res = wpa_ft_process_auth_req(sm, body, len, &resp_ies,
1354 &resp_ies_len);
1355 if (res < 0) {
1356 wpa_printf(MSG_DEBUG, "FT: No immediate response available - wait for pull response");
1357 return 0;
1358 }
1359 status = res;
1360
1361 res = wpa_ft_send_rrb_auth_resp(sm, current_ap, sta_addr, status,
1362 resp_ies, resp_ies_len);
1363 os_free(resp_ies);
1364 return res;
1365}
1366
1367
1368static int wpa_ft_send_rrb_auth_resp(struct wpa_state_machine *sm,
1369 const u8 *current_ap, const u8 *sta_addr,
1370 u16 status, const u8 *resp_ies,
1371 size_t resp_ies_len)
1372{
1373 struct wpa_authenticator *wpa_auth = sm->wpa_auth;
1374 size_t rlen;
1375 struct ft_rrb_frame *frame;
1376 u8 *pos;
6fc6879b
JM
1377
1378 wpa_printf(MSG_DEBUG, "FT: RRB authentication response: STA=" MACSTR
1379 " CurrentAP=" MACSTR " status=%d",
1380 MAC2STR(sm->addr), MAC2STR(current_ap), status);
1381 wpa_hexdump(MSG_DEBUG, "FT: Response IEs", resp_ies, resp_ies_len);
1382
1383 /* RRB - Forward action frame response to the Current AP */
1384
1385 /*
1386 * data: Category[1] Action[1] STA_Address[6] Target_AP_Address[6]
1387 * Status_Code[2] FT Request action frame body[variable]
1388 */
1389 rlen = 2 + 2 * ETH_ALEN + 2 + resp_ies_len;
1390
1391 frame = os_malloc(sizeof(*frame) + rlen);
692ec305 1392 if (frame == NULL)
2c48211c 1393 return -1;
6fc6879b
JM
1394 frame->frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
1395 frame->packet_type = FT_PACKET_RESPONSE;
1396 frame->action_length = host_to_le16(rlen);
1397 os_memcpy(frame->ap_address, wpa_auth->addr, ETH_ALEN);
1398 pos = (u8 *) (frame + 1);
1399 *pos++ = WLAN_ACTION_FT;
1400 *pos++ = 2; /* Action: Response */
1401 os_memcpy(pos, sta_addr, ETH_ALEN);
1402 pos += ETH_ALEN;
1403 os_memcpy(pos, wpa_auth->addr, ETH_ALEN);
1404 pos += ETH_ALEN;
1405 WPA_PUT_LE16(pos, status);
1406 pos += 2;
692ec305 1407 if (resp_ies)
6fc6879b 1408 os_memcpy(pos, resp_ies, resp_ies_len);
6fc6879b
JM
1409
1410 wpa_ft_rrb_send(wpa_auth, current_ap, (u8 *) frame,
1411 sizeof(*frame) + rlen);
1412 os_free(frame);
1413
1414 return 0;
1415}
1416
1417
1418static int wpa_ft_rrb_rx_pull(struct wpa_authenticator *wpa_auth,
1419 const u8 *src_addr,
1420 const u8 *data, size_t data_len)
1421{
76967603
JM
1422 struct ft_r0kh_r1kh_pull_frame f;
1423 const u8 *crypt;
1424 u8 *plain;
6fc6879b
JM
1425 struct ft_remote_r1kh *r1kh;
1426 struct ft_r0kh_r1kh_resp_frame resp, r;
1427 u8 pmk_r0[PMK_LEN];
1b484d60 1428 int pairwise;
6fc6879b
JM
1429
1430 wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull");
1431
76967603 1432 if (data_len < sizeof(f))
6fc6879b
JM
1433 return -1;
1434
1435 r1kh = wpa_auth->conf.r1kh_list;
1436 while (r1kh) {
1437 if (os_memcmp(r1kh->addr, src_addr, ETH_ALEN) == 0)
1438 break;
1439 r1kh = r1kh->next;
1440 }
1441 if (r1kh == NULL) {
1442 wpa_printf(MSG_DEBUG, "FT: No matching R1KH address found for "
1443 "PMK-R1 pull source address " MACSTR,
1444 MAC2STR(src_addr));
1445 return -1;
1446 }
1447
76967603
JM
1448 crypt = data + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce);
1449 os_memset(&f, 0, sizeof(f));
1450 plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_pull_frame, nonce);
6fc6879b
JM
1451 /* aes_unwrap() does not support inplace decryption, so use a temporary
1452 * buffer for the data. */
eefec1e4
JM
1453 if (aes_unwrap(r1kh->key, sizeof(r1kh->key),
1454 (FT_R0KH_R1KH_PULL_DATA_LEN + 7) / 8,
76967603 1455 crypt, plain) < 0) {
6fc6879b
JM
1456 wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
1457 "request from " MACSTR, MAC2STR(src_addr));
1458 return -1;
1459 }
1460
1461 wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
1462 f.nonce, sizeof(f.nonce));
1463 wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR0Name",
1464 f.pmk_r0_name, WPA_PMK_NAME_LEN);
692ec305 1465 wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
6fc6879b
JM
1466 MACSTR, MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id));
1467
1468 os_memset(&resp, 0, sizeof(resp));
1469 resp.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
1470 resp.packet_type = FT_PACKET_R0KH_R1KH_RESP;
1471 resp.data_length = host_to_le16(FT_R0KH_R1KH_RESP_DATA_LEN);
1472 os_memcpy(resp.ap_address, wpa_auth->addr, ETH_ALEN);
1473
1474 /* aes_wrap() does not support inplace encryption, so use a temporary
1475 * buffer for the data. */
1476 os_memcpy(r.nonce, f.nonce, sizeof(f.nonce));
1477 os_memcpy(r.r1kh_id, f.r1kh_id, FT_R1KH_ID_LEN);
1478 os_memcpy(r.s1kh_id, f.s1kh_id, ETH_ALEN);
1b484d60
JM
1479 if (wpa_ft_fetch_pmk_r0(wpa_auth, f.s1kh_id, f.pmk_r0_name, pmk_r0,
1480 &pairwise) < 0) {
6fc6879b
JM
1481 wpa_printf(MSG_DEBUG, "FT: No matching PMKR0Name found for "
1482 "PMK-R1 pull");
1483 return -1;
1484 }
1485
1486 wpa_derive_pmk_r1(pmk_r0, f.pmk_r0_name, f.r1kh_id, f.s1kh_id,
1487 r.pmk_r1, r.pmk_r1_name);
1488 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", r.pmk_r1, PMK_LEN);
1489 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", r.pmk_r1_name,
1490 WPA_PMK_NAME_LEN);
e9501a07 1491 r.pairwise = host_to_le16(pairwise);
5bcd5c5a 1492 os_memset(r.pad, 0, sizeof(r.pad));
6fc6879b 1493
eefec1e4
JM
1494 if (aes_wrap(r1kh->key, sizeof(r1kh->key),
1495 (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
6fc6879b
JM
1496 r.nonce, resp.nonce) < 0) {
1497 os_memset(pmk_r0, 0, PMK_LEN);
1498 return -1;
1499 }
1500
1501 os_memset(pmk_r0, 0, PMK_LEN);
1502
1503 wpa_ft_rrb_send(wpa_auth, src_addr, (u8 *) &resp, sizeof(resp));
1504
1505 return 0;
1506}
1507
1508
692ec305
JM
1509static void ft_pull_resp_cb_finish(void *eloop_ctx, void *timeout_ctx)
1510{
1511 struct wpa_state_machine *sm = eloop_ctx;
1512 int res;
1513 u8 *resp_ies;
1514 size_t resp_ies_len;
1515 u16 status;
1516
1517 res = wpa_ft_process_auth_req(sm, wpabuf_head(sm->ft_pending_req_ies),
1518 wpabuf_len(sm->ft_pending_req_ies),
1519 &resp_ies, &resp_ies_len);
1520 wpabuf_free(sm->ft_pending_req_ies);
1521 sm->ft_pending_req_ies = NULL;
1522 if (res < 0)
1523 res = WLAN_STATUS_UNSPECIFIED_FAILURE;
1524 status = res;
1525 wpa_printf(MSG_DEBUG, "FT: Postponed auth callback result for " MACSTR
1526 " - status %u", MAC2STR(sm->addr), status);
1527
1528 sm->ft_pending_cb(sm->ft_pending_cb_ctx, sm->addr, sm->wpa_auth->addr,
1529 sm->ft_pending_auth_transaction + 1, status,
1530 resp_ies, resp_ies_len);
1531 os_free(resp_ies);
1532}
1533
1534
1535static int ft_pull_resp_cb(struct wpa_state_machine *sm, void *ctx)
1536{
1537 struct ft_r0kh_r1kh_resp_frame *frame = ctx;
1538
1539 if (os_memcmp(frame->s1kh_id, sm->addr, ETH_ALEN) != 0)
1540 return 0;
1541 if (os_memcmp(frame->nonce, sm->ft_pending_pull_nonce,
1542 FT_R0KH_R1KH_PULL_NONCE_LEN) != 0)
1543 return 0;
1544 if (sm->ft_pending_cb == NULL || sm->ft_pending_req_ies == NULL)
1545 return 0;
1546
1547 wpa_printf(MSG_DEBUG, "FT: Response to a pending pull request for "
1548 MACSTR " - process from timeout", MAC2STR(sm->addr));
1549 eloop_register_timeout(0, 0, ft_pull_resp_cb_finish, sm, NULL);
1550 return 1;
1551}
1552
1553
6fc6879b
JM
1554static int wpa_ft_rrb_rx_resp(struct wpa_authenticator *wpa_auth,
1555 const u8 *src_addr,
1556 const u8 *data, size_t data_len)
1557{
76967603
JM
1558 struct ft_r0kh_r1kh_resp_frame f;
1559 const u8 *crypt;
1560 u8 *plain;
6fc6879b 1561 struct ft_remote_r0kh *r0kh;
692ec305 1562 int pairwise, res;
6fc6879b
JM
1563
1564 wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 pull response");
1565
76967603 1566 if (data_len < sizeof(f))
6fc6879b
JM
1567 return -1;
1568
1569 r0kh = wpa_auth->conf.r0kh_list;
1570 while (r0kh) {
1571 if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
1572 break;
1573 r0kh = r0kh->next;
1574 }
1575 if (r0kh == NULL) {
1576 wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
1577 "PMK-R0 pull response source address " MACSTR,
1578 MAC2STR(src_addr));
1579 return -1;
1580 }
1581
76967603
JM
1582 crypt = data + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce);
1583 os_memset(&f, 0, sizeof(f));
1584 plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_resp_frame, nonce);
6fc6879b
JM
1585 /* aes_unwrap() does not support inplace decryption, so use a temporary
1586 * buffer for the data. */
eefec1e4
JM
1587 if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
1588 (FT_R0KH_R1KH_RESP_DATA_LEN + 7) / 8,
76967603 1589 crypt, plain) < 0) {
6fc6879b
JM
1590 wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 pull "
1591 "response from " MACSTR, MAC2STR(src_addr));
1592 return -1;
1593 }
1594
870834a1
JM
1595 if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
1596 FT_R1KH_ID_LEN) != 0) {
6fc6879b
JM
1597 wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull response did not use a "
1598 "matching R1KH-ID");
1599 return -1;
1600 }
1601
1b484d60 1602 pairwise = le_to_host16(f.pairwise);
6fc6879b
JM
1603 wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - nonce",
1604 f.nonce, sizeof(f.nonce));
692ec305 1605 wpa_printf(MSG_DEBUG, "FT: PMK-R1 pull - R1KH-ID=" MACSTR " S1KH-ID="
1b484d60
JM
1606 MACSTR " pairwise=0x%x",
1607 MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
6fc6879b
JM
1608 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 pull - PMK-R1",
1609 f.pmk_r1, PMK_LEN);
1610 wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 pull - PMKR1Name",
1611 f.pmk_r1_name, WPA_PMK_NAME_LEN);
1612
692ec305
JM
1613 res = wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
1614 pairwise);
1615 wpa_printf(MSG_DEBUG, "FT: Look for pending pull request");
1616 wpa_auth_for_each_sta(wpa_auth, ft_pull_resp_cb, &f);
6fc6879b
JM
1617 os_memset(f.pmk_r1, 0, PMK_LEN);
1618
692ec305 1619 return res ? 0 : -1;
6fc6879b
JM
1620}
1621
1622
1623static int wpa_ft_rrb_rx_push(struct wpa_authenticator *wpa_auth,
1624 const u8 *src_addr,
1625 const u8 *data, size_t data_len)
1626{
76967603
JM
1627 struct ft_r0kh_r1kh_push_frame f;
1628 const u8 *crypt;
1629 u8 *plain;
6fc6879b
JM
1630 struct ft_remote_r0kh *r0kh;
1631 struct os_time now;
1632 os_time_t tsend;
1b484d60 1633 int pairwise;
6fc6879b
JM
1634
1635 wpa_printf(MSG_DEBUG, "FT: Received PMK-R1 push");
1636
76967603 1637 if (data_len < sizeof(f))
6fc6879b
JM
1638 return -1;
1639
1640 r0kh = wpa_auth->conf.r0kh_list;
1641 while (r0kh) {
1642 if (os_memcmp(r0kh->addr, src_addr, ETH_ALEN) == 0)
1643 break;
1644 r0kh = r0kh->next;
1645 }
1646 if (r0kh == NULL) {
1647 wpa_printf(MSG_DEBUG, "FT: No matching R0KH address found for "
1648 "PMK-R0 push source address " MACSTR,
1649 MAC2STR(src_addr));
1650 return -1;
1651 }
1652
76967603
JM
1653 crypt = data + offsetof(struct ft_r0kh_r1kh_push_frame, timestamp);
1654 os_memset(&f, 0, sizeof(f));
1655 plain = ((u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame,
1656 timestamp);
6fc6879b
JM
1657 /* aes_unwrap() does not support inplace decryption, so use a temporary
1658 * buffer for the data. */
eefec1e4
JM
1659 if (aes_unwrap(r0kh->key, sizeof(r0kh->key),
1660 (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
76967603 1661 crypt, plain) < 0) {
6fc6879b
JM
1662 wpa_printf(MSG_DEBUG, "FT: Failed to decrypt PMK-R1 push from "
1663 MACSTR, MAC2STR(src_addr));
1664 return -1;
1665 }
1666
1667 os_get_time(&now);
1668 tsend = WPA_GET_LE32(f.timestamp);
1669 if ((now.sec > tsend && now.sec - tsend > 60) ||
1670 (now.sec < tsend && tsend - now.sec > 60)) {
1671 wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not have a valid "
1672 "timestamp: sender time %d own time %d\n",
1673 (int) tsend, (int) now.sec);
1674 return -1;
1675 }
1676
870834a1
JM
1677 if (os_memcmp_const(f.r1kh_id, wpa_auth->conf.r1_key_holder,
1678 FT_R1KH_ID_LEN) != 0) {
6fc6879b
JM
1679 wpa_printf(MSG_DEBUG, "FT: PMK-R1 push did not use a matching "
1680 "R1KH-ID (received " MACSTR " own " MACSTR ")",
1681 MAC2STR(f.r1kh_id),
1682 MAC2STR(wpa_auth->conf.r1_key_holder));
1683 return -1;
1684 }
1685
1b484d60 1686 pairwise = le_to_host16(f.pairwise);
6fc6879b 1687 wpa_printf(MSG_DEBUG, "FT: PMK-R1 push - R1KH-ID=" MACSTR " S1KH-ID="
1b484d60
JM
1688 MACSTR " pairwise=0x%x",
1689 MAC2STR(f.r1kh_id), MAC2STR(f.s1kh_id), pairwise);
6fc6879b
JM
1690 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1 push - PMK-R1",
1691 f.pmk_r1, PMK_LEN);
1692 wpa_hexdump(MSG_DEBUG, "FT: PMK-R1 push - PMKR1Name",
1693 f.pmk_r1_name, WPA_PMK_NAME_LEN);
1694
1b484d60
JM
1695 wpa_ft_store_pmk_r1(wpa_auth, f.s1kh_id, f.pmk_r1, f.pmk_r1_name,
1696 pairwise);
6fc6879b
JM
1697 os_memset(f.pmk_r1, 0, PMK_LEN);
1698
1699 return 0;
1700}
1701
1702
1703int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
1704 const u8 *data, size_t data_len)
1705{
1706 struct ft_rrb_frame *frame;
1707 u16 alen;
1708 const u8 *pos, *end, *start;
1709 u8 action;
1710 const u8 *sta_addr, *target_ap_addr;
1711
1712 wpa_printf(MSG_DEBUG, "FT: RRB received frame from remote AP " MACSTR,
1713 MAC2STR(src_addr));
1714
1715 if (data_len < sizeof(*frame)) {
1716 wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (data_len=%lu)",
1717 (unsigned long) data_len);
1718 return -1;
1719 }
1720
1721 pos = data;
1722 frame = (struct ft_rrb_frame *) pos;
1723 pos += sizeof(*frame);
1724
1725 alen = le_to_host16(frame->action_length);
1726 wpa_printf(MSG_DEBUG, "FT: RRB frame - frame_type=%d packet_type=%d "
1727 "action_length=%d ap_address=" MACSTR,
1728 frame->frame_type, frame->packet_type, alen,
1729 MAC2STR(frame->ap_address));
1730
1731 if (frame->frame_type != RSN_REMOTE_FRAME_TYPE_FT_RRB) {
c1e033b0 1732 /* Discard frame per IEEE Std 802.11r-2008, 11A.10.3 */
6fc6879b
JM
1733 wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with "
1734 "unrecognized type %d", frame->frame_type);
1735 return -1;
1736 }
1737
1738 if (alen > data_len - sizeof(*frame)) {
1739 wpa_printf(MSG_DEBUG, "FT: RRB frame too short for action "
1740 "frame");
1741 return -1;
1742 }
1743
1744 if (frame->packet_type == FT_PACKET_R0KH_R1KH_PULL)
1745 return wpa_ft_rrb_rx_pull(wpa_auth, src_addr, data, data_len);
1746 if (frame->packet_type == FT_PACKET_R0KH_R1KH_RESP)
1747 return wpa_ft_rrb_rx_resp(wpa_auth, src_addr, data, data_len);
1748 if (frame->packet_type == FT_PACKET_R0KH_R1KH_PUSH)
1749 return wpa_ft_rrb_rx_push(wpa_auth, src_addr, data, data_len);
1750
1751 wpa_hexdump(MSG_MSGDUMP, "FT: RRB - FT Action frame", pos, alen);
1752
1753 if (alen < 1 + 1 + 2 * ETH_ALEN) {
1754 wpa_printf(MSG_DEBUG, "FT: Too short RRB frame (not enough "
1755 "room for Action Frame body); alen=%lu",
1756 (unsigned long) alen);
1757 return -1;
1758 }
1759 start = pos;
1760 end = pos + alen;
1761
1762 if (*pos != WLAN_ACTION_FT) {
1763 wpa_printf(MSG_DEBUG, "FT: Unexpected Action frame category "
1764 "%d", *pos);
1765 return -1;
1766 }
1767
1768 pos++;
1769 action = *pos++;
1770 sta_addr = pos;
1771 pos += ETH_ALEN;
1772 target_ap_addr = pos;
1773 pos += ETH_ALEN;
1774 wpa_printf(MSG_DEBUG, "FT: RRB Action Frame: action=%d sta_addr="
1775 MACSTR " target_ap_addr=" MACSTR,
1776 action, MAC2STR(sta_addr), MAC2STR(target_ap_addr));
1777
1778 if (frame->packet_type == FT_PACKET_REQUEST) {
1779 wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Request");
1780
1781 if (action != 1) {
1782 wpa_printf(MSG_DEBUG, "FT: Unexpected Action %d in "
1783 "RRB Request", action);
1784 return -1;
1785 }
1786
1787 if (os_memcmp(target_ap_addr, wpa_auth->addr, ETH_ALEN) != 0) {
1788 wpa_printf(MSG_DEBUG, "FT: Target AP address in the "
1789 "RRB Request does not match with own "
1790 "address");
1791 return -1;
1792 }
1793
1794 if (wpa_ft_rrb_rx_request(wpa_auth, frame->ap_address,
1795 sta_addr, pos, end - pos) < 0)
1796 return -1;
1797 } else if (frame->packet_type == FT_PACKET_RESPONSE) {
1798 u16 status_code;
1799
1800 if (end - pos < 2) {
1801 wpa_printf(MSG_DEBUG, "FT: Not enough room for status "
1802 "code in RRB Response");
1803 return -1;
1804 }
1805 status_code = WPA_GET_LE16(pos);
1806 pos += 2;
1807
1808 wpa_printf(MSG_DEBUG, "FT: FT Packet Type - Response "
1809 "(status_code=%d)", status_code);
1810
1811 if (wpa_ft_action_send(wpa_auth, sta_addr, start, alen) < 0)
1812 return -1;
1813 } else {
1814 wpa_printf(MSG_DEBUG, "FT: RRB discarded frame with unknown "
1815 "packet_type %d", frame->packet_type);
1816 return -1;
1817 }
1818
164a453f
JM
1819 if (end > pos) {
1820 wpa_hexdump(MSG_DEBUG, "FT: Ignore extra data in end",
1821 pos, end - pos);
1822 }
1823
6fc6879b
JM
1824 return 0;
1825}
1826
1827
1828static void wpa_ft_generate_pmk_r1(struct wpa_authenticator *wpa_auth,
1829 struct wpa_ft_pmk_r0_sa *pmk_r0,
1830 struct ft_remote_r1kh *r1kh,
1b484d60 1831 const u8 *s1kh_id, int pairwise)
6fc6879b
JM
1832{
1833 struct ft_r0kh_r1kh_push_frame frame, f;
1834 struct os_time now;
369d07af
JM
1835 const u8 *plain;
1836 u8 *crypt;
6fc6879b
JM
1837
1838 os_memset(&frame, 0, sizeof(frame));
1839 frame.frame_type = RSN_REMOTE_FRAME_TYPE_FT_RRB;
1840 frame.packet_type = FT_PACKET_R0KH_R1KH_PUSH;
1841 frame.data_length = host_to_le16(FT_R0KH_R1KH_PUSH_DATA_LEN);
1842 os_memcpy(frame.ap_address, wpa_auth->addr, ETH_ALEN);
1843
1844 /* aes_wrap() does not support inplace encryption, so use a temporary
1845 * buffer for the data. */
1846 os_memcpy(f.r1kh_id, r1kh->id, FT_R1KH_ID_LEN);
1847 os_memcpy(f.s1kh_id, s1kh_id, ETH_ALEN);
1848 os_memcpy(f.pmk_r0_name, pmk_r0->pmk_r0_name, WPA_PMK_NAME_LEN);
1849 wpa_derive_pmk_r1(pmk_r0->pmk_r0, pmk_r0->pmk_r0_name, r1kh->id,
1850 s1kh_id, f.pmk_r1, f.pmk_r1_name);
1851 wpa_printf(MSG_DEBUG, "FT: R1KH-ID " MACSTR, MAC2STR(r1kh->id));
1852 wpa_hexdump_key(MSG_DEBUG, "FT: PMK-R1", f.pmk_r1, PMK_LEN);
1853 wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name", f.pmk_r1_name,
1854 WPA_PMK_NAME_LEN);
1855 os_get_time(&now);
1856 WPA_PUT_LE32(f.timestamp, now.sec);
e9501a07 1857 f.pairwise = host_to_le16(pairwise);
5bcd5c5a 1858 os_memset(f.pad, 0, sizeof(f.pad));
369d07af
JM
1859 plain = ((const u8 *) &f) + offsetof(struct ft_r0kh_r1kh_push_frame,
1860 timestamp);
1861 crypt = ((u8 *) &frame) + offsetof(struct ft_r0kh_r1kh_push_frame,
1862 timestamp);
eefec1e4
JM
1863 if (aes_wrap(r1kh->key, sizeof(r1kh->key),
1864 (FT_R0KH_R1KH_PUSH_DATA_LEN + 7) / 8,
369d07af 1865 plain, crypt) < 0)
6fc6879b
JM
1866 return;
1867
1868 wpa_ft_rrb_send(wpa_auth, r1kh->addr, (u8 *) &frame, sizeof(frame));
1869}
1870
1871
1872void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr)
1873{
1874 struct wpa_ft_pmk_r0_sa *r0;
1875 struct ft_remote_r1kh *r1kh;
1876
1877 if (!wpa_auth->conf.pmk_r1_push)
1878 return;
1879
1880 r0 = wpa_auth->ft_pmk_cache->pmk_r0;
1881 while (r0) {
1882 if (os_memcmp(r0->spa, addr, ETH_ALEN) == 0)
1883 break;
1884 r0 = r0->next;
1885 }
1886
1887 if (r0 == NULL || r0->pmk_r1_pushed)
1888 return;
1889 r0->pmk_r1_pushed = 1;
1890
1891 wpa_printf(MSG_DEBUG, "FT: Deriving and pushing PMK-R1 keys to R1KHs "
1892 "for STA " MACSTR, MAC2STR(addr));
1893
1894 r1kh = wpa_auth->conf.r1kh_list;
1895 while (r1kh) {
1b484d60 1896 wpa_ft_generate_pmk_r1(wpa_auth, r0, r1kh, addr, r0->pairwise);
6fc6879b
JM
1897 r1kh = r1kh->next;
1898 }
1899}
1900
4ec1fd8e 1901#endif /* CONFIG_IEEE80211R_AP */