blob: 2b3332ea36bff16b2f7296feb71803c2d60d9276 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
3 * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#ifdef CONFIG_PEERKEY
18
19#include "common.h"
20#include "eloop.h"
21#include "crypto/sha1.h"
22#include "crypto/sha256.h"
23#include "crypto/random.h"
24#include "common/ieee802_11_defs.h"
25#include "wpa.h"
26#include "wpa_i.h"
27#include "wpa_ie.h"
28#include "peerkey.h"
29
30
31static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
32{
33 os_memcpy(pos, ie, ie_len);
34 return pos + ie_len;
35}
36
37
38static u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len)
39{
40 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
41 *pos++ = RSN_SELECTOR_LEN + data_len;
42 RSN_SELECTOR_PUT(pos, kde);
43 pos += RSN_SELECTOR_LEN;
44 os_memcpy(pos, data, data_len);
45 pos += data_len;
46 return pos;
47}
48
49
50static void wpa_supplicant_smk_timeout(void *eloop_ctx, void *timeout_ctx)
51{
52#if 0
53 struct wpa_sm *sm = eloop_ctx;
54 struct wpa_peerkey *peerkey = timeout_ctx;
55#endif
56 /* TODO: time out SMK and any STK that was generated using this SMK */
57}
58
59
60static void wpa_supplicant_peerkey_free(struct wpa_sm *sm,
61 struct wpa_peerkey *peerkey)
62{
63 eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
64 os_free(peerkey);
65}
66
67
68static int wpa_supplicant_send_smk_error(struct wpa_sm *sm, const u8 *dst,
69 const u8 *peer,
70 u16 mui, u16 error_type, int ver)
71{
72 size_t rlen;
73 struct wpa_eapol_key *err;
74 struct rsn_error_kde error;
75 u8 *rbuf, *pos;
76 size_t kde_len;
77 u16 key_info;
78
79 kde_len = 2 + RSN_SELECTOR_LEN + sizeof(error);
80 if (peer)
81 kde_len += 2 + RSN_SELECTOR_LEN + ETH_ALEN;
82
83 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
84 NULL, sizeof(*err) + kde_len, &rlen,
85 (void *) &err);
86 if (rbuf == NULL)
87 return -1;
88
89 err->type = EAPOL_KEY_TYPE_RSN;
90 key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
91 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_ERROR |
92 WPA_KEY_INFO_REQUEST;
93 WPA_PUT_BE16(err->key_info, key_info);
94 WPA_PUT_BE16(err->key_length, 0);
95 os_memcpy(err->replay_counter, sm->request_counter,
96 WPA_REPLAY_COUNTER_LEN);
97 inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
98
99 WPA_PUT_BE16(err->key_data_length, (u16) kde_len);
100 pos = (u8 *) (err + 1);
101
102 if (peer) {
103 /* Peer MAC Address KDE */
104 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
105 }
106
107 /* Error KDE */
108 error.mui = host_to_be16(mui);
109 error.error_type = host_to_be16(error_type);
110 wpa_add_kde(pos, RSN_KEY_DATA_ERROR, (u8 *) &error, sizeof(error));
111
112 if (peer) {
113 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error (peer "
114 MACSTR " mui %d error_type %d)",
115 MAC2STR(peer), mui, error_type);
116 } else {
117 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK Error "
118 "(mui %d error_type %d)", mui, error_type);
119 }
120
121 wpa_eapol_key_send(sm, sm->ptk.kck, ver, dst, ETH_P_EAPOL,
122 rbuf, rlen, err->key_mic);
123
124 return 0;
125}
126
127
128static int wpa_supplicant_send_smk_m3(struct wpa_sm *sm,
129 const unsigned char *src_addr,
130 const struct wpa_eapol_key *key,
131 int ver, struct wpa_peerkey *peerkey)
132{
133 size_t rlen;
134 struct wpa_eapol_key *reply;
135 u8 *rbuf, *pos;
136 size_t kde_len;
137 u16 key_info;
138
139 /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
140 kde_len = peerkey->rsnie_p_len +
141 2 + RSN_SELECTOR_LEN + ETH_ALEN +
142 2 + RSN_SELECTOR_LEN + WPA_NONCE_LEN;
143
144 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY,
145 NULL, sizeof(*reply) + kde_len, &rlen,
146 (void *) &reply);
147 if (rbuf == NULL)
148 return -1;
149
150 reply->type = EAPOL_KEY_TYPE_RSN;
151 key_info = ver | WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
152 WPA_KEY_INFO_SECURE;
153 WPA_PUT_BE16(reply->key_info, key_info);
154 WPA_PUT_BE16(reply->key_length, 0);
155 os_memcpy(reply->replay_counter, key->replay_counter,
156 WPA_REPLAY_COUNTER_LEN);
157
158 os_memcpy(reply->key_nonce, peerkey->pnonce, WPA_NONCE_LEN);
159
160 WPA_PUT_BE16(reply->key_data_length, (u16) kde_len);
161 pos = (u8 *) (reply + 1);
162
163 /* Peer RSN IE */
164 pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
165
166 /* Initiator MAC Address KDE */
167 pos = wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peerkey->addr, ETH_ALEN);
168
169 /* Initiator Nonce */
170 wpa_add_kde(pos, RSN_KEY_DATA_NONCE, peerkey->inonce, WPA_NONCE_LEN);
171
172 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key SMK M3");
173 wpa_eapol_key_send(sm, sm->ptk.kck, ver, src_addr, ETH_P_EAPOL,
174 rbuf, rlen, reply->key_mic);
175
176 return 0;
177}
178
179
180static int wpa_supplicant_process_smk_m2(
181 struct wpa_sm *sm, const unsigned char *src_addr,
182 const struct wpa_eapol_key *key, size_t extra_len, int ver)
183{
184 struct wpa_peerkey *peerkey;
185 struct wpa_eapol_ie_parse kde;
186 struct wpa_ie_data ie;
187 int cipher;
188 struct rsn_ie_hdr *hdr;
189 u8 *pos;
190
191 wpa_printf(MSG_DEBUG, "RSN: Received SMK M2");
192
193 if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
194 wpa_printf(MSG_INFO, "RSN: SMK handshake not allowed for "
195 "the current network");
196 return -1;
197 }
198
199 if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
200 0) {
201 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M2");
202 return -1;
203 }
204
205 if (kde.rsn_ie == NULL || kde.mac_addr == NULL ||
206 kde.mac_addr_len < ETH_ALEN) {
207 wpa_printf(MSG_INFO, "RSN: No RSN IE or MAC address KDE in "
208 "SMK M2");
209 return -1;
210 }
211
212 wpa_printf(MSG_DEBUG, "RSN: SMK M2 - SMK initiator " MACSTR,
213 MAC2STR(kde.mac_addr));
214
215 if (kde.rsn_ie_len > PEERKEY_MAX_IE_LEN) {
216 wpa_printf(MSG_INFO, "RSN: Too long Initiator RSN IE in SMK "
217 "M2");
218 return -1;
219 }
220
221 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
222 wpa_printf(MSG_INFO, "RSN: Failed to parse RSN IE in SMK M2");
223 return -1;
224 }
225
226 cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
227 if (cipher & WPA_CIPHER_CCMP) {
228 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
229 cipher = WPA_CIPHER_CCMP;
230 } else if (cipher & WPA_CIPHER_TKIP) {
231 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
232 cipher = WPA_CIPHER_TKIP;
233 } else {
234 wpa_printf(MSG_INFO, "RSN: No acceptable cipher in SMK M2");
235 wpa_supplicant_send_smk_error(sm, src_addr, kde.mac_addr,
236 STK_MUI_SMK, STK_ERR_CPHR_NS,
237 ver);
238 return -1;
239 }
240
241 /* TODO: find existing entry and if found, use that instead of adding
242 * a new one; how to handle the case where both ends initiate at the
243 * same time? */
244 peerkey = os_zalloc(sizeof(*peerkey));
245 if (peerkey == NULL)
246 return -1;
247 os_memcpy(peerkey->addr, kde.mac_addr, ETH_ALEN);
248 os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
249 os_memcpy(peerkey->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
250 peerkey->rsnie_i_len = kde.rsn_ie_len;
251 peerkey->cipher = cipher;
252#ifdef CONFIG_IEEE80211W
253 if (ie.key_mgmt & (WPA_KEY_MGMT_IEEE8021X_SHA256 |
254 WPA_KEY_MGMT_PSK_SHA256))
255 peerkey->use_sha256 = 1;
256#endif /* CONFIG_IEEE80211W */
257
258 if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
259 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
260 "WPA: Failed to get random data for PNonce");
261 wpa_supplicant_peerkey_free(sm, peerkey);
262 return -1;
263 }
264
265 hdr = (struct rsn_ie_hdr *) peerkey->rsnie_p;
266 hdr->elem_id = WLAN_EID_RSN;
267 WPA_PUT_LE16(hdr->version, RSN_VERSION);
268 pos = (u8 *) (hdr + 1);
269 /* Group Suite can be anything for SMK RSN IE; receiver will just
270 * ignore it. */
271 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
272 pos += RSN_SELECTOR_LEN;
273 /* Include only the selected cipher in pairwise cipher suite */
274 WPA_PUT_LE16(pos, 1);
275 pos += 2;
276 if (cipher == WPA_CIPHER_CCMP)
277 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
278 else if (cipher == WPA_CIPHER_TKIP)
279 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
280 pos += RSN_SELECTOR_LEN;
281
282 hdr->len = (pos - peerkey->rsnie_p) - 2;
283 peerkey->rsnie_p_len = pos - peerkey->rsnie_p;
284 wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
285 peerkey->rsnie_p, peerkey->rsnie_p_len);
286
287 wpa_supplicant_send_smk_m3(sm, src_addr, key, ver, peerkey);
288
289 peerkey->next = sm->peerkey;
290 sm->peerkey = peerkey;
291
292 return 0;
293}
294
295
296/**
297 * rsn_smkid - Derive SMK identifier
298 * @smk: Station master key (32 bytes)
299 * @pnonce: Peer Nonce
300 * @mac_p: Peer MAC address
301 * @inonce: Initiator Nonce
302 * @mac_i: Initiator MAC address
303 * @use_sha256: Whether to use SHA256-based KDF
304 *
305 * 8.5.1.4 Station to station (STK) key hierarchy
306 * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
307 */
308static void rsn_smkid(const u8 *smk, const u8 *pnonce, const u8 *mac_p,
309 const u8 *inonce, const u8 *mac_i, u8 *smkid,
310 int use_sha256)
311{
312 char *title = "SMK Name";
313 const u8 *addr[5];
314 const size_t len[5] = { 8, WPA_NONCE_LEN, ETH_ALEN, WPA_NONCE_LEN,
315 ETH_ALEN };
316 unsigned char hash[SHA256_MAC_LEN];
317
318 addr[0] = (u8 *) title;
319 addr[1] = pnonce;
320 addr[2] = mac_p;
321 addr[3] = inonce;
322 addr[4] = mac_i;
323
324#ifdef CONFIG_IEEE80211W
325 if (use_sha256)
326 hmac_sha256_vector(smk, PMK_LEN, 5, addr, len, hash);
327 else
328#endif /* CONFIG_IEEE80211W */
329 hmac_sha1_vector(smk, PMK_LEN, 5, addr, len, hash);
330 os_memcpy(smkid, hash, PMKID_LEN);
331}
332
333
334static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm *sm,
335 struct wpa_peerkey *peerkey)
336{
337 size_t mlen;
338 struct wpa_eapol_key *msg;
339 u8 *mbuf;
340 size_t kde_len;
341 u16 key_info, ver;
342
343 kde_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN;
344
345 mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
346 sizeof(*msg) + kde_len, &mlen,
347 (void *) &msg);
348 if (mbuf == NULL)
349 return;
350
351 msg->type = EAPOL_KEY_TYPE_RSN;
352
353 if (peerkey->cipher == WPA_CIPHER_CCMP)
354 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
355 else
356 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
357
358 key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK;
359 WPA_PUT_BE16(msg->key_info, key_info);
360
361 if (peerkey->cipher == WPA_CIPHER_CCMP)
362 WPA_PUT_BE16(msg->key_length, 16);
363 else
364 WPA_PUT_BE16(msg->key_length, 32);
365
366 os_memcpy(msg->replay_counter, peerkey->replay_counter,
367 WPA_REPLAY_COUNTER_LEN);
368 inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
369
370 WPA_PUT_BE16(msg->key_data_length, kde_len);
371 wpa_add_kde((u8 *) (msg + 1), RSN_KEY_DATA_PMKID,
372 peerkey->smkid, PMKID_LEN);
373
374 if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) {
375 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
376 "RSN: Failed to get random data for INonce (STK)");
377 os_free(mbuf);
378 return;
379 }
380 wpa_hexdump(MSG_DEBUG, "RSN: INonce for STK 4-Way Handshake",
381 peerkey->inonce, WPA_NONCE_LEN);
382 os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
383
384 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR,
385 MAC2STR(peerkey->addr));
386 wpa_eapol_key_send(sm, NULL, ver, peerkey->addr, ETH_P_EAPOL,
387 mbuf, mlen, NULL);
388}
389
390
391static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm *sm,
392 struct wpa_peerkey *peerkey)
393{
394 size_t mlen;
395 struct wpa_eapol_key *msg;
396 u8 *mbuf, *pos;
397 size_t kde_len;
398 u16 key_info, ver;
399 be32 lifetime;
400
401 kde_len = peerkey->rsnie_i_len +
402 2 + RSN_SELECTOR_LEN + sizeof(lifetime);
403
404 mbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
405 sizeof(*msg) + kde_len, &mlen,
406 (void *) &msg);
407 if (mbuf == NULL)
408 return;
409
410 msg->type = EAPOL_KEY_TYPE_RSN;
411
412 if (peerkey->cipher == WPA_CIPHER_CCMP)
413 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
414 else
415 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
416
417 key_info = ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_ACK |
418 WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE;
419 WPA_PUT_BE16(msg->key_info, key_info);
420
421 if (peerkey->cipher == WPA_CIPHER_CCMP)
422 WPA_PUT_BE16(msg->key_length, 16);
423 else
424 WPA_PUT_BE16(msg->key_length, 32);
425
426 os_memcpy(msg->replay_counter, peerkey->replay_counter,
427 WPA_REPLAY_COUNTER_LEN);
428 inc_byte_array(peerkey->replay_counter, WPA_REPLAY_COUNTER_LEN);
429
430 WPA_PUT_BE16(msg->key_data_length, kde_len);
431 pos = (u8 *) (msg + 1);
432 pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
433 lifetime = host_to_be32(peerkey->lifetime);
434 wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
435 (u8 *) &lifetime, sizeof(lifetime));
436
437 os_memcpy(msg->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
438
439 wpa_printf(MSG_DEBUG, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR,
440 MAC2STR(peerkey->addr));
441 wpa_eapol_key_send(sm, peerkey->stk.kck, ver, peerkey->addr,
442 ETH_P_EAPOL, mbuf, mlen, msg->key_mic);
443}
444
445
446static int wpa_supplicant_process_smk_m4(struct wpa_peerkey *peerkey,
447 struct wpa_eapol_ie_parse *kde)
448{
449 wpa_printf(MSG_DEBUG, "RSN: Received SMK M4 (Initiator " MACSTR ")",
450 MAC2STR(kde->mac_addr));
451
452 if (os_memcmp(kde->smk + PMK_LEN, peerkey->pnonce, WPA_NONCE_LEN) != 0)
453 {
454 wpa_printf(MSG_INFO, "RSN: PNonce in SMK KDE does not "
455 "match with the one used in SMK M3");
456 return -1;
457 }
458
459 if (os_memcmp(kde->nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
460 wpa_printf(MSG_INFO, "RSN: INonce in SMK M4 did not "
461 "match with the one received in SMK M2");
462 return -1;
463 }
464
465 return 0;
466}
467
468
469static int wpa_supplicant_process_smk_m5(struct wpa_sm *sm,
470 const unsigned char *src_addr,
471 const struct wpa_eapol_key *key,
472 int ver,
473 struct wpa_peerkey *peerkey,
474 struct wpa_eapol_ie_parse *kde)
475{
476 int cipher;
477 struct wpa_ie_data ie;
478
479 wpa_printf(MSG_DEBUG, "RSN: Received SMK M5 (Peer " MACSTR ")",
480 MAC2STR(kde->mac_addr));
481 if (kde->rsn_ie == NULL || kde->rsn_ie_len > PEERKEY_MAX_IE_LEN ||
482 wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0) {
483 wpa_printf(MSG_INFO, "RSN: No RSN IE in SMK M5");
484 /* TODO: abort negotiation */
485 return -1;
486 }
487
488 if (os_memcmp(key->key_nonce, peerkey->inonce, WPA_NONCE_LEN) != 0) {
489 wpa_printf(MSG_INFO, "RSN: Key Nonce in SMK M5 does "
490 "not match with INonce used in SMK M1");
491 return -1;
492 }
493
494 if (os_memcmp(kde->smk + PMK_LEN, peerkey->inonce, WPA_NONCE_LEN) != 0)
495 {
496 wpa_printf(MSG_INFO, "RSN: INonce in SMK KDE does not "
497 "match with the one used in SMK M1");
498 return -1;
499 }
500
501 os_memcpy(peerkey->rsnie_p, kde->rsn_ie, kde->rsn_ie_len);
502 peerkey->rsnie_p_len = kde->rsn_ie_len;
503 os_memcpy(peerkey->pnonce, kde->nonce, WPA_NONCE_LEN);
504
505 cipher = ie.pairwise_cipher & sm->allowed_pairwise_cipher;
506 if (cipher & WPA_CIPHER_CCMP) {
507 wpa_printf(MSG_DEBUG, "RSN: Using CCMP for PeerKey");
508 peerkey->cipher = WPA_CIPHER_CCMP;
509 } else if (cipher & WPA_CIPHER_TKIP) {
510 wpa_printf(MSG_DEBUG, "RSN: Using TKIP for PeerKey");
511 peerkey->cipher = WPA_CIPHER_TKIP;
512 } else {
513 wpa_printf(MSG_INFO, "RSN: SMK Peer STA " MACSTR " selected "
514 "unacceptable cipher", MAC2STR(kde->mac_addr));
515 wpa_supplicant_send_smk_error(sm, src_addr, kde->mac_addr,
516 STK_MUI_SMK, STK_ERR_CPHR_NS,
517 ver);
518 /* TODO: abort negotiation */
519 return -1;
520 }
521
522 return 0;
523}
524
525
526static int wpa_supplicant_process_smk_m45(
527 struct wpa_sm *sm, const unsigned char *src_addr,
528 const struct wpa_eapol_key *key, size_t extra_len, int ver)
529{
530 struct wpa_peerkey *peerkey;
531 struct wpa_eapol_ie_parse kde;
532 u32 lifetime;
533 struct os_time now;
534
535 if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
536 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
537 "the current network");
538 return -1;
539 }
540
541 if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
542 0) {
543 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK M4/M5");
544 return -1;
545 }
546
547 if (kde.mac_addr == NULL || kde.mac_addr_len < ETH_ALEN ||
548 kde.nonce == NULL || kde.nonce_len < WPA_NONCE_LEN ||
549 kde.smk == NULL || kde.smk_len < PMK_LEN + WPA_NONCE_LEN ||
550 kde.lifetime == NULL || kde.lifetime_len < 4) {
551 wpa_printf(MSG_INFO, "RSN: No MAC Address, Nonce, SMK, or "
552 "Lifetime KDE in SMK M4/M5");
553 return -1;
554 }
555
556 for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
557 if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) == 0 &&
558 os_memcmp(peerkey->initiator ? peerkey->inonce :
559 peerkey->pnonce,
560 key->key_nonce, WPA_NONCE_LEN) == 0)
561 break;
562 }
563 if (peerkey == NULL) {
564 wpa_printf(MSG_INFO, "RSN: No matching SMK handshake found "
565 "for SMK M4/M5: peer " MACSTR,
566 MAC2STR(kde.mac_addr));
567 return -1;
568 }
569
570 if (peerkey->initiator) {
571 if (wpa_supplicant_process_smk_m5(sm, src_addr, key, ver,
572 peerkey, &kde) < 0)
573 return -1;
574 } else {
575 if (wpa_supplicant_process_smk_m4(peerkey, &kde) < 0)
576 return -1;
577 }
578
579 os_memcpy(peerkey->smk, kde.smk, PMK_LEN);
580 peerkey->smk_complete = 1;
581 wpa_hexdump_key(MSG_DEBUG, "RSN: SMK", peerkey->smk, PMK_LEN);
582 lifetime = WPA_GET_BE32(kde.lifetime);
583 wpa_printf(MSG_DEBUG, "RSN: SMK lifetime %u seconds", lifetime);
584 if (lifetime > 1000000000)
585 lifetime = 1000000000; /* avoid overflowing expiration time */
586 peerkey->lifetime = lifetime;
587 os_get_time(&now);
588 peerkey->expiration = now.sec + lifetime;
589 eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
590 sm, peerkey);
591
592 if (peerkey->initiator) {
593 rsn_smkid(peerkey->smk, peerkey->pnonce, peerkey->addr,
594 peerkey->inonce, sm->own_addr, peerkey->smkid,
595 peerkey->use_sha256);
596 wpa_supplicant_send_stk_1_of_4(sm, peerkey);
597 } else {
598 rsn_smkid(peerkey->smk, peerkey->pnonce, sm->own_addr,
599 peerkey->inonce, peerkey->addr, peerkey->smkid,
600 peerkey->use_sha256);
601 }
602 wpa_hexdump(MSG_DEBUG, "RSN: SMKID", peerkey->smkid, PMKID_LEN);
603
604 return 0;
605}
606
607
608static int wpa_supplicant_process_smk_error(
609 struct wpa_sm *sm, const unsigned char *src_addr,
610 const struct wpa_eapol_key *key, size_t extra_len)
611{
612 struct wpa_eapol_ie_parse kde;
613 struct rsn_error_kde error;
614 u8 peer[ETH_ALEN];
615 u16 error_type;
616
617 wpa_printf(MSG_DEBUG, "RSN: Received SMK Error");
618
619 if (!sm->peerkey_enabled || sm->proto != WPA_PROTO_RSN) {
620 wpa_printf(MSG_DEBUG, "RSN: SMK handshake not allowed for "
621 "the current network");
622 return -1;
623 }
624
625 if (wpa_supplicant_parse_ies((const u8 *) (key + 1), extra_len, &kde) <
626 0) {
627 wpa_printf(MSG_INFO, "RSN: Failed to parse KDEs in SMK Error");
628 return -1;
629 }
630
631 if (kde.error == NULL || kde.error_len < sizeof(error)) {
632 wpa_printf(MSG_INFO, "RSN: No Error KDE in SMK Error");
633 return -1;
634 }
635
636 if (kde.mac_addr && kde.mac_addr_len >= ETH_ALEN)
637 os_memcpy(peer, kde.mac_addr, ETH_ALEN);
638 else
639 os_memset(peer, 0, ETH_ALEN);
640 os_memcpy(&error, kde.error, sizeof(error));
641 error_type = be_to_host16(error.error_type);
642 wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
643 "RSN: SMK Error KDE received: MUI %d error_type %d peer "
644 MACSTR,
645 be_to_host16(error.mui), error_type,
646 MAC2STR(peer));
647
648 if (kde.mac_addr &&
649 (error_type == STK_ERR_STA_NR || error_type == STK_ERR_STA_NRSN ||
650 error_type == STK_ERR_CPHR_NS)) {
651 struct wpa_peerkey *peerkey;
652
653 for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) {
654 if (os_memcmp(peerkey->addr, kde.mac_addr, ETH_ALEN) ==
655 0)
656 break;
657 }
658 if (peerkey == NULL) {
659 wpa_printf(MSG_DEBUG, "RSN: No matching SMK handshake "
660 "found for SMK Error");
661 return -1;
662 }
663 /* TODO: abort SMK/STK handshake and remove all related keys */
664 }
665
666 return 0;
667}
668
669
670static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm *sm,
671 struct wpa_peerkey *peerkey,
672 const struct wpa_eapol_key *key,
673 u16 ver)
674{
675 struct wpa_eapol_ie_parse ie;
676 const u8 *kde;
677 size_t len, kde_buf_len;
678 struct wpa_ptk *stk;
679 u8 buf[8], *kde_buf, *pos;
680 be32 lifetime;
681
682 wpa_printf(MSG_DEBUG, "RSN: RX message 1 of STK 4-Way Handshake from "
683 MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
684
685 os_memset(&ie, 0, sizeof(ie));
686
687 /* RSN: msg 1/4 should contain SMKID for the selected SMK */
688 kde = (const u8 *) (key + 1);
689 len = WPA_GET_BE16(key->key_data_length);
690 wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", kde, len);
691 if (wpa_supplicant_parse_ies(kde, len, &ie) < 0 || ie.pmkid == NULL) {
692 wpa_printf(MSG_DEBUG, "RSN: No SMKID in STK 1/4");
693 return;
694 }
695 if (os_memcmp(ie.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
696 wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 1/4",
697 ie.pmkid, PMKID_LEN);
698 return;
699 }
700
701 if (random_get_bytes(peerkey->pnonce, WPA_NONCE_LEN)) {
702 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
703 "RSN: Failed to get random data for PNonce");
704 return;
705 }
706 wpa_hexdump(MSG_DEBUG, "WPA: Renewed PNonce",
707 peerkey->pnonce, WPA_NONCE_LEN);
708
709 /* Calculate STK which will be stored as a temporary STK until it has
710 * been verified when processing message 3/4. */
711 stk = &peerkey->tstk;
712 wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
713 sm->own_addr, peerkey->addr,
714 peerkey->pnonce, key->key_nonce,
715 (u8 *) stk, sizeof(*stk),
716 peerkey->use_sha256);
717 /* Supplicant: swap tx/rx Mic keys */
718 os_memcpy(buf, stk->u.auth.tx_mic_key, 8);
719 os_memcpy(stk->u.auth.tx_mic_key, stk->u.auth.rx_mic_key, 8);
720 os_memcpy(stk->u.auth.rx_mic_key, buf, 8);
721 peerkey->tstk_set = 1;
722
723 kde_buf_len = peerkey->rsnie_p_len +
724 2 + RSN_SELECTOR_LEN + sizeof(lifetime) +
725 2 + RSN_SELECTOR_LEN + PMKID_LEN;
726 kde_buf = os_malloc(kde_buf_len);
727 if (kde_buf == NULL)
728 return;
729 pos = kde_buf;
730 pos = wpa_add_ie(pos, peerkey->rsnie_p, peerkey->rsnie_p_len);
731 lifetime = host_to_be32(peerkey->lifetime);
732 pos = wpa_add_kde(pos, RSN_KEY_DATA_LIFETIME,
733 (u8 *) &lifetime, sizeof(lifetime));
734 wpa_add_kde(pos, RSN_KEY_DATA_PMKID, peerkey->smkid, PMKID_LEN);
735
736 if (wpa_supplicant_send_2_of_4(sm, peerkey->addr, key, ver,
737 peerkey->pnonce, kde_buf, kde_buf_len,
738 stk)) {
739 os_free(kde_buf);
740 return;
741 }
742 os_free(kde_buf);
743
744 os_memcpy(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN);
745}
746
747
748static void wpa_supplicant_update_smk_lifetime(struct wpa_sm *sm,
749 struct wpa_peerkey *peerkey,
750 struct wpa_eapol_ie_parse *kde)
751{
752 u32 lifetime;
753 struct os_time now;
754
755 if (kde->lifetime == NULL || kde->lifetime_len < sizeof(lifetime))
756 return;
757
758 lifetime = WPA_GET_BE32(kde->lifetime);
759
760 if (lifetime >= peerkey->lifetime) {
761 wpa_printf(MSG_DEBUG, "RSN: Peer used SMK lifetime %u seconds "
762 "which is larger than or equal to own value %u "
763 "seconds - ignored", lifetime, peerkey->lifetime);
764 return;
765 }
766
767 wpa_printf(MSG_DEBUG, "RSN: Peer used shorter SMK lifetime %u seconds "
768 "(own was %u seconds) - updated",
769 lifetime, peerkey->lifetime);
770 peerkey->lifetime = lifetime;
771
772 os_get_time(&now);
773 peerkey->expiration = now.sec + lifetime;
774 eloop_cancel_timeout(wpa_supplicant_smk_timeout, sm, peerkey);
775 eloop_register_timeout(lifetime, 0, wpa_supplicant_smk_timeout,
776 sm, peerkey);
777}
778
779
780static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm *sm,
781 struct wpa_peerkey *peerkey,
782 const struct wpa_eapol_key *key,
783 u16 ver)
784{
785 struct wpa_eapol_ie_parse kde;
786 const u8 *keydata;
787 size_t len;
788
789 wpa_printf(MSG_DEBUG, "RSN: RX message 2 of STK 4-Way Handshake from "
790 MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
791
792 os_memset(&kde, 0, sizeof(kde));
793
794 /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
795 * from the peer. It may also include Lifetime KDE. */
796 keydata = (const u8 *) (key + 1);
797 len = WPA_GET_BE16(key->key_data_length);
798 wpa_hexdump(MSG_DEBUG, "RSN: msg 2/4 key data", keydata, len);
799 if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0 ||
800 kde.pmkid == NULL || kde.rsn_ie == NULL) {
801 wpa_printf(MSG_DEBUG, "RSN: No SMKID or RSN IE in STK 2/4");
802 return;
803 }
804
805 if (os_memcmp(kde.pmkid, peerkey->smkid, PMKID_LEN) != 0) {
806 wpa_hexdump(MSG_DEBUG, "RSN: Unknown SMKID in STK 2/4",
807 kde.pmkid, PMKID_LEN);
808 return;
809 }
810
811 if (kde.rsn_ie_len != peerkey->rsnie_p_len ||
812 os_memcmp(kde.rsn_ie, peerkey->rsnie_p, kde.rsn_ie_len) != 0) {
813 wpa_printf(MSG_INFO, "RSN: Peer RSN IE in SMK and STK "
814 "handshakes did not match");
815 wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in SMK handshake",
816 peerkey->rsnie_p, peerkey->rsnie_p_len);
817 wpa_hexdump(MSG_DEBUG, "RSN: Peer RSN IE in STK handshake",
818 kde.rsn_ie, kde.rsn_ie_len);
819 return;
820 }
821
822 wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
823
824 wpa_supplicant_send_stk_3_of_4(sm, peerkey);
825 os_memcpy(peerkey->pnonce, key->key_nonce, WPA_NONCE_LEN);
826}
827
828
829static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm *sm,
830 struct wpa_peerkey *peerkey,
831 const struct wpa_eapol_key *key,
832 u16 ver)
833{
834 struct wpa_eapol_ie_parse kde;
835 const u8 *keydata;
836 size_t len, key_len;
837 const u8 *_key;
838 u8 key_buf[32], rsc[6];
839
840 wpa_printf(MSG_DEBUG, "RSN: RX message 3 of STK 4-Way Handshake from "
841 MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
842
843 os_memset(&kde, 0, sizeof(kde));
844
845 /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
846 * Lifetime KDE. */
847 keydata = (const u8 *) (key + 1);
848 len = WPA_GET_BE16(key->key_data_length);
849 wpa_hexdump(MSG_DEBUG, "RSN: msg 3/4 key data", keydata, len);
850 if (wpa_supplicant_parse_ies(keydata, len, &kde) < 0) {
851 wpa_printf(MSG_DEBUG, "RSN: Failed to parse key data in "
852 "STK 3/4");
853 return;
854 }
855
856 if (kde.rsn_ie_len != peerkey->rsnie_i_len ||
857 os_memcmp(kde.rsn_ie, peerkey->rsnie_i, kde.rsn_ie_len) != 0) {
858 wpa_printf(MSG_INFO, "RSN: Initiator RSN IE in SMK and STK "
859 "handshakes did not match");
860 wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in SMK "
861 "handshake",
862 peerkey->rsnie_i, peerkey->rsnie_i_len);
863 wpa_hexdump(MSG_DEBUG, "RSN: Initiator RSN IE in STK "
864 "handshake",
865 kde.rsn_ie, kde.rsn_ie_len);
866 return;
867 }
868
869 if (os_memcmp(peerkey->inonce, key->key_nonce, WPA_NONCE_LEN) != 0) {
870 wpa_printf(MSG_WARNING, "RSN: INonce from message 1 of STK "
871 "4-Way Handshake differs from 3 of STK 4-Way "
872 "Handshake - drop packet (src=" MACSTR ")",
873 MAC2STR(peerkey->addr));
874 return;
875 }
876
877 wpa_supplicant_update_smk_lifetime(sm, peerkey, &kde);
878
879 if (wpa_supplicant_send_4_of_4(sm, peerkey->addr, key, ver,
880 WPA_GET_BE16(key->key_info),
881 NULL, 0, &peerkey->stk))
882 return;
883
884 _key = (u8 *) peerkey->stk.tk1;
885 if (peerkey->cipher == WPA_CIPHER_TKIP) {
886 /* Swap Tx/Rx keys for Michael MIC */
887 os_memcpy(key_buf, _key, 16);
888 os_memcpy(key_buf + 16, peerkey->stk.u.auth.rx_mic_key, 8);
889 os_memcpy(key_buf + 24, peerkey->stk.u.auth.tx_mic_key, 8);
890 _key = key_buf;
891 key_len = 32;
892 } else
893 key_len = 16;
894
895 os_memset(rsc, 0, 6);
896 if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
897 rsc, sizeof(rsc), _key, key_len) < 0) {
898 wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
899 "driver.");
900 return;
901 }
902}
903
904
905static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm *sm,
906 struct wpa_peerkey *peerkey,
907 const struct wpa_eapol_key *key,
908 u16 ver)
909{
910 u8 rsc[6];
911
912 wpa_printf(MSG_DEBUG, "RSN: RX message 4 of STK 4-Way Handshake from "
913 MACSTR " (ver=%d)", MAC2STR(peerkey->addr), ver);
914
915 os_memset(rsc, 0, 6);
916 if (wpa_sm_set_key(sm, peerkey->cipher, peerkey->addr, 0, 1,
917 rsc, sizeof(rsc), (u8 *) peerkey->stk.tk1,
918 peerkey->cipher == WPA_CIPHER_TKIP ? 32 : 16) < 0) {
919 wpa_printf(MSG_WARNING, "RSN: Failed to set STK to the "
920 "driver.");
921 return;
922 }
923}
924
925
926/**
927 * peerkey_verify_eapol_key_mic - Verify PeerKey MIC
928 * @sm: Pointer to WPA state machine data from wpa_sm_init()
929 * @peerkey: Pointer to the PeerKey data for the peer
930 * @key: Pointer to the EAPOL-Key frame header
931 * @ver: Version bits from EAPOL-Key Key Info
932 * @buf: Pointer to the beginning of EAPOL-Key frame
933 * @len: Length of the EAPOL-Key frame
934 * Returns: 0 on success, -1 on failure
935 */
936int peerkey_verify_eapol_key_mic(struct wpa_sm *sm,
937 struct wpa_peerkey *peerkey,
938 struct wpa_eapol_key *key, u16 ver,
939 const u8 *buf, size_t len)
940{
941 u8 mic[16];
942 int ok = 0;
943
944 if (peerkey->initiator && !peerkey->stk_set) {
945 wpa_pmk_to_ptk(peerkey->smk, PMK_LEN, "Peer key expansion",
946 sm->own_addr, peerkey->addr,
947 peerkey->inonce, key->key_nonce,
948 (u8 *) &peerkey->stk, sizeof(peerkey->stk),
949 peerkey->use_sha256);
950 peerkey->stk_set = 1;
951 }
952
953 os_memcpy(mic, key->key_mic, 16);
954 if (peerkey->tstk_set) {
955 os_memset(key->key_mic, 0, 16);
956 wpa_eapol_key_mic(peerkey->tstk.kck, ver, buf, len,
957 key->key_mic);
958 if (os_memcmp(mic, key->key_mic, 16) != 0) {
959 wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
960 "when using TSTK - ignoring TSTK");
961 } else {
962 ok = 1;
963 peerkey->tstk_set = 0;
964 peerkey->stk_set = 1;
965 os_memcpy(&peerkey->stk, &peerkey->tstk,
966 sizeof(peerkey->stk));
967 }
968 }
969
970 if (!ok && peerkey->stk_set) {
971 os_memset(key->key_mic, 0, 16);
972 wpa_eapol_key_mic(peerkey->stk.kck, ver, buf, len,
973 key->key_mic);
974 if (os_memcmp(mic, key->key_mic, 16) != 0) {
975 wpa_printf(MSG_WARNING, "RSN: Invalid EAPOL-Key MIC "
976 "- dropping packet");
977 return -1;
978 }
979 ok = 1;
980 }
981
982 if (!ok) {
983 wpa_printf(MSG_WARNING, "RSN: Could not verify EAPOL-Key MIC "
984 "- dropping packet");
985 return -1;
986 }
987
988 os_memcpy(peerkey->replay_counter, key->replay_counter,
989 WPA_REPLAY_COUNTER_LEN);
990 peerkey->replay_counter_set = 1;
991 return 0;
992}
993
994
995/**
996 * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
997 * @sm: Pointer to WPA state machine data from wpa_sm_init()
998 * @peer: MAC address of the peer STA
999 * Returns: 0 on success, or -1 on failure
1000 *
1001 * Send an EAPOL-Key Request to the current authenticator to start STK
1002 * handshake with the peer.
1003 */
1004int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer)
1005{
1006 size_t rlen, kde_len;
1007 struct wpa_eapol_key *req;
1008 int key_info, ver;
1009 u8 bssid[ETH_ALEN], *rbuf, *pos, *count_pos;
1010 u16 count;
1011 struct rsn_ie_hdr *hdr;
1012 struct wpa_peerkey *peerkey;
1013 struct wpa_ie_data ie;
1014
1015 if (sm->proto != WPA_PROTO_RSN || !sm->ptk_set || !sm->peerkey_enabled)
1016 return -1;
1017
1018 if (sm->ap_rsn_ie &&
1019 wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &ie) == 0 &&
1020 !(ie.capabilities & WPA_CAPABILITY_PEERKEY_ENABLED)) {
1021 wpa_printf(MSG_DEBUG, "RSN: Current AP does not support STK");
1022 return -1;
1023 }
1024
1025 if (sm->pairwise_cipher == WPA_CIPHER_CCMP)
1026 ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES;
1027 else
1028 ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4;
1029
1030 if (wpa_sm_get_bssid(sm, bssid) < 0) {
1031 wpa_printf(MSG_WARNING, "Failed to read BSSID for EAPOL-Key "
1032 "SMK M1");
1033 return -1;
1034 }
1035
1036 /* TODO: find existing entry and if found, use that instead of adding
1037 * a new one */
1038 peerkey = os_zalloc(sizeof(*peerkey));
1039 if (peerkey == NULL)
1040 return -1;
1041 peerkey->initiator = 1;
1042 os_memcpy(peerkey->addr, peer, ETH_ALEN);
1043#ifdef CONFIG_IEEE80211W
1044 if (wpa_key_mgmt_sha256(sm->key_mgmt))
1045 peerkey->use_sha256 = 1;
1046#endif /* CONFIG_IEEE80211W */
1047
1048 /* SMK M1:
1049 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
1050 * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
1051 */
1052
1053 hdr = (struct rsn_ie_hdr *) peerkey->rsnie_i;
1054 hdr->elem_id = WLAN_EID_RSN;
1055 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1056 pos = (u8 *) (hdr + 1);
1057 /* Group Suite can be anything for SMK RSN IE; receiver will just
1058 * ignore it. */
1059 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1060 pos += RSN_SELECTOR_LEN;
1061 count_pos = pos;
1062 pos += 2;
1063
1064 count = 0;
1065 if (sm->allowed_pairwise_cipher & WPA_CIPHER_CCMP) {
1066 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1067 pos += RSN_SELECTOR_LEN;
1068 count++;
1069 }
1070 if (sm->allowed_pairwise_cipher & WPA_CIPHER_TKIP) {
1071 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP);
1072 pos += RSN_SELECTOR_LEN;
1073 count++;
1074 }
1075 WPA_PUT_LE16(count_pos, count);
1076
1077 hdr->len = (pos - peerkey->rsnie_i) - 2;
1078 peerkey->rsnie_i_len = pos - peerkey->rsnie_i;
1079 wpa_hexdump(MSG_DEBUG, "WPA: RSN IE for SMK handshake",
1080 peerkey->rsnie_i, peerkey->rsnie_i_len);
1081
1082 kde_len = peerkey->rsnie_i_len + 2 + RSN_SELECTOR_LEN + ETH_ALEN;
1083
1084 rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL,
1085 sizeof(*req) + kde_len, &rlen,
1086 (void *) &req);
1087 if (rbuf == NULL) {
1088 wpa_supplicant_peerkey_free(sm, peerkey);
1089 return -1;
1090 }
1091
1092 req->type = EAPOL_KEY_TYPE_RSN;
1093 key_info = WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_MIC |
1094 WPA_KEY_INFO_SECURE | WPA_KEY_INFO_REQUEST | ver;
1095 WPA_PUT_BE16(req->key_info, key_info);
1096 WPA_PUT_BE16(req->key_length, 0);
1097 os_memcpy(req->replay_counter, sm->request_counter,
1098 WPA_REPLAY_COUNTER_LEN);
1099 inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN);
1100
1101 if (random_get_bytes(peerkey->inonce, WPA_NONCE_LEN)) {
1102 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1103 "WPA: Failed to get random data for INonce");
1104 os_free(rbuf);
1105 wpa_supplicant_peerkey_free(sm, peerkey);
1106 return -1;
1107 }
1108 os_memcpy(req->key_nonce, peerkey->inonce, WPA_NONCE_LEN);
1109 wpa_hexdump(MSG_DEBUG, "WPA: INonce for SMK handshake",
1110 req->key_nonce, WPA_NONCE_LEN);
1111
1112 WPA_PUT_BE16(req->key_data_length, (u16) kde_len);
1113 pos = (u8 *) (req + 1);
1114
1115 /* Initiator RSN IE */
1116 pos = wpa_add_ie(pos, peerkey->rsnie_i, peerkey->rsnie_i_len);
1117 /* Peer MAC address KDE */
1118 wpa_add_kde(pos, RSN_KEY_DATA_MAC_ADDR, peer, ETH_ALEN);
1119
1120 wpa_printf(MSG_INFO, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
1121 MACSTR ")", MAC2STR(peer));
1122 wpa_eapol_key_send(sm, sm->ptk.kck, ver, bssid, ETH_P_EAPOL,
1123 rbuf, rlen, req->key_mic);
1124
1125 peerkey->next = sm->peerkey;
1126 sm->peerkey = peerkey;
1127
1128 return 0;
1129}
1130
1131
1132/**
1133 * peerkey_deinit - Free PeerKey values
1134 * @sm: Pointer to WPA state machine data from wpa_sm_init()
1135 */
1136void peerkey_deinit(struct wpa_sm *sm)
1137{
1138 struct wpa_peerkey *prev, *peerkey = sm->peerkey;
1139 while (peerkey) {
1140 prev = peerkey;
1141 peerkey = peerkey->next;
1142 os_free(prev);
1143 }
1144 sm->peerkey = NULL;
1145}
1146
1147
1148void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey,
1149 struct wpa_eapol_key *key, u16 key_info, u16 ver)
1150{
1151 if ((key_info & (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) ==
1152 (WPA_KEY_INFO_MIC | WPA_KEY_INFO_ACK)) {
1153 /* 3/4 STK 4-Way Handshake */
1154 wpa_supplicant_process_stk_3_of_4(sm, peerkey, key, ver);
1155 } else if (key_info & WPA_KEY_INFO_ACK) {
1156 /* 1/4 STK 4-Way Handshake */
1157 wpa_supplicant_process_stk_1_of_4(sm, peerkey, key, ver);
1158 } else if (key_info & WPA_KEY_INFO_SECURE) {
1159 /* 4/4 STK 4-Way Handshake */
1160 wpa_supplicant_process_stk_4_of_4(sm, peerkey, key, ver);
1161 } else {
1162 /* 2/4 STK 4-Way Handshake */
1163 wpa_supplicant_process_stk_2_of_4(sm, peerkey, key, ver);
1164 }
1165}
1166
1167
1168void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr,
1169 struct wpa_eapol_key *key, size_t extra_len,
1170 u16 key_info, u16 ver)
1171{
1172 if (key_info & WPA_KEY_INFO_ERROR) {
1173 /* SMK Error */
1174 wpa_supplicant_process_smk_error(sm, src_addr, key, extra_len);
1175 } else if (key_info & WPA_KEY_INFO_ACK) {
1176 /* SMK M2 */
1177 wpa_supplicant_process_smk_m2(sm, src_addr, key, extra_len,
1178 ver);
1179 } else {
1180 /* SMK M4 or M5 */
1181 wpa_supplicant_process_smk_m45(sm, src_addr, key, extra_len,
1182 ver);
1183 }
1184}
1185
1186#endif /* CONFIG_PEERKEY */