2 * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
3 * Copyright (c) 2006-2008, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
21 #include "crypto/sha1.h"
22 #include "crypto/sha256.h"
23 #include "common/ieee802_11_defs.h"
30 static u8
* wpa_add_ie(u8
*pos
, const u8
*ie
, size_t ie_len
)
32 os_memcpy(pos
, ie
, ie_len
);
37 static u8
* wpa_add_kde(u8
*pos
, u32 kde
, const u8
*data
, size_t data_len
)
39 *pos
++ = WLAN_EID_VENDOR_SPECIFIC
;
40 *pos
++ = RSN_SELECTOR_LEN
+ data_len
;
41 RSN_SELECTOR_PUT(pos
, kde
);
42 pos
+= RSN_SELECTOR_LEN
;
43 os_memcpy(pos
, data
, data_len
);
49 static void wpa_supplicant_smk_timeout(void *eloop_ctx
, void *timeout_ctx
)
52 struct wpa_sm
*sm
= eloop_ctx
;
53 struct wpa_peerkey
*peerkey
= timeout_ctx
;
55 /* TODO: time out SMK and any STK that was generated using this SMK */
59 static void wpa_supplicant_peerkey_free(struct wpa_sm
*sm
,
60 struct wpa_peerkey
*peerkey
)
62 eloop_cancel_timeout(wpa_supplicant_smk_timeout
, sm
, peerkey
);
67 static int wpa_supplicant_send_smk_error(struct wpa_sm
*sm
, const u8
*dst
,
69 u16 mui
, u16 error_type
, int ver
)
72 struct wpa_eapol_key
*err
;
73 struct rsn_error_kde error
;
78 kde_len
= 2 + RSN_SELECTOR_LEN
+ sizeof(error
);
80 kde_len
+= 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
;
82 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
,
83 NULL
, sizeof(*err
) + kde_len
, &rlen
,
88 err
->type
= EAPOL_KEY_TYPE_RSN
;
89 key_info
= ver
| WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
90 WPA_KEY_INFO_SECURE
| WPA_KEY_INFO_ERROR
|
92 WPA_PUT_BE16(err
->key_info
, key_info
);
93 WPA_PUT_BE16(err
->key_length
, 0);
94 os_memcpy(err
->replay_counter
, sm
->request_counter
,
95 WPA_REPLAY_COUNTER_LEN
);
96 inc_byte_array(sm
->request_counter
, WPA_REPLAY_COUNTER_LEN
);
98 WPA_PUT_BE16(err
->key_data_length
, (u16
) kde_len
);
99 pos
= (u8
*) (err
+ 1);
102 /* Peer MAC Address KDE */
103 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peer
, ETH_ALEN
);
107 error
.mui
= host_to_be16(mui
);
108 error
.error_type
= host_to_be16(error_type
);
109 wpa_add_kde(pos
, RSN_KEY_DATA_ERROR
, (u8
*) &error
, sizeof(error
));
112 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key SMK Error (peer "
113 MACSTR
" mui %d error_type %d)",
114 MAC2STR(peer
), mui
, error_type
);
116 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key SMK Error "
117 "(mui %d error_type %d)", mui
, error_type
);
120 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, dst
, ETH_P_EAPOL
,
121 rbuf
, rlen
, err
->key_mic
);
127 static int wpa_supplicant_send_smk_m3(struct wpa_sm
*sm
,
128 const unsigned char *src_addr
,
129 const struct wpa_eapol_key
*key
,
130 int ver
, struct wpa_peerkey
*peerkey
)
133 struct wpa_eapol_key
*reply
;
138 /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
139 kde_len
= peerkey
->rsnie_p_len
+
140 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
+
141 2 + RSN_SELECTOR_LEN
+ WPA_NONCE_LEN
;
143 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
,
144 NULL
, sizeof(*reply
) + kde_len
, &rlen
,
149 reply
->type
= EAPOL_KEY_TYPE_RSN
;
150 key_info
= ver
| WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
152 WPA_PUT_BE16(reply
->key_info
, key_info
);
153 WPA_PUT_BE16(reply
->key_length
, 0);
154 os_memcpy(reply
->replay_counter
, key
->replay_counter
,
155 WPA_REPLAY_COUNTER_LEN
);
157 os_memcpy(reply
->key_nonce
, peerkey
->pnonce
, WPA_NONCE_LEN
);
159 WPA_PUT_BE16(reply
->key_data_length
, (u16
) kde_len
);
160 pos
= (u8
*) (reply
+ 1);
163 pos
= wpa_add_ie(pos
, peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
165 /* Initiator MAC Address KDE */
166 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peerkey
->addr
, ETH_ALEN
);
168 /* Initiator Nonce */
169 wpa_add_kde(pos
, RSN_KEY_DATA_NONCE
, peerkey
->inonce
, WPA_NONCE_LEN
);
171 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key SMK M3");
172 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, src_addr
, ETH_P_EAPOL
,
173 rbuf
, rlen
, reply
->key_mic
);
179 static int wpa_supplicant_process_smk_m2(
180 struct wpa_sm
*sm
, const unsigned char *src_addr
,
181 const struct wpa_eapol_key
*key
, size_t extra_len
, int ver
)
183 struct wpa_peerkey
*peerkey
;
184 struct wpa_eapol_ie_parse kde
;
185 struct wpa_ie_data ie
;
187 struct rsn_ie_hdr
*hdr
;
190 wpa_printf(MSG_DEBUG
, "RSN: Received SMK M2");
192 if (!sm
->peerkey_enabled
|| sm
->proto
!= WPA_PROTO_RSN
) {
193 wpa_printf(MSG_INFO
, "RSN: SMK handshake not allowed for "
194 "the current network");
198 if (wpa_supplicant_parse_ies((const u8
*) (key
+ 1), extra_len
, &kde
) <
200 wpa_printf(MSG_INFO
, "RSN: Failed to parse KDEs in SMK M2");
204 if (kde
.rsn_ie
== NULL
|| kde
.mac_addr
== NULL
||
205 kde
.mac_addr_len
< ETH_ALEN
) {
206 wpa_printf(MSG_INFO
, "RSN: No RSN IE or MAC address KDE in "
211 wpa_printf(MSG_DEBUG
, "RSN: SMK M2 - SMK initiator " MACSTR
,
212 MAC2STR(kde
.mac_addr
));
214 if (kde
.rsn_ie_len
> PEERKEY_MAX_IE_LEN
) {
215 wpa_printf(MSG_INFO
, "RSN: Too long Initiator RSN IE in SMK "
220 if (wpa_parse_wpa_ie_rsn(kde
.rsn_ie
, kde
.rsn_ie_len
, &ie
) < 0) {
221 wpa_printf(MSG_INFO
, "RSN: Failed to parse RSN IE in SMK M2");
225 cipher
= ie
.pairwise_cipher
& sm
->allowed_pairwise_cipher
;
226 if (cipher
& WPA_CIPHER_CCMP
) {
227 wpa_printf(MSG_DEBUG
, "RSN: Using CCMP for PeerKey");
228 cipher
= WPA_CIPHER_CCMP
;
229 } else if (cipher
& WPA_CIPHER_TKIP
) {
230 wpa_printf(MSG_DEBUG
, "RSN: Using TKIP for PeerKey");
231 cipher
= WPA_CIPHER_TKIP
;
233 wpa_printf(MSG_INFO
, "RSN: No acceptable cipher in SMK M2");
234 wpa_supplicant_send_smk_error(sm
, src_addr
, kde
.mac_addr
,
235 STK_MUI_SMK
, STK_ERR_CPHR_NS
,
240 /* TODO: find existing entry and if found, use that instead of adding
241 * a new one; how to handle the case where both ends initiate at the
243 peerkey
= os_zalloc(sizeof(*peerkey
));
246 os_memcpy(peerkey
->addr
, kde
.mac_addr
, ETH_ALEN
);
247 os_memcpy(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
);
248 os_memcpy(peerkey
->rsnie_i
, kde
.rsn_ie
, kde
.rsn_ie_len
);
249 peerkey
->rsnie_i_len
= kde
.rsn_ie_len
;
250 peerkey
->cipher
= cipher
;
251 #ifdef CONFIG_IEEE80211W
252 if (ie
.key_mgmt
& (WPA_KEY_MGMT_IEEE8021X_SHA256
|
253 WPA_KEY_MGMT_PSK_SHA256
))
254 peerkey
->use_sha256
= 1;
255 #endif /* CONFIG_IEEE80211W */
257 if (os_get_random(peerkey
->pnonce
, WPA_NONCE_LEN
)) {
258 wpa_msg(sm
->ctx
->msg_ctx
, MSG_WARNING
,
259 "WPA: Failed to get random data for PNonce");
260 wpa_supplicant_peerkey_free(sm
, peerkey
);
264 hdr
= (struct rsn_ie_hdr
*) peerkey
->rsnie_p
;
265 hdr
->elem_id
= WLAN_EID_RSN
;
266 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
267 pos
= (u8
*) (hdr
+ 1);
268 /* Group Suite can be anything for SMK RSN IE; receiver will just
270 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
271 pos
+= RSN_SELECTOR_LEN
;
272 /* Include only the selected cipher in pairwise cipher suite */
273 WPA_PUT_LE16(pos
, 1);
275 if (cipher
== WPA_CIPHER_CCMP
)
276 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
277 else if (cipher
== WPA_CIPHER_TKIP
)
278 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_TKIP
);
279 pos
+= RSN_SELECTOR_LEN
;
281 hdr
->len
= (pos
- peerkey
->rsnie_p
) - 2;
282 peerkey
->rsnie_p_len
= pos
- peerkey
->rsnie_p
;
283 wpa_hexdump(MSG_DEBUG
, "WPA: RSN IE for SMK handshake",
284 peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
286 wpa_supplicant_send_smk_m3(sm
, src_addr
, key
, ver
, peerkey
);
288 peerkey
->next
= sm
->peerkey
;
289 sm
->peerkey
= peerkey
;
296 * rsn_smkid - Derive SMK identifier
297 * @smk: Station master key (32 bytes)
298 * @pnonce: Peer Nonce
299 * @mac_p: Peer MAC address
300 * @inonce: Initiator Nonce
301 * @mac_i: Initiator MAC address
302 * @use_sha256: Whether to use SHA256-based KDF
304 * 8.5.1.4 Station to station (STK) key hierarchy
305 * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
307 static void rsn_smkid(const u8
*smk
, const u8
*pnonce
, const u8
*mac_p
,
308 const u8
*inonce
, const u8
*mac_i
, u8
*smkid
,
311 char *title
= "SMK Name";
313 const size_t len
[5] = { 8, WPA_NONCE_LEN
, ETH_ALEN
, WPA_NONCE_LEN
,
315 unsigned char hash
[SHA256_MAC_LEN
];
317 addr
[0] = (u8
*) title
;
323 #ifdef CONFIG_IEEE80211W
325 hmac_sha256_vector(smk
, PMK_LEN
, 5, addr
, len
, hash
);
327 #endif /* CONFIG_IEEE80211W */
328 hmac_sha1_vector(smk
, PMK_LEN
, 5, addr
, len
, hash
);
329 os_memcpy(smkid
, hash
, PMKID_LEN
);
333 static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm
*sm
,
334 struct wpa_peerkey
*peerkey
)
337 struct wpa_eapol_key
*msg
;
342 kde_len
= 2 + RSN_SELECTOR_LEN
+ PMKID_LEN
;
344 mbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
345 sizeof(*msg
) + kde_len
, &mlen
,
350 msg
->type
= EAPOL_KEY_TYPE_RSN
;
352 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
353 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
355 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
357 key_info
= ver
| WPA_KEY_INFO_KEY_TYPE
| WPA_KEY_INFO_ACK
;
358 WPA_PUT_BE16(msg
->key_info
, key_info
);
360 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
361 WPA_PUT_BE16(msg
->key_length
, 16);
363 WPA_PUT_BE16(msg
->key_length
, 32);
365 os_memcpy(msg
->replay_counter
, peerkey
->replay_counter
,
366 WPA_REPLAY_COUNTER_LEN
);
367 inc_byte_array(peerkey
->replay_counter
, WPA_REPLAY_COUNTER_LEN
);
369 WPA_PUT_BE16(msg
->key_data_length
, kde_len
);
370 wpa_add_kde((u8
*) (msg
+ 1), RSN_KEY_DATA_PMKID
,
371 peerkey
->smkid
, PMKID_LEN
);
373 if (os_get_random(peerkey
->inonce
, WPA_NONCE_LEN
)) {
374 wpa_msg(sm
->ctx
->msg_ctx
, MSG_WARNING
,
375 "RSN: Failed to get random data for INonce (STK)");
379 wpa_hexdump(MSG_DEBUG
, "RSN: INonce for STK 4-Way Handshake",
380 peerkey
->inonce
, WPA_NONCE_LEN
);
381 os_memcpy(msg
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
383 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR
,
384 MAC2STR(peerkey
->addr
));
385 wpa_eapol_key_send(sm
, NULL
, ver
, peerkey
->addr
, ETH_P_EAPOL
,
390 static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm
*sm
,
391 struct wpa_peerkey
*peerkey
)
394 struct wpa_eapol_key
*msg
;
400 kde_len
= peerkey
->rsnie_i_len
+
401 2 + RSN_SELECTOR_LEN
+ sizeof(lifetime
);
403 mbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
404 sizeof(*msg
) + kde_len
, &mlen
,
409 msg
->type
= EAPOL_KEY_TYPE_RSN
;
411 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
412 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
414 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
416 key_info
= ver
| WPA_KEY_INFO_KEY_TYPE
| WPA_KEY_INFO_ACK
|
417 WPA_KEY_INFO_MIC
| WPA_KEY_INFO_SECURE
;
418 WPA_PUT_BE16(msg
->key_info
, key_info
);
420 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
421 WPA_PUT_BE16(msg
->key_length
, 16);
423 WPA_PUT_BE16(msg
->key_length
, 32);
425 os_memcpy(msg
->replay_counter
, peerkey
->replay_counter
,
426 WPA_REPLAY_COUNTER_LEN
);
427 inc_byte_array(peerkey
->replay_counter
, WPA_REPLAY_COUNTER_LEN
);
429 WPA_PUT_BE16(msg
->key_data_length
, kde_len
);
430 pos
= (u8
*) (msg
+ 1);
431 pos
= wpa_add_ie(pos
, peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
432 lifetime
= host_to_be32(peerkey
->lifetime
);
433 wpa_add_kde(pos
, RSN_KEY_DATA_LIFETIME
,
434 (u8
*) &lifetime
, sizeof(lifetime
));
436 os_memcpy(msg
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
438 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR
,
439 MAC2STR(peerkey
->addr
));
440 wpa_eapol_key_send(sm
, peerkey
->stk
.kck
, ver
, peerkey
->addr
,
441 ETH_P_EAPOL
, mbuf
, mlen
, msg
->key_mic
);
445 static int wpa_supplicant_process_smk_m4(struct wpa_peerkey
*peerkey
,
446 struct wpa_eapol_ie_parse
*kde
)
448 wpa_printf(MSG_DEBUG
, "RSN: Received SMK M4 (Initiator " MACSTR
")",
449 MAC2STR(kde
->mac_addr
));
451 if (os_memcmp(kde
->smk
+ PMK_LEN
, peerkey
->pnonce
, WPA_NONCE_LEN
) != 0)
453 wpa_printf(MSG_INFO
, "RSN: PNonce in SMK KDE does not "
454 "match with the one used in SMK M3");
458 if (os_memcmp(kde
->nonce
, peerkey
->inonce
, WPA_NONCE_LEN
) != 0) {
459 wpa_printf(MSG_INFO
, "RSN: INonce in SMK M4 did not "
460 "match with the one received in SMK M2");
468 static int wpa_supplicant_process_smk_m5(struct wpa_sm
*sm
,
469 const unsigned char *src_addr
,
470 const struct wpa_eapol_key
*key
,
472 struct wpa_peerkey
*peerkey
,
473 struct wpa_eapol_ie_parse
*kde
)
476 struct wpa_ie_data ie
;
478 wpa_printf(MSG_DEBUG
, "RSN: Received SMK M5 (Peer " MACSTR
")",
479 MAC2STR(kde
->mac_addr
));
480 if (kde
->rsn_ie
== NULL
|| kde
->rsn_ie_len
> PEERKEY_MAX_IE_LEN
||
481 wpa_parse_wpa_ie_rsn(kde
->rsn_ie
, kde
->rsn_ie_len
, &ie
) < 0) {
482 wpa_printf(MSG_INFO
, "RSN: No RSN IE in SMK M5");
483 /* TODO: abort negotiation */
487 if (os_memcmp(key
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
) != 0) {
488 wpa_printf(MSG_INFO
, "RSN: Key Nonce in SMK M5 does "
489 "not match with INonce used in SMK M1");
493 if (os_memcmp(kde
->smk
+ PMK_LEN
, peerkey
->inonce
, WPA_NONCE_LEN
) != 0)
495 wpa_printf(MSG_INFO
, "RSN: INonce in SMK KDE does not "
496 "match with the one used in SMK M1");
500 os_memcpy(peerkey
->rsnie_p
, kde
->rsn_ie
, kde
->rsn_ie_len
);
501 peerkey
->rsnie_p_len
= kde
->rsn_ie_len
;
502 os_memcpy(peerkey
->pnonce
, kde
->nonce
, WPA_NONCE_LEN
);
504 cipher
= ie
.pairwise_cipher
& sm
->allowed_pairwise_cipher
;
505 if (cipher
& WPA_CIPHER_CCMP
) {
506 wpa_printf(MSG_DEBUG
, "RSN: Using CCMP for PeerKey");
507 peerkey
->cipher
= WPA_CIPHER_CCMP
;
508 } else if (cipher
& WPA_CIPHER_TKIP
) {
509 wpa_printf(MSG_DEBUG
, "RSN: Using TKIP for PeerKey");
510 peerkey
->cipher
= WPA_CIPHER_TKIP
;
512 wpa_printf(MSG_INFO
, "RSN: SMK Peer STA " MACSTR
" selected "
513 "unacceptable cipher", MAC2STR(kde
->mac_addr
));
514 wpa_supplicant_send_smk_error(sm
, src_addr
, kde
->mac_addr
,
515 STK_MUI_SMK
, STK_ERR_CPHR_NS
,
517 /* TODO: abort negotiation */
525 static int wpa_supplicant_process_smk_m45(
526 struct wpa_sm
*sm
, const unsigned char *src_addr
,
527 const struct wpa_eapol_key
*key
, size_t extra_len
, int ver
)
529 struct wpa_peerkey
*peerkey
;
530 struct wpa_eapol_ie_parse kde
;
534 if (!sm
->peerkey_enabled
|| sm
->proto
!= WPA_PROTO_RSN
) {
535 wpa_printf(MSG_DEBUG
, "RSN: SMK handshake not allowed for "
536 "the current network");
540 if (wpa_supplicant_parse_ies((const u8
*) (key
+ 1), extra_len
, &kde
) <
542 wpa_printf(MSG_INFO
, "RSN: Failed to parse KDEs in SMK M4/M5");
546 if (kde
.mac_addr
== NULL
|| kde
.mac_addr_len
< ETH_ALEN
||
547 kde
.nonce
== NULL
|| kde
.nonce_len
< WPA_NONCE_LEN
||
548 kde
.smk
== NULL
|| kde
.smk_len
< PMK_LEN
+ WPA_NONCE_LEN
||
549 kde
.lifetime
== NULL
|| kde
.lifetime_len
< 4) {
550 wpa_printf(MSG_INFO
, "RSN: No MAC Address, Nonce, SMK, or "
551 "Lifetime KDE in SMK M4/M5");
555 for (peerkey
= sm
->peerkey
; peerkey
; peerkey
= peerkey
->next
) {
556 if (os_memcmp(peerkey
->addr
, kde
.mac_addr
, ETH_ALEN
) == 0 &&
557 os_memcmp(peerkey
->initiator
? peerkey
->inonce
:
559 key
->key_nonce
, WPA_NONCE_LEN
) == 0)
562 if (peerkey
== NULL
) {
563 wpa_printf(MSG_INFO
, "RSN: No matching SMK handshake found "
564 "for SMK M4/M5: peer " MACSTR
,
565 MAC2STR(kde
.mac_addr
));
569 if (peerkey
->initiator
) {
570 if (wpa_supplicant_process_smk_m5(sm
, src_addr
, key
, ver
,
574 if (wpa_supplicant_process_smk_m4(peerkey
, &kde
) < 0)
578 os_memcpy(peerkey
->smk
, kde
.smk
, PMK_LEN
);
579 peerkey
->smk_complete
= 1;
580 wpa_hexdump_key(MSG_DEBUG
, "RSN: SMK", peerkey
->smk
, PMK_LEN
);
581 lifetime
= WPA_GET_BE32(kde
.lifetime
);
582 wpa_printf(MSG_DEBUG
, "RSN: SMK lifetime %u seconds", lifetime
);
583 if (lifetime
> 1000000000)
584 lifetime
= 1000000000; /* avoid overflowing expiration time */
585 peerkey
->lifetime
= lifetime
;
587 peerkey
->expiration
= now
.sec
+ lifetime
;
588 eloop_register_timeout(lifetime
, 0, wpa_supplicant_smk_timeout
,
591 if (peerkey
->initiator
) {
592 rsn_smkid(peerkey
->smk
, peerkey
->pnonce
, peerkey
->addr
,
593 peerkey
->inonce
, sm
->own_addr
, peerkey
->smkid
,
594 peerkey
->use_sha256
);
595 wpa_supplicant_send_stk_1_of_4(sm
, peerkey
);
597 rsn_smkid(peerkey
->smk
, peerkey
->pnonce
, sm
->own_addr
,
598 peerkey
->inonce
, peerkey
->addr
, peerkey
->smkid
,
599 peerkey
->use_sha256
);
601 wpa_hexdump(MSG_DEBUG
, "RSN: SMKID", peerkey
->smkid
, PMKID_LEN
);
607 static int wpa_supplicant_process_smk_error(
608 struct wpa_sm
*sm
, const unsigned char *src_addr
,
609 const struct wpa_eapol_key
*key
, size_t extra_len
)
611 struct wpa_eapol_ie_parse kde
;
612 struct rsn_error_kde error
;
616 wpa_printf(MSG_DEBUG
, "RSN: Received SMK Error");
618 if (!sm
->peerkey_enabled
|| sm
->proto
!= WPA_PROTO_RSN
) {
619 wpa_printf(MSG_DEBUG
, "RSN: SMK handshake not allowed for "
620 "the current network");
624 if (wpa_supplicant_parse_ies((const u8
*) (key
+ 1), extra_len
, &kde
) <
626 wpa_printf(MSG_INFO
, "RSN: Failed to parse KDEs in SMK Error");
630 if (kde
.error
== NULL
|| kde
.error_len
< sizeof(error
)) {
631 wpa_printf(MSG_INFO
, "RSN: No Error KDE in SMK Error");
635 if (kde
.mac_addr
&& kde
.mac_addr_len
>= ETH_ALEN
)
636 os_memcpy(peer
, kde
.mac_addr
, ETH_ALEN
);
638 os_memset(peer
, 0, ETH_ALEN
);
639 os_memcpy(&error
, kde
.error
, sizeof(error
));
640 error_type
= be_to_host16(error
.error_type
);
641 wpa_msg(sm
->ctx
->msg_ctx
, MSG_INFO
,
642 "RSN: SMK Error KDE received: MUI %d error_type %d peer "
644 be_to_host16(error
.mui
), error_type
,
648 (error_type
== STK_ERR_STA_NR
|| error_type
== STK_ERR_STA_NRSN
||
649 error_type
== STK_ERR_CPHR_NS
)) {
650 struct wpa_peerkey
*peerkey
;
652 for (peerkey
= sm
->peerkey
; peerkey
; peerkey
= peerkey
->next
) {
653 if (os_memcmp(peerkey
->addr
, kde
.mac_addr
, ETH_ALEN
) ==
657 if (peerkey
== NULL
) {
658 wpa_printf(MSG_DEBUG
, "RSN: No matching SMK handshake "
659 "found for SMK Error");
662 /* TODO: abort SMK/STK handshake and remove all related keys */
669 static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm
*sm
,
670 struct wpa_peerkey
*peerkey
,
671 const struct wpa_eapol_key
*key
,
674 struct wpa_eapol_ie_parse ie
;
676 size_t len
, kde_buf_len
;
678 u8 buf
[8], *kde_buf
, *pos
;
681 wpa_printf(MSG_DEBUG
, "RSN: RX message 1 of STK 4-Way Handshake from "
682 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
684 os_memset(&ie
, 0, sizeof(ie
));
686 /* RSN: msg 1/4 should contain SMKID for the selected SMK */
687 kde
= (const u8
*) (key
+ 1);
688 len
= WPA_GET_BE16(key
->key_data_length
);
689 wpa_hexdump(MSG_DEBUG
, "RSN: msg 1/4 key data", kde
, len
);
690 if (wpa_supplicant_parse_ies(kde
, len
, &ie
) < 0 || ie
.pmkid
== NULL
) {
691 wpa_printf(MSG_DEBUG
, "RSN: No SMKID in STK 1/4");
694 if (os_memcmp(ie
.pmkid
, peerkey
->smkid
, PMKID_LEN
) != 0) {
695 wpa_hexdump(MSG_DEBUG
, "RSN: Unknown SMKID in STK 1/4",
696 ie
.pmkid
, PMKID_LEN
);
700 if (os_get_random(peerkey
->pnonce
, WPA_NONCE_LEN
)) {
701 wpa_msg(sm
->ctx
->msg_ctx
, MSG_WARNING
,
702 "RSN: Failed to get random data for PNonce");
705 wpa_hexdump(MSG_DEBUG
, "WPA: Renewed PNonce",
706 peerkey
->pnonce
, WPA_NONCE_LEN
);
708 /* Calculate STK which will be stored as a temporary STK until it has
709 * been verified when processing message 3/4. */
710 stk
= &peerkey
->tstk
;
711 wpa_pmk_to_ptk(peerkey
->smk
, PMK_LEN
, "Peer key expansion",
712 sm
->own_addr
, peerkey
->addr
,
713 peerkey
->pnonce
, key
->key_nonce
,
714 (u8
*) stk
, sizeof(*stk
),
715 peerkey
->use_sha256
);
716 /* Supplicant: swap tx/rx Mic keys */
717 os_memcpy(buf
, stk
->u
.auth
.tx_mic_key
, 8);
718 os_memcpy(stk
->u
.auth
.tx_mic_key
, stk
->u
.auth
.rx_mic_key
, 8);
719 os_memcpy(stk
->u
.auth
.rx_mic_key
, buf
, 8);
720 peerkey
->tstk_set
= 1;
722 kde_buf_len
= peerkey
->rsnie_p_len
+
723 2 + RSN_SELECTOR_LEN
+ sizeof(lifetime
) +
724 2 + RSN_SELECTOR_LEN
+ PMKID_LEN
;
725 kde_buf
= os_malloc(kde_buf_len
);
729 pos
= wpa_add_ie(pos
, peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
730 lifetime
= host_to_be32(peerkey
->lifetime
);
731 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_LIFETIME
,
732 (u8
*) &lifetime
, sizeof(lifetime
));
733 wpa_add_kde(pos
, RSN_KEY_DATA_PMKID
, peerkey
->smkid
, PMKID_LEN
);
735 if (wpa_supplicant_send_2_of_4(sm
, peerkey
->addr
, key
, ver
,
736 peerkey
->pnonce
, kde_buf
, kde_buf_len
,
743 os_memcpy(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
);
747 static void wpa_supplicant_update_smk_lifetime(struct wpa_sm
*sm
,
748 struct wpa_peerkey
*peerkey
,
749 struct wpa_eapol_ie_parse
*kde
)
754 if (kde
->lifetime
== NULL
|| kde
->lifetime_len
< sizeof(lifetime
))
757 lifetime
= WPA_GET_BE32(kde
->lifetime
);
759 if (lifetime
>= peerkey
->lifetime
) {
760 wpa_printf(MSG_DEBUG
, "RSN: Peer used SMK lifetime %u seconds "
761 "which is larger than or equal to own value %u "
762 "seconds - ignored", lifetime
, peerkey
->lifetime
);
766 wpa_printf(MSG_DEBUG
, "RSN: Peer used shorter SMK lifetime %u seconds "
767 "(own was %u seconds) - updated",
768 lifetime
, peerkey
->lifetime
);
769 peerkey
->lifetime
= lifetime
;
772 peerkey
->expiration
= now
.sec
+ lifetime
;
773 eloop_cancel_timeout(wpa_supplicant_smk_timeout
, sm
, peerkey
);
774 eloop_register_timeout(lifetime
, 0, wpa_supplicant_smk_timeout
,
779 static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm
*sm
,
780 struct wpa_peerkey
*peerkey
,
781 const struct wpa_eapol_key
*key
,
784 struct wpa_eapol_ie_parse kde
;
788 wpa_printf(MSG_DEBUG
, "RSN: RX message 2 of STK 4-Way Handshake from "
789 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
791 os_memset(&kde
, 0, sizeof(kde
));
793 /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
794 * from the peer. It may also include Lifetime KDE. */
795 keydata
= (const u8
*) (key
+ 1);
796 len
= WPA_GET_BE16(key
->key_data_length
);
797 wpa_hexdump(MSG_DEBUG
, "RSN: msg 2/4 key data", keydata
, len
);
798 if (wpa_supplicant_parse_ies(keydata
, len
, &kde
) < 0 ||
799 kde
.pmkid
== NULL
|| kde
.rsn_ie
== NULL
) {
800 wpa_printf(MSG_DEBUG
, "RSN: No SMKID or RSN IE in STK 2/4");
804 if (os_memcmp(kde
.pmkid
, peerkey
->smkid
, PMKID_LEN
) != 0) {
805 wpa_hexdump(MSG_DEBUG
, "RSN: Unknown SMKID in STK 2/4",
806 kde
.pmkid
, PMKID_LEN
);
810 if (kde
.rsn_ie_len
!= peerkey
->rsnie_p_len
||
811 os_memcmp(kde
.rsn_ie
, peerkey
->rsnie_p
, kde
.rsn_ie_len
) != 0) {
812 wpa_printf(MSG_INFO
, "RSN: Peer RSN IE in SMK and STK "
813 "handshakes did not match");
814 wpa_hexdump(MSG_DEBUG
, "RSN: Peer RSN IE in SMK handshake",
815 peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
816 wpa_hexdump(MSG_DEBUG
, "RSN: Peer RSN IE in STK handshake",
817 kde
.rsn_ie
, kde
.rsn_ie_len
);
821 wpa_supplicant_update_smk_lifetime(sm
, peerkey
, &kde
);
823 wpa_supplicant_send_stk_3_of_4(sm
, peerkey
);
824 os_memcpy(peerkey
->pnonce
, key
->key_nonce
, WPA_NONCE_LEN
);
828 static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm
*sm
,
829 struct wpa_peerkey
*peerkey
,
830 const struct wpa_eapol_key
*key
,
833 struct wpa_eapol_ie_parse kde
;
837 u8 key_buf
[32], rsc
[6];
839 wpa_printf(MSG_DEBUG
, "RSN: RX message 3 of STK 4-Way Handshake from "
840 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
842 os_memset(&kde
, 0, sizeof(kde
));
844 /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
846 keydata
= (const u8
*) (key
+ 1);
847 len
= WPA_GET_BE16(key
->key_data_length
);
848 wpa_hexdump(MSG_DEBUG
, "RSN: msg 3/4 key data", keydata
, len
);
849 if (wpa_supplicant_parse_ies(keydata
, len
, &kde
) < 0) {
850 wpa_printf(MSG_DEBUG
, "RSN: Failed to parse key data in "
855 if (kde
.rsn_ie_len
!= peerkey
->rsnie_i_len
||
856 os_memcmp(kde
.rsn_ie
, peerkey
->rsnie_i
, kde
.rsn_ie_len
) != 0) {
857 wpa_printf(MSG_INFO
, "RSN: Initiator RSN IE in SMK and STK "
858 "handshakes did not match");
859 wpa_hexdump(MSG_DEBUG
, "RSN: Initiator RSN IE in SMK "
861 peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
862 wpa_hexdump(MSG_DEBUG
, "RSN: Initiator RSN IE in STK "
864 kde
.rsn_ie
, kde
.rsn_ie_len
);
868 if (os_memcmp(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
) != 0) {
869 wpa_printf(MSG_WARNING
, "RSN: INonce from message 1 of STK "
870 "4-Way Handshake differs from 3 of STK 4-Way "
871 "Handshake - drop packet (src=" MACSTR
")",
872 MAC2STR(peerkey
->addr
));
876 wpa_supplicant_update_smk_lifetime(sm
, peerkey
, &kde
);
878 if (wpa_supplicant_send_4_of_4(sm
, peerkey
->addr
, key
, ver
,
879 WPA_GET_BE16(key
->key_info
),
880 NULL
, 0, &peerkey
->stk
))
883 _key
= (u8
*) peerkey
->stk
.tk1
;
884 if (peerkey
->cipher
== WPA_CIPHER_TKIP
) {
885 /* Swap Tx/Rx keys for Michael MIC */
886 os_memcpy(key_buf
, _key
, 16);
887 os_memcpy(key_buf
+ 16, peerkey
->stk
.u
.auth
.rx_mic_key
, 8);
888 os_memcpy(key_buf
+ 24, peerkey
->stk
.u
.auth
.tx_mic_key
, 8);
894 os_memset(rsc
, 0, 6);
895 if (wpa_sm_set_key(sm
, peerkey
->cipher
, peerkey
->addr
, 0, 1,
896 rsc
, sizeof(rsc
), _key
, key_len
) < 0) {
897 wpa_printf(MSG_WARNING
, "RSN: Failed to set STK to the "
904 static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm
*sm
,
905 struct wpa_peerkey
*peerkey
,
906 const struct wpa_eapol_key
*key
,
911 wpa_printf(MSG_DEBUG
, "RSN: RX message 4 of STK 4-Way Handshake from "
912 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
914 os_memset(rsc
, 0, 6);
915 if (wpa_sm_set_key(sm
, peerkey
->cipher
, peerkey
->addr
, 0, 1,
916 rsc
, sizeof(rsc
), (u8
*) peerkey
->stk
.tk1
,
917 peerkey
->cipher
== WPA_CIPHER_TKIP
? 32 : 16) < 0) {
918 wpa_printf(MSG_WARNING
, "RSN: Failed to set STK to the "
926 * peerkey_verify_eapol_key_mic - Verify PeerKey MIC
927 * @sm: Pointer to WPA state machine data from wpa_sm_init()
928 * @peerkey: Pointer to the PeerKey data for the peer
929 * @key: Pointer to the EAPOL-Key frame header
930 * @ver: Version bits from EAPOL-Key Key Info
931 * @buf: Pointer to the beginning of EAPOL-Key frame
932 * @len: Length of the EAPOL-Key frame
933 * Returns: 0 on success, -1 on failure
935 int peerkey_verify_eapol_key_mic(struct wpa_sm
*sm
,
936 struct wpa_peerkey
*peerkey
,
937 struct wpa_eapol_key
*key
, u16 ver
,
938 const u8
*buf
, size_t len
)
943 if (peerkey
->initiator
&& !peerkey
->stk_set
) {
944 wpa_pmk_to_ptk(peerkey
->smk
, PMK_LEN
, "Peer key expansion",
945 sm
->own_addr
, peerkey
->addr
,
946 peerkey
->inonce
, key
->key_nonce
,
947 (u8
*) &peerkey
->stk
, sizeof(peerkey
->stk
),
948 peerkey
->use_sha256
);
949 peerkey
->stk_set
= 1;
952 os_memcpy(mic
, key
->key_mic
, 16);
953 if (peerkey
->tstk_set
) {
954 os_memset(key
->key_mic
, 0, 16);
955 wpa_eapol_key_mic(peerkey
->tstk
.kck
, ver
, buf
, len
,
957 if (os_memcmp(mic
, key
->key_mic
, 16) != 0) {
958 wpa_printf(MSG_WARNING
, "RSN: Invalid EAPOL-Key MIC "
959 "when using TSTK - ignoring TSTK");
962 peerkey
->tstk_set
= 0;
963 peerkey
->stk_set
= 1;
964 os_memcpy(&peerkey
->stk
, &peerkey
->tstk
,
965 sizeof(peerkey
->stk
));
969 if (!ok
&& peerkey
->stk_set
) {
970 os_memset(key
->key_mic
, 0, 16);
971 wpa_eapol_key_mic(peerkey
->stk
.kck
, ver
, buf
, len
,
973 if (os_memcmp(mic
, key
->key_mic
, 16) != 0) {
974 wpa_printf(MSG_WARNING
, "RSN: Invalid EAPOL-Key MIC "
975 "- dropping packet");
982 wpa_printf(MSG_WARNING
, "RSN: Could not verify EAPOL-Key MIC "
983 "- dropping packet");
987 os_memcpy(peerkey
->replay_counter
, key
->replay_counter
,
988 WPA_REPLAY_COUNTER_LEN
);
989 peerkey
->replay_counter_set
= 1;
995 * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
996 * @sm: Pointer to WPA state machine data from wpa_sm_init()
997 * @peer: MAC address of the peer STA
998 * Returns: 0 on success, or -1 on failure
1000 * Send an EAPOL-Key Request to the current authenticator to start STK
1001 * handshake with the peer.
1003 int wpa_sm_stkstart(struct wpa_sm
*sm
, const u8
*peer
)
1005 size_t rlen
, kde_len
;
1006 struct wpa_eapol_key
*req
;
1008 u8 bssid
[ETH_ALEN
], *rbuf
, *pos
, *count_pos
;
1010 struct rsn_ie_hdr
*hdr
;
1011 struct wpa_peerkey
*peerkey
;
1012 struct wpa_ie_data ie
;
1014 if (sm
->proto
!= WPA_PROTO_RSN
|| !sm
->ptk_set
|| !sm
->peerkey_enabled
)
1017 if (sm
->ap_rsn_ie
&&
1018 wpa_parse_wpa_ie_rsn(sm
->ap_rsn_ie
, sm
->ap_rsn_ie_len
, &ie
) == 0 &&
1019 !(ie
.capabilities
& WPA_CAPABILITY_PEERKEY_ENABLED
)) {
1020 wpa_printf(MSG_DEBUG
, "RSN: Current AP does not support STK");
1024 if (sm
->pairwise_cipher
== WPA_CIPHER_CCMP
)
1025 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
1027 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
1029 if (wpa_sm_get_bssid(sm
, bssid
) < 0) {
1030 wpa_printf(MSG_WARNING
, "Failed to read BSSID for EAPOL-Key "
1035 /* TODO: find existing entry and if found, use that instead of adding
1037 peerkey
= os_zalloc(sizeof(*peerkey
));
1038 if (peerkey
== NULL
)
1040 peerkey
->initiator
= 1;
1041 os_memcpy(peerkey
->addr
, peer
, ETH_ALEN
);
1042 #ifdef CONFIG_IEEE80211W
1043 if (wpa_key_mgmt_sha256(sm
->key_mgmt
))
1044 peerkey
->use_sha256
= 1;
1045 #endif /* CONFIG_IEEE80211W */
1048 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
1049 * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
1052 hdr
= (struct rsn_ie_hdr
*) peerkey
->rsnie_i
;
1053 hdr
->elem_id
= WLAN_EID_RSN
;
1054 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
1055 pos
= (u8
*) (hdr
+ 1);
1056 /* Group Suite can be anything for SMK RSN IE; receiver will just
1058 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
1059 pos
+= RSN_SELECTOR_LEN
;
1064 if (sm
->allowed_pairwise_cipher
& WPA_CIPHER_CCMP
) {
1065 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
1066 pos
+= RSN_SELECTOR_LEN
;
1069 if (sm
->allowed_pairwise_cipher
& WPA_CIPHER_TKIP
) {
1070 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_TKIP
);
1071 pos
+= RSN_SELECTOR_LEN
;
1074 WPA_PUT_LE16(count_pos
, count
);
1076 hdr
->len
= (pos
- peerkey
->rsnie_i
) - 2;
1077 peerkey
->rsnie_i_len
= pos
- peerkey
->rsnie_i
;
1078 wpa_hexdump(MSG_DEBUG
, "WPA: RSN IE for SMK handshake",
1079 peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
1081 kde_len
= peerkey
->rsnie_i_len
+ 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
;
1083 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
1084 sizeof(*req
) + kde_len
, &rlen
,
1087 wpa_supplicant_peerkey_free(sm
, peerkey
);
1091 req
->type
= EAPOL_KEY_TYPE_RSN
;
1092 key_info
= WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
1093 WPA_KEY_INFO_SECURE
| WPA_KEY_INFO_REQUEST
| ver
;
1094 WPA_PUT_BE16(req
->key_info
, key_info
);
1095 WPA_PUT_BE16(req
->key_length
, 0);
1096 os_memcpy(req
->replay_counter
, sm
->request_counter
,
1097 WPA_REPLAY_COUNTER_LEN
);
1098 inc_byte_array(sm
->request_counter
, WPA_REPLAY_COUNTER_LEN
);
1100 if (os_get_random(peerkey
->inonce
, WPA_NONCE_LEN
)) {
1101 wpa_msg(sm
->ctx
->msg_ctx
, MSG_WARNING
,
1102 "WPA: Failed to get random data for INonce");
1104 wpa_supplicant_peerkey_free(sm
, peerkey
);
1107 os_memcpy(req
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
1108 wpa_hexdump(MSG_DEBUG
, "WPA: INonce for SMK handshake",
1109 req
->key_nonce
, WPA_NONCE_LEN
);
1111 WPA_PUT_BE16(req
->key_data_length
, (u16
) kde_len
);
1112 pos
= (u8
*) (req
+ 1);
1114 /* Initiator RSN IE */
1115 pos
= wpa_add_ie(pos
, peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
1116 /* Peer MAC address KDE */
1117 wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peer
, ETH_ALEN
);
1119 wpa_printf(MSG_INFO
, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
1120 MACSTR
")", MAC2STR(peer
));
1121 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, bssid
, ETH_P_EAPOL
,
1122 rbuf
, rlen
, req
->key_mic
);
1124 peerkey
->next
= sm
->peerkey
;
1125 sm
->peerkey
= peerkey
;
1132 * peerkey_deinit - Free PeerKey values
1133 * @sm: Pointer to WPA state machine data from wpa_sm_init()
1135 void peerkey_deinit(struct wpa_sm
*sm
)
1137 struct wpa_peerkey
*prev
, *peerkey
= sm
->peerkey
;
1140 peerkey
= peerkey
->next
;
1146 void peerkey_rx_eapol_4way(struct wpa_sm
*sm
, struct wpa_peerkey
*peerkey
,
1147 struct wpa_eapol_key
*key
, u16 key_info
, u16 ver
)
1149 if ((key_info
& (WPA_KEY_INFO_MIC
| WPA_KEY_INFO_ACK
)) ==
1150 (WPA_KEY_INFO_MIC
| WPA_KEY_INFO_ACK
)) {
1151 /* 3/4 STK 4-Way Handshake */
1152 wpa_supplicant_process_stk_3_of_4(sm
, peerkey
, key
, ver
);
1153 } else if (key_info
& WPA_KEY_INFO_ACK
) {
1154 /* 1/4 STK 4-Way Handshake */
1155 wpa_supplicant_process_stk_1_of_4(sm
, peerkey
, key
, ver
);
1156 } else if (key_info
& WPA_KEY_INFO_SECURE
) {
1157 /* 4/4 STK 4-Way Handshake */
1158 wpa_supplicant_process_stk_4_of_4(sm
, peerkey
, key
, ver
);
1160 /* 2/4 STK 4-Way Handshake */
1161 wpa_supplicant_process_stk_2_of_4(sm
, peerkey
, key
, ver
);
1166 void peerkey_rx_eapol_smk(struct wpa_sm
*sm
, const u8
*src_addr
,
1167 struct wpa_eapol_key
*key
, size_t extra_len
,
1168 u16 key_info
, u16 ver
)
1170 if (key_info
& WPA_KEY_INFO_ERROR
) {
1172 wpa_supplicant_process_smk_error(sm
, src_addr
, key
, extra_len
);
1173 } else if (key_info
& WPA_KEY_INFO_ACK
) {
1175 wpa_supplicant_process_smk_m2(sm
, src_addr
, key
, extra_len
,
1179 wpa_supplicant_process_smk_m45(sm
, src_addr
, key
, extra_len
,
1184 #endif /* CONFIG_PEERKEY */