2 * WPA Supplicant - PeerKey for Direct Link Setup (DLS)
3 * Copyright (c) 2006-2007, 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.
25 #include "ieee802_11_defs.h"
29 static u8
* wpa_add_ie(u8
*pos
, const u8
*ie
, size_t ie_len
)
31 os_memcpy(pos
, ie
, ie_len
);
36 static u8
* wpa_add_kde(u8
*pos
, u32 kde
, const u8
*data
, size_t data_len
)
38 *pos
++ = WLAN_EID_VENDOR_SPECIFIC
;
39 *pos
++ = RSN_SELECTOR_LEN
+ data_len
;
40 RSN_SELECTOR_PUT(pos
, kde
);
41 pos
+= RSN_SELECTOR_LEN
;
42 os_memcpy(pos
, data
, data_len
);
48 static void wpa_supplicant_smk_timeout(void *eloop_ctx
, void *timeout_ctx
)
51 struct wpa_sm
*sm
= eloop_ctx
;
52 struct wpa_peerkey
*peerkey
= timeout_ctx
;
54 /* TODO: time out SMK and any STK that was generated using this SMK */
58 static void wpa_supplicant_peerkey_free(struct wpa_sm
*sm
,
59 struct wpa_peerkey
*peerkey
)
61 eloop_cancel_timeout(wpa_supplicant_smk_timeout
, sm
, peerkey
);
66 static int wpa_supplicant_send_smk_error(struct wpa_sm
*sm
, const u8
*dst
,
68 u16 mui
, u16 error_type
, int ver
)
71 struct wpa_eapol_key
*err
;
72 struct rsn_error_kde error
;
77 kde_len
= 2 + RSN_SELECTOR_LEN
+ sizeof(error
);
79 kde_len
+= 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
;
81 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
,
82 NULL
, sizeof(*err
) + kde_len
, &rlen
,
87 err
->type
= EAPOL_KEY_TYPE_RSN
;
88 key_info
= ver
| WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
89 WPA_KEY_INFO_SECURE
| WPA_KEY_INFO_ERROR
|
91 WPA_PUT_BE16(err
->key_info
, key_info
);
92 WPA_PUT_BE16(err
->key_length
, 0);
93 os_memcpy(err
->replay_counter
, sm
->request_counter
,
94 WPA_REPLAY_COUNTER_LEN
);
95 inc_byte_array(sm
->request_counter
, WPA_REPLAY_COUNTER_LEN
);
97 WPA_PUT_BE16(err
->key_data_length
, (u16
) kde_len
);
98 pos
= (u8
*) (err
+ 1);
101 /* Peer MAC Address KDE */
102 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peer
, ETH_ALEN
);
106 error
.mui
= host_to_be16(mui
);
107 error
.error_type
= host_to_be16(error_type
);
108 wpa_add_kde(pos
, RSN_KEY_DATA_ERROR
, (u8
*) &error
, sizeof(error
));
111 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key SMK Error (peer "
112 MACSTR
" mui %d error_type %d)",
113 MAC2STR(peer
), mui
, error_type
);
115 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key SMK Error "
116 "(mui %d error_type %d)", mui
, error_type
);
119 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, dst
, ETH_P_EAPOL
,
120 rbuf
, rlen
, err
->key_mic
);
126 static int wpa_supplicant_send_smk_m3(struct wpa_sm
*sm
,
127 const unsigned char *src_addr
,
128 const struct wpa_eapol_key
*key
,
129 int ver
, struct wpa_peerkey
*peerkey
)
132 struct wpa_eapol_key
*reply
;
137 /* KDEs: Peer RSN IE, Initiator MAC Address, Initiator Nonce */
138 kde_len
= peerkey
->rsnie_p_len
+
139 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
+
140 2 + RSN_SELECTOR_LEN
+ WPA_NONCE_LEN
;
142 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
,
143 NULL
, sizeof(*reply
) + kde_len
, &rlen
,
148 reply
->type
= EAPOL_KEY_TYPE_RSN
;
149 key_info
= ver
| WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
151 WPA_PUT_BE16(reply
->key_info
, key_info
);
152 WPA_PUT_BE16(reply
->key_length
, 0);
153 os_memcpy(reply
->replay_counter
, key
->replay_counter
,
154 WPA_REPLAY_COUNTER_LEN
);
156 os_memcpy(reply
->key_nonce
, peerkey
->pnonce
, WPA_NONCE_LEN
);
158 WPA_PUT_BE16(reply
->key_data_length
, (u16
) kde_len
);
159 pos
= (u8
*) (reply
+ 1);
162 pos
= wpa_add_ie(pos
, peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
164 /* Initiator MAC Address KDE */
165 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peerkey
->addr
, ETH_ALEN
);
167 /* Initiator Nonce */
168 wpa_add_kde(pos
, RSN_KEY_DATA_NONCE
, peerkey
->inonce
, WPA_NONCE_LEN
);
170 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key SMK M3");
171 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, src_addr
, ETH_P_EAPOL
,
172 rbuf
, rlen
, reply
->key_mic
);
178 static int wpa_supplicant_process_smk_m2(
179 struct wpa_sm
*sm
, const unsigned char *src_addr
,
180 const struct wpa_eapol_key
*key
, size_t extra_len
, int ver
)
182 struct wpa_peerkey
*peerkey
;
183 struct wpa_eapol_ie_parse kde
;
184 struct wpa_ie_data ie
;
186 struct rsn_ie_hdr
*hdr
;
189 wpa_printf(MSG_DEBUG
, "RSN: Received SMK M2");
191 if (!sm
->peerkey_enabled
|| sm
->proto
!= WPA_PROTO_RSN
) {
192 wpa_printf(MSG_INFO
, "RSN: SMK handshake not allowed for "
193 "the current network");
197 if (wpa_supplicant_parse_ies((const u8
*) (key
+ 1), extra_len
, &kde
) <
199 wpa_printf(MSG_INFO
, "RSN: Failed to parse KDEs in SMK M2");
203 if (kde
.rsn_ie
== NULL
|| kde
.mac_addr
== NULL
||
204 kde
.mac_addr_len
< ETH_ALEN
) {
205 wpa_printf(MSG_INFO
, "RSN: No RSN IE or MAC address KDE in "
210 wpa_printf(MSG_DEBUG
, "RSN: SMK M2 - SMK initiator " MACSTR
,
211 MAC2STR(kde
.mac_addr
));
213 if (kde
.rsn_ie_len
> PEERKEY_MAX_IE_LEN
) {
214 wpa_printf(MSG_INFO
, "RSN: Too long Initiator RSN IE in SMK "
219 if (wpa_parse_wpa_ie_rsn(kde
.rsn_ie
, kde
.rsn_ie_len
, &ie
) < 0) {
220 wpa_printf(MSG_INFO
, "RSN: Failed to parse RSN IE in SMK M2");
224 cipher
= ie
.pairwise_cipher
& sm
->allowed_pairwise_cipher
;
225 if (cipher
& WPA_CIPHER_CCMP
) {
226 wpa_printf(MSG_DEBUG
, "RSN: Using CCMP for PeerKey");
227 cipher
= WPA_CIPHER_CCMP
;
228 } else if (cipher
& WPA_CIPHER_TKIP
) {
229 wpa_printf(MSG_DEBUG
, "RSN: Using TKIP for PeerKey");
230 cipher
= WPA_CIPHER_TKIP
;
232 wpa_printf(MSG_INFO
, "RSN: No acceptable cipher in SMK M2");
233 wpa_supplicant_send_smk_error(sm
, src_addr
, kde
.mac_addr
,
234 STK_MUI_SMK
, STK_ERR_CPHR_NS
,
239 /* TODO: find existing entry and if found, use that instead of adding
240 * a new one; how to handle the case where both ends initiate at the
242 peerkey
= os_malloc(sizeof(*peerkey
));
245 os_memset(peerkey
, 0, 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
;
252 if (os_get_random(peerkey
->pnonce
, WPA_NONCE_LEN
)) {
253 wpa_msg(sm
->ctx
->ctx
, MSG_WARNING
,
254 "WPA: Failed to get random data for PNonce");
255 wpa_supplicant_peerkey_free(sm
, peerkey
);
259 hdr
= (struct rsn_ie_hdr
*) peerkey
->rsnie_p
;
260 hdr
->elem_id
= WLAN_EID_RSN
;
261 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
262 pos
= (u8
*) (hdr
+ 1);
263 /* Group Suite can be anything for SMK RSN IE; receiver will just
265 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
266 pos
+= RSN_SELECTOR_LEN
;
267 /* Include only the selected cipher in pairwise cipher suite */
268 WPA_PUT_LE16(pos
, 1);
270 if (cipher
== WPA_CIPHER_CCMP
)
271 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
272 else if (cipher
== WPA_CIPHER_TKIP
)
273 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_TKIP
);
274 pos
+= RSN_SELECTOR_LEN
;
276 hdr
->len
= (pos
- peerkey
->rsnie_p
) - 2;
277 peerkey
->rsnie_p_len
= pos
- peerkey
->rsnie_p
;
278 wpa_hexdump(MSG_DEBUG
, "WPA: RSN IE for SMK handshake",
279 peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
281 wpa_supplicant_send_smk_m3(sm
, src_addr
, key
, ver
, peerkey
);
283 peerkey
->next
= sm
->peerkey
;
284 sm
->peerkey
= peerkey
;
291 * rsn_smkid - Derive SMK identifier
292 * @smk: Station master key (32 bytes)
293 * @pnonce: Peer Nonce
294 * @mac_p: Peer MAC address
295 * @inonce: Initiator Nonce
296 * @mac_i: Initiator MAC address
298 * 8.5.1.4 Station to station (STK) key hierarchy
299 * SMKID = HMAC-SHA1-128(SMK, "SMK Name" || PNonce || MAC_P || INonce || MAC_I)
301 static void rsn_smkid(const u8
*smk
, const u8
*pnonce
, const u8
*mac_p
,
302 const u8
*inonce
, const u8
*mac_i
, u8
*smkid
)
304 char *title
= "SMK Name";
306 const size_t len
[5] = { 8, WPA_NONCE_LEN
, ETH_ALEN
, WPA_NONCE_LEN
,
308 unsigned char hash
[SHA1_MAC_LEN
];
310 addr
[0] = (u8
*) title
;
316 hmac_sha1_vector(smk
, PMK_LEN
, 5, addr
, len
, hash
);
317 os_memcpy(smkid
, hash
, PMKID_LEN
);
321 static void wpa_supplicant_send_stk_1_of_4(struct wpa_sm
*sm
,
322 struct wpa_peerkey
*peerkey
)
325 struct wpa_eapol_key
*msg
;
330 kde_len
= 2 + RSN_SELECTOR_LEN
+ PMKID_LEN
;
332 mbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
333 sizeof(*msg
) + kde_len
, &mlen
,
338 msg
->type
= EAPOL_KEY_TYPE_RSN
;
340 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
341 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
343 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
345 key_info
= ver
| WPA_KEY_INFO_KEY_TYPE
| WPA_KEY_INFO_ACK
;
346 WPA_PUT_BE16(msg
->key_info
, key_info
);
348 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
349 WPA_PUT_BE16(msg
->key_length
, 16);
351 WPA_PUT_BE16(msg
->key_length
, 32);
353 os_memcpy(msg
->replay_counter
, peerkey
->replay_counter
,
354 WPA_REPLAY_COUNTER_LEN
);
355 inc_byte_array(peerkey
->replay_counter
, WPA_REPLAY_COUNTER_LEN
);
357 WPA_PUT_BE16(msg
->key_data_length
, kde_len
);
358 wpa_add_kde((u8
*) (msg
+ 1), RSN_KEY_DATA_PMKID
,
359 peerkey
->smkid
, PMKID_LEN
);
361 if (os_get_random(peerkey
->inonce
, WPA_NONCE_LEN
)) {
362 wpa_msg(sm
->ctx
->ctx
, MSG_WARNING
,
363 "RSN: Failed to get random data for INonce (STK)");
367 wpa_hexdump(MSG_DEBUG
, "RSN: INonce for STK 4-Way Handshake",
368 peerkey
->inonce
, WPA_NONCE_LEN
);
369 os_memcpy(msg
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
371 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key STK 1/4 to " MACSTR
,
372 MAC2STR(peerkey
->addr
));
373 wpa_eapol_key_send(sm
, NULL
, ver
, peerkey
->addr
, ETH_P_EAPOL
,
378 static void wpa_supplicant_send_stk_3_of_4(struct wpa_sm
*sm
,
379 struct wpa_peerkey
*peerkey
)
382 struct wpa_eapol_key
*msg
;
388 kde_len
= peerkey
->rsnie_i_len
+
389 2 + RSN_SELECTOR_LEN
+ sizeof(lifetime
);
391 mbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
392 sizeof(*msg
) + kde_len
, &mlen
,
397 msg
->type
= EAPOL_KEY_TYPE_RSN
;
399 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
400 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
402 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
404 key_info
= ver
| WPA_KEY_INFO_KEY_TYPE
| WPA_KEY_INFO_ACK
|
405 WPA_KEY_INFO_MIC
| WPA_KEY_INFO_SECURE
;
406 WPA_PUT_BE16(msg
->key_info
, key_info
);
408 if (peerkey
->cipher
== WPA_CIPHER_CCMP
)
409 WPA_PUT_BE16(msg
->key_length
, 16);
411 WPA_PUT_BE16(msg
->key_length
, 32);
413 os_memcpy(msg
->replay_counter
, peerkey
->replay_counter
,
414 WPA_REPLAY_COUNTER_LEN
);
415 inc_byte_array(peerkey
->replay_counter
, WPA_REPLAY_COUNTER_LEN
);
417 WPA_PUT_BE16(msg
->key_data_length
, kde_len
);
418 pos
= (u8
*) (msg
+ 1);
419 pos
= wpa_add_ie(pos
, peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
420 lifetime
= host_to_be32(peerkey
->lifetime
);
421 wpa_add_kde(pos
, RSN_KEY_DATA_LIFETIME
,
422 (u8
*) &lifetime
, sizeof(lifetime
));
424 os_memcpy(msg
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
426 wpa_printf(MSG_DEBUG
, "RSN: Sending EAPOL-Key STK 3/4 to " MACSTR
,
427 MAC2STR(peerkey
->addr
));
428 wpa_eapol_key_send(sm
, peerkey
->stk
.kck
, ver
, peerkey
->addr
,
429 ETH_P_EAPOL
, mbuf
, mlen
, msg
->key_mic
);
433 static int wpa_supplicant_process_smk_m4(struct wpa_peerkey
*peerkey
,
434 struct wpa_eapol_ie_parse
*kde
)
436 wpa_printf(MSG_DEBUG
, "RSN: Received SMK M4 (Initiator " MACSTR
")",
437 MAC2STR(kde
->mac_addr
));
439 if (os_memcmp(kde
->smk
+ PMK_LEN
, peerkey
->pnonce
, WPA_NONCE_LEN
) != 0)
441 wpa_printf(MSG_INFO
, "RSN: PNonce in SMK KDE does not "
442 "match with the one used in SMK M3");
446 if (os_memcmp(kde
->nonce
, peerkey
->inonce
, WPA_NONCE_LEN
) != 0) {
447 wpa_printf(MSG_INFO
, "RSN: INonce in SMK M4 did not "
448 "match with the one received in SMK M2");
456 static int wpa_supplicant_process_smk_m5(struct wpa_sm
*sm
,
457 const unsigned char *src_addr
,
458 const struct wpa_eapol_key
*key
,
460 struct wpa_peerkey
*peerkey
,
461 struct wpa_eapol_ie_parse
*kde
)
464 struct wpa_ie_data ie
;
466 wpa_printf(MSG_DEBUG
, "RSN: Received SMK M5 (Peer " MACSTR
")",
467 MAC2STR(kde
->mac_addr
));
468 if (kde
->rsn_ie
== NULL
|| kde
->rsn_ie_len
> PEERKEY_MAX_IE_LEN
||
469 wpa_parse_wpa_ie_rsn(kde
->rsn_ie
, kde
->rsn_ie_len
, &ie
) < 0) {
470 wpa_printf(MSG_INFO
, "RSN: No RSN IE in SMK M5");
471 /* TODO: abort negotiation */
475 if (os_memcmp(key
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
) != 0) {
476 wpa_printf(MSG_INFO
, "RSN: Key Nonce in SMK M5 does "
477 "not match with INonce used in SMK M1");
481 if (os_memcmp(kde
->smk
+ PMK_LEN
, peerkey
->inonce
, WPA_NONCE_LEN
) != 0)
483 wpa_printf(MSG_INFO
, "RSN: INonce in SMK KDE does not "
484 "match with the one used in SMK M1");
488 os_memcpy(peerkey
->rsnie_p
, kde
->rsn_ie
, kde
->rsn_ie_len
);
489 peerkey
->rsnie_p_len
= kde
->rsn_ie_len
;
490 os_memcpy(peerkey
->pnonce
, kde
->nonce
, WPA_NONCE_LEN
);
492 cipher
= ie
.pairwise_cipher
& sm
->allowed_pairwise_cipher
;
493 if (cipher
& WPA_CIPHER_CCMP
) {
494 wpa_printf(MSG_DEBUG
, "RSN: Using CCMP for PeerKey");
495 peerkey
->cipher
= WPA_CIPHER_CCMP
;
496 } else if (cipher
& WPA_CIPHER_TKIP
) {
497 wpa_printf(MSG_DEBUG
, "RSN: Using TKIP for PeerKey");
498 peerkey
->cipher
= WPA_CIPHER_TKIP
;
500 wpa_printf(MSG_INFO
, "RSN: SMK Peer STA " MACSTR
" selected "
501 "unacceptable cipher", MAC2STR(kde
->mac_addr
));
502 wpa_supplicant_send_smk_error(sm
, src_addr
, kde
->mac_addr
,
503 STK_MUI_SMK
, STK_ERR_CPHR_NS
,
505 /* TODO: abort negotiation */
513 static int wpa_supplicant_process_smk_m45(
514 struct wpa_sm
*sm
, const unsigned char *src_addr
,
515 const struct wpa_eapol_key
*key
, size_t extra_len
, int ver
)
517 struct wpa_peerkey
*peerkey
;
518 struct wpa_eapol_ie_parse kde
;
522 if (!sm
->peerkey_enabled
|| sm
->proto
!= WPA_PROTO_RSN
) {
523 wpa_printf(MSG_DEBUG
, "RSN: SMK handshake not allowed for "
524 "the current network");
528 if (wpa_supplicant_parse_ies((const u8
*) (key
+ 1), extra_len
, &kde
) <
530 wpa_printf(MSG_INFO
, "RSN: Failed to parse KDEs in SMK M4/M5");
534 if (kde
.mac_addr
== NULL
|| kde
.mac_addr_len
< ETH_ALEN
||
535 kde
.nonce
== NULL
|| kde
.nonce_len
< WPA_NONCE_LEN
||
536 kde
.smk
== NULL
|| kde
.smk_len
< PMK_LEN
+ WPA_NONCE_LEN
||
537 kde
.lifetime
== NULL
|| kde
.lifetime_len
< 4) {
538 wpa_printf(MSG_INFO
, "RSN: No MAC Address, Nonce, SMK, or "
539 "Lifetime KDE in SMK M4/M5");
543 for (peerkey
= sm
->peerkey
; peerkey
; peerkey
= peerkey
->next
) {
544 if (os_memcmp(peerkey
->addr
, kde
.mac_addr
, ETH_ALEN
) == 0 &&
545 os_memcmp(peerkey
->initiator
? peerkey
->inonce
:
547 key
->key_nonce
, WPA_NONCE_LEN
) == 0)
550 if (peerkey
== NULL
) {
551 wpa_printf(MSG_INFO
, "RSN: No matching SMK handshake found "
552 "for SMK M4/M5: peer " MACSTR
,
553 MAC2STR(kde
.mac_addr
));
557 if (peerkey
->initiator
) {
558 if (wpa_supplicant_process_smk_m5(sm
, src_addr
, key
, ver
,
562 if (wpa_supplicant_process_smk_m4(peerkey
, &kde
) < 0)
566 os_memcpy(peerkey
->smk
, kde
.smk
, PMK_LEN
);
567 peerkey
->smk_complete
= 1;
568 wpa_hexdump_key(MSG_DEBUG
, "RSN: SMK", peerkey
->smk
, PMK_LEN
);
569 lifetime
= WPA_GET_BE32(kde
.lifetime
);
570 wpa_printf(MSG_DEBUG
, "RSN: SMK lifetime %u seconds", lifetime
);
571 if (lifetime
> 1000000000)
572 lifetime
= 1000000000; /* avoid overflowing expiration time */
573 peerkey
->lifetime
= lifetime
;
575 peerkey
->expiration
= now
.sec
+ lifetime
;
576 eloop_register_timeout(lifetime
, 0, wpa_supplicant_smk_timeout
,
579 if (peerkey
->initiator
) {
580 rsn_smkid(peerkey
->smk
, peerkey
->pnonce
, peerkey
->addr
,
581 peerkey
->inonce
, sm
->own_addr
, peerkey
->smkid
);
582 wpa_supplicant_send_stk_1_of_4(sm
, peerkey
);
584 rsn_smkid(peerkey
->smk
, peerkey
->pnonce
, sm
->own_addr
,
585 peerkey
->inonce
, peerkey
->addr
, peerkey
->smkid
);
587 wpa_hexdump(MSG_DEBUG
, "RSN: SMKID", peerkey
->smkid
, PMKID_LEN
);
593 static int wpa_supplicant_process_smk_error(
594 struct wpa_sm
*sm
, const unsigned char *src_addr
,
595 const struct wpa_eapol_key
*key
, size_t extra_len
)
597 struct wpa_eapol_ie_parse kde
;
598 struct rsn_error_kde error
;
602 wpa_printf(MSG_DEBUG
, "RSN: Received SMK Error");
604 if (!sm
->peerkey_enabled
|| sm
->proto
!= WPA_PROTO_RSN
) {
605 wpa_printf(MSG_DEBUG
, "RSN: SMK handshake not allowed for "
606 "the current network");
610 if (wpa_supplicant_parse_ies((const u8
*) (key
+ 1), extra_len
, &kde
) <
612 wpa_printf(MSG_INFO
, "RSN: Failed to parse KDEs in SMK Error");
616 if (kde
.error
== NULL
|| kde
.error_len
< sizeof(error
)) {
617 wpa_printf(MSG_INFO
, "RSN: No Error KDE in SMK Error");
621 if (kde
.mac_addr
&& kde
.mac_addr_len
>= ETH_ALEN
)
622 os_memcpy(peer
, kde
.mac_addr
, ETH_ALEN
);
623 os_memcpy(&error
, kde
.error
, sizeof(error
));
624 error_type
= be_to_host16(error
.error_type
);
625 wpa_msg(sm
->ctx
->ctx
, MSG_INFO
,
626 "RSN: SMK Error KDE received: MUI %d error_type %d peer "
628 be_to_host16(error
.mui
), error_type
,
632 (error_type
== STK_ERR_STA_NR
|| error_type
== STK_ERR_STA_NRSN
||
633 error_type
== STK_ERR_CPHR_NS
)) {
634 struct wpa_peerkey
*peerkey
;
636 for (peerkey
= sm
->peerkey
; peerkey
; peerkey
= peerkey
->next
) {
637 if (os_memcmp(peerkey
->addr
, kde
.mac_addr
, ETH_ALEN
) ==
641 if (peerkey
== NULL
) {
642 wpa_printf(MSG_DEBUG
, "RSN: No matching SMK handshake "
643 "found for SMK Error");
646 /* TODO: abort SMK/STK handshake and remove all related keys */
653 static void wpa_supplicant_process_stk_1_of_4(struct wpa_sm
*sm
,
654 struct wpa_peerkey
*peerkey
,
655 const struct wpa_eapol_key
*key
,
658 struct wpa_eapol_ie_parse ie
;
660 size_t len
, kde_buf_len
;
662 u8 buf
[8], *kde_buf
, *pos
;
665 wpa_printf(MSG_DEBUG
, "RSN: RX message 1 of STK 4-Way Handshake from "
666 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
668 os_memset(&ie
, 0, sizeof(ie
));
670 /* RSN: msg 1/4 should contain SMKID for the selected SMK */
671 kde
= (const u8
*) (key
+ 1);
672 len
= WPA_GET_BE16(key
->key_data_length
);
673 wpa_hexdump(MSG_DEBUG
, "RSN: msg 1/4 key data", kde
, len
);
674 if (wpa_supplicant_parse_ies(kde
, len
, &ie
) < 0 || ie
.pmkid
== NULL
) {
675 wpa_printf(MSG_DEBUG
, "RSN: No SMKID in STK 1/4");
678 if (os_memcmp(ie
.pmkid
, peerkey
->smkid
, PMKID_LEN
) != 0) {
679 wpa_hexdump(MSG_DEBUG
, "RSN: Unknown SMKID in STK 1/4",
680 ie
.pmkid
, PMKID_LEN
);
684 if (os_get_random(peerkey
->pnonce
, WPA_NONCE_LEN
)) {
685 wpa_msg(sm
->ctx
->ctx
, MSG_WARNING
,
686 "RSN: Failed to get random data for PNonce");
689 wpa_hexdump(MSG_DEBUG
, "WPA: Renewed PNonce",
690 peerkey
->pnonce
, WPA_NONCE_LEN
);
692 /* Calculate STK which will be stored as a temporary STK until it has
693 * been verified when processing message 3/4. */
694 stk
= &peerkey
->tstk
;
695 wpa_pmk_to_ptk(peerkey
->smk
, PMK_LEN
, "Peer key expansion",
696 sm
->own_addr
, peerkey
->addr
,
697 peerkey
->pnonce
, key
->key_nonce
,
698 (u8
*) stk
, sizeof(*stk
));
699 /* Supplicant: swap tx/rx Mic keys */
700 os_memcpy(buf
, stk
->u
.auth
.tx_mic_key
, 8);
701 os_memcpy(stk
->u
.auth
.tx_mic_key
, stk
->u
.auth
.rx_mic_key
, 8);
702 os_memcpy(stk
->u
.auth
.rx_mic_key
, buf
, 8);
703 peerkey
->tstk_set
= 1;
705 kde_buf_len
= peerkey
->rsnie_p_len
+
706 2 + RSN_SELECTOR_LEN
+ sizeof(lifetime
) +
707 2 + RSN_SELECTOR_LEN
+ PMKID_LEN
;
708 kde_buf
= os_malloc(kde_buf_len
);
712 pos
= wpa_add_ie(pos
, peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
713 lifetime
= host_to_be32(peerkey
->lifetime
);
714 pos
= wpa_add_kde(pos
, RSN_KEY_DATA_LIFETIME
,
715 (u8
*) &lifetime
, sizeof(lifetime
));
716 wpa_add_kde(pos
, RSN_KEY_DATA_PMKID
, peerkey
->smkid
, PMKID_LEN
);
718 if (wpa_supplicant_send_2_of_4(sm
, peerkey
->addr
, key
, ver
,
719 peerkey
->pnonce
, kde_buf
, kde_buf_len
,
726 os_memcpy(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
);
730 static void wpa_supplicant_update_smk_lifetime(struct wpa_sm
*sm
,
731 struct wpa_peerkey
*peerkey
,
732 struct wpa_eapol_ie_parse
*kde
)
737 if (kde
->lifetime
== NULL
|| kde
->lifetime_len
< sizeof(lifetime
))
740 lifetime
= WPA_GET_BE32(kde
->lifetime
);
742 if (lifetime
>= peerkey
->lifetime
) {
743 wpa_printf(MSG_DEBUG
, "RSN: Peer used SMK lifetime %u seconds "
744 "which is larger than or equal to own value %u "
745 "seconds - ignored", lifetime
, peerkey
->lifetime
);
749 wpa_printf(MSG_DEBUG
, "RSN: Peer used shorter SMK lifetime %u seconds "
750 "(own was %u seconds) - updated",
751 lifetime
, peerkey
->lifetime
);
752 peerkey
->lifetime
= lifetime
;
755 peerkey
->expiration
= now
.sec
+ lifetime
;
756 eloop_cancel_timeout(wpa_supplicant_smk_timeout
, sm
, peerkey
);
757 eloop_register_timeout(lifetime
, 0, wpa_supplicant_smk_timeout
,
762 static void wpa_supplicant_process_stk_2_of_4(struct wpa_sm
*sm
,
763 struct wpa_peerkey
*peerkey
,
764 const struct wpa_eapol_key
*key
,
767 struct wpa_eapol_ie_parse kde
;
771 wpa_printf(MSG_DEBUG
, "RSN: RX message 2 of STK 4-Way Handshake from "
772 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
774 os_memset(&kde
, 0, sizeof(kde
));
776 /* RSN: msg 2/4 should contain SMKID for the selected SMK and RSN IE
777 * from the peer. It may also include Lifetime KDE. */
778 keydata
= (const u8
*) (key
+ 1);
779 len
= WPA_GET_BE16(key
->key_data_length
);
780 wpa_hexdump(MSG_DEBUG
, "RSN: msg 2/4 key data", keydata
, len
);
781 if (wpa_supplicant_parse_ies(keydata
, len
, &kde
) < 0 ||
782 kde
.pmkid
== NULL
|| kde
.rsn_ie
== NULL
) {
783 wpa_printf(MSG_DEBUG
, "RSN: No SMKID or RSN IE in STK 2/4");
787 if (os_memcmp(kde
.pmkid
, peerkey
->smkid
, PMKID_LEN
) != 0) {
788 wpa_hexdump(MSG_DEBUG
, "RSN: Unknown SMKID in STK 2/4",
789 kde
.pmkid
, PMKID_LEN
);
793 if (kde
.rsn_ie_len
!= peerkey
->rsnie_p_len
||
794 os_memcmp(kde
.rsn_ie
, peerkey
->rsnie_p
, kde
.rsn_ie_len
) != 0) {
795 wpa_printf(MSG_INFO
, "RSN: Peer RSN IE in SMK and STK "
796 "handshakes did not match");
797 wpa_hexdump(MSG_DEBUG
, "RSN: Peer RSN IE in SMK handshake",
798 peerkey
->rsnie_p
, peerkey
->rsnie_p_len
);
799 wpa_hexdump(MSG_DEBUG
, "RSN: Peer RSN IE in STK handshake",
800 kde
.rsn_ie
, kde
.rsn_ie_len
);
804 wpa_supplicant_update_smk_lifetime(sm
, peerkey
, &kde
);
806 wpa_supplicant_send_stk_3_of_4(sm
, peerkey
);
807 os_memcpy(peerkey
->pnonce
, key
->key_nonce
, WPA_NONCE_LEN
);
811 static void wpa_supplicant_process_stk_3_of_4(struct wpa_sm
*sm
,
812 struct wpa_peerkey
*peerkey
,
813 const struct wpa_eapol_key
*key
,
816 struct wpa_eapol_ie_parse kde
;
820 u8 key_buf
[32], rsc
[6];
822 wpa_printf(MSG_DEBUG
, "RSN: RX message 3 of STK 4-Way Handshake from "
823 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
825 os_memset(&kde
, 0, sizeof(kde
));
827 /* RSN: msg 3/4 should contain Initiator RSN IE. It may also include
829 keydata
= (const u8
*) (key
+ 1);
830 len
= WPA_GET_BE16(key
->key_data_length
);
831 wpa_hexdump(MSG_DEBUG
, "RSN: msg 3/4 key data", keydata
, len
);
832 if (wpa_supplicant_parse_ies(keydata
, len
, &kde
) < 0) {
833 wpa_printf(MSG_DEBUG
, "RSN: Failed to parse key data in "
838 if (kde
.rsn_ie_len
!= peerkey
->rsnie_i_len
||
839 os_memcmp(kde
.rsn_ie
, peerkey
->rsnie_i
, kde
.rsn_ie_len
) != 0) {
840 wpa_printf(MSG_INFO
, "RSN: Initiator RSN IE in SMK and STK "
841 "handshakes did not match");
842 wpa_hexdump(MSG_DEBUG
, "RSN: Initiator RSN IE in SMK "
844 peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
845 wpa_hexdump(MSG_DEBUG
, "RSN: Initiator RSN IE in STK "
847 kde
.rsn_ie
, kde
.rsn_ie_len
);
851 if (os_memcmp(peerkey
->inonce
, key
->key_nonce
, WPA_NONCE_LEN
) != 0) {
852 wpa_printf(MSG_WARNING
, "RSN: INonce from message 1 of STK "
853 "4-Way Handshake differs from 3 of STK 4-Way "
854 "Handshake - drop packet (src=" MACSTR
")",
855 MAC2STR(peerkey
->addr
));
859 wpa_supplicant_update_smk_lifetime(sm
, peerkey
, &kde
);
861 if (wpa_supplicant_send_4_of_4(sm
, peerkey
->addr
, key
, ver
,
862 WPA_GET_BE16(key
->key_info
),
863 NULL
, 0, &peerkey
->stk
))
866 _key
= (u8
*) peerkey
->stk
.tk1
;
867 if (peerkey
->cipher
== WPA_CIPHER_TKIP
) {
868 /* Swap Tx/Rx keys for Michael MIC */
869 os_memcpy(key_buf
, _key
, 16);
870 os_memcpy(key_buf
+ 16, peerkey
->stk
.u
.auth
.rx_mic_key
, 8);
871 os_memcpy(key_buf
+ 24, peerkey
->stk
.u
.auth
.tx_mic_key
, 8);
877 os_memset(rsc
, 0, 6);
878 if (wpa_sm_set_key(sm
, peerkey
->cipher
, peerkey
->addr
, 0, 1,
879 rsc
, sizeof(rsc
), _key
, key_len
) < 0) {
880 wpa_printf(MSG_WARNING
, "RSN: Failed to set STK to the "
887 static void wpa_supplicant_process_stk_4_of_4(struct wpa_sm
*sm
,
888 struct wpa_peerkey
*peerkey
,
889 const struct wpa_eapol_key
*key
,
894 wpa_printf(MSG_DEBUG
, "RSN: RX message 4 of STK 4-Way Handshake from "
895 MACSTR
" (ver=%d)", MAC2STR(peerkey
->addr
), ver
);
897 os_memset(rsc
, 0, 6);
898 if (wpa_sm_set_key(sm
, peerkey
->cipher
, peerkey
->addr
, 0, 1,
899 rsc
, sizeof(rsc
), (u8
*) peerkey
->stk
.tk1
,
900 peerkey
->cipher
== WPA_CIPHER_TKIP
? 32 : 16) < 0) {
901 wpa_printf(MSG_WARNING
, "RSN: Failed to set STK to the "
909 * peerkey_verify_eapol_key_mic - Verify PeerKey MIC
910 * @sm: Pointer to WPA state machine data from wpa_sm_init()
911 * @peerkey: Pointer to the PeerKey data for the peer
912 * @key: Pointer to the EAPOL-Key frame header
913 * @ver: Version bits from EAPOL-Key Key Info
914 * @buf: Pointer to the beginning of EAPOL-Key frame
915 * @len: Length of the EAPOL-Key frame
916 * Returns: 0 on success, -1 on failure
918 int peerkey_verify_eapol_key_mic(struct wpa_sm
*sm
,
919 struct wpa_peerkey
*peerkey
,
920 struct wpa_eapol_key
*key
, u16 ver
,
921 const u8
*buf
, size_t len
)
926 if (peerkey
->initiator
&& !peerkey
->stk_set
) {
927 wpa_pmk_to_ptk(peerkey
->smk
, PMK_LEN
, "Peer key expansion",
928 sm
->own_addr
, peerkey
->addr
,
929 peerkey
->inonce
, key
->key_nonce
,
930 (u8
*) &peerkey
->stk
, sizeof(peerkey
->stk
));
931 peerkey
->stk_set
= 1;
934 os_memcpy(mic
, key
->key_mic
, 16);
935 if (peerkey
->tstk_set
) {
936 os_memset(key
->key_mic
, 0, 16);
937 wpa_eapol_key_mic(peerkey
->tstk
.kck
, ver
, buf
, len
,
939 if (os_memcmp(mic
, key
->key_mic
, 16) != 0) {
940 wpa_printf(MSG_WARNING
, "RSN: Invalid EAPOL-Key MIC "
941 "when using TSTK - ignoring TSTK");
944 peerkey
->tstk_set
= 0;
945 peerkey
->stk_set
= 1;
946 os_memcpy(&peerkey
->stk
, &peerkey
->tstk
,
947 sizeof(peerkey
->stk
));
951 if (!ok
&& peerkey
->stk_set
) {
952 os_memset(key
->key_mic
, 0, 16);
953 wpa_eapol_key_mic(peerkey
->stk
.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 "- dropping packet");
964 wpa_printf(MSG_WARNING
, "RSN: Could not verify EAPOL-Key MIC "
965 "- dropping packet");
969 os_memcpy(peerkey
->replay_counter
, key
->replay_counter
,
970 WPA_REPLAY_COUNTER_LEN
);
971 peerkey
->replay_counter_set
= 1;
977 * wpa_sm_stkstart - Send EAPOL-Key Request for STK handshake (STK M1)
978 * @sm: Pointer to WPA state machine data from wpa_sm_init()
979 * @peer: MAC address of the peer STA
980 * Returns: 0 on success, or -1 on failure
982 * Send an EAPOL-Key Request to the current authenticator to start STK
983 * handshake with the peer.
985 int wpa_sm_stkstart(struct wpa_sm
*sm
, const u8
*peer
)
987 size_t rlen
, kde_len
;
988 struct wpa_eapol_key
*req
;
990 u8 bssid
[ETH_ALEN
], *rbuf
, *pos
, *count_pos
;
992 struct rsn_ie_hdr
*hdr
;
993 struct wpa_peerkey
*peerkey
;
994 struct wpa_ie_data ie
;
996 if (sm
->proto
!= WPA_PROTO_RSN
|| !sm
->ptk_set
|| !sm
->peerkey_enabled
)
1000 wpa_parse_wpa_ie_rsn(sm
->ap_rsn_ie
, sm
->ap_rsn_ie_len
, &ie
) == 0 &&
1001 !(ie
.capabilities
& WPA_CAPABILITY_PEERKEY_ENABLED
)) {
1002 wpa_printf(MSG_DEBUG
, "RSN: Current AP does not support STK");
1006 if (sm
->pairwise_cipher
== WPA_CIPHER_CCMP
)
1007 ver
= WPA_KEY_INFO_TYPE_HMAC_SHA1_AES
;
1009 ver
= WPA_KEY_INFO_TYPE_HMAC_MD5_RC4
;
1011 if (wpa_sm_get_bssid(sm
, bssid
) < 0) {
1012 wpa_printf(MSG_WARNING
, "Failed to read BSSID for EAPOL-Key "
1017 /* TODO: find existing entry and if found, use that instead of adding
1019 peerkey
= os_malloc(sizeof(*peerkey
));
1020 if (peerkey
== NULL
)
1022 os_memset(peerkey
, 0, sizeof(*peerkey
));
1023 peerkey
->initiator
= 1;
1024 os_memcpy(peerkey
->addr
, peer
, ETH_ALEN
);
1027 * EAPOL-Key(S=1, M=1, A=0, I=0, K=0, SM=1, KeyRSC=0, Nonce=INonce,
1028 * MIC=MIC, DataKDs=(RSNIE_I, MAC_P KDE))
1031 hdr
= (struct rsn_ie_hdr
*) peerkey
->rsnie_i
;
1032 hdr
->elem_id
= WLAN_EID_RSN
;
1033 WPA_PUT_LE16(hdr
->version
, RSN_VERSION
);
1034 pos
= (u8
*) (hdr
+ 1);
1035 /* Group Suite can be anything for SMK RSN IE; receiver will just
1037 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
1038 pos
+= RSN_SELECTOR_LEN
;
1043 if (sm
->allowed_pairwise_cipher
& WPA_CIPHER_CCMP
) {
1044 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_CCMP
);
1045 pos
+= RSN_SELECTOR_LEN
;
1048 if (sm
->allowed_pairwise_cipher
& WPA_CIPHER_TKIP
) {
1049 RSN_SELECTOR_PUT(pos
, RSN_CIPHER_SUITE_TKIP
);
1050 pos
+= RSN_SELECTOR_LEN
;
1053 WPA_PUT_LE16(count_pos
, count
);
1055 hdr
->len
= (pos
- peerkey
->rsnie_i
) - 2;
1056 peerkey
->rsnie_i_len
= pos
- peerkey
->rsnie_i
;
1057 wpa_hexdump(MSG_DEBUG
, "WPA: RSN IE for SMK handshake",
1058 peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
1060 kde_len
= peerkey
->rsnie_i_len
+ 2 + RSN_SELECTOR_LEN
+ ETH_ALEN
;
1062 rbuf
= wpa_sm_alloc_eapol(sm
, IEEE802_1X_TYPE_EAPOL_KEY
, NULL
,
1063 sizeof(*req
) + kde_len
, &rlen
,
1066 wpa_supplicant_peerkey_free(sm
, peerkey
);
1070 req
->type
= EAPOL_KEY_TYPE_RSN
;
1071 key_info
= WPA_KEY_INFO_SMK_MESSAGE
| WPA_KEY_INFO_MIC
|
1072 WPA_KEY_INFO_SECURE
| WPA_KEY_INFO_REQUEST
| ver
;
1073 WPA_PUT_BE16(req
->key_info
, key_info
);
1074 WPA_PUT_BE16(req
->key_length
, 0);
1075 os_memcpy(req
->replay_counter
, sm
->request_counter
,
1076 WPA_REPLAY_COUNTER_LEN
);
1077 inc_byte_array(sm
->request_counter
, WPA_REPLAY_COUNTER_LEN
);
1079 if (os_get_random(peerkey
->inonce
, WPA_NONCE_LEN
)) {
1080 wpa_msg(sm
->ctx
->ctx
, MSG_WARNING
,
1081 "WPA: Failed to get random data for INonce");
1083 wpa_supplicant_peerkey_free(sm
, peerkey
);
1086 os_memcpy(req
->key_nonce
, peerkey
->inonce
, WPA_NONCE_LEN
);
1087 wpa_hexdump(MSG_DEBUG
, "WPA: INonce for SMK handshake",
1088 req
->key_nonce
, WPA_NONCE_LEN
);
1090 WPA_PUT_BE16(req
->key_data_length
, (u16
) kde_len
);
1091 pos
= (u8
*) (req
+ 1);
1093 /* Initiator RSN IE */
1094 pos
= wpa_add_ie(pos
, peerkey
->rsnie_i
, peerkey
->rsnie_i_len
);
1095 /* Peer MAC address KDE */
1096 wpa_add_kde(pos
, RSN_KEY_DATA_MAC_ADDR
, peer
, ETH_ALEN
);
1098 wpa_printf(MSG_INFO
, "RSN: Sending EAPOL-Key SMK M1 Request (peer "
1099 MACSTR
")", MAC2STR(peer
));
1100 wpa_eapol_key_send(sm
, sm
->ptk
.kck
, ver
, bssid
, ETH_P_EAPOL
,
1101 rbuf
, rlen
, req
->key_mic
);
1103 peerkey
->next
= sm
->peerkey
;
1104 sm
->peerkey
= peerkey
;
1111 * peerkey_deinit - Free PeerKey values
1112 * @sm: Pointer to WPA state machine data from wpa_sm_init()
1114 void peerkey_deinit(struct wpa_sm
*sm
)
1116 struct wpa_peerkey
*prev
, *peerkey
= sm
->peerkey
;
1119 peerkey
= peerkey
->next
;
1125 void peerkey_rx_eapol_4way(struct wpa_sm
*sm
, struct wpa_peerkey
*peerkey
,
1126 struct wpa_eapol_key
*key
, u16 key_info
, u16 ver
)
1128 if ((key_info
& (WPA_KEY_INFO_MIC
| WPA_KEY_INFO_ACK
)) ==
1129 (WPA_KEY_INFO_MIC
| WPA_KEY_INFO_ACK
)) {
1130 /* 3/4 STK 4-Way Handshake */
1131 wpa_supplicant_process_stk_3_of_4(sm
, peerkey
, key
, ver
);
1132 } else if (key_info
& WPA_KEY_INFO_ACK
) {
1133 /* 1/4 STK 4-Way Handshake */
1134 wpa_supplicant_process_stk_1_of_4(sm
, peerkey
, key
, ver
);
1135 } else if (key_info
& WPA_KEY_INFO_SECURE
) {
1136 /* 4/4 STK 4-Way Handshake */
1137 wpa_supplicant_process_stk_4_of_4(sm
, peerkey
, key
, ver
);
1139 /* 2/4 STK 4-Way Handshake */
1140 wpa_supplicant_process_stk_2_of_4(sm
, peerkey
, key
, ver
);
1145 void peerkey_rx_eapol_smk(struct wpa_sm
*sm
, const u8
*src_addr
,
1146 struct wpa_eapol_key
*key
, size_t extra_len
,
1147 u16 key_info
, u16 ver
)
1149 if (key_info
& WPA_KEY_INFO_ERROR
) {
1151 wpa_supplicant_process_smk_error(sm
, src_addr
, key
, extra_len
);
1152 } else if (key_info
& WPA_KEY_INFO_ACK
) {
1154 wpa_supplicant_process_smk_m2(sm
, src_addr
, key
, extra_len
,
1158 wpa_supplicant_process_smk_m45(sm
, src_addr
, key
, extra_len
,
1163 #endif /* CONFIG_PEERKEY */