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
);
637 os_memcpy(&error
, kde
.error
, sizeof(error
));
638 error_type
= be_to_host16(error
.error_type
);
639 wpa_msg(sm
->ctx
->msg_ctx
, MSG_INFO
,
640 "RSN: SMK Error KDE received: MUI %d error_type %d peer "
642 be_to_host16(error
.mui
), error_type
,
646 (error_type
== STK_ERR_STA_NR
|| error_type
== STK_ERR_STA_NRSN
||
647 error_type
== STK_ERR_CPHR_NS
)) {
648 struct wpa_peerkey
*peerkey
;
650 for (peerkey
= sm
->peerkey
; peerkey
; peerkey
= peerkey
->next
) {
651 if (os_memcmp(peerkey
->addr
, kde
.mac_addr
, ETH_ALEN
) ==
655 if (peerkey
== NULL
) {
656 wpa_printf(MSG_DEBUG
, "RSN: No matching SMK handshake "
657 "found for SMK Error");
660 /* TODO: abort SMK/STK handshake and remove all related keys */
667 static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm
*sm
,
668 struct wpa_peerkey
*peerkey
,
669 const struct wpa_eapol_key
*key
,
672 struct wpa_eapol_ie_parse ie
;
674 size_t len
, kde_buf_len
;
676 u8 buf
[8], *kde_buf
, *pos
;
679 wpa_printf(MSG_DEBUG
, "RSN: RX message 1 of STK 4-Way Handshake from "
680 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
682 os_memset(&ie
, 0, sizeof(ie
));
684 /* RSN: msg 1/4 should contain SMKID for the selected SMK */
685 kde
= (const u8
*) (key
+ 1);
686 len
= WPA_GET_BE16(key
->key_data_length
);
687 wpa_hexdump(MSG_DEBUG
, "RSN: msg 1/4 key data", kde
, len
);
688 if (wpa_supplicant_parse_ies(kde
, len
, &ie
) < 0 || ie
.pmkid
== NULL
) {
689 wpa_printf(MSG_DEBUG
, "RSN: No SMKID in STK 1/4");
692 if (os_memcmp(ie
.pmkid
, peerkey
->smkid
, PMKID_LEN
) != 0) {
693 wpa_hexdump(MSG_DEBUG
, "RSN: Unknown SMKID in STK 1/4",
694 ie
.pmkid
, PMKID_LEN
);
698 if (os_get_random(peerkey
->pnonce
, WPA_NONCE_LEN
)) {
699 wpa_msg(sm
->ctx
->msg_ctx
, MSG_WARNING
,
700 "RSN: Failed to get random data for PNonce");
703 wpa_hexdump(MSG_DEBUG
, "WPA: Renewed PNonce",
704 peerkey
->pnonce
, WPA_NONCE_LEN
);
706 /* Calculate STK which will be stored as a temporary STK until it has
707 * been verified when processing message 3/4. */
708 stk
= &peerkey
->tstk
;
709 wpa_pmk_to_ptk(peerkey
->smk
, PMK_LEN
, "Peer key expansion",
710 sm
->own_addr
, peerkey
->addr
,
711 peerkey
->pnonce
, key
->key_nonce
,
712 (u8
*) stk
, sizeof(*stk
),
713 peerkey
->use_sha256
);
714 /* Supplicant: swap tx/rx Mic keys */
715 os_memcpy(buf
, stk
->u
.auth
.tx_mic_key
, 8);
716 os_memcpy(stk
->u
.auth
.tx_mic_key
, stk
->u
.auth
.rx_mic_key
, 8);
717 os_memcpy(stk
->u
.auth
.rx_mic_key
, buf
, 8);
718 peerkey
->tstk_set
= 1;
720 kde_buf_len
= peerkey
->rsnie_p_len
+
721 2 + RSN_SELECTOR_LEN
+ sizeof(lifetime
) +
722 2 + RSN_SELECTOR_LEN
+ PMKID_LEN
;
723 kde_buf
= os_malloc(kde_buf_len
);
727 pos
= wpa_add_ie(pos
, peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
728 lifetime
= host_to_be32(peerkey
->lifetime
);
729 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_LIFETIME
,
730 (u8
*) &lifetime
, sizeof(lifetime
));
731 wpa_add_kde(pos
, RSN_KEY_DATA_PMKID
, peerkey
->smkid
, PMKID_LEN
);
733 if (wpa_supplicant_send_2_of_4(sm
, peerkey
->addr
, key
, ver
,
734 peerkey
->pnonce
, kde_buf
, kde_buf_len
,
741 os_memcpy(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
);
745 static void wpa_supplicant_update_smk_lifetime(struct wpa_sm
*sm
,
746 struct wpa_peerkey
*peerkey
,
747 struct wpa_eapol_ie_parse
*kde
)
752 if (kde
->lifetime
== NULL
|| kde
->lifetime_len
< sizeof(lifetime
))
755 lifetime
= WPA_GET_BE32(kde
->lifetime
);
757 if (lifetime
>= peerkey
->lifetime
) {
758 wpa_printf(MSG_DEBUG
, "RSN: Peer used SMK lifetime %u seconds "
759 "which is larger than or equal to own value %u "
760 "seconds - ignored", lifetime
, peerkey
->lifetime
);
764 wpa_printf(MSG_DEBUG
, "RSN: Peer used shorter SMK lifetime %u seconds "
765 "(own was %u seconds) - updated",
766 lifetime
, peerkey
->lifetime
);
767 peerkey
->lifetime
= lifetime
;
770 peerkey
->expiration
= now
.sec
+ lifetime
;
771 eloop_cancel_timeout(wpa_supplicant_smk_timeout
, sm
, peerkey
);
772 eloop_register_timeout(lifetime
, 0, wpa_supplicant_smk_timeout
,
777 static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm
*sm
,
778 struct wpa_peerkey
*peerkey
,
779 const struct wpa_eapol_key
*key
,
782 struct wpa_eapol_ie_parse kde
;
786 wpa_printf(MSG_DEBUG
, "RSN: RX message 2 of STK 4-Way Handshake from "
787 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
789 os_memset(&kde
, 0, sizeof(kde
));
791 /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
792 * from the peer. It may also include Lifetime KDE. */
793 keydata
= (const u8
*) (key
+ 1);
794 len
= WPA_GET_BE16(key
->key_data_length
);
795 wpa_hexdump(MSG_DEBUG
, "RSN: msg 2/4 key data", keydata
, len
);
796 if (wpa_supplicant_parse_ies(keydata
, len
, &kde
) < 0 ||
797 kde
.pmkid
== NULL
|| kde
.rsn_ie
== NULL
) {
798 wpa_printf(MSG_DEBUG
, "RSN: No SMKID or RSN IE in STK 2/4");
802 if (os_memcmp(kde
.pmkid
, peerkey
->smkid
, PMKID_LEN
) != 0) {
803 wpa_hexdump(MSG_DEBUG
, "RSN: Unknown SMKID in STK 2/4",
804 kde
.pmkid
, PMKID_LEN
);
808 if (kde
.rsn_ie_len
!= peerkey
->rsnie_p_len
||
809 os_memcmp(kde
.rsn_ie
, peerkey
->rsnie_p
, kde
.rsn_ie_len
) != 0) {
810 wpa_printf(MSG_INFO
, "RSN: Peer RSN IE in SMK and STK "
811 "handshakes did not match");
812 wpa_hexdump(MSG_DEBUG
, "RSN: Peer RSN IE in SMK handshake",
813 peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
814 wpa_hexdump(MSG_DEBUG
, "RSN: Peer RSN IE in STK handshake",
815 kde
.rsn_ie
, kde
.rsn_ie_len
);
819 wpa_supplicant_update_smk_lifetime(sm
, peerkey
, &kde
);
821 wpa_supplicant_send_stk_3_of_4(sm
, peerkey
);
822 os_memcpy(peerkey
->pnonce
, key
->key_nonce
, WPA_NONCE_LEN
);
826 static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm
*sm
,
827 struct wpa_peerkey
*peerkey
,
828 const struct wpa_eapol_key
*key
,
831 struct wpa_eapol_ie_parse kde
;
835 u8 key_buf
[32], rsc
[6];
837 wpa_printf(MSG_DEBUG
, "RSN: RX message 3 of STK 4-Way Handshake from "
838 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
840 os_memset(&kde
, 0, sizeof(kde
));
842 /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
844 keydata
= (const u8
*) (key
+ 1);
845 len
= WPA_GET_BE16(key
->key_data_length
);
846 wpa_hexdump(MSG_DEBUG
, "RSN: msg 3/4 key data", keydata
, len
);
847 if (wpa_supplicant_parse_ies(keydata
, len
, &kde
) < 0) {
848 wpa_printf(MSG_DEBUG
, "RSN: Failed to parse key data in "
853 if (kde
.rsn_ie_len
!= peerkey
->rsnie_i_len
||
854 os_memcmp(kde
.rsn_ie
, peerkey
->rsnie_i
, kde
.rsn_ie_len
) != 0) {
855 wpa_printf(MSG_INFO
, "RSN: Initiator RSN IE in SMK and STK "
856 "handshakes did not match");
857 wpa_hexdump(MSG_DEBUG
, "RSN: Initiator RSN IE in SMK "
859 peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
860 wpa_hexdump(MSG_DEBUG
, "RSN: Initiator RSN IE in STK "
862 kde
.rsn_ie
, kde
.rsn_ie_len
);
866 if (os_memcmp(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
) != 0) {
867 wpa_printf(MSG_WARNING
, "RSN: INonce from message 1 of STK "
868 "4-Way Handshake differs from 3 of STK 4-Way "
869 "Handshake - drop packet (src=" MACSTR
")",
870 MAC2STR(peerkey
->addr
));
874 wpa_supplicant_update_smk_lifetime(sm
, peerkey
, &kde
);
876 if (wpa_supplicant_send_4_of_4(sm
, peerkey
->addr
, key
, ver
,
877 WPA_GET_BE16(key
->key_info
),
878 NULL
, 0, &peerkey
->stk
))
881 _key
= (u8
*) peerkey
->stk
.tk1
;
882 if (peerkey
->cipher
== WPA_CIPHER_TKIP
) {
883 /* Swap Tx/Rx keys for Michael MIC */
884 os_memcpy(key_buf
, _key
, 16);
885 os_memcpy(key_buf
+ 16, peerkey
->stk
.u
.auth
.rx_mic_key
, 8);
886 os_memcpy(key_buf
+ 24, peerkey
->stk
.u
.auth
.tx_mic_key
, 8);
892 os_memset(rsc
, 0, 6);
893 if (wpa_sm_set_key(sm
, peerkey
->cipher
, peerkey
->addr
, 0, 1,
894 rsc
, sizeof(rsc
), _key
, key_len
) < 0) {
895 wpa_printf(MSG_WARNING
, "RSN: Failed to set STK to the "
902 static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm
*sm
,
903 struct wpa_peerkey
*peerkey
,
904 const struct wpa_eapol_key
*key
,
909 wpa_printf(MSG_DEBUG
, "RSN: RX message 4 of STK 4-Way Handshake from "
910 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
912 os_memset(rsc
, 0, 6);
913 if (wpa_sm_set_key(sm
, peerkey
->cipher
, peerkey
->addr
, 0, 1,
914 rsc
, sizeof(rsc
), (u8
*) peerkey
->stk
.tk1
,
915 peerkey
->cipher
== WPA_CIPHER_TKIP
? 32 : 16) < 0) {
916 wpa_printf(MSG_WARNING
, "RSN: Failed to set STK to the "
924 * peerkey_verify_eapol_key_mic - Verify PeerKey MIC
925 * @sm: Pointer to WPA state machine data from wpa_sm_init()
926 * @peerkey: Pointer to the PeerKey data for the peer
927 * @key: Pointer to the EAPOL-Key frame header
928 * @ver: Version bits from EAPOL-Key Key Info
929 * @buf: Pointer to the beginning of EAPOL-Key frame
930 * @len: Length of the EAPOL-Key frame
931 * Returns: 0 on success, -1 on failure
933 int peerkey_verify_eapol_key_mic(struct wpa_sm
*sm
,
934 struct wpa_peerkey
*peerkey
,
935 struct wpa_eapol_key
*key
, u16 ver
,
936 const u8
*buf
, size_t len
)
941 if (peerkey
->initiator
&& !peerkey
->stk_set
) {
942 wpa_pmk_to_ptk(peerkey
->smk
, PMK_LEN
, "Peer key expansion",
943 sm
->own_addr
, peerkey
->addr
,
944 peerkey
->inonce
, key
->key_nonce
,
945 (u8
*) &peerkey
->stk
, sizeof(peerkey
->stk
),
946 peerkey
->use_sha256
);
947 peerkey
->stk_set
= 1;
950 os_memcpy(mic
, key
->key_mic
, 16);
951 if (peerkey
->tstk_set
) {
952 os_memset(key
->key_mic
, 0, 16);
953 wpa_eapol_key_mic(peerkey
->tstk
.kck
, ver
, buf
, len
,
955 if (os_memcmp(mic
, key
->key_mic
, 16) != 0) {
956 wpa_printf(MSG_WARNING
, "RSN: Invalid EAPOL-Key MIC "
957 "when using TSTK - ignoring TSTK");
960 peerkey
->tstk_set
= 0;
961 peerkey
->stk_set
= 1;
962 os_memcpy(&peerkey
->stk
, &peerkey
->tstk
,
963 sizeof(peerkey
->stk
));
967 if (!ok
&& peerkey
->stk_set
) {
968 os_memset(key
->key_mic
, 0, 16);
969 wpa_eapol_key_mic(peerkey
->stk
.kck
, ver
, buf
, len
,
971 if (os_memcmp(mic
, key
->key_mic
, 16) != 0) {
972 wpa_printf(MSG_WARNING
, "RSN: Invalid EAPOL-Key MIC "
973 "- dropping packet");
980 wpa_printf(MSG_WARNING
, "RSN: Could not verify EAPOL-Key MIC "
981 "- dropping packet");
985 os_memcpy(peerkey
->replay_counter
, key
->replay_counter
,
986 WPA_REPLAY_COUNTER_LEN
);
987 peerkey
->replay_counter_set
= 1;
993 * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
994 * @sm: Pointer to WPA state machine data from wpa_sm_init()
995 * @peer: MAC address of the peer STA
996 * Returns: 0 on success, or -1 on failure
998 * Send an EAPOL-Key Request to the current authenticator to start STK
999 * handshake with the peer.
1001 int wpa_sm_stkstart(struct wpa_sm
*sm
, const u8
*peer
)
1003 size_t rlen
, kde_len
;
1004 struct wpa_eapol_key
*req
;
1006 u8 bssid
[ETH_ALEN
], *rbuf
, *pos
, *count_pos
;
1008 struct rsn_ie_hdr
*hdr
;
1009 struct wpa_peerkey
*peerkey
;
1010 struct wpa_ie_data ie
;
1012 if (sm
->proto
!= WPA_PROTO_RSN
|| !sm
->ptk_set
|| !sm
->peerkey_enabled
)
1015 if (sm
->ap_rsn_ie
&&
1016 wpa_parse_wpa_ie_rsn(sm
->ap_rsn_ie
, sm
->ap_rsn_ie_len
, &ie
) == 0 &&
1017 !(ie
.capabilities
& WPA_CAPABILITY_PEERKEY_ENABLED
)) {
1018 wpa_printf(MSG_DEBUG
, "RSN: Current AP does not support STK");
1022 if (sm
->pairwise_cipher
== WPA_CIPHER_CCMP
)
1023 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
1025 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
1027 if (wpa_sm_get_bssid(sm
, bssid
) < 0) {
1028 wpa_printf(MSG_WARNING
, "Failed to read BSSID for EAPOL-Key "
1033 /* TODO: find existing entry and if found, use that instead of adding
1035 peerkey
= os_zalloc(sizeof(*peerkey
));
1036 if (peerkey
== NULL
)
1038 peerkey
->initiator
= 1;
1039 os_memcpy(peerkey
->addr
, peer
, ETH_ALEN
);
1040 #ifdef CONFIG_IEEE80211W
1041 if (wpa_key_mgmt_sha256(sm
->key_mgmt
))
1042 peerkey
->use_sha256
= 1;
1043 #endif /* CONFIG_IEEE80211W */
1046 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
1047 * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
1050 hdr
= (struct rsn_ie_hdr
*) peerkey
->rsnie_i
;
1051 hdr
->elem_id
= WLAN_EID_RSN
;
1052 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
1053 pos
= (u8
*) (hdr
+ 1);
1054 /* Group Suite can be anything for SMK RSN IE; receiver will just
1056 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
1057 pos
+= RSN_SELECTOR_LEN
;
1062 if (sm
->allowed_pairwise_cipher
& WPA_CIPHER_CCMP
) {
1063 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
1064 pos
+= RSN_SELECTOR_LEN
;
1067 if (sm
->allowed_pairwise_cipher
& WPA_CIPHER_TKIP
) {
1068 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_TKIP
);
1069 pos
+= RSN_SELECTOR_LEN
;
1072 WPA_PUT_LE16(count_pos
, count
);
1074 hdr
->len
= (pos
- peerkey
->rsnie_i
) - 2;
1075 peerkey
->rsnie_i_len
= pos
- peerkey
->rsnie_i
;
1076 wpa_hexdump(MSG_DEBUG
, "WPA: RSN IE for SMK handshake",
1077 peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
1079 kde_len
= peerkey
->rsnie_i_len
+ 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
;
1081 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
1082 sizeof(*req
) + kde_len
, &rlen
,
1085 wpa_supplicant_peerkey_free(sm
, peerkey
);
1089 req
->type
= EAPOL_KEY_TYPE_RSN
;
1090 key_info
= WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
1091 WPA_KEY_INFO_SECURE
| WPA_KEY_INFO_REQUEST
| ver
;
1092 WPA_PUT_BE16(req
->key_info
, key_info
);
1093 WPA_PUT_BE16(req
->key_length
, 0);
1094 os_memcpy(req
->replay_counter
, sm
->request_counter
,
1095 WPA_REPLAY_COUNTER_LEN
);
1096 inc_byte_array(sm
->request_counter
, WPA_REPLAY_COUNTER_LEN
);
1098 if (os_get_random(peerkey
->inonce
, WPA_NONCE_LEN
)) {
1099 wpa_msg(sm
->ctx
->msg_ctx
, MSG_WARNING
,
1100 "WPA: Failed to get random data for INonce");
1102 wpa_supplicant_peerkey_free(sm
, peerkey
);
1105 os_memcpy(req
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
1106 wpa_hexdump(MSG_DEBUG
, "WPA: INonce for SMK handshake",
1107 req
->key_nonce
, WPA_NONCE_LEN
);
1109 WPA_PUT_BE16(req
->key_data_length
, (u16
) kde_len
);
1110 pos
= (u8
*) (req
+ 1);
1112 /* Initiator RSN IE */
1113 pos
= wpa_add_ie(pos
, peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
1114 /* Peer MAC address KDE */
1115 wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peer
, ETH_ALEN
);
1117 wpa_printf(MSG_INFO
, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
1118 MACSTR
")", MAC2STR(peer
));
1119 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, bssid
, ETH_P_EAPOL
,
1120 rbuf
, rlen
, req
->key_mic
);
1122 peerkey
->next
= sm
->peerkey
;
1123 sm
->peerkey
= peerkey
;
1130 * peerkey_deinit - Free PeerKey values
1131 * @sm: Pointer to WPA state machine data from wpa_sm_init()
1133 void peerkey_deinit(struct wpa_sm
*sm
)
1135 struct wpa_peerkey
*prev
, *peerkey
= sm
->peerkey
;
1138 peerkey
= peerkey
->next
;
1144 void peerkey_rx_eapol_4way(struct wpa_sm
*sm
, struct wpa_peerkey
*peerkey
,
1145 struct wpa_eapol_key
*key
, u16 key_info
, u16 ver
)
1147 if ((key_info
& (WPA_KEY_INFO_MIC
| WPA_KEY_INFO_ACK
)) ==
1148 (WPA_KEY_INFO_MIC
| WPA_KEY_INFO_ACK
)) {
1149 /* 3/4 STK 4-Way Handshake */
1150 wpa_supplicant_process_stk_3_of_4(sm
, peerkey
, key
, ver
);
1151 } else if (key_info
& WPA_KEY_INFO_ACK
) {
1152 /* 1/4 STK 4-Way Handshake */
1153 wpa_supplicant_process_stk_1_of_4(sm
, peerkey
, key
, ver
);
1154 } else if (key_info
& WPA_KEY_INFO_SECURE
) {
1155 /* 4/4 STK 4-Way Handshake */
1156 wpa_supplicant_process_stk_4_of_4(sm
, peerkey
, key
, ver
);
1158 /* 2/4 STK 4-Way Handshake */
1159 wpa_supplicant_process_stk_2_of_4(sm
, peerkey
, key
, ver
);
1164 void peerkey_rx_eapol_smk(struct wpa_sm
*sm
, const u8
*src_addr
,
1165 struct wpa_eapol_key
*key
, size_t extra_len
,
1166 u16 key_info
, u16 ver
)
1168 if (key_info
& WPA_KEY_INFO_ERROR
) {
1170 wpa_supplicant_process_smk_error(sm
, src_addr
, key
, extra_len
);
1171 } else if (key_info
& WPA_KEY_INFO_ACK
) {
1173 wpa_supplicant_process_smk_m2(sm
, src_addr
, key
, extra_len
,
1177 wpa_supplicant_process_smk_m45(sm
, src_addr
, key
, extra_len
,
1182 #endif /* CONFIG_PEERKEY */